diff --git a/erpnext/accounts/custom/address.json b/erpnext/accounts/custom/address.json new file mode 100644 index 00000000000..08f972d13b3 --- /dev/null +++ b/erpnext/accounts/custom/address.json @@ -0,0 +1,58 @@ +{ + "custom_fields": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2018-12-28 22:29:21.828090", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Address", + "fetch_from": null, + "fieldname": "tax_category", + "fieldtype": "Link", + "hidden": 0, + "idx": 14, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "insert_after": "fax", + "label": "Tax Category", + "modified": "2018-12-28 22:29:21.828090", + "modified_by": "Administrator", + "name": "Address-tax_category", + "no_copy": 0, + "options": "Tax Category", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "translatable": 0, + "unique": 0, + "width": null + } + ], + "custom_perms": [], + "doctype": "Address", + "property_setters": [], + "sync_on_migrate": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 1fc226575f3..945d5d47f58 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -112,6 +112,41 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Billing Address", + "description": "Address used to determine Tax Category in transactions.", + "fieldname": "determine_address_tax_category_from", + "fieldtype": "Select", + "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": "Determine Address Tax Category From", + "length": 0, + "no_copy": 0, + "options": "Billing Address\nShipping Address", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -338,6 +373,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "add_taxes_from_item_tax_template", + "fieldtype": "Check", + "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": "Automatically Add Taxes and Charges from Item Tax Template", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -642,7 +710,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2019-01-07 16:52:03.869199", + "modified": "2019-01-07 00:42:34.510150", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", @@ -714,4 +782,4 @@ "track_changes": 1, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py index 54467495364..3222aeb0855 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py @@ -15,6 +15,9 @@ class AccountsSettings(Document): frappe.clear_cache() def validate(self): + for f in ["add_taxes_from_item_tax_template"]: + frappe.db.set_default(f, self.get(f, "")) + self.validate_stale_days() self.enable_payment_schedule_in_print() self.enable_fields_for_cost_center_settings() diff --git a/erpnext/accounts/doctype/item_tax_template/__init__.py b/erpnext/accounts/doctype/item_tax_template/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.js b/erpnext/accounts/doctype/item_tax_template/item_tax_template.js new file mode 100644 index 00000000000..42abdb809ba --- /dev/null +++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.js @@ -0,0 +1,15 @@ +// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Item Tax Template', { + setup: function(frm) { + frm.set_query("tax_type", "taxes", function(doc) { + return { + filters: [ + ['Account', 'is_group', '=', 0], + ['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']] + ] + } + }); + } +}); diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.json b/erpnext/accounts/doctype/item_tax_template/item_tax_template.json new file mode 100644 index 00000000000..f713cfc0bac --- /dev/null +++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.json @@ -0,0 +1,168 @@ +{ + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 1, + "autoname": "field:title", + "beta": 0, + "creation": "2018-11-22 22:45:00.370913", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "title", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Title", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 1 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "taxes", + "fieldtype": "Table", + "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": "Tax Rates", + "length": 0, + "no_copy": 0, + "options": "Item Tax Template Detail", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2018-12-21 23:51:16.328340", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Item Tax Template", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 0 + } + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "search_fields": "", + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0, + "track_views": 0 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.py b/erpnext/accounts/doctype/item_tax_template/item_tax_template.py new file mode 100644 index 00000000000..e77481d44f5 --- /dev/null +++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe.model.document import Document +from frappe import _ + +class ItemTaxTemplate(Document): + def validate(self): + self.validate_tax_accounts() + + def validate_tax_accounts(self): + """Check whether Tax Rate is not entered twice for same Tax Type""" + check_list = [] + for d in self.get('taxes'): + if d.tax_type: + account_type = frappe.db.get_value("Account", d.tax_type, "account_type") + + if account_type not in ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']: + frappe.throw( + _("Item Tax Row {0} must have account of type Tax or Income or Expense or Chargeable").format( + d.idx)) + else: + if d.tax_type in check_list: + frappe.throw(_("{0} entered twice in Item Tax").format(d.tax_type)) + else: + check_list.append(d.tax_type) diff --git a/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.js b/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.js new file mode 100644 index 00000000000..68934993914 --- /dev/null +++ b/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Item Tax Template", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Item Tax Template + () => frappe.tests.make('Item Tax Template', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.py b/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.py new file mode 100644 index 00000000000..acf1e446e74 --- /dev/null +++ b/erpnext/accounts/doctype/item_tax_template/test_item_tax_template.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +class TestItemTaxTemplate(unittest.TestCase): + pass diff --git a/erpnext/accounts/doctype/item_tax_template/test_records.json b/erpnext/accounts/doctype/item_tax_template/test_records.json new file mode 100644 index 00000000000..db540e86aac --- /dev/null +++ b/erpnext/accounts/doctype/item_tax_template/test_records.json @@ -0,0 +1,74 @@ +[ + { + "doctype": "Item Tax Template", + "title": "_Test Account Excise Duty @ 10", + "taxes": [ + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 10, + "tax_type": "_Test Account Excise Duty - _TC" + } + ] + }, + { + "doctype": "Item Tax Template", + "title": "_Test Account Excise Duty @ 12", + "taxes": [ + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 12, + "tax_type": "_Test Account Excise Duty - _TC" + } + ] + }, + { + "doctype": "Item Tax Template", + "title": "_Test Account Excise Duty @ 15", + "taxes": [ + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 15, + "tax_type": "_Test Account Excise Duty - _TC" + } + ] + }, + { + "doctype": "Item Tax Template", + "title": "_Test Account Excise Duty @ 20", + "taxes": [ + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 20, + "tax_type": "_Test Account Excise Duty - _TC" + } + ] + }, + { + "doctype": "Item Tax Template", + "title": "_Test Item Tax Template 1", + "taxes": [ + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 5, + "tax_type": "_Test Account Excise Duty - _TC" + }, + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 10, + "tax_type": "_Test Account Education Cess - _TC" + }, + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 15, + "tax_type": "_Test Account S&H Education Cess - _TC" + } + ] + } +] diff --git a/erpnext/accounts/doctype/item_tax_template_detail/__init__.py b/erpnext/accounts/doctype/item_tax_template_detail/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.json b/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.json new file mode 100644 index 00000000000..fa40222fc66 --- /dev/null +++ b/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.json @@ -0,0 +1,108 @@ +{ + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2018-11-22 23:47:02.804568", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "tax_type", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Tax", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "tax_rate", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Tax Rate", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "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, + "translatable": 0, + "unique": 0 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2018-12-21 23:51:39.445198", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Item Tax Template Detail", + "name_case": "", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0, + "track_views": 0 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py b/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py new file mode 100644 index 00000000000..d51bed0520a --- /dev/null +++ b/erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe.model.document import Document + +class ItemTaxTemplateDetail(Document): + pass diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json old mode 100755 new mode 100644 index 41b3c13a3b9..97c011f082d --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -2185,7 +2185,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "taxes_and_charges", + "fieldname": "tax_category", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -2194,13 +2194,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Taxes and Charges", + "label": "Tax Category", "length": 0, "no_copy": 0, - "oldfieldname": "purchase_other_charges", - "oldfieldtype": "Link", - "options": "Purchase Taxes and Charges Template", + "options": "Tax Category", "permlevel": 0, + "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, @@ -2307,6 +2306,40 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "taxes_and_charges", + "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": "Purchase Taxes and Charges Template", + "length": 0, + "no_copy": 0, + "oldfieldname": "purchase_other_charges", + "oldfieldtype": "Link", + "options": "Purchase Taxes and Charges Template", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -4726,7 +4759,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2019-01-07 16:51:59.800081", + "modified": "2018-12-27 02:07:04.299399", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", @@ -4841,4 +4874,4 @@ "track_changes": 1, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index bfdf451f440..d28dc936bb0 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -206,6 +206,10 @@ class PurchaseInvoice(BuyingController): stock_not_billed_account = self.get_company_default("stock_received_but_not_billed") stock_items = self.get_stock_items() + asset_items = [d.is_fixed_asset for d in self.items if d.is_fixed_asset] + if len(asset_items) > 0: + asset_received_but_not_billed = self.get_company_default("asset_received_but_not_billed") + if self.update_stock: self.validate_item_code() self.validate_warehouse() @@ -226,7 +230,8 @@ class PurchaseInvoice(BuyingController): item.expense_account = warehouse_account[item.warehouse]["account"] else: item.expense_account = stock_not_billed_account - + elif item.is_fixed_asset and d.pr_detail: + item.expense_account = asset_received_but_not_billed elif not item.expense_account and for_validate: throw(_("Expense account is mandatory for item {0}").format(item.item_code or item.item_name)) @@ -360,7 +365,10 @@ class PurchaseInvoice(BuyingController): def get_gl_entries(self, warehouse_account=None): self.auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company) - self.stock_received_but_not_billed = self.get_company_default("stock_received_but_not_billed") + if self.auto_accounting_for_stock: + self.stock_received_but_not_billed = self.get_company_default("stock_received_but_not_billed") + else: + self.stock_received_but_not_billed = None self.expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") self.negative_expense_to_be_booked = 0.0 gl_entries = [] diff --git a/erpnext/accounts/doctype/purchase_invoice/test_records.json b/erpnext/accounts/doctype/purchase_invoice/test_records.json index 7feca2380fe..171927c1822 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_records.json +++ b/erpnext/accounts/doctype/purchase_invoice/test_records.json @@ -18,7 +18,7 @@ "expense_account": "_Test Account Cost for Goods Sold - _TC", "item_code": "_Test Item Home Desktop 100", "item_name": "_Test Item Home Desktop 100", - "item_tax_rate": "{\"_Test Account Excise Duty - _TC\": 10}", + "item_tax_template": "_Test Account Excise Duty @ 10", "parentfield": "items", "qty": 10, "rate": 50, diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index c2309b264a9..7c7a9a31bc0 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -1631,6 +1631,39 @@ "unique": 0, "width": "120px" }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_tax_template", + "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": "Item Tax Template", + "length": 0, + "no_copy": 0, + "options": "Item Tax Template", + "permlevel": 0, + "precision": "", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2626,7 +2659,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-01-07 16:52:00.749414", + "modified": "2018-11-23 16:23:49.360332", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", @@ -2641,4 +2674,4 @@ "track_changes": 0, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 13ba053baeb..5964e954c6c 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -2274,7 +2274,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "taxes_and_charges", + "fieldname": "tax_category", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -2283,13 +2283,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Taxes and Charges", + "label": "Tax Category", "length": 0, "no_copy": 0, - "oldfieldname": "charge", - "oldfieldtype": "Link", - "options": "Sales Taxes and Charges Template", + "options": "Tax Category", "permlevel": 0, + "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, @@ -2394,6 +2393,40 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "taxes_and_charges", + "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": "Sales Taxes and Charges Template", + "length": 0, + "no_copy": 0, + "oldfieldname": "charge", + "oldfieldtype": "Link", + "options": "Sales Taxes and Charges Template", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -5644,7 +5677,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2019-01-07 16:51:53.914523", + "modified": "2018-12-27 02:03:14.009762", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", @@ -5740,4 +5773,4 @@ "track_changes": 1, "track_seen": 1, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/sales_invoice/test_records.json b/erpnext/accounts/doctype/sales_invoice/test_records.json index 0b7b76d1b3b..9c8de7d5a24 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_records.json +++ b/erpnext/accounts/doctype/sales_invoice/test_records.json @@ -142,7 +142,7 @@ "expense_account": "_Test Account Cost for Goods Sold - _TC", "item_code": "_Test Item Home Desktop 100", "item_name": "_Test Item Home Desktop 100", - "item_tax_rate": "{\"_Test Account Excise Duty - _TC\": 10}", + "item_tax_template": "_Test Account Excise Duty @ 10", "parentfield": "items", "price_list_rate": 50, "qty": 10, @@ -269,7 +269,7 @@ "expense_account": "_Test Account Cost for Goods Sold - _TC", "item_code": "_Test Item Home Desktop 100", "item_name": "_Test Item Home Desktop 100", - "item_tax_rate": "{\"_Test Account Excise Duty - _TC\": 10}", + "item_tax_template": "_Test Account Excise Duty @ 10", "parentfield": "items", "price_list_rate": 62.5, "qty": 10, diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index d6ce11536e5..42e6e7a0042 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -1542,6 +1542,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_tax_template", + "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": "Item Tax Template", + "length": 0, + "no_copy": 0, + "options": "Item Tax Template", + "permlevel": 0, + "precision": "", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2766,7 +2799,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-01-07 16:51:55.018091", + "modified": "2018-11-23 17:23:38.327395", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", @@ -2781,4 +2814,4 @@ "track_changes": 0, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/tax_category/__init__.py b/erpnext/accounts/doctype/tax_category/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/doctype/tax_category/tax_category.js b/erpnext/accounts/doctype/tax_category/tax_category.js new file mode 100644 index 00000000000..4b63edbde2d --- /dev/null +++ b/erpnext/accounts/doctype/tax_category/tax_category.js @@ -0,0 +1,8 @@ +// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Tax Category', { + refresh: function(frm) { + + } +}); diff --git a/erpnext/accounts/doctype/tax_category/tax_category.json b/erpnext/accounts/doctype/tax_category/tax_category.json new file mode 100644 index 00000000000..3556e127675 --- /dev/null +++ b/erpnext/accounts/doctype/tax_category/tax_category.json @@ -0,0 +1,134 @@ +{ + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "field:title", + "beta": 0, + "creation": "2018-11-22 23:38:39.668804", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "title", + "fieldtype": "Data", + "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": "Title", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "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, + "translatable": 0, + "unique": 1 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2018-11-22 23:38:39.668804", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Tax Category", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 0 + } + ], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0, + "track_views": 0 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/tax_category/tax_category.py b/erpnext/accounts/doctype/tax_category/tax_category.py new file mode 100644 index 00000000000..2870e3200f8 --- /dev/null +++ b/erpnext/accounts/doctype/tax_category/tax_category.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe.model.document import Document + +class TaxCategory(Document): + pass diff --git a/erpnext/accounts/doctype/tax_category/test_records.json b/erpnext/accounts/doctype/tax_category/test_records.json new file mode 100644 index 00000000000..056b2f3e7ba --- /dev/null +++ b/erpnext/accounts/doctype/tax_category/test_records.json @@ -0,0 +1,10 @@ +[ + { + "doctype": "Tax Category", + "title": "_Test Tax Category 1" + }, + { + "doctype": "Tax Category", + "title": "_Test Tax Category 2" + } +] diff --git a/erpnext/accounts/doctype/tax_category/test_tax_category.js b/erpnext/accounts/doctype/tax_category/test_tax_category.js new file mode 100644 index 00000000000..5142456d769 --- /dev/null +++ b/erpnext/accounts/doctype/tax_category/test_tax_category.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Tax Category", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Tax Category + () => frappe.tests.make('Tax Category', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/accounts/doctype/tax_category/test_tax_category.py b/erpnext/accounts/doctype/tax_category/test_tax_category.py new file mode 100644 index 00000000000..548d00852aa --- /dev/null +++ b/erpnext/accounts/doctype/tax_category/test_tax_category.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +class TestTaxCategory(unittest.TestCase): + pass diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.json b/erpnext/accounts/doctype/tax_rule/tax_rule.json index 6de782f9925..ef155381c0b 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.json +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, @@ -471,6 +472,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "tax_category", + "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": "Tax Category", + "length": 0, + "no_copy": 0, + "options": "Tax Category", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1030,7 +1064,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-08-21 16:15:51.095450", + "modified": "2018-12-27 01:22:17.721636", "modified_by": "Administrator", "module": "Accounts", "name": "Tax Rule", diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index 57b5ddb8894..77f8a0c2bad 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -68,6 +68,7 @@ class TaxRule(Document): "shipping_state": self.shipping_state, "shipping_zipcode": self.shipping_zipcode, "shipping_country": self.shipping_country, + "tax_category": self.tax_category, "company": self.company } @@ -144,10 +145,14 @@ def get_tax_template(posting_date, args): conditions = ["""(from_date is null or from_date <= '{0}') and (to_date is null or to_date >= '{0}')""".format(posting_date)] + conditions.append("ifnull(tax_category, '') = '{0}'".format(frappe.db.escape(cstr(args.get("tax_category"))))) + if 'tax_category' in args.keys(): + del args['tax_category'] + for key, value in iteritems(args): if key=="use_for_shopping_cart": conditions.append("use_for_shopping_cart = {0}".format(1 if value else 0)) - if key == 'customer_group': + elif key == 'customer_group': if not value: value = get_root_of("Customer Group") customer_group_condition = get_customer_group_condition(value) conditions.append("ifnull({0}, '') in ('', {1})".format(key, customer_group_condition)) diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py index d6f9a47079b..bbbcc7f3a69 100644 --- a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py @@ -74,6 +74,26 @@ class TestTaxRule(unittest.TestCase): self.assertEqual(get_tax_template("2015-01-01", {"customer":"_Test Customer 2"}), "_Test Sales Taxes and Charges Template 2 - _TC") + def test_select_tax_rule_based_on_tax_category(self): + make_tax_rule(customer="_Test Customer", tax_category="_Test Tax Category 1", + sales_tax_template="_Test Sales Taxes and Charges Template 1 - _TC", save=1) + + make_tax_rule(customer="_Test Customer", tax_category="_Test Tax Category 2", + sales_tax_template="_Test Sales Taxes and Charges Template 2 - _TC", save=1) + + self.assertFalse(get_tax_template("2015-01-01", {"customer": "_Test Customer"})) + + self.assertEqual(get_tax_template("2015-01-01", {"customer": "_Test Customer", "tax_category": "_Test Tax Category 1"}), + "_Test Sales Taxes and Charges Template 1 - _TC") + self.assertEqual(get_tax_template("2015-01-01", {"customer": "_Test Customer", "tax_category": "_Test Tax Category 2"}), + "_Test Sales Taxes and Charges Template 2 - _TC") + + make_tax_rule(customer="_Test Customer", tax_category="", + sales_tax_template="_Test Sales Taxes and Charges Template - _TC", save=1) + + self.assertEqual(get_tax_template("2015-01-01", {"customer": "_Test Customer"}), + "_Test Sales Taxes and Charges Template - _TC") + def test_select_tax_rule_based_on_better_match(self): make_tax_rule(customer= "_Test Customer", billing_city = "Test City", billing_state = "Test State", sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 9e030cbe771..b200c345485 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -8,7 +8,7 @@ from frappe import _, msgprint, scrub from frappe.core.doctype.user_permission.user_permission import get_permitted_documents from frappe.model.utils import get_fetch_values from frappe.utils import (add_days, getdate, formatdate, date_diff, - add_years, get_timestamp, nowdate, flt, add_months, get_last_day) + add_years, get_timestamp, nowdate, flt, cstr, add_months, get_last_day) from frappe.contacts.doctype.address.address import (get_address_display, get_default_address, get_company_address) from frappe.contacts.doctype.contact.contact import get_contact_details, get_default_contact @@ -16,7 +16,7 @@ from erpnext.exceptions import PartyFrozen, PartyDisabled, InvalidAccountCurrenc from erpnext.accounts.utils import get_fiscal_year from erpnext import get_default_currency, get_company_currency -from six import iteritems +from six import iteritems, string_types class DuplicatePartyAccountError(frappe.ValidationError): pass @@ -44,14 +44,16 @@ def _get_party_details(party=None, account=None, party_type="Customer", company= party = frappe.get_doc(party_type, party) currency = party.default_currency if party.default_currency else get_company_currency(company) - out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out.customer_group, out.supplier_group) - out["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company) - set_address_details(out, party, party_type, doctype, company, party_address, shipping_address) + party_address, shipping_address = set_address_details(out, party, party_type, doctype, company, party_address, shipping_address) set_contact_details(out, party, party_type) set_other_values(out, party, party_type) set_price_list(out, party, party_type, price_list) - out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out.customer_group, out.supplier_type) + out["tax_category"] = get_address_tax_category(party.get("tax_category"), + party_address, shipping_address if party_type != "Supplier" else party_address) + out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, + customer_group=out.customer_group, supplier_group=out.supplier_group, tax_category=out.tax_category, + billing_address=party_address, shipping_address=shipping_address) if fetch_payment_terms_template: out["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company) @@ -101,6 +103,8 @@ def set_address_details(out, party, party_type, doctype=None, company=None, part out.update(get_fetch_values(doctype, 'shipping_address', out.shipping_address)) get_regional_address_details(out, doctype, company) + return out.get(billing_address_field), out.shipping_address_name + @erpnext.allow_regional def get_regional_address_details(out, doctype, company): pass @@ -351,7 +355,19 @@ def validate_due_date(posting_date, due_date, party_type, party, company=None, b .format(formatdate(default_due_date))) @frappe.whitelist() -def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_group=None, +def get_address_tax_category(tax_category, billing_address=None, shipping_address=None): + addr_tax_category_from = frappe.db.get_single_value("Accounts Settings", "determine_address_tax_category_from") + if addr_tax_category_from == "Shipping Address": + if shipping_address: + tax_category = frappe.db.get_value("Address", shipping_address, "tax_category") or tax_category + else: + if billing_address: + tax_category = frappe.db.get_value("Address", billing_address, "tax_category") or tax_category + + return cstr(tax_category) + +@frappe.whitelist() +def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_group=None, tax_category=None, billing_address=None, shipping_address=None, use_for_shopping_cart=None): from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details args = { @@ -359,6 +375,9 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup "company": company } + if tax_category: + args['tax_category'] = tax_category + if customer_group: args['customer_group'] = customer_group diff --git a/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py b/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py index 1ec0abc3bf1..13424dbcb56 100644 --- a/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py +++ b/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py @@ -35,16 +35,22 @@ def get_conditions(filters): def get_entries(filters): conditions = get_conditions(filters) - journal_entries = frappe.db.sql("""select "Journal Entry", jv.name, jv.posting_date, - jv.cheque_no, jv.clearance_date, jvd.against_account, (jvd.debit - jvd.credit) - from `tabJournal Entry Account` jvd, `tabJournal Entry` jv - where jvd.parent = jv.name and jv.docstatus=1 and jvd.account = %(account)s {0} - order by posting_date DESC, jv.name DESC""".format(conditions), filters, as_list=1) + journal_entries = frappe.db.sql("""SELECT + "Journal Entry", jv.name, jv.posting_date, jv.cheque_no, jv.clearance_date, jvd.against_account, + if((jvd.debit - jvd.credit) < 0, (jvd.debit - jvd.credit) * -1, (jvd.debit - jvd.credit)) + FROM + `tabJournal Entry Account` jvd, `tabJournal Entry` jv + WHERE + jvd.parent = jv.name and jv.docstatus=1 and jvd.account = %(account)s {0} + order by posting_date DESC, jv.name DESC""".format(conditions), filters, as_list=1) - payment_entries = frappe.db.sql("""select "Payment Entry", name, posting_date, - reference_no, clearance_date, party, if(paid_from=%(account)s, paid_amount, received_amount) - from `tabPayment Entry` - where docstatus=1 and (paid_from = %(account)s or paid_to = %(account)s) {0} - order by posting_date DESC, name DESC""".format(conditions), filters, as_list=1) + payment_entries = frappe.db.sql("""SELECT + "Payment Entry", name, posting_date, reference_no, clearance_date, party, + if(paid_from=%(account)s, paid_amount, received_amount) + FROM + `tabPayment Entry` + WHERE + docstatus=1 and (paid_from = %(account)s or paid_to = %(account)s) {0} + order by posting_date DESC, name DESC""".format(conditions), filters, as_list=1) return sorted(journal_entries + payment_entries, key=lambda k: k[2] or getdate(nowdate())) \ No newline at end of file diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index d855873d5ad..65629d28181 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -9,6 +9,7 @@ from frappe.utils import cstr, nowdate, getdate, flt, get_last_day, add_days, ad from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset from erpnext.assets.doctype.asset.asset import make_sales_invoice, make_purchase_invoice from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice as make_invoice class TestAsset(unittest.TestCase): def setUp(self): @@ -494,6 +495,15 @@ class TestAsset(unittest.TestCase): self.assertEqual(gle, expected_gle) + def test_expense_head(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=2, rate=200000.0, location="Test Location") + + doc = make_invoice(pr.name) + + self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account) + + def create_asset_data(): if not frappe.db.exists("Asset Category", "Computers"): create_asset_category() diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index 8c586d14669..5e5110d969f 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -1914,8 +1914,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "description": "", - "fieldname": "taxes_and_charges", + "fieldname": "tax_category", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -1924,13 +1923,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Taxes and Charges", + "label": "Tax Category", "length": 0, "no_copy": 0, - "oldfieldname": "purchase_other_charges", - "oldfieldtype": "Link", - "options": "Purchase Taxes and Charges Template", + "options": "Tax Category", "permlevel": 0, + "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, @@ -2037,6 +2035,41 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "", + "fieldname": "taxes_and_charges", + "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": "Purchase Taxes and Charges Template", + "length": 0, + "no_copy": 0, + "oldfieldname": "purchase_other_charges", + "oldfieldtype": "Link", + "options": "Purchase Taxes and Charges Template", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2881,6 +2914,7 @@ "label": "Rounded Total", "length": 0, "no_copy": 0, + "options": "currency", "permlevel": 0, "precision": "", "print_hide": 0, @@ -3831,7 +3865,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-01-07 16:51:56.739693", + "modified": "2018-12-27 02:04:14.410491", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", @@ -3926,4 +3960,4 @@ "track_changes": 0, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json old mode 100755 new mode 100644 index 3d981c56da7..9b26085cbde --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -2236,6 +2236,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_tax_template", + "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": "Item Tax Template", + "length": 0, + "no_copy": 0, + "options": "Item Tax Template", + "permlevel": 0, + "precision": "", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2344,7 +2377,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-01-07 16:51:57.546323", + "modified": "2018-11-23 16:53:57.220731", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item", @@ -2359,4 +2392,4 @@ "track_changes": 1, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index 3b1f4e0dfcc..d6c6f8842c5 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -181,6 +181,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "tax_category", + "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": "Tax Category", + "length": 0, + "no_copy": 0, + "options": "Tax Category", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1463,7 +1496,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-01-07 16:52:04.660271", + "modified": "2018-11-23 16:15:44.497406", "modified_by": "Administrator", "module": "Buying", "name": "Supplier", @@ -1614,4 +1647,4 @@ "track_changes": 1, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json index 5738433a312..049dc9fcb39 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json @@ -1198,8 +1198,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "description": "", - "fieldname": "taxes_and_charges", + "fieldname": "tax_category", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -1208,13 +1207,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Taxes and Charges", + "label": "Tax Category", "length": 0, - "no_copy": 1, - "oldfieldname": "purchase_other_charges", - "oldfieldtype": "Link", - "options": "Purchase Taxes and Charges Template", + "no_copy": 0, + "options": "Tax Category", "permlevel": 0, + "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, @@ -1321,6 +1319,41 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "", + "fieldname": "taxes_and_charges", + "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": "Purchase Taxes and Charges Template", + "length": 0, + "no_copy": 1, + "oldfieldname": "purchase_other_charges", + "oldfieldtype": "Link", + "options": "Purchase Taxes and Charges Template", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2845,7 +2878,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2019-01-07 16:52:01.505553", + "modified": "2018-12-27 02:08:16.421501", "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation", @@ -2959,4 +2992,4 @@ "track_changes": 0, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json index 94d93f6a61f..7ef3e40e0b3 100644 --- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json +++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json @@ -1543,6 +1543,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_tax_template", + "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": "Item Tax Template", + "length": 0, + "no_copy": 0, + "options": "Item Tax Template", + "permlevel": 0, + "precision": "", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1786,7 +1819,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-01-07 16:52:02.125715", + "modified": "2018-11-23 17:34:54.977366", "modified_by": "Administrator", "module": "Buying", "name": "Supplier Quotation Item", @@ -1801,4 +1834,4 @@ "track_changes": 1, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py index 95ce1ebe3f0..c8b7eff3355 100644 --- a/erpnext/config/accounts.py +++ b/erpnext/config/accounts.py @@ -163,6 +163,11 @@ def get_data(): { "label": _("Taxes"), "items": [ + { + "type": "doctype", + "name": "Tax Category", + "description": _("Tax Category for overriding tax rates.") + }, { "type": "doctype", "name": "Sales Taxes and Charges Template", @@ -173,6 +178,11 @@ def get_data(): "name": "Purchase Taxes and Charges Template", "description": _("Tax template for buying transactions.") }, + { + "type": "doctype", + "name": "Item Tax Template", + "description": _("Tax template for item tax rates.") + }, { "type": "doctype", "name": "Tax Rule", diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index e402a1f01a4..3a5c7f93923 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -16,7 +16,7 @@ from erpnext.accounts.party import get_party_account_currency, validate_party_fr from erpnext.exceptions import InvalidCurrency from six import text_type -force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset") +force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset", "item_tax_rate") class AccountsController(TransactionBase): @@ -605,13 +605,14 @@ class AccountsController(TransactionBase): advance.account_currency) if advance.account_currency == self.currency: - order_total = self.grand_total - formatted_order_total = fmt_money(order_total, precision=self.precision("grand_total"), - currency=advance.account_currency) + order_total = self.get("rounded_total") or self.grand_total + precision = "rounded_total" if self.get("rounded_total") else "grand_total" else: - order_total = self.base_grand_total - formatted_order_total = fmt_money(order_total, precision=self.precision("base_grand_total"), - currency=advance.account_currency) + order_total = self.get("base_rounded_total") or self.base_grand_total + precision = "base_rounded_total" if self.get("base_rounded_total") else "base_grand_total" + + formatted_order_total = fmt_money(order_total, precision=self.precision(precision), + currency=advance.account_currency) if self.currency == self.company_currency and advance_paid > order_total: frappe.throw(_("Total advance ({0}) against Order {1} cannot be greater than the Grand Total ({2})") diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index f35eb5919e9..02262012f1c 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -54,6 +54,9 @@ class EmployeeBoardingController(Document): where parenttype='User' and role=%s''', activity.role) users = users + user_list + if "Administrator" in users: + users.remove("Administrator") + # assign the task the users if users: self.assign_task_to_users(task, set(users)) diff --git a/erpnext/patches.txt b/erpnext/patches.txt old mode 100755 new mode 100644 index 1da7eba491a..d3d0d05ea2b --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -580,6 +580,8 @@ erpnext.patches.v11_0.update_delivery_trip_status erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items erpnext.patches.v11_0.set_missing_gst_hsn_code erpnext.patches.v11_0.rename_bom_wo_fields +erpnext.patches.v11_0.move_item_tax_to_item_tax_template +erpnext.patches.v11_0.rename_additional_salary_component_additional_salary erpnext.patches.v12_0.rename_learn_to_help erpnext.patches.v12_0.rename_accounts_desktop_icon_to_accounting erpnext.patches.v12_0.replace_project_list_desktop_icon_with_projects_module_desktop_icon diff --git a/erpnext/patches/v11_0/move_item_tax_to_item_tax_template.py b/erpnext/patches/v11_0/move_item_tax_to_item_tax_template.py new file mode 100644 index 00000000000..8de7009206b --- /dev/null +++ b/erpnext/patches/v11_0/move_item_tax_to_item_tax_template.py @@ -0,0 +1,80 @@ +import frappe +import json +from six import iteritems + +old_item_taxes = {} +item_tax_templates = {} +rename_template_to_untitled = [] + +def execute(): + for d in frappe.db.sql("""select parent as item_code, tax_type, tax_rate from `tabItem Tax`""", as_dict=1): + old_item_taxes.setdefault(d.item_code, []) + old_item_taxes[d.item_code].append(d) + + frappe.reload_doc("accounts", "doctype", "item_tax_template_detail") + frappe.reload_doc("accounts", "doctype", "item_tax_template") + frappe.reload_doc("stock", "doctype", "item") + frappe.reload_doc("stock", "doctype", "item_tax") + frappe.reload_doc("selling", "doctype", "quotation_item") + frappe.reload_doc("selling", "doctype", "sales_order_item") + frappe.reload_doc("stock", "doctype", "delivery_note_item") + frappe.reload_doc("accounts", "doctype", "sales_invoice_item") + frappe.reload_doc("buying", "doctype", "supplier_quotation_item") + frappe.reload_doc("buying", "doctype", "purchase_order_item") + frappe.reload_doc("stock", "doctype", "purchase_receipt_item") + frappe.reload_doc("accounts", "doctype", "purchase_invoice_item") + frappe.reload_doc("accounts", "doctype", "accounts_settings") + + # for each item that have item tax rates + for item_code in old_item_taxes.keys(): + # make current item's tax map + item_tax_map = {} + for d in old_item_taxes[item_code]: + item_tax_map[d.tax_type] = d.tax_rate + + item_tax_template_name = get_item_tax_template(item_tax_map, item_code) + + # update the item tax table + item = frappe.get_doc("Item", item_code) + item.set("taxes", []) + item.append("taxes", {"item_tax_template": item_tax_template_name, "tax_category": ""}) + item.save() + + doctypes = [ + 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice', + 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice' + ] + for dt in doctypes: + for d in frappe.db.sql("""select name, parent, item_code, item_tax_rate from `tab{0} Item` + where ifnull(item_tax_rate, '') not in ('', '{{}}')""".format(dt), as_dict=1): + item_tax_map = json.loads(d.item_tax_rate) + item_tax_template = get_item_tax_template(item_tax_map, d.item_code, d.parent) + frappe.db.set_value(dt + " Item", d.name, "item_tax_template", item_tax_template) + + idx = 1 + for oldname in rename_template_to_untitled: + frappe.rename_doc("Item Tax Template", oldname, "Untitled {}".format(idx)) + idx += 1 + + settings = frappe.get_single("Accounts Settings") + settings.add_taxes_from_item_tax_template = 0 + settings.determine_address_tax_category_from = "Billing Address" + settings.save() + +def get_item_tax_template(item_tax_map, item_code, parent=None): + # search for previously created item tax template by comparing tax maps + for template, item_tax_template_map in iteritems(item_tax_templates): + if item_tax_map == item_tax_template_map: + if not parent: + rename_template_to_untitled.append(template) + return template + + # if no item tax template found, create one + item_tax_template = frappe.new_doc("Item Tax Template") + item_tax_template.title = "{}--{}".format(parent, item_code) if parent else "Item-{}".format(item_code) + for tax_type, tax_rate in iteritems(item_tax_map): + item_tax_template.append("taxes", {"tax_type": tax_type, "tax_rate": tax_rate}) + item_tax_templates.setdefault(item_tax_template.title, {}) + item_tax_templates[item_tax_template.title][tax_type] = tax_rate + item_tax_template.save() + return item_tax_template.name diff --git a/erpnext/patches/v11_0/rename_additional_salary_component_additional_salary.py b/erpnext/patches/v11_0/rename_additional_salary_component_additional_salary.py new file mode 100644 index 00000000000..8fa876dd743 --- /dev/null +++ b/erpnext/patches/v11_0/rename_additional_salary_component_additional_salary.py @@ -0,0 +1,10 @@ +import frappe + +# this patch should have been included with this PR https://github.com/frappe/erpnext/pull/14302 + +def execute(): + if frappe.db.table_exists("Additional Salary Component"): + if not frappe.db.table_exists("Additional Salary"): + frappe.rename_doc("DocType", "Additional Salary Component", "Additional Salary") + + frappe.delete_doc('DocType', "Additional Salary Component") diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js index 4ea44155091..1449e4f5eb3 100644 --- a/erpnext/public/js/controllers/buying.js +++ b/erpnext/public/js/controllers/buying.js @@ -112,6 +112,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ supplier_address: function() { erpnext.utils.get_address_display(this.frm); + erpnext.utils.set_taxes_from_address(this.frm, "supplier_address", "supplier_address", "supplier_address"); }, buying_price_list: function() { diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 035c58d6d2a..f409f617f37 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -441,13 +441,19 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ weight_uom: item.weight_uom, uom : item.uom, pos_profile: me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : '', - cost_center: item.cost_center + cost_center: item.cost_center, + tax_category: me.frm.doc.tax_category, + item_tax_template: item.item_tax_template } }, callback: function(r) { if(!r.exc) { frappe.run_serially([ + () => { + var d = locals[cdt][cdn]; + me.add_taxes_from_item_tax_template(d.item_tax_rate); + }, () => me.frm.script_manager.trigger("price_list_rate", cdt, cdn), () => me.toggle_conversion_factor(item), () => { @@ -471,6 +477,26 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, + add_taxes_from_item_tax_template: function(item_tax_map) { + let me = this; + + if(item_tax_map && cint(frappe.defaults.get_default("add_taxes_from_item_tax_template"))) { + if(typeof (item_tax_map) == "string") { + item_tax_map = JSON.parse(item_tax_map); + } + + $.each(item_tax_map, function(tax, rate) { + let found = (me.frm.doc.taxes || []).find(d => d.account_head === tax); + if(!found) { + let child = frappe.model.add_child(me.frm.doc, "taxes"); + child.charge_type = "On Net Total"; + child.account_head = tax; + child.rate = 0; + } + }); + } + }, + serial_no: function(doc, cdt, cdn) { var me = this; var item = frappe.get_doc(cdt, cdn); @@ -539,6 +565,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ frappe.run_serially([ () => me.frm.script_manager.trigger("currency"), + () => me.update_item_tax_map(), () => me.apply_default_taxes(), () => me.apply_pricing_rule() ]); @@ -1282,6 +1309,80 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, + tax_category: function() { + var me = this; + if(me.frm.updating_party_details) return; + + frappe.run_serially([ + () => this.update_item_tax_map(), + () => erpnext.utils.set_taxes(this.frm, "tax_category"), + ]); + }, + + item_tax_template: function(doc, cdt, cdn) { + var me = this; + if(me.frm.updating_party_details) return; + + var item = frappe.get_doc(cdt, cdn); + + if(item.item_tax_template) { + return this.frm.call({ + method: "erpnext.stock.get_item_details.get_item_tax_map", + args: { + company: me.frm.doc.company, + item_tax_template: item.item_tax_template, + as_json: true + }, + callback: function(r) { + if(!r.exc) { + item.item_tax_rate = r.message; + me.add_taxes_from_item_tax_template(item.item_tax_rate); + me.calculate_taxes_and_totals(); + } + } + }); + } else { + item.item_tax_rate = "{}"; + me.calculate_taxes_and_totals(); + } + }, + + update_item_tax_map: function() { + var me = this; + var item_codes = []; + $.each(this.frm.doc.items || [], function(i, item) { + if(item.item_code) { + item_codes.push(item.item_code); + } + }); + + if(item_codes.length) { + return this.frm.call({ + method: "erpnext.stock.get_item_details.get_item_tax_info", + args: { + company: me.frm.doc.company, + tax_category: cstr(me.frm.doc.tax_category), + item_codes: item_codes + }, + callback: function(r) { + if(!r.exc) { + $.each(me.frm.doc.items || [], function(i, item) { + if(item.item_code && r.message.hasOwnProperty(item.item_code)) { + item.item_tax_template = r.message[item.item_code].item_tax_template; + item.item_tax_rate = r.message[item.item_code].item_tax_rate; + me.add_taxes_from_item_tax_template(item.item_tax_rate); + } else { + item.item_tax_template = ""; + item.item_tax_rate = "{}"; + } + }); + me.calculate_taxes_and_totals(); + } + } + }); + } + }, + is_recurring: function() { // set default values for recurring documents if(this.frm.doc.is_recurring && this.frm.doc.__islocal) { diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js index eab04006c21..44f9f24a912 100644 --- a/erpnext/public/js/utils/party.js +++ b/erpnext/public/js/utils/party.js @@ -92,7 +92,6 @@ erpnext.utils.get_address_display = function(frm, address_field, display_field, if(r.message) { frm.set_value(display_field, r.message) } - erpnext.utils.set_taxes(frm, address_field, display_field, is_your_company_address); } }) } else { @@ -100,15 +99,51 @@ erpnext.utils.get_address_display = function(frm, address_field, display_field, } }; -erpnext.utils.set_taxes = function(frm, address_field, display_field, is_your_company_address) { - if(frappe.meta.get_docfield(frm.doc.doctype, "taxes") && !is_your_company_address) { +erpnext.utils.set_taxes_from_address = function(frm, triggered_from_field, billing_address_field, shipping_address_field) { + if(frm.updating_party_details) return; + + if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) { if(!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier", - frm.doc.customer || frm.doc.supplier || frm.doc.lead, address_field)) { + frm.doc.customer || frm.doc.supplier || frm.doc.lead, triggered_from_field)) { return; } if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date", - frm.doc.posting_date || frm.doc.transaction_date, address_field)) { + frm.doc.posting_date || frm.doc.transaction_date, triggered_from_field)) { + return; + } + } else { + return; + } + + frappe.call({ + method: "erpnext.accounts.party.get_address_tax_category", + args: { + "tax_category": frm.doc.tax_category, + "billing_address": frm.doc[billing_address_field], + "shipping_address": frm.doc[shipping_address_field] + }, + callback: function(r) { + if(!r.exc){ + if(frm.doc.tax_category != r.message) { + frm.set_value("tax_category", r.message); + } else { + erpnext.utils.set_taxes(frm, triggered_from_field); + } + } + } + }); +}; + +erpnext.utils.set_taxes = function(frm, triggered_from_field) { + if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) { + if(!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier", + frm.doc.customer || frm.doc.supplier || frm.doc.lead, triggered_from_field)) { + return; + } + + if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date", + frm.doc.posting_date || frm.doc.transaction_date, triggered_from_field)) { return; } } else { @@ -134,6 +169,9 @@ erpnext.utils.set_taxes = function(frm, address_field, display_field, is_your_co "party_type": party_type, "posting_date": frm.doc.posting_date || frm.doc.transaction_date, "company": frm.doc.company, + "customer_group": frm.doc.customer_group, + "supplier_group": frm.doc.supplier_group, + "tax_category": frm.doc.tax_category, "billing_address": ((frm.doc.customer || frm.doc.lead) ? (frm.doc.customer_address) : (frm.doc.supplier_address)), "shipping_address": frm.doc.shipping_address_name }, @@ -143,7 +181,7 @@ erpnext.utils.set_taxes = function(frm, address_field, display_field, is_your_co } } }); -} +}; erpnext.utils.get_contact_details = function(frm) { if(frm.updating_party_details) return; diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index 608c0e950ed..362db61d91c 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -416,6 +416,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "tax_category", + "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": "Tax Category", + "length": 0, + "no_copy": 0, + "options": "Tax Category", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1873,7 +1906,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-10-01 10:07:34.510264", + "modified": "2018-11-23 16:14:43.710167", "modified_by": "Administrator", "module": "Selling", "name": "Customer", diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json index 08c9b80c2e9..0b602221657 100644 --- a/erpnext/selling/doctype/quotation/quotation.json +++ b/erpnext/selling/doctype/quotation/quotation.json @@ -1478,7 +1478,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "taxes_and_charges", + "fieldname": "tax_category", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -1487,13 +1487,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Taxes and Charges", + "label": "Tax Category", "length": 0, "no_copy": 0, - "oldfieldname": "charge", - "oldfieldtype": "Link", - "options": "Sales Taxes and Charges Template", + "options": "Tax Category", "permlevel": 0, + "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, @@ -1598,6 +1597,40 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "taxes_and_charges", + "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": "Sales Taxes and Charges Template", + "length": 0, + "no_copy": 0, + "oldfieldname": "charge", + "oldfieldtype": "Link", + "options": "Sales Taxes and Charges Template", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -3198,7 +3231,7 @@ "istable": 0, "max_attachments": 1, "menu_index": 0, - "modified": "2019-01-07 16:51:55.604845", + "modified": "2018-12-27 02:07:50.702241", "modified_by": "Administrator", "module": "Selling", "name": "Quotation", @@ -3373,4 +3406,4 @@ "track_changes": 0, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json index 3a8b0df5c59..b21360fdf0b 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.json +++ b/erpnext/selling/doctype/quotation_item/quotation_item.json @@ -1798,6 +1798,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_tax_template", + "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": "Item Tax Template", + "length": 0, + "no_copy": 0, + "options": "Item Tax Template", + "permlevel": 0, + "precision": "", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1914,7 +1947,7 @@ "istable": 1, "max_attachments": 0, "menu_index": 0, - "modified": "2019-01-07 16:51:56.248107", + "modified": "2018-11-23 17:32:30.302066", "modified_by": "Administrator", "module": "Selling", "name": "Quotation Item", @@ -1929,4 +1962,4 @@ "track_changes": 1, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index aa29f3a264c..480bd918b9f 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -1662,7 +1662,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "taxes_and_charges", + "fieldname": "tax_category", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -1671,13 +1671,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Taxes and Charges", + "label": "Tax Category", "length": 0, "no_copy": 0, - "oldfieldname": "charge", - "oldfieldtype": "Link", - "options": "Sales Taxes and Charges Template", + "options": "Tax Category", "permlevel": 0, + "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, @@ -1782,6 +1781,40 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "taxes_and_charges", + "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": "Sales Taxes and Charges Template", + "length": 0, + "no_copy": 0, + "oldfieldname": "charge", + "oldfieldtype": "Link", + "options": "Sales Taxes and Charges Template", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -4015,7 +4048,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-01-07 16:51:50.857438", + "modified": "2018-12-27 02:01:13.780828", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order", @@ -4148,4 +4181,4 @@ "track_changes": 1, "track_seen": 1, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json index 19065dfa375..f56ebfcf719 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -2032,39 +2032,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "page_break", - "fieldtype": "Check", - "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": "Page Break", - "length": 0, - "no_copy": 0, - "oldfieldname": "page_break", - "oldfieldtype": "Check", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2326,6 +2293,103 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_tax_template", + "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": "Item Tax Template", + "length": 0, + "no_copy": 0, + "options": "Item Tax Template", + "permlevel": 0, + "precision": "", + "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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "col_break5", + "fieldtype": "Column Break", + "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, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "page_break", + "fieldtype": "Check", + "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": "Page Break", + "length": 0, + "no_copy": 0, + "oldfieldname": "page_break", + "oldfieldtype": "Check", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 1, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2477,7 +2541,7 @@ "istable": 1, "max_attachments": 0, "menu_index": 0, - "modified": "2019-01-07 16:51:51.852343", + "modified": "2018-11-23 17:20:53.728337", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order Item", @@ -2492,4 +2556,4 @@ "track_changes": 1, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index b839d8176ba..a246822cd60 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -103,10 +103,12 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ customer_address: function() { erpnext.utils.get_address_display(this.frm, "customer_address"); + erpnext.utils.set_taxes_from_address(this.frm, "customer_address", "customer_address", "shipping_address_name"); }, shipping_address_name: function() { erpnext.utils.get_address_display(this.frm, "shipping_address_name", "shipping_address"); + erpnext.utils.set_taxes_from_address(this.frm, "shipping_address_name", "customer_address", "shipping_address_name"); }, sales_partner: function() { diff --git a/erpnext/setup/doctype/item_group/item_group.json b/erpnext/setup/doctype/item_group/item_group.json index c9cbc9d1cba..656d460e0f5 100644 --- a/erpnext/setup/doctype/item_group/item_group.json +++ b/erpnext/setup/doctype/item_group/item_group.json @@ -275,6 +275,72 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": "", + "columns": 0, + "fieldname": "sec_break_taxes", + "fieldtype": "Section Break", + "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": "Item Tax", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "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, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "taxes", + "fieldtype": "Table", + "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": "Taxes", + "length": 0, + "no_copy": 0, + "options": "Item Tax", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -617,7 +683,7 @@ "issingle": 0, "istable": 0, "max_attachments": 3, - "modified": "2019-01-07 16:52:06.106336", + "modified": "2018-11-23 15:17:28.003933", "modified_by": "Administrator", "module": "Setup", "name": "Item Group", @@ -748,4 +814,4 @@ "track_changes": 0, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/setup/doctype/item_group/test_records.json b/erpnext/setup/doctype/item_group/test_records.json index 436535eef01..71159643209 100644 --- a/erpnext/setup/doctype/item_group/test_records.json +++ b/erpnext/setup/doctype/item_group/test_records.json @@ -69,5 +69,39 @@ "is_group": 1, "item_group_name": "_Test Item Group D", "parent_item_group": "All Item Groups" + }, + { + "doctype": "Item Group", + "is_group": 1, + "item_group_name": "_Test Item Group Tax Parent", + "parent_item_group": "All Item Groups", + "taxes": [ + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 10", + "tax_category": "" + }, + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 12", + "tax_category": "_Test Tax Category 1" + } + ] + }, + { + "doctype": "Item Group", + "is_group": 0, + "item_group_name": "_Test Item Group Tax Child Override", + "parent_item_group": "_Test Item Group Tax Parent", + "taxes": [ + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 15", + "tax_category": "" + } + ] } ] \ No newline at end of file diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index 254d7b74af3..dc3700769a5 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -303,9 +303,10 @@ def set_taxes(quotation, cart_settings): customer_group = frappe.db.get_value("Customer", quotation.customer, "customer_group") - quotation.taxes_and_charges = set_taxes(quotation.customer, "Customer", \ - quotation.transaction_date, quotation.company, customer_group, None, \ - quotation.customer_address, quotation.shipping_address_name, 1) + quotation.taxes_and_charges = set_taxes(quotation.customer, "Customer", + quotation.transaction_date, quotation.company, customer_group=customer_group, supplier_group=None, + tax_category=quotation.tax_category, billing_address=quotation.customer_address, + shipping_address=quotation.shipping_address_name, use_for_shopping_cart=1) # # # clear table quotation.set("taxes", []) diff --git a/erpnext/shopping_cart/test_shopping_cart.py b/erpnext/shopping_cart/test_shopping_cart.py index 7d6b41ef5fc..daad799246a 100644 --- a/erpnext/shopping_cart/test_shopping_cart.py +++ b/erpnext/shopping_cart/test_shopping_cart.py @@ -107,9 +107,10 @@ class TestShoppingCart(unittest.TestCase): from erpnext.accounts.party import set_taxes - tax_rule_master = set_taxes(quotation.customer, "Customer", \ - quotation.transaction_date, quotation.company, None, None, \ - quotation.customer_address, quotation.shipping_address_name, 1) + tax_rule_master = set_taxes(quotation.customer, "Customer", + quotation.transaction_date, quotation.company, customer_group=None, supplier_group=None, + tax_category=quotation.tax_category, billing_address=quotation.customer_address, + shipping_address=quotation.shipping_address_name, use_for_shopping_cart=1) self.assertEqual(quotation.taxes_and_charges, tax_rule_master) self.assertEqual(quotation.total_taxes_and_charges, 1000.0) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json index 4e08a7a59f7..9f7de648c41 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.json +++ b/erpnext/stock/doctype/delivery_note/delivery_note.json @@ -1961,8 +1961,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "description": "If you have created a standard template in Sales Taxes and Charges Template, select one and click on the button below.", - "fieldname": "taxes_and_charges", + "fieldname": "tax_category", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -1971,13 +1970,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Taxes and Charges", + "label": "Tax Category", "length": 0, "no_copy": 0, - "oldfieldname": "charge", - "oldfieldtype": "Link", - "options": "Sales Taxes and Charges Template", + "options": "Tax Category", "permlevel": 0, + "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, @@ -2082,6 +2080,41 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "If you have created a standard template in Sales Taxes and Charges Template, select one and click on the button below.", + "fieldname": "taxes_and_charges", + "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": "Sales Taxes and Charges Template", + "length": 0, + "no_copy": 0, + "oldfieldname": "charge", + "oldfieldtype": "Link", + "options": "Sales Taxes and Charges Template", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -4296,7 +4329,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2019-01-07 16:51:52.357859", + "modified": "2018-12-27 01:53:41.645566", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note", @@ -4410,4 +4443,4 @@ "track_changes": 1, "track_seen": 1, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json index 9fe741a11e2..a47ec4cf46d 100644 --- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json +++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -2001,6 +2001,39 @@ "unique": 0, "width": "120px" }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_tax_template", + "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": "Item Tax Template", + "length": 0, + "no_copy": 0, + "options": "Item Tax Template", + "permlevel": 0, + "precision": "", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2310,7 +2343,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-01-07 16:51:53.322875", + "modified": "2018-11-23 17:20:07.347814", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note Item", @@ -2325,4 +2358,4 @@ "track_changes": 0, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 7b5e5545c51..9e7d9a1fe55 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -3114,6 +3114,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 1, + "collapsible_depends_on": "taxes", "columns": 0, "fieldname": "item_tax_section_break", "fieldtype": "Section Break", @@ -4180,7 +4181,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2019-01-10 04:14:34.497557", + "modified": "2018-11-23 01:48:29.347662", "modified_by": "Administrator", "module": "Stock", "name": "Item", @@ -4350,4 +4351,4 @@ "track_changes": 1, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index f7cdcf091b3..a0d94bffbf7 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -450,7 +450,7 @@ class Item(WebsiteGenerator): # add item taxes from template for d in template.get("taxes"): - self.append("taxes", {"tax_type": d.tax_type, "tax_rate": d.tax_rate}) + self.append("taxes", {"item_tax_template": d.item_tax_template}) # copy re-order table if empty if not self.get("reorder_levels"): @@ -499,17 +499,11 @@ class Item(WebsiteGenerator): """Check whether Tax Rate is not entered twice for same Tax Type""" check_list = [] for d in self.get('taxes'): - if d.tax_type: - account_type = frappe.db.get_value("Account", d.tax_type, "account_type") - - if account_type not in ['Tax', 'Chargeable', 'Income Account', 'Expense Account']: - frappe.throw( - _("Item Tax Row {0} must have account of type Tax or Income or Expense or Chargeable").format(d.idx)) + if d.item_tax_template: + if d.item_tax_template in check_list: + frappe.throw(_("{0} entered twice in Item Tax").format(d.item_tax_template)) else: - if d.tax_type in check_list: - frappe.throw(_("{0} entered twice in Item Tax").format(d.tax_type)) - else: - check_list.append(d.tax_type) + check_list.append(d.item_tax_template) def validate_barcode(self): from stdnum import ean diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 4b1bf90d4f6..2ab5bb3932b 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import unittest import frappe +import json from frappe.test_runner import make_test_objects from erpnext.controllers.item_variant import (create_variant, ItemVariantExistsError, @@ -17,7 +18,7 @@ from erpnext.stock.get_item_details import get_item_details from six import iteritems test_ignore = ["BOM"] -test_dependencies = ["Warehouse", "Item Group"] +test_dependencies = ["Warehouse", "Item Group", "Item Tax Template"] def make_item(item_code, properties=None): if frappe.db.exists("Item", item_code): @@ -76,7 +77,6 @@ class TestItem(unittest.TestCase): "amount": 0.0, "base_amount": 0.0, "batch_no": None, - "item_tax_rate": '{}', "uom": "_Test UOM", "conversion_factor": 1.0, } @@ -102,6 +102,68 @@ class TestItem(unittest.TestCase): for key, value in iteritems(to_check): self.assertEqual(value, details.get(key)) + def test_item_tax_template(self): + expected_item_tax_template = [ + {"item_code": "_Test Item With Item Tax Template", "tax_category": "", + "item_tax_template": "_Test Account Excise Duty @ 10"}, + {"item_code": "_Test Item With Item Tax Template", "tax_category": "_Test Tax Category 1", + "item_tax_template": "_Test Account Excise Duty @ 12"}, + {"item_code": "_Test Item With Item Tax Template", "tax_category": "_Test Tax Category 2", + "item_tax_template": None}, + + {"item_code": "_Test Item Inherit Group Item Tax Template 1", "tax_category": "", + "item_tax_template": "_Test Account Excise Duty @ 10"}, + {"item_code": "_Test Item Inherit Group Item Tax Template 1", "tax_category": "_Test Tax Category 1", + "item_tax_template": "_Test Account Excise Duty @ 12"}, + {"item_code": "_Test Item Inherit Group Item Tax Template 1", "tax_category": "_Test Tax Category 2", + "item_tax_template": None}, + + {"item_code": "_Test Item Inherit Group Item Tax Template 2", "tax_category": "", + "item_tax_template": "_Test Account Excise Duty @ 15"}, + {"item_code": "_Test Item Inherit Group Item Tax Template 2", "tax_category": "_Test Tax Category 1", + "item_tax_template": "_Test Account Excise Duty @ 12"}, + {"item_code": "_Test Item Inherit Group Item Tax Template 2", "tax_category": "_Test Tax Category 2", + "item_tax_template": None}, + + {"item_code": "_Test Item Override Group Item Tax Template", "tax_category": "", + "item_tax_template": "_Test Account Excise Duty @ 20"}, + {"item_code": "_Test Item Override Group Item Tax Template", "tax_category": "_Test Tax Category 1", + "item_tax_template": "_Test Item Tax Template 1"}, + {"item_code": "_Test Item Override Group Item Tax Template", "tax_category": "_Test Tax Category 2", + "item_tax_template": None}, + ] + + expected_item_tax_map = { + None: {}, + "_Test Account Excise Duty @ 10": {"_Test Account Excise Duty - _TC": 10}, + "_Test Account Excise Duty @ 12": {"_Test Account Excise Duty - _TC": 12}, + "_Test Account Excise Duty @ 15": {"_Test Account Excise Duty - _TC": 15}, + "_Test Account Excise Duty @ 20": {"_Test Account Excise Duty - _TC": 20}, + "_Test Item Tax Template 1": {"_Test Account Excise Duty - _TC": 5, "_Test Account Education Cess - _TC": 10, + "_Test Account S&H Education Cess - _TC": 15} + } + + for data in expected_item_tax_template: + details = get_item_details({ + "item_code": data['item_code'], + "tax_category": data['tax_category'], + "company": "_Test Company", + "price_list": "_Test Price List", + "currency": "_Test Currency", + "doctype": "Sales Order", + "conversion_rate": 1, + "price_list_currency": "_Test Currency", + "plc_conversion_rate": 1, + "order_type": "Sales", + "customer": "_Test Customer", + "conversion_factor": 1, + "price_list_uom_dependant": 1, + "ignore_pricing_rule": 1 + }) + + self.assertEqual(details.item_tax_template, data['item_tax_template']) + self.assertEqual(json.loads(details.item_tax_rate), expected_item_tax_map[details.item_tax_template]) + def test_item_attribute_change_after_variant(self): frappe.delete_doc_if_exists("Item", "_Test Variant Item-L", force=1) diff --git a/erpnext/stock/doctype/item/test_records.json b/erpnext/stock/doctype/item/test_records.json index 18e2910126d..b09a3c0866c 100644 --- a/erpnext/stock/doctype/item/test_records.json +++ b/erpnext/stock/doctype/item/test_records.json @@ -92,8 +92,8 @@ { "doctype": "Item Tax", "parentfield": "taxes", - "tax_rate": 10, - "tax_type": "_Test Account Excise Duty - _TC" + "item_tax_template": "_Test Account Excise Duty @ 10", + "tax_category": "" } ], "stock_uom": "_Test UOM 1" @@ -344,5 +344,121 @@ "stock_uom": "_Test UOM", "show_in_website": 1, "website_warehouse": "_Test Warehouse Group-C1 - _TC" + }, + { + "description": "_Test Item With Item Tax Template", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item With Item Tax Template", + "item_group": "_Test Item Group", + "item_name": "_Test Item With Item Tax Template", + "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", + "item_defaults": [{ + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC" + }], + "taxes": [ + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 10", + "tax_category": "" + }, + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 12", + "tax_category": "_Test Tax Category 1" + } + ] + }, + { + "description": "_Test Item Inherit Group Item Tax Template 1", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item Inherit Group Item Tax Template 1", + "item_group": "_Test Item Group Tax Parent", + "item_name": "_Test Item Inherit Group Item Tax Template 1", + "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", + "item_defaults": [{ + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC" + }] + }, + { + "description": "_Test Item Inherit Group Item Tax Template 2", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item Inherit Group Item Tax Template 2", + "item_group": "_Test Item Group Tax Child Override", + "item_name": "_Test Item Inherit Group Item Tax Template 2", + "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", + "item_defaults": [{ + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC" + }] + }, + { + "description": "_Test Item Override Group Item Tax Template", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item Override Group Item Tax Template", + "item_group": "_Test Item Group Tax Child Override", + "item_name": "_Test Item Override Group Item Tax Template", + "stock_uom": "_Test UOM", + "gst_hsn_code": "999800", + "item_defaults": [{ + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC" + }], + "taxes": [ + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 20", + "tax_category": "" + }, + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Item Tax Template 1", + "tax_category": "_Test Tax Category 1" + } + ] } ] diff --git a/erpnext/stock/doctype/item_tax/item_tax.json b/erpnext/stock/doctype/item_tax/item_tax.json index 6c1bd0999a8..37daa2938da 100644 --- a/erpnext/stock/doctype/item_tax/item_tax.json +++ b/erpnext/stock/doctype/item_tax/item_tax.json @@ -1,5 +1,7 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -10,70 +12,86 @@ "editable_grid": 1, "fields": [ { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "fieldname": "tax_type", + "columns": 0, + "fieldname": "item_tax_template", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, - "label": "Tax", + "in_standard_filter": 0, + "label": "Item Tax Template", "length": 0, "no_copy": 0, "oldfieldname": "tax_type", "oldfieldtype": "Link", - "options": "Account", + "options": "Item Tax Template", "permlevel": 0, "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "fieldname": "tax_rate", - "fieldtype": "Float", + "columns": 0, + "fetch_from": "", + "fieldname": "tax_category", + "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, - "label": "Tax Rate", + "in_standard_filter": 0, + "label": "Tax Category", "length": 0, "no_copy": 0, "oldfieldname": "tax_rate", "oldfieldtype": "Currency", + "options": "Tax Category", "permlevel": 0, "print_hide": 0, "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, + "translatable": 0, "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 1, "image_view": 0, "in_create": 0, - "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-07-11 03:28:01.235369", + "modified": "2018-12-21 23:52:40.798944", "modified_by": "Administrator", "module": "Stock", "name": "Item Tax", @@ -82,5 +100,8 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 0, - "track_seen": 0 + "show_name_in_global_search": 0, + "track_changes": 0, + "track_seen": 0, + "track_views": 0 } \ No newline at end of file diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index 3e9ff4997d5..61767d9bedd 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -85,7 +85,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "default": "{supplier_name}", + "default": "{supplier_name}", "fieldname": "title", "fieldtype": "Data", "hidden": 1, @@ -98,6 +98,7 @@ "label": "Title", "length": 0, "no_copy": 1, + "options": "", "permlevel": 0, "precision": "", "print_hide": 1, @@ -247,7 +248,7 @@ "set_only_once": 0, "translatable": 0, "unique": 0 - }, + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1748,8 +1749,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "description": "", - "fieldname": "taxes_and_charges", + "fieldname": "tax_category", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -1758,13 +1758,12 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Taxes and Charges", + "label": "Tax Category", "length": 0, "no_copy": 0, - "oldfieldname": "purchase_other_charges", - "oldfieldtype": "Link", - "options": "Purchase Taxes and Charges Template", + "options": "Tax Category", "permlevel": 0, + "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, @@ -1871,6 +1870,41 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "", + "fieldname": "taxes_and_charges", + "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": "Purchase Taxes and Charges Template", + "length": 0, + "no_copy": 0, + "oldfieldname": "purchase_other_charges", + "oldfieldtype": "Link", + "options": "Purchase Taxes and Charges Template", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -3708,7 +3742,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2018-11-02 19:59:01.423485", + "modified": "2018-12-27 02:06:29.508848", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", @@ -3813,7 +3847,7 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 1, - "search_fields": "status, posting_date, supplier", + "search_fields": "status, posting_date, supplier", "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index 3746dfb2235..dcc70d7c864 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -2059,6 +2059,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "item_tax_template", + "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": "Item Tax Template", + "length": 0, + "no_copy": 0, + "options": "Item Tax Template", + "permlevel": 0, + "precision": "", + "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, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2608,7 +2641,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-01-07 16:51:59.002215", + "modified": "2018-11-23 16:52:02.808534", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", @@ -2623,4 +2656,4 @@ "track_changes": 0, "track_seen": 0, "track_views": 0 -} \ No newline at end of file +} diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 692fe5d0fbe..f86be148415 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -44,6 +44,10 @@ def get_item_details(args): out = get_basic_details(args, item) + get_item_tax_template(args, item, out) + out["item_tax_rate"] = get_item_tax_map(args.company, args.get("item_tax_template") if out.get("item_tax_template") is None \ + else out.get("item_tax_template"), as_json=True) + get_party_item_code(args, item, out) set_valuation_rate(out, args) @@ -248,8 +252,6 @@ def get_basic_details(args, item): 'has_serial_no': item.has_serial_no, 'has_batch_no': item.has_batch_no, "batch_no": None, - "item_tax_rate": json.dumps(dict(([d.tax_type, d.tax_rate] for d in - item.get("taxes")))), "uom": args.uom, "min_order_qty": flt(item.min_order_qty) if args.doctype == "Material Request" else "", "qty": args.qty or 1.0, @@ -304,6 +306,59 @@ def get_basic_details(args, item): return out +@frappe.whitelist() +def get_item_tax_info(company, tax_category, item_codes): + out = {} + if isinstance(item_codes, string_types): + item_codes = json.loads(item_codes) + + for item_code in item_codes: + if not item_code or item_code in out: + continue + out[item_code] = {} + item = frappe.get_cached_doc("Item", item_code) + get_item_tax_template({"tax_category": tax_category}, item, out[item_code]) + out[item_code]["item_tax_rate"] = get_item_tax_map(company, out[item_code].get("item_tax_template"), as_json=True) + + return out + +def get_item_tax_template(args, item, out): + """ + args = { + "tax_category": None + "item_tax_template": None + } + """ + item_tax_template = args.get("item_tax_template") + + if not item_tax_template: + item_tax_template = _get_item_tax_template(args, item.taxes, out) + + if not item_tax_template: + item_group = item.item_group + while item_group and not item_tax_template: + item_group_doc = frappe.get_cached_doc("Item Group", item_group) + item_tax_template = _get_item_tax_template(args, item_group_doc.taxes, out) + item_group = item_group_doc.parent_item_group + +def _get_item_tax_template(args, taxes, out): + for tax in taxes: + if cstr(tax.tax_category) == cstr(args.get("tax_category")): + out["item_tax_template"] = tax.item_tax_template + return tax.item_tax_template + return None + +@frappe.whitelist() +def get_item_tax_map(company, item_tax_template, as_json=True): + item_tax_map = {} + if item_tax_template: + template = frappe.get_cached_doc("Item Tax Template", item_tax_template) + for d in template.taxes: + if frappe.get_cached_value("Account", d.tax_type, "company") == company: + item_tax_map[d.tax_type] = d.tax_rate + + return json.dumps(item_tax_map) if as_json else item_tax_map + @frappe.whitelist() def calculate_service_end_date(args, item=None): args = process_args(args)