Merge pull request #16377 from SaiFi0102/Item-Tax-Template-V12

feat: Tax Category and Item Tax Template (v12)
This commit is contained in:
Nabin Hait 2019-02-02 13:51:55 +05:30 committed by GitHub
commit 690b83076d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 17315 additions and 15089 deletions

View File

@ -0,0 +1,58 @@
{
"custom_fields": [
{
"_assign": null,
"_comments": null,
"_liked_by": null,
"_user_tags": null,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"collapsible_depends_on": null,
"columns": 0,
"creation": "2018-12-28 22:29:21.828090",
"default": null,
"depends_on": null,
"description": null,
"docstatus": 0,
"dt": "Address",
"fetch_from": null,
"fieldname": "tax_category",
"fieldtype": "Link",
"hidden": 0,
"idx": 14,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"insert_after": "fax",
"label": "Tax Category",
"modified": "2018-12-28 22:29:21.828090",
"modified_by": "Administrator",
"name": "Address-tax_category",
"no_copy": 0,
"options": "Tax Category",
"owner": "Administrator",
"parent": null,
"parentfield": null,
"parenttype": null,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": null,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"translatable": 0,
"unique": 0,
"width": null
}
],
"custom_perms": [],
"doctype": "Address",
"property_setters": [],
"sync_on_migrate": 1
}

View File

@ -112,6 +112,41 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Billing Address",
"description": "Address used to determine Tax Category in transactions.",
"fieldname": "determine_address_tax_category_from",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Determine Address Tax Category From",
"length": 0,
"no_copy": 0,
"options": "Billing Address\nShipping Address",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -338,6 +373,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"fieldname": "add_taxes_from_item_tax_template",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Automatically Add Taxes and Charges from Item Tax Template",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -642,7 +710,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-07 16:52:03.869199",
"modified": "2019-01-07 00:42:34.510150",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
@ -714,4 +782,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -15,6 +15,9 @@ class AccountsSettings(Document):
frappe.clear_cache()
def validate(self):
for f in ["add_taxes_from_item_tax_template"]:
frappe.db.set_default(f, self.get(f, ""))
self.validate_stale_days()
self.enable_payment_schedule_in_print()
self.enable_fields_for_cost_center_settings()

View File

@ -0,0 +1,15 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Item Tax Template', {
setup: function(frm) {
frm.set_query("tax_type", "taxes", function(doc) {
return {
filters: [
['Account', 'is_group', '=', 0],
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
]
}
});
}
});

View File

@ -0,0 +1,168 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:title",
"beta": 0,
"creation": "2018-11-22 22:45:00.370913",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Title",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "taxes",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Tax Rates",
"length": 0,
"no_copy": 0,
"options": "Item Tax Template Detail",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-12-21 23:51:16.328340",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Item Tax Template",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 0
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe import _
class ItemTaxTemplate(Document):
def validate(self):
self.validate_tax_accounts()
def validate_tax_accounts(self):
"""Check whether Tax Rate is not entered twice for same Tax Type"""
check_list = []
for d in self.get('taxes'):
if d.tax_type:
account_type = frappe.db.get_value("Account", d.tax_type, "account_type")
if account_type not in ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']:
frappe.throw(
_("Item Tax Row {0} must have account of type Tax or Income or Expense or Chargeable").format(
d.idx))
else:
if d.tax_type in check_list:
frappe.throw(_("{0} entered twice in Item Tax").format(d.tax_type))
else:
check_list.append(d.tax_type)

View File

@ -0,0 +1,23 @@
/* eslint-disable */
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
QUnit.test("test: Item Tax Template", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
// insert a new Item Tax Template
() => frappe.tests.make('Item Tax Template', [
// values to be set
{key: 'value'}
]),
() => {
assert.equal(cur_frm.doc.key, 'value');
},
() => done()
]);
});

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestItemTaxTemplate(unittest.TestCase):
pass

View File

@ -0,0 +1,74 @@
[
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 10",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 10,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 12",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 12,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 15",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 15,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 20",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 20,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Item Tax Template 1",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 5,
"tax_type": "_Test Account Excise Duty - _TC"
},
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 10,
"tax_type": "_Test Account Education Cess - _TC"
},
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 15,
"tax_type": "_Test Account S&H Education Cess - _TC"
}
]
}
]

View File

@ -0,0 +1,108 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2018-11-22 23:47:02.804568",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "tax_type",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Tax",
"length": 0,
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "tax_rate",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Tax Rate",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-12-21 23:51:39.445198",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Item Tax Template Detail",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class ItemTaxTemplateDetail(Document):
pass

View File

@ -2185,7 +2185,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "taxes_and_charges",
"fieldname": "tax_category",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@ -2194,13 +2194,12 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Taxes and Charges",
"label": "Tax Category",
"length": 0,
"no_copy": 0,
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
"options": "Tax Category",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
@ -2307,6 +2306,40 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Purchase Taxes and Charges Template",
"length": 0,
"no_copy": 0,
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -4726,7 +4759,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-01-07 16:51:59.800081",
"modified": "2018-12-27 02:07:04.299399",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
@ -4841,4 +4874,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -18,7 +18,7 @@
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"item_code": "_Test Item Home Desktop 100",
"item_name": "_Test Item Home Desktop 100",
"item_tax_rate": "{\"_Test Account Excise Duty - _TC\": 10}",
"item_tax_template": "_Test Account Excise Duty @ 10",
"parentfield": "items",
"qty": 10,
"rate": 50,

View File

@ -1631,6 +1631,39 @@
"unique": 0,
"width": "120px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Tax Template",
"length": 0,
"no_copy": 0,
"options": "Item Tax Template",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -2626,7 +2659,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-01-07 16:52:00.749414",
"modified": "2018-11-23 16:23:49.360332",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
@ -2641,4 +2674,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -2274,7 +2274,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "taxes_and_charges",
"fieldname": "tax_category",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@ -2283,13 +2283,12 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Taxes and Charges",
"label": "Tax Category",
"length": 0,
"no_copy": 0,
"oldfieldname": "charge",
"oldfieldtype": "Link",
"options": "Sales Taxes and Charges Template",
"options": "Tax Category",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
@ -2394,6 +2393,40 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Sales Taxes and Charges Template",
"length": 0,
"no_copy": 0,
"oldfieldname": "charge",
"oldfieldtype": "Link",
"options": "Sales Taxes and Charges Template",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -5644,7 +5677,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-01-07 16:51:53.914523",
"modified": "2018-12-27 02:03:14.009762",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
@ -5740,4 +5773,4 @@
"track_changes": 1,
"track_seen": 1,
"track_views": 0
}
}

View File

@ -142,7 +142,7 @@
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"item_code": "_Test Item Home Desktop 100",
"item_name": "_Test Item Home Desktop 100",
"item_tax_rate": "{\"_Test Account Excise Duty - _TC\": 10}",
"item_tax_template": "_Test Account Excise Duty @ 10",
"parentfield": "items",
"price_list_rate": 50,
"qty": 10,
@ -269,7 +269,7 @@
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"item_code": "_Test Item Home Desktop 100",
"item_name": "_Test Item Home Desktop 100",
"item_tax_rate": "{\"_Test Account Excise Duty - _TC\": 10}",
"item_tax_template": "_Test Account Excise Duty @ 10",
"parentfield": "items",
"price_list_rate": 62.5,
"qty": 10,

View File

@ -381,6 +381,63 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(si.grand_total, 5474.0)
def test_tax_calculation_with_item_tax_template(self):
si = create_sales_invoice(qty=84, rate=4.6, do_not_save=True)
item_row = si.get("items")[0]
add_items = [
(54, '_Test Account Excise Duty @ 12'),
(288, '_Test Account Excise Duty @ 15'),
(144, '_Test Account Excise Duty @ 20'),
(430, '_Test Item Tax Template 1')
]
for qty, item_tax_template in add_items:
item_row_copy = copy.deepcopy(item_row)
item_row_copy.qty = qty
item_row_copy.item_tax_template = item_tax_template
si.append("items", item_row_copy)
si.append("taxes", {
"account_head": "_Test Account Excise Duty - _TC",
"charge_type": "On Net Total",
"cost_center": "_Test Cost Center - _TC",
"description": "Excise Duty",
"doctype": "Sales Taxes and Charges",
"rate": 11
})
si.append("taxes", {
"account_head": "_Test Account Education Cess - _TC",
"charge_type": "On Net Total",
"cost_center": "_Test Cost Center - _TC",
"description": "Education Cess",
"doctype": "Sales Taxes and Charges",
"rate": 0
})
si.append("taxes", {
"account_head": "_Test Account S&H Education Cess - _TC",
"charge_type": "On Net Total",
"cost_center": "_Test Cost Center - _TC",
"description": "S&H Education Cess",
"doctype": "Sales Taxes and Charges",
"rate": 3
})
si.insert()
self.assertEqual(si.net_total, 4600)
self.assertEqual(si.get("taxes")[0].tax_amount, 502.41)
self.assertEqual(si.get("taxes")[0].total, 5102.41)
self.assertEqual(si.get("taxes")[1].tax_amount, 197.80)
self.assertEqual(si.get("taxes")[1].total, 5300.21)
self.assertEqual(si.get("taxes")[2].tax_amount, 375.36)
self.assertEqual(si.get("taxes")[2].total, 5675.57)
self.assertEqual(si.grand_total, 5675.57)
self.assertEqual(si.rounding_adjustment, 0.43)
self.assertEqual(si.rounded_total, 5676.0)
def test_tax_calculation_with_multiple_items_and_discount(self):
si = create_sales_invoice(qty=1, rate=75, do_not_save=True)
item_row = si.get("items")[0]

View File

@ -1542,6 +1542,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Tax Template",
"length": 0,
"no_copy": 0,
"options": "Item Tax Template",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -2766,7 +2799,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-01-07 16:51:55.018091",
"modified": "2018-11-23 17:23:38.327395",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",
@ -2781,4 +2814,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -0,0 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Tax Category', {
refresh: function(frm) {
}
});

View File

@ -0,0 +1,134 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:title",
"beta": 0,
"creation": "2018-11-22 23:38:39.668804",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Title",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 1
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-11-22 23:38:39.668804",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Tax Category",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 0
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class TaxCategory(Document):
pass

View File

@ -0,0 +1,14 @@
[
{
"doctype": "Tax Category",
"title": "_Test Tax Category 1"
},
{
"doctype": "Tax Category",
"title": "_Test Tax Category 2"
},
{
"doctype": "Tax Category",
"title": "_Test Tax Category 3"
}
]

View File

@ -0,0 +1,23 @@
/* eslint-disable */
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
QUnit.test("test: Tax Category", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
// insert a new Tax Category
() => frappe.tests.make('Tax Category', [
// values to be set
{key: 'value'}
]),
() => {
assert.equal(cur_frm.doc.key, 'value');
},
() => done()
]);
});

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestTaxCategory(unittest.TestCase):
pass

View File

@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
@ -471,6 +472,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "tax_category",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Tax Category",
"length": 0,
"no_copy": 0,
"options": "Tax Category",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -1030,7 +1064,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-08-21 16:15:51.095450",
"modified": "2018-12-27 01:22:17.721636",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Tax Rule",

View File

@ -68,6 +68,7 @@ class TaxRule(Document):
"shipping_state": self.shipping_state,
"shipping_zipcode": self.shipping_zipcode,
"shipping_country": self.shipping_country,
"tax_category": self.tax_category,
"company": self.company
}
@ -144,10 +145,14 @@ def get_tax_template(posting_date, args):
conditions = ["""(from_date is null or from_date <= '{0}')
and (to_date is null or to_date >= '{0}')""".format(posting_date)]
conditions.append("ifnull(tax_category, '') = {0}".format(frappe.db.escape(cstr(args.get("tax_category")))))
if 'tax_category' in args.keys():
del args['tax_category']
for key, value in iteritems(args):
if key=="use_for_shopping_cart":
conditions.append("use_for_shopping_cart = {0}".format(1 if value else 0))
if key == 'customer_group':
elif key == 'customer_group':
if not value: value = get_root_of("Customer Group")
customer_group_condition = get_customer_group_condition(value)
conditions.append("ifnull({0}, '') in ('', {1})".format(key, customer_group_condition))

View File

@ -74,6 +74,26 @@ class TestTaxRule(unittest.TestCase):
self.assertEqual(get_tax_template("2015-01-01", {"customer":"_Test Customer 2"}),
"_Test Sales Taxes and Charges Template 2 - _TC")
def test_select_tax_rule_based_on_tax_category(self):
make_tax_rule(customer="_Test Customer", tax_category="_Test Tax Category 1",
sales_tax_template="_Test Sales Taxes and Charges Template 1 - _TC", save=1)
make_tax_rule(customer="_Test Customer", tax_category="_Test Tax Category 2",
sales_tax_template="_Test Sales Taxes and Charges Template 2 - _TC", save=1)
self.assertFalse(get_tax_template("2015-01-01", {"customer": "_Test Customer"}))
self.assertEqual(get_tax_template("2015-01-01", {"customer": "_Test Customer", "tax_category": "_Test Tax Category 1"}),
"_Test Sales Taxes and Charges Template 1 - _TC")
self.assertEqual(get_tax_template("2015-01-01", {"customer": "_Test Customer", "tax_category": "_Test Tax Category 2"}),
"_Test Sales Taxes and Charges Template 2 - _TC")
make_tax_rule(customer="_Test Customer", tax_category="",
sales_tax_template="_Test Sales Taxes and Charges Template - _TC", save=1)
self.assertEqual(get_tax_template("2015-01-01", {"customer": "_Test Customer"}),
"_Test Sales Taxes and Charges Template - _TC")
def test_select_tax_rule_based_on_better_match(self):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City", billing_state = "Test State",
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)

View File

@ -8,7 +8,7 @@ from frappe import _, msgprint, scrub
from frappe.core.doctype.user_permission.user_permission import get_permitted_documents
from frappe.model.utils import get_fetch_values
from frappe.utils import (add_days, getdate, formatdate, date_diff,
add_years, get_timestamp, nowdate, flt, add_months, get_last_day)
add_years, get_timestamp, nowdate, flt, cstr, add_months, get_last_day)
from frappe.contacts.doctype.address.address import (get_address_display,
get_default_address, get_company_address)
from frappe.contacts.doctype.contact.contact import get_contact_details, get_default_contact
@ -16,7 +16,7 @@ from erpnext.exceptions import PartyFrozen, PartyDisabled, InvalidAccountCurrenc
from erpnext.accounts.utils import get_fiscal_year
from erpnext import get_company_currency
from six import iteritems
from six import iteritems, string_types
class DuplicatePartyAccountError(frappe.ValidationError): pass
@ -46,14 +46,16 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
party = frappe.get_doc(party_type, party)
currency = party.default_currency if party.default_currency else get_company_currency(company)
out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out.customer_group, out.supplier_group)
out["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company)
set_address_details(out, party, party_type, doctype, company, party_address, shipping_address)
party_address, shipping_address = set_address_details(out, party, party_type, doctype, company, party_address, shipping_address)
set_contact_details(out, party, party_type)
set_other_values(out, party, party_type)
set_price_list(out, party, party_type, price_list, pos_profile)
out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out.customer_group, out.supplier_type)
out["tax_category"] = get_address_tax_category(party.get("tax_category"),
party_address, shipping_address if party_type != "Supplier" else party_address)
out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company,
customer_group=out.customer_group, supplier_group=out.supplier_group, tax_category=out.tax_category,
billing_address=party_address, shipping_address=shipping_address)
if fetch_payment_terms_template:
out["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company)
@ -103,6 +105,8 @@ def set_address_details(out, party, party_type, doctype=None, company=None, part
out.update(get_fetch_values(doctype, 'shipping_address', out.shipping_address))
get_regional_address_details(out, doctype, company)
return out.get(billing_address_field), out.shipping_address_name
@erpnext.allow_regional
def get_regional_address_details(out, doctype, company):
pass
@ -361,7 +365,19 @@ def validate_due_date(posting_date, due_date, party_type, party, company=None, b
.format(formatdate(default_due_date)))
@frappe.whitelist()
def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_group=None,
def get_address_tax_category(tax_category, billing_address=None, shipping_address=None):
addr_tax_category_from = frappe.db.get_single_value("Accounts Settings", "determine_address_tax_category_from")
if addr_tax_category_from == "Shipping Address":
if shipping_address:
tax_category = frappe.db.get_value("Address", shipping_address, "tax_category") or tax_category
else:
if billing_address:
tax_category = frappe.db.get_value("Address", billing_address, "tax_category") or tax_category
return cstr(tax_category)
@frappe.whitelist()
def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_group=None, tax_category=None,
billing_address=None, shipping_address=None, use_for_shopping_cart=None):
from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details
args = {
@ -369,6 +385,9 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup
"company": company
}
if tax_category:
args['tax_category'] = tax_category
if customer_group:
args['customer_group'] = customer_group

File diff suppressed because it is too large Load Diff

View File

@ -2236,6 +2236,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Tax Template",
"length": 0,
"no_copy": 0,
"options": "Item Tax Template",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -2344,7 +2377,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-01-07 16:51:57.546323",
"modified": "2018-11-23 16:53:57.220731",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",
@ -2359,4 +2392,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -214,6 +214,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "tax_category",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Tax Category",
"length": 0,
"no_copy": 0,
"options": "Tax Category",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -1496,7 +1529,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-17 13:58:08.597792",
"modified": "2019-01-17 13:58:08.597793",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier",
@ -1647,4 +1680,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -39,5 +39,11 @@
"company": "_Test Company",
"account": "_Test Payable USD - _TC"
}]
},
{
"doctype": "Supplier",
"supplier_name": "_Test Supplier With Tax Category",
"supplier_group": "_Test Supplier Group",
"tax_category": "_Test Tax Category 1"
}
]

View File

@ -90,3 +90,33 @@ class TestSupplier(unittest.TestCase):
supplier.country = 'Greece'
supplier.save()
self.assertEqual(supplier.country, "Greece")
def test_party_details_tax_category(self):
from erpnext.accounts.party import get_party_details
frappe.delete_doc_if_exists("Address", "_Test Address With Tax Category-Billing")
# Tax Category without Address
details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier")
self.assertEqual(details.tax_category, "_Test Tax Category 1")
address = frappe.get_doc(dict(
doctype='Address',
address_title='_Test Address With Tax Category',
tax_category='_Test Tax Category 2',
address_type='Billing',
address_line1='Station Road',
city='_Test City',
country='India',
links=[dict(
link_doctype='Supplier',
link_name='_Test Supplier With Tax Category'
)]
)).insert()
# Tax Category with Address
details = get_party_details("_Test Supplier With Tax Category", party_type="Supplier")
self.assertEqual(details.tax_category, "_Test Tax Category 2")
# Rollback
address.delete()

View File

@ -1198,8 +1198,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "taxes_and_charges",
"fieldname": "tax_category",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@ -1208,13 +1207,12 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Taxes and Charges",
"label": "Tax Category",
"length": 0,
"no_copy": 1,
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
"no_copy": 0,
"options": "Tax Category",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
@ -1321,6 +1319,41 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Purchase Taxes and Charges Template",
"length": 0,
"no_copy": 1,
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -2845,7 +2878,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-01-07 16:52:01.505553",
"modified": "2018-12-27 02:08:16.421501",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",
@ -2959,4 +2992,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -1543,6 +1543,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Tax Template",
"length": 0,
"no_copy": 0,
"options": "Item Tax Template",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -1786,7 +1819,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-01-07 16:52:02.125715",
"modified": "2018-11-23 17:34:54.977366",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",
@ -1801,4 +1834,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -163,6 +163,11 @@ def get_data():
{
"label": _("Taxes"),
"items": [
{
"type": "doctype",
"name": "Tax Category",
"description": _("Tax Category for overriding tax rates.")
},
{
"type": "doctype",
"name": "Sales Taxes and Charges Template",
@ -173,6 +178,11 @@ def get_data():
"name": "Purchase Taxes and Charges Template",
"description": _("Tax template for buying transactions.")
},
{
"type": "doctype",
"name": "Item Tax Template",
"description": _("Tax template for item tax rates.")
},
{
"type": "doctype",
"name": "Tax Rule",

View File

@ -16,7 +16,7 @@ from erpnext.accounts.party import get_party_account_currency, validate_party_fr
from erpnext.exceptions import InvalidCurrency
from six import text_type
force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset")
force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset", "item_tax_rate")
class AccountsController(TransactionBase):

View File

@ -27,6 +27,16 @@ class TestTaxes(unittest.TestCase):
'item_group_name': uuid4(),
'parent_item_group': 'All Item Groups',
}).insert()
self.item_tax_template = frappe.get_doc({
'doctype': 'Item Tax Template',
'title': uuid4(),
'taxes': [
{
'tax_type': self.account.name,
'tax_rate': 2,
}
]
}).insert()
self.item = frappe.get_doc({
'doctype': 'Item',
'item_code': uuid4(),
@ -34,8 +44,8 @@ class TestTaxes(unittest.TestCase):
'is_stock_item': 0,
'taxes': [
{
'tax_type': self.account.name,
'tax_rate': 2,
'item_tax_template': self.item_tax_template.name,
'tax_category': '',
}
],
}).insert()
@ -58,6 +68,7 @@ class TestTaxes(unittest.TestCase):
'doctype': dt,
'company': self.company.name,
'supplier': self.supplier.name,
'currency': "USD",
'schedule_date': frappe.utils.nowdate(),
'delivery_date': frappe.utils.nowdate(),
'customer': self.customer.name,
@ -90,5 +101,6 @@ class TestTaxes(unittest.TestCase):
doc.delete()
self.item.delete()
self.item_group.delete()
self.item_tax_template.delete()
self.account.delete()
self.company.delete()

1
erpnext/patches.txt Executable file → Normal file
View File

@ -589,3 +589,4 @@ erpnext.patches.v12_0.change_qms_icon
erpnext.patches.v12_0.rename_learn_to_help
erpnext.patches.v12_0.rename_accounts_desktop_icon_to_accounting
erpnext.patches.v12_0.replace_project_list_desktop_icon_with_projects_module_desktop_icon # 09-01-2019
erpnext.patches.v12_0.move_item_tax_to_item_tax_template

View File

@ -0,0 +1,82 @@
import frappe
import json
from six import iteritems
def execute():
old_item_taxes = {}
item_tax_templates = {}
rename_template_to_untitled = []
for d in frappe.db.sql("""select parent as item_code, tax_type, tax_rate from `tabItem Tax`""", as_dict=1):
old_item_taxes.setdefault(d.item_code, [])
old_item_taxes[d.item_code].append(d)
frappe.reload_doc("accounts", "doctype", "item_tax_template_detail")
frappe.reload_doc("accounts", "doctype", "item_tax_template")
frappe.reload_doc("stock", "doctype", "item")
frappe.reload_doc("stock", "doctype", "item_tax")
frappe.reload_doc("selling", "doctype", "quotation_item")
frappe.reload_doc("selling", "doctype", "sales_order_item")
frappe.reload_doc("stock", "doctype", "delivery_note_item")
frappe.reload_doc("accounts", "doctype", "sales_invoice_item")
frappe.reload_doc("buying", "doctype", "supplier_quotation_item")
frappe.reload_doc("buying", "doctype", "purchase_order_item")
frappe.reload_doc("stock", "doctype", "purchase_receipt_item")
frappe.reload_doc("accounts", "doctype", "purchase_invoice_item")
frappe.reload_doc("accounts", "doctype", "accounts_settings")
# for each item that have item tax rates
for item_code in old_item_taxes.keys():
# make current item's tax map
item_tax_map = {}
for d in old_item_taxes[item_code]:
item_tax_map[d.tax_type] = d.tax_rate
item_tax_template_name = get_item_tax_template(item_tax_templates, rename_template_to_untitled,
item_tax_map, item_code)
# update the item tax table
item = frappe.get_doc("Item", item_code)
item.set("taxes", [])
item.append("taxes", {"item_tax_template": item_tax_template_name, "tax_category": ""})
item.save()
doctypes = [
'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice',
'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice'
]
for dt in doctypes:
for d in frappe.db.sql("""select name, parent, item_code, item_tax_rate from `tab{0} Item`
where ifnull(item_tax_rate, '') not in ('', '{{}}')""".format(dt), as_dict=1):
item_tax_map = json.loads(d.item_tax_rate)
item_tax_template = get_item_tax_template(item_tax_templates, rename_template_to_untitled,
item_tax_map, d.item_code, d.parent)
frappe.db.set_value(dt + " Item", d.name, "item_tax_template", item_tax_template)
idx = 1
for oldname in rename_template_to_untitled:
frappe.rename_doc("Item Tax Template", oldname, "Untitled {}".format(idx))
idx += 1
settings = frappe.get_single("Accounts Settings")
settings.add_taxes_from_item_tax_template = 0
settings.determine_address_tax_category_from = "Billing Address"
settings.save()
def get_item_tax_template(item_tax_templates, rename_template_to_untitled, item_tax_map, item_code, parent=None):
# search for previously created item tax template by comparing tax maps
for template, item_tax_template_map in iteritems(item_tax_templates):
if item_tax_map == item_tax_template_map:
if not parent:
rename_template_to_untitled.append(template)
return template
# if no item tax template found, create one
item_tax_template = frappe.new_doc("Item Tax Template")
item_tax_template.title = "{}--{}".format(parent, item_code) if parent else "Item-{}".format(item_code)
for tax_type, tax_rate in iteritems(item_tax_map):
item_tax_template.append("taxes", {"tax_type": tax_type, "tax_rate": tax_rate})
item_tax_templates.setdefault(item_tax_template.title, {})
item_tax_templates[item_tax_template.title][tax_type] = tax_rate
item_tax_template.save()
return item_tax_template.name

View File

@ -115,6 +115,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
supplier_address: function() {
erpnext.utils.get_address_display(this.frm);
erpnext.utils.set_taxes_from_address(this.frm, "supplier_address", "supplier_address", "supplier_address");
},
buying_price_list: function() {

View File

@ -443,13 +443,19 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
uom : item.uom,
stock_uom: item.stock_uom,
pos_profile: me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : '',
cost_center: item.cost_center
cost_center: item.cost_center,
tax_category: me.frm.doc.tax_category,
item_tax_template: item.item_tax_template
}
},
callback: function(r) {
if(!r.exc) {
frappe.run_serially([
() => {
var d = locals[cdt][cdn];
me.add_taxes_from_item_tax_template(d.item_tax_rate);
},
() => me.frm.script_manager.trigger("price_list_rate", cdt, cdn),
() => me.toggle_conversion_factor(item),
() => {
@ -473,6 +479,26 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
},
add_taxes_from_item_tax_template: function(item_tax_map) {
let me = this;
if(item_tax_map && cint(frappe.defaults.get_default("add_taxes_from_item_tax_template"))) {
if(typeof (item_tax_map) == "string") {
item_tax_map = JSON.parse(item_tax_map);
}
$.each(item_tax_map, function(tax, rate) {
let found = (me.frm.doc.taxes || []).find(d => d.account_head === tax);
if(!found) {
let child = frappe.model.add_child(me.frm.doc, "taxes");
child.charge_type = "On Net Total";
child.account_head = tax;
child.rate = 0;
}
});
}
},
serial_no: function(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
@ -541,6 +567,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
frappe.run_serially([
() => me.frm.script_manager.trigger("currency"),
() => me.update_item_tax_map(),
() => me.apply_default_taxes(),
() => me.apply_pricing_rule()
]);
@ -1284,6 +1311,80 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
},
tax_category: function() {
var me = this;
if(me.frm.updating_party_details) return;
frappe.run_serially([
() => this.update_item_tax_map(),
() => erpnext.utils.set_taxes(this.frm, "tax_category"),
]);
},
item_tax_template: function(doc, cdt, cdn) {
var me = this;
if(me.frm.updating_party_details) return;
var item = frappe.get_doc(cdt, cdn);
if(item.item_tax_template) {
return this.frm.call({
method: "erpnext.stock.get_item_details.get_item_tax_map",
args: {
company: me.frm.doc.company,
item_tax_template: item.item_tax_template,
as_json: true
},
callback: function(r) {
if(!r.exc) {
item.item_tax_rate = r.message;
me.add_taxes_from_item_tax_template(item.item_tax_rate);
me.calculate_taxes_and_totals();
}
}
});
} else {
item.item_tax_rate = "{}";
me.calculate_taxes_and_totals();
}
},
update_item_tax_map: function() {
var me = this;
var item_codes = [];
$.each(this.frm.doc.items || [], function(i, item) {
if(item.item_code) {
item_codes.push(item.item_code);
}
});
if(item_codes.length) {
return this.frm.call({
method: "erpnext.stock.get_item_details.get_item_tax_info",
args: {
company: me.frm.doc.company,
tax_category: cstr(me.frm.doc.tax_category),
item_codes: item_codes
},
callback: function(r) {
if(!r.exc) {
$.each(me.frm.doc.items || [], function(i, item) {
if(item.item_code && r.message.hasOwnProperty(item.item_code)) {
item.item_tax_template = r.message[item.item_code].item_tax_template;
item.item_tax_rate = r.message[item.item_code].item_tax_rate;
me.add_taxes_from_item_tax_template(item.item_tax_rate);
} else {
item.item_tax_template = "";
item.item_tax_rate = "{}";
}
});
me.calculate_taxes_and_totals();
}
}
});
}
},
is_recurring: function() {
// set default values for recurring documents
if(this.frm.doc.is_recurring && this.frm.doc.__islocal) {

View File

@ -92,7 +92,6 @@ erpnext.utils.get_address_display = function(frm, address_field, display_field,
if(r.message) {
frm.set_value(display_field, r.message)
}
erpnext.utils.set_taxes(frm, address_field, display_field, is_your_company_address);
}
})
} else {
@ -100,15 +99,51 @@ erpnext.utils.get_address_display = function(frm, address_field, display_field,
}
};
erpnext.utils.set_taxes = function(frm, address_field, display_field, is_your_company_address) {
if(frappe.meta.get_docfield(frm.doc.doctype, "taxes") && !is_your_company_address) {
erpnext.utils.set_taxes_from_address = function(frm, triggered_from_field, billing_address_field, shipping_address_field) {
if(frm.updating_party_details) return;
if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
if(!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier",
frm.doc.customer || frm.doc.supplier || frm.doc.lead, address_field)) {
frm.doc.customer || frm.doc.supplier || frm.doc.lead, triggered_from_field)) {
return;
}
if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date",
frm.doc.posting_date || frm.doc.transaction_date, address_field)) {
frm.doc.posting_date || frm.doc.transaction_date, triggered_from_field)) {
return;
}
} else {
return;
}
frappe.call({
method: "erpnext.accounts.party.get_address_tax_category",
args: {
"tax_category": frm.doc.tax_category,
"billing_address": frm.doc[billing_address_field],
"shipping_address": frm.doc[shipping_address_field]
},
callback: function(r) {
if(!r.exc){
if(frm.doc.tax_category != r.message) {
frm.set_value("tax_category", r.message);
} else {
erpnext.utils.set_taxes(frm, triggered_from_field);
}
}
}
});
};
erpnext.utils.set_taxes = function(frm, triggered_from_field) {
if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
if(!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier",
frm.doc.customer || frm.doc.supplier || frm.doc.lead, triggered_from_field)) {
return;
}
if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date",
frm.doc.posting_date || frm.doc.transaction_date, triggered_from_field)) {
return;
}
} else {
@ -134,6 +169,9 @@ erpnext.utils.set_taxes = function(frm, address_field, display_field, is_your_co
"party_type": party_type,
"posting_date": frm.doc.posting_date || frm.doc.transaction_date,
"company": frm.doc.company,
"customer_group": frm.doc.customer_group,
"supplier_group": frm.doc.supplier_group,
"tax_category": frm.doc.tax_category,
"billing_address": ((frm.doc.customer || frm.doc.lead) ? (frm.doc.customer_address) : (frm.doc.supplier_address)),
"shipping_address": frm.doc.shipping_address_name
},
@ -143,7 +181,7 @@ erpnext.utils.set_taxes = function(frm, address_field, display_field, is_your_co
}
}
});
}
};
erpnext.utils.get_contact_details = function(frm) {
if(frm.updating_party_details) return;

View File

@ -449,6 +449,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "tax_category",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Tax Category",
"length": 0,
"no_copy": 0,
"options": "Tax Category",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -1906,7 +1939,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-17 13:10:24.360875",
"modified": "2019-01-17 13:10:24.360876",
"modified_by": "Administrator",
"module": "Selling",
"name": "Customer",
@ -2095,4 +2128,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -56,6 +56,64 @@ class TestCustomer(unittest.TestCase):
for key, value in iteritems(to_check):
self.assertEqual(value, details.get(key))
def test_party_details_tax_category(self):
from erpnext.accounts.party import get_party_details
frappe.delete_doc_if_exists("Address", "_Test Address With Tax Category-Billing")
frappe.delete_doc_if_exists("Address", "_Test Address With Tax Category-Shipping")
# Tax Category without Address
details = get_party_details("_Test Customer With Tax Category")
self.assertEqual(details.tax_category, "_Test Tax Category 1")
billing_address = frappe.get_doc(dict(
doctype='Address',
address_title='_Test Address With Tax Category',
tax_category='_Test Tax Category 2',
address_type='Billing',
address_line1='Station Road',
city='_Test City',
country='India',
links=[dict(
link_doctype='Customer',
link_name='_Test Customer With Tax Category'
)]
)).insert()
shipping_address = frappe.get_doc(dict(
doctype='Address',
address_title='_Test Address With Tax Category',
tax_category='_Test Tax Category 3',
address_type='Shipping',
address_line1='Station Road',
city='_Test City',
country='India',
links=[dict(
link_doctype='Customer',
link_name='_Test Customer With Tax Category'
)]
)).insert()
settings = frappe.get_single("Accounts Settings")
rollback_setting = settings.determine_address_tax_category_from
# Tax Category from Billing Address
settings.determine_address_tax_category_from = "Billing Address"
settings.save()
details = get_party_details("_Test Customer With Tax Category")
self.assertEqual(details.tax_category, "_Test Tax Category 2")
# Tax Category from Shipping Address
settings.determine_address_tax_category_from = "Shipping Address"
settings.save()
details = get_party_details("_Test Customer With Tax Category")
self.assertEqual(details.tax_category, "_Test Tax Category 3")
# Rollback
settings.determine_address_tax_category_from = rollback_setting
settings.save()
billing_address.delete()
shipping_address.delete()
def test_rename(self):
# delete communication linked to these 2 customers
for name in ("_Test Customer 1", "_Test Customer 1 Renamed"):

View File

@ -51,5 +51,13 @@
"company": "_Test Company",
"account": "_Test Receivable USD - _TC"
}]
},
{
"customer_group": "_Test Customer Group",
"customer_name": "_Test Customer With Tax Category",
"customer_type": "Individual",
"doctype": "Customer",
"territory": "_Test Territory",
"tax_category": "_Test Tax Category 1"
}
]

File diff suppressed because it is too large Load Diff

View File

@ -1798,6 +1798,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Tax Template",
"length": 0,
"no_copy": 0,
"options": "Item Tax Template",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -1914,7 +1947,7 @@
"istable": 1,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-01-07 16:51:56.248107",
"modified": "2018-11-23 17:32:30.302066",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation Item",
@ -1929,4 +1962,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

File diff suppressed because it is too large Load Diff

View File

@ -2032,39 +2032,6 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "page_break",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Page Break",
"length": 0,
"no_copy": 0,
"oldfieldname": "page_break",
"oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -2326,6 +2293,103 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Tax Template",
"length": 0,
"no_copy": 0,
"options": "Item Tax Template",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "col_break5",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "page_break",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Page Break",
"length": 0,
"no_copy": 0,
"oldfieldname": "page_break",
"oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -2477,7 +2541,7 @@
"istable": 1,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-01-07 16:51:51.852343",
"modified": "2018-11-23 17:20:53.728337",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order Item",
@ -2492,4 +2556,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -103,10 +103,12 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
customer_address: function() {
erpnext.utils.get_address_display(this.frm, "customer_address");
erpnext.utils.set_taxes_from_address(this.frm, "customer_address", "customer_address", "shipping_address_name");
},
shipping_address_name: function() {
erpnext.utils.get_address_display(this.frm, "shipping_address_name", "shipping_address");
erpnext.utils.set_taxes_from_address(this.frm, "shipping_address_name", "customer_address", "shipping_address_name");
},
sales_partner: function() {

View File

@ -275,6 +275,72 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"collapsible_depends_on": "",
"columns": 0,
"fieldname": "sec_break_taxes",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Tax",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "taxes",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Taxes",
"length": 0,
"no_copy": 0,
"options": "Item Tax",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -617,7 +683,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 3,
"modified": "2019-01-07 16:52:06.106336",
"modified": "2018-11-23 15:17:28.003933",
"modified_by": "Administrator",
"module": "Setup",
"name": "Item Group",
@ -748,4 +814,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -69,5 +69,39 @@
"is_group": 1,
"item_group_name": "_Test Item Group D",
"parent_item_group": "All Item Groups"
},
{
"doctype": "Item Group",
"is_group": 1,
"item_group_name": "_Test Item Group Tax Parent",
"parent_item_group": "All Item Groups",
"taxes": [
{
"doctype": "Item Tax",
"parentfield": "taxes",
"item_tax_template": "_Test Account Excise Duty @ 10",
"tax_category": ""
},
{
"doctype": "Item Tax",
"parentfield": "taxes",
"item_tax_template": "_Test Account Excise Duty @ 12",
"tax_category": "_Test Tax Category 1"
}
]
},
{
"doctype": "Item Group",
"is_group": 0,
"item_group_name": "_Test Item Group Tax Child Override",
"parent_item_group": "_Test Item Group Tax Parent",
"taxes": [
{
"doctype": "Item Tax",
"parentfield": "taxes",
"item_tax_template": "_Test Account Excise Duty @ 15",
"tax_category": ""
}
]
}
]

View File

@ -303,9 +303,10 @@ def set_taxes(quotation, cart_settings):
customer_group = frappe.db.get_value("Customer", quotation.customer, "customer_group")
quotation.taxes_and_charges = set_taxes(quotation.customer, "Customer", \
quotation.transaction_date, quotation.company, customer_group, None, \
quotation.customer_address, quotation.shipping_address_name, 1)
quotation.taxes_and_charges = set_taxes(quotation.customer, "Customer",
quotation.transaction_date, quotation.company, customer_group=customer_group, supplier_group=None,
tax_category=quotation.tax_category, billing_address=quotation.customer_address,
shipping_address=quotation.shipping_address_name, use_for_shopping_cart=1)
#
# # clear table
quotation.set("taxes", [])

View File

@ -107,9 +107,10 @@ class TestShoppingCart(unittest.TestCase):
from erpnext.accounts.party import set_taxes
tax_rule_master = set_taxes(quotation.customer, "Customer", \
quotation.transaction_date, quotation.company, None, None, \
quotation.customer_address, quotation.shipping_address_name, 1)
tax_rule_master = set_taxes(quotation.customer, "Customer",
quotation.transaction_date, quotation.company, customer_group=None, supplier_group=None,
tax_category=quotation.tax_category, billing_address=quotation.customer_address,
shipping_address=quotation.shipping_address_name, use_for_shopping_cart=1)
self.assertEqual(quotation.taxes_and_charges, tax_rule_master)
self.assertEqual(quotation.total_taxes_and_charges, 1000.0)

View File

@ -1961,8 +1961,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "If you have created a standard template in Sales Taxes and Charges Template, select one and click on the button below.",
"fieldname": "taxes_and_charges",
"fieldname": "tax_category",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@ -1971,13 +1970,12 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Taxes and Charges",
"label": "Tax Category",
"length": 0,
"no_copy": 0,
"oldfieldname": "charge",
"oldfieldtype": "Link",
"options": "Sales Taxes and Charges Template",
"options": "Tax Category",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
@ -2082,6 +2080,41 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "If you have created a standard template in Sales Taxes and Charges Template, select one and click on the button below.",
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Sales Taxes and Charges Template",
"length": 0,
"no_copy": 0,
"oldfieldname": "charge",
"oldfieldtype": "Link",
"options": "Sales Taxes and Charges Template",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -4296,7 +4329,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-01-07 16:51:52.357859",
"modified": "2018-12-27 01:53:41.645566",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note",
@ -4410,4 +4443,4 @@
"track_changes": 1,
"track_seen": 1,
"track_views": 0
}
}

View File

@ -2001,6 +2001,39 @@
"unique": 0,
"width": "120px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Tax Template",
"length": 0,
"no_copy": 0,
"options": "Item Tax Template",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -2310,7 +2343,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-01-07 16:51:53.322875",
"modified": "2018-11-23 17:20:07.347814",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note Item",
@ -2325,4 +2358,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

File diff suppressed because it is too large Load Diff

View File

@ -450,7 +450,7 @@ class Item(WebsiteGenerator):
# add item taxes from template
for d in template.get("taxes"):
self.append("taxes", {"tax_type": d.tax_type, "tax_rate": d.tax_rate})
self.append("taxes", {"item_tax_template": d.item_tax_template})
# copy re-order table if empty
if not self.get("reorder_levels"):
@ -499,17 +499,11 @@ class Item(WebsiteGenerator):
"""Check whether Tax Rate is not entered twice for same Tax Type"""
check_list = []
for d in self.get('taxes'):
if d.tax_type:
account_type = frappe.db.get_value("Account", d.tax_type, "account_type")
if account_type not in ['Tax', 'Chargeable', 'Income Account', 'Expense Account']:
frappe.throw(
_("Item Tax Row {0} must have account of type Tax or Income or Expense or Chargeable").format(d.idx))
if d.item_tax_template:
if d.item_tax_template in check_list:
frappe.throw(_("{0} entered twice in Item Tax").format(d.item_tax_template))
else:
if d.tax_type in check_list:
frappe.throw(_("{0} entered twice in Item Tax").format(d.tax_type))
else:
check_list.append(d.tax_type)
check_list.append(d.item_tax_template)
def validate_barcode(self):
from stdnum import ean

View File

@ -4,6 +4,7 @@
from __future__ import unicode_literals
import unittest
import frappe
import json
from frappe.test_runner import make_test_objects
from erpnext.controllers.item_variant import (create_variant, ItemVariantExistsError,
@ -17,7 +18,7 @@ from erpnext.stock.get_item_details import get_item_details
from six import iteritems
test_ignore = ["BOM"]
test_dependencies = ["Warehouse", "Item Group"]
test_dependencies = ["Warehouse", "Item Group", "Item Tax Template"]
def make_item(item_code, properties=None):
if frappe.db.exists("Item", item_code):
@ -76,7 +77,6 @@ class TestItem(unittest.TestCase):
"amount": 0.0,
"base_amount": 0.0,
"batch_no": None,
"item_tax_rate": '{}',
"uom": "_Test UOM",
"conversion_factor": 1.0,
}
@ -102,6 +102,68 @@ class TestItem(unittest.TestCase):
for key, value in iteritems(to_check):
self.assertEqual(value, details.get(key))
def test_item_tax_template(self):
expected_item_tax_template = [
{"item_code": "_Test Item With Item Tax Template", "tax_category": "",
"item_tax_template": "_Test Account Excise Duty @ 10"},
{"item_code": "_Test Item With Item Tax Template", "tax_category": "_Test Tax Category 1",
"item_tax_template": "_Test Account Excise Duty @ 12"},
{"item_code": "_Test Item With Item Tax Template", "tax_category": "_Test Tax Category 2",
"item_tax_template": None},
{"item_code": "_Test Item Inherit Group Item Tax Template 1", "tax_category": "",
"item_tax_template": "_Test Account Excise Duty @ 10"},
{"item_code": "_Test Item Inherit Group Item Tax Template 1", "tax_category": "_Test Tax Category 1",
"item_tax_template": "_Test Account Excise Duty @ 12"},
{"item_code": "_Test Item Inherit Group Item Tax Template 1", "tax_category": "_Test Tax Category 2",
"item_tax_template": None},
{"item_code": "_Test Item Inherit Group Item Tax Template 2", "tax_category": "",
"item_tax_template": "_Test Account Excise Duty @ 15"},
{"item_code": "_Test Item Inherit Group Item Tax Template 2", "tax_category": "_Test Tax Category 1",
"item_tax_template": "_Test Account Excise Duty @ 12"},
{"item_code": "_Test Item Inherit Group Item Tax Template 2", "tax_category": "_Test Tax Category 2",
"item_tax_template": None},
{"item_code": "_Test Item Override Group Item Tax Template", "tax_category": "",
"item_tax_template": "_Test Account Excise Duty @ 20"},
{"item_code": "_Test Item Override Group Item Tax Template", "tax_category": "_Test Tax Category 1",
"item_tax_template": "_Test Item Tax Template 1"},
{"item_code": "_Test Item Override Group Item Tax Template", "tax_category": "_Test Tax Category 2",
"item_tax_template": None},
]
expected_item_tax_map = {
None: {},
"_Test Account Excise Duty @ 10": {"_Test Account Excise Duty - _TC": 10},
"_Test Account Excise Duty @ 12": {"_Test Account Excise Duty - _TC": 12},
"_Test Account Excise Duty @ 15": {"_Test Account Excise Duty - _TC": 15},
"_Test Account Excise Duty @ 20": {"_Test Account Excise Duty - _TC": 20},
"_Test Item Tax Template 1": {"_Test Account Excise Duty - _TC": 5, "_Test Account Education Cess - _TC": 10,
"_Test Account S&H Education Cess - _TC": 15}
}
for data in expected_item_tax_template:
details = get_item_details({
"item_code": data['item_code'],
"tax_category": data['tax_category'],
"company": "_Test Company",
"price_list": "_Test Price List",
"currency": "_Test Currency",
"doctype": "Sales Order",
"conversion_rate": 1,
"price_list_currency": "_Test Currency",
"plc_conversion_rate": 1,
"order_type": "Sales",
"customer": "_Test Customer",
"conversion_factor": 1,
"price_list_uom_dependant": 1,
"ignore_pricing_rule": 1
})
self.assertEqual(details.item_tax_template, data['item_tax_template'])
self.assertEqual(json.loads(details.item_tax_rate), expected_item_tax_map[details.item_tax_template])
def test_item_attribute_change_after_variant(self):
frappe.delete_doc_if_exists("Item", "_Test Variant Item-L", force=1)

View File

@ -92,8 +92,8 @@
{
"doctype": "Item Tax",
"parentfield": "taxes",
"tax_rate": 10,
"tax_type": "_Test Account Excise Duty - _TC"
"item_tax_template": "_Test Account Excise Duty @ 10",
"tax_category": ""
}
],
"stock_uom": "_Test UOM 1"
@ -344,5 +344,121 @@
"stock_uom": "_Test UOM",
"show_in_website": 1,
"website_warehouse": "_Test Warehouse Group-C1 - _TC"
},
{
"description": "_Test Item With Item Tax Template",
"doctype": "Item",
"has_batch_no": 0,
"has_serial_no": 0,
"inspection_required": 0,
"is_stock_item": 1,
"is_sub_contracted_item": 0,
"item_code": "_Test Item With Item Tax Template",
"item_group": "_Test Item Group",
"item_name": "_Test Item With Item Tax Template",
"stock_uom": "_Test UOM",
"gst_hsn_code": "999800",
"item_defaults": [{
"company": "_Test Company",
"default_warehouse": "_Test Warehouse - _TC",
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"buying_cost_center": "_Test Cost Center - _TC",
"selling_cost_center": "_Test Cost Center - _TC",
"income_account": "Sales - _TC"
}],
"taxes": [
{
"doctype": "Item Tax",
"parentfield": "taxes",
"item_tax_template": "_Test Account Excise Duty @ 10",
"tax_category": ""
},
{
"doctype": "Item Tax",
"parentfield": "taxes",
"item_tax_template": "_Test Account Excise Duty @ 12",
"tax_category": "_Test Tax Category 1"
}
]
},
{
"description": "_Test Item Inherit Group Item Tax Template 1",
"doctype": "Item",
"has_batch_no": 0,
"has_serial_no": 0,
"inspection_required": 0,
"is_stock_item": 1,
"is_sub_contracted_item": 0,
"item_code": "_Test Item Inherit Group Item Tax Template 1",
"item_group": "_Test Item Group Tax Parent",
"item_name": "_Test Item Inherit Group Item Tax Template 1",
"stock_uom": "_Test UOM",
"gst_hsn_code": "999800",
"item_defaults": [{
"company": "_Test Company",
"default_warehouse": "_Test Warehouse - _TC",
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"buying_cost_center": "_Test Cost Center - _TC",
"selling_cost_center": "_Test Cost Center - _TC",
"income_account": "Sales - _TC"
}]
},
{
"description": "_Test Item Inherit Group Item Tax Template 2",
"doctype": "Item",
"has_batch_no": 0,
"has_serial_no": 0,
"inspection_required": 0,
"is_stock_item": 1,
"is_sub_contracted_item": 0,
"item_code": "_Test Item Inherit Group Item Tax Template 2",
"item_group": "_Test Item Group Tax Child Override",
"item_name": "_Test Item Inherit Group Item Tax Template 2",
"stock_uom": "_Test UOM",
"gst_hsn_code": "999800",
"item_defaults": [{
"company": "_Test Company",
"default_warehouse": "_Test Warehouse - _TC",
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"buying_cost_center": "_Test Cost Center - _TC",
"selling_cost_center": "_Test Cost Center - _TC",
"income_account": "Sales - _TC"
}]
},
{
"description": "_Test Item Override Group Item Tax Template",
"doctype": "Item",
"has_batch_no": 0,
"has_serial_no": 0,
"inspection_required": 0,
"is_stock_item": 1,
"is_sub_contracted_item": 0,
"item_code": "_Test Item Override Group Item Tax Template",
"item_group": "_Test Item Group Tax Child Override",
"item_name": "_Test Item Override Group Item Tax Template",
"stock_uom": "_Test UOM",
"gst_hsn_code": "999800",
"item_defaults": [{
"company": "_Test Company",
"default_warehouse": "_Test Warehouse - _TC",
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"buying_cost_center": "_Test Cost Center - _TC",
"selling_cost_center": "_Test Cost Center - _TC",
"income_account": "Sales - _TC"
}],
"taxes": [
{
"doctype": "Item Tax",
"parentfield": "taxes",
"item_tax_template": "_Test Account Excise Duty @ 20",
"tax_category": ""
},
{
"doctype": "Item Tax",
"parentfield": "taxes",
"item_tax_template": "_Test Item Tax Template 1",
"tax_category": "_Test Tax Category 1"
}
]
}
]

View File

@ -1,5 +1,7 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@ -10,70 +12,86 @@
"editable_grid": 1,
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "tax_type",
"columns": 0,
"fieldname": "item_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"label": "Tax",
"in_standard_filter": 0,
"label": "Item Tax Template",
"length": 0,
"no_copy": 0,
"oldfieldname": "tax_type",
"oldfieldtype": "Link",
"options": "Account",
"options": "Item Tax Template",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "tax_rate",
"fieldtype": "Float",
"columns": 0,
"fetch_from": "",
"fieldname": "tax_category",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"label": "Tax Rate",
"in_standard_filter": 0,
"label": "Tax Category",
"length": 0,
"no_copy": 0,
"oldfieldname": "tax_rate",
"oldfieldtype": "Currency",
"options": "Tax Category",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-07-11 03:28:01.235369",
"modified": "2018-12-21 23:52:40.798944",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Tax",
@ -82,5 +100,8 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"track_seen": 0
"show_name_in_global_search": 0,
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}

View File

@ -85,7 +85,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "{supplier_name}",
"default": "{supplier_name}",
"fieldname": "title",
"fieldtype": "Data",
"hidden": 1,
@ -98,6 +98,7 @@
"label": "Title",
"length": 0,
"no_copy": 1,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 1,
@ -247,7 +248,7 @@
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -1748,8 +1749,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "taxes_and_charges",
"fieldname": "tax_category",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@ -1758,13 +1758,12 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Taxes and Charges",
"label": "Tax Category",
"length": 0,
"no_copy": 0,
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
"options": "Tax Category",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
@ -1871,6 +1870,41 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Purchase Taxes and Charges Template",
"length": 0,
"no_copy": 0,
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -3708,7 +3742,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2018-11-02 19:59:01.423485",
"modified": "2018-12-27 02:06:29.508848",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt",
@ -3813,7 +3847,7 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 1,
"search_fields": "status, posting_date, supplier",
"search_fields": "status, posting_date, supplier",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",

View File

@ -2059,6 +2059,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Tax Template",
"length": 0,
"no_copy": 0,
"options": "Item Tax Template",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -2608,7 +2641,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-01-07 16:51:59.002215",
"modified": "2018-11-23 16:52:02.808534",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",
@ -2623,4 +2656,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -45,6 +45,10 @@ def get_item_details(args):
out = get_basic_details(args, item)
get_item_tax_template(args, item, out)
out["item_tax_rate"] = get_item_tax_map(args.company, args.get("item_tax_template") if out.get("item_tax_template") is None \
else out.get("item_tax_template"), as_json=True)
get_party_item_code(args, item, out)
set_valuation_rate(out, args)
@ -248,8 +252,6 @@ def get_basic_details(args, item):
'has_serial_no': item.has_serial_no,
'has_batch_no': item.has_batch_no,
"batch_no": None,
"item_tax_rate": json.dumps(dict(([d.tax_type, d.tax_rate] for d in
item.get("taxes")))),
"uom": args.uom,
"min_order_qty": flt(item.min_order_qty) if args.doctype == "Material Request" else "",
"qty": flt(args.qty) or 1.0,
@ -304,6 +306,59 @@ def get_basic_details(args, item):
return out
@frappe.whitelist()
def get_item_tax_info(company, tax_category, item_codes):
out = {}
if isinstance(item_codes, string_types):
item_codes = json.loads(item_codes)
for item_code in item_codes:
if not item_code or item_code in out:
continue
out[item_code] = {}
item = frappe.get_cached_doc("Item", item_code)
get_item_tax_template({"tax_category": tax_category}, item, out[item_code])
out[item_code]["item_tax_rate"] = get_item_tax_map(company, out[item_code].get("item_tax_template"), as_json=True)
return out
def get_item_tax_template(args, item, out):
"""
args = {
"tax_category": None
"item_tax_template": None
}
"""
item_tax_template = args.get("item_tax_template")
if not item_tax_template:
item_tax_template = _get_item_tax_template(args, item.taxes, out)
if not item_tax_template:
item_group = item.item_group
while item_group and not item_tax_template:
item_group_doc = frappe.get_cached_doc("Item Group", item_group)
item_tax_template = _get_item_tax_template(args, item_group_doc.taxes, out)
item_group = item_group_doc.parent_item_group
def _get_item_tax_template(args, taxes, out):
for tax in taxes:
if cstr(tax.tax_category) == cstr(args.get("tax_category")):
out["item_tax_template"] = tax.item_tax_template
return tax.item_tax_template
return None
@frappe.whitelist()
def get_item_tax_map(company, item_tax_template, as_json=True):
item_tax_map = {}
if item_tax_template:
template = frappe.get_cached_doc("Item Tax Template", item_tax_template)
for d in template.taxes:
if frappe.get_cached_value("Account", d.tax_type, "company") == company:
item_tax_map[d.tax_type] = d.tax_rate
return json.dumps(item_tax_map) if as_json else item_tax_map
@frappe.whitelist()
def calculate_service_end_date(args, item=None):
args = process_args(args)