Item qty based tax (CESS) calculation support (#15456)

* fix conflicts

* added test case for qty cess

* use company specified in document to get region
This commit is contained in:
Himanshu Mishra 2018-11-13 11:13:04 +05:30 committed by Nabin Hait
parent 47a1dbab96
commit 35b2627112
6 changed files with 152 additions and 13 deletions

View File

@ -74,7 +74,7 @@ def is_perpetual_inventory_enabled(company):
frappe.local.enable_perpetual_inventory = {}
if not company in frappe.local.enable_perpetual_inventory:
frappe.local.enable_perpetual_inventory[company] = frappe.get_cached_value('Company',
frappe.local.enable_perpetual_inventory[company] = frappe.get_cached_value('Company',
company, "enable_perpetual_inventory") or 0
return frappe.local.enable_perpetual_inventory[company]
@ -87,7 +87,7 @@ def get_default_finance_book(company=None):
frappe.local.default_finance_book = {}
if not company in frappe.local.default_finance_book:
frappe.local.default_finance_book[company] = frappe.get_cached_value('Company',
frappe.local.default_finance_book[company] = frappe.get_cached_value('Company',
company, "default_finance_book")
return frappe.local.default_finance_book[company]
@ -108,7 +108,7 @@ def get_region(company=None):
You can also set global company flag in `frappe.flags.company`
'''
if company or frappe.flags.company:
return frappe.get_cached_value('Company',
return frappe.get_cached_value('Company',
company or frappe.flags.company, 'country')
elif frappe.flags.country:
return frappe.flags.country
@ -144,4 +144,4 @@ def is_member():
last_membership = get_last_membership()
if last_membership and getdate(last_membership.to_date) > getdate():
return True
return False
return False

View File

@ -15,6 +15,7 @@
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -44,10 +45,12 @@
"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,
@ -77,10 +80,12 @@
"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,
@ -99,7 +104,7 @@
"no_copy": 0,
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@ -109,10 +114,12 @@
"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,
@ -141,10 +148,12 @@
"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,
@ -172,10 +181,12 @@
"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,
@ -200,10 +211,12 @@
"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,
@ -232,10 +245,12 @@
"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,
@ -265,10 +280,12 @@
"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,
@ -297,11 +314,13 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "300px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -327,10 +346,12 @@
"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,
@ -358,10 +379,12 @@
"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,
@ -387,10 +410,12 @@
"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,
@ -419,10 +444,12 @@
"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,
@ -450,10 +477,12 @@
"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,
@ -482,10 +511,12 @@
"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,
@ -511,10 +542,12 @@
"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,
@ -542,10 +575,12 @@
"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,
@ -573,10 +608,12 @@
"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,
@ -604,10 +641,12 @@
"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,
@ -635,10 +674,12 @@
"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,
@ -666,6 +707,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
@ -679,7 +721,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-12-06 13:37:44.483509",
"modified": "2018-09-19 13:48:32.755198",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",
@ -690,5 +732,6 @@
"read_only_onload": 0,
"show_name_in_global_search": 0,
"track_changes": 1,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

View File

@ -33,7 +33,7 @@
"no_copy": 0,
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@ -652,7 +652,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-08-21 16:15:51.518582",
"modified": "2018-09-19 13:48:59.341454",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",
@ -666,4 +666,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -270,6 +270,8 @@ class calculate_taxes_and_totals(object):
elif tax.charge_type == "On Previous Row Total":
current_tax_amount = (tax_rate / 100.0) * \
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item
elif tax.charge_type == "On Item Quantity":
current_tax_amount = tax_rate * item.stock_qty
self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)
@ -646,4 +648,4 @@ def get_rounded_tax_amount(itemised_tax, precision):
# Rounding based on tax_amount precision
for taxes in itemised_tax.values():
for tax_account in taxes:
taxes[tax_account]["tax_amount"] = flt(taxes[tax_account]["tax_amount"], precision)
taxes[tax_account]["tax_amount"] = flt(taxes[tax_account]["tax_amount"], precision)

View File

@ -0,0 +1,94 @@
from __future__ import unicode_literals, print_function
import unittest
import frappe
from uuid import uuid4 as _uuid4
def uuid4():
return str(_uuid4())
class TestTaxes(unittest.TestCase):
def setUp(self):
self.company = frappe.get_doc({
'doctype': 'Company',
'company_name': uuid4(),
'abbr': ''.join(s[0] for s in uuid4().split('-')),
'default_currency': 'USD',
'country': 'United States',
}).insert()
self.account = frappe.get_doc({
'doctype': 'Account',
'account_name': uuid4(),
'account_type': 'Tax',
'company': self.company.name,
'parent_account': 'Duties and Taxes - {self.company.abbr}'.format(self=self)
}).insert()
self.item_group = frappe.get_doc({
'doctype': 'Item Group',
'item_group_name': uuid4(),
'parent_item_group': 'All Item Groups',
}).insert()
self.item = frappe.get_doc({
'doctype': 'Item',
'item_code': uuid4(),
'item_group': self.item_group.name,
'is_stock_item': 0,
'taxes': [
{
'tax_type': self.account.name,
'tax_rate': 2,
}
],
}).insert()
self.customer = frappe.get_doc({
'doctype': 'Customer',
'customer_name': uuid4(),
'customer_group': 'All Customer Groups',
}).insert()
self.supplier = frappe.get_doc({
'doctype': 'Supplier',
'supplier_name': uuid4(),
'supplier_group': 'All Supplier Groups',
}).insert()
def test_taxes(self):
self.created_docs = []
for dt in ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice',
'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']:
doc = frappe.get_doc({
'doctype': dt,
'company': self.company.name,
'supplier': self.supplier.name,
'schedule_date': frappe.utils.nowdate(),
'delivery_date': frappe.utils.nowdate(),
'customer': self.customer.name,
'buying_price_list' if dt.startswith('Purchase') else 'selling_price_list'
: 'Standard Buying' if dt.startswith('Purchase') else 'Standard Selling',
'items': [
{
'item_code': self.item.name,
'qty': 300,
'rate': 100,
}
],
'taxes': [
{
'charge_type': 'On Item Quantity',
'account_head': self.account.name,
'description': 'N/A',
'rate': 0,
},
],
})
doc.run_method('set_missing_values')
doc.run_method('calculate_taxes_and_totals')
doc.insert()
self.assertEqual(doc.taxes[0].tax_amount, 600)
self.created_docs.append(doc)
def tearDown(self):
for doc in self.created_docs:
doc.delete()
self.item.delete()
self.item_group.delete()
self.account.delete()
self.company.delete()

View File

@ -6,6 +6,6 @@ from frappe import _
from erpnext import get_region
def check_deletion_permission(doc, method):
region = get_region()
region = get_region(doc.company)
if region in ["Nepal", "France"]:
frappe.throw(_("Deletion is not permitted for country {0}".format(region)))
frappe.throw(_("Deletion is not permitted for country {0}".format(region)))