diff --git a/india_compliance/gst_india/overrides/test_subcontracting_transaction.py b/india_compliance/gst_india/overrides/test_subcontracting_transaction.py index 44cc6f023..da84449f0 100644 --- a/india_compliance/gst_india/overrides/test_subcontracting_transaction.py +++ b/india_compliance/gst_india/overrides/test_subcontracting_transaction.py @@ -1,7 +1,7 @@ import re import frappe -from frappe.tests.utils import FrappeTestCase, change_settings +from frappe.tests.utils import FrappeTestCase from erpnext.controllers.subcontracting_controller import ( get_materials_from_supplier, make_rm_stock_entry, @@ -102,25 +102,14 @@ def make_item(item_code=None, properties=None): def create_purchase_order(**args): - po_dict = { - "doctype": "Purchase Order", - "supplier": args.get("supplier") or "_Test Registered Supplier", - "is_subcontracted": 1, - "items": args.get("items"), - "supplier_warehouse": "Finished Goods - _TIRC", - "do_not_save": 1, - "do_not_submit": 1, - } - - po = create_transaction(**po_dict) - - if po.is_subcontracted: - supp_items = po.get("supplied_items") - for d in supp_items: - if not d.reserve_warehouse: - d.reserve_warehouse = "Stores - _TIRC" + args.update( + { + "doctype": "Purchase Order", + "is_subcontracted": 1, + } + ) - return po.submit() + return create_transaction(**args) def make_stock_transfer_entry(**args): @@ -145,8 +134,10 @@ def make_stock_transfer_entry(**args): ste_dict = make_rm_stock_entry(args.sco_no, items) ste_dict.update( { - "bill_from_address": "_Test Indian Registered Company-Billing", - "bill_to_address": "_Test Registered Supplier-Billing", + "bill_from_address": args.bill_from_address + or "_Test Indian Registered Company-Billing", + "bill_to_address": args.bill_to_address + or "_Test Registered Supplier-Billing", } ) @@ -156,6 +147,38 @@ def make_stock_transfer_entry(**args): return doc.submit() +def make_stock_entry(**args): + items = [ + { + "item_code": "_Test Trading Goods 1", + "qty": 1, + "s_warehouse": args.get("from_warehouse") or "Stores - _TIRC", + "t_warehouse": args.get("to_warehouse") or "Finished Goods - _TIRC", + "amount": 100, + } + ] + se = frappe.new_doc("Stock Entry") + se.update( + { + "purpose": args.get("purpose") or "Material Receipt", + "stock_entry_type": args.get("purpose") or "Material Receipt", + "company": args.get("company") or "_Test Indian Registered Company", + "items": args.get("items") or items, + } + ) + + return se + + +SERVICE_ITEM = { + "item_code": "Subcontracted Service Item 1", + "qty": 10, + "rate": 100, + "fg_item": "Subcontracted Item SA1", + "fg_item_qty": 10, +} + + class TestSubcontractingTransaction(FrappeTestCase): @classmethod def setUpClass(cls): @@ -165,6 +188,15 @@ def setUpClass(cls): make_subcontracted_items() make_boms() + frappe.db.set_single_value( + "GST Settings", + { + "enable_api": 1, + "enable_e_waybill": 1, + "enable_e_waybill_for_sc": 1, + }, + ) + def _create_stock_entry(self, doc_args): """Generate Stock Entry to test e-Waybill functionalities""" doc_args.update({"doctype": "Stock Entry"}) @@ -176,7 +208,6 @@ def test_create_and_update_stock_entry(self): # Create a subcontracting transaction args = { "stock_entry_type": "Send to Subcontractor", - "purpose": "Send to Subcontractor", "bill_from_address": "_Test Indian Registered Company-Billing", "bill_to_address": "_Test Registered Supplier-Billing", "items": [ @@ -187,11 +218,9 @@ def test_create_and_update_stock_entry(self): "s_warehouse": "Finished Goods - _TIRC", "t_warehouse": "Goods In Transit - _TIRC", "amount": 100, - "taxable_value": 100, } ], "company": "_Test Indian Registered Company", - "base_grand_total": 100, } stock_entry = self._create_stock_entry(args) @@ -203,19 +232,90 @@ def test_create_and_update_stock_entry(self): self.assertEqual(stock_entry.select_print_heading, "Credit Note") + def test_for_unregistered_company(self): + po = create_purchase_order( + company="_Test Indian Unregistered Company", + supplier_warehouse="Finished Goods - _TIUC", + **SERVICE_ITEM, + ) + + sco = create_subcontracting_order(po_name=po.name) + self.assertEqual(sco.total_taxes, None) + + rm_items = get_rm_items(sco.supplied_items) + args = { + "sco_no": sco.name, + "rm_items": rm_items, + "bill_from_address": "_Test Indian Unregistered Company-Billing", + "bill_to_address": "_Test Unregistered Supplier-Billing", + } + se = make_stock_transfer_entry(**args) + self.assertEqual(se.total_taxes, 0.0) + + scr = make_subcontracting_receipt(sco.name) + scr.submit() + self.assertEqual(scr.total_taxes, 0.0) + + def test_stock_entry_for_material_receipt(self): + se = make_stock_entry() + se.save() + + self.assertEqual(se.total_taxes, None) + + def test_subcontracting_validations(self): + po = create_purchase_order( + **SERVICE_ITEM, supplier_warehouse="Finished Goods - _TIRC" + ) + sco = create_subcontracting_order(po_name=po.name) + + rm_items = get_rm_items(sco.supplied_items) + make_stock_transfer_entry(sco_no=sco.name, rm_items=rm_items) + + scr = make_subcontracting_receipt(sco.name) + scr.save() + + scr.billing_address = None + self.assertRaisesRegex( + frappe.ValidationError, + re.compile(r"(to ensure Company GSTIN is fetched in the transaction.$)"), + scr.save, + ) + + scr.reload() + self.assertEqual(scr.total_taxes, 252.0) + + def test_standalone_stock_entry(self): + purpose = "Send to Subcontractor" + se = make_stock_entry(purpose=purpose) + + self.assertRaisesRegex( + frappe.ValidationError, + re.compile(r"(to ensure Company GSTIN is fetched in the transaction.$)"), + se.save, + ) + + se.bill_from_address = "_Test Indian Registered Company-Billing" + + self.assertRaisesRegex( + frappe.ValidationError, + re.compile( + r"(.*Please ensure that it is set in the Party and / or Address.*)" + ), + se.save, + ) + + se.bill_to_address = "_Test Registered Supplier-Billing" + + se.save() + def test_validation_for_doc_references(self): - service_item = [ - { - "warehouse": "Stores - _TIRC", - "item_code": "Subcontracted Service Item 1", - "qty": 10, - "rate": 100, - "fg_item": "Subcontracted Item SA1", - "fg_item_qty": 10, - } - ] + from india_compliance.gst_india.overrides.subcontracting_transaction import ( + get_stock_entry_references, + ) - po = create_purchase_order(items=service_item) + po = create_purchase_order( + **SERVICE_ITEM, supplier_warehouse="Finished Goods - _TIRC" + ) sco = create_subcontracting_order(po_name=po.name) rm_items = get_rm_items(sco.supplied_items) @@ -224,9 +324,11 @@ def test_validation_for_doc_references(self): return_se = get_materials_from_supplier( sco.name, [d.name for d in sco.supplied_items] ) + return_se.supplier = "_Test Registered Supplier" return_se.save() scr = make_subcontracting_receipt(sco.name) + scr.save() scr.submit() self.assertRaisesRegex( @@ -236,16 +338,25 @@ def test_validation_for_doc_references(self): ) return_se.reload() + + filters = { + "supplier": return_se.supplier, + "supplied_items": [d.item_code for d in return_se.items], + "subcontracting_orders": [return_se.subcontracting_order], + } + doc_references_data = get_stock_entry_references( + filters=filters, only_linked_references=True + ) + doc_references = [row[0] for row in doc_references_data] + + self.assertTrue(se.name in doc_references) + return_se.append( "doc_references", {"link_doctype": "Stock Entry", "link_name": se.name}, ) return_se.submit() - @change_settings( - "GST Settings", - {"enable_api": 1, "enable_e_waybill": 1, "enable_e_waybill_for_sc": 1}, - ) def test_validation_when_gstin_field_empty(self): service_item = [ { @@ -259,7 +370,12 @@ def test_validation_when_gstin_field_empty(self): ] po = create_purchase_order( - items=service_item, supplier="_Test Unregistered Supplier" + items=service_item, + supplier="_Test Unregistered Supplier", + supplier_warhouse="Finished Goods - _TIUC", ) - create_subcontracting_order(po_name=po.name) + sco = create_subcontracting_order(po_name=po.name, do_not_save=True) + sco.supplier_warehouse = "Finished Goods - _TIUC" + sco.save() + sco.submit() diff --git a/india_compliance/gst_india/utils/test_e_waybill.py b/india_compliance/gst_india/utils/test_e_waybill.py index 883968e86..d9a2bf0c0 100644 --- a/india_compliance/gst_india/utils/test_e_waybill.py +++ b/india_compliance/gst_india/utils/test_e_waybill.py @@ -15,7 +15,7 @@ from erpnext.controllers.sales_and_purchase_return import make_return_doc from india_compliance.gst_india.api_classes.base import BASE_URL -from india_compliance.gst_india.utils import load_doc +from india_compliance.gst_india.utils import load_doc, parse_datetime from india_compliance.gst_india.utils.e_invoice import ( retry_e_invoice_e_waybill_generation, ) @@ -1056,6 +1056,18 @@ def test_e_waybill_for_stock_entry(self): frappe.get_doc("e-Waybill Log", {"reference_name": stock_entry.name}), ) + stock_entry = load_doc("Stock Entry", stock_entry.name, "submit") + + e_waybill_info = stock_entry.get("__onload").e_waybill_info + + self.assertEqual( + e_waybill_info.valid_upto, + parse_datetime( + se_data.get("response_data").get("result").get("validUpto"), + day_first=True, + ), + ) + @change_settings("GST Settings", {"enable_e_waybill_for_sc": 1}) @responses.activate def test_e_waybill_for_stock_entry_same_gstin(self): @@ -1071,6 +1083,18 @@ def test_e_waybill_for_stock_entry_same_gstin(self): frappe.get_doc("e-Waybill Log", {"reference_name": stock_entry.name}), ) + stock_entry = load_doc("Stock Entry", stock_entry.name, "submit") + + e_waybill_info = stock_entry.get("__onload").e_waybill_info + + self.assertEqual( + e_waybill_info.valid_upto, + parse_datetime( + se_data.get("response_data").get("result").get("validUpto"), + day_first=True, + ), + ) + def update_dates_for_test_data(test_data): """Update dates in test data""" diff --git a/india_compliance/gst_india/utils/tests.py b/india_compliance/gst_india/utils/tests.py index ceb3bd8ae..c77351439 100644 --- a/india_compliance/gst_india/utils/tests.py +++ b/india_compliance/gst_india/utils/tests.py @@ -108,6 +108,8 @@ def append_item(transaction, data=None, company_abbr="_TIRC"): "warehouse": f"Stores - {company_abbr}", "expense_account": f"Cost of Goods Sold - {company_abbr}", "taxable_value": data.taxable_value or 0, + "fg_item": data.fg_item, + "fg_item_qty": data.fg_item_qty, }, )