[selling] [calculations] server side calculations, test cases and rounding based on currency number format
This commit is contained in:
parent
b8b1e58c4d
commit
21f4ea36b2
@ -1,8 +1,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"creation": "2013-04-19 11:00:14",
|
"creation": "2013-05-06 12:03:41",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-04-22 11:59:40",
|
"modified": "2013-05-09 17:34:14",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -10,6 +10,7 @@
|
|||||||
"allow_attach": 1,
|
"allow_attach": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
|
"document_type": "Transaction",
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "__common__",
|
"name": "__common__",
|
||||||
@ -30,6 +31,7 @@
|
|||||||
"parent": "Sales Invoice",
|
"parent": "Sales Invoice",
|
||||||
"parentfield": "permissions",
|
"parentfield": "permissions",
|
||||||
"parenttype": "DocType",
|
"parenttype": "DocType",
|
||||||
|
"permlevel": 0,
|
||||||
"read": 1
|
"read": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -251,7 +253,6 @@
|
|||||||
"width": "50%"
|
"width": "50%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Will be calculated automatically when you enter the details",
|
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "net_total",
|
"fieldname": "net_total",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
@ -259,10 +260,19 @@
|
|||||||
"oldfieldname": "net_total",
|
"oldfieldname": "net_total",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"print_hide": 0,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "net_total_export",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Net Total (Export)",
|
||||||
|
"options": "currency",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "recalculate_values",
|
"fieldname": "recalculate_values",
|
||||||
@ -1288,7 +1298,6 @@
|
|||||||
"cancel": 1,
|
"cancel": 1,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"permlevel": 0,
|
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Accounts User",
|
"role": "Accounts User",
|
||||||
"submit": 1,
|
"submit": 1,
|
||||||
@ -1297,8 +1306,7 @@
|
|||||||
{
|
{
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "customer",
|
"match": "customer",
|
||||||
"permlevel": 0,
|
"report": 0,
|
||||||
"report": 1,
|
|
||||||
"role": "Customer"
|
"role": "Customer"
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -1,13 +1,227 @@
|
|||||||
import webnotes
|
import webnotes
|
||||||
import unittest
|
import unittest, json
|
||||||
|
from webnotes.utils import flt
|
||||||
|
|
||||||
class TestSalesInvoice(unittest.TestCase):
|
class TestSalesInvoice(unittest.TestCase):
|
||||||
def make(self):
|
def make(self):
|
||||||
w = webnotes.bean(webnotes.copy_doclist(test_records[0]))
|
w = webnotes.bean(copy=test_records[0])
|
||||||
w.insert()
|
w.insert()
|
||||||
w.submit()
|
w.submit()
|
||||||
return w
|
return w
|
||||||
|
|
||||||
|
def test_sales_invoice_calculation_base_currency(self):
|
||||||
|
si = webnotes.bean(copy=test_records[2])
|
||||||
|
si.run_method("calculate_taxes_and_totals")
|
||||||
|
si.insert()
|
||||||
|
|
||||||
|
expected_values = {
|
||||||
|
"keys": ["ref_rate", "adj_rate", "export_rate", "export_amount",
|
||||||
|
"base_ref_rate", "basic_rate", "amount"],
|
||||||
|
"_Test Item Home Desktop 100": [50, 0, 50, 500, 50, 50, 500],
|
||||||
|
"_Test Item Home Desktop 200": [150, 0, 150, 750, 150, 150, 750],
|
||||||
|
}
|
||||||
|
|
||||||
|
# check if children are saved
|
||||||
|
self.assertEquals(len(si.doclist.get({"parentfield": "entries"})),
|
||||||
|
len(expected_values)-1)
|
||||||
|
|
||||||
|
# check if item values are calculated
|
||||||
|
for d in si.doclist.get({"parentfield": "entries"}):
|
||||||
|
for i, k in enumerate(expected_values["keys"]):
|
||||||
|
self.assertEquals(d.fields.get(k), expected_values[d.item_code][i])
|
||||||
|
|
||||||
|
# check net total
|
||||||
|
self.assertEquals(si.doc.net_total, 1250)
|
||||||
|
self.assertEquals(si.doc.net_total_export, 1250)
|
||||||
|
|
||||||
|
# check tax calculation
|
||||||
|
expected_values = {
|
||||||
|
"keys": ["tax_amount", "total"],
|
||||||
|
"_Test Account Shipping Charges - _TC": [100, 1350],
|
||||||
|
"_Test Account Customs Duty - _TC": [125, 1475],
|
||||||
|
"_Test Account Excise Duty - _TC": [140, 1615],
|
||||||
|
"_Test Account Education Cess - _TC": [2.8, 1617.8],
|
||||||
|
"_Test Account S&H Education Cess - _TC": [1.4, 1619.2],
|
||||||
|
"_Test Account CST - _TC": [32.38, 1651.58],
|
||||||
|
"_Test Account VAT - _TC": [156.25, 1807.83],
|
||||||
|
"_Test Account Discount - _TC": [-180.78, 1627.05]
|
||||||
|
}
|
||||||
|
|
||||||
|
for d in si.doclist.get({"parentfield": "other_charges"}):
|
||||||
|
for i, k in enumerate(expected_values["keys"]):
|
||||||
|
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
|
||||||
|
|
||||||
|
self.assertEquals(si.doc.grand_total, 1627.05)
|
||||||
|
self.assertEquals(si.doc.grand_total_export, 1627.05)
|
||||||
|
|
||||||
|
def test_sales_invoice_calculation_export_currency(self):
|
||||||
|
si = webnotes.bean(copy=test_records[2])
|
||||||
|
si.doc.currency = "USD"
|
||||||
|
si.doc.conversion_rate = 50
|
||||||
|
si.doclist[1].export_rate = 1
|
||||||
|
si.doclist[1].ref_rate = 1
|
||||||
|
si.doclist[2].export_rate = 3
|
||||||
|
si.doclist[2].ref_rate = 3
|
||||||
|
si.run_method("calculate_taxes_and_totals")
|
||||||
|
si.insert()
|
||||||
|
|
||||||
|
expected_values = {
|
||||||
|
"keys": ["ref_rate", "adj_rate", "export_rate", "export_amount",
|
||||||
|
"base_ref_rate", "basic_rate", "amount"],
|
||||||
|
"_Test Item Home Desktop 100": [1, 0, 1, 10, 50, 50, 500],
|
||||||
|
"_Test Item Home Desktop 200": [3, 0, 3, 15, 150, 150, 750],
|
||||||
|
}
|
||||||
|
|
||||||
|
# check if children are saved
|
||||||
|
self.assertEquals(len(si.doclist.get({"parentfield": "entries"})),
|
||||||
|
len(expected_values)-1)
|
||||||
|
|
||||||
|
# check if item values are calculated
|
||||||
|
for d in si.doclist.get({"parentfield": "entries"}):
|
||||||
|
for i, k in enumerate(expected_values["keys"]):
|
||||||
|
self.assertEquals(d.fields.get(k), expected_values[d.item_code][i])
|
||||||
|
|
||||||
|
# check net total
|
||||||
|
self.assertEquals(si.doc.net_total, 1250)
|
||||||
|
self.assertEquals(si.doc.net_total_export, 25)
|
||||||
|
|
||||||
|
# check tax calculation
|
||||||
|
expected_values = {
|
||||||
|
"keys": ["tax_amount", "total"],
|
||||||
|
"_Test Account Shipping Charges - _TC": [100, 1350],
|
||||||
|
"_Test Account Customs Duty - _TC": [125, 1475],
|
||||||
|
"_Test Account Excise Duty - _TC": [140, 1615],
|
||||||
|
"_Test Account Education Cess - _TC": [2.8, 1617.8],
|
||||||
|
"_Test Account S&H Education Cess - _TC": [1.4, 1619.2],
|
||||||
|
"_Test Account CST - _TC": [32.38, 1651.58],
|
||||||
|
"_Test Account VAT - _TC": [156.25, 1807.83],
|
||||||
|
"_Test Account Discount - _TC": [-180.78, 1627.05]
|
||||||
|
}
|
||||||
|
|
||||||
|
for d in si.doclist.get({"parentfield": "other_charges"}):
|
||||||
|
for i, k in enumerate(expected_values["keys"]):
|
||||||
|
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
|
||||||
|
|
||||||
|
self.assertEquals(si.doc.grand_total, 1627.05)
|
||||||
|
self.assertEquals(si.doc.grand_total_export, 32.54)
|
||||||
|
|
||||||
|
def test_inclusive_rate_validations(self):
|
||||||
|
si = webnotes.bean(copy=test_records[2])
|
||||||
|
for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})):
|
||||||
|
tax.idx = i+1
|
||||||
|
|
||||||
|
si.doclist[1].export_rate = 62.5
|
||||||
|
si.doclist[1].export_rate = 191
|
||||||
|
for i in [3, 5, 6, 7, 8, 9]:
|
||||||
|
si.doclist[i].included_in_print_rate = 1
|
||||||
|
|
||||||
|
# tax type "Actual" cannot be inclusive
|
||||||
|
self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals")
|
||||||
|
|
||||||
|
# taxes above included type 'On Previous Row Total' should also be included
|
||||||
|
si.doclist[3].included_in_print_rate = 0
|
||||||
|
self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals")
|
||||||
|
|
||||||
|
def test_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self):
|
||||||
|
# prepare
|
||||||
|
si = webnotes.bean(copy=test_records[3])
|
||||||
|
si.run_method("calculate_taxes_and_totals")
|
||||||
|
si.insert()
|
||||||
|
|
||||||
|
expected_values = {
|
||||||
|
"keys": ["ref_rate", "adj_rate", "export_rate", "export_amount",
|
||||||
|
"base_ref_rate", "basic_rate", "amount"],
|
||||||
|
"_Test Item Home Desktop 100": [62.5, 0, 62.5, 625.0, 50, 50, 500],
|
||||||
|
"_Test Item Home Desktop 200": [190.66, 0, 190.66, 953.3, 150, 150, 750],
|
||||||
|
}
|
||||||
|
|
||||||
|
# check if children are saved
|
||||||
|
self.assertEquals(len(si.doclist.get({"parentfield": "entries"})),
|
||||||
|
len(expected_values)-1)
|
||||||
|
|
||||||
|
# check if item values are calculated
|
||||||
|
for d in si.doclist.get({"parentfield": "entries"}):
|
||||||
|
for i, k in enumerate(expected_values["keys"]):
|
||||||
|
self.assertEquals(d.fields.get(k), expected_values[d.item_code][i])
|
||||||
|
|
||||||
|
# check net total
|
||||||
|
self.assertEquals(si.doc.net_total, 1250)
|
||||||
|
self.assertEquals(si.doc.net_total_export, 1578.3)
|
||||||
|
|
||||||
|
# check tax calculation
|
||||||
|
expected_values = {
|
||||||
|
"keys": ["tax_amount", "total"],
|
||||||
|
"_Test Account Excise Duty - _TC": [140, 1390],
|
||||||
|
"_Test Account Education Cess - _TC": [2.8, 1392.8],
|
||||||
|
"_Test Account S&H Education Cess - _TC": [1.4, 1394.2],
|
||||||
|
"_Test Account CST - _TC": [27.88, 1422.08],
|
||||||
|
"_Test Account VAT - _TC": [156.25, 1578.33],
|
||||||
|
"_Test Account Customs Duty - _TC": [125, 1703.33],
|
||||||
|
"_Test Account Shipping Charges - _TC": [100, 1803.33],
|
||||||
|
"_Test Account Discount - _TC": [-180.33, 1623]
|
||||||
|
}
|
||||||
|
|
||||||
|
for d in si.doclist.get({"parentfield": "other_charges"}):
|
||||||
|
for i, k in enumerate(expected_values["keys"]):
|
||||||
|
self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i])
|
||||||
|
|
||||||
|
self.assertEquals(si.doc.grand_total, 1623)
|
||||||
|
self.assertEquals(si.doc.grand_total_export, 1623)
|
||||||
|
|
||||||
|
def test_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self):
|
||||||
|
# prepare
|
||||||
|
si = webnotes.bean(copy=test_records[3])
|
||||||
|
si.doc.currency = "USD"
|
||||||
|
si.doc.conversion_rate = 50
|
||||||
|
si.doclist[1].export_rate = 50
|
||||||
|
si.doclist[1].adj_rate = 10
|
||||||
|
si.doclist[2].export_rate = 150
|
||||||
|
si.doclist[2].adj_rate = 20
|
||||||
|
si.doclist[9].rate = 5000
|
||||||
|
|
||||||
|
si.run_method("calculate_taxes_and_totals")
|
||||||
|
si.insert()
|
||||||
|
|
||||||
|
expected_values = {
|
||||||
|
"keys": ["ref_rate", "adj_rate", "export_rate", "export_amount",
|
||||||
|
"base_ref_rate", "basic_rate", "amount"],
|
||||||
|
"_Test Item Home Desktop 100": [55.56, 10, 50, 500, 2222.11, 1999.9, 19999.0],
|
||||||
|
"_Test Item Home Desktop 200": [187.5, 20, 150, 750, 7375.66, 5900.53, 29502.65],
|
||||||
|
}
|
||||||
|
|
||||||
|
# check if children are saved
|
||||||
|
self.assertEquals(len(si.doclist.get({"parentfield": "entries"})),
|
||||||
|
len(expected_values)-1)
|
||||||
|
|
||||||
|
# check if item values are calculated
|
||||||
|
for d in si.doclist.get({"parentfield": "entries"}):
|
||||||
|
for i, k in enumerate(expected_values["keys"]):
|
||||||
|
self.assertEquals(d.fields.get(k), expected_values[d.item_code][i])
|
||||||
|
|
||||||
|
# check net total
|
||||||
|
self.assertEquals(si.doc.net_total, 49501.65)
|
||||||
|
self.assertEquals(si.doc.net_total_export, 1250)
|
||||||
|
|
||||||
|
# check tax calculation
|
||||||
|
expected_values = {
|
||||||
|
"keys": ["tax_amount", "total"],
|
||||||
|
"_Test Account Excise Duty - _TC": [5540.22, 55041.87],
|
||||||
|
"_Test Account Education Cess - _TC": [110.81, 55152.68],
|
||||||
|
"_Test Account S&H Education Cess - _TC": [55.4, 55208.08],
|
||||||
|
"_Test Account CST - _TC": [1104.16, 56312.24],
|
||||||
|
"_Test Account VAT - _TC": [6187.71, 62499.95],
|
||||||
|
"_Test Account Customs Duty - _TC": [4950.17, 67450.12],
|
||||||
|
"_Test Account Shipping Charges - _TC": [5000, 72450.12],
|
||||||
|
"_Test Account Discount - _TC": [-7245.01, 65205.11]
|
||||||
|
}
|
||||||
|
|
||||||
|
for d in si.doclist.get({"parentfield": "other_charges"}):
|
||||||
|
for i, k in enumerate(expected_values["keys"]):
|
||||||
|
self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i])
|
||||||
|
|
||||||
|
self.assertEquals(si.doc.grand_total, 65205.11)
|
||||||
|
self.assertEquals(si.doc.grand_total_export, 1304.1)
|
||||||
|
|
||||||
def test_outstanding(self):
|
def test_outstanding(self):
|
||||||
w = self.make()
|
w = self.make()
|
||||||
self.assertEquals(w.doc.outstanding_amount, w.doc.grand_total)
|
self.assertEquals(w.doc.outstanding_amount, w.doc.grand_total)
|
||||||
@ -520,4 +734,263 @@ test_records = [
|
|||||||
"tax_amount": 50.0,
|
"tax_amount": 50.0,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"naming_series": "_T-Sales Invoice-",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"conversion_rate": 1.0,
|
||||||
|
"currency": "INR",
|
||||||
|
"debit_to": "_Test Customer - _TC",
|
||||||
|
"customer": "_Test Customer",
|
||||||
|
"customer_name": "_Test Customer",
|
||||||
|
"doctype": "Sales Invoice",
|
||||||
|
"due_date": "2013-01-23",
|
||||||
|
"fiscal_year": "_Test Fiscal Year 2013",
|
||||||
|
"grand_total_export": 0,
|
||||||
|
"plc_conversion_rate": 1.0,
|
||||||
|
"posting_date": "2013-01-23",
|
||||||
|
"price_list_currency": "INR",
|
||||||
|
"price_list_name": "_Test Price List",
|
||||||
|
"territory": "_Test Territory",
|
||||||
|
},
|
||||||
|
# items
|
||||||
|
{
|
||||||
|
"doctype": "Sales Invoice Item",
|
||||||
|
"parentfield": "entries",
|
||||||
|
"item_code": "_Test Item Home Desktop 100",
|
||||||
|
"item_name": "_Test Item Home Desktop 100",
|
||||||
|
"qty": 10,
|
||||||
|
"export_rate": 50,
|
||||||
|
"stock_uom": "_Test UOM",
|
||||||
|
"item_tax_rate": json.dumps({"_Test Account Excise Duty - _TC": 10}),
|
||||||
|
"income_account": "Sales - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Invoice Item",
|
||||||
|
"parentfield": "entries",
|
||||||
|
"item_code": "_Test Item Home Desktop 200",
|
||||||
|
"item_name": "_Test Item Home Desktop 200",
|
||||||
|
"qty": 5,
|
||||||
|
"export_rate": 150,
|
||||||
|
"stock_uom": "_Test UOM",
|
||||||
|
"income_account": "Sales - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
|
||||||
|
},
|
||||||
|
# taxes
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "Actual",
|
||||||
|
"account_head": "_Test Account Shipping Charges - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Shipping Charges",
|
||||||
|
"rate": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account Customs Duty - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Customs Duty",
|
||||||
|
"rate": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account Excise Duty - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Excise Duty",
|
||||||
|
"rate": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Previous Row Amount",
|
||||||
|
"account_head": "_Test Account Education Cess - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Education Cess",
|
||||||
|
"rate": 2,
|
||||||
|
"row_id": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Previous Row Amount",
|
||||||
|
"account_head": "_Test Account S&H Education Cess - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "S&H Education Cess",
|
||||||
|
"rate": 1,
|
||||||
|
"row_id": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Previous Row Total",
|
||||||
|
"account_head": "_Test Account CST - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "CST",
|
||||||
|
"rate": 2,
|
||||||
|
"row_id": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account VAT - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "VAT",
|
||||||
|
"rate": 12.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Previous Row Total",
|
||||||
|
"account_head": "_Test Account Discount - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Discount",
|
||||||
|
"rate": -10,
|
||||||
|
"row_id": 7
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"naming_series": "_T-Sales Invoice-",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"conversion_rate": 1.0,
|
||||||
|
"currency": "INR",
|
||||||
|
"debit_to": "_Test Customer - _TC",
|
||||||
|
"customer": "_Test Customer",
|
||||||
|
"customer_name": "_Test Customer",
|
||||||
|
"doctype": "Sales Invoice",
|
||||||
|
"due_date": "2013-01-23",
|
||||||
|
"fiscal_year": "_Test Fiscal Year 2013",
|
||||||
|
"grand_total_export": 0,
|
||||||
|
"plc_conversion_rate": 1.0,
|
||||||
|
"posting_date": "2013-01-23",
|
||||||
|
"price_list_currency": "INR",
|
||||||
|
"price_list_name": "_Test Price List",
|
||||||
|
"territory": "_Test Territory",
|
||||||
|
},
|
||||||
|
# items
|
||||||
|
{
|
||||||
|
"doctype": "Sales Invoice Item",
|
||||||
|
"parentfield": "entries",
|
||||||
|
"item_code": "_Test Item Home Desktop 100",
|
||||||
|
"item_name": "_Test Item Home Desktop 100",
|
||||||
|
"qty": 10,
|
||||||
|
"export_rate": 62.5,
|
||||||
|
"stock_uom": "_Test UOM",
|
||||||
|
"item_tax_rate": json.dumps({"_Test Account Excise Duty - _TC": 10}),
|
||||||
|
"income_account": "Sales - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Invoice Item",
|
||||||
|
"parentfield": "entries",
|
||||||
|
"item_code": "_Test Item Home Desktop 200",
|
||||||
|
"item_name": "_Test Item Home Desktop 200",
|
||||||
|
"qty": 5,
|
||||||
|
"export_rate": 190.66,
|
||||||
|
"stock_uom": "_Test UOM",
|
||||||
|
"income_account": "Sales - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
|
||||||
|
},
|
||||||
|
# taxes
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account Excise Duty - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Excise Duty",
|
||||||
|
"rate": 12,
|
||||||
|
"included_in_print_rate": 1,
|
||||||
|
"idx": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Previous Row Amount",
|
||||||
|
"account_head": "_Test Account Education Cess - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Education Cess",
|
||||||
|
"rate": 2,
|
||||||
|
"row_id": 1,
|
||||||
|
"included_in_print_rate": 1,
|
||||||
|
"idx": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Previous Row Amount",
|
||||||
|
"account_head": "_Test Account S&H Education Cess - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "S&H Education Cess",
|
||||||
|
"rate": 1,
|
||||||
|
"row_id": 1,
|
||||||
|
"included_in_print_rate": 1,
|
||||||
|
"idx": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Previous Row Total",
|
||||||
|
"account_head": "_Test Account CST - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "CST",
|
||||||
|
"rate": 2,
|
||||||
|
"row_id": 3,
|
||||||
|
"included_in_print_rate": 1,
|
||||||
|
"idx": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account VAT - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "VAT",
|
||||||
|
"rate": 12.5,
|
||||||
|
"included_in_print_rate": 1,
|
||||||
|
"idx": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account Customs Duty - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Customs Duty",
|
||||||
|
"rate": 10,
|
||||||
|
"idx": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "Actual",
|
||||||
|
"account_head": "_Test Account Shipping Charges - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Shipping Charges",
|
||||||
|
"rate": 100,
|
||||||
|
"idx": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Previous Row Total",
|
||||||
|
"account_head": "_Test Account Discount - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Discount",
|
||||||
|
"rate": -10,
|
||||||
|
"row_id": 7,
|
||||||
|
"idx": 8
|
||||||
|
},
|
||||||
|
],
|
||||||
]
|
]
|
@ -22,7 +22,6 @@ import json
|
|||||||
|
|
||||||
from buying.utils import get_item_details
|
from buying.utils import get_item_details
|
||||||
from setup.utils import get_company_currency
|
from setup.utils import get_company_currency
|
||||||
from webnotes.model.utils import round_floats_in_doc
|
|
||||||
|
|
||||||
from controllers.stock_controller import StockController
|
from controllers.stock_controller import StockController
|
||||||
|
|
||||||
@ -138,19 +137,20 @@ class BuyingController(StockController):
|
|||||||
def _set_base(item, print_field, base_field):
|
def _set_base(item, print_field, base_field):
|
||||||
"""set values in base currency"""
|
"""set values in base currency"""
|
||||||
item.fields[base_field] = flt((flt(item.fields[print_field],
|
item.fields[base_field] = flt((flt(item.fields[print_field],
|
||||||
self.precision.item[print_field]) * self.doc.conversion_rate),
|
self.precision_of(print_field, item.parentfield)) * self.doc.conversion_rate),
|
||||||
self.precision.item[base_field])
|
self.precision_of(base_field, item.parentfield))
|
||||||
|
|
||||||
# hack! - cleaned up in _cleanup()
|
# hack! - cleaned up in _cleanup()
|
||||||
if self.doc.doctype != "Purchase Invoice":
|
if self.doc.doctype != "Purchase Invoice":
|
||||||
self.precision.item["rate"] = self.precision.item.purchase_rate
|
df = self.meta.get_field("purchase_rate", parentfield=self.fname)
|
||||||
|
df.fieldname = "rate"
|
||||||
|
|
||||||
for item in self.item_doclist:
|
for item in self.item_doclist:
|
||||||
# hack! - cleaned up in _cleanup()
|
# hack! - cleaned up in _cleanup()
|
||||||
if self.doc.doctype != "Purchase Invoice":
|
if self.doc.doctype != "Purchase Invoice":
|
||||||
item.rate = item.purchase_rate
|
item.rate = item.purchase_rate
|
||||||
|
|
||||||
round_floats_in_doc(item, self.precision.item)
|
self.round_floats_in_doc(item, item.parentfield)
|
||||||
|
|
||||||
if item.discount_rate == 100:
|
if item.discount_rate == 100:
|
||||||
item.import_ref_rate = item.import_ref_rate or item.import_rate
|
item.import_ref_rate = item.import_ref_rate or item.import_rate
|
||||||
@ -158,14 +158,14 @@ class BuyingController(StockController):
|
|||||||
else:
|
else:
|
||||||
if item.import_ref_rate:
|
if item.import_ref_rate:
|
||||||
item.import_rate = flt(item.import_ref_rate * (1.0 - (item.discount_rate / 100.0)),
|
item.import_rate = flt(item.import_ref_rate * (1.0 - (item.discount_rate / 100.0)),
|
||||||
self.precision.item.import_rate)
|
self.precision_of("import_rate", item.parentfield))
|
||||||
else:
|
else:
|
||||||
# assume that print rate and discount_rate are specified
|
# assume that print rate and discount_rate are specified
|
||||||
item.import_ref_rate = flt(item.import_rate / (1.0 - (item.discount_rate / 100.0)),
|
item.import_ref_rate = flt(item.import_rate / (1.0 - (item.discount_rate / 100.0)),
|
||||||
self.precision.item.import_ref_rate)
|
self.precision_of("import_ref_rate", item.parentfield))
|
||||||
|
|
||||||
item.import_amount = flt(item.import_rate * item.qty,
|
item.import_amount = flt(item.import_rate * item.qty,
|
||||||
self.precision.item.import_amount)
|
self.precision_of("import_amount", item.parentfield))
|
||||||
|
|
||||||
_set_base(item, "import_ref_rate", "purchase_ref_rate")
|
_set_base(item, "import_ref_rate", "purchase_ref_rate")
|
||||||
_set_base(item, "import_rate", "rate")
|
_set_base(item, "import_rate", "rate")
|
||||||
@ -183,7 +183,7 @@ class BuyingController(StockController):
|
|||||||
|
|
||||||
self.validate_on_previous_row(tax)
|
self.validate_on_previous_row(tax)
|
||||||
|
|
||||||
round_floats_in_doc(tax, self.precision.tax)
|
self.round_floats_in_doc(tax, tax.parentfield)
|
||||||
|
|
||||||
def calculate_net_total(self):
|
def calculate_net_total(self):
|
||||||
self.doc.net_total = 0
|
self.doc.net_total = 0
|
||||||
@ -193,9 +193,9 @@ class BuyingController(StockController):
|
|||||||
self.doc.net_total += item.amount
|
self.doc.net_total += item.amount
|
||||||
self.doc.net_total_import += item.import_amount
|
self.doc.net_total_import += item.import_amount
|
||||||
|
|
||||||
self.doc.net_total = flt(self.doc.net_total, self.precision.main.net_total)
|
self.doc.net_total = flt(self.doc.net_total, self.precision_of("net_total"))
|
||||||
self.doc.net_total_import = flt(self.doc.net_total_import,
|
self.doc.net_total_import = flt(self.doc.net_total_import,
|
||||||
self.precision.main.net_total_import)
|
self.precision_of("net_total_import"))
|
||||||
|
|
||||||
def calculate_taxes(self):
|
def calculate_taxes(self):
|
||||||
for item in self.item_doclist:
|
for item in self.item_doclist:
|
||||||
@ -213,7 +213,7 @@ class BuyingController(StockController):
|
|||||||
# and tax.grand_total_for_current_item for the first such iteration
|
# and tax.grand_total_for_current_item for the first such iteration
|
||||||
if not (current_tax_amount or self.doc.net_total or tax.tax_amount) and \
|
if not (current_tax_amount or self.doc.net_total or tax.tax_amount) and \
|
||||||
tax.charge_type=="Actual":
|
tax.charge_type=="Actual":
|
||||||
zero_net_total_adjustment = flt(tax.rate, self.precision.tax.tax_amount)
|
zero_net_total_adjustment = flt(tax.rate, self.precision_of("tax_amount", tax.parentfield))
|
||||||
current_tax_amount += zero_net_total_adjustment
|
current_tax_amount += zero_net_total_adjustment
|
||||||
|
|
||||||
# store tax_amount for current item as it will be used for
|
# store tax_amount for current item as it will be used for
|
||||||
@ -235,12 +235,12 @@ class BuyingController(StockController):
|
|||||||
# item's amount, previously applied tax and the current tax on that item
|
# item's amount, previously applied tax and the current tax on that item
|
||||||
if i==0:
|
if i==0:
|
||||||
tax.grand_total_for_current_item = flt(item.amount +
|
tax.grand_total_for_current_item = flt(item.amount +
|
||||||
current_tax_amount, self.precision.tax.total)
|
current_tax_amount, self.precision_of("total", tax.parentfield))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
tax.grand_total_for_current_item = \
|
tax.grand_total_for_current_item = \
|
||||||
flt(self.tax_doclist[i-1].grand_total_for_current_item +
|
flt(self.tax_doclist[i-1].grand_total_for_current_item +
|
||||||
current_tax_amount, self.precision.tax.total)
|
current_tax_amount, self.precision_of("total", tax.parentfield))
|
||||||
|
|
||||||
# in tax.total, accumulate grand total of each item
|
# in tax.total, accumulate grand total of each item
|
||||||
tax.total += tax.grand_total_for_current_item
|
tax.total += tax.grand_total_for_current_item
|
||||||
@ -252,20 +252,20 @@ class BuyingController(StockController):
|
|||||||
def calculate_totals(self):
|
def calculate_totals(self):
|
||||||
if self.tax_doclist:
|
if self.tax_doclist:
|
||||||
self.doc.grand_total = flt(self.tax_doclist[-1].total,
|
self.doc.grand_total = flt(self.tax_doclist[-1].total,
|
||||||
self.precision.main.grand_total)
|
self.precision_of("grand_total"))
|
||||||
self.doc.grand_total_import = flt(
|
self.doc.grand_total_import = flt(
|
||||||
self.doc.grand_total / self.doc.conversion_rate,
|
self.doc.grand_total / self.doc.conversion_rate,
|
||||||
self.precision.main.grand_total_import)
|
self.precision_of("grand_total_import"))
|
||||||
else:
|
else:
|
||||||
self.doc.grand_total = flt(self.doc.net_total,
|
self.doc.grand_total = flt(self.doc.net_total,
|
||||||
self.precision.main.grand_total)
|
self.precision_of("grand_total"))
|
||||||
self.doc.grand_total_import = flt(
|
self.doc.grand_total_import = flt(
|
||||||
self.doc.grand_total / self.doc.conversion_rate,
|
self.doc.grand_total / self.doc.conversion_rate,
|
||||||
self.precision.main.grand_total_import)
|
self.precision_of("grand_total_import"))
|
||||||
|
|
||||||
self.doc.total_tax = \
|
self.doc.total_tax = \
|
||||||
flt(self.doc.grand_total - self.doc.net_total,
|
flt(self.doc.grand_total - self.doc.net_total,
|
||||||
self.precision.main.total_tax)
|
self.precision_of("total_tax"))
|
||||||
|
|
||||||
if self.meta.get_field("rounded_total"):
|
if self.meta.get_field("rounded_total"):
|
||||||
self.doc.rounded_total = round(self.doc.grand_total)
|
self.doc.rounded_total = round(self.doc.grand_total)
|
||||||
@ -276,11 +276,11 @@ class BuyingController(StockController):
|
|||||||
def calculate_outstanding_amount(self):
|
def calculate_outstanding_amount(self):
|
||||||
if self.doc.doctype == "Purchase Invoice" and self.doc.docstatus == 0:
|
if self.doc.doctype == "Purchase Invoice" and self.doc.docstatus == 0:
|
||||||
self.doc.total_advance = flt(self.doc.total_advance,
|
self.doc.total_advance = flt(self.doc.total_advance,
|
||||||
self.precision.main.total_advance)
|
self.precision_of("total_advance"))
|
||||||
self.doc.total_amount_to_pay = flt(self.doc.grand_total - flt(self.doc.write_off_amount,
|
self.doc.total_amount_to_pay = flt(self.doc.grand_total - flt(self.doc.write_off_amount,
|
||||||
self.precision.main.write_off_amount), self.precision.main.total_amount_to_pay)
|
self.precision_of("write_off_amount")), self.precision_of("total_amount_to_pay"))
|
||||||
self.doc.outstanding_amount = flt(self.doc.total_amount_to_pay - self.doc.total_advance,
|
self.doc.outstanding_amount = flt(self.doc.total_amount_to_pay - self.doc.total_advance,
|
||||||
self.precision.main.outstanding_amount)
|
self.precision_of("outstanding_amount"))
|
||||||
|
|
||||||
def _cleanup(self):
|
def _cleanup(self):
|
||||||
for tax in self.tax_doclist:
|
for tax in self.tax_doclist:
|
||||||
@ -319,7 +319,7 @@ class BuyingController(StockController):
|
|||||||
|
|
||||||
if tax.charge_type == "Actual":
|
if tax.charge_type == "Actual":
|
||||||
# distribute the tax amount proportionally to each item row
|
# distribute the tax amount proportionally to each item row
|
||||||
actual = flt(tax.rate, self.precision.tax.tax_amount)
|
actual = flt(tax.rate, self.precision_of("tax_amount", tax.parentfield))
|
||||||
current_tax_amount = (self.doc.net_total
|
current_tax_amount = (self.doc.net_total
|
||||||
and ((item.amount / self.doc.net_total) * actual)
|
and ((item.amount / self.doc.net_total) * actual)
|
||||||
or 0)
|
or 0)
|
||||||
@ -332,11 +332,11 @@ class BuyingController(StockController):
|
|||||||
current_tax_amount = (tax_rate / 100.0) * \
|
current_tax_amount = (tax_rate / 100.0) * \
|
||||||
self.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item
|
self.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item
|
||||||
|
|
||||||
return flt(current_tax_amount, self.precision.tax.tax_amount)
|
return flt(current_tax_amount, self.precision_of("tax_amount", tax.parentfield))
|
||||||
|
|
||||||
def _get_tax_rate(self, tax, item_tax_map):
|
def _get_tax_rate(self, tax, item_tax_map):
|
||||||
if item_tax_map.has_key(tax.account_head):
|
if item_tax_map.has_key(tax.account_head):
|
||||||
return flt(item_tax_map.get(tax.account_head), self.precision.tax.rate)
|
return flt(item_tax_map.get(tax.account_head), self.precision_of("rate", tax.parentfield))
|
||||||
else:
|
else:
|
||||||
return tax.rate
|
return tax.rate
|
||||||
|
|
||||||
@ -350,7 +350,7 @@ class BuyingController(StockController):
|
|||||||
if tax.category in ["Valuation", "Valuation and Total"] and \
|
if tax.category in ["Valuation", "Valuation and Total"] and \
|
||||||
item.item_code in self.stock_items:
|
item.item_code in self.stock_items:
|
||||||
item.item_tax_amount += flt(current_tax_amount,
|
item.item_tax_amount += flt(current_tax_amount,
|
||||||
self.precision.item.item_tax_amount)
|
self.precision_of("item_tax_amount", item.parentfield))
|
||||||
|
|
||||||
# update valuation rate
|
# update valuation rate
|
||||||
def update_valuation_rate(self, parentfield):
|
def update_valuation_rate(self, parentfield):
|
||||||
@ -427,18 +427,6 @@ class BuyingController(StockController):
|
|||||||
|
|
||||||
return bom_items
|
return bom_items
|
||||||
|
|
||||||
|
|
||||||
@property
|
|
||||||
def precision(self):
|
|
||||||
if not hasattr(self, "_precision"):
|
|
||||||
self._precision = webnotes._dict()
|
|
||||||
self._precision.main = self.meta.get_precision_map()
|
|
||||||
self._precision.item = self.meta.get_precision_map(parentfield = self.fname)
|
|
||||||
if self.meta.get_field("purchase_tax_details"):
|
|
||||||
self._precision.tax = self.meta.get_precision_map(parentfield = \
|
|
||||||
"purchase_tax_details")
|
|
||||||
return self._precision
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def sub_contracted_items(self):
|
def sub_contracted_items(self):
|
||||||
if not hasattr(self, "_sub_contracted_items"):
|
if not hasattr(self, "_sub_contracted_items"):
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
from webnotes.utils import cint
|
from webnotes.utils import cint, flt
|
||||||
from setup.utils import get_company_currency
|
from setup.utils import get_company_currency
|
||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
|
import json
|
||||||
|
|
||||||
from controllers.stock_controller import StockController
|
from controllers.stock_controller import StockController
|
||||||
|
|
||||||
@ -71,3 +72,279 @@ class SellingController(StockController):
|
|||||||
if item.buying_amount and not item.cost_center:
|
if item.buying_amount and not item.cost_center:
|
||||||
msgprint(_("""Cost Center is mandatory for item: """) + item.item_code,
|
msgprint(_("""Cost Center is mandatory for item: """) + item.item_code,
|
||||||
raise_exception=1)
|
raise_exception=1)
|
||||||
|
|
||||||
|
def calculate_taxes_and_totals(self):
|
||||||
|
self.doc.conversion_rate = flt(self.doc.conversion_rate)
|
||||||
|
self.item_doclist = self.doclist.get({"parentfield": self.fname})
|
||||||
|
self.tax_doclist = self.doclist.get({"parentfield": "other_charges"})
|
||||||
|
|
||||||
|
self.calculate_item_values()
|
||||||
|
self.initialize_taxes()
|
||||||
|
|
||||||
|
self.determin_exclusive_rate()
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
# code: save net_total_export on client side
|
||||||
|
# print format: show net_total_export instead of net_total
|
||||||
|
|
||||||
|
self.calculate_net_total()
|
||||||
|
self.calculate_taxes()
|
||||||
|
self.calculate_totals()
|
||||||
|
# self.calculate_outstanding_amount()
|
||||||
|
#
|
||||||
|
self._cleanup()
|
||||||
|
|
||||||
|
def determin_exclusive_rate(self):
|
||||||
|
if not any((cint(tax.included_in_print_rate) for tax in self.tax_doclist)):
|
||||||
|
# no inclusive tax
|
||||||
|
return
|
||||||
|
|
||||||
|
for item in self.item_doclist:
|
||||||
|
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
|
||||||
|
cumulated_tax_fraction = 0
|
||||||
|
for i, tax in enumerate(self.tax_doclist):
|
||||||
|
if cint(tax.included_in_print_rate):
|
||||||
|
tax.tax_fraction_for_current_item = \
|
||||||
|
self.get_current_tax_fraction(tax, item_tax_map)
|
||||||
|
else:
|
||||||
|
tax.tax_fraction_for_current_item = 0
|
||||||
|
|
||||||
|
if i==0:
|
||||||
|
tax.grand_total_fraction_for_current_item = 1 + \
|
||||||
|
tax.tax_fraction_for_current_item
|
||||||
|
else:
|
||||||
|
tax.grand_total_fraction_for_current_item = \
|
||||||
|
self.tax_doclist[i-1].grand_total_fraction_for_current_item \
|
||||||
|
+ tax.tax_fraction_for_current_item
|
||||||
|
|
||||||
|
cumulated_tax_fraction += tax.tax_fraction_for_current_item
|
||||||
|
|
||||||
|
if cumulated_tax_fraction:
|
||||||
|
item.basic_rate = flt((item.export_rate * self.doc.conversion_rate) /
|
||||||
|
(1 + cumulated_tax_fraction), self.precision_of("basic_rate", item.parentfield))
|
||||||
|
|
||||||
|
item.amount = flt(item.basic_rate * item.qty, self.precision_of("amount", item.parentfield))
|
||||||
|
|
||||||
|
item.base_ref_rate = flt(item.basic_rate / (1 - (item.adj_rate / 100.0)),
|
||||||
|
self.precision_of("base_ref_rate", item.parentfield))
|
||||||
|
|
||||||
|
def get_current_tax_fraction(self, tax, item_tax_map):
|
||||||
|
"""
|
||||||
|
Get tax fraction for calculating tax exclusive amount
|
||||||
|
from tax inclusive amount
|
||||||
|
"""
|
||||||
|
current_tax_fraction = 0
|
||||||
|
|
||||||
|
if cint(tax.included_in_print_rate):
|
||||||
|
tax_rate = self._get_tax_rate(tax, item_tax_map)
|
||||||
|
|
||||||
|
if tax.charge_type == "On Net Total":
|
||||||
|
current_tax_fraction = tax_rate / 100.0
|
||||||
|
|
||||||
|
elif tax.charge_type == "On Previous Row Amount":
|
||||||
|
current_tax_fraction = (tax_rate / 100.0) * \
|
||||||
|
self.tax_doclist[cint(tax.row_id) - 1].tax_fraction_for_current_item
|
||||||
|
|
||||||
|
elif tax.charge_type == "On Previous Row Total":
|
||||||
|
current_tax_fraction = (tax_rate / 100.0) * \
|
||||||
|
self.tax_doclist[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
|
||||||
|
|
||||||
|
return current_tax_fraction
|
||||||
|
|
||||||
|
def calculate_item_values(self):
|
||||||
|
def _set_base(item, print_field, base_field):
|
||||||
|
"""set values in base currency"""
|
||||||
|
item.fields[base_field] = flt((flt(item.fields[print_field],
|
||||||
|
self.precision_of(print_field, item.parentfield)) * self.doc.conversion_rate),
|
||||||
|
self.precision_of(base_field, item.parentfield))
|
||||||
|
|
||||||
|
for item in self.item_doclist:
|
||||||
|
self.round_floats_in_doc(item, item.parentfield)
|
||||||
|
|
||||||
|
if item.adj_rate == 100:
|
||||||
|
item.ref_rate = item.ref_rate or item.export_rate
|
||||||
|
item.export_rate = 0
|
||||||
|
else:
|
||||||
|
if item.ref_rate:
|
||||||
|
item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)),
|
||||||
|
self.precision_of("export_rate", item.parentfield))
|
||||||
|
else:
|
||||||
|
# assume that print rate and discount are specified
|
||||||
|
item.ref_rate = flt(item.export_rate / (1.0 - (item.adj_rate / 100.0)),
|
||||||
|
self.precision_of("ref_rate", item.parentfield))
|
||||||
|
|
||||||
|
item.export_amount = flt(item.export_rate * item.qty,
|
||||||
|
self.precision_of("export_amount", item.parentfield))
|
||||||
|
|
||||||
|
_set_base(item, "ref_rate", "base_ref_rate")
|
||||||
|
_set_base(item, "export_rate", "basic_rate")
|
||||||
|
_set_base(item, "export_amount", "amount")
|
||||||
|
|
||||||
|
def initialize_taxes(self):
|
||||||
|
for tax in self.tax_doclist:
|
||||||
|
tax.tax_amount = tax.total = 0.0
|
||||||
|
# temporary fields
|
||||||
|
tax.tax_amount_for_current_item = tax.grand_total_for_current_item = 0.0
|
||||||
|
tax.item_wise_tax_detail = {}
|
||||||
|
self.validate_on_previous_row(tax)
|
||||||
|
self.validate_inclusive_tax(tax)
|
||||||
|
self.round_floats_in_doc(tax, tax.parentfield)
|
||||||
|
|
||||||
|
def calculate_net_total(self):
|
||||||
|
self.doc.net_total = 0
|
||||||
|
self.doc.net_total_export = 0
|
||||||
|
|
||||||
|
for item in self.item_doclist:
|
||||||
|
self.doc.net_total += item.amount
|
||||||
|
self.doc.net_total_export += item.export_amount
|
||||||
|
|
||||||
|
self.doc.net_total = flt(self.doc.net_total, self.precision_of("net_total"))
|
||||||
|
self.doc.net_total_export = flt(self.doc.net_total_export,
|
||||||
|
self.precision_of("net_total_export"))
|
||||||
|
|
||||||
|
def calculate_taxes(self):
|
||||||
|
for item in self.item_doclist:
|
||||||
|
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
|
||||||
|
|
||||||
|
for i, tax in enumerate(self.tax_doclist):
|
||||||
|
# tax_amount represents the amount of tax for the current step
|
||||||
|
current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map)
|
||||||
|
|
||||||
|
# case when net total is 0 but there is an actual type charge
|
||||||
|
# in this case add the actual amount to tax.tax_amount
|
||||||
|
# and tax.grand_total_for_current_item for the first such iteration
|
||||||
|
if not (current_tax_amount or self.doc.net_total or tax.tax_amount) and \
|
||||||
|
tax.charge_type=="Actual":
|
||||||
|
zero_net_total_adjustment = flt(tax.rate, self.precision_of("tax_amount", tax.parentfield))
|
||||||
|
current_tax_amount += zero_net_total_adjustment
|
||||||
|
|
||||||
|
# store tax_amount for current item as it will be used for
|
||||||
|
# charge type = 'On Previous Row Amount'
|
||||||
|
tax.tax_amount_for_current_item = current_tax_amount
|
||||||
|
|
||||||
|
# accumulate tax amount into tax.tax_amount
|
||||||
|
tax.tax_amount += tax.tax_amount_for_current_item
|
||||||
|
|
||||||
|
# Calculate tax.total viz. grand total till that step
|
||||||
|
# note: grand_total_for_current_item contains the contribution of
|
||||||
|
# item's amount, previously applied tax and the current tax on that item
|
||||||
|
if i==0:
|
||||||
|
tax.grand_total_for_current_item = flt(item.amount +
|
||||||
|
current_tax_amount, self.precision_of("total", tax.parentfield))
|
||||||
|
|
||||||
|
else:
|
||||||
|
tax.grand_total_for_current_item = \
|
||||||
|
flt(self.tax_doclist[i-1].grand_total_for_current_item +
|
||||||
|
current_tax_amount, self.precision_of("total", tax.parentfield))
|
||||||
|
|
||||||
|
# in tax.total, accumulate grand total of each item
|
||||||
|
tax.total += tax.grand_total_for_current_item
|
||||||
|
|
||||||
|
# store tax_breakup for each item
|
||||||
|
# DOUBT: should valuation type amount also be stored?
|
||||||
|
tax.item_wise_tax_detail[item.item_code] = current_tax_amount
|
||||||
|
|
||||||
|
def calculate_totals(self):
|
||||||
|
self.doc.grand_total = flt(self.tax_doclist and \
|
||||||
|
self.tax_doclist[-1].total or self.doc.net_total, self.precision_of("grand_total"))
|
||||||
|
self.doc.grand_total_export = flt(self.doc.grand_total / self.doc.conversion_rate,
|
||||||
|
self.precision_of("grand_total_export"))
|
||||||
|
|
||||||
|
self.doc.rounded_total = round(self.doc.grand_total)
|
||||||
|
self.doc.rounded_total_export = round(self.doc.grand_total_export)
|
||||||
|
|
||||||
|
def get_current_tax_amount(self, item, tax, item_tax_map):
|
||||||
|
tax_rate = self._get_tax_rate(tax, item_tax_map)
|
||||||
|
|
||||||
|
if tax.charge_type == "Actual":
|
||||||
|
# distribute the tax amount proportionally to each item row
|
||||||
|
actual = flt(tax.rate, self.precision_of("tax_amount", tax.parentfield))
|
||||||
|
current_tax_amount = (self.doc.net_total
|
||||||
|
and ((item.amount / self.doc.net_total) * actual)
|
||||||
|
or 0)
|
||||||
|
elif tax.charge_type == "On Net Total":
|
||||||
|
current_tax_amount = (tax_rate / 100.0) * item.amount
|
||||||
|
elif tax.charge_type == "On Previous Row Amount":
|
||||||
|
current_tax_amount = (tax_rate / 100.0) * \
|
||||||
|
self.tax_doclist[cint(tax.row_id) - 1].tax_amount_for_current_item
|
||||||
|
elif tax.charge_type == "On Previous Row Total":
|
||||||
|
current_tax_amount = (tax_rate / 100.0) * \
|
||||||
|
self.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item
|
||||||
|
|
||||||
|
return flt(current_tax_amount, self.precision_of("tax_amount", tax.parentfield))
|
||||||
|
|
||||||
|
def validate_on_previous_row(self, tax):
|
||||||
|
"""
|
||||||
|
validate if a valid row id is mentioned in case of
|
||||||
|
On Previous Row Amount and On Previous Row Total
|
||||||
|
"""
|
||||||
|
if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"] and \
|
||||||
|
(not tax.row_id or cint(tax.row_id) >= tax.idx):
|
||||||
|
msgprint((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \
|
||||||
|
_("Please specify a valid") + " %(row_id_label)s") % {
|
||||||
|
"idx": tax.idx,
|
||||||
|
"taxes_doctype": tax.parenttype,
|
||||||
|
"row_id_label": self.meta.get_label("row_id",
|
||||||
|
parentfield="other_charges")
|
||||||
|
}, raise_exception=True)
|
||||||
|
|
||||||
|
def validate_inclusive_tax(self, tax):
|
||||||
|
def _on_previous_row_error(tax, row_range):
|
||||||
|
msgprint((_("Row")
|
||||||
|
+ " # %(idx)s [%(taxes_doctype)s] [%(charge_type_label)s = \"%(charge_type)s\"]: "
|
||||||
|
+ _("If:") + ' "%(inclusive_label)s" = ' + _("checked") + ", "
|
||||||
|
+ _("then it is required that:") + " [" + _("Row") + " # %(row_range)s] "
|
||||||
|
+ '"%(inclusive_label)s" = ' + _("checked")) % {
|
||||||
|
"idx": tax.idx,
|
||||||
|
"taxes_doctype": tax.doctype,
|
||||||
|
"inclusive_label": self.meta.get_label("included_in_print_rate",
|
||||||
|
parentfield="other_charges"),
|
||||||
|
"charge_type_label": self.meta.get_label("charge_type",
|
||||||
|
parentfield="other_charges"),
|
||||||
|
"charge_type": tax.charge_type,
|
||||||
|
"row_range": row_range
|
||||||
|
}, raise_exception=True)
|
||||||
|
|
||||||
|
if cint(tax.included_in_print_rate):
|
||||||
|
if tax.charge_type == "Actual":
|
||||||
|
# inclusive cannot be of type Actual
|
||||||
|
msgprint((_("Row")
|
||||||
|
+ " # %(idx)s [%(taxes_doctype)s]: %(charge_type_label)s = \"%(charge_type)s\" "
|
||||||
|
+ "cannot be included in Item's rate") % {
|
||||||
|
"idx": tax.idx,
|
||||||
|
"taxes_doctype": tax.doctype,
|
||||||
|
"charge_type_label": self.meta.get_label("charge_type",
|
||||||
|
parentfield="other_charges"),
|
||||||
|
"charge_type": tax.charge_type,
|
||||||
|
}, raise_exception=True)
|
||||||
|
elif tax.charge_type == "On Previous Row Amount" and \
|
||||||
|
not cint(self.tax_doclist[tax.row_id - 1].included_in_print_rate):
|
||||||
|
# referred row should also be inclusive
|
||||||
|
_on_previous_row_error(tax, tax.row_id)
|
||||||
|
elif tax.charge_type == "On Previous Row Total" and \
|
||||||
|
not all([cint(t.included_in_print_rate) for t in self.tax_doclist[:tax.idx - 1]]):
|
||||||
|
# all rows about this tax should be inclusive
|
||||||
|
_on_previous_row_error(tax, "1 - %d" % (tax.idx - 1,))
|
||||||
|
|
||||||
|
def _load_item_tax_rate(self, item_tax_rate):
|
||||||
|
if not item_tax_rate:
|
||||||
|
return {}
|
||||||
|
return json.loads(item_tax_rate)
|
||||||
|
|
||||||
|
def _get_tax_rate(self, tax, item_tax_map):
|
||||||
|
if item_tax_map.has_key(tax.account_head):
|
||||||
|
return flt(item_tax_map.get(tax.account_head), self.precision_of("rate", tax.parentfield))
|
||||||
|
else:
|
||||||
|
return tax.rate
|
||||||
|
|
||||||
|
def _cleanup(self):
|
||||||
|
for tax in self.tax_doclist:
|
||||||
|
del tax.fields["grand_total_for_current_item"]
|
||||||
|
del tax.fields["tax_amount_for_current_item"]
|
||||||
|
|
||||||
|
for fieldname in ("tax_fraction_for_current_item",
|
||||||
|
"grand_total_fraction_for_current_item"):
|
||||||
|
if fieldname in tax.fields:
|
||||||
|
del tax.fields[fieldname]
|
||||||
|
|
||||||
|
tax.item_wise_tax_detail = json.dumps(tax.item_wise_tax_detail)
|
||||||
|
0
patches/may_2013/__init__.py
Normal file
0
patches/may_2013/__init__.py
Normal file
10
patches/may_2013/p01_selling_net_total_export.py
Normal file
10
patches/may_2013/p01_selling_net_total_export.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import webnotes
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
for module, doctype in (("Accounts", "Sales Invoice"), ("Selling", "Sales Order"), ("Selling", "Quotation"),
|
||||||
|
("Stock", "Delivery Note")):
|
||||||
|
webnotes.reload_doc(module, "DocType", doctype)
|
||||||
|
webnotes.conn.sql("""update `tab%s`
|
||||||
|
set net_total_export = round(net_total / if(conversion_rate=0, 1, ifnull(conversion_rate, 1)), 2)""" %
|
||||||
|
(doctype,))
|
@ -250,4 +250,5 @@ patch_list = [
|
|||||||
"patches.april_2013.p07_update_file_data_2",
|
"patches.april_2013.p07_update_file_data_2",
|
||||||
"patches.april_2013.rebuild_sales_browser",
|
"patches.april_2013.rebuild_sales_browser",
|
||||||
"patches.april_2013.p08_price_list_country",
|
"patches.april_2013.p08_price_list_country",
|
||||||
|
"patches.may_2013.p01_selling_net_total_export",
|
||||||
]
|
]
|
@ -1,8 +1,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"creation": "2013-04-03 09:10:44",
|
"creation": "2013-05-06 12:03:40",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-04-03 09:58:02",
|
"modified": "2013-05-06 13:07:37",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -239,11 +239,19 @@
|
|||||||
"oldfieldname": "net_total",
|
"oldfieldname": "net_total",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"print_hide": 0,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "net_total_export",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Net Total (Export)",
|
||||||
|
"options": "currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "recalculate_values",
|
"fieldname": "recalculate_values",
|
||||||
|
@ -519,6 +519,8 @@ cur_frm.cscript.calc_doc_values = function(doc, cdt, cdn, tname, fname, other_fn
|
|||||||
net_total_incl *= flt(doc.conversion_rate);
|
net_total_incl *= flt(doc.conversion_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: store net_total_export
|
||||||
|
|
||||||
doc.net_total = inclusive_rate ? flt(net_total_incl) : flt(net_total);
|
doc.net_total = inclusive_rate ? flt(net_total_incl) : flt(net_total);
|
||||||
doc.other_charges_total = roundNumber(flt(other_charges_total), 2);
|
doc.other_charges_total = roundNumber(flt(other_charges_total), 2);
|
||||||
doc.grand_total = roundNumber((flt(net_total) + flt(other_charges_total)), 2);
|
doc.grand_total = roundNumber((flt(net_total) + flt(other_charges_total)), 2);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"creation": "2013-03-07 14:48:34",
|
"creation": "2013-05-06 12:03:43",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-01-29 17:14:58",
|
"modified": "2013-05-06 13:06:37",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -251,11 +251,19 @@
|
|||||||
"oldfieldname": "net_total",
|
"oldfieldname": "net_total",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"print_hide": 0,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "net_total_export",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Net Total (Export)",
|
||||||
|
"options": "currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "recalculate_values",
|
"fieldname": "recalculate_values",
|
||||||
@ -955,7 +963,6 @@
|
|||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "",
|
|
||||||
"permlevel": 1,
|
"permlevel": 1,
|
||||||
"report": 0,
|
"report": 0,
|
||||||
"role": "Sales Manager",
|
"role": "Sales Manager",
|
||||||
@ -978,7 +985,6 @@
|
|||||||
"cancel": 1,
|
"cancel": 1,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "",
|
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Sales User",
|
"role": "Sales User",
|
||||||
@ -990,7 +996,6 @@
|
|||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "",
|
|
||||||
"permlevel": 1,
|
"permlevel": 1,
|
||||||
"report": 0,
|
"report": 0,
|
||||||
"role": "Sales User",
|
"role": "Sales User",
|
||||||
@ -1013,7 +1018,6 @@
|
|||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "",
|
|
||||||
"permlevel": 1,
|
"permlevel": 1,
|
||||||
"role": "Maintenance Manager",
|
"role": "Maintenance Manager",
|
||||||
"submit": 0
|
"submit": 0
|
||||||
@ -1034,7 +1038,6 @@
|
|||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "",
|
|
||||||
"permlevel": 1,
|
"permlevel": 1,
|
||||||
"role": "Maintenance User",
|
"role": "Maintenance User",
|
||||||
"submit": 0
|
"submit": 0
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"creation": "2013-04-02 10:50:50",
|
"creation": "2013-05-06 12:03:30",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-02-02 19:18:38",
|
"modified": "2013-05-06 13:08:13",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -255,12 +255,20 @@
|
|||||||
"oldfieldname": "net_total",
|
"oldfieldname": "net_total",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"print_hide": 0,
|
"print_hide": 1,
|
||||||
"print_width": "150px",
|
"print_width": "150px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "net_total_export",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Net Total (Export)",
|
||||||
|
"options": "currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "recalculate_values",
|
"fieldname": "recalculate_values",
|
||||||
@ -1136,7 +1144,6 @@
|
|||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "",
|
|
||||||
"permlevel": 1,
|
"permlevel": 1,
|
||||||
"report": 0,
|
"report": 0,
|
||||||
"role": "Material User",
|
"role": "Material User",
|
||||||
@ -1159,7 +1166,6 @@
|
|||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "",
|
|
||||||
"permlevel": 1,
|
"permlevel": 1,
|
||||||
"report": 0,
|
"report": 0,
|
||||||
"role": "Material Manager",
|
"role": "Material Manager",
|
||||||
@ -1171,7 +1177,6 @@
|
|||||||
"cancel": 1,
|
"cancel": 1,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "",
|
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Sales User",
|
"role": "Sales User",
|
||||||
@ -1183,7 +1188,6 @@
|
|||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "",
|
|
||||||
"permlevel": 1,
|
"permlevel": 1,
|
||||||
"report": 0,
|
"report": 0,
|
||||||
"role": "Sales User",
|
"role": "Sales User",
|
||||||
@ -1205,7 +1209,6 @@
|
|||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"doctype": "DocPerm",
|
"doctype": "DocPerm",
|
||||||
"match": "",
|
|
||||||
"permlevel": 1,
|
"permlevel": 1,
|
||||||
"role": "Accounts User",
|
"role": "Accounts User",
|
||||||
"submit": 0
|
"submit": 0
|
||||||
|
@ -450,6 +450,7 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
for d in pi.doclist.get({"parentfield": "entries"}):
|
for d in pi.doclist.get({"parentfield": "entries"}):
|
||||||
d.expense_head = "_Test Account Cost for Goods Sold - _TC"
|
d.expense_head = "_Test Account Cost for Goods Sold - _TC"
|
||||||
d.cost_center = "_Test Cost Center - _TC"
|
d.cost_center = "_Test Cost Center - _TC"
|
||||||
|
|
||||||
for d in pi.doclist.get({"parentfield": "purchase_tax_details"}):
|
for d in pi.doclist.get({"parentfield": "purchase_tax_details"}):
|
||||||
d.cost_center = "_Test Cost Center - _TC"
|
d.cost_center = "_Test Cost Center - _TC"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user