Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57041084d1 | ||
|
|
cf4c7b406a | ||
|
|
edb3cdbb59 | ||
|
|
55025d4dc9 | ||
|
|
6f7a5e525d | ||
|
|
342c77c851 | ||
|
|
94f4d81b70 | ||
|
|
74f31c6677 | ||
|
|
7589b9f822 | ||
|
|
b761169976 | ||
|
|
537c3a79ab | ||
|
|
0510988b3e | ||
|
|
79c389a48f | ||
|
|
239779dad0 | ||
|
|
37a7ab9d0e | ||
|
|
17ea15eb91 | ||
|
|
ddaf81051e | ||
|
|
d06f3882e9 | ||
|
|
523994c2cf | ||
|
|
00219ab7f0 | ||
|
|
0c4f1e5e67 | ||
|
|
29e3cfd60f | ||
|
|
95058eac21 | ||
|
|
4b963be8c4 | ||
|
|
a4434b1a50 | ||
|
|
d3dc241878 | ||
|
|
012e617c55 | ||
|
|
bee135c8c6 | ||
|
|
8a19cd1096 | ||
|
|
5b14ca081c | ||
|
|
4fbf03c760 | ||
|
|
503d1d3291 | ||
|
|
e2108d75dc | ||
|
|
9a009a1d1c | ||
|
|
61211486bc | ||
|
|
42fd7451bf | ||
|
|
70a1c1bdac | ||
|
|
eb6d74217c | ||
|
|
172a8f1cea | ||
|
|
164057fa5b | ||
|
|
3c21ac6bb6 | ||
|
|
ad2585e1b7 | ||
|
|
09fe604452 | ||
|
|
28d836cfea | ||
|
|
8005f350ae | ||
|
|
3168ae7dcc | ||
|
|
447b8dab96 | ||
|
|
6408949d43 | ||
|
|
5fe2272861 | ||
|
|
7165a5d1f8 | ||
|
|
2ec21fa9fb | ||
|
|
a162f560dd | ||
|
|
c3c168a70d | ||
|
|
b5ac3b8a53 | ||
|
|
30452a8bcd | ||
|
|
36676effd9 | ||
|
|
f31ff74a75 | ||
|
|
4298cc1cdb | ||
|
|
abe5a5ae30 | ||
|
|
9daaeaed07 |
101
.travis.yml
101
.travis.yml
@@ -1,51 +1,80 @@
|
||||
language: python
|
||||
dist: trusty
|
||||
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.6"
|
||||
language: python
|
||||
|
||||
env:
|
||||
- TEST_TYPE="Server Side Test"
|
||||
- TEST_TYPE="Patch Test"
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
services:
|
||||
- mysql
|
||||
cache:
|
||||
- pip
|
||||
|
||||
addons:
|
||||
hosts: test_site
|
||||
mariadb: 10.3
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- name: "Python 2.7 Server Side Test"
|
||||
python: 2.7
|
||||
script: bench --site test_site run-tests --app erpnext --coverage
|
||||
|
||||
- name: "Python 3.6 Server Side Test"
|
||||
python: 3.6
|
||||
script: bench --site test_site run-tests --app erpnext --coverage
|
||||
|
||||
- name: "Python 2.7 Patch Test"
|
||||
python: 2.7
|
||||
before_script:
|
||||
- wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz
|
||||
- bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz
|
||||
script: bench --site test_site migrate
|
||||
|
||||
- name: "Python 3.6 Patch Test"
|
||||
python: 3.6
|
||||
before_script:
|
||||
- wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz
|
||||
- bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz
|
||||
script: bench --site test_site migrate
|
||||
|
||||
install:
|
||||
# fix mongodb travis error
|
||||
- sudo rm /etc/apt/sources.list.d/mongodb*.list
|
||||
- pip install flake8==3.3.0
|
||||
- flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
|
||||
- sudo rm /etc/apt/sources.list.d/docker.list
|
||||
- sudo apt-get install hhvm && rm -rf /home/travis/.kiex/
|
||||
- sudo apt-get purge -y mysql-common mysql-server mysql-client
|
||||
- cd ~
|
||||
- nvm install 10
|
||||
- pip install python-coveralls
|
||||
- wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py
|
||||
- sudo python install.py --develop --user travis --without-bench-setup
|
||||
- sudo pip install -e ~/bench
|
||||
|
||||
- rm $TRAVIS_BUILD_DIR/.git/shallow
|
||||
- bash $TRAVIS_BUILD_DIR/travis/bench_init.sh
|
||||
- cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/
|
||||
- git clone https://github.com/frappe/bench --depth 1
|
||||
- pip install -e ./bench
|
||||
|
||||
before_script:
|
||||
- mysql -u root -ptravis -e 'create database test_frappe'
|
||||
- echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis
|
||||
- echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis
|
||||
- git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1
|
||||
- bench init --skip-assets --frappe-path ~/frappe --python $(which python) frappe-bench
|
||||
|
||||
- mkdir ~/frappe-bench/sites/test_site
|
||||
- cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/
|
||||
|
||||
- mysql -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
|
||||
- mysql -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
|
||||
|
||||
- mysql -u root -e "CREATE DATABASE test_frappe"
|
||||
- mysql -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
|
||||
- mysql -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
|
||||
|
||||
- mysql -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
|
||||
- mysql -u root -e "FLUSH PRIVILEGES"
|
||||
|
||||
- wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
|
||||
- tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
|
||||
- sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
|
||||
- sudo chmod o+x /usr/local/bin/wkhtmltopdf
|
||||
|
||||
- cd ~/frappe-bench
|
||||
- bench get-app erpnext $TRAVIS_BUILD_DIR
|
||||
- bench use test_site
|
||||
- bench reinstall --mariadb-root-username root --mariadb-root-password travis --yes
|
||||
- bench scheduler disable
|
||||
- sed -i 's/9000/9001/g' sites/common_site_config.json
|
||||
- bench start &
|
||||
- sleep 10
|
||||
|
||||
script:
|
||||
- bash $TRAVIS_BUILD_DIR/travis/run-tests.sh
|
||||
- sed -i 's/watch:/# watch:/g' Procfile
|
||||
- sed -i 's/schedule:/# schedule:/g' Procfile
|
||||
- sed -i 's/socketio:/# socketio:/g' Procfile
|
||||
- sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile
|
||||
|
||||
- bench get-app erpnext $TRAVIS_BUILD_DIR
|
||||
- bench start &
|
||||
- bench --site test_site reinstall --yes
|
||||
|
||||
after_script:
|
||||
- pip install python-coveralls
|
||||
- coveralls -b apps/erpnext -d ../../sites/.coverage
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"mail_login": "test@example.com",
|
||||
"mail_password": "test",
|
||||
"admin_password": "admin",
|
||||
"run_selenium_tests": 1,
|
||||
"host_name": "http://localhost:8000",
|
||||
"root_login": "root",
|
||||
"root_password": "travis",
|
||||
"host_name": "http://test_site:8000",
|
||||
"install_apps": ["erpnext"]
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '11.1.49'
|
||||
__version__ = '11.1.53'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -45,7 +45,7 @@ class BankTransaction(StatusUpdater):
|
||||
def clear_linked_payment_entries(self):
|
||||
for payment_entry in self.payment_entries:
|
||||
allocated_amount = get_total_allocated_amount(payment_entry)
|
||||
paid_amount = get_paid_amount(payment_entry)
|
||||
paid_amount = get_paid_amount(payment_entry, self.currency)
|
||||
|
||||
if paid_amount and allocated_amount:
|
||||
if flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount):
|
||||
@@ -80,9 +80,17 @@ def get_total_allocated_amount(payment_entry):
|
||||
AND
|
||||
bt.docstatus = 1""", (payment_entry.payment_document, payment_entry.payment_entry), as_dict=True)
|
||||
|
||||
def get_paid_amount(payment_entry):
|
||||
def get_paid_amount(payment_entry, currency):
|
||||
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
|
||||
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "paid_amount")
|
||||
|
||||
paid_amount_field = "paid_amount"
|
||||
if payment_entry.payment_document == 'Payment Entry':
|
||||
doc = frappe.get_doc("Payment Entry", payment_entry.payment_entry)
|
||||
paid_amount_field = ("base_paid_amount"
|
||||
if doc.paid_to_account_currency == currency else "paid_amount")
|
||||
|
||||
return frappe.db.get_value(payment_entry.payment_document,
|
||||
payment_entry.payment_entry, paid_amount_field)
|
||||
|
||||
elif payment_entry.payment_document == "Journal Entry":
|
||||
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_credit")
|
||||
|
||||
@@ -38,7 +38,10 @@ def get_loyalty_details(customer, loyalty_program, expiry_date=None, company=Non
|
||||
@frappe.whitelist()
|
||||
def get_loyalty_program_details_with_points(customer, loyalty_program=None, expiry_date=None, company=None, silent=False, include_expired_entry=False, current_transaction_amount=0):
|
||||
lp_details = get_loyalty_program_details(customer, loyalty_program, company=company, silent=silent)
|
||||
loyalty_program = frappe.get_doc("Loyalty Program", loyalty_program or lp_details.loyalty_program)
|
||||
loyalty_program_name = loyalty_program or lp_details.loyalty_program
|
||||
if not loyalty_program_name: return
|
||||
|
||||
loyalty_program = frappe.get_doc("Loyalty Program", loyalty_program_name)
|
||||
lp_details.update(get_loyalty_details(customer, loyalty_program.name, expiry_date, company, include_expired_entry))
|
||||
|
||||
tier_spent_level = sorted([d.as_dict() for d in loyalty_program.collection_rules],
|
||||
|
||||
@@ -613,13 +613,18 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
|
||||
|
||||
orders = []
|
||||
if voucher_type:
|
||||
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
||||
if party_account_currency == company_currency:
|
||||
grand_total_field = "base_grand_total"
|
||||
rounded_total_field = "base_rounded_total"
|
||||
else:
|
||||
grand_total_field = "grand_total"
|
||||
rounded_total_field = "rounded_total"
|
||||
|
||||
orders = frappe.db.sql("""
|
||||
select
|
||||
name as voucher_no,
|
||||
{ref_field} as invoice_amount,
|
||||
({ref_field} - advance_paid) as outstanding_amount,
|
||||
if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) as invoice_amount,
|
||||
(if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) - advance_paid) as outstanding_amount,
|
||||
transaction_date as posting_date
|
||||
from
|
||||
`tab{voucher_type}`
|
||||
@@ -627,17 +632,18 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
|
||||
{party_type} = %s
|
||||
and docstatus = 1
|
||||
and ifnull(status, "") != "Closed"
|
||||
and {ref_field} > advance_paid
|
||||
and if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) > advance_paid
|
||||
and abs(100 - per_billed) > 0.01
|
||||
{condition}
|
||||
order by
|
||||
transaction_date, name
|
||||
""".format(**{
|
||||
"ref_field": ref_field,
|
||||
"rounded_total_field": rounded_total_field,
|
||||
"grand_total_field": grand_total_field,
|
||||
"voucher_type": voucher_type,
|
||||
"party_type": scrub(party_type),
|
||||
"condition": condition
|
||||
}), party, as_dict=True)
|
||||
}), (party), as_dict=True)
|
||||
|
||||
order_list = []
|
||||
for d in orders:
|
||||
|
||||
@@ -20,11 +20,13 @@ test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Templ
|
||||
test_ignore = ["Serial No"]
|
||||
|
||||
class TestPurchaseInvoice(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
unlink_payment_on_cancel_of_invoice()
|
||||
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
|
||||
|
||||
def tearDown(self):
|
||||
@classmethod
|
||||
def tearDownClass(self):
|
||||
unlink_payment_on_cancel_of_invoice(0)
|
||||
|
||||
def test_gl_entries_without_perpetual_inventory(self):
|
||||
@@ -91,6 +93,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
pi_doc = frappe.get_doc('Purchase Invoice', pi_doc.name)
|
||||
|
||||
self.assertRaises(frappe.LinkExistsError, pi_doc.cancel)
|
||||
unlink_payment_on_cancel_of_invoice()
|
||||
|
||||
def test_purchase_invoice_for_blocked_supplier(self):
|
||||
supplier = frappe.get_doc('Supplier', '_Test Supplier')
|
||||
|
||||
@@ -44,6 +44,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
|
||||
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
|
||||
|
||||
if (this.frm.doc.is_return) {
|
||||
this.frm.return_print_format = "Sales Invoice Return";
|
||||
}
|
||||
|
||||
this.show_general_ledger();
|
||||
|
||||
if(doc.update_stock) this.show_stock_ledger();
|
||||
@@ -131,16 +135,24 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
},
|
||||
|
||||
set_default_print_format: function() {
|
||||
// set default print format to POS type
|
||||
// set default print format to POS type or Credit Note
|
||||
if(cur_frm.doc.is_pos) {
|
||||
if(cur_frm.pos_print_format) {
|
||||
cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
|
||||
cur_frm.meta.default_print_format = cur_frm.pos_print_format;
|
||||
}
|
||||
} else if(cur_frm.doc.is_return) {
|
||||
if(cur_frm.return_print_format) {
|
||||
cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
|
||||
cur_frm.meta.default_print_format = cur_frm.return_print_format;
|
||||
}
|
||||
} else {
|
||||
if(cur_frm.meta._default_print_format) {
|
||||
cur_frm.meta.default_print_format = cur_frm.meta._default_print_format;
|
||||
cur_frm.meta._default_print_format = null;
|
||||
} else if(in_list([cur_frm.pos_print_format, cur_frm.return_print_format], cur_frm.meta.default_print_format)) {
|
||||
cur_frm.meta.default_print_format = null;
|
||||
cur_frm.meta._default_print_format = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -28,10 +28,12 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
w.submit()
|
||||
return w
|
||||
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
unlink_payment_on_cancel_of_invoice()
|
||||
|
||||
def tearDown(self):
|
||||
@classmethod
|
||||
def tearDownClass(self):
|
||||
unlink_payment_on_cancel_of_invoice(0)
|
||||
|
||||
def test_timestamp_change(self):
|
||||
@@ -134,6 +136,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
unlink_payment_on_cancel_of_invoice(0)
|
||||
si = frappe.get_doc('Sales Invoice', si.name)
|
||||
self.assertRaises(frappe.LinkExistsError, si.cancel)
|
||||
unlink_payment_on_cancel_of_invoice()
|
||||
|
||||
def test_sales_invoice_calculation_export_currency(self):
|
||||
si = frappe.copy_doc(test_records[2])
|
||||
|
||||
@@ -124,8 +124,6 @@ def check_matching_amount(bank_account, company, transaction):
|
||||
'txt': '%%%s%%' % amount
|
||||
}, as_dict=True)
|
||||
|
||||
frappe.errprint(journal_entries)
|
||||
|
||||
if transaction.credit > 0:
|
||||
sales_invoices = frappe.db.sql("""
|
||||
SELECT
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
{%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value, fieldmeta,
|
||||
get_width, get_align_class -%}
|
||||
|
||||
{%- macro render_currency(df, doc) -%}
|
||||
<div class="row {% if df.bold %}important{% endif %} data-field">
|
||||
<div class="col-xs-{{ "9" if df.fieldtype=="Check" else "5" }}
|
||||
{%- if doc._align_labels_right %} text-right{%- endif -%}">
|
||||
<label>{{ _(df.label) }}</label>
|
||||
</div>
|
||||
<div class="col-xs-{{ "3" if df.fieldtype=="Check" else "7" }} value">
|
||||
{% if doc.get(df.fieldname) != None -%}
|
||||
{{ frappe.utils.fmt_money((doc[df.fieldname])|int|abs, currency=doc.currency) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro render_taxes(df, doc) -%}
|
||||
{%- set data = doc.get(df.fieldname)[df.start:df.end] -%}
|
||||
<div class="row">
|
||||
<div class="col-xs-6"></div>
|
||||
<div class="col-xs-6">
|
||||
{%- for charge in data -%}
|
||||
{%- if (charge.tax_amount or doc.flags.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
|
||||
<div class="row">
|
||||
<div class="col-xs-5 {%- if doc._align_labels_right %} text-right{%- endif -%}">
|
||||
<label>{{ charge.get_formatted("description") }}</label></div>
|
||||
<div class="col-xs-7 text-right">
|
||||
{{ frappe.utils.fmt_money((charge.tax_amount)|int|abs, currency=doc.currency) }}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro render_table(df, doc) -%}
|
||||
{%- set table_meta = frappe.get_meta(df.options) -%}
|
||||
{%- set data = doc.get(df.fieldname)[df.start:df.end] -%}
|
||||
{%- if doc.print_templates and
|
||||
doc.print_templates.get(df.fieldname) -%}
|
||||
{% include doc.print_templates[df.fieldname] %}
|
||||
{%- else -%}
|
||||
{%- if data -%}
|
||||
{%- set visible_columns = get_visible_columns(doc.get(df.fieldname),
|
||||
table_meta, df) -%}
|
||||
<div {{ fieldmeta(df) }}>
|
||||
<table class="table table-bordered table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 40px" class="table-sr">{{ _("Sr") }}</th>
|
||||
{% for tdf in visible_columns %}
|
||||
{% if (data and not data[0].flags.compact_item_print) or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %}
|
||||
<th style="width: {{ get_width(tdf) }};" class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
|
||||
{{ _(tdf.label) }}</th>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for d in data %}
|
||||
<tr>
|
||||
<td class="table-sr">{{ d.idx }}</td>
|
||||
{% for tdf in visible_columns %}
|
||||
{% if not d.flags.compact_item_print or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %}
|
||||
<td class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
|
||||
{% if tdf.fieldtype == 'Currency' %}
|
||||
<div class="value">{{ frappe.utils.fmt_money((d[tdf.fieldname])|int|abs, currency=doc.currency) }}</div></td>
|
||||
{% else %}
|
||||
<div class="value">{{ print_value(tdf, d, doc, visible_columns) }}</div></td>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{% for page in layout %}
|
||||
<div class="page-break">
|
||||
<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
|
||||
{{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}
|
||||
</div>
|
||||
|
||||
{% if print_settings.repeat_header_footer %}
|
||||
<div id="footer-html" class="visible-pdf">
|
||||
{% if not no_letterhead and footer %}
|
||||
<div class="letter-head-footer">
|
||||
{{ footer }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<p class="text-center small page-number visible-pdf">
|
||||
{{ _("Page {0} of {1}").format('<span class="page"></span>', '<span class="topage"></span>') }}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% for section in page %}
|
||||
<div class="row section-break">
|
||||
{% if section.columns.fields %}
|
||||
{%- if doc._line_breaks and loop.index != 1 -%}<hr>{%- endif -%}
|
||||
{%- if doc._show_section_headings and section.label and section.has_data -%}
|
||||
<h4 class='col-sm-12'>{{ _(section.label) }}</h4>
|
||||
{% endif %}
|
||||
{%- endif -%}
|
||||
{% for column in section.columns %}
|
||||
<div class="col-xs-{{ (12 / section.columns|len)|int }} column-break">
|
||||
{% for df in column.fields %}
|
||||
{% if df.fieldname == 'taxes' %}
|
||||
{{ render_taxes(df, doc) }}
|
||||
{% elif df.fieldtype == 'Currency' %}
|
||||
{{ render_currency(df, doc) }}
|
||||
{% elif df.fieldtype =='Table' %}
|
||||
{{ render_table(df, doc)}}
|
||||
{% elif doc[df.fieldname] %}
|
||||
{{ render_field(df, doc) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"align_labels_right": 1,
|
||||
"creation": "2019-07-24 20:13:30.259953",
|
||||
"custom_format": 0,
|
||||
"default_print_language": "en-US",
|
||||
"disabled": 0,
|
||||
"doc_type": "Sales Invoice",
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Format",
|
||||
"font": "Default",
|
||||
"html": "",
|
||||
"idx": 0,
|
||||
"line_breaks": 1,
|
||||
"modified": "2019-07-24 20:13:30.259953",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Return",
|
||||
"owner": "Administrator",
|
||||
"print_format_builder": 0,
|
||||
"print_format_type": "Jinja",
|
||||
"raw_printing": 0,
|
||||
"show_section_headings": 1,
|
||||
"standard": "Yes"
|
||||
}
|
||||
@@ -58,8 +58,7 @@ def get_columns():
|
||||
{
|
||||
"fieldname": "payment_document",
|
||||
"label": _("Payment Document Type"),
|
||||
"fieldtype": "Link",
|
||||
"options": "DocType",
|
||||
"fieldtype": "Data",
|
||||
"width": 220
|
||||
},
|
||||
{
|
||||
|
||||
@@ -30,7 +30,9 @@ def update_last_purchase_rate(doc, is_submit):
|
||||
# for it to be considered for latest purchase rate
|
||||
if flt(d.conversion_factor):
|
||||
last_purchase_rate = flt(d.base_rate) / flt(d.conversion_factor)
|
||||
else:
|
||||
# Check if item code is present
|
||||
# Conversion factor should not be mandatory for non itemized items
|
||||
elif d.item_code:
|
||||
frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx))
|
||||
|
||||
# update last purchsae rate
|
||||
@@ -84,13 +86,13 @@ def get_linked_material_requests(items):
|
||||
items = json.loads(items)
|
||||
mr_list = []
|
||||
for item in items:
|
||||
material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name,
|
||||
(mr_item.qty - mr_item.ordered_qty) AS qty,
|
||||
material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name,
|
||||
(mr_item.qty - mr_item.ordered_qty) AS qty,
|
||||
mr_item.item_code AS item_code,
|
||||
mr_item.name AS mr_item
|
||||
mr_item.name AS mr_item
|
||||
FROM `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
|
||||
WHERE mr.name = mr_item.parent
|
||||
AND mr_item.item_code = %(item)s
|
||||
AND mr_item.item_code = %(item)s
|
||||
AND mr.material_request_type = 'Purchase'
|
||||
AND mr.per_ordered < 99.99
|
||||
AND mr.docstatus = 1
|
||||
@@ -98,6 +100,6 @@ def get_linked_material_requests(items):
|
||||
ORDER BY mr_item.item_code ASC""",{"item": item}, as_dict=1)
|
||||
if material_request:
|
||||
mr_list.append(material_request)
|
||||
|
||||
|
||||
return mr_list
|
||||
|
||||
|
||||
@@ -58,7 +58,9 @@ class AccountsController(TransactionBase):
|
||||
|
||||
def validate(self):
|
||||
|
||||
self.validate_qty_is_not_zero()
|
||||
if not self.get('is_return'):
|
||||
self.validate_qty_is_not_zero()
|
||||
|
||||
if self.get("_action") and self._action != "update_after_submit":
|
||||
self.set_missing_values(for_validate=True)
|
||||
|
||||
@@ -1110,6 +1112,10 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name):
|
||||
.format(child_item.idx, child_item.item_code))
|
||||
else:
|
||||
child_item.rate = flt(d.get("rate"))
|
||||
if flt(child_item.price_list_rate):
|
||||
child_item.discount_percentage = flt((1 - flt(child_item.rate) / flt(child_item.price_list_rate)) * 100.0, \
|
||||
child_item.precision("discount_percentage"))
|
||||
|
||||
child_item.flags.ignore_validate_update_after_submit = True
|
||||
child_item.save()
|
||||
|
||||
|
||||
@@ -395,7 +395,9 @@ class BuyingController(StockController):
|
||||
def set_qty_as_per_stock_uom(self):
|
||||
for d in self.get("items"):
|
||||
if d.meta.get_field("stock_qty"):
|
||||
if not d.conversion_factor:
|
||||
# Check if item code is present
|
||||
# Conversion factor should not be mandatory for non itemized items
|
||||
if not d.conversion_factor and d.item_code:
|
||||
frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx))
|
||||
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
|
||||
|
||||
|
||||
@@ -76,7 +76,12 @@ class calculate_taxes_and_totals(object):
|
||||
item.discount_amount = item.price_list_rate - item.rate
|
||||
|
||||
item.net_rate = item.rate
|
||||
item.amount = flt(item.rate * item.qty, item.precision("amount"))
|
||||
|
||||
if not item.qty and self.doc.get("is_return"):
|
||||
item.amount = flt(-1 * item.rate, item.precision("amount"))
|
||||
else:
|
||||
item.amount = flt(item.rate * item.qty, item.precision("amount"))
|
||||
|
||||
item.net_amount = item.amount
|
||||
|
||||
self._set_in_company_currency(item, ["price_list_rate", "rate", "net_rate", "amount", "net_amount"])
|
||||
|
||||
@@ -77,7 +77,7 @@ def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_len
|
||||
|
||||
if or_filters:
|
||||
for r in frappe.get_list(doctype, fields=fields,filters=filters, or_filters=or_filters,
|
||||
limit_start=limit_start, limit_page_length=limit_page_length,
|
||||
limit_start=limit_start, limit_page_length=limit_page_length,
|
||||
ignore_permissions=ignore_permissions, order_by=order_by):
|
||||
data.append(r)
|
||||
|
||||
@@ -130,38 +130,56 @@ def get_customers_suppliers(doctype, user):
|
||||
suppliers = []
|
||||
meta = frappe.get_meta(doctype)
|
||||
|
||||
customer_field_name = get_customer_field_name(doctype)
|
||||
|
||||
has_customer_field = meta.has_field(customer_field_name)
|
||||
has_supplier_field = meta.has_field('supplier')
|
||||
|
||||
if has_common(["Supplier", "Customer"], frappe.get_roles(user)):
|
||||
contacts = frappe.db.sql("""
|
||||
select
|
||||
select
|
||||
`tabContact`.email_id,
|
||||
`tabDynamic Link`.link_doctype,
|
||||
`tabDynamic Link`.link_name
|
||||
from
|
||||
from
|
||||
`tabContact`, `tabDynamic Link`
|
||||
where
|
||||
`tabContact`.name=`tabDynamic Link`.parent and `tabContact`.email_id =%s
|
||||
""", user, as_dict=1)
|
||||
customers = [c.link_name for c in contacts if c.link_doctype == 'Customer'] \
|
||||
if meta.get_field("customer") else None
|
||||
suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier'] \
|
||||
if meta.get_field("supplier") else None
|
||||
customers = [c.link_name for c in contacts if c.link_doctype == 'Customer']
|
||||
suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier']
|
||||
elif frappe.has_permission(doctype, 'read', user=user):
|
||||
customers = [customer.name for customer in frappe.get_list("Customer")] \
|
||||
if meta.get_field("customer") else None
|
||||
suppliers = [supplier.name for supplier in frappe.get_list("Customer")] \
|
||||
if meta.get_field("supplier") else None
|
||||
customer_list = frappe.get_list("Customer")
|
||||
customers = suppliers = [customer.name for customer in customer_list]
|
||||
|
||||
return customers, suppliers
|
||||
return customers if has_customer_field else None, \
|
||||
suppliers if has_supplier_field else None
|
||||
|
||||
def has_website_permission(doc, ptype, user, verbose=False):
|
||||
doctype = doc.doctype
|
||||
customers, suppliers = get_customers_suppliers(doctype, user)
|
||||
if customers:
|
||||
return frappe.get_all(doctype, filters=[(doctype, "customer", "in", customers),
|
||||
(doctype, "name", "=", doc.name)]) and True or False
|
||||
return frappe.db.exists(doctype, filters=get_customer_filter(doc, customers))
|
||||
elif suppliers:
|
||||
fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier'
|
||||
return frappe.get_all(doctype, filters=[(doctype, fieldname, "in", suppliers),
|
||||
(doctype, "name", "=", doc.name)]) and True or False
|
||||
return frappe.db.exists(doctype, filters={
|
||||
'name': doc.name,
|
||||
fieldname: ["in", suppliers]
|
||||
})
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_customer_filter(doc, customers):
|
||||
doctype = doc.doctype
|
||||
filters = frappe._dict()
|
||||
filters.name = doc.name
|
||||
filters[get_customer_field_name(doctype)] = ['in', customers]
|
||||
if doctype == 'Quotation':
|
||||
filters.party_type = 'Customer'
|
||||
return filters
|
||||
|
||||
def get_customer_field_name(doctype):
|
||||
if doctype == 'Quotation':
|
||||
return 'party_name'
|
||||
else:
|
||||
return 'customer'
|
||||
@@ -64,13 +64,20 @@ class EmployeeAdvance(Document):
|
||||
|
||||
def update_claimed_amount(self):
|
||||
claimed_amount = frappe.db.sql("""
|
||||
select sum(ifnull(allocated_amount, 0))
|
||||
from `tabExpense Claim Advance`
|
||||
where employee_advance = %s and docstatus=1 and allocated_amount > 0
|
||||
SELECT sum(ifnull(allocated_amount, 0))
|
||||
FROM `tabExpense Claim Advance` eca, `tabExpense Claim` ec
|
||||
WHERE
|
||||
eca.employee_advance = %s
|
||||
AND ec.approval_status="Approved"
|
||||
AND ec.name = eca.parent
|
||||
AND ec.docstatus=1
|
||||
AND eca.allocated_amount > 0
|
||||
""", self.name)[0][0] or 0
|
||||
|
||||
if claimed_amount:
|
||||
frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
|
||||
frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
|
||||
self.reload()
|
||||
self.set_status()
|
||||
frappe.db.set_value("Employee Advance", self.name, "status", self.status)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_due_advance_amount(employee, posting_date):
|
||||
|
||||
@@ -178,7 +178,7 @@ frappe.ui.form.on("Expense Claim", {
|
||||
refresh: function(frm) {
|
||||
frm.trigger("toggle_fields");
|
||||
|
||||
if(frm.doc.docstatus == 1) {
|
||||
if(frm.doc.docstatus === 1 && frm.doc.approval_status !== "Rejected") {
|
||||
frm.add_custom_button(__('Accounting Ledger'), function() {
|
||||
frappe.route_options = {
|
||||
voucher_no: frm.doc.name,
|
||||
@@ -189,7 +189,7 @@ frappe.ui.form.on("Expense Claim", {
|
||||
}, __("View"));
|
||||
}
|
||||
|
||||
if (frm.doc.docstatus===1
|
||||
if (frm.doc.docstatus===1 && !cint(frm.doc.is_paid) && cint(frm.doc.grand_total) > 0
|
||||
&& (cint(frm.doc.total_amount_reimbursed) < cint(frm.doc.total_sanctioned_amount))
|
||||
&& frappe.model.can_create("Payment Entry")) {
|
||||
frm.add_custom_button(__('Payment'),
|
||||
|
||||
@@ -12,6 +12,16 @@ from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
|
||||
|
||||
class PayrollEntry(Document):
|
||||
def onload(self):
|
||||
if not self.docstatus==1:
|
||||
return
|
||||
|
||||
# check if salary slips were manually submitted
|
||||
entries = frappe.db.count("Salary Slip", {'payroll_entry': self.name, 'docstatus': 1}, ['name'])
|
||||
if cint(entries) == len(self.employees) and not self.salary_slips_submitted:
|
||||
self.db_set("salary_slips_submitted", 1)
|
||||
self.reload()
|
||||
|
||||
def on_submit(self):
|
||||
self.create_salary_slips()
|
||||
|
||||
|
||||
@@ -92,5 +92,5 @@ def make_company():
|
||||
company.abbr = "_TC10"
|
||||
company.parent_company = "_Test Company"
|
||||
company.default_currency = "INR"
|
||||
company.country = "India"
|
||||
company.country = "Pakistan"
|
||||
company.insert()
|
||||
|
||||
@@ -91,7 +91,13 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
||||
$.each(this.frm.doc["items"] || [], function(i, item) {
|
||||
frappe.model.round_floats_in(item);
|
||||
item.net_rate = item.rate;
|
||||
item.amount = flt(item.rate * item.qty, precision("amount", item));
|
||||
|
||||
if ((!item.qty) && me.frm.doc.is_return) {
|
||||
item.amount = flt(item.rate * -1, precision("amount", item));
|
||||
} else {
|
||||
item.amount = flt(item.rate * item.qty, precision("amount", item));
|
||||
}
|
||||
|
||||
item.net_amount = item.amount;
|
||||
item.item_tax_amount = 0.0;
|
||||
item.total_weight = flt(item.weight_per_unit * item.stock_qty);
|
||||
|
||||
@@ -152,7 +152,7 @@ class Gstr1Report(object):
|
||||
|
||||
customers = frappe.get_all("Customer", filters={"disabled": 0})
|
||||
|
||||
if self.filters.get("type_of_business") == "B2B":
|
||||
if self.filters.get("type_of_business") == "B2B" and customers:
|
||||
conditions += """ and ifnull(invoice_type, '') != 'Export' and is_return != 1
|
||||
and customer in ('{0}') and (customer_gstin IS NOT NULL AND customer_gstin NOT IN ('', 'NA'))""".\
|
||||
format("', '".join([frappe.db.escape(c.name) for c in customers]))
|
||||
@@ -162,14 +162,14 @@ class Gstr1Report(object):
|
||||
if not b2c_limit:
|
||||
frappe.throw(_("Please set B2C Limit in GST Settings."))
|
||||
|
||||
if self.filters.get("type_of_business") == "B2C Large":
|
||||
if self.filters.get("type_of_business") == "B2C Large" and customers:
|
||||
conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2)
|
||||
and grand_total > {0} and is_return != 1 and customer in ('{1}')""".\
|
||||
and grand_total > {0} and is_return != 1 and customer in ('{1}') and (customer_gstin IS NULL OR customer_gstin IN ('', 'NA'))""".\
|
||||
format(flt(b2c_limit), "', '".join([frappe.db.escape(c.name) for c in customers]))
|
||||
elif self.filters.get("type_of_business") == "B2C Small":
|
||||
elif self.filters.get("type_of_business") == "B2C Small" and customers:
|
||||
conditions += """ and (
|
||||
SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2)
|
||||
or grand_total <= {0}) and is_return != 1 and customer in ('{1}')""".\
|
||||
or grand_total <= {0}) and is_return != 1 and customer in ('{1}') and (customer_gstin IS NULL OR customer_gstin IN ('', 'NA'))""".\
|
||||
format(flt(b2c_limit), "', '".join([frappe.db.escape(c.name) for c in customers]))
|
||||
|
||||
elif self.filters.get("type_of_business") == "CDNR":
|
||||
|
||||
@@ -262,27 +262,44 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
var fields = [
|
||||
{fieldtype:'Table', fieldname: 'items',
|
||||
description: __('Select BOM and Qty for Production'),
|
||||
fields: [
|
||||
{fieldtype:'Read Only', fieldname:'item_code',
|
||||
label: __('Item Code'), in_list_view:1},
|
||||
{fieldtype:'Link', fieldname:'bom', options: 'BOM', reqd: 1,
|
||||
label: __('Select BOM'), in_list_view:1, get_query: function(doc) {
|
||||
return {filters: {item: doc.item_code}};
|
||||
}},
|
||||
{fieldtype:'Float', fieldname:'pending_qty', reqd: 1,
|
||||
label: __('Qty'), in_list_view:1},
|
||||
{fieldtype:'Data', fieldname:'sales_order_item', reqd: 1,
|
||||
label: __('Sales Order Item'), hidden:1}
|
||||
],
|
||||
data: r.message,
|
||||
get_data: function() {
|
||||
return r.message
|
||||
const fields = [{
|
||||
label: 'Items',
|
||||
fieldtype: 'Table',
|
||||
fieldname: 'items',
|
||||
description: __('Select BOM and Qty for Production'),
|
||||
fields: [{
|
||||
fieldtype: 'Read Only',
|
||||
fieldname: 'item_code',
|
||||
label: __('Item Code'),
|
||||
in_list_view: 1
|
||||
}, {
|
||||
fieldtype: 'Link',
|
||||
fieldname: 'bom',
|
||||
options: 'BOM',
|
||||
reqd: 1,
|
||||
label: __('Select BOM'),
|
||||
in_list_view: 1,
|
||||
get_query: function (doc) {
|
||||
return { filters: { item: doc.item_code } };
|
||||
}
|
||||
}, {
|
||||
fieldtype: 'Float',
|
||||
fieldname: 'pending_qty',
|
||||
reqd: 1,
|
||||
label: __('Qty'),
|
||||
in_list_view: 1
|
||||
}, {
|
||||
fieldtype: 'Data',
|
||||
fieldname: 'sales_order_item',
|
||||
reqd: 1,
|
||||
label: __('Sales Order Item'),
|
||||
hidden: 1
|
||||
}],
|
||||
data: r.message,
|
||||
get_data: () => {
|
||||
return r.message
|
||||
}
|
||||
]
|
||||
}]
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __('Select Items to Manufacture'),
|
||||
fields: fields,
|
||||
|
||||
@@ -202,13 +202,12 @@ def _get_cart_quotation(party=None):
|
||||
if quotation:
|
||||
qdoc = frappe.get_doc("Quotation", quotation[0].name)
|
||||
else:
|
||||
[company, price_list] = frappe.db.get_value("Shopping Cart Settings", None, ["company", "price_list"])
|
||||
company = frappe.db.get_value("Shopping Cart Settings", None, ["company"])
|
||||
qdoc = frappe.get_doc({
|
||||
"doctype": "Quotation",
|
||||
"naming_series": get_shopping_cart_settings().quotation_series or "QTN-CART-",
|
||||
"quotation_to": party.doctype,
|
||||
"company": company,
|
||||
"selling_price_list": price_list,
|
||||
"order_type": "Shopping Cart",
|
||||
"status": "Draft",
|
||||
"docstatus": 0,
|
||||
|
||||
@@ -753,13 +753,13 @@ class StockEntry(StockController):
|
||||
|
||||
self.add_to_stock_entry_detail(item_dict)
|
||||
|
||||
if self.purpose != "Subcontract":
|
||||
scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty)
|
||||
for item in itervalues(scrap_item_dict):
|
||||
if self.pro_doc and self.pro_doc.scrap_warehouse:
|
||||
item["to_warehouse"] = self.pro_doc.scrap_warehouse
|
||||
if self.purpose != "Subcontract" and self.purpose == "Manufacture":
|
||||
scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty)
|
||||
for item in itervalues(scrap_item_dict):
|
||||
if self.pro_doc and self.pro_doc.scrap_warehouse:
|
||||
item["to_warehouse"] = self.pro_doc.scrap_warehouse
|
||||
|
||||
self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no)
|
||||
self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no)
|
||||
|
||||
# fetch the serial_no of the first stock entry for the second stock entry
|
||||
if self.work_order and self.purpose == "Manufacture":
|
||||
|
||||
@@ -15,9 +15,10 @@ from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
|
||||
class TestStockReconciliation(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
|
||||
self.insert_existing_sle()
|
||||
insert_existing_sle()
|
||||
|
||||
def test_reco_for_fifo(self):
|
||||
self._test_reco_sle_gle("FIFO")
|
||||
@@ -94,17 +95,17 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
self.assertEqual(["_Test Stock Reco Item", "_Test Warehouse Ledger 1 - _TC", 100],
|
||||
[items[0]["item_code"], items[0]["warehouse"], items[0]["qty"]])
|
||||
|
||||
def insert_existing_sle(self):
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||
def insert_existing_sle():
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||
|
||||
make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item",
|
||||
target="_Test Warehouse - _TC", qty=10, basic_rate=700)
|
||||
make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item",
|
||||
target="_Test Warehouse - _TC", qty=10, basic_rate=700)
|
||||
|
||||
make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item",
|
||||
source="_Test Warehouse - _TC", qty=15)
|
||||
make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item",
|
||||
source="_Test Warehouse - _TC", qty=15)
|
||||
|
||||
make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item",
|
||||
target="_Test Warehouse - _TC", qty=15, basic_rate=1200)
|
||||
make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item",
|
||||
target="_Test Warehouse - _TC", qty=15, basic_rate=1200)
|
||||
|
||||
def create_stock_reconciliation(**args):
|
||||
args = frappe._dict(args)
|
||||
|
||||
@@ -8,16 +8,7 @@ import unittest
|
||||
|
||||
class TestStockSettings(unittest.TestCase):
|
||||
def setUp(self):
|
||||
settings = frappe.get_single('Stock Settings')
|
||||
settings.clean_description_html = 0
|
||||
settings.save()
|
||||
|
||||
frappe.delete_doc('Item', 'Item for description test')
|
||||
|
||||
def tearDown(self):
|
||||
settings = frappe.get_single('Stock Settings')
|
||||
settings.clean_description_html = 1
|
||||
settings.save()
|
||||
frappe.db.set_value("Stock Settings", None, "clean_description_html", 0)
|
||||
|
||||
def test_settings(self):
|
||||
item = frappe.get_doc(dict(
|
||||
|
||||
@@ -360,8 +360,17 @@ class update_entries_after(object):
|
||||
self.stock_queue.append([0, sle.incoming_rate or sle.outgoing_rate or self.valuation_rate])
|
||||
|
||||
def check_if_allow_zero_valuation_rate(self, voucher_type, voucher_detail_no):
|
||||
ref_item_dt = voucher_type + (" Detail" if voucher_type == "Stock Entry" else " Item")
|
||||
return frappe.db.get_value(ref_item_dt, voucher_detail_no, "allow_zero_valuation_rate")
|
||||
ref_item_dt = ""
|
||||
|
||||
if voucher_type == "Stock Entry":
|
||||
ref_item_dt = voucher_type + " Detail"
|
||||
elif voucher_type in ["Purchase Invoice", "Sales Invoice", "Delivery Note", "Purchase Receipt"]:
|
||||
ref_item_dt = voucher_type + " Item"
|
||||
|
||||
if ref_item_dt:
|
||||
return frappe.db.get_value(ref_item_dt, voucher_detail_no, "allow_zero_valuation_rate")
|
||||
else:
|
||||
return 0
|
||||
|
||||
def get_sle_before_datetime(self):
|
||||
"""get previous stock ledger entry before current time-bucket"""
|
||||
|
||||
@@ -2,45 +2,31 @@
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
from frappe.desk import notifications
|
||||
from frappe.test_runner import make_test_objects
|
||||
|
||||
class TestNotifications(unittest.TestCase):
|
||||
def setUp(self):
|
||||
test_records_company = [
|
||||
{
|
||||
"abbr": "_TC6",
|
||||
"company_name": "_Test Company 6",
|
||||
"country": "India",
|
||||
"default_currency": "INR",
|
||||
"doctype": "Company",
|
||||
"domain": "Manufacturing",
|
||||
"monthly_sales_target": 2000,
|
||||
"chart_of_accounts": "Standard"
|
||||
},
|
||||
{
|
||||
"abbr": "_TC7",
|
||||
"company_name": "_Test Company 7",
|
||||
"country": "United States",
|
||||
"default_currency": "USD",
|
||||
"doctype": "Company",
|
||||
"domain": "Retail",
|
||||
"monthly_sales_target": 10000,
|
||||
"total_monthly_sales": 1000,
|
||||
"chart_of_accounts": "Standard"
|
||||
},
|
||||
]
|
||||
|
||||
make_test_objects('Company', test_records=test_records_company, reset=True)
|
||||
|
||||
def test_get_notifications_for_targets(self):
|
||||
'''
|
||||
Test notification config entries for targets as percentages
|
||||
'''
|
||||
|
||||
company = frappe.get_all("Company")[0]
|
||||
frappe.db.set_value("Company", company.name, "monthly_sales_target", 10000)
|
||||
frappe.db.set_value("Company", company.name, "total_monthly_sales", 1000)
|
||||
|
||||
config = notifications.get_notification_config()
|
||||
doc_target_percents = notifications.get_notifications_for_targets(config, {})
|
||||
self.assertEqual(doc_target_percents['Company']['_Test Company 7'], 10)
|
||||
self.assertEqual(doc_target_percents['Company']['_Test Company 6'], 0)
|
||||
|
||||
self.assertEqual(doc_target_percents['Company'][company.name], 10)
|
||||
|
||||
frappe.db.set_value("Company", company.name, "monthly_sales_target", 2000)
|
||||
frappe.db.set_value("Company", company.name, "total_monthly_sales", 0)
|
||||
|
||||
config = notifications.get_notification_config()
|
||||
doc_target_percents = notifications.get_notifications_for_targets(config, {})
|
||||
|
||||
self.assertEqual(doc_target_percents['Company'][company.name], 0)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
erpnext
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd ~/
|
||||
curl -I https://github.com/frappe/frappe/tree/$TRAVIS_BRANCH | head -n 1 | cut -d $' ' -f2 | (
|
||||
read response;
|
||||
[ $response == '200' ] && branch=$TRAVIS_BRANCH || branch='develop';
|
||||
bench init frappe-bench --frappe-path https://github.com/frappe/frappe.git --frappe-branch $branch --python $(which python)
|
||||
)
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ $TEST_TYPE == 'Server Side Test' ]]; then
|
||||
bench run-tests --app erpnext --coverage
|
||||
|
||||
elif [[ $TEST_TYPE == 'Patch Test' ]]; then
|
||||
wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz
|
||||
bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis
|
||||
bench migrate
|
||||
fi
|
||||
Reference in New Issue
Block a user