mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-26 00:14:50 +00:00
fix: einvoice test (#24463)
This commit is contained in:
@@ -1877,23 +1877,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
def test_einvoice_json(self):
|
def test_einvoice_json(self):
|
||||||
from erpnext.regional.india.e_invoice.utils import make_einvoice
|
from erpnext.regional.india.e_invoice.utils import make_einvoice
|
||||||
|
|
||||||
customer_gstin = '27AACCM7806M1Z3'
|
|
||||||
customer_gstin_dtls = {
|
|
||||||
'LegalName': '_Test Customer', 'TradeName': '_Test Customer', 'AddrLoc': '_Test City',
|
|
||||||
'StateCode': '27', 'AddrPncd': '410038', 'AddrBno': '_Test Bldg',
|
|
||||||
'AddrBnm': '100', 'AddrFlno': '200', 'AddrSt': '_Test Street'
|
|
||||||
}
|
|
||||||
company_gstin = '27AAECE4835E1ZR'
|
|
||||||
company_gstin_dtls = {
|
|
||||||
'LegalName': '_Test Company', 'TradeName': '_Test Company', 'AddrLoc': '_Test City',
|
|
||||||
'StateCode': '27', 'AddrPncd': '401108', 'AddrBno': '_Test Bldg',
|
|
||||||
'AddrBnm': '100', 'AddrFlno': '200', 'AddrSt': '_Test Street'
|
|
||||||
}
|
|
||||||
# set cache gstin details to avoid fetching details which will require connection to GSP servers
|
|
||||||
frappe.local.gstin_cache = {}
|
|
||||||
frappe.local.gstin_cache[customer_gstin] = customer_gstin_dtls
|
|
||||||
frappe.local.gstin_cache[company_gstin] = company_gstin_dtls
|
|
||||||
|
|
||||||
si = make_sales_invoice_for_ewaybill()
|
si = make_sales_invoice_for_ewaybill()
|
||||||
si.naming_series = 'INV-2020-.#####'
|
si.naming_series = 'INV-2020-.#####'
|
||||||
si.items = []
|
si.items = []
|
||||||
@@ -1901,8 +1884,8 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
"item_code": "_Test Item",
|
"item_code": "_Test Item",
|
||||||
"uom": "Nos",
|
"uom": "Nos",
|
||||||
"warehouse": "_Test Warehouse - _TC",
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
"qty": 2,
|
"qty": 2000,
|
||||||
"rate": 100,
|
"rate": 12,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"expense_account": "Cost of Goods Sold - _TC",
|
"expense_account": "Cost of Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
@@ -1911,31 +1894,50 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
"item_code": "_Test Item 2",
|
"item_code": "_Test Item 2",
|
||||||
"uom": "Nos",
|
"uom": "Nos",
|
||||||
"warehouse": "_Test Warehouse - _TC",
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
"qty": 4,
|
"qty": 420,
|
||||||
"rate": 150,
|
"rate": 15,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"expense_account": "Cost of Goods Sold - _TC",
|
"expense_account": "Cost of Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
})
|
})
|
||||||
|
si.discount_amount = 100
|
||||||
si.save()
|
si.save()
|
||||||
|
|
||||||
einvoice = make_einvoice(si)
|
einvoice = make_einvoice(si)
|
||||||
|
|
||||||
total_item_ass_value = sum([d['AssAmt'] for d in einvoice['ItemList']])
|
total_item_ass_value = 0
|
||||||
total_item_cgst_value = sum([d['CgstAmt'] for d in einvoice['ItemList']])
|
total_item_cgst_value = 0
|
||||||
total_item_sgst_value = sum([d['SgstAmt'] for d in einvoice['ItemList']])
|
total_item_sgst_value = 0
|
||||||
total_item_igst_value = sum([d['IgstAmt'] for d in einvoice['ItemList']])
|
total_item_igst_value = 0
|
||||||
total_item_value = sum([d['TotItemVal'] for d in einvoice['ItemList']])
|
total_item_value = 0
|
||||||
|
|
||||||
|
for item in einvoice['ItemList']:
|
||||||
|
total_item_ass_value += item['AssAmt']
|
||||||
|
total_item_cgst_value += item['CgstAmt']
|
||||||
|
total_item_sgst_value += item['SgstAmt']
|
||||||
|
total_item_igst_value += item['IgstAmt']
|
||||||
|
total_item_value += item['TotItemVal']
|
||||||
|
|
||||||
|
self.assertTrue(item['AssAmt'], item['TotAmt'] - item['Discount'])
|
||||||
|
self.assertTrue(item['TotItemVal'], item['AssAmt'] + item['CgstAmt'] + item['SgstAmt'] + item['IgstAmt'])
|
||||||
|
|
||||||
|
value_details = einvoice['ValDtls']
|
||||||
|
|
||||||
self.assertEqual(einvoice['Version'], '1.1')
|
self.assertEqual(einvoice['Version'], '1.1')
|
||||||
self.assertEqual(einvoice['ValDtls']['AssVal'], total_item_ass_value)
|
self.assertTrue(abs(value_details['AssVal'] - total_item_ass_value) <= 1)
|
||||||
self.assertEqual(einvoice['ValDtls']['CgstVal'], total_item_cgst_value)
|
self.assertTrue(abs(value_details['CgstVal'] - total_item_cgst_value) <= 1)
|
||||||
self.assertEqual(einvoice['ValDtls']['SgstVal'], total_item_sgst_value)
|
self.assertTrue(abs(value_details['SgstVal'] - total_item_sgst_value) <= 1)
|
||||||
self.assertEqual(einvoice['ValDtls']['IgstVal'], total_item_igst_value)
|
self.assertTrue(abs(value_details['IgstVal'] - total_item_igst_value) <= 1)
|
||||||
self.assertEqual(einvoice['ValDtls']['TotInvVal'], total_item_value)
|
|
||||||
|
calculated_invoice_value = \
|
||||||
|
value_details['AssVal'] + value_details['CgstVal'] \
|
||||||
|
+ value_details['SgstVal'] + value_details['IgstVal'] \
|
||||||
|
+ value_details['OthChrg'] - value_details['Discount']
|
||||||
|
|
||||||
|
self.assertTrue(abs(value_details['TotInvVal'] - calculated_invoice_value) <= 1)
|
||||||
self.assertTrue(einvoice['EwbDtls'])
|
self.assertTrue(einvoice['EwbDtls'])
|
||||||
|
|
||||||
def make_sales_invoice_for_ewaybill():
|
def make_test_address_for_ewaybill():
|
||||||
if not frappe.db.exists('Address', '_Test Address for Eway bill-Billing'):
|
if not frappe.db.exists('Address', '_Test Address for Eway bill-Billing'):
|
||||||
address = frappe.get_doc({
|
address = frappe.get_doc({
|
||||||
"address_line1": "_Test Address Line 1",
|
"address_line1": "_Test Address Line 1",
|
||||||
@@ -1984,6 +1986,7 @@ def make_sales_invoice_for_ewaybill():
|
|||||||
|
|
||||||
address.save()
|
address.save()
|
||||||
|
|
||||||
|
def make_test_transporter_for_ewaybill():
|
||||||
if not frappe.db.exists('Supplier', '_Test Transporter'):
|
if not frappe.db.exists('Supplier', '_Test Transporter'):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Supplier",
|
"doctype": "Supplier",
|
||||||
@@ -1994,12 +1997,17 @@ def make_sales_invoice_for_ewaybill():
|
|||||||
"is_transporter": 1
|
"is_transporter": 1
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
|
def make_sales_invoice_for_ewaybill():
|
||||||
|
make_test_address_for_ewaybill()
|
||||||
|
make_test_transporter_for_ewaybill()
|
||||||
|
|
||||||
gst_settings = frappe.get_doc("GST Settings")
|
gst_settings = frappe.get_doc("GST Settings")
|
||||||
|
|
||||||
gst_account = frappe.get_all(
|
gst_account = frappe.get_all(
|
||||||
"GST Account",
|
"GST Account",
|
||||||
fields=["cgst_account", "sgst_account", "igst_account"],
|
fields=["cgst_account", "sgst_account", "igst_account"],
|
||||||
filters = {"company": "_Test Company"})
|
filters = {"company": "_Test Company"}
|
||||||
|
)
|
||||||
|
|
||||||
if not gst_account:
|
if not gst_account:
|
||||||
gst_settings.append("gst_accounts", {
|
gst_settings.append("gst_accounts", {
|
||||||
@@ -2011,7 +2019,7 @@ def make_sales_invoice_for_ewaybill():
|
|||||||
|
|
||||||
gst_settings.save()
|
gst_settings.save()
|
||||||
|
|
||||||
si = create_sales_invoice(do_not_save =1, rate = '60000')
|
si = create_sales_invoice(do_not_save=1, rate='60000')
|
||||||
|
|
||||||
si.distance = 2000
|
si.distance = 2000
|
||||||
si.company_address = "_Test Address for Eway bill-Billing"
|
si.company_address = "_Test Address for Eway bill-Billing"
|
||||||
@@ -2039,27 +2047,6 @@ def make_sales_invoice_for_ewaybill():
|
|||||||
|
|
||||||
return si
|
return si
|
||||||
|
|
||||||
def test_item_tax_validity(self):
|
|
||||||
item = frappe.get_doc("Item", "_Test Item 2")
|
|
||||||
|
|
||||||
if item.taxes:
|
|
||||||
item.taxes = []
|
|
||||||
item.save()
|
|
||||||
|
|
||||||
item.append("taxes", {
|
|
||||||
"item_tax_template": "_Test Item Tax Template 1",
|
|
||||||
"valid_from": add_days(nowdate(), 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
item.save()
|
|
||||||
|
|
||||||
sales_invoice = create_sales_invoice(item = "_Test Item 2", do_not_save=1)
|
|
||||||
sales_invoice.items[0].item_tax_template = "_Test Item Tax Template 1"
|
|
||||||
self.assertRaises(frappe.ValidationError, sales_invoice.save)
|
|
||||||
|
|
||||||
item.taxes = []
|
|
||||||
item.save()
|
|
||||||
|
|
||||||
def create_sales_invoice(**args):
|
def create_sales_invoice(**args):
|
||||||
si = frappe.new_doc("Sales Invoice")
|
si = frappe.new_doc("Sales Invoice")
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
{item_list}
|
{item_list}
|
||||||
],
|
],
|
||||||
"ValDtls": {{
|
"ValDtls": {{
|
||||||
"AssVal": "{invoice_value_details.base_net_total}",
|
"AssVal": "{invoice_value_details.base_total}",
|
||||||
"CgstVal": "{invoice_value_details.total_cgst_amt}",
|
"CgstVal": "{invoice_value_details.total_cgst_amt}",
|
||||||
"SgstVal": "{invoice_value_details.total_sgst_amt}",
|
"SgstVal": "{invoice_value_details.total_sgst_amt}",
|
||||||
"IgstVal": "{invoice_value_details.total_igst_amt}",
|
"IgstVal": "{invoice_value_details.total_igst_amt}",
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ def update_item_taxes(invoice, item):
|
|||||||
item[attr] = 0
|
item[attr] = 0
|
||||||
|
|
||||||
for t in invoice.taxes:
|
for t in invoice.taxes:
|
||||||
|
# this contains item wise tax rate & tax amount (incl. discount)
|
||||||
item_tax_detail = json.loads(t.item_wise_tax_detail).get(item.item_code)
|
item_tax_detail = json.loads(t.item_wise_tax_detail).get(item.item_code)
|
||||||
if t.account_head in gst_accounts_list:
|
if t.account_head in gst_accounts_list:
|
||||||
item_tax_rate = item_tax_detail[0]
|
item_tax_rate = item_tax_detail[0]
|
||||||
@@ -200,30 +201,30 @@ def update_item_taxes(invoice, item):
|
|||||||
item_tax_amount = (item_tax_rate / 100) * item.base_net_amount
|
item_tax_amount = (item_tax_rate / 100) * item.base_net_amount
|
||||||
|
|
||||||
if t.account_head in gst_accounts.cess_account:
|
if t.account_head in gst_accounts.cess_account:
|
||||||
|
item_tax_amount_after_discount = item_tax_detail[1]
|
||||||
if t.charge_type == 'On Item Quantity':
|
if t.charge_type == 'On Item Quantity':
|
||||||
item.cess_nadv_amount += abs(item_tax_detail[1])
|
item.cess_nadv_amount += abs(item_tax_amount_after_discount)
|
||||||
else:
|
else:
|
||||||
item.cess_rate += item_tax_detail[0]
|
item.cess_rate += item_tax_rate
|
||||||
item.cess_amount += abs(item_tax_detail[1])
|
item.cess_amount += abs(item_tax_amount_after_discount)
|
||||||
elif t.account_head in gst_accounts.igst_account:
|
|
||||||
item.tax_rate += item_tax_detail[0]
|
for tax_type in ['igst', 'cgst', 'sgst']:
|
||||||
item.igst_amount += abs(item_tax_detail[1])
|
if t.account_head in gst_accounts['{}_account'.format(tax_type)]:
|
||||||
elif t.account_head in gst_accounts.sgst_account:
|
item.tax_rate += item_tax_rate
|
||||||
item.tax_rate += item_tax_detail[0]
|
item['{}_amount'.format(tax_type)] += abs(item_tax_amount)
|
||||||
item.sgst_amount += abs(item_tax_detail[1])
|
|
||||||
elif t.account_head in gst_accounts.cgst_account:
|
|
||||||
item.tax_rate += item_tax_detail[0]
|
|
||||||
item.cgst_amount += abs(item_tax_detail[1])
|
|
||||||
|
|
||||||
return item
|
return item
|
||||||
|
|
||||||
def get_invoice_value_details(invoice):
|
def get_invoice_value_details(invoice):
|
||||||
invoice_value_details = frappe._dict(dict())
|
invoice_value_details = frappe._dict(dict())
|
||||||
|
|
||||||
if invoice.apply_discount_on == 'Net Total' and invoice.discount_amount:
|
if invoice.apply_discount_on == 'Net Total' and invoice.discount_amount:
|
||||||
invoice_value_details.base_total = abs(invoice.base_total)
|
invoice_value_details.base_total = abs(invoice.base_total)
|
||||||
else:
|
else:
|
||||||
invoice_value_details.base_total = abs(invoice.base_net_total)
|
invoice_value_details.base_total = abs(invoice.base_net_total)
|
||||||
invoice_value_details.invoice_discount_amt = invoice.base_discount_amount
|
|
||||||
|
# since tax already considers discount amount
|
||||||
|
invoice_value_details.invoice_discount_amt = 0 # invoice.base_discount_amount
|
||||||
invoice_value_details.round_off = invoice.base_rounding_adjustment
|
invoice_value_details.round_off = invoice.base_rounding_adjustment
|
||||||
invoice_value_details.base_grand_total = abs(invoice.base_rounded_total) or abs(invoice.base_grand_total)
|
invoice_value_details.base_grand_total = abs(invoice.base_rounded_total) or abs(invoice.base_grand_total)
|
||||||
invoice_value_details.grand_total = abs(invoice.rounded_total) or abs(invoice.grand_total)
|
invoice_value_details.grand_total = abs(invoice.rounded_total) or abs(invoice.grand_total)
|
||||||
@@ -244,13 +245,12 @@ def update_invoice_taxes(invoice, invoice_value_details):
|
|||||||
for t in invoice.taxes:
|
for t in invoice.taxes:
|
||||||
if t.account_head in gst_accounts_list:
|
if t.account_head in gst_accounts_list:
|
||||||
if t.account_head in gst_accounts.cess_account:
|
if t.account_head in gst_accounts.cess_account:
|
||||||
|
# using after discount amt since item also uses after discount amt for cess calc
|
||||||
invoice_value_details.total_cess_amt += abs(t.base_tax_amount_after_discount_amount)
|
invoice_value_details.total_cess_amt += abs(t.base_tax_amount_after_discount_amount)
|
||||||
elif t.account_head in gst_accounts.igst_account:
|
|
||||||
invoice_value_details.total_igst_amt += abs(t.base_tax_amount_after_discount_amount)
|
for tax_type in ['igst', 'cgst', 'sgst']:
|
||||||
elif t.account_head in gst_accounts.sgst_account:
|
if t.account_head in gst_accounts['{}_account'.format(tax_type)]:
|
||||||
invoice_value_details.total_sgst_amt += abs(t.base_tax_amount_after_discount_amount)
|
invoice_value_details['total_{}_amt'.format(tax_type)] += abs(t.base_tax_amount_after_discount_amount)
|
||||||
elif t.account_head in gst_accounts.cgst_account:
|
|
||||||
invoice_value_details.total_cgst_amt += abs(t.base_tax_amount_after_discount_amount)
|
|
||||||
else:
|
else:
|
||||||
invoice_value_details.total_other_charges += abs(t.base_tax_amount_after_discount_amount)
|
invoice_value_details.total_other_charges += abs(t.base_tax_amount_after_discount_amount)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user