mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-26 08:24:47 +00:00
chore: add tests
This commit is contained in:
@@ -1841,94 +1841,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
self.assertEqual(target_doc.supplier, "_Test Internal Supplier")
|
self.assertEqual(target_doc.supplier, "_Test Internal Supplier")
|
||||||
|
|
||||||
def test_eway_bill_json(self):
|
def test_eway_bill_json(self):
|
||||||
if not frappe.db.exists('Address', '_Test Address for Eway bill-Billing'):
|
si = make_sales_invoice_for_ewaybill()
|
||||||
address = frappe.get_doc({
|
|
||||||
"address_line1": "_Test Address Line 1",
|
|
||||||
"address_title": "_Test Address for Eway bill",
|
|
||||||
"address_type": "Billing",
|
|
||||||
"city": "_Test City",
|
|
||||||
"state": "Test State",
|
|
||||||
"country": "India",
|
|
||||||
"doctype": "Address",
|
|
||||||
"is_primary_address": 1,
|
|
||||||
"phone": "+91 0000000000",
|
|
||||||
"gstin": "27AAECE4835E1ZR",
|
|
||||||
"gst_state": "Maharashtra",
|
|
||||||
"gst_state_number": "27",
|
|
||||||
"pincode": "401108"
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
address.append("links", {
|
|
||||||
"link_doctype": "Company",
|
|
||||||
"link_name": "_Test Company"
|
|
||||||
})
|
|
||||||
|
|
||||||
address.save()
|
|
||||||
|
|
||||||
if not frappe.db.exists('Address', '_Test Customer-Address for Eway bill-Shipping'):
|
|
||||||
address = frappe.get_doc({
|
|
||||||
"address_line1": "_Test Address Line 1",
|
|
||||||
"address_title": "_Test Customer-Address for Eway bill",
|
|
||||||
"address_type": "Shipping",
|
|
||||||
"city": "_Test City",
|
|
||||||
"state": "Test State",
|
|
||||||
"country": "India",
|
|
||||||
"doctype": "Address",
|
|
||||||
"is_primary_address": 1,
|
|
||||||
"phone": "+91 0000000000",
|
|
||||||
"gst_state": "Maharashtra",
|
|
||||||
"gst_state_number": "27",
|
|
||||||
"pincode": "410038"
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
address.append("links", {
|
|
||||||
"link_doctype": "Customer",
|
|
||||||
"link_name": "_Test Customer"
|
|
||||||
})
|
|
||||||
|
|
||||||
address.save()
|
|
||||||
|
|
||||||
gst_settings = frappe.get_doc("GST Settings")
|
|
||||||
|
|
||||||
gst_account = frappe.get_all(
|
|
||||||
"GST Account",
|
|
||||||
fields=["cgst_account", "sgst_account", "igst_account"],
|
|
||||||
filters = {"company": "_Test Company"})
|
|
||||||
|
|
||||||
if not gst_account:
|
|
||||||
gst_settings.append("gst_accounts", {
|
|
||||||
"company": "_Test Company",
|
|
||||||
"cgst_account": "CGST - _TC",
|
|
||||||
"sgst_account": "SGST - _TC",
|
|
||||||
"igst_account": "IGST - _TC",
|
|
||||||
})
|
|
||||||
|
|
||||||
gst_settings.save()
|
|
||||||
|
|
||||||
si = create_sales_invoice(do_not_save =1, rate = '60000')
|
|
||||||
|
|
||||||
si.distance = 2000
|
|
||||||
si.company_address = "_Test Address for Eway bill-Billing"
|
|
||||||
si.customer_address = "_Test Customer-Address for Eway bill-Shipping"
|
|
||||||
si.vehicle_no = "KA12KA1234"
|
|
||||||
si.gst_category = "Registered Regular"
|
|
||||||
si.mode_of_transport = 'Road'
|
|
||||||
|
|
||||||
si.append("taxes", {
|
|
||||||
"charge_type": "On Net Total",
|
|
||||||
"account_head": "CGST - _TC",
|
|
||||||
"cost_center": "Main - _TC",
|
|
||||||
"description": "CGST @ 9.0",
|
|
||||||
"rate": 9
|
|
||||||
})
|
|
||||||
|
|
||||||
si.append("taxes", {
|
|
||||||
"charge_type": "On Net Total",
|
|
||||||
"account_head": "SGST - _TC",
|
|
||||||
"cost_center": "Main - _TC",
|
|
||||||
"description": "SGST @ 9.0",
|
|
||||||
"rate": 9
|
|
||||||
})
|
|
||||||
|
|
||||||
si.submit()
|
si.submit()
|
||||||
|
|
||||||
@@ -1944,6 +1857,187 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
self.assertEqual(data['billLists'][0]['sgstValue'], 5400)
|
self.assertEqual(data['billLists'][0]['sgstValue'], 5400)
|
||||||
self.assertEqual(data['billLists'][0]['vehicleNo'], 'KA12KA1234')
|
self.assertEqual(data['billLists'][0]['vehicleNo'], 'KA12KA1234')
|
||||||
self.assertEqual(data['billLists'][0]['itemList'][0]['taxableAmount'], 60000)
|
self.assertEqual(data['billLists'][0]['itemList'][0]['taxableAmount'], 60000)
|
||||||
|
|
||||||
|
def test_einvoice_submission_without_irn(self):
|
||||||
|
# init
|
||||||
|
frappe.db.set_value('E Invoice Settings', 'E Invoice Settings', 'enable', 1)
|
||||||
|
country = frappe.flags.country
|
||||||
|
frappe.flags.country = 'India'
|
||||||
|
|
||||||
|
si = make_sales_invoice_for_ewaybill()
|
||||||
|
self.assertRaises(frappe.ValidationError, si.submit)
|
||||||
|
|
||||||
|
si.irn = 'test_irn'
|
||||||
|
si.submit()
|
||||||
|
|
||||||
|
# reset
|
||||||
|
frappe.db.set_value('E Invoice Settings', 'E Invoice Settings', 'enable', 0)
|
||||||
|
frappe.flags.country = country
|
||||||
|
|
||||||
|
def test_einvoice_json(self):
|
||||||
|
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.naming_series = 'INV-2020-.#####'
|
||||||
|
si.items = []
|
||||||
|
si.append("items", {
|
||||||
|
"item_code": "_Test Item",
|
||||||
|
"uom": "Nos",
|
||||||
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
|
"qty": 2,
|
||||||
|
"rate": 100,
|
||||||
|
"income_account": "Sales - _TC",
|
||||||
|
"expense_account": "Cost of Goods Sold - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
})
|
||||||
|
si.append("items", {
|
||||||
|
"item_code": "_Test Item 2",
|
||||||
|
"uom": "Nos",
|
||||||
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
|
"qty": 4,
|
||||||
|
"rate": 150,
|
||||||
|
"income_account": "Sales - _TC",
|
||||||
|
"expense_account": "Cost of Goods Sold - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
})
|
||||||
|
si.save()
|
||||||
|
|
||||||
|
einvoice = make_einvoice(si)
|
||||||
|
|
||||||
|
total_item_ass_value = sum([d['AssAmt'] for d in einvoice['ItemList']])
|
||||||
|
total_item_cgst_value = sum([d['CgstAmt'] for d in einvoice['ItemList']])
|
||||||
|
total_item_sgst_value = sum([d['SgstAmt'] for d in einvoice['ItemList']])
|
||||||
|
total_item_igst_value = sum([d['IgstAmt'] for d in einvoice['ItemList']])
|
||||||
|
total_item_value = sum([d['TotItemVal'] for d in einvoice['ItemList']])
|
||||||
|
|
||||||
|
self.assertEqual(einvoice['Version'], '1.1')
|
||||||
|
self.assertEqual(einvoice['ValDtls']['AssVal'], total_item_ass_value)
|
||||||
|
self.assertEqual(einvoice['ValDtls']['CgstVal'], total_item_cgst_value)
|
||||||
|
self.assertEqual(einvoice['ValDtls']['SgstVal'], total_item_sgst_value)
|
||||||
|
self.assertEqual(einvoice['ValDtls']['IgstVal'], total_item_igst_value)
|
||||||
|
self.assertEqual(einvoice['ValDtls']['TotInvVal'], total_item_value)
|
||||||
|
self.assertTrue(einvoice['EwbDtls'])
|
||||||
|
|
||||||
|
def make_sales_invoice_for_ewaybill():
|
||||||
|
if not frappe.db.exists('Address', '_Test Address for Eway bill-Billing'):
|
||||||
|
address = frappe.get_doc({
|
||||||
|
"address_line1": "_Test Address Line 1",
|
||||||
|
"address_title": "_Test Address for Eway bill",
|
||||||
|
"address_type": "Billing",
|
||||||
|
"city": "_Test City",
|
||||||
|
"state": "Test State",
|
||||||
|
"country": "India",
|
||||||
|
"doctype": "Address",
|
||||||
|
"is_primary_address": 1,
|
||||||
|
"phone": "+910000000000",
|
||||||
|
"gstin": "27AAECE4835E1ZR",
|
||||||
|
"gst_state": "Maharashtra",
|
||||||
|
"gst_state_number": "27",
|
||||||
|
"pincode": "401108"
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
address.append("links", {
|
||||||
|
"link_doctype": "Company",
|
||||||
|
"link_name": "_Test Company"
|
||||||
|
})
|
||||||
|
|
||||||
|
address.save()
|
||||||
|
|
||||||
|
if not frappe.db.exists('Address', '_Test Customer-Address for Eway bill-Shipping'):
|
||||||
|
address = frappe.get_doc({
|
||||||
|
"address_line1": "_Test Address Line 1",
|
||||||
|
"address_title": "_Test Customer-Address for Eway bill",
|
||||||
|
"address_type": "Shipping",
|
||||||
|
"city": "_Test City",
|
||||||
|
"state": "Test State",
|
||||||
|
"country": "India",
|
||||||
|
"doctype": "Address",
|
||||||
|
"is_primary_address": 1,
|
||||||
|
"phone": "+910000000000",
|
||||||
|
"gstin": "27AACCM7806M1Z3",
|
||||||
|
"gst_state": "Maharashtra",
|
||||||
|
"gst_state_number": "27",
|
||||||
|
"pincode": "410038"
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
address.append("links", {
|
||||||
|
"link_doctype": "Customer",
|
||||||
|
"link_name": "_Test Customer"
|
||||||
|
})
|
||||||
|
|
||||||
|
address.save()
|
||||||
|
|
||||||
|
if not frappe.db.exists('Supplier', '_Test Transporter'):
|
||||||
|
supplier = frappe.get_doc({
|
||||||
|
"doctype": "Supplier",
|
||||||
|
"supplier_name": "_Test Transporter",
|
||||||
|
"country": "India",
|
||||||
|
"supplier_group": "_Test Supplier Group",
|
||||||
|
"supplier_type": "Company",
|
||||||
|
"is_transporter": 1
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
gst_settings = frappe.get_doc("GST Settings")
|
||||||
|
|
||||||
|
gst_account = frappe.get_all(
|
||||||
|
"GST Account",
|
||||||
|
fields=["cgst_account", "sgst_account", "igst_account"],
|
||||||
|
filters = {"company": "_Test Company"})
|
||||||
|
|
||||||
|
if not gst_account:
|
||||||
|
gst_settings.append("gst_accounts", {
|
||||||
|
"company": "_Test Company",
|
||||||
|
"cgst_account": "CGST - _TC",
|
||||||
|
"sgst_account": "SGST - _TC",
|
||||||
|
"igst_account": "IGST - _TC",
|
||||||
|
})
|
||||||
|
|
||||||
|
gst_settings.save()
|
||||||
|
|
||||||
|
si = create_sales_invoice(do_not_save =1, rate = '60000')
|
||||||
|
|
||||||
|
si.distance = 2000
|
||||||
|
si.company_address = "_Test Address for Eway bill-Billing"
|
||||||
|
si.customer_address = "_Test Customer-Address for Eway bill-Shipping"
|
||||||
|
si.vehicle_no = "KA12KA1234"
|
||||||
|
si.gst_category = "Registered Regular"
|
||||||
|
si.mode_of_transport = 'Road'
|
||||||
|
si.transporter = '_Test Transporter'
|
||||||
|
|
||||||
|
si.append("taxes", {
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "CGST - _TC",
|
||||||
|
"cost_center": "Main - _TC",
|
||||||
|
"description": "CGST @ 9.0",
|
||||||
|
"rate": 9
|
||||||
|
})
|
||||||
|
|
||||||
|
si.append("taxes", {
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "SGST - _TC",
|
||||||
|
"cost_center": "Main - _TC",
|
||||||
|
"description": "SGST @ 9.0",
|
||||||
|
"rate": 9
|
||||||
|
})
|
||||||
|
|
||||||
|
return si
|
||||||
|
|
||||||
def test_item_tax_validity(self):
|
def test_item_tax_validity(self):
|
||||||
item = frappe.get_doc("Item", "_Test Item 2")
|
item = frappe.get_doc("Item", "_Test Item 2")
|
||||||
|
|||||||
@@ -71,10 +71,7 @@ def get_trans_details(invoice):
|
|||||||
))
|
))
|
||||||
|
|
||||||
def get_doc_details(invoice):
|
def get_doc_details(invoice):
|
||||||
if invoice.doctype == 'Purchase Invoice' and invoice.is_return:
|
invoice_type = 'CRN' if invoice.is_return else 'INV'
|
||||||
invoice_type = 'DBN'
|
|
||||||
else:
|
|
||||||
invoice_type = 'CRN' if invoice.is_return else 'INV'
|
|
||||||
|
|
||||||
invoice_name = invoice.name
|
invoice_name = invoice.name
|
||||||
invoice_date = format_date(invoice.posting_date, 'dd/mm/yyyy')
|
invoice_date = format_date(invoice.posting_date, 'dd/mm/yyyy')
|
||||||
@@ -89,7 +86,7 @@ def get_party_details(address_name):
|
|||||||
address = frappe.get_all('Address', filters={'name': address_name}, fields=['*'])[0]
|
address = frappe.get_all('Address', filters={'name': address_name}, fields=['*'])[0]
|
||||||
gstin = address.get('gstin')
|
gstin = address.get('gstin')
|
||||||
|
|
||||||
gstin_details = GSPConnector.get_gstin_details(gstin)
|
gstin_details = get_gstin_details(gstin)
|
||||||
legal_name = gstin_details.get('LegalName')
|
legal_name = gstin_details.get('LegalName')
|
||||||
trade_name = gstin_details.get('TradeName')
|
trade_name = gstin_details.get('TradeName')
|
||||||
location = gstin_details.get('AddrLoc') or address.get('city')
|
location = gstin_details.get('AddrLoc') or address.get('city')
|
||||||
@@ -98,7 +95,7 @@ def get_party_details(address_name):
|
|||||||
address_line1 = '{} {}'.format(gstin_details.get('AddrBno'), gstin_details.get('AddrFlno'))
|
address_line1 = '{} {}'.format(gstin_details.get('AddrBno'), gstin_details.get('AddrFlno'))
|
||||||
address_line2 = '{} {}'.format(gstin_details.get('AddrBnm'), gstin_details.get('AddrSt'))
|
address_line2 = '{} {}'.format(gstin_details.get('AddrBnm'), gstin_details.get('AddrSt'))
|
||||||
email_id = address.get('email_id')
|
email_id = address.get('email_id')
|
||||||
phone = address.get('phone')
|
phone = address.get('phone').replace(" ", "")[-10:] # get last 10 digit
|
||||||
if state_code == 97:
|
if state_code == 97:
|
||||||
pincode = 999999
|
pincode = 999999
|
||||||
|
|
||||||
@@ -108,6 +105,23 @@ def get_party_details(address_name):
|
|||||||
address_line2=address_line2, email=email_id, phone=phone
|
address_line2=address_line2, email=email_id, phone=phone
|
||||||
))
|
))
|
||||||
|
|
||||||
|
def get_gstin_details(gstin):
|
||||||
|
if not hasattr(frappe.local, 'gstin_cache'):
|
||||||
|
frappe.local.gstin_cache = {}
|
||||||
|
|
||||||
|
key = gstin
|
||||||
|
details = frappe.local.gstin_cache.get(key)
|
||||||
|
if details:
|
||||||
|
return details
|
||||||
|
|
||||||
|
details = frappe.cache().hget('gstin_cache', key)
|
||||||
|
if details:
|
||||||
|
frappe.local.gstin_cache[key] = details
|
||||||
|
return details
|
||||||
|
|
||||||
|
if not details:
|
||||||
|
return GSPConnector.get_gstin_details(gstin)
|
||||||
|
|
||||||
def get_overseas_address_details(address_name):
|
def get_overseas_address_details(address_name):
|
||||||
address_title, address_line1, address_line2, city, phone, email_id = frappe.db.get_value(
|
address_title, address_line1, address_line2, city, phone, email_id = frappe.db.get_value(
|
||||||
'Address', address_name, ['address_title', 'address_line1', 'address_line2', 'city', 'phone', 'email_id']
|
'Address', address_name, ['address_title', 'address_line1', 'address_line2', 'city', 'phone', 'email_id']
|
||||||
@@ -180,9 +194,9 @@ def get_value_details(invoice):
|
|||||||
|
|
||||||
value_details = frappe._dict(dict())
|
value_details = frappe._dict(dict())
|
||||||
value_details.base_net_total = abs(invoice.base_net_total)
|
value_details.base_net_total = abs(invoice.base_net_total)
|
||||||
value_details.invoice_discount_amt = invoice.discount_amount if invoice.discount_amount > 0 else 0
|
value_details.invoice_discount_amt = invoice.discount_amount if invoice.discount_amount and invoice.discount_amount > 0 else 0
|
||||||
# discount amount cannnot be -ve in an e-invoice, so if -ve include discount in round_off
|
# discount amount cannnot be -ve in an e-invoice, so if -ve include discount in round_off
|
||||||
value_details.round_off = invoice.rounding_adjustment - (invoice.discount_amount if invoice.discount_amount < 0 else 0)
|
value_details.round_off = invoice.rounding_adjustment - (invoice.discount_amount if invoice.discount_amount and invoice.discount_amount < 0 else 0)
|
||||||
disable_rounded = frappe.db.get_single_value('Global Defaults', 'disable_rounded_total')
|
disable_rounded = frappe.db.get_single_value('Global Defaults', 'disable_rounded_total')
|
||||||
value_details.base_grand_total = abs(invoice.base_grand_total) if disable_rounded else invoice.base_rounded_total
|
value_details.base_grand_total = abs(invoice.base_grand_total) if disable_rounded else invoice.base_rounded_total
|
||||||
value_details.grand_total = abs(invoice.grand_total) if disable_rounded else invoice.rounded_total
|
value_details.grand_total = abs(invoice.grand_total) if disable_rounded else invoice.rounded_total
|
||||||
@@ -293,11 +307,7 @@ def make_einvoice(invoice):
|
|||||||
"Errors: ", json.dumps(errors, default=str, indent=4)
|
"Errors: ", json.dumps(errors, default=str, indent=4)
|
||||||
])
|
])
|
||||||
frappe.log_error(title="E Invoice Validation Failed", message=message)
|
frappe.log_error(title="E Invoice Validation Failed", message=message)
|
||||||
if len(errors) > 1:
|
frappe.throw(errors, title=_('E Invoice Validation Failed'), as_list=1)
|
||||||
li = ['<li>'+ d +'</li>' for d in errors]
|
|
||||||
frappe.throw("<ul style='padding-left: 20px'>{}</ul>".format(''.join(li)), title=_('E Invoice Validation Failed'))
|
|
||||||
else:
|
|
||||||
frappe.throw(errors[0], title=_('E Invoice Validation Failed'))
|
|
||||||
|
|
||||||
return einvoice
|
return einvoice
|
||||||
|
|
||||||
@@ -421,21 +431,9 @@ class GSPConnector():
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_gstin_details(gstin):
|
def get_gstin_details(gstin):
|
||||||
'''fetch or get cached GSTIN details'''
|
'''fetch and cache GSTIN details'''
|
||||||
|
|
||||||
if not hasattr(frappe.local, 'gstin_cache'):
|
|
||||||
frappe.local.gstin_cache = {}
|
|
||||||
|
|
||||||
key = gstin
|
key = gstin
|
||||||
details = frappe.local.gstin_cache.get(key)
|
|
||||||
if details:
|
|
||||||
return details
|
|
||||||
|
|
||||||
details = frappe.cache().hget('gstin_cache', key)
|
|
||||||
if details:
|
|
||||||
frappe.local.gstin_cache[key] = details
|
|
||||||
return details
|
|
||||||
|
|
||||||
gsp_connector = GSPConnector()
|
gsp_connector = GSPConnector()
|
||||||
details = gsp_connector.fetch_gstin_details(gstin)
|
details = gsp_connector.fetch_gstin_details(gstin)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user