From b7b7f0062deec675e2d4d6e5c288eb706ec3e096 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 28 Apr 2016 17:31:27 +0530 Subject: [PATCH 1/3] [report][fix] Consider taxes only the tax contributed in invoice total --- .../purchase_register/purchase_register.py | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 7934bf25cd..53cb7af663 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -119,16 +119,22 @@ def get_conditions(filters): def get_invoices(filters): conditions = get_conditions(filters) - return frappe.db.sql("""select name, posting_date, credit_to, supplier, supplier_name, - bill_no, bill_date, remarks, base_net_total, base_grand_total, outstanding_amount - from `tabPurchase Invoice` where docstatus = 1 %s + return frappe.db.sql(""" + select + name, posting_date, credit_to, supplier, supplier_name, + bill_no, bill_date, remarks, base_net_total, base_grand_total, outstanding_amount + from `tabPurchase Invoice` + where docstatus = 1 %s order by posting_date desc, name desc""" % conditions, filters, as_dict=1) def get_invoice_expense_map(invoice_list): - expense_details = frappe.db.sql("""select parent, expense_account, sum(base_net_amount) as amount - from `tabPurchase Invoice Item` where parent in (%s) group by parent, expense_account""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + expense_details = frappe.db.sql(""" + select parent, expense_account, sum(base_net_amount) as amount + from `tabPurchase Invoice Item` + where parent in (%s) + group by parent, expense_account + """ % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) invoice_expense_map = {} for d in expense_details: @@ -138,9 +144,12 @@ def get_invoice_expense_map(invoice_list): return invoice_expense_map def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts): - tax_details = frappe.db.sql("""select parent, account_head, sum(base_tax_amount_after_discount_amount) as tax_amount - from `tabPurchase Taxes and Charges` where parent in (%s) group by parent, account_head""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + tax_details = frappe.db.sql(""" + select parent, account_head, sum(base_tax_amount_after_discount_amount) as tax_amount + from `tabPurchase Taxes and Charges` + where parent in (%s) and category in ('Total', 'Valuation and Total') + group by parent, account_head + """ % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) invoice_tax_map = {} for d in tax_details: @@ -156,10 +165,11 @@ def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts): return invoice_expense_map, invoice_tax_map def get_invoice_po_pr_map(invoice_list): - pi_items = frappe.db.sql("""select parent, purchase_order, purchase_receipt, po_detail, - project from `tabPurchase Invoice Item` where parent in (%s) - and (ifnull(purchase_order, '') != '' or ifnull(purchase_receipt, '') != '')""" % - ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) + pi_items = frappe.db.sql(""" + select parent, purchase_order, purchase_receipt, po_detail, project + from `tabPurchase Invoice Item` + where parent in (%s) and (ifnull(purchase_order, '') != '' or ifnull(purchase_receipt, '') != '') + """ % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1) invoice_po_pr_map = {} for d in pi_items: From 314246939f0968f909d174ffabf0ac5cc5c8af74 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 28 Apr 2016 17:32:36 +0530 Subject: [PATCH 2/3] [report][fix] Item-wise tax calculation if item appears multiple times in the same invoice --- .../item_wise_purchase_register.py | 62 +++++++++++------- .../item_wise_sales_register.py | 63 ++++++++++++------- 2 files changed, 80 insertions(+), 45 deletions(-) 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 f1e706e5d6..0eda1db01e 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 @@ -14,7 +14,7 @@ def execute(filters=None): item_list = get_items(filters) aii_account_map = get_aii_accounts() if item_list: - item_tax, tax_accounts = get_tax_accounts(item_list, columns) + item_row_tax, tax_accounts = get_tax_accounts(item_list, columns) columns.append({ "fieldname": "currency", @@ -23,7 +23,7 @@ def execute(filters=None): "width": 80 }) company_currency = frappe.db.get_value("Company", filters.company, "default_currency") - print company_currency + data = [] for d in item_list: purchase_receipt = None @@ -39,7 +39,7 @@ def execute(filters=None): purchase_receipt, expense_account, d.qty, d.base_net_rate, d.base_net_amount] for tax in tax_accounts: - row.append(item_tax.get(d.parent, {}).get(d.item_code, {}).get(tax, 0)) + row.append(item_row_tax.get(d.name, {}).get(tax, 0)) total_tax = sum(row[last_col:]) row += [total_tax, d.base_net_amount + total_tax, company_currency] @@ -76,29 +76,40 @@ def get_items(filters): conditions = get_conditions(filters) match_conditions = frappe.build_match_conditions("Purchase Invoice") - return frappe.db.sql("""select 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 + return frappe.db.sql(""" + select + 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 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""" % (conditions, match_conditions), filters, as_dict=1) + order by pi.posting_date desc, pi_item.item_code desc + """ % (conditions, match_conditions), filters, as_dict=1) 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_tax = {} + item_row_tax = {} tax_accounts = [] - invoice_wise_items = {} + invoice_item_row = {} + item_row_map = {} for d in item_list: - invoice_wise_items.setdefault(d.parent, []).append(d) + 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, 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_wise_items)), tuple(invoice_wise_items.keys())) + 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())) for parent, account_head, item_wise_tax_detail, charge_type, tax_amount in tax_details: if account_head not in tax_accounts: @@ -107,19 +118,26 @@ def get_tax_accounts(item_list, columns): if item_wise_tax_detail: try: item_wise_tax_detail = json.loads(item_wise_tax_detail) - for item, tax_amount in item_wise_tax_detail.items(): - item_tax.setdefault(parent, {}).setdefault(item, {})[account_head] = \ - flt(tax_amount[1]) if isinstance(tax_amount, list) else flt(tax_amount) + + 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_row_tax.setdefault(d.name, {})[account_head] = \ + flt((tax_amount * d.base_net_amount) / item_net_amount) except ValueError: continue elif charge_type == "Actual" and tax_amount: - for d in invoice_wise_items.get(parent, []): - item_tax.setdefault(parent, {}).setdefault(d.item_code, {})[account_head] = \ - (tax_amount * d.base_net_amount) / d.base_net_total + 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_tax, tax_accounts + return item_row_tax, tax_accounts 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 2401202937..df71350cc7 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,7 +13,7 @@ def execute(filters=None): item_list = get_items(filters) if item_list: - item_tax, tax_accounts = get_tax_accounts(item_list, columns) + item_row_tax, tax_accounts = get_tax_accounts(item_list, columns) columns.append({ "fieldname": "currency", "label": _("Currency"), @@ -36,7 +36,7 @@ def execute(filters=None): delivery_note, d.income_account, d.qty, d.base_net_rate, d.base_net_amount] for tax in tax_accounts: - row.append(item_tax.get(d.parent, {}).get(d.item_code, {}).get(tax, 0)) + row.append(item_row_tax.get(d.name, {}).get(tax, 0)) total_tax = sum(row[last_col:]) row += [total_tax, d.base_net_amount + total_tax, company_currency] @@ -73,49 +73,66 @@ def get_conditions(filters): def get_items(filters): conditions = get_conditions(filters) - return frappe.db.sql("""select 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.qty, si_item.base_net_rate, si_item.base_net_amount, si.customer_name, - si.customer_group, si_item.so_detail + return frappe.db.sql(""" + select + 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.qty, + si_item.base_net_rate, si_item.base_net_amount, si.customer_name, + si.customer_group, si_item.so_detail 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""" % conditions, filters, as_dict=1) def get_tax_accounts(item_list, columns): import json - item_tax = {} + item_row_tax = {} tax_accounts = [] - invoice_wise_items = {} + invoice_item_row = {} + item_row_map = {} for d in item_list: - invoice_wise_items.setdefault(d.parent, []).append(d) + 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, - charge_type, base_tax_amount_after_discount_amount - from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice' - and docstatus = 1 and (account_head is not null and account_head != '') - and parent in (%s)""" % ', '.join(['%s']*len(invoice_wise_items)), - tuple(invoice_wise_items.keys())) + tax_details = frappe.db.sql(""" + select + parent, account_head, item_wise_tax_detail, + charge_type, base_tax_amount_after_discount_amount + from `tabSales Taxes and Charges` + where + parenttype = 'Sales Invoice' and docstatus = 1 + and (account_head is not null and account_head != '') + and parent in (%s) + """ % ', '.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) - + if item_wise_tax_detail: try: item_wise_tax_detail = json.loads(item_wise_tax_detail) - for item, tax_amount in item_wise_tax_detail.items(): - item_tax.setdefault(parent, {}).setdefault(item, {})[account_head] = \ - flt(tax_amount[1]) if isinstance(tax_amount, list) else flt(tax_amount) + + 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_row_tax.setdefault(d.name, {})[account_head] = \ + flt((tax_amount * d.base_net_amount) / item_net_amount) + except ValueError: continue elif charge_type == "Actual" and tax_amount: - for d in invoice_wise_items.get(parent, []): - item_tax.setdefault(parent, {}).setdefault(d.item_code, {})[account_head] = \ + 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_tax, tax_accounts + return item_row_tax, tax_accounts From 761a7a8e7cdeaff37e94a1760bd71583788dbfb8 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 28 Apr 2016 17:33:49 +0530 Subject: [PATCH 3/3] [fix] On rename update item code in item_wise_tax_detail json in tax table --- erpnext/stock/doctype/item/item.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index f18bc8bbe9..e26aaa7089 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -463,9 +463,22 @@ class Item(WebsiteGenerator): clear_cache(self.page_name) frappe.db.set_value("Item", newdn, "item_code", newdn) + if merge: self.set_last_purchase_rate(newdn) self.recalculate_bin_qty(newdn) + + for dt in ("Sales Taxes and Charges", "Purchase Taxes and Charges"): + for d in frappe.db.sql("""select name, item_wise_tax_detail from `tab{0}` + where ifnull(item_wise_tax_detail, '') != ''""".format(dt), as_dict=1): + + item_wise_tax_detail = json.loads(d.item_wise_tax_detail) + if olddn in item_wise_tax_detail: + item_wise_tax_detail[newdn] = item_wise_tax_detail[olddn] + item_wise_tax_detail.pop(olddn) + + frappe.db.set_value(dt, d.name, "item_wise_tax_detail", + json.dumps(item_wise_tax_detail), update_modified=False) def set_last_purchase_rate(self, newdn): last_purchase_rate = get_last_purchase_details(newdn).get("base_rate", 0) @@ -562,7 +575,8 @@ class Item(WebsiteGenerator): variant = get_variant(self.variant_of, args, self.name) if variant: frappe.throw(_("Item variant {0} exists with same attributes") - .format(variant), ItemVariantExistsError) + .format(variant), ItemVariantExistsError) + def validate_end_of_life(item_code, end_of_life=None, disabled=None, verbose=1): if (not end_of_life) or (disabled is None):