diff --git a/.travis.yml b/.travis.yml index f7d28be0095..a70062fea3a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,4 +55,7 @@ script: - set -e - bench run-tests - sleep 5 + - bench reinstall --yes + - bench execute erpnext.setup.setup_wizard.utils.complete + - bench execute erpnext.setup.utils.enable_all_roles_and_domains - bench run-ui-tests --app erpnext diff --git a/erpnext/__init__.py b/erpnext/__init__.py index fb7c761e4f0..1d47f02b41e 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from erpnext.hooks import regional_overrides -__version__ = '8.8.3' +__version__ = '8.8.4' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 05986a08085..92a805f37df 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -499,6 +499,7 @@ frappe.ui.form.on('Payment Entry', { var c = frm.add_child("references"); c.reference_doctype = d.voucher_type; c.reference_name = d.voucher_no; + c.due_date = d.due_date c.total_amount = d.invoice_amount; c.outstanding_amount = d.outstanding_amount; if(!in_list(["Sales Order", "Purchase Order", "Expense Claim"], d.voucher_type)) { diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index c38645067c2..ef233c67995 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -325,23 +325,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte } this.frm.refresh_fields(); - }, - - company_address: function() { - var me = this; - if(this.frm.doc.company_address) { - frappe.call({ - method: "frappe.contacts.doctype.address.address.get_address_display", - args: {"address_dict": this.frm.doc.company_address }, - callback: function(r) { - if(r.message) { - me.frm.set_value("company_address_display", r.message) - } - } - }) - } else { - this.frm.set_value("company_address_display", ""); - } } }); diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 8c57cab83bf..6002590d8f8 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -19,6 +19,7 @@ from erpnext.accounts.doctype.asset.depreciation \ import get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal from erpnext.stock.doctype.batch.batch import set_batch_nos from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, get_delivery_note_serial_no +from erpnext.setup.doctype.company.company import update_company_current_month_sales form_grid_templates = { "items": "templates/form_grid/item_grid.html" @@ -140,7 +141,7 @@ class SalesInvoice(SellingController): self.update_time_sheet(self.name) - frappe.enqueue('erpnext.setup.doctype.company.company.update_company_current_month_sales', company=self.company) + self.update_current_month_sales() def validate_pos_paid_amount(self): if len(self.payments) == 0 and self.is_pos: @@ -178,6 +179,15 @@ class SalesInvoice(SellingController): self.make_gl_entries_on_cancel() frappe.db.set(self, 'status', 'Cancelled') + self.update_current_month_sales() + + def update_current_month_sales(self): + if frappe.flags.in_test: + update_company_current_month_sales(self.company) + else: + frappe.enqueue('erpnext.setup.doctype.company.company.update_company_current_month_sales', + company=self.company) + def update_status_updater_args(self): if cint(self.update_stock): self.status_updater.extend([{ diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 331aee9e9b3..23007fbc1ae 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1304,6 +1304,17 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(getdate(expected_gl_entries[i][3]), getdate(gle.due_date)) + def test_company_monthly_sales(self): + existing_current_month_sales = frappe.db.get_value("Company", "_Test Company", "total_monthly_sales") + + si = create_sales_invoice() + current_month_sales = frappe.db.get_value("Company", "_Test Company", "total_monthly_sales") + self.assertEqual(current_month_sales, existing_current_month_sales + si.base_grand_total) + + si.cancel() + current_month_sales = frappe.db.get_value("Company", "_Test Company", "total_monthly_sales") + self.assertEqual(current_month_sales, existing_current_month_sales) + def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") args = frappe._dict(args) diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index 36f4221ce13..9e963328b54 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -8,6 +8,7 @@ from frappe import _ from frappe.model.document import Document from frappe.utils import cstr, cint from frappe.contacts.doctype.address.address import get_default_address +from erpnext.setup.doctype.customer_group.customer_group import get_parent_customer_groups class IncorrectCustomerGroup(frappe.ValidationError): pass class IncorrectSupplierType(frappe.ValidationError): pass @@ -134,6 +135,9 @@ def get_tax_template(posting_date, args): for key, value in args.iteritems(): if key=="use_for_shopping_cart": conditions.append("use_for_shopping_cart = {0}".format(1 if value else 0)) + if key == 'customer_group' and value: + customer_group_condition = get_customer_group_condition(value) + conditions.append("ifnull({0}, '') in ('', {1})".format(key, customer_group_condition)) else: conditions.append("ifnull({0}, '') in ('', '{1}')".format(key, frappe.db.escape(cstr(value)))) @@ -157,3 +161,8 @@ def get_tax_template(posting_date, args): return None return tax_template + +def get_customer_group_condition(customer_group): + customer_groups = ["'%s'"%(d.name) for d in get_parent_customer_groups(frappe.db.escape(customer_group))] + condition = ",".join(['%s'] * len(customer_groups))%(tuple(customer_groups)) + return condition \ No newline at end of file diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py index a09d81b5c67..383b02b1287 100644 --- a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py @@ -34,6 +34,14 @@ class TestTaxRule(unittest.TestCase): tax_rule2.save() self.assertTrue(tax_rule2.name) + def test_for_parent_customer_group(self): + tax_rule1 = make_tax_rule(customer_group= "All Customer Groups", + sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01") + tax_rule1.save() + + self.assertEquals(get_tax_template("2015-01-01", {"customer_group" : "Commercial"}), + "_Test Sales Taxes and Charges Template") + def test_conflict_with_overlapping_dates(self): tax_rule1 = make_tax_rule(customer= "_Test Customer", sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01", to_date = "2015-01-05") diff --git a/erpnext/accounts/page/pos/test_pos.js b/erpnext/accounts/page/pos/test_pos.js index 62c6e31eb5d..bc5edc9f2a4 100644 --- a/erpnext/accounts/page/pos/test_pos.js +++ b/erpnext/accounts/page/pos/test_pos.js @@ -6,11 +6,11 @@ QUnit.test("test:POS Profile", function(assert) { () => { return frappe.tests.make("POS Profile", [ {naming_series: "SINV"}, - {company: "_Test Company"}, + {company: "Test Company"}, {country: "India"}, {currency: "INR"}, - {write_off_account: "Write Off - _TC"}, - {write_off_cost_center: "Main - _TC"}, + {write_off_account: "Write Off - TC"}, + {write_off_cost_center: "Main - TC"}, {payments: [ [ {"default": 1}, @@ -35,15 +35,16 @@ QUnit.test("test:Sales Invoice", function(assert) { frappe.run_serially([ () => { return frappe.tests.make("Sales Invoice", [ - {customer: "_Test Customer 2"}, - {company: "_Test Company"}, + {customer: "Test Customer 2"}, + {company: "Test Company"}, {is_pos: 1}, {posting_date: frappe.datetime.get_today()}, {due_date: frappe.datetime.get_today()}, {items: [ [ - {"item_code": "_Test Item"}, - {"qty": 5} + {"item_code": "Test Product 1"}, + {"qty": 5}, + {"warehouse":'Stores - TC'} ]] } ]); diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 5cb04c5eb65..ba7ae323d46 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -79,7 +79,7 @@ def set_address_details(out, party, party_type, doctype=None, company=None): out.shipping_address = get_address_display(out["shipping_address_name"]) out.update(get_fetch_values(doctype, 'shipping_address_name', out.shipping_address_name)) - if doctype and doctype in ['Sales Invoice']: + if doctype and doctype in ['Delivery Note', 'Sales Invoice']: out.update(get_company_address(company)) if out.company_address: out.update(get_fetch_values(doctype, 'company_address', out.company_address)) diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index 0d1eba1ad3c..8f9948e41c5 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import flt +from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import get_tax_accounts def execute(filters=None): return _execute(filters) @@ -12,12 +13,12 @@ def execute(filters=None): def _execute(filters=None, additional_table_columns=None, additional_query_columns=None): if not filters: filters = {} columns = get_columns(additional_table_columns) - last_col = len(columns) item_list = get_items(filters, additional_query_columns) aii_account_map = get_aii_accounts() if item_list: - item_row_tax, tax_accounts = get_tax_accounts(item_list, columns) + itemised_tax, tax_columns = get_tax_accounts(item_list, columns, + tax_doctype="Purchase Taxes and Charges") columns.append({ "fieldname": "currency", @@ -26,6 +27,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum "width": 80 }) company_currency = frappe.db.get_value("Company", filters.company, "default_currency") + po_pr_map = get_purchase_receipts_against_purchase_order(item_list) data = [] for d in item_list: @@ -33,8 +35,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum if d.purchase_receipt: purchase_receipt = d.purchase_receipt elif d.po_detail: - purchase_receipt = ", ".join(frappe.db.sql_list("""select distinct parent - from `tabPurchase Receipt Item` where docstatus=1 and purchase_order_item=%s""", d.po_detail)) + purchase_receipt = ", ".join(po_pr_map.get(d.po_detail, [])) expense_account = d.expense_account or aii_account_map.get(d.company) row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date, d.supplier, @@ -46,13 +47,15 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum row += [ d.credit_to, d.mode_of_payment, d.project, d.company, d.purchase_order, - purchase_receipt, expense_account, d.qty, d.base_net_rate, d.base_net_amount + purchase_receipt, expense_account, d.qty, d.stock_uom, d.base_net_rate, d.base_net_amount ] - for tax in tax_accounts: - row.append(item_row_tax.get(d.name, {}).get(tax, 0)) + total_tax = 0 + for tax in tax_columns: + item_tax = itemised_tax.get(d.name, {}).get(tax, {}) + row += [item_tax.get("tax_rate", 0), item_tax.get("tax_amount", 0)] + total_tax += flt(item_tax.get("tax_amount")) - total_tax = sum(row[last_col:]) row += [total_tax, d.base_net_amount + total_tax, company_currency] data.append(row) @@ -76,7 +79,8 @@ def get_columns(additional_table_columns): _("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100", _("Purchase Order") + ":Link/Purchase Order:100", _("Purchase Receipt") + ":Link/Purchase Receipt:100", _("Expense Account") + ":Link/Account:140", - _("Qty") + ":Float:120", _("Rate") + ":Currency/currency:120", _("Amount") + ":Currency/currency:120" + _("Qty") + ":Float:120", _("Stock UOM") + "::100", + _("Rate") + ":Currency/currency:120", _("Amount") + ":Currency/currency:120" ] return columns @@ -106,8 +110,9 @@ def get_items(filters, additional_query_columns): pi_item.name, pi_item.parent, pi.posting_date, pi.credit_to, pi.company, pi.supplier, pi.remarks, pi.base_net_total, pi_item.item_code, pi_item.item_name, pi_item.item_group, pi_item.project, pi_item.purchase_order, pi_item.purchase_receipt, - pi_item.po_detail, pi_item.expense_account, pi_item.qty, pi_item.base_net_rate, - pi_item.base_net_amount, pi.supplier_name, pi.mode_of_payment {0} + pi_item.po_detail, pi_item.expense_account, pi_item.qty, pi_item.stock_uom, + pi_item.base_net_rate, pi_item.base_net_amount, + pi.supplier_name, pi.mode_of_payment {0} from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item where pi.name = pi_item.parent and pi.docstatus = 1 %s %s order by pi.posting_date desc, pi_item.item_code desc @@ -116,53 +121,18 @@ def get_items(filters, additional_query_columns): def get_aii_accounts(): return dict(frappe.db.sql("select name, stock_received_but_not_billed from tabCompany")) -def get_tax_accounts(item_list, columns): - import json - item_row_tax = {} - tax_accounts = [] - invoice_item_row = {} - item_row_map = {} - for d in item_list: - invoice_item_row.setdefault(d.parent, []).append(d) - item_row_map.setdefault(d.parent, {}).setdefault(d.item_code, []).append(d) +def get_purchase_receipts_against_purchase_order(item_list): + po_pr_map = frappe._dict() + po_item_rows = list(set([d.po_detail for d in item_list])) - tax_details = frappe.db.sql(""" - select - parent, account_head, item_wise_tax_detail, charge_type, base_tax_amount_after_discount_amount - from `tabPurchase Taxes and Charges` - where parenttype = 'Purchase Invoice' and docstatus = 1 - and (account_head is not null and account_head != '') - and category in ('Total', 'Valuation and Total') - and parent in (%s) - """ % ', '.join(['%s']*len(invoice_item_row)), tuple(invoice_item_row.keys())) + purchase_receipts = frappe.db.sql(""" + select parent, purchase_order_item + from `tabPurchase Receipt Item` + where docstatus=1 and purchase_order_item in (%s) + group by purchase_order_item, parent + """ % (', '.join(['%s']*len(po_item_rows))), tuple(po_item_rows), as_dict=1) - for parent, account_head, item_wise_tax_detail, charge_type, tax_amount in tax_details: - if account_head not in tax_accounts: - tax_accounts.append(account_head) + for pr in purchase_receipts: + po_pr_map.setdefault(pr.po_detail, []).append(pr.parent) - if item_wise_tax_detail: - try: - item_wise_tax_detail = json.loads(item_wise_tax_detail) - - for item_code, tax_amount in item_wise_tax_detail.items(): - tax_amount = flt(tax_amount[1]) if isinstance(tax_amount, list) else flt(tax_amount) - - item_net_amount = sum([flt(d.base_net_amount) - for d in item_row_map.get(parent, {}).get(item_code, [])]) - - for d in item_row_map.get(parent, {}).get(item_code, []): - item_tax_amount = flt((tax_amount * d.base_net_amount) / item_net_amount) if item_net_amount else 0 - item_row_tax.setdefault(d.name, {})[account_head] = item_tax_amount - - except ValueError: - continue - elif charge_type == "Actual" and tax_amount: - for d in invoice_item_row.get(parent, []): - item_row_tax.setdefault(d.name, {})[account_head] = \ - flt((tax_amount * d.base_net_amount) / d.base_net_total) - - tax_accounts.sort() - columns += [account_head + ":Currency/currency:80" for account_head in tax_accounts] - columns += ["Total Tax:Currency/currency:80", "Total:Currency/currency:80"] - - return item_row_tax, tax_accounts + return po_pr_map \ No newline at end of file diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index 7d10b19dcee..30c545f58c0 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -13,11 +13,10 @@ def execute(filters=None): def _execute(filters=None, additional_table_columns=None, additional_query_columns=None): if not filters: filters = {} columns = get_columns(additional_table_columns) - last_col = len(columns) item_list = get_items(filters, additional_query_columns) if item_list: - item_row_tax, tax_accounts = get_tax_accounts(item_list, columns) + itemised_tax, tax_columns = get_tax_accounts(item_list, columns) columns.append({ "fieldname": "currency", "label": _("Currency"), @@ -26,6 +25,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum }) company_currency = frappe.db.get_value("Company", filters.get("company"), "default_currency") mode_of_payments = get_mode_of_payments(set([d.parent for d in item_list])) + so_dn_map = get_delivery_notes_against_sales_order(item_list) data = [] for d in item_list: @@ -33,8 +33,8 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum if d.delivery_note: delivery_note = d.delivery_note elif d.so_detail: - delivery_note = ", ".join(frappe.db.sql_list("""select distinct parent - from `tabDelivery Note Item` where docstatus=1 and so_detail=%s""", d.so_detail)) + delivery_note = ", ".join(so_dn_map.get(d.so_detail, [])) + if not delivery_note and d.update_stock: delivery_note = d.parent @@ -47,13 +47,16 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum row += [ d.customer_group, d.debit_to, ", ".join(mode_of_payments.get(d.parent, [])), d.territory, d.project, d.company, d.sales_order, - delivery_note, d.income_account, d.cost_center, d.qty, d.base_net_rate, d.base_net_amount + delivery_note, d.income_account, d.cost_center, d.qty, d.stock_uom, + d.base_net_rate, d.base_net_amount ] - for tax in tax_accounts: - row.append(item_row_tax.get(d.name, {}).get(tax, 0)) + total_tax = 0 + for tax in tax_columns: + item_tax = itemised_tax.get(d.name, {}).get(tax, {}) + row += [item_tax.get("tax_rate", 0), item_tax.get("tax_amount", 0)] + total_tax += flt(item_tax.get("tax_amount")) - total_tax = sum(row[last_col:]) row += [total_tax, d.base_net_amount + total_tax, company_currency] data.append(row) @@ -77,7 +80,7 @@ def get_columns(additional_table_columns): _("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100", _("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100", _("Income Account") + ":Link/Account:140", _("Cost Center") + ":Link/Cost Center:140", - _("Qty") + ":Float:120", + _("Qty") + ":Float:120", _("Stock UOM") + "::100", _("Rate") + ":Currency/currency:120", _("Amount") + ":Currency/currency:120" ] @@ -112,62 +115,98 @@ def get_items(filters, additional_query_columns): si_item.name, si_item.parent, si.posting_date, si.debit_to, si.project, si.customer, si.remarks, si.territory, si.company, si.base_net_total, si_item.item_code, si_item.item_name, si_item.item_group, si_item.sales_order, - si_item.delivery_note, si_item.income_account, si_item.cost_center, si_item.qty, - si_item.base_net_rate, si_item.base_net_amount, si.customer_name, - si.customer_group, si_item.so_detail, si.update_stock {0} + si_item.delivery_note, si_item.income_account, si_item.cost_center, + si_item.qty, si_item.stock_uom, si_item.base_net_rate, si_item.base_net_amount, + si.customer_name, si.customer_group, si_item.so_detail, si.update_stock {0} from `tabSales Invoice` si, `tabSales Invoice Item` si_item where si.name = si_item.parent and si.docstatus = 1 %s order by si.posting_date desc, si_item.item_code desc """.format(additional_query_columns or '') % conditions, filters, as_dict=1) -def get_tax_accounts(item_list, columns): +def get_delivery_notes_against_sales_order(item_list): + so_dn_map = frappe._dict() + so_item_rows = list(set([d.so_detail for d in item_list])) + + delivery_notes = frappe.db.sql(""" + select parent, so_detail + from `tabDelivery Note Item` + where docstatus=1 and so_detail in (%s) + group by so_detail, parent + """ % (', '.join(['%s']*len(so_item_rows))), tuple(so_item_rows), as_dict=1) + + for dn in delivery_notes: + so_dn_map.setdefault(dn.so_detail, []).append(dn.parent) + + return so_dn_map + +def get_tax_accounts(item_list, columns, tax_doctype="Sales Taxes and Charges"): import json - item_row_tax = {} - tax_accounts = [] - invoice_item_row = {} item_row_map = {} + tax_columns = [] + invoice_item_row = {} + itemised_tax = {} for d in item_list: invoice_item_row.setdefault(d.parent, []).append(d) item_row_map.setdefault(d.parent, {}).setdefault(d.item_code, []).append(d) tax_details = frappe.db.sql(""" select - parent, account_head, item_wise_tax_detail, + parent, description, item_wise_tax_detail, charge_type, base_tax_amount_after_discount_amount - from `tabSales Taxes and Charges` + from `tab%s` where parenttype = 'Sales Invoice' and docstatus = 1 - and (account_head is not null and account_head != '') + and (description is not null and description != '') and parent in (%s) - """ % ', '.join(['%s']*len(invoice_item_row)), tuple(invoice_item_row.keys())) + order by description + """ % (tax_doctype, ', '.join(['%s']*len(invoice_item_row))), tuple(invoice_item_row.keys())) - for parent, account_head, item_wise_tax_detail, charge_type, tax_amount in tax_details: - if account_head not in tax_accounts: - tax_accounts.append(account_head) + for parent, description, item_wise_tax_detail, charge_type, tax_amount in tax_details: + if description not in tax_columns and tax_amount: + tax_columns.append(description) if item_wise_tax_detail: try: item_wise_tax_detail = json.loads(item_wise_tax_detail) - for item_code, tax_amount in item_wise_tax_detail.items(): - tax_amount = flt(tax_amount[1]) if isinstance(tax_amount, list) else flt(tax_amount) + for item_code, tax_data in item_wise_tax_detail.items(): + itemised_tax.setdefault(item_code, frappe._dict()) + + if isinstance(tax_data, list): + tax_rate, tax_amount = tax_data + else: + tax_rate = tax_data + tax_amount = 0 + + if charge_type == "Actual" and not tax_rate: + tax_rate = "NA" item_net_amount = sum([flt(d.base_net_amount) for d in item_row_map.get(parent, {}).get(item_code, [])]) for d in item_row_map.get(parent, {}).get(item_code, []): - item_tax_amount = flt((tax_amount * d.base_net_amount) / item_net_amount) if item_net_amount else 0 - item_row_tax.setdefault(d.name, {})[account_head] = item_tax_amount + item_tax_amount = flt((tax_amount * d.base_net_amount) / item_net_amount) \ + if item_net_amount else 0 + if item_tax_amount: + itemised_tax.setdefault(d.name, {})[description] = frappe._dict({ + "tax_rate": tax_rate, + "tax_amount": item_tax_amount + }) except ValueError: continue elif charge_type == "Actual" and tax_amount: for d in invoice_item_row.get(parent, []): - item_row_tax.setdefault(d.name, {})[account_head] = \ - flt((tax_amount * d.base_net_amount) / d.base_net_total) + itemised_tax.setdefault(d.name, {})[description] = frappe._dict({ + "tax_rate": "NA", + "tax_amount": flt((tax_amount * d.base_net_amount) / d.base_net_total) + }) - tax_accounts.sort() - columns += [account_head + ":Currency/currency:80" for account_head in tax_accounts] - columns += ["Total Tax:Currency/currency:80", "Total:Currency/currency:80"] + tax_columns.sort() + for desc in tax_columns: + columns.append(desc + " Rate:Data:80") + columns.append(desc + " Amount:Currency/currency:100") - return item_row_tax, tax_accounts + columns += ["Total Tax:Currency/currency:80", "Total:Currency/currency:100"] + + return itemised_tax, tax_columns diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 00d52d1a1cc..6d6acedd3b6 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -580,9 +580,15 @@ def get_outstanding_invoices(party_type, party, account, condition=None): dr_or_cr = "credit_in_account_currency - debit_in_account_currency" payment_dr_or_cr = "payment_gl_entry.debit_in_account_currency - payment_gl_entry.credit_in_account_currency" + invoice = 'Sales Invoice' if party_type == 'Customer' else 'Purchase Invoice' invoice_list = frappe.db.sql(""" select voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount, due_date, + ( + case when (voucher_type = 'Sales Invoice' or voucher_type = 'Purchase Invoice') + then (select due_date from `tab{invoice}` where name = voucher_no) + else posting_date end + ) as due_date, ( select ifnull(sum({payment_dr_or_cr}), 0) from `tabGL Entry` payment_gl_entry @@ -607,6 +613,7 @@ def get_outstanding_invoices(party_type, party, account, condition=None): having (invoice_amount - payment_amount) > 0.005 order by posting_date, name, due_date""".format( dr_or_cr = dr_or_cr, + invoice = invoice, payment_dr_or_cr = payment_dr_or_cr, condition = condition or "" ), { @@ -621,6 +628,7 @@ def get_outstanding_invoices(party_type, party, account, condition=None): outstanding_invoices.append(frappe._dict({ 'voucher_no': d.voucher_no, 'voucher_type': d.voucher_type, + 'due_date': d.due_date, 'posting_date': d.posting_date, 'invoice_amount': flt(d.invoice_amount), 'payment_amount': flt(d.payment_amount), diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js index 940f36f1fd2..e6529e60dbb 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js @@ -8,10 +8,8 @@ QUnit.test("test: purchase order", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, - {buying_price_list: 'Test-Buying-USD'}, - {currency: 'USD'}, + {currency: 'INR'}, {items: [ [ {"item_code": 'Test Product 4'}, @@ -20,7 +18,7 @@ QUnit.test("test: purchase order", function(assert) { {"qty": 5}, {"uom": 'Unit'}, {"rate": 100}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js index 09fc33d4d8e..8c0c1443144 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order with get items", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {buying_price_list: 'Test-Buying-USD'}, {currency: 'USD'}, @@ -18,7 +17,7 @@ QUnit.test("test: purchase order with get items", function(assert) { {"qty": 5}, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]} ]); @@ -46,9 +45,9 @@ QUnit.test("test: purchase order with get items", function(assert) { assert.ok(cur_frm.doc.items[3].item_name == 'Keyboard', "Product bundle item 3 correct"); }, - () => cur_frm.doc.items[1].warehouse = 'Stores - WP', - () => cur_frm.doc.items[2].warehouse = 'Stores - WP', - () => cur_frm.doc.items[3].warehouse = 'Stores - WP', + () => cur_frm.doc.items[1].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")), + () => cur_frm.doc.items[2].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")), + () => cur_frm.doc.items[3].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")), () => cur_frm.save(), () => frappe.timeout(1), diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js index 654586ae57e..407891d2700 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order receipt", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {buying_price_list: 'Test-Buying-USD'}, {currency: 'USD'}, @@ -20,7 +19,7 @@ QUnit.test("test: purchase order receipt", function(assert) { {"qty": 5}, {"uom": 'Unit'}, {"rate": 100}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, ]); @@ -69,9 +68,9 @@ QUnit.test("test: purchase order receipt", function(assert) { () => { assert.ok($('div.slick-cell.l2.r2 > a').text().includes('Test Product 1') && $('div.slick-cell.l9.r9 > div').text().includes(5) - && $('div.slick-cell.l12.r12 > div').text().includes(100), "Stock ledger entry correct"); + && $('div.slick-cell.l12.r12 > div').text().includes(433.29), "Stock ledger entry correct",$('div.slick-cell.l12.r12 > div').text()); }, () => done() ]); -}); \ No newline at end of file +}); diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js index 54fa7776680..4e73ab8ef4f 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order with discount on grand total", function(assert) () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {buying_price_list: 'Test-Buying-EUR'}, {currency: 'EUR'}, @@ -20,7 +19,7 @@ QUnit.test("test: purchase order with discount on grand total", function(assert) {"rate": 500 }, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, {apply_discount_on: 'Grand Total'}, diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js index 4ea8b976fba..1e54e50dda9 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order with item wise discount", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {buying_price_list: 'Test-Buying-EUR'}, {currency: 'EUR'}, @@ -19,7 +18,7 @@ QUnit.test("test: purchase order with item wise discount", function(assert) { {"uom": 'Unit'}, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, - {"warehouse": 'Stores - WP'}, + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}, {"discount_percentage": 20} ] ]} diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js index 0f543c5972d..bf2dfeb37b7 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order with multi UOM", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {items: [ [ @@ -18,7 +17,7 @@ QUnit.test("test: purchase order with multi UOM", function(assert) { {"rate": 100}, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]} ]); diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js index b5f59ad339d..9d87af23425 100644 --- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js +++ b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js @@ -8,7 +8,6 @@ QUnit.test("test: purchase order with taxes and charges", function(assert) { () => { return frappe.tests.make('Purchase Order', [ {supplier: 'Test Supplier'}, - {company: 'Wind Power LLC'}, {is_subcontracted: 'No'}, {buying_price_list: 'Test-Buying-USD'}, {currency: 'USD'}, @@ -20,7 +19,7 @@ QUnit.test("test: purchase order with taxes and charges", function(assert) { {"rate": 500 }, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)}, {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)}, - {"warehouse": 'Stores - WP'} + {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index 2d8820d9922..d27d224d32a 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -196,6 +196,7 @@ def get_list_context(context=None): from erpnext.controllers.website_list_for_contact import get_list_context list_context = get_list_context(context) list_context["show_sidebar"] = True + list_context["title"] = "Request for Quotation" return list_context def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters): diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js index 6927d82b723..46e8d1f2d69 100644 --- a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js +++ b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js @@ -9,7 +9,6 @@ QUnit.test("test: request_for_quotation", function(assert) { date = frappe.datetime.add_days(frappe.datetime.now_date(), 10); return frappe.tests.make('Request for Quotation', [ {transaction_date: date}, - {company: 'Wind Power LLC'}, {suppliers: [ [ {"supplier": 'Test Supplier'}, @@ -21,7 +20,7 @@ QUnit.test("test: request_for_quotation", function(assert) { {"item_code": 'Test Product 4'}, {"qty": 5}, {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(),20)}, - {"warehouse": 'All Warehouses - WP'} + {"warehouse": 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, {message_for_supplier: 'Please supply the specified items at the best possible rates'}, @@ -30,12 +29,12 @@ QUnit.test("test: request_for_quotation", function(assert) { }, () => { assert.ok(cur_frm.doc.transaction_date == date, "Date correct"); - assert.ok(cur_frm.doc.company == 'Wind Power LLC', "Company correct"); + assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct"); assert.ok(cur_frm.doc.suppliers[0].supplier_name == 'Test Supplier', "Supplier name correct"); assert.ok(cur_frm.doc.suppliers[0].contact == 'Contact 3-Test Supplier', "Contact correct"); assert.ok(cur_frm.doc.suppliers[0].email_id == 'test@supplier.com', "Email id correct"); assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item Name correct"); - assert.ok(cur_frm.doc.items[0].warehouse == 'All Warehouses - WP', "Warehouse correct"); + assert.ok(cur_frm.doc.items[0].warehouse == 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company")), "Warehouse correct"); assert.ok(cur_frm.doc.message_for_supplier == 'Please supply the specified items at the best possible rates', "Reply correct"); assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Term name correct"); }, diff --git a/erpnext/buying/doctype/supplier/test_supplier.js b/erpnext/buying/doctype/supplier/test_supplier.js index 6be40a52bf7..a953a8dd135 100644 --- a/erpnext/buying/doctype/supplier/test_supplier.js +++ b/erpnext/buying/doctype/supplier/test_supplier.js @@ -8,9 +8,8 @@ QUnit.test("test: supplier", function(assert) { return frappe.tests.make('Supplier', [ {supplier_name: 'Test Supplier'}, {supplier_type: 'Hardware'}, - {country: 'United States'}, - {default_currency: 'USD'}, - {default_price_list: 'Test-Buying-USD'}, + {country: 'India'}, + {default_currency: 'INR'}, {credit_days_based_on: 'Fixed Days'}, {accounts: [ [ @@ -68,7 +67,7 @@ QUnit.test("test: supplier", function(assert) { () => { assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Name correct"); assert.ok(cur_frm.doc.supplier_type == 'Hardware', "Type correct"); - assert.ok(cur_frm.doc.default_currency == 'USD', "Currency correct"); + assert.ok(cur_frm.doc.default_currency == 'INR', "Currency correct"); assert.ok(cur_frm.doc.accounts[0].account == 'Creditors - '+frappe.get_abbr('Test Company'), " Account Head abbr correct"); assert.ok($('.address-box:nth-child(3) p').text().includes('Shipping City 3'), "Address correct"); assert.ok($('.col-sm-6+ .col-sm-6 .h6').text().includes('Contact 3'), "Contact correct"); diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js index 8404cb5b25f..76be06c6fbb 100644 --- a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js +++ b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js @@ -11,16 +11,14 @@ QUnit.test("test: supplier quotation", function(assert) { return frappe.tests.make('Supplier Quotation', [ {supplier: 'Test Supplier'}, {transaction_date: date}, - {company: 'Wind Power LLC'}, - {buying_price_list: 'Test-Buying-USD'}, - {currency: 'USD'}, + {currency: 'INR'}, {items: [ [ {"item_code": 'Test Product 4'}, {"qty": 5}, {"uom": 'Unit'}, {"rate": 200}, - {"warehouse": 'All Warehouses - WP'} + {"warehouse": 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company"))} ] ]}, {apply_discount_on: 'Grand Total'}, @@ -32,7 +30,7 @@ QUnit.test("test: supplier quotation", function(assert) { () => { // Get Supplier details assert.ok(cur_frm.doc.supplier == 'Test Supplier', "Supplier correct"); - assert.ok(cur_frm.doc.company == 'Wind Power LLC', "Company correct"); + assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct"); // Get Contact details assert.ok(cur_frm.doc.contact_display == 'Contact 3', "Conatct correct"); assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Email correct"); diff --git a/erpnext/docs/assets/img/setup/print/print-style.png b/erpnext/docs/assets/img/setup/print/print-style.png new file mode 100644 index 00000000000..db93ceb0e6b Binary files /dev/null and b/erpnext/docs/assets/img/setup/print/print-style.png differ diff --git a/erpnext/docs/user/manual/en/setting-up/print/index.txt b/erpnext/docs/user/manual/en/setting-up/print/index.txt index fa236525645..9597cc06cfd 100644 --- a/erpnext/docs/user/manual/en/setting-up/print/index.txt +++ b/erpnext/docs/user/manual/en/setting-up/print/index.txt @@ -1,5 +1,6 @@ print-settings print-format-builder +print-style print-headings letter-head address-template diff --git a/erpnext/docs/user/manual/en/setting-up/print/print-style.md b/erpnext/docs/user/manual/en/setting-up/print/print-style.md new file mode 100644 index 00000000000..bdb0ab0e261 --- /dev/null +++ b/erpnext/docs/user/manual/en/setting-up/print/print-style.md @@ -0,0 +1,15 @@ +# Print Style + +Frappe/ERPNext comes with pre-set styles for your printed documents. You can also create new styles using CSS that can be applied to all your print formats. + +To create a new **Print Style** go to **Setup > Printing and Branding > Print Style**, or just type "print style" in the search bar. + +Here you can define the CSS rules for your print formats. These apply to both standard and custom print formats. To find out the various classes available, you can make a standard print format, open in a new page and see the source. + +To set a default style, you can go to [Print Settings](/docs/setup/print/print-settings) + +All Print Format styles are based on Bootstrap (Version 3) CSS Framework. + +Print Style + +{next} \ No newline at end of file diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 1d176133814..356104e69c2 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -231,12 +231,12 @@ class SalarySlip(TransactionBase): holidays = self.get_holidays_for_employee(self.start_date, self.end_date) working_days = date_diff(self.end_date, self.start_date) + 1 + actual_lwp = self.calculate_lwp(holidays, working_days) if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")): working_days -= len(holidays) if working_days < 0: frappe.throw(_("There are more holidays than working days this month.")) - actual_lwp = self.calculate_lwp(holidays, working_days) if not lwp: lwp = actual_lwp elif lwp != actual_lwp: diff --git a/erpnext/hr/doctype/salary_structure/test_salary_structure.js b/erpnext/hr/doctype/salary_structure/test_salary_structure.js index 074035772cc..23b52f6a1d7 100644 --- a/erpnext/hr/doctype/salary_structure/test_salary_structure.js +++ b/erpnext/hr/doctype/salary_structure/test_salary_structure.js @@ -46,7 +46,7 @@ QUnit.test("test Salary Structure", function(assert) { { payment_account: 'CASH - TC'}, ]); }, - () => frappe.timeout(9), + () => frappe.timeout(10), () => cur_dialog.set_value('value','Test Salary Structure'), () => frappe.timeout(2), () => frappe.click_button('Create'), @@ -75,7 +75,7 @@ QUnit.test("test Salary Structure", function(assert) { }; frappe.run_serially([ () => salary_structure('Test Employee 1','Test Employee 3'), - () => frappe.timeout(14), + () => frappe.timeout(16), () => done() ]); }); \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.js b/erpnext/manufacturing/doctype/production_order/test_production_order.js index 0a7745e6738..a1e910a5de5 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.js +++ b/erpnext/manufacturing/doctype/production_order/test_production_order.js @@ -112,11 +112,11 @@ QUnit.test("test: production order", function (assert) { () => click_make(), () => { assert.equal(cur_frm.doc.total_incoming_value, "105700", - "Incoming cost is correct"); // Price of each item x5, values are in USD + "Incoming cost is correct "+cur_frm.doc.total_incoming_value); // Price of each item x5, values are in INR assert.equal(cur_frm.doc.total_outgoing_value, "99000", - "Outgoing cost is correct"); // Price of each item x5, values are in USD + "Outgoing cost is correct"); // Price of each item x5, values are in INR assert.equal(cur_frm.doc.total_incoming_value - cur_frm.doc.total_outgoing_value, cur_frm.doc.value_difference, - "Value difference is correct"); // Price of each item x5, values are in USD + "Value difference is correct"); // Price of each item x5, values are in INR }, () => frappe.click_button("Save"), () => frappe.timeout(1), @@ -135,4 +135,4 @@ QUnit.test("test: production order", function (assert) { () => done() ]); -}); \ No newline at end of file +}); diff --git a/erpnext/patches.txt b/erpnext/patches.txt index abbb04a6c4c..d781ec788f5 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -421,7 +421,7 @@ erpnext.patches.v8_1.removed_report_support_hours erpnext.patches.v8_1.add_indexes_in_transaction_doctypes erpnext.patches.v8_3.set_restrict_to_domain_for_module_def erpnext.patches.v8_1.update_expense_claim_status -erpnext.patches.v8_3.update_company_total_sales +erpnext.patches.v8_3.update_company_total_sales #2017-08-16 erpnext.patches.v8_4.make_scorecard_records erpnext.patches.v8_1.set_delivery_date_in_so_item #2017-07-28 erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs @@ -432,3 +432,4 @@ erpnext.patches.v8_5.update_customer_group_in_POS_profile erpnext.patches.v8_6.update_timesheet_company_from_PO erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager erpnext.patches.v8_5.remove_project_type_property_setter +erpnext.patches.v8_7.add_more_gst_fields \ No newline at end of file diff --git a/erpnext/patches/v8_7/__init__.py b/erpnext/patches/v8_7/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/patches/v8_7/add_more_gst_fields.py b/erpnext/patches/v8_7/add_more_gst_fields.py new file mode 100644 index 00000000000..a1512ed9b77 --- /dev/null +++ b/erpnext/patches/v8_7/add_more_gst_fields.py @@ -0,0 +1,9 @@ +import frappe +from erpnext.regional.india.setup import make_custom_fields + +def execute(): + company = frappe.get_all('Company', filters = {'country': 'India'}) + if not company: + return + + make_custom_fields() \ No newline at end of file diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js index 92ef72540a0..010d4d92692 100644 --- a/erpnext/public/js/controllers/buying.js +++ b/erpnext/public/js/controllers/buying.js @@ -346,7 +346,21 @@ erpnext.buying.get_items_from_product_bundle = function(frm) { }, freeze: true, callback: function(r) { + const first_row_is_empty = function(child_table){ + if($.isArray(child_table) && child_table.length > 0) { + return !child_table[0].item_code; + } + return false; + }; + + const remove_empty_first_row = function(frm){ + if (first_row_is_empty(frm.doc.items)){ + frm.doc.items = frm.doc.items.splice(1); + } + }; + if(!r.exc && r.message) { + remove_empty_first_row(frm); for ( var i=0; i< r.message.length; i++ ) { var d = frm.add_child("items"); var item = r.message[i]; @@ -366,3 +380,4 @@ erpnext.buying.get_items_from_product_bundle = function(frm) { }); dialog.show(); } + diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index c653640de65..d042bb7220a 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -62,7 +62,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ this.frm.doc.conversion_rate = flt(this.frm.doc.conversion_rate, (cur_frm) ? precision("conversion_rate") : 9); var conversion_rate_label = frappe.meta.get_label(this.frm.doc.doctype, "conversion_rate", this.frm.doc.name); - var company_currency = this.frm.doc.currency || this.get_company_currency(); + var company_currency = this.get_company_currency(); if(!this.frm.doc.conversion_rate) { if(this.frm.doc.currency == company_currency) { @@ -419,7 +419,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ this.frm.doc.currency, precision("rounded_total")); } if(frappe.meta.get_docfield(this.frm.doc.doctype, "base_rounded_total", this.frm.doc.name)) { - var company_currency = this.frm.doc.currency || this.get_company_currency(); + var company_currency = this.get_company_currency(); this.frm.doc.base_rounded_total = round_based_on_smallest_currency_fraction(this.frm.doc.base_grand_total, diff --git a/erpnext/regional/india/gst_state_code_data.json b/erpnext/regional/india/gst_state_code_data.json index 47af9b190ad..6dab81d6688 100644 --- a/erpnext/regional/india/gst_state_code_data.json +++ b/erpnext/regional/india/gst_state_code_data.json @@ -147,7 +147,7 @@ { "state_number": "22", "state_code": "CT", - "state_name": "Chattisgarh" + "state_name": "Chhattisgarh" }, { "state_number": "04", diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index 7a7e937ea45..0c59ba003a8 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -81,6 +81,47 @@ def add_print_formats(): def make_custom_fields(): hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC', fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description', print_hide=1) + invoice_gst_fields = [ + dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break', + insert_after='select_print_heading', print_hide=1, collapsible=1), + dict(fieldname='invoice_copy', label='Invoice Copy', + fieldtype='Select', insert_after='gst_section', print_hide=1, allow_on_submit=1, + options='Original for Recipient\nDuplicate for Transporter\nDuplicate for Supplier\nTriplicate for Supplier'), + dict(fieldname='reverse_charge', label='Reverse Charge', + fieldtype='Select', insert_after='invoice_copy', print_hide=1, + options='Y\nN', default='N'), + dict(fieldname='gst_col_break', fieldtype='Column Break', insert_after='reverse_charge'), + dict(fieldname='invoice_type', label='Invoice Type', + fieldtype='Select', insert_after='reverse_charge', print_hide=1, + options='Regular\nSEZ\nExport\nDeemed Export', default='Regular'), + dict(fieldname='export_type', label='Export Type', + fieldtype='Select', insert_after='invoice_type', print_hide=1, + depends_on='eval:in_list(["SEZ", "Export", "Deemed Export"], doc.invoice_type)', + options='\nWith Payment of Tax\nWithout Payment of Tax'), + dict(fieldname='ecommerce_gstin', label='E-commerce GSTIN', + fieldtype='Data', insert_after='export_type', print_hide=1) + ] + + purchase_invoice_gst_fields = [ + dict(fieldname='supplier_gstin', label='Supplier GSTIN', + fieldtype='Data', insert_after='supplier_address', + options='supplier_address.gstin', print_hide=1), + dict(fieldname='company_gstin', label='Company GSTIN', + fieldtype='Data', insert_after='shipping_address', + options='shipping_address.gstin', print_hide=1) + ] + + sales_invoice_gst_fields = [ + dict(fieldname='customer_gstin', label='Customer GSTIN', + fieldtype='Data', insert_after='shipping_address', + options='shipping_address_name.gstin', print_hide=1), + dict(fieldname='place_of_supply', label='Place of Supply', + fieldtype='Data', insert_after='customer_gstin', print_hide=1, + options='shipping_address_name.gst_state_number', read_only=1), + dict(fieldname='company_gstin', label='Company GSTIN', + fieldtype='Data', insert_after='company_address', + options='company_address.gstin', print_hide=1) + ] custom_fields = { 'Address': [ @@ -91,25 +132,9 @@ def make_custom_fields(): dict(fieldname='gst_state_number', label='GST State Number', fieldtype='Int', insert_after='gst_state', read_only=1), ], - 'Purchase Invoice': [ - dict(fieldname='supplier_gstin', label='Supplier GSTIN', - fieldtype='Data', insert_after='supplier_address', - options='supplier_address.gstin', print_hide=1), - dict(fieldname='company_gstin', label='Company GSTIN', - fieldtype='Data', insert_after='shipping_address', - options='shipping_address.gstin', print_hide=1), - ], - 'Sales Invoice': [ - dict(fieldname='customer_gstin', label='Customer GSTIN', - fieldtype='Data', insert_after='shipping_address', - options='shipping_address_name.gstin', print_hide=1), - dict(fieldname='company_gstin', label='Company GSTIN', - fieldtype='Data', insert_after='company_address', - options='company_address.gstin', print_hide=1), - dict(fieldname='invoice_copy', label='Invoice Copy', - fieldtype='Select', insert_after='select_print_heading', print_hide=1, allow_on_submit=1, - options='Original for Recipient\nDuplicate for Transporter\nDuplicate for Supplier\nTriplicate for Supplier') - ], + 'Purchase Invoice': purchase_invoice_gst_fields + invoice_gst_fields, + 'Sales Invoice': sales_invoice_gst_fields + invoice_gst_fields, + "Delivery Note": sales_invoice_gst_fields, 'Item': [ dict(fieldname='gst_hsn_code', label='HSN/SAC', fieldtype='Link', options='GST HSN Code', insert_after='item_group'), diff --git a/erpnext/regional/report/gst_itemised_purchase_register/gst_itemised_purchase_register.py b/erpnext/regional/report/gst_itemised_purchase_register/gst_itemised_purchase_register.py index d88febcf333..1d94c97ed26 100644 --- a/erpnext/regional/report/gst_itemised_purchase_register/gst_itemised_purchase_register.py +++ b/erpnext/regional/report/gst_itemised_purchase_register/gst_itemised_purchase_register.py @@ -9,9 +9,17 @@ def execute(filters=None): return _execute(filters, additional_table_columns=[ dict(fieldtype='Data', label='Supplier GSTIN', width=120), dict(fieldtype='Data', label='Company GSTIN', width=120), + dict(fieldtype='Data', label='Reverse Charge', width=120), + dict(fieldtype='Data', label='Invoice Type', width=120), + dict(fieldtype='Data', label='Export Type', width=120), + dict(fieldtype='Data', label='E-Commerce GSTIN', width=130), dict(fieldtype='Data', label='HSN Code', width=120) ], additional_query_columns=[ 'supplier_gstin', 'company_gstin', + 'reverse_charge', + 'invoice_type', + 'export_type', + 'ecommerce_gstin', 'gst_hsn_code' ]) diff --git a/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.py b/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.py index 14ddff37539..40bbae8b555 100644 --- a/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.py +++ b/erpnext/regional/report/gst_itemised_sales_register/gst_itemised_sales_register.py @@ -9,9 +9,19 @@ def execute(filters=None): return _execute(filters, additional_table_columns=[ dict(fieldtype='Data', label='Customer GSTIN', width=120), dict(fieldtype='Data', label='Company GSTIN', width=120), + dict(fieldtype='Data', label='Place of Supply', width=120), + dict(fieldtype='Data', label='Reverse Charge', width=120), + dict(fieldtype='Data', label='Invoice Type', width=120), + dict(fieldtype='Data', label='Export Type', width=120), + dict(fieldtype='Data', label='E-Commerce GSTIN', width=130), dict(fieldtype='Data', label='HSN Code', width=120) ], additional_query_columns=[ 'customer_gstin', 'company_gstin', + 'place_of_supply', + 'reverse_charge', + 'invoice_type', + 'export_type', + 'ecommerce_gstin', 'gst_hsn_code' ]) diff --git a/erpnext/regional/report/gst_purchase_register/gst_purchase_register.py b/erpnext/regional/report/gst_purchase_register/gst_purchase_register.py index 59687d00866..8d479a96cd7 100644 --- a/erpnext/regional/report/gst_purchase_register/gst_purchase_register.py +++ b/erpnext/regional/report/gst_purchase_register/gst_purchase_register.py @@ -8,9 +8,17 @@ from erpnext.accounts.report.purchase_register.purchase_register import _execute def execute(filters=None): return _execute(filters, additional_table_columns=[ dict(fieldtype='Data', label='Supplier GSTIN', width=120), - dict(fieldtype='Data', label='Company GSTIN', width=120) + dict(fieldtype='Data', label='Company GSTIN', width=120), + dict(fieldtype='Data', label='Reverse Charge', width=120), + dict(fieldtype='Data', label='Invoice Type', width=120), + dict(fieldtype='Data', label='Export Type', width=120), + dict(fieldtype='Data', label='E-Commerce GSTIN', width=130) ], additional_query_columns=[ 'supplier_gstin', - 'company_gstin' + 'company_gstin', + 'reverse_charge', + 'invoice_type', + 'export_type', + 'ecommerce_gstin' ]) diff --git a/erpnext/regional/report/gst_sales_register/gst_sales_register.py b/erpnext/regional/report/gst_sales_register/gst_sales_register.py index 440594abb02..7f6f8092764 100644 --- a/erpnext/regional/report/gst_sales_register/gst_sales_register.py +++ b/erpnext/regional/report/gst_sales_register/gst_sales_register.py @@ -8,8 +8,18 @@ from erpnext.accounts.report.sales_register.sales_register import _execute def execute(filters=None): return _execute(filters, additional_table_columns=[ dict(fieldtype='Data', label='Customer GSTIN', width=120), - dict(fieldtype='Data', label='Company GSTIN', width=120) + dict(fieldtype='Data', label='Company GSTIN', width=120), + dict(fieldtype='Data', label='Place of Supply', width=120), + dict(fieldtype='Data', label='Reverse Charge', width=120), + dict(fieldtype='Data', label='Invoice Type', width=120), + dict(fieldtype='Data', label='Export Type', width=120), + dict(fieldtype='Data', label='E-Commerce GSTIN', width=130) ], additional_query_columns=[ 'customer_gstin', - 'company_gstin' + 'company_gstin', + 'place_of_supply', + 'reverse_charge', + 'invoice_type', + 'export_type', + 'ecommerce_gstin' ]) diff --git a/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js b/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js index 5a6f6df99b7..d8877e63e34 100644 --- a/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js +++ b/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js @@ -15,6 +15,7 @@ QUnit.test('test student applicant', function(assert){ () => frappe.timeout(0.5), () => frappe.tests.click_button('Submit'), () => frappe.tests.click_button('Yes'), + () => frappe.timeout(0.5), () => { testing_status = $('span.indicator.orange').text(); assert.ok(testing_status.indexOf('Submit this document to confirm') == -1); // checking if submit has been successfull diff --git a/erpnext/schools/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py b/erpnext/schools/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py index f191022f206..641b78372ce 100644 --- a/erpnext/schools/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py +++ b/erpnext/schools/report/student_and_guardian_contact_details/student_and_guardian_contact_details.py @@ -82,7 +82,7 @@ def get_guardian_map(student_list): select parent, guardian, guardian_name, relation from `tabStudent Guardian` where parent in (%s)''' % ', '.join(['%s']*len(student_list)), tuple(student_list), as_dict=1) - guardian_list = list(set([g.guardian for g in guardian_details])) + guardian_list = list(set([g.guardian for g in guardian_details])) or [''] guardian_mobile_no = dict(frappe.db.sql("""select name, mobile_number from `tabGuardian` where name in (%s)""" % ", ".join(['%s']*len(guardian_list)), tuple(guardian_list))) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 80dc4f23ec6..901e236bd2e 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -179,7 +179,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( doc: this.frm.doc, method: 'get_production_order_items', callback: function(r) { - if(!r.message.every(function(d) { return !!d.bom })) { + if(!r.message) { frappe.msgprint({ title: __('Production Order not created'), message: __('No Items with Bill of Materials to Manufacture'), diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index c6dbd7043b9..396b1c2f61e 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -330,18 +330,19 @@ class SalesOrder(SellingController): def get_production_order_items(self): '''Returns items with BOM that already do not have a linked production order''' items = [] - for i in self.packed_items or self.items: - bom = frappe.get_all('BOM', dict(item=i.item_code, is_active=True), - order_by='is_default desc') - bom = bom[0].name if bom else None - stock_qty = i.qty if self.packed_items else i.stock_qty - items.append(dict( - item_code= i.item_code, - bom = bom, - warehouse = i.warehouse, - pending_qty= stock_qty - flt(frappe.db.sql('''select sum(qty) from `tabProduction Order` - where production_item=%s and sales_order=%s''', (i.item_code, self.name))[0][0]) - )) + + for table in [self.items, self.packed_items]: + for i in table: + bom = get_default_bom_item(i.item_code) + if bom: + stock_qty = i.qty if i.doctype == 'Packed Item' else i.stock_qty + items.append(dict( + item_code= i.item_code, + bom = bom, + warehouse = i.warehouse, + pending_qty= stock_qty - flt(frappe.db.sql('''select sum(qty) from `tabProduction Order` + where production_item=%s and sales_order=%s''', (i.item_code, self.name))[0][0]) + )) return items @@ -465,6 +466,11 @@ def make_delivery_note(source_name, target_doc=None): target.ignore_pricing_rule = 1 target.run_method("set_missing_values") target.run_method("calculate_taxes_and_totals") + + # set company address + target.update(get_company_address(target.company)) + if target.company_address: + target.update(get_fetch_values("Delivery Note", 'company_address', target.company_address)) def update_item(source, target, source_parent): target.base_amount = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.base_rate) @@ -774,3 +780,10 @@ def make_production_orders(items, sales_order, company, project=None): def update_status(status, name): so = frappe.get_doc("Sales Order", name) so.update_status(status) + +def get_default_bom_item(item_code): + bom = frappe.get_all('BOM', dict(item=item_code, is_active=True), + order_by='is_default desc') + bom = bom[0].name if bom else None + + return bom diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 6a84d0e09b5..e9671c87117 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -326,6 +326,23 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.calculate_taxes_and_totals(); cur_frm.refresh_fields(); } + }, + + company_address: function() { + var me = this; + if(this.frm.doc.company_address) { + frappe.call({ + method: "frappe.contacts.doctype.address.address.get_address_display", + args: {"address_dict": this.frm.doc.company_address }, + callback: function(r) { + if(r.message) { + me.frm.set_value("company_address_display", r.message) + } + } + }) + } else { + this.frm.set_value("company_address_display", ""); + } } }); diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 29630eeb843..b945ee41048 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe, os from frappe import _ -from frappe.utils import cint +from frappe.utils import cint, today, formatdate import frappe.defaults @@ -312,39 +312,35 @@ def get_name_with_abbr(name, company): return " - ".join(parts) def update_company_current_month_sales(company): - from frappe.utils import today, formatdate current_month_year = formatdate(today(), "MM-yyyy") - results = frappe.db.sql((''' + results = frappe.db.sql(''' select sum(base_grand_total) as total, date_format(posting_date, '%m-%Y') as month_year from `tabSales Invoice` where - date_format(posting_date, '%m-%Y')="{0}" and - company = "{1}" + date_format(posting_date, '%m-%Y')="{0}" + and docstatus = 1 + and company = "{1}" group by - month_year; - ''').format(current_month_year, frappe.db.escape(company)), as_dict = True) + month_year + '''.format(current_month_year, frappe.db.escape(company)), as_dict = True) monthly_total = results[0]['total'] if len(results) > 0 else 0 - frappe.db.sql((''' - update tabCompany set total_monthly_sales = %s where name=%s - '''), (monthly_total, frappe.db.escape(company))) + frappe.db.set_value("Company", company, "total_monthly_sales", monthly_total) frappe.db.commit() - def update_company_monthly_sales(company): '''Cache past year monthly sales of every company based on sales invoices''' from frappe.utils.goal import get_monthly_results import json - filter_str = "company = '{0}' and status != 'Draft'".format(frappe.db.escape(company)) - month_to_value_dict = get_monthly_results("Sales Invoice", "base_grand_total", "posting_date", filter_str, "sum") + filter_str = "company = '{0}' and status != 'Draft' and docstatus=1".format(frappe.db.escape(company)) + month_to_value_dict = get_monthly_results("Sales Invoice", "base_grand_total", + "posting_date", filter_str, "sum") - frappe.db.sql((''' - update tabCompany set sales_monthly_history = %s where name=%s - '''), (json.dumps(month_to_value_dict), frappe.db.escape(company))) + frappe.db.set_value("Company", company, "sales_monthly_history", json.dumps(month_to_value_dict)) frappe.db.commit() def cache_companies_monthly_sales_history(): diff --git a/erpnext/setup/doctype/company/delete_company_transactions.py b/erpnext/setup/doctype/company/delete_company_transactions.py index f1fb0cf96e4..d975a9ee8da 100644 --- a/erpnext/setup/doctype/company/delete_company_transactions.py +++ b/erpnext/setup/doctype/company/delete_company_transactions.py @@ -27,6 +27,10 @@ def delete_company_transactions(company_name): "Purchase Taxes and Charges Template", "POS Profile", 'BOM'): delete_for_doctype(doctype, company_name) + # reset company values + doc.total_monthly_sales = 0 + doc.sales_monthly_history = None + doc.save() # Clear notification counts clear_notifications() diff --git a/erpnext/setup/doctype/company/tests/test_company_production.js b/erpnext/setup/doctype/company/tests/test_company_production.js index 73bd710e236..b73af1dd98b 100644 --- a/erpnext/setup/doctype/company/tests/test_company_production.js +++ b/erpnext/setup/doctype/company/tests/test_company_production.js @@ -10,7 +10,7 @@ QUnit.test("Test: Company", function (assert) { () => frappe.timeout(1), () => cur_frm.set_value("company_name", "Razer Blade"), () => cur_frm.set_value("abbr", "RB"), - () => cur_frm.set_value("default_currency", "USD"), + () => cur_frm.set_value("default_currency", "INR"), () => cur_frm.save(), () => frappe.timeout(1), diff --git a/erpnext/setup/doctype/customer_group/customer_group.py b/erpnext/setup/doctype/customer_group/customer_group.py index b25095b1b1b..0f1ee818637 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.py +++ b/erpnext/setup/doctype/customer_group/customer_group.py @@ -18,3 +18,10 @@ class CustomerGroup(NestedSet): def validate_name_with_customer(self): if frappe.db.exists("Customer", self.name): frappe.msgprint(_("An Customer exists with same name"), raise_exception=1) + +def get_parent_customer_groups(customer_group): + lft, rgt = frappe.db.get_value("Customer Group", customer_group, ['lft', 'rgt']) + + return frappe.db.sql("""select name from `tabCustomer Group` + where lft <= %s and rgt >= %s + order by lft asc""", (lft, rgt), as_dict=True) \ No newline at end of file diff --git a/erpnext/setup/setup_wizard/data/test_mfg.json b/erpnext/setup/setup_wizard/data/test_mfg.json index 47acaff75ae..b6ea665c76a 100644 --- a/erpnext/setup/setup_wizard/data/test_mfg.json +++ b/erpnext/setup/setup_wizard/data/test_mfg.json @@ -1,7 +1,7 @@ { "add_sample_data": 1, "bank_account": "HDFC", - "company_abbr": "GT", + "company_abbr": "FT", "company_name": "For Testing", "company_tagline": "Just for GST", "country": "India", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json index 345750f04a7..4477c1d0ecb 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.json +++ b/erpnext/stock/doctype/delivery_note/delivery_note.json @@ -860,22 +860,22 @@ "bold": 0, "collapsible": 0, "columns": 0, - "description": "", - "fieldname": "customer_group", + "fieldname": "company_address", "fieldtype": "Link", - "hidden": 1, + "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Customer Group", + "label": "Company Address Name", "length": 0, "no_copy": 0, - "options": "Customer Group", + "options": "Address", "permlevel": 0, - "print_hide": 1, + "precision": "", + "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -891,9 +891,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "description": "", - "fieldname": "territory", - "fieldtype": "Link", + "fieldname": "company_address_display", + "fieldtype": "Small Text", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -901,12 +900,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Territory", + "label": "Company Address", "length": 0, "no_copy": 0, - "options": "Territory", "permlevel": 0, - "print_hide": 1, + "precision": "", + "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -2757,6 +2756,68 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "", + "fieldname": "customer_group", + "fieldtype": "Link", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Customer Group", + "length": 0, + "no_copy": 0, + "options": "Customer Group", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "", + "fieldname": "territory", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Territory", + "length": 0, + "no_copy": 0, + "options": "Territory", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -3426,7 +3487,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-07-19 13:48:09.630820", + "modified": "2017-08-09 15:44:14.253457", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note", diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index 6820d8fa5ba..8377f599791 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -89,7 +89,9 @@ def get_sle_conditions(filters): conditions.append("""sle.item_code in (select item.name from tabItem item {item_conditions})""".format(item_conditions=item_conditions)) if filters.get("warehouse"): - conditions.append(get_warehouse_condition(filters.get("warehouse"))) + warehouse_condition = get_warehouse_condition(filters.get("warehouse")) + if warehouse_condition: + conditions.append(warehouse_condition) if filters.get("voucher_no"): conditions.append("voucher_no=%(voucher_no)s") if filters.get("batch_no"): diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 7c5582b522c..ffdccfd0066 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -60,32 +60,12 @@ erpnext/stock/doctype/material_request/tests/test_material_request_type_manufact erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue.js erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt.js erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer.js -erpnext/schools/doctype/grading_scale/test_grading_scale.js -erpnext/schools/doctype/assessment_criteria_group/test_assessment_criteria_group.js -erpnext/schools/doctype/assessment_criteria/test_assessment_criteria.js -erpnext/schools/doctype/course/test_course.js -erpnext/schools/doctype/program/test_program.js erpnext/hr/doctype/salary_structure/test_salary_structure.js erpnext/hr/doctype/salary_slip/test_salary_slip.js erpnext/hr/doctype/process_payroll/test_process_payroll.js erpnext/hr/doctype/job_opening/test_job_opening.js erpnext/hr/doctype/job_applicant/test_job_applicant.js erpnext/hr/doctype/offer_letter/test_offer_letter.js -erpnext/schools/doctype/guardian/test_guardian.js -erpnext/schools/doctype/student_admission/test_student_admission.js -erpnext/schools/doctype/student_applicant/tests/test_student_applicant_dummy_data.js -erpnext/schools/doctype/student_applicant/tests/test_student_applicant.js -erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js -erpnext/schools/doctype/student_log/test_student_log.js -erpnext/schools/doctype/student_group/test_student_group.js -erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js -erpnext/schools/doctype/student_leave_application/test_student_leave_application.js -erpnext/schools/doctype/student_attendance_tool/test_student_attendance_tool.js -erpnext/schools/doctype/student_attendance/test_student_attendance.js -erpnext/schools/doctype/assessment_group/test_assessment_group.js -erpnext/schools/doctype/assessment_plan/test_assessment_plan.js -erpnext/schools/doctype/assessment_result/test_assessment_result.js -erpnext/schools/doctype/assessment_result_tool/test_assessment_result_tool.js erpnext/buying/doctype/supplier/test_supplier.js erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js @@ -101,4 +81,24 @@ erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_d erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js -erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js \ No newline at end of file +erpnext/schools/doctype/grading_scale/test_grading_scale.js +erpnext/schools/doctype/assessment_criteria_group/test_assessment_criteria_group.js +erpnext/schools/doctype/assessment_criteria/test_assessment_criteria.js +erpnext/schools/doctype/course/test_course.js +erpnext/schools/doctype/program/test_program.js +erpnext/schools/doctype/guardian/test_guardian.js +erpnext/schools/doctype/student_admission/test_student_admission.js +erpnext/schools/doctype/student_applicant/tests/test_student_applicant_dummy_data.js +erpnext/schools/doctype/student_applicant/tests/test_student_applicant.js +erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js +erpnext/schools/doctype/student_log/test_student_log.js +erpnext/schools/doctype/student_group/test_student_group.js +erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js +erpnext/schools/doctype/student_leave_application/test_student_leave_application.js +erpnext/schools/doctype/student_attendance_tool/test_student_attendance_tool.js +erpnext/schools/doctype/student_attendance/test_student_attendance.js +erpnext/schools/doctype/assessment_group/test_assessment_group.js +erpnext/schools/doctype/assessment_plan/test_assessment_plan.js +erpnext/schools/doctype/assessment_result/test_assessment_result.js +erpnext/schools/doctype/assessment_result_tool/test_assessment_result_tool.js +erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js