From 72e6aa160c911aa468885aa91b40e34822cae372 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Fri, 14 Aug 2015 11:40:00 +0530 Subject: [PATCH 01/16] Added New Doctype Tax Rule --- erpnext/accounts/doctype/tax_rule/__init__.py | 0 .../accounts/doctype/tax_rule/tax_rule.json | 475 ++++++++++++++++++ erpnext/accounts/doctype/tax_rule/tax_rule.py | 10 + .../doctype/tax_rule/test_tax_rule.py | 12 + 4 files changed, 497 insertions(+) create mode 100644 erpnext/accounts/doctype/tax_rule/__init__.py create mode 100644 erpnext/accounts/doctype/tax_rule/tax_rule.json create mode 100644 erpnext/accounts/doctype/tax_rule/tax_rule.py create mode 100644 erpnext/accounts/doctype/tax_rule/test_tax_rule.py diff --git a/erpnext/accounts/doctype/tax_rule/__init__.py b/erpnext/accounts/doctype/tax_rule/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.json b/erpnext/accounts/doctype/tax_rule/tax_rule.json new file mode 100644 index 0000000000..7e20f41291 --- /dev/null +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.json @@ -0,0 +1,475 @@ +{ + "allow_copy": 0, + "allow_import": 1, + "allow_rename": 0, + "creation": "2015-08-07 02:33:52.670866", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "Master", + "fields": [ + { + "allow_on_submit": 0, + "fieldname": "filters", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Filters", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "customer", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Customer", + "no_copy": 0, + "options": "Customer", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "billing_city", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Billing City", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "billing_country", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Billing Country", + "no_copy": 0, + "options": "Country", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "column_break_2", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "customer_group", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Customer Group", + "no_copy": 0, + "options": "Customer Group", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "shipping_city", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Shipping City", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "shipping_country", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Shipping Country", + "no_copy": 0, + "options": "Country", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "section_break_4", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Validity", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "from_date", + "fieldtype": "Date", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "From Date", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "column_break_7", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "to_date", + "fieldtype": "Date", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "To Date", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "section_break_7", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "tax_type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Tax Type", + "no_copy": 0, + "options": "\nSales\nPurchase", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "column_break_9", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "depends_on": "eval: doc.tax_type == \"Sales\"", + "fieldname": "sales_tax_template", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Sales Tax Template", + "no_copy": 0, + "options": "Sales Taxes and Charges", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "depends_on": "eval: doc.tax_type == \"Purchase\"", + "fieldname": "purchase_tax_template", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Purchase Tax Template", + "no_copy": 0, + "options": "Purchase Taxes and Charges", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "section_break_6", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "priority", + "fieldtype": "Int", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Priority", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "column_break_20", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "company", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Company", + "no_copy": 0, + "options": "Company", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + } + ], + "hide_heading": 0, + "hide_toolbar": 0, + "in_create": 0, + "in_dialog": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "modified": "2015-08-13 09:12:42.118276", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Tax Rule", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 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": "Administrator", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "read_only": 0, + "read_only_onload": 0, + "sort_field": "modified", + "sort_order": "DESC" +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py new file mode 100644 index 0000000000..f4bf17746f --- /dev/null +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, 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 TaxRule(Document): + pass diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py new file mode 100644 index 0000000000..4712243495 --- /dev/null +++ b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Tax Rule') + +class TestTaxRule(unittest.TestCase): + pass From 949d7dbaba038c7188a687f571aebcb602bc800d Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Mon, 17 Aug 2015 14:55:15 +0530 Subject: [PATCH 02/16] Added validations, test-cases to Tax Rule --- erpnext/accounts/doctype/tax_rule/tax_rule.js | 7 +++ .../accounts/doctype/tax_rule/tax_rule.json | 8 ++- erpnext/accounts/doctype/tax_rule/tax_rule.py | 57 ++++++++++++++++++- .../doctype/tax_rule/test_tax_rule.py | 33 ++++++++++- .../doctype/customer_group/test_records.json | 6 ++ 5 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 erpnext/accounts/doctype/tax_rule/tax_rule.js diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.js b/erpnext/accounts/doctype/tax_rule/tax_rule.js new file mode 100644 index 0000000000..b9221785d5 --- /dev/null +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.js @@ -0,0 +1,7 @@ +// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +// License: GNU General Public License v3. See license.txt + +cur_frm.add_fetch("customer", "customer_group", "customer_group" ); + +this.frm.toggle_reqd("sales_tax_template", this.frm.doc.tax_type=="Sales"); +this.frm.toggle_reqd("purchase_tax_template", this.frm.doc.tax_type=="Purchase"); \ No newline at end of file diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.json b/erpnext/accounts/doctype/tax_rule/tax_rule.json index 7e20f41291..f2df6544c4 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.json +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.json @@ -2,6 +2,7 @@ "allow_copy": 0, "allow_import": 1, "allow_rename": 0, + "autoname": "TR.####", "creation": "2015-08-07 02:33:52.670866", "custom": 0, "docstatus": 0, @@ -320,7 +321,7 @@ "in_list_view": 0, "label": "Sales Tax Template", "no_copy": 0, - "options": "Sales Taxes and Charges", + "options": "Sales Taxes and Charges Template", "permlevel": 0, "precision": "", "print_hide": 0, @@ -342,7 +343,7 @@ "in_list_view": 0, "label": "Purchase Tax Template", "no_copy": 0, - "options": "Purchase Taxes and Charges", + "options": "Purchase Taxes and Charges Template", "permlevel": 0, "precision": "", "print_hide": 0, @@ -374,6 +375,7 @@ }, { "allow_on_submit": 0, + "default": "1", "fieldname": "priority", "fieldtype": "Int", "hidden": 0, @@ -440,7 +442,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-08-13 09:12:42.118276", + "modified": "2015-08-14 08:10:56.694925", "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 f4bf17746f..d1b0bdc8de 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -4,7 +4,62 @@ from __future__ import unicode_literals import frappe +from frappe import _ from frappe.model.document import Document +class IncorrectCustomerGroup(frappe.ValidationError): pass + class TaxRule(Document): - pass + def validate(self): + self.validate_tax_template() + self.validate_customer_group() + self.validate_date() + self.validate_filters() + + def validate_tax_template(self): + if not (self.sales_tax_template or self.purchase_tax_template): + frappe.throw(_("Tax Template is mandatory.")) + if self.tax_type=="Sales": + self.purchase_tax_template= None + else: + self.sales_tax_template= None + + def validate_customer_group(self): + if self.customer and self.customer_group: + if not frappe.db.get_value("Customer", self.customer, "customer_group") == self.customer_group: + frappe.throw(_("Customer {0} does not belong to customer group {1}"). \ + format(self.customer, self.customer_group), IncorrectCustomerGroup) + + def validate_date(self): + if self.from_date and self.to_date and self.from_date > self.to_date: + frappe.throw(_("From Date cannot be greater than To Date")) + + def validate_filters(self): + filters = { + "customer": self.customer, + "customer_group": self.customer_group, + "billing_city": self.billing_city, + "billing_country": self.billing_country, + "shipping_city": self.shipping_city, + "shipping_country": self.shipping_country, + "tax_type": self.tax_type, + "company": self.company + } + + conds="" + for d in filters: + if conds: + conds += " and " + conds += """{0} = '{1}'""".format(d, filters[d]) + + conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or + (to_date > '{from_date}' and to_date < '{to_date}') or + ('{from_date}' > from_date and '{from_date}' < to_date) or + ('{from_date}' = from_date and '{to_date}' = to_date))""".format(from_date=self.from_date, to_date=self.to_date) + + tax_rule = frappe.db.sql("select name, priority \ + from `tabTax Rule` where {0} and name != '{1}'".format(conds, self.name), as_dict=1) + + if tax_rule: + if tax_rule[0].priority == self.priority: + frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name))) \ No newline at end of file diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py index 4712243495..7a2c6ef080 100644 --- a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py @@ -5,8 +5,39 @@ from __future__ import unicode_literals import frappe import unittest +from frappe.utils import nowdate, add_days +from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup # test_records = frappe.get_test_records('Tax Rule') class TestTaxRule(unittest.TestCase): - pass + def test_customer_group(self): + tax_rule = make_tax_rule_test_record(customer_group= "_Test Customer Group 1", do_not_save= True) + self.assertRaises(IncorrectCustomerGroup, tax_rule.save) + + def test_tax_template(self): + tax_rule = make_tax_rule_test_record() + self.assertEquals(tax_rule.purchase_tax_template, None) + +def make_tax_rule_test_record(**args): + args = frappe._dict(args) + + tax_rule = frappe.new_doc("Tax Rule") + tax_rule.customer= args.customer or "_Test Customer" + tax_rule.customer_group= args.customer_group or "_Test Customer Group" + tax_rule.billing_city= args.billing_city or "_Test City" + tax_rule.billing_country= args.billing_country or "_Test Country" + tax_rule.shipping_city= args.shipping_city or "_Test City" + tax_rule.shipping_country= args.shipping_country or "_Test Country" + tax_rule.from_date= args.from_date or nowdate() + tax_rule.to_date= args.to_date or add_days(nowdate(), 1) + tax_rule.tax_type= args.tax_type or "Sales" + tax_rule.sales_tax_template= args.sales_tax_template or "_Test Sales Taxes and Charges Template" + tax_rule.purchase_tax_template= args.purchase_tax_template or "_Test Purchase Taxes and Charges Template" + tax_rule.priority= args.priority or 1 + tax_rule.compant= args.company or "_Test Company" + + if not args.do_not_save: + tax_rule.save() + return tax_rule + \ No newline at end of file diff --git a/erpnext/setup/doctype/customer_group/test_records.json b/erpnext/setup/doctype/customer_group/test_records.json index 14d815ce76..cc3f87e098 100644 --- a/erpnext/setup/doctype/customer_group/test_records.json +++ b/erpnext/setup/doctype/customer_group/test_records.json @@ -4,5 +4,11 @@ "doctype": "Customer Group", "is_group": "No", "parent_customer_group": "All Customer Groups" + }, + { + "customer_group_name": "_Test Customer Group 1", + "doctype": "Customer Group", + "is_group": "No", + "parent_customer_group": "All Customer Groups" } ] From 810bd35609aade27e84a729bd82b03bd733e678f Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Fri, 21 Aug 2015 15:04:57 +0530 Subject: [PATCH 03/16] Apply Tax Rule based on Customer Selection in Sales / Purchase Transactions --- .../test_records.json | 60 +++++ erpnext/accounts/doctype/tax_rule/tax_rule.js | 39 ++- .../accounts/doctype/tax_rule/tax_rule.json | 238 ++++++++++-------- erpnext/accounts/doctype/tax_rule/tax_rule.py | 83 ++++-- .../doctype/tax_rule/test_tax_rule.py | 132 ++++++++-- erpnext/accounts/party.py | 22 +- erpnext/buying/doctype/supplier/supplier.json | 1 + erpnext/public/js/utils/party.js | 1 + 8 files changed, 431 insertions(+), 145 deletions(-) diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json b/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json index 656d29c461..5c25517f7f 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json @@ -153,5 +153,65 @@ "territory": "_Test Territory Rest Of The World" } ] + }, + { + "company": "_Test Company", + "doctype": "Sales Taxes and Charges Template", + "taxes": [ + { + "account_head": "_Test Account VAT - _TC", + "charge_type": "On Net Total", + "description": "VAT", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": 12 + }, + { + "account_head": "_Test Account Service Tax - _TC", + "charge_type": "On Net Total", + "description": "Service Tax", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": 4 + } + ], + "title": "_Test Sales Taxes and Charges Template 1", + "territories": [ + { + "doctype": "Applicable Territory", + "parentfield": "territories", + "territory": "_Test Territory Rest Of The World" + } + ] + }, + { + "company": "_Test Company", + "doctype": "Sales Taxes and Charges Template", + "taxes": [ + { + "account_head": "_Test Account VAT - _TC", + "charge_type": "On Net Total", + "description": "VAT", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": 12 + }, + { + "account_head": "_Test Account Service Tax - _TC", + "charge_type": "On Net Total", + "description": "Service Tax", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": 4 + } + ], + "title": "_Test Sales Taxes and Charges Template 2", + "territories": [ + { + "doctype": "Applicable Territory", + "parentfield": "territories", + "territory": "_Test Territory Rest Of The World" + } + ] } ] diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.js b/erpnext/accounts/doctype/tax_rule/tax_rule.js index b9221785d5..d4a10aaec3 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.js +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.js @@ -2,6 +2,41 @@ // License: GNU General Public License v3. See license.txt cur_frm.add_fetch("customer", "customer_group", "customer_group" ); +cur_frm.add_fetch("supplier", "supplier_type", "supplier_type" ); -this.frm.toggle_reqd("sales_tax_template", this.frm.doc.tax_type=="Sales"); -this.frm.toggle_reqd("purchase_tax_template", this.frm.doc.tax_type=="Purchase"); \ No newline at end of file +cur_frm.toggle_reqd("sales_tax_template", cur_frm.doc.tax_type=="Sales"); +cur_frm.toggle_reqd("purchase_tax_template", cur_frm.doc.tax_type=="Purchase"); + +frappe.ui.form.on("Tax Rule", "customer", function(frm) { + frappe.call({ + method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details", + args: { + "party": frm.doc.customer, + "party_type": "customer" + }, + callback: function(r) { + if(!r.exc) { + $.each(r.message, function(k, v) { + frm.set_value(k, v); + }); + } + } + }); +}); + +frappe.ui.form.on("Tax Rule", "supplier", function(frm) { + frappe.call({ + method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details", + args: { + "party": frm.doc.supplier, + "party_type": "supplier" + }, + callback: function(r) { + if(!r.exc) { + $.each(r.message, function(k, v) { + frm.set_value(k, v); + }); + } + } + }); +}); \ No newline at end of file diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.json b/erpnext/accounts/doctype/tax_rule/tax_rule.json index f2df6544c4..52ca63f62e 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.json +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.json @@ -7,8 +7,93 @@ "custom": 0, "docstatus": 0, "doctype": "DocType", - "document_type": "Master", + "document_type": "Setup", "fields": [ + { + "allow_on_submit": 0, + "default": "Sales", + "fieldname": "tax_type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Tax Type", + "no_copy": 0, + "options": "Sales\nPurchase", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "fieldname": "column_break_1", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "depends_on": "eval:doc.tax_type==\"Sales\"", + "fieldname": "sales_tax_template", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Sales Tax Template", + "no_copy": 0, + "options": "Sales Taxes and Charges Template", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "depends_on": "eval:doc.tax_type==\"Purchase\"", + "fieldname": "purchase_tax_template", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Purchase Tax Template", + "no_copy": 0, + "options": "Purchase Taxes and Charges Template", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "fieldname": "filters", @@ -31,6 +116,7 @@ }, { "allow_on_submit": 0, + "depends_on": "eval:doc.tax_type==\"Sales\"", "fieldname": "customer", "fieldtype": "Link", "hidden": 0, @@ -50,6 +136,28 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "depends_on": "eval:doc.tax_type==\"Purchase\"", + "fieldname": "supplier", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Supplier", + "no_copy": 0, + "options": "Supplier", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "fieldname": "billing_city", @@ -112,6 +220,7 @@ }, { "allow_on_submit": 0, + "depends_on": "eval:doc.tax_type==\"Sales\"", "fieldname": "customer_group", "fieldtype": "Link", "hidden": 0, @@ -131,6 +240,28 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "depends_on": "eval:doc.tax_type==\"Purchase\"", + "fieldname": "supplier_type", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Supplier Type", + "no_copy": 0, + "options": "Supplier Type", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "fieldname": "shipping_city", @@ -251,109 +382,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "fieldname": "section_break_7", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "fieldname": "tax_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Tax Type", - "no_copy": 0, - "options": "\nSales\nPurchase", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "fieldname": "column_break_9", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "depends_on": "eval: doc.tax_type == \"Sales\"", - "fieldname": "sales_tax_template", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Sales Tax Template", - "no_copy": 0, - "options": "Sales Taxes and Charges Template", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "depends_on": "eval: doc.tax_type == \"Purchase\"", - "fieldname": "purchase_tax_template", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Purchase Tax Template", - "no_copy": 0, - "options": "Purchase Taxes and Charges Template", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_on_submit": 0, "fieldname": "section_break_6", @@ -442,7 +470,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-08-14 08:10:56.694925", + "modified": "2015-08-21 03:27:43.564183", "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 d1b0bdc8de..635bdc1ed9 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -6,43 +6,56 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document +from frappe.utils import cstr class IncorrectCustomerGroup(frappe.ValidationError): pass +class IncorrectSupplierType(frappe.ValidationError): pass +class ConflictingTaxRule(frappe.ValidationError): pass class TaxRule(Document): def validate(self): self.validate_tax_template() self.validate_customer_group() + self.validate_supplier_type() self.validate_date() self.validate_filters() - + def validate_tax_template(self): + if self.tax_type== "Sales": + self.purchase_tax_template = self.supplier = self.supplier_type= None + else: + self.sales_tax_template= self.customer = self.customer_group= None + if not (self.sales_tax_template or self.purchase_tax_template): frappe.throw(_("Tax Template is mandatory.")) - if self.tax_type=="Sales": - self.purchase_tax_template= None - else: - self.sales_tax_template= None def validate_customer_group(self): if self.customer and self.customer_group: if not frappe.db.get_value("Customer", self.customer, "customer_group") == self.customer_group: frappe.throw(_("Customer {0} does not belong to customer group {1}"). \ format(self.customer, self.customer_group), IncorrectCustomerGroup) - + + def validate_supplier_type(self): + if self.supplier and self.supplier_type: + if not frappe.db.get_value("Supplier", self.supplier, "supplier_type") == self.supplier_type: + frappe.throw(_("Supplier {0} does not belong to Supplier Type {1}"). \ + format(self.supplier, self.supplier_type), IncorrectSupplierType) + def validate_date(self): if self.from_date and self.to_date and self.from_date > self.to_date: frappe.throw(_("From Date cannot be greater than To Date")) def validate_filters(self): filters = { + "tax_type": self.tax_type, "customer": self.customer, "customer_group": self.customer_group, + "supplier": self.supplier, + "supplier_type": self.supplier_type, "billing_city": self.billing_city, "billing_country": self.billing_country, "shipping_city": self.shipping_city, "shipping_country": self.shipping_country, - "tax_type": self.tax_type, "company": self.company } @@ -50,16 +63,58 @@ class TaxRule(Document): for d in filters: if conds: conds += " and " - conds += """{0} = '{1}'""".format(d, filters[d]) - - conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or - (to_date > '{from_date}' and to_date < '{to_date}') or - ('{from_date}' > from_date and '{from_date}' < to_date) or - ('{from_date}' = from_date and '{to_date}' = to_date))""".format(from_date=self.from_date, to_date=self.to_date) + conds += """ifnull({0}, '') = '{1}'""".format(d, frappe.db.escape(cstr(filters[d]))) + + if self.from_date and self.to_date: + conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or + (to_date > '{from_date}' and to_date < '{to_date}') or + ('{from_date}' > from_date and '{from_date}' < to_date) or + ('{from_date}' = from_date and '{to_date}' = to_date))""".format(from_date=self.from_date, to_date=self.to_date) + + elif self.from_date and not self.to_date: + conds += """ and to_date > '{from_date}'""".format(from_date = self.from_date) + + elif self.to_date and not self.from_date: + conds += """ and from_date < '{to_date}'""".format(to_date = self.to_date) tax_rule = frappe.db.sql("select name, priority \ from `tabTax Rule` where {0} and name != '{1}'".format(conds, self.name), as_dict=1) if tax_rule: if tax_rule[0].priority == self.priority: - frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name))) \ No newline at end of file + frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name)), ConflictingTaxRule) + +@frappe.whitelist() +def get_party_details(party, party_type): + out = {} + billing_address = frappe.get_list("Address", fields=["city", "country"], filters={party_type: party, "is_primary_address": 1}) + shipping_address = frappe.get_list("Address", fields=["city", "country"], filters={party_type:party, "is_shipping_address": 1}) + if billing_address: + out["billing_city"]= billing_address[0].city + out["billing_country"]= billing_address[0].country + if shipping_address: + out["shipping_city"]= shipping_address[0].city + out["shipping_country"]= shipping_address[0].country + return out + +def get_tax_template(posting_date, args): + """Get matching tax rule""" + args = frappe._dict(args) + conditions = [] + + for key, value in args.iteritems(): + conditions.append("ifnull({0}, '') in ('', '{1}')".format(key, frappe.db.escape(cstr(value)))) + + matching = frappe.db.sql("""select * from `tabTax Rule` + where {0}""".format(" and ".join(conditions)), as_dict = True) + + if not matching: + return None + + for rule in matching: + rule.no_of_keys_matched = 0 + for key in args: + if rule.get(key): rule.no_of_keys_matched += 1 + + rule = sorted(matching, lambda b, a: cmp(a.no_of_keys_matched, b.no_of_keys_matched) or cmp(a.priority, b.priority))[0] + return rule.sales_tax_template or rule.purchase_tax_template \ No newline at end of file diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py index 7a2c6ef080..873a4e38a7 100644 --- a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py @@ -5,39 +5,127 @@ from __future__ import unicode_literals import frappe import unittest -from frappe.utils import nowdate, add_days -from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup +from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup, IncorrectSupplierType, ConflictingTaxRule, get_tax_template # test_records = frappe.get_test_records('Tax Rule') class TestTaxRule(unittest.TestCase): + def setUp(self): + frappe.db.sql("delete from `tabTax Rule`") + def test_customer_group(self): - tax_rule = make_tax_rule_test_record(customer_group= "_Test Customer Group 1", do_not_save= True) + tax_rule = make_tax_rule(customer= "_Test Customer", customer_group= "_Test Customer Group 1", + sales_tax_template = "_Test Sales Taxes and Charges Template") self.assertRaises(IncorrectCustomerGroup, tax_rule.save) - def test_tax_template(self): - tax_rule = make_tax_rule_test_record() - self.assertEquals(tax_rule.purchase_tax_template, None) + def test_supplier_type(self): + tax_rule = make_tax_rule(supplier= "_Test Supplier", supplier_type= "_Test Supplier Type 1", + purchase_tax_template = "_Test Purchase Taxes and Charges Template") + self.assertRaises(IncorrectSupplierType, tax_rule.save) + + def test_conflict(self): + tax_rule1 = make_tax_rule(customer= "_Test Customer", + sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1) + tax_rule1.save() -def make_tax_rule_test_record(**args): + tax_rule2 = make_tax_rule(customer= "_Test Customer", + sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1) + + self.assertRaises(ConflictingTaxRule, tax_rule2.save) + + def test_conflict_with_non_overlapping_dates(self): + tax_rule1 = make_tax_rule(customer= "_Test Customer", + sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01") + tax_rule1.save() + + tax_rule2 = make_tax_rule(customer= "_Test Customer", + sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, to_date = "2013-01-01") + + tax_rule2.save() + self.assertTrue(tax_rule2.name) + + def test_conflict_with_overlapping_dates(self): + tax_rule1 = make_tax_rule(customer= "_Test Customer", + sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01", to_date = "2015-01-05") + tax_rule1.save() + + tax_rule2 = make_tax_rule(customer= "_Test Customer", + sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-03", to_date = "2015-01-09") + + self.assertRaises(ConflictingTaxRule, tax_rule2.save) + + def test_tax_template(self): + tax_rule = make_tax_rule() + self.assertEquals(tax_rule.purchase_tax_template, None) + + + def test_select_tax_rule_based_on_customer(self): + make_tax_rule(customer= "_Test Customer", + sales_tax_template = "_Test Sales Taxes and Charges Template", save=1) + + make_tax_rule(customer= "_Test Customer 1", + sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1) + + make_tax_rule(customer= "_Test Customer 2", + sales_tax_template = "_Test Sales Taxes and Charges Template 2", save=1) + + self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer 2"}), + "_Test Sales Taxes and Charges Template 2") + + def test_select_tax_rule_based_on_better_match(self): + make_tax_rule(customer= "_Test Customer", billing_city = "Test City", + sales_tax_template = "_Test Sales Taxes and Charges Template", save=1) + + make_tax_rule(customer= "_Test Customer", + sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1) + + self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}), + "_Test Sales Taxes and Charges Template") + + def test_select_tax_rule_based_on_better_priority(self): + make_tax_rule(customer= "_Test Customer", billing_city = "Test City", + sales_tax_template = "_Test Sales Taxes and Charges Template", priority=1, save=1) + + make_tax_rule(customer= "_Test Customer", billing_city = "Test City", + sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1) + + self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}), + "_Test Sales Taxes and Charges Template 1") + + def test_select_tax_rule_based_cross_matching_keys(self): + make_tax_rule(customer= "_Test Customer", billing_city = "Test City", + sales_tax_template = "_Test Sales Taxes and Charges Template", save=1) + + make_tax_rule(customer= "_Test Customer 1", billing_city = "Test City 1", + sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1) + + self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}), + None) + + def test_select_tax_rule_based_cross_partially_keys(self): + make_tax_rule(customer= "_Test Customer", billing_city = "Test City", + sales_tax_template = "_Test Sales Taxes and Charges Template", save=1) + + make_tax_rule(billing_city = "Test City 1", + sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1) + + self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}), + "_Test Sales Taxes and Charges Template 1") + + +def make_tax_rule(**args): args = frappe._dict(args) tax_rule = frappe.new_doc("Tax Rule") - tax_rule.customer= args.customer or "_Test Customer" - tax_rule.customer_group= args.customer_group or "_Test Customer Group" - tax_rule.billing_city= args.billing_city or "_Test City" - tax_rule.billing_country= args.billing_country or "_Test Country" - tax_rule.shipping_city= args.shipping_city or "_Test City" - tax_rule.shipping_country= args.shipping_country or "_Test Country" - tax_rule.from_date= args.from_date or nowdate() - tax_rule.to_date= args.to_date or add_days(nowdate(), 1) - tax_rule.tax_type= args.tax_type or "Sales" - tax_rule.sales_tax_template= args.sales_tax_template or "_Test Sales Taxes and Charges Template" - tax_rule.purchase_tax_template= args.purchase_tax_template or "_Test Purchase Taxes and Charges Template" - tax_rule.priority= args.priority or 1 - tax_rule.compant= args.company or "_Test Company" - if not args.do_not_save: - tax_rule.save() + for key, val in args.iteritems(): + if key != "save": + tax_rule.set(key, val) + + tax_rule.company = args.company or "_Test Company" + + if args.save: + tax_rule.insert() + return tax_rule \ No newline at end of file diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 4f49bc07fd..313544f143 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -43,6 +43,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company= 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) if not out.get("currency"): out["currency"] = currency @@ -99,7 +100,7 @@ def set_other_values(out, party, party_type): out[f] = party.get(f) # fields prepended with default in Customer doctype - for f in ['currency', 'taxes_and_charges'] \ + for f in ['currency'] \ + (['sales_partner', 'commission_rate'] if party_type=="Customer" else []): if party.get("default_" + f): out[f] = party.get("default_" + f) @@ -274,4 +275,21 @@ def validate_due_date(posting_date, due_date, party_type, party, company): msgprint(_("Note: Due / Reference Date exceeds allowed customer credit days by {0} day(s)") .format(date_diff(due_date, default_due_date))) else: - frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date))) \ No newline at end of file + frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date))) + +def set_taxes(party, party_type, posting_date, company, out): + print "posting_date", posting_date + from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details + args = { + party_type: party, + "customer_group": out.customer_group, + "supplier_type": out.supplier_type, + "company": company + } + args.update(get_party_details(party, party_type)) + if party_type=="Customer": + args.update({"tax_type": "Sales"}) + else: + args.update({"tax_type": "Purchase"}) + + return get_tax_template(posting_date, args) \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index 2a0a50d45d..ce68370d13 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -1,4 +1,5 @@ { +<<<<<<< HEAD "allow_copy": 0, "allow_import": 1, "allow_rename": 1, diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js index 919225f9a9..59992ebc04 100644 --- a/erpnext/public/js/utils/party.js +++ b/erpnext/public/js/utils/party.js @@ -20,6 +20,7 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) { price_list: frm.doc.buying_price_list }; } + args.posting_date = frm.doc.transaction_date; } if(!args) return; From 1a2d121073e31d72a3790792cd3818d7a24b569e Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Fri, 21 Aug 2015 15:53:10 +0530 Subject: [PATCH 04/16] Removed default taxes and charges from customer and supplier master. Added patch to create tax rules against customer/supplier --- .../doctype/tax_rule/test_tax_rule.py | 2 +- erpnext/patches/v5_8/tax_rule.py | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v5_8/tax_rule.py diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py index 873a4e38a7..9802c09600 100644 --- a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py @@ -19,7 +19,7 @@ class TestTaxRule(unittest.TestCase): self.assertRaises(IncorrectCustomerGroup, tax_rule.save) def test_supplier_type(self): - tax_rule = make_tax_rule(supplier= "_Test Supplier", supplier_type= "_Test Supplier Type 1", + tax_rule = make_tax_rule(tax_type= "Purchase", supplier= "_Test Supplier", supplier_type= "_Test Supplier Type 1", purchase_tax_template = "_Test Purchase Taxes and Charges Template") self.assertRaises(IncorrectSupplierType, tax_rule.save) diff --git a/erpnext/patches/v5_8/tax_rule.py b/erpnext/patches/v5_8/tax_rule.py new file mode 100644 index 0000000000..b710ddcbe4 --- /dev/null +++ b/erpnext/patches/v5_8/tax_rule.py @@ -0,0 +1,27 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + customers = frappe.db.sql("""select name, default_taxes_and_charges from tabCustomer where + ifnull(default_taxes_and_charges, '') != '' """, as_dict=1) + + for d in customers: + tr = frappe.new_doc("Tax Rule") + tr.tax_type = "Sales" + tr.customer = d.name + tr.sales_tax_template = d.default_taxes_and_charges + tr.save() + + + suppliers = frappe.db.sql("""select name, default_taxes_and_charges from tabSupplier where + ifnull(default_taxes_and_charges, '') != '' """, as_dict=1) + + for d in suppliers: + tr = frappe.new_doc("Tax Rule") + tr.tax_type = "Purchase" + tr.supplier = d.name + tr.purchase_tax_template = d.default_taxes_and_charges + tr.save() \ No newline at end of file From 09f9c96c5375036f8379a25da46314af9fe9ad9d Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Wed, 26 Aug 2015 10:41:31 +0530 Subject: [PATCH 05/16] Fixes in Tax Rule --- erpnext/accounts/doctype/tax_rule/tax_rule.py | 15 ++++++++++--- erpnext/accounts/party.py | 18 +++++++++------- erpnext/public/js/utils/party.js | 21 ++++++++++++++++++- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index 635bdc1ed9..705a26e771 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -85,13 +85,22 @@ class TaxRule(Document): frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name)), ConflictingTaxRule) @frappe.whitelist() -def get_party_details(party, party_type): +def get_party_details(party, party_type, args=None): out = {} - billing_address = frappe.get_list("Address", fields=["city", "country"], filters={party_type: party, "is_primary_address": 1}) - shipping_address = frappe.get_list("Address", fields=["city", "country"], filters={party_type:party, "is_shipping_address": 1}) + if args: + billing_filters= {"name": args.get("billing_address")} + shipping_filters= {"name": args.get("shipping_address")} + else: + billing_filters= {party_type: party, "is_primary_address": 1} + shipping_filters= {party_type:party, "is_shipping_address": 1} + + billing_address= frappe.get_all("Address", fields=["city", "country"], filters= billing_filters) + shipping_address= frappe.get_all("Address", fields=["city", "country"], filters= shipping_filters) + if billing_address: out["billing_city"]= billing_address[0].city out["billing_country"]= billing_address[0].country + if shipping_address: out["shipping_city"]= shipping_address[0].city out["shipping_country"]= shipping_address[0].country diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 313544f143..a6b5c78cad 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -43,7 +43,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company= 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) + out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out.customer_group, out.supplier_type) if not out.get("currency"): out["currency"] = currency @@ -277,19 +277,23 @@ def validate_due_date(posting_date, due_date, party_type, party, company): else: frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date))) -def set_taxes(party, party_type, posting_date, company, out): - print "posting_date", posting_date +@frappe.whitelist() +def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_type=None, billing_address=None, shipping_address=None): from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details args = { party_type: party, - "customer_group": out.customer_group, - "supplier_type": out.supplier_type, + "customer_group": customer_group, + "supplier_type": supplier_type, "company": company } - args.update(get_party_details(party, party_type)) + + if billing_address or shipping_address: + args.update(get_party_details(party, party_type, {"billing_address": billing_address, "shipping_address": shipping_address })) + else: + args.update(get_party_details(party, party_type)) + if party_type=="Customer": args.update({"tax_type": "Sales"}) else: args.update({"tax_type": "Purchase"}) - return get_tax_template(posting_date, args) \ No newline at end of file diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js index 59992ebc04..1a86b2b620 100644 --- a/erpnext/public/js/utils/party.js +++ b/erpnext/public/js/utils/party.js @@ -43,6 +43,7 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) { erpnext.utils.get_address_display = function(frm, address_field, display_field) { if(frm.updating_party_details) return; + if(!address_field) { if(frm.doc.customer) { address_field = "customer_address"; @@ -50,14 +51,32 @@ erpnext.utils.get_address_display = function(frm, address_field, display_field) address_field = "supplier_address"; } else return; } + if(!display_field) display_field = "address_display"; if(frm.doc[address_field]) { frappe.call({ method: "erpnext.utilities.doctype.address.address.get_address_display", args: {"address_dict": frm.doc[address_field] }, callback: function(r) { - if(r.message) + if(r.message){ frm.set_value(display_field, r.message) + } + frappe.call({ + method: "erpnext.accounts.party.set_taxes", + args: { + "party": frm.doc.customer || frm.doc.supplier, + "party_type": (frm.doc.customer ? "Customer" : "Supplier"), + "posting_date": frm.doc.posting_date || frm.doc.transaction_date, + "company": frm.doc.company, + "billing_address": ((frm.doc.customer) ? (frm.doc.customer_address) : (frm.doc.supplier_address)), + "shipping_address": frm.doc.shipping_address_name + }, + callback: function(r) { + if(r.message){ + frm.set_value("taxes_and_charges", r.message) + } + } + }); } }) } From ef511b160ee496d8f9e9bfb2de05b3d65050ec18 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Wed, 26 Aug 2015 15:01:20 +0530 Subject: [PATCH 06/16] Added Tax Rule under ERPNext > Accounts > Setup --- .../purchase_invoice/purchase_invoice.json | 2 +- .../purchase_taxes_and_charges.json | 2 +- .../sales_taxes_and_charges.json | 2 +- .../accounts/doctype/tax_rule/tax_rule.json | 46 ++- .../purchase_order/purchase_order.json | 1 + erpnext/buying/doctype/supplier/supplier.json | 269 ++++++++++++++++++ erpnext/config/accounts.py | 5 + 7 files changed, 323 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 25ac8ffcc3..c1801eb20a 100755 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -2375,4 +2375,4 @@ "sort_field": "modified", "sort_order": "DESC", "title_field": "title" -} +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json index a00184bf01..9e43ca05f8 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json @@ -504,7 +504,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-08-19 12:46:32.687299", + "modified": "2015-08-28 02:57:08.769473", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Taxes and Charges", diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json index 29534d832d..a0d8df47b1 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json +++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json @@ -456,7 +456,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-08-19 12:46:33.165519", + "modified": "2015-08-28 02:57:00.766305", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Taxes and Charges", diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.json b/erpnext/accounts/doctype/tax_rule/tax_rule.json index 52ca63f62e..1974440692 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.json +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.json @@ -11,6 +11,8 @@ "fields": [ { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "default": "Sales", "fieldname": "tax_type", "fieldtype": "Select", @@ -33,6 +35,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "column_break_1", "fieldtype": "Column Break", "hidden": 0, @@ -52,6 +56,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "depends_on": "eval:doc.tax_type==\"Sales\"", "fieldname": "sales_tax_template", "fieldtype": "Link", @@ -74,6 +80,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "depends_on": "eval:doc.tax_type==\"Purchase\"", "fieldname": "purchase_tax_template", "fieldtype": "Link", @@ -96,6 +104,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "filters", "fieldtype": "Section Break", "hidden": 0, @@ -116,6 +126,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "depends_on": "eval:doc.tax_type==\"Sales\"", "fieldname": "customer", "fieldtype": "Link", @@ -138,6 +150,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "depends_on": "eval:doc.tax_type==\"Purchase\"", "fieldname": "supplier", "fieldtype": "Link", @@ -160,6 +174,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "billing_city", "fieldtype": "Data", "hidden": 0, @@ -180,6 +196,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "billing_country", "fieldtype": "Link", "hidden": 0, @@ -201,6 +219,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "column_break_2", "fieldtype": "Column Break", "hidden": 0, @@ -220,6 +240,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "depends_on": "eval:doc.tax_type==\"Sales\"", "fieldname": "customer_group", "fieldtype": "Link", @@ -242,6 +264,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "depends_on": "eval:doc.tax_type==\"Purchase\"", "fieldname": "supplier_type", "fieldtype": "Link", @@ -264,6 +288,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "shipping_city", "fieldtype": "Data", "hidden": 0, @@ -284,6 +310,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "shipping_country", "fieldtype": "Link", "hidden": 0, @@ -305,6 +333,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "section_break_4", "fieldtype": "Section Break", "hidden": 0, @@ -325,6 +355,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "from_date", "fieldtype": "Date", "hidden": 0, @@ -345,6 +377,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "column_break_7", "fieldtype": "Column Break", "hidden": 0, @@ -364,6 +398,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "to_date", "fieldtype": "Date", "hidden": 0, @@ -384,6 +420,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "section_break_6", "fieldtype": "Section Break", "hidden": 0, @@ -403,6 +441,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "default": "1", "fieldname": "priority", "fieldtype": "Int", @@ -424,6 +464,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "column_break_20", "fieldtype": "Column Break", "hidden": 0, @@ -443,6 +485,8 @@ }, { "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -470,7 +514,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-08-21 03:27:43.564183", + "modified": "2015-08-28 02:56:51.283291", "modified_by": "Administrator", "module": "Accounts", "name": "Tax Rule", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index b092037b71..f6b6b31f38 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -1609,6 +1609,7 @@ { "allow_on_submit": 0, "bold": 0, +<<<<<<< HEAD "collapsible": 1, "fieldname": "column_break5", "fieldtype": "Section Break", diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index ce68370d13..ec7dd5e1a2 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -12,6 +12,7 @@ "document_type": "Setup", "fields": [ { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -32,9 +33,32 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "basic_info", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "", + "no_copy": 0, + "oldfieldtype": "Section Break", + "options": "icon-user", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -56,9 +80,33 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "naming_series", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Series", + "no_copy": 1, + "oldfieldname": "naming_series", + "oldfieldtype": "Select", + "options": "SUPP-", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -79,9 +127,32 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "supplier_name", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Supplier Name", + "no_copy": 1, + "oldfieldname": "supplier_name", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -100,9 +171,30 @@ "search_index": 0, "set_only_once": 0, "unique": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break0", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "width": "50%" }, { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -124,9 +216,33 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "supplier_type", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Supplier Type", + "no_copy": 0, + "oldfieldname": "supplier_type", + "oldfieldtype": "Link", + "options": "Supplier Type", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -146,9 +262,31 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "is_frozen", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Is Frozen", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -167,9 +305,33 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:!doc.__islocal", + "fieldname": "address_contacts", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Address & Contacts", + "no_copy": 0, + "oldfieldtype": "Column Break", + "options": "icon-map-marker", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -189,9 +351,30 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "address_html", + "fieldtype": "HTML", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Address HTML", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -254,9 +437,51 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break1", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0, + "width": "50%" + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "contact_html", + "fieldtype": "HTML", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Contact HTML", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -275,9 +500,30 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "default_payable_accounts", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Default Payable Accounts", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { +<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -299,6 +545,29 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, +======= + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:!doc.__islocal", + "description": "Mention if non-standard receivable account applicable", + "fieldname": "accounts", + "fieldtype": "Table", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Accounts", + "no_copy": 0, + "options": "Party Account", + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, +>>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py index f32aeed022..71a2d700a6 100644 --- a/erpnext/config/accounts.py +++ b/erpnext/config/accounts.py @@ -106,6 +106,11 @@ def get_data(): "name": "Accounts Settings", "description": _("Default settings for accounting transactions.") }, + { + "type": "doctype", + "name": "Tax Rule", + "description": _("Tax Rule for transactions.") + }, { "type": "doctype", "name": "Sales Taxes and Charges Template", From def71d4d5dddc2ac19428c45d228fa50721450f2 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Fri, 11 Sep 2015 11:14:07 +0530 Subject: [PATCH 07/16] [Shopping Cart][Fixes] tax calculation based on tax rule --- erpnext/accounts/doctype/tax_rule/tax_rule.js | 18 ++++++++ .../accounts/doctype/tax_rule/tax_rule.json | 24 +++++++++- erpnext/accounts/party.py | 6 ++- erpnext/shopping_cart/cart.py | 15 ++++--- .../shopping_cart_settings.json | 44 +------------------ .../shopping_cart_settings.py | 22 +++++----- 6 files changed, 68 insertions(+), 61 deletions(-) diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.js b/erpnext/accounts/doctype/tax_rule/tax_rule.js index d4a10aaec3..4b059dc564 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.js +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.js @@ -7,6 +7,24 @@ cur_frm.add_fetch("supplier", "supplier_type", "supplier_type" ); cur_frm.toggle_reqd("sales_tax_template", cur_frm.doc.tax_type=="Sales"); cur_frm.toggle_reqd("purchase_tax_template", cur_frm.doc.tax_type=="Purchase"); + +frappe.ui.form.on("Tax Rule", "onload", function(frm) { + if(frm.doc.__islocal){ + frm.set_value("use_for_shopping_cart", 1); + } +}) + +frappe.ui.form.on("Tax Rule", "use_for_shopping_cart", function(frm) { + if(!frm.doc.use_for_shopping_cart && (frappe.get_list("Tax Rule", {"use_for_shopping_cart":1}).length == 0)){ + frappe.model.get_value("Shopping Cart Settings", "Shopping Cart Settings", "enabled", function(docfield) { + if(docfield.enabled){ + frm.set_value("use_for_shopping_cart", 1); + frappe.throw(__("Shopping Cart is enabled")); + } + }); + } +}) + frappe.ui.form.on("Tax Rule", "customer", function(frm) { frappe.call({ method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details", diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.json b/erpnext/accounts/doctype/tax_rule/tax_rule.json index 1974440692..61d4d1d04a 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.json +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.json @@ -33,6 +33,28 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "use_for_shopping_cart", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Use for Shopping Cart", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -514,7 +536,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-08-28 02:56:51.283291", + "modified": "2015-09-10 19:27:47.969867", "modified_by": "Administrator", "module": "Accounts", "name": "Tax Rule", diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index a6b5c78cad..d830a20bf6 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -278,7 +278,7 @@ def validate_due_date(posting_date, due_date, party_type, party, company): frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date))) @frappe.whitelist() -def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_type=None, billing_address=None, shipping_address=None): +def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_type=None, billing_address=None, shipping_address=None, for_shopping_cart=None): from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details args = { party_type: party, @@ -296,4 +296,8 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup args.update({"tax_type": "Sales"}) else: args.update({"tax_type": "Purchase"}) + + if for_shopping_cart: + args.update({"use_for_shopping_cart": for_shopping_cart}) + return get_tax_template(posting_date, args) \ No newline at end of file diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index cfba98b4ab..78fd6ba141 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -266,12 +266,16 @@ def _set_price_list(quotation, cart_settings, billing_territory): def set_taxes(quotation, cart_settings, billing_territory): """set taxes based on billing territory""" - quotation.taxes_and_charges = cart_settings.get_tax_master(billing_territory) - - # clear table + from erpnext.accounts.party import set_taxes + + quotation.taxes_and_charges = set_taxes(quotation.customer, "Customer", \ + quotation.transaction_date, quotation.company, None, None, \ + quotation.customer_address, quotation.shipping_address_name, 1) +# +# # clear table quotation.set("taxes", []) - - # append taxes +# +# # append taxes quotation.append_taxes_from_master() def get_lead_or_customer(): @@ -357,6 +361,7 @@ def get_shipping_rules(party=None, quotation=None, cart_settings=None): shipping_territory = get_address_territory(quotation.shipping_address_name) or \ party.territory + shipping_rules = cart_settings.get_shipping_rules(shipping_territory) return shipping_rules diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json index 818550e75f..873120f7e1 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json @@ -221,48 +221,6 @@ "search_index": 0, "set_only_once": 0, "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "column_break_10", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "sales_taxes_and_charges_masters", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Taxes and Charges", - "no_copy": 0, - "options": "Shopping Cart Taxes and Charges Master", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 } ], "hide_heading": 0, @@ -274,7 +232,7 @@ "is_submittable": 0, "issingle": 1, "istable": 0, - "modified": "2015-02-05 05:11:46.714019", + "modified": "2015-09-10 19:05:17.386135", "modified_by": "Administrator", "module": "Shopping Cart", "name": "Shopping Cart Settings", diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py index 8fbf4a430e..425c6d6a9f 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py @@ -20,15 +20,15 @@ class ShoppingCartSettings(Document): def validate(self): if self.enabled: self.validate_price_lists() - self.validate_tax_masters() self.validate_exchange_rates_exist() - + self.validate_tax_rule() + def validate_overlapping_territories(self, parentfield, fieldname): # for displaying message doctype = self.meta.get_field(parentfield).options # specify atleast one entry in the table - self.validate_table_has_rows(parentfield, raise_exception=ShoppingCartSetupError) + # self.validate_table_has_rows(parentfield, raise_exception=ShoppingCartSetupError) territory_name_map = self.get_territory_name_map(parentfield, fieldname) for territory, names in territory_name_map.items(): @@ -48,20 +48,14 @@ class ShoppingCartSettings(Document): msgprint(_("Please specify a Price List which is valid for Territory") + ": " + self.default_territory, raise_exception=ShoppingCartSetupError) - def validate_tax_masters(self): - self.validate_overlapping_territories("sales_taxes_and_charges_masters", - "sales_taxes_and_charges_master") - def get_territory_name_map(self, parentfield, fieldname): territory_name_map = {} # entries in table names = [doc.get(fieldname) for doc in self.get(parentfield)] - if names: # for condition in territory check parenttype = frappe.get_meta(self.meta.get_options(parentfield)).get_options(fieldname) - # to validate territory overlap # make a map of territory: [list of names] # if list against each territory has more than one element, raise exception @@ -75,7 +69,6 @@ class ShoppingCartSettings(Document): if len(territory_name_map[territory]) > 1: territory_name_map[territory].sort(key=lambda val: names.index(val)) - return territory_name_map def validate_exchange_rates_exist(self): @@ -131,7 +124,11 @@ class ShoppingCartSettings(Document): "price_lists", "selling_price_list") return price_list and price_list[0] or None - + + def validate_tax_rule(self): + if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart" : 1}, "name", debug=1): + frappe.throw(frappe._("Set Tax Rule for shopping cart"), ShoppingCartSetupError) + def get_tax_master(self, billing_territory): tax_master = self.get_name_from_territory(billing_territory, "sales_taxes_and_charges_masters", "sales_taxes_and_charges_master") @@ -170,6 +167,9 @@ def check_shopping_cart_enabled(): def apply_shopping_cart_settings(quotation, method): """Called via a validate hook on Quotation""" + + """no hooks call added yet. same functionality is in cart.py, which will get triggered by cart.js""" + from erpnext.shopping_cart import get_party if quotation.order_type != "Shopping Cart": return From 957e7a37be8e71f18ea78971d64c5c8932bd211d Mon Sep 17 00:00:00 2001 From: Saurabh Date: Fri, 11 Sep 2015 15:44:06 +0530 Subject: [PATCH 08/16] [Shopping Cart][Fixes] tax calculation based on tax rule --- erpnext/accounts/doctype/tax_rule/tax_rule.py | 2 +- erpnext/accounts/party.py | 12 ++-- .../shopping_cart_settings.py | 2 +- .../test_shopping_cart_settings.py | 32 ++++------- erpnext/shopping_cart/test_shopping_cart.py | 55 ++++++++++++++++--- 5 files changed, 68 insertions(+), 35 deletions(-) diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index 705a26e771..ddd2a20013 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -115,7 +115,7 @@ def get_tax_template(posting_date, args): conditions.append("ifnull({0}, '') in ('', '{1}')".format(key, frappe.db.escape(cstr(value)))) matching = frappe.db.sql("""select * from `tabTax Rule` - where {0}""".format(" and ".join(conditions)), as_dict = True) + where {0}""".format(" and ".join(conditions)), as_dict = True, debug=True) if not matching: return None diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index d830a20bf6..edb362560f 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -278,7 +278,9 @@ def validate_due_date(posting_date, due_date, party_type, party, company): frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date))) @frappe.whitelist() -def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_type=None, billing_address=None, shipping_address=None, for_shopping_cart=None): +def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_type=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 = { party_type: party, @@ -288,7 +290,8 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup } if billing_address or shipping_address: - args.update(get_party_details(party, party_type, {"billing_address": billing_address, "shipping_address": shipping_address })) + args.update(get_party_details(party, party_type, {"billing_address": billing_address, \ + "shipping_address": shipping_address })) else: args.update(get_party_details(party, party_type)) @@ -297,7 +300,8 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup else: args.update({"tax_type": "Purchase"}) - if for_shopping_cart: - args.update({"use_for_shopping_cart": for_shopping_cart}) + if use_for_shopping_cart: + print "use_for_shopping_cart", use_for_shopping_cart + args.update({"use_for_shopping_cart": use_for_shopping_cart}) return get_tax_template(posting_date, args) \ No newline at end of file diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py index 425c6d6a9f..35f21dc3f7 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py @@ -126,7 +126,7 @@ class ShoppingCartSettings(Document): return price_list and price_list[0] or None def validate_tax_rule(self): - if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart" : 1}, "name", debug=1): + if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart" : 1}, "name"): frappe.throw(frappe._("Set Tax Rule for shopping cart"), ShoppingCartSetupError) def get_tax_master(self, billing_territory): diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py index 46cbfdf9ed..23d74fa0bb 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py @@ -43,28 +43,6 @@ class TestShoppingCartSettings(unittest.TestCase): return cart_settings - def test_taxes_territory_overlap(self): - cart_settings = self.get_cart_settings() - - def _add_tax_master(tax_master): - cart_settings.append("sales_taxes_and_charges_masters", { - "doctype": "Shopping Cart Taxes and Charges Master", - "sales_taxes_and_charges_master": tax_master - }) - - for tax_master in ("_Test Sales Taxes and Charges Template", "_Test India Tax Master"): - _add_tax_master(tax_master) - - controller = cart_settings - controller.validate_overlapping_territories("sales_taxes_and_charges_masters", - "sales_taxes_and_charges_master") - - _add_tax_master("_Test Sales Taxes and Charges Template - Rest of the World") - - controller = cart_settings - self.assertRaises(ShoppingCartSetupError, controller.validate_overlapping_territories, - "sales_taxes_and_charges_masters", "sales_taxes_and_charges_master") - def test_exchange_rate_exists(self): frappe.db.sql("""delete from `tabCurrency Exchange`""") @@ -77,3 +55,13 @@ class TestShoppingCartSettings(unittest.TestCase): frappe.get_doc(currency_exchange_records[0]).insert() controller.validate_exchange_rates_exist() + def test_tax_rule_validation(self): + frappe.db.sql("update `tabTax Rule` set use_for_shopping_cart = 0") + frappe.db.commit() + + cart_settings = self.get_cart_settings() + cart_settings.enabled = 1 + if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart": 1}, "name"): + print "here" + self.assertRaises(ShoppingCartSetupError, cart_settings.validate_tax_rule) + diff --git a/erpnext/shopping_cart/test_shopping_cart.py b/erpnext/shopping_cart/test_shopping_cart.py index 1873b813be..086100c821 100644 --- a/erpnext/shopping_cart/test_shopping_cart.py +++ b/erpnext/shopping_cart/test_shopping_cart.py @@ -109,6 +109,54 @@ class TestShoppingCart(unittest.TestCase): quotation = self.test_get_cart_lead() self.assertEquals(quotation.net_total, 0) self.assertEquals(len(quotation.get("items")), 0) + + def test_taxe_rule(self): + frappe.set_user("Administrator") + self.create_tax_rule() + quotation = self.test_get_cart_customer() + set_item_in_cart("_Test Item", 1) + + 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) + + self.assertEquals(quotation.taxes_and_charges, tax_rule_master) + self.assertEquals(quotation.total_taxes_and_charges, "1000") + + def create_tax_rule(self): + for tax_rule_setting in [{"priority": 1, "use_for_shopping_cart": 1}, {"priority": 2, "use_for_shopping_cart": 0}]: + tax_template = self.get_tax_template(tax_rule_setting['priority']).name + print tax_template + tax_rule = frappe.get_doc({ + "doctype": "Tax Rule", + "tax_type" : "Sales", + "sales_tax_template": tax_template, + "use_for_shopping_cart": tax_rule_setting["use_for_shopping_cart"], + "billing_city": "_Test City", + "billing_country": "India", + "shipping_city": "_Test City", + "shipping_country": "India", + "priority": tax_rule_setting['priority'] + }).insert() + + def get_tax_template(self, priority): + return frappe.get_doc({ + "doctype" : "Sales Taxes and Charges Template", + "title": "_Test Tax %s"%priority, + "company": "_Test Company", + "taxes":[{ + "charge_type": "Actual", + "account_head": "Sales Expenses - _TC", + "cost_center": "Main - _TC", + "description": "Test Shopping cart taxes with Tax Rule", + "tax_amount": 1000*priority + }], + "territories":[{ + "territory" : "All Territories" + }] + }).insert() # helper functions def enable_shopping_cart(self): @@ -131,13 +179,6 @@ class TestShoppingCart(unittest.TestCase): {"doctype": "Shopping Cart Price List", "parentfield": "price_lists", "selling_price_list": "_Test Price List Rest of the World"} ]) - settings.set("sales_taxes_and_charges_masters", [ - # tax masters - {"doctype": "Shopping Cart Taxes and Charges Master", "parentfield": "sales_taxes_and_charges_masters", - "sales_taxes_and_charges_master": "_Test India Tax Master"}, - {"doctype": "Shopping Cart Taxes and Charges Master", "parentfield": "sales_taxes_and_charges_masters", - "sales_taxes_and_charges_master": "_Test Sales Taxes and Charges Template - Rest of the World"}, - ]) settings.set("shipping_rules", {"doctype": "Shopping Cart Shipping Rule", "parentfield": "shipping_rules", "shipping_rule": "_Test Shipping Rule - India"}) From 8f7317175da1179fb8a258d8dbd9a05e6bd78a5c Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 14 Sep 2015 11:13:01 +0530 Subject: [PATCH 09/16] [enhancement] bring taxes from tax rules and test cases --- erpnext/accounts/doctype/tax_rule/tax_rule.py | 2 +- erpnext/accounts/party.py | 1 - erpnext/shopping_cart/__init__.py | 1 + erpnext/shopping_cart/cart.py | 7 +- .../shopping_cart_settings.json | 23 ++++++- .../shopping_cart_settings.py | 56 +-------------- .../test_shopping_cart_settings.py | 1 - erpnext/shopping_cart/test_shopping_cart.py | 69 +++++++++++++------ 8 files changed, 79 insertions(+), 81 deletions(-) diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index ddd2a20013..705a26e771 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -115,7 +115,7 @@ def get_tax_template(posting_date, args): conditions.append("ifnull({0}, '') in ('', '{1}')".format(key, frappe.db.escape(cstr(value)))) matching = frappe.db.sql("""select * from `tabTax Rule` - where {0}""".format(" and ".join(conditions)), as_dict = True, debug=True) + where {0}""".format(" and ".join(conditions)), as_dict = True) if not matching: return None diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index edb362560f..8ad30583e1 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -301,7 +301,6 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup args.update({"tax_type": "Purchase"}) if use_for_shopping_cart: - print "use_for_shopping_cart", use_for_shopping_cart args.update({"use_for_shopping_cart": use_for_shopping_cart}) return get_tax_template(posting_date, args) \ No newline at end of file diff --git a/erpnext/shopping_cart/__init__.py b/erpnext/shopping_cart/__init__.py index 1858c0d842..e92f94e9a7 100644 --- a/erpnext/shopping_cart/__init__.py +++ b/erpnext/shopping_cart/__init__.py @@ -35,6 +35,7 @@ def get_quotation(user=None): quotation = frappe.new_doc("Quotation") quotation.update(values) if party.doctype == "Customer": + print "create quoation for cutomer" quotation.contact_person = frappe.db.get_value("Contact", {"customer": party.name, "email_id": user}) quotation.insert(ignore_permissions=True) diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index 78fd6ba141..30f4aba493 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -267,9 +267,11 @@ def _set_price_list(quotation, cart_settings, billing_territory): def set_taxes(quotation, cart_settings, billing_territory): """set taxes based on billing territory""" from erpnext.accounts.party import set_taxes - + + 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, None, None, \ + quotation.transaction_date, quotation.company, customer_group, None, \ quotation.customer_address, quotation.shipping_address_name, 1) # # # clear table @@ -361,7 +363,6 @@ def get_shipping_rules(party=None, quotation=None, cart_settings=None): shipping_territory = get_address_territory(quotation.shipping_address_name) or \ party.territory - shipping_rules = cart_settings.get_shipping_rules(shipping_territory) return shipping_rules diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json index 873120f7e1..881ff4e377 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json @@ -200,6 +200,27 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "column_break_10", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -232,7 +253,7 @@ "is_submittable": 0, "issingle": 1, "istable": 0, - "modified": "2015-09-10 19:05:17.386135", + "modified": "2015-09-11 19:03:54.750937", "modified_by": "Administrator", "module": "Shopping Cart", "name": "Shopping Cart Settings", diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py index 35f21dc3f7..da7d27af10 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py @@ -28,7 +28,7 @@ class ShoppingCartSettings(Document): doctype = self.meta.get_field(parentfield).options # specify atleast one entry in the table - # self.validate_table_has_rows(parentfield, raise_exception=ShoppingCartSetupError) + self.validate_table_has_rows(parentfield, raise_exception=ShoppingCartSetupError) territory_name_map = self.get_territory_name_map(parentfield, fieldname) for territory, names in territory_name_map.items(): @@ -105,7 +105,6 @@ class ShoppingCartSettings(Document): def get_name_from_territory(self, territory, parentfield, fieldname): name = None territory_name_map = self.get_territory_name_map(parentfield, fieldname) - if territory_name_map.get(territory): name = territory_name_map.get(territory) else: @@ -164,55 +163,4 @@ def get_default_territory(): def check_shopping_cart_enabled(): if not get_shopping_cart_settings().enabled: frappe.throw(_("You need to enable Shopping Cart"), ShoppingCartSetupError) - -def apply_shopping_cart_settings(quotation, method): - """Called via a validate hook on Quotation""" - - """no hooks call added yet. same functionality is in cart.py, which will get triggered by cart.js""" - - from erpnext.shopping_cart import get_party - if quotation.order_type != "Shopping Cart": - return - - quotation.billing_territory = (get_territory_from_address(quotation.customer_address) - or get_party(quotation.contact_email).territory or get_default_territory()) - quotation.shipping_territory = (get_territory_from_address(quotation.shipping_address_name) - or get_party(quotation.contact_email).territory or get_default_territory()) - - set_price_list(quotation) - set_taxes_and_charges(quotation) - quotation.calculate_taxes_and_totals() - set_shipping_rule(quotation) - -def set_price_list(quotation): - previous_selling_price_list = quotation.selling_price_list - quotation.selling_price_list = get_shopping_cart_settings().get_price_list(quotation.billing_territory) - - if not quotation.selling_price_list: - quotation.selling_price_list = get_shopping_cart_settings().get_price_list(get_default_territory()) - - if previous_selling_price_list != quotation.selling_price_list: - quotation.price_list_currency = quotation.currency = quotation.plc_conversion_rate = quotation.conversion_rate = None - for d in quotation.get("items"): - d.price_list_rate = d.discount_percentage = d.rate = d.amount = None - - quotation.set_price_list_and_item_details() - -def set_taxes_and_charges(quotation): - previous_taxes_and_charges = quotation.taxes_and_charges - quotation.taxes_and_charges = get_shopping_cart_settings().get_tax_master(quotation.billing_territory) - - if previous_taxes_and_charges != quotation.taxes_and_charges: - quotation.set_other_charges() - -def set_shipping_rule(quotation): - shipping_rules = get_shopping_cart_settings().get_shipping_rules(quotation.shipping_territory) - if not shipping_rules: - quotation.remove_shipping_charge() - return - - if quotation.shipping_rule not in shipping_rules: - quotation.remove_shipping_charge() - quotation.shipping_rule = shipping_rules[0] - - quotation.apply_shipping_rule() + diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py index 23d74fa0bb..b38072c5fb 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py @@ -62,6 +62,5 @@ class TestShoppingCartSettings(unittest.TestCase): cart_settings = self.get_cart_settings() cart_settings.enabled = 1 if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart": 1}, "name"): - print "here" self.assertRaises(ShoppingCartSetupError, cart_settings.validate_tax_rule) diff --git a/erpnext/shopping_cart/test_shopping_cart.py b/erpnext/shopping_cart/test_shopping_cart.py index 086100c821..c0945a1c4f 100644 --- a/erpnext/shopping_cart/test_shopping_cart.py +++ b/erpnext/shopping_cart/test_shopping_cart.py @@ -4,7 +4,8 @@ from __future__ import unicode_literals import unittest import frappe -from erpnext.shopping_cart import get_quotation, set_item_in_cart +from erpnext.shopping_cart import get_quotation, set_item_in_cart, get_party +import random class TestShoppingCart(unittest.TestCase): """ @@ -110,42 +111,42 @@ class TestShoppingCart(unittest.TestCase): self.assertEquals(quotation.net_total, 0) self.assertEquals(len(quotation.get("items")), 0) - def test_taxe_rule(self): - frappe.set_user("Administrator") + + def test_taxe_rule(self): self.create_tax_rule() - quotation = self.test_get_cart_customer() - set_item_in_cart("_Test Item", 1) - + self.login_as_customer() + quotation = self.create_quotation() + 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) - + self.assertEquals(quotation.taxes_and_charges, tax_rule_master) - self.assertEquals(quotation.total_taxes_and_charges, "1000") + self.assertEquals(quotation.total_taxes_and_charges, 1000.0) def create_tax_rule(self): for tax_rule_setting in [{"priority": 1, "use_for_shopping_cart": 1}, {"priority": 2, "use_for_shopping_cart": 0}]: tax_template = self.get_tax_template(tax_rule_setting['priority']).name - print tax_template tax_rule = frappe.get_doc({ - "doctype": "Tax Rule", - "tax_type" : "Sales", - "sales_tax_template": tax_template, - "use_for_shopping_cart": tax_rule_setting["use_for_shopping_cart"], - "billing_city": "_Test City", - "billing_country": "India", - "shipping_city": "_Test City", - "shipping_country": "India", - "priority": tax_rule_setting['priority'] + "doctype": "Tax Rule", + "tax_type" : "Sales", + "sales_tax_template": tax_template, + "use_for_shopping_cart": tax_rule_setting["use_for_shopping_cart"], + "billing_city": "_Test City", + "billing_country": "India", + "shipping_city": "_Test City", + "shipping_country": "India", + "priority": tax_rule_setting['priority'], + "company": frappe.get_value("Global Defaults", "Global Defaults", "default_company") }).insert() def get_tax_template(self, priority): return frappe.get_doc({ "doctype" : "Sales Taxes and Charges Template", "title": "_Test Tax %s"%priority, - "company": "_Test Company", + "company": frappe.get_value("Global Defaults", "Global Defaults", "default_company"), "taxes":[{ "charge_type": "Actual", "account_head": "Sales Expenses - _TC", @@ -157,6 +158,34 @@ class TestShoppingCart(unittest.TestCase): "territory" : "All Territories" }] }).insert() + + def create_quotation(self): + quotation = frappe.new_doc("Quotation") + + values = { + "doctype": "Quotation", + "quotation_to": "Customer", + "order_type": "Shopping Cart", + "customer": get_party(frappe.session.user).name, + "docstatus": 0, + "contact_email": frappe.session.user, + "selling_price_list": "_Test Price List Rest of the World", + "currency": "USD", + "taxes_and_charges" : "_Test Tax 1", + "items": [{ + "item_code": "_Test Item", + "qty": 1 + }], + "taxes": frappe.get_doc("Sales Taxes and Charges Template", "_Test Tax 1").taxes + } + + quotation.update(values) + + quotation.insert(ignore_permissions=True) + + frappe.reload_doc("selling", "Quotation", quotation.name) + + return quotation # helper functions def enable_shopping_cart(self): From 7c867ae9ad04df6f62f232cdf14e572baad3c02b Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 14 Sep 2015 16:59:10 +0530 Subject: [PATCH 10/16] [Fixes] Tax Rule preparation and test taxes creation, remove dummy quotation --- .../test_records.json | 30 +++++++++++ .../doctype/tax_rule/test_records.json | 26 ++++++++++ erpnext/controllers/accounts_controller.py | 1 + erpnext/shopping_cart/__init__.py | 1 - .../__init__.py | 0 ...hopping_cart_taxes_and_charges_master.json | 49 ----------------- .../shopping_cart_taxes_and_charges_master.py | 12 ----- erpnext/shopping_cart/test_shopping_cart.py | 52 ++++--------------- 8 files changed, 68 insertions(+), 103 deletions(-) create mode 100644 erpnext/accounts/doctype/tax_rule/test_records.json delete mode 100644 erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/__init__.py delete mode 100644 erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.json delete mode 100644 erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.py diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json b/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json index 5c25517f7f..69dbd8e9a6 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_records.json @@ -213,5 +213,35 @@ "territory": "_Test Territory Rest Of The World" } ] + }, + { + "doctype" : "Sales Taxes and Charges Template", + "title": "_Test Tax 1", + "company": "_Test Company", + "taxes":[{ + "charge_type": "Actual", + "account_head": "Sales Expenses - _TC", + "cost_center": "Main - _TC", + "description": "Test Shopping cart taxes with Tax Rule", + "tax_amount": 1000 + }], + "territories":[{ + "territory" : "All Territories" + }] + }, + { + "doctype" : "Sales Taxes and Charges Template", + "title": "_Test Tax 2", + "company": "_Test Company", + "taxes":[{ + "charge_type": "Actual", + "account_head": "Sales Expenses - _TC", + "cost_center": "Main - _TC", + "description": "Test Shopping cart taxes with Tax Rule", + "tax_amount": 200 + }], + "territories":[{ + "territory" : "All Territories" + }] } ] diff --git a/erpnext/accounts/doctype/tax_rule/test_records.json b/erpnext/accounts/doctype/tax_rule/test_records.json new file mode 100644 index 0000000000..ebfb0c5b1b --- /dev/null +++ b/erpnext/accounts/doctype/tax_rule/test_records.json @@ -0,0 +1,26 @@ +[ + { + "doctype": "Tax Rule", + "tax_type" : "Sales", + "sales_tax_template": "_Test Tax 1", + "use_for_shopping_cart": 1, + "billing_city": "_Test City", + "billing_country": "India", + "shipping_city": "_Test City", + "shipping_country": "India", + "priority": 1, + "company": "_Test Company" + }, + { + "doctype": "Tax Rule", + "tax_type" : "Sales", + "sales_tax_template": "_Test Tax 2", + "use_for_shopping_cart": 0, + "billing_city": "_Test City", + "billing_country": "India", + "shipping_city": "_Test City", + "shipping_country": "India", + "priority": 2, + "company": "_Test Company" + } +] \ No newline at end of file diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index ceb993096a..8c61005a71 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -182,6 +182,7 @@ class AccountsController(TransactionBase): self.append_taxes_from_master(tax_master_doctype) def append_taxes_from_master(self, tax_master_doctype=None): + print "append_taxes_from_master" if self.get("taxes_and_charges"): if not tax_master_doctype: tax_master_doctype = self.meta.get_field("taxes_and_charges").options diff --git a/erpnext/shopping_cart/__init__.py b/erpnext/shopping_cart/__init__.py index e92f94e9a7..1858c0d842 100644 --- a/erpnext/shopping_cart/__init__.py +++ b/erpnext/shopping_cart/__init__.py @@ -35,7 +35,6 @@ def get_quotation(user=None): quotation = frappe.new_doc("Quotation") quotation.update(values) if party.doctype == "Customer": - print "create quoation for cutomer" quotation.contact_person = frappe.db.get_value("Contact", {"customer": party.name, "email_id": user}) quotation.insert(ignore_permissions=True) diff --git a/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/__init__.py b/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.json b/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.json deleted file mode 100644 index e15dcab5af..0000000000 --- a/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "allow_copy": 0, - "allow_import": 0, - "allow_rename": 0, - "creation": "2013-06-20 16:57:03", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "fields": [ - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "sales_taxes_and_charges_master", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Tax Master", - "no_copy": 0, - "options": "Sales Taxes and Charges Template", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - } - ], - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 1, - "in_create": 0, - "in_dialog": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "modified": "2013-12-20 19:30:47", - "modified_by": "Administrator", - "module": "Shopping Cart", - "name": "Shopping Cart Taxes and Charges Master", - "owner": "Administrator", - "permissions": [], - "read_only": 0, - "read_only_onload": 0 -} \ No newline at end of file diff --git a/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.py b/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.py deleted file mode 100644 index d2ec545c7e..0000000000 --- a/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.py +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe - -from frappe.model.document import Document - -class ShoppingCartTaxesandChargesMaster(Document): - pass diff --git a/erpnext/shopping_cart/test_shopping_cart.py b/erpnext/shopping_cart/test_shopping_cart.py index c0945a1c4f..bd0b138d45 100644 --- a/erpnext/shopping_cart/test_shopping_cart.py +++ b/erpnext/shopping_cart/test_shopping_cart.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals import unittest import frappe from erpnext.shopping_cart import get_quotation, set_item_in_cart, get_party -import random class TestShoppingCart(unittest.TestCase): """ @@ -113,10 +112,9 @@ class TestShoppingCart(unittest.TestCase): def test_taxe_rule(self): - self.create_tax_rule() self.login_as_customer() quotation = self.create_quotation() - + from erpnext.accounts.party import set_taxes tax_rule_master = set_taxes(quotation.customer, "Customer", \ @@ -126,38 +124,7 @@ class TestShoppingCart(unittest.TestCase): self.assertEquals(quotation.taxes_and_charges, tax_rule_master) self.assertEquals(quotation.total_taxes_and_charges, 1000.0) - def create_tax_rule(self): - for tax_rule_setting in [{"priority": 1, "use_for_shopping_cart": 1}, {"priority": 2, "use_for_shopping_cart": 0}]: - tax_template = self.get_tax_template(tax_rule_setting['priority']).name - tax_rule = frappe.get_doc({ - "doctype": "Tax Rule", - "tax_type" : "Sales", - "sales_tax_template": tax_template, - "use_for_shopping_cart": tax_rule_setting["use_for_shopping_cart"], - "billing_city": "_Test City", - "billing_country": "India", - "shipping_city": "_Test City", - "shipping_country": "India", - "priority": tax_rule_setting['priority'], - "company": frappe.get_value("Global Defaults", "Global Defaults", "default_company") - }).insert() - - def get_tax_template(self, priority): - return frappe.get_doc({ - "doctype" : "Sales Taxes and Charges Template", - "title": "_Test Tax %s"%priority, - "company": frappe.get_value("Global Defaults", "Global Defaults", "default_company"), - "taxes":[{ - "charge_type": "Actual", - "account_head": "Sales Expenses - _TC", - "cost_center": "Main - _TC", - "description": "Test Shopping cart taxes with Tax Rule", - "tax_amount": 1000*priority - }], - "territories":[{ - "territory" : "All Territories" - }] - }).insert() + self.remove_test_quotation(quotation) def create_quotation(self): quotation = frappe.new_doc("Quotation") @@ -176,16 +143,19 @@ class TestShoppingCart(unittest.TestCase): "item_code": "_Test Item", "qty": 1 }], - "taxes": frappe.get_doc("Sales Taxes and Charges Template", "_Test Tax 1").taxes + "taxes": frappe.get_doc("Sales Taxes and Charges Template", "_Test Tax 1").taxes, + "company": "_Test Company" } quotation.update(values) quotation.insert(ignore_permissions=True) - frappe.reload_doc("selling", "Quotation", quotation.name) - return quotation + + def remove_test_quotation(self, quotation): + frappe.set_user("Administrator") + quotation.delete() # helper functions def enable_shopping_cart(self): @@ -210,6 +180,7 @@ class TestShoppingCart(unittest.TestCase): ]) settings.set("shipping_rules", {"doctype": "Shopping Cart Shipping Rule", "parentfield": "shipping_rules", "shipping_rule": "_Test Shipping Rule - India"}) + settings.save() frappe.local.shopping_cart_settings = None @@ -273,7 +244,6 @@ class TestShoppingCart(unittest.TestCase): quotation = get_quotation() quotation.set("items", []) quotation.save(ignore_permissions=True) - - + test_dependencies = ["Sales Taxes and Charges Template", "Price List", "Item Price", "Shipping Rule", "Currency Exchange", - "Customer Group", "Lead", "Customer", "Contact", "Address", "Item"] + "Customer Group", "Lead", "Customer", "Contact", "Address", "Item", "Tax Rule"] From 24fa06bc53ddad1b6a40e71b352bdd7b1171ce74 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 14 Sep 2015 18:48:39 +0530 Subject: [PATCH 11/16] [Fixes] rebase conflict fixes --- .../purchase_order/purchase_order.json | 1 - erpnext/buying/doctype/supplier/supplier.json | 270 ------------------ 2 files changed, 271 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index f6b6b31f38..b092037b71 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -1609,7 +1609,6 @@ { "allow_on_submit": 0, "bold": 0, -<<<<<<< HEAD "collapsible": 1, "fieldname": "column_break5", "fieldtype": "Section Break", diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index ec7dd5e1a2..2a0a50d45d 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -1,5 +1,4 @@ { -<<<<<<< HEAD "allow_copy": 0, "allow_import": 1, "allow_rename": 1, @@ -12,7 +11,6 @@ "document_type": "Setup", "fields": [ { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -33,32 +31,9 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "basic_info", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "", - "no_copy": 0, - "oldfieldtype": "Section Break", - "options": "icon-user", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -80,33 +55,9 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "naming_series", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Series", - "no_copy": 1, - "oldfieldname": "naming_series", - "oldfieldtype": "Select", - "options": "SUPP-", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -127,32 +78,9 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "supplier_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Supplier Name", - "no_copy": 1, - "oldfieldname": "supplier_name", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -171,30 +99,9 @@ "search_index": 0, "set_only_once": 0, "unique": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "column_break0", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "width": "50%" }, { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -216,33 +123,9 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "supplier_type", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Supplier Type", - "no_copy": 0, - "oldfieldname": "supplier_type", - "oldfieldtype": "Link", - "options": "Supplier Type", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -262,31 +145,9 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "is_frozen", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Is Frozen", - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -305,33 +166,9 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "eval:!doc.__islocal", - "fieldname": "address_contacts", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Address & Contacts", - "no_copy": 0, - "oldfieldtype": "Column Break", - "options": "icon-map-marker", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -351,30 +188,9 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "address_html", - "fieldtype": "HTML", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Address HTML", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -437,51 +253,9 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "column_break1", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0, - "width": "50%" - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "contact_html", - "fieldtype": "HTML", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Contact HTML", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -500,30 +274,9 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "default_payable_accounts", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Default Payable Accounts", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { -<<<<<<< HEAD "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -545,29 +298,6 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, -======= - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "depends_on": "eval:!doc.__islocal", - "description": "Mention if non-standard receivable account applicable", - "fieldname": "accounts", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Accounts", - "no_copy": 0, - "options": "Party Account", - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, ->>>>>>> Added Tax Rule under ERPNext > Accounts > Setup "unique": 0 }, { From 052babc6b6c2d5bbfbe35c7839fbaacf86680343 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 14 Sep 2015 18:51:46 +0530 Subject: [PATCH 12/16] [Fixes] [Minor] removed console statement --- erpnext/controllers/accounts_controller.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 8c61005a71..ceb993096a 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -182,7 +182,6 @@ class AccountsController(TransactionBase): self.append_taxes_from_master(tax_master_doctype) def append_taxes_from_master(self, tax_master_doctype=None): - print "append_taxes_from_master" if self.get("taxes_and_charges"): if not tax_master_doctype: tax_master_doctype = self.meta.get_field("taxes_and_charges").options From bb9427d1efcefb850714d1dffa6ccc503e34edba Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 14 Sep 2015 19:15:16 +0530 Subject: [PATCH 13/16] [Fixes] deprecated --- .../shopping_cart_settings/test_shopping_cart_settings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py index b38072c5fb..b18cece44a 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py @@ -12,7 +12,6 @@ class TestShoppingCartSettings(unittest.TestCase): def setUp(self): frappe.db.sql("""delete from `tabSingles` where doctype="Shipping Cart Settings" """) frappe.db.sql("""delete from `tabShopping Cart Price List`""") - frappe.db.sql("""delete from `tabShopping Cart Taxes and Charges Master`""") frappe.db.sql("""delete from `tabShopping Cart Shipping Rule`""") def get_cart_settings(self): From adde1cff487d541370cb5cafbffb96fb6c3e09af Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 15 Sep 2015 12:49:32 +0530 Subject: [PATCH 14/16] [Enhancement] add state ccriteria in tax rule --- .../accounts/doctype/tax_rule/tax_rule.json | 46 ++++++++++++++++++- erpnext/accounts/doctype/tax_rule/tax_rule.py | 7 ++- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.json b/erpnext/accounts/doctype/tax_rule/tax_rule.json index 61d4d1d04a..60011dd9a3 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.json +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.json @@ -216,6 +216,28 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "billing_state", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Billing State", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -330,6 +352,28 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "shipping_state", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Shipping State", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -536,7 +580,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-09-10 19:27:47.969867", + "modified": "2015-09-15 12:29:34.435839", "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 705a26e771..93bbf459c3 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -94,16 +94,19 @@ def get_party_details(party, party_type, args=None): billing_filters= {party_type: party, "is_primary_address": 1} shipping_filters= {party_type:party, "is_shipping_address": 1} - billing_address= frappe.get_all("Address", fields=["city", "country"], filters= billing_filters) - shipping_address= frappe.get_all("Address", fields=["city", "country"], filters= shipping_filters) + billing_address= frappe.get_all("Address", fields=["city", "state", "country"], filters= billing_filters) + shipping_address= frappe.get_all("Address", fields=["city", "state", "country"], filters= shipping_filters) if billing_address: out["billing_city"]= billing_address[0].city + out["billing_state"]= billing_address[0].state out["billing_country"]= billing_address[0].country if shipping_address: out["shipping_city"]= shipping_address[0].city + out["shipping_state"]= shipping_address[0].state out["shipping_country"]= shipping_address[0].country + return out def get_tax_template(posting_date, args): From c663f5c2bd8bd524257ac077e1b3e1dd89cf3fd9 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 15 Sep 2015 15:36:21 +0530 Subject: [PATCH 15/16] [Test] test state based taxasion --- .../accounts/doctype/tax_rule/test_tax_rule.py | 18 ++++++++++++++---- erpnext/accounts/party.py | 1 - 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py index 9802c09600..85fbe52220 100644 --- a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py @@ -73,13 +73,23 @@ class TestTaxRule(unittest.TestCase): "_Test Sales Taxes and Charges Template 2") def test_select_tax_rule_based_on_better_match(self): - make_tax_rule(customer= "_Test Customer", billing_city = "Test City", + make_tax_rule(customer= "_Test Customer", billing_city = "Test City", billing_state = "Test State", sales_tax_template = "_Test Sales Taxes and Charges Template", save=1) - make_tax_rule(customer= "_Test Customer", + make_tax_rule(customer= "_Test Customer", billing_city = "Test City1", billing_state = "Test State", sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1) - self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}), + self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City", "billing_state": "Test State"}), + "_Test Sales Taxes and Charges Template") + + def test_select_tax_rule_based_on_state_match(self): + make_tax_rule(customer= "_Test Customer", shipping_state = "Test State", + sales_tax_template = "_Test Sales Taxes and Charges Template", save=1) + + make_tax_rule(customer= "_Test Customer", shipping_state = "Test State12", + sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1) + + self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "shipping_state": "Test State"}), "_Test Sales Taxes and Charges Template") def test_select_tax_rule_based_on_better_priority(self): @@ -93,7 +103,7 @@ class TestTaxRule(unittest.TestCase): "_Test Sales Taxes and Charges Template 1") def test_select_tax_rule_based_cross_matching_keys(self): - make_tax_rule(customer= "_Test Customer", billing_city = "Test City", + make_tax_rule(customer= "_Test Customer", billing_city = "Test City", sales_tax_template = "_Test Sales Taxes and Charges Template", save=1) make_tax_rule(customer= "_Test Customer 1", billing_city = "Test City 1", diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 8ad30583e1..a589a694dd 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -280,7 +280,6 @@ def validate_due_date(posting_date, due_date, party_type, party, company): @frappe.whitelist() def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_type=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 = { party_type: party, From 0bd145a6086638ff753e9a552cf51e52c60dc9e7 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 15 Sep 2015 17:06:52 +0530 Subject: [PATCH 16/16] [fixes] test cases and tax rule validation --- erpnext/accounts/doctype/tax_rule/tax_rule.py | 2 ++ erpnext/accounts/doctype/tax_rule/test_records.json | 2 ++ erpnext/accounts/doctype/tax_rule/test_tax_rule.py | 4 ++-- erpnext/utilities/doctype/address/test_records.json | 3 ++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index 93bbf459c3..0a9bb1114b 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -53,8 +53,10 @@ class TaxRule(Document): "supplier": self.supplier, "supplier_type": self.supplier_type, "billing_city": self.billing_city, + "billing_state": self.billing_state, "billing_country": self.billing_country, "shipping_city": self.shipping_city, + "shipping_state": self.shipping_state, "shipping_country": self.shipping_country, "company": self.company } diff --git a/erpnext/accounts/doctype/tax_rule/test_records.json b/erpnext/accounts/doctype/tax_rule/test_records.json index ebfb0c5b1b..0913fba4fb 100644 --- a/erpnext/accounts/doctype/tax_rule/test_records.json +++ b/erpnext/accounts/doctype/tax_rule/test_records.json @@ -5,6 +5,7 @@ "sales_tax_template": "_Test Tax 1", "use_for_shopping_cart": 1, "billing_city": "_Test City", + "billing_state": "Test State", "billing_country": "India", "shipping_city": "_Test City", "shipping_country": "India", @@ -19,6 +20,7 @@ "billing_city": "_Test City", "billing_country": "India", "shipping_city": "_Test City", + "shipping_state": "Test State", "shipping_country": "India", "priority": 2, "company": "_Test Company" diff --git a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py index 85fbe52220..3e175fabf7 100644 --- a/erpnext/accounts/doctype/tax_rule/test_tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/test_tax_rule.py @@ -7,11 +7,11 @@ import frappe import unittest from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup, IncorrectSupplierType, ConflictingTaxRule, get_tax_template -# test_records = frappe.get_test_records('Tax Rule') +test_records = frappe.get_test_records('Tax Rule') class TestTaxRule(unittest.TestCase): def setUp(self): - frappe.db.sql("delete from `tabTax Rule`") + frappe.db.sql("delete from `tabTax Rule` where use_for_shopping_cart <> 1") def test_customer_group(self): tax_rule = make_tax_rule(customer= "_Test Customer", customer_group= "_Test Customer Group 1", diff --git a/erpnext/utilities/doctype/address/test_records.json b/erpnext/utilities/doctype/address/test_records.json index 41a6abcd09..a7bde9a814 100644 --- a/erpnext/utilities/doctype/address/test_records.json +++ b/erpnext/utilities/doctype/address/test_records.json @@ -3,7 +3,8 @@ "address_line1": "_Test Address Line 1", "address_title": "_Test Address", "address_type": "Office", - "city": "_Test City", + "city": "_Test City", + "state": "Test State", "country": "India", "customer": "_Test Customer", "customer_name": "_Test Customer",