diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py index 8eb28dfaa2c..8f06d41f9a6 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py @@ -29,10 +29,12 @@ class TestPOSClosingEntry(unittest.TestCase): pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1) pos_inv1.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500}) + pos_inv1.save() pos_inv1.submit() pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200}) + pos_inv2.save() pos_inv2.submit() pcv_doc = make_closing_entry_from_opening(opening_entry) @@ -49,16 +51,70 @@ class TestPOSClosingEntry(unittest.TestCase): self.assertEqual(pcv_doc.total_quantity, 2) self.assertEqual(pcv_doc.net_total, 6700) +<<<<<<< HEAD +======= + def test_pos_closing_without_item_code(self): + """ + Test if POS Closing Entry is created without item code + """ + test_user, pos_profile = init_user_and_profile() + opening_entry = create_opening_entry(pos_profile, test_user.name) + + pos_inv = create_pos_invoice(rate=3500, do_not_submit=1, item_name="Test Item", without_item_code=1) + pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500}) + pos_inv.save() + pos_inv.submit() + + pcv_doc = make_closing_entry_from_opening(opening_entry) + pcv_doc.submit() + + self.assertTrue(pcv_doc.name) + + def test_pos_qty_for_item(self): + """ + Test if quantity is calculated correctly for an item in POS Closing Entry + """ + test_user, pos_profile = init_user_and_profile() + opening_entry = create_opening_entry(pos_profile, test_user.name) + + test_item_qty = get_test_item_qty(pos_profile) + + pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1) + pos_inv1.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500}) + pos_inv1.save() + pos_inv1.submit() + + pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) + pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200}) + pos_inv2.save() + pos_inv2.submit() + + # make return entry of pos_inv2 + pos_return = make_sales_return(pos_inv2.name) + pos_return.paid_amount = pos_return.grand_total + pos_return.save() + pos_return.submit() + + pcv_doc = make_closing_entry_from_opening(opening_entry) + pcv_doc.submit() + + opening_entry = create_opening_entry(pos_profile, test_user.name) + test_item_qty_after_sales = get_test_item_qty(pos_profile) + self.assertEqual(test_item_qty_after_sales, test_item_qty - 1) + +>>>>>>> d94802067b (fix: disable partial payment in pos (#45752)) def test_cancelling_of_pos_closing_entry(self): test_user, pos_profile = init_user_and_profile() opening_entry = create_opening_entry(pos_profile, test_user.name) pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1) pos_inv1.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500}) + pos_inv1.save() pos_inv1.submit() pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200}) + pos_inv2.save() pos_inv2.submit() pcv_doc = make_closing_entry_from_opening(opening_entry) @@ -90,6 +146,145 @@ class TestPOSClosingEntry(unittest.TestCase): pos_inv1.load_from_db() self.assertEqual(pos_inv1.status, "Paid") +<<<<<<< HEAD +======= + def test_pos_closing_for_required_accounting_dimension_in_pos_profile(self): + """ + test case to check whether we can create POS Closing Entry without mandatory accounting dimension + """ + + create_dimension() + pos_profile = make_pos_profile(do_not_insert=1, do_not_set_accounting_dimension=1) + + self.assertRaises(frappe.ValidationError, pos_profile.insert) + + pos_profile.location = "Block 1" + pos_profile.insert() + self.assertTrue(frappe.db.exists("POS Profile", pos_profile.name)) + + test_user = init_user_and_profile(do_not_create_pos_profile=1) + + opening_entry = create_opening_entry(pos_profile, test_user.name) + pos_inv1 = create_pos_invoice(rate=350, do_not_submit=1, pos_profile=pos_profile.name) + pos_inv1.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500}) + pos_inv1.save() + pos_inv1.submit() + + # if in between a mandatory accounting dimension is added to the POS Profile then + accounting_dimension_department = frappe.get_doc("Accounting Dimension", {"name": "Department"}) + accounting_dimension_department.dimension_defaults[0].mandatory_for_bs = 1 + accounting_dimension_department.save() + + pcv_doc = make_closing_entry_from_opening(opening_entry) + # will assert coz the new mandatory accounting dimension bank is not set in POS Profile + self.assertRaises(frappe.ValidationError, pcv_doc.submit) + + accounting_dimension_department = frappe.get_doc( + "Accounting Dimension Detail", {"parent": "Department"} + ) + accounting_dimension_department.mandatory_for_bs = 0 + accounting_dimension_department.save() + disable_dimension() + + def test_merging_into_sales_invoice_for_batched_item(self): + frappe.flags.print_message = False + from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import ( + init_user_and_profile, + ) + from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import ( + consolidate_pos_invoices, + ) + from erpnext.stock.doctype.batch.batch import get_batch_qty + + frappe.db.sql("delete from `tabPOS Invoice`") + item_doc = make_item( + "_Test Item With Batch FOR POS Merge Test", + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "batch_number_series": "BATCH-PM-POS-MERGE-.####", + "create_new_batch": 1, + }, + ) + + item_code = item_doc.name + se = make_stock_entry( + target="_Test Warehouse - _TC", + item_code=item_code, + qty=10, + basic_rate=100, + use_serial_batch_fields=0, + ) + batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle) + + test_user, pos_profile = init_user_and_profile() + opening_entry = create_opening_entry(pos_profile, test_user.name) + + pos_inv = create_pos_invoice( + item_code=item_code, + qty=5, + rate=300, + use_serial_batch_fields=1, + batch_no=batch_no, + do_not_submit=True, + ) + pos_inv.payments[0].amount = pos_inv.grand_total + pos_inv.save() + pos_inv.submit() + pos_inv2 = create_pos_invoice( + item_code=item_code, + qty=5, + rate=300, + use_serial_batch_fields=1, + batch_no=batch_no, + do_not_submit=True, + ) + pos_inv2.payments[0].amount = pos_inv2.grand_total + pos_inv2.save() + pos_inv2.submit() + + batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code) + self.assertEqual(batch_qty_with_pos, 0.0) + + pcv_doc = make_closing_entry_from_opening(opening_entry) + pcv_doc.submit() + + piv_merge = frappe.db.get_value("POS Invoice Merge Log", {"pos_closing_entry": pcv_doc.name}, "name") + + self.assertTrue(piv_merge) + piv_merge_doc = frappe.get_doc("POS Invoice Merge Log", piv_merge) + self.assertTrue(piv_merge_doc.pos_invoices[0].pos_invoice) + self.assertTrue(piv_merge_doc.pos_invoices[1].pos_invoice) + + pos_inv.load_from_db() + self.assertTrue(pos_inv.consolidated_invoice) + pos_inv2.load_from_db() + self.assertTrue(pos_inv2.consolidated_invoice) + + batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty") + self.assertEqual(batch_qty, 0.0) + + batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code) + self.assertEqual(batch_qty_with_pos, 0.0) + + frappe.flags.print_message = True + + pcv_doc.reload() + pcv_doc.cancel() + + batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code) + self.assertEqual(batch_qty_with_pos, 0.0) + + pos_inv.reload() + pos_inv2.reload() + + pos_inv.cancel() + pos_inv2.cancel() + + batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code) + self.assertEqual(batch_qty_with_pos, 10.0) + +>>>>>>> d94802067b (fix: disable partial payment in pos (#45752)) def init_user_and_profile(**args): user = "test@example.com" diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 80c4db50acb..63b9b949d22 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -25,6 +25,10 @@ from erpnext.stock.doctype.serial_no.serial_no import ( ) +class PartialPaymentValidationError(frappe.ValidationError): + pass + + class POSInvoice(SalesInvoice): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -55,7 +59,11 @@ class POSInvoice(SalesInvoice): self.validate_payment_amount() self.validate_loyalty_transaction() self.validate_company_with_pos_company() +<<<<<<< HEAD self.validate_duplicate_serial_no() +======= + self.validate_full_payment() +>>>>>>> d94802067b (fix: disable partial payment in pos (#45752)) if self.coupon_code: from erpnext.accounts.doctype.pricing_rule.utils import validate_coupon_code @@ -407,6 +415,20 @@ class POSInvoice(SalesInvoice): if self.redeem_loyalty_points and self.loyalty_program and self.loyalty_points: validate_loyalty_points(self, self.loyalty_points) + def validate_full_payment(self): + invoice_total = flt(self.rounded_total) or flt(self.grand_total) + + if self.docstatus == 1: + if self.is_return and self.paid_amount != invoice_total: + frappe.throw( + msg=_("Partial Payment in POS Invoice is not allowed."), exc=PartialPaymentValidationError + ) + + if self.paid_amount < invoice_total: + frappe.throw( + msg=_("Partial Payment in POS Invoice is not allowed."), exc=PartialPaymentValidationError + ) + def set_status(self, update=False, status=None, update_modified=True): if self.is_new(): if self.get("amended_from"): diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py index b44262cc280..ed3e64f36ff 100644 --- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py @@ -6,7 +6,7 @@ import unittest import frappe -from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return +from erpnext.accounts.doctype.pos_invoice.pos_invoice import PartialPaymentValidationError, make_sales_return from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.stock.doctype.item.test_item import make_item @@ -307,7 +307,7 @@ class TestPOSInvoice(unittest.TestCase): pos.get("items")[0].serial_no = serial_nos[0] + "\n" + serial_nos[1] pos.append( - "payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 1000, "default": 1} + "payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2000, "default": 1} ) pos.insert() @@ -317,12 +317,30 @@ class TestPOSInvoice(unittest.TestCase): # partial return 1 pos_return1.get("items")[0].qty = -1 +<<<<<<< HEAD pos_return1.get("items")[0].serial_no = serial_nos[0] pos_return1.insert() +======= + pos_return1.set("payments", []) + pos_return1.append( + "payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": -1000, "default": 1} + ) + pos_return1.paid_amount = -1000 +>>>>>>> d94802067b (fix: disable partial payment in pos (#45752)) pos_return1.submit() # partial return 2 pos_return2 = make_sales_return(pos.name) +<<<<<<< HEAD +======= + pos_return2.set("payments", []) + pos_return2.append( + "payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": -1000, "default": 1} + ) + pos_return2.paid_amount = -1000 + pos_return2.submit() + +>>>>>>> d94802067b (fix: disable partial payment in pos (#45752)) self.assertEqual(pos_return2.get("items")[0].qty, -1) self.assertEqual(pos_return2.get("items")[0].serial_no, serial_nos[1]) @@ -355,6 +373,15 @@ class TestPOSInvoice(unittest.TestCase): inv.payments = [] self.assertRaises(frappe.ValidationError, inv.insert) + def test_partial_payment(self): + pos_inv = create_pos_invoice(rate=10000, do_not_save=1) + pos_inv.append( + "payments", + {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 9000}, + ) + pos_inv.insert() + self.assertRaises(PartialPaymentValidationError, pos_inv.submit) + def test_serialized_item_transaction(self): from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item @@ -597,7 +624,13 @@ class TestPOSInvoice(unittest.TestCase): "Test Loyalty Customer", company="_Test Company", loyalty_program="Test Single Loyalty" ) - inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000) + inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000, do_not_save=1) + inv.append( + "payments", + {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 10000}, + ) + inv.insert() + inv.submit() lpe = frappe.get_doc( "Loyalty Point Entry", @@ -623,7 +656,13 @@ class TestPOSInvoice(unittest.TestCase): ) # add 10 loyalty points - create_pos_invoice(customer="Test Loyalty Customer", rate=10000) + pos_inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000, do_not_save=1) + pos_inv.append( + "payments", + {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 10000}, + ) + pos_inv.paid_amount = 10000 + pos_inv.submit() before_lp_details = get_loyalty_program_details_with_points( "Test Loyalty Customer", company="_Test Company", loyalty_program="Test Single Loyalty" @@ -657,10 +696,12 @@ class TestPOSInvoice(unittest.TestCase): test_user, pos_profile = init_user_and_profile() pos_inv = create_pos_invoice(rate=300, additional_discount_percentage=10, do_not_submit=1) pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 270}) + pos_inv.save() pos_inv.submit() pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200}) + pos_inv2.save() pos_inv2.submit() consolidate_pos_invoices() @@ -692,6 +733,7 @@ class TestPOSInvoice(unittest.TestCase): "included_in_print_rate": 1, }, ) + pos_inv.save() pos_inv.submit() pos_inv2 = create_pos_invoice(rate=300, qty=2, do_not_submit=1) @@ -708,6 +750,7 @@ class TestPOSInvoice(unittest.TestCase): "included_in_print_rate": 1, }, ) + pos_inv2.save() pos_inv2.submit() consolidate_pos_invoices() @@ -760,6 +803,7 @@ class TestPOSInvoice(unittest.TestCase): "included_in_print_rate": 1, }, ) + pos_inv2.save() pos_inv2.submit() consolidate_pos_invoices() @@ -768,6 +812,69 @@ class TestPOSInvoice(unittest.TestCase): rounded_total = frappe.db.get_value("Sales Invoice", pos_inv2.consolidated_invoice, "rounded_total") self.assertEqual(rounded_total, 400) +<<<<<<< HEAD +======= + def test_pos_batch_reservation(self): + from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import ( + get_auto_batch_nos, + ) + from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( + create_batch_item_with_batch, + ) + + create_batch_item_with_batch("_BATCH ITEM Test For Reserve", "TestBatch-RS 02") + se = make_stock_entry( + target="_Test Warehouse - _TC", + item_code="_BATCH ITEM Test For Reserve", + qty=30, + basic_rate=100, + ) + + se.reload() + + batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle) + + # POS Invoice 1, for the batch without bundle + pos_inv1 = create_pos_invoice(item="_BATCH ITEM Test For Reserve", rate=300, qty=15, do_not_save=1) + pos_inv1.append( + "payments", + {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 4500}, + ) + pos_inv1.items[0].batch_no = batch_no + pos_inv1.save() + pos_inv1.submit() + pos_inv1.reload() + + batches = get_auto_batch_nos( + frappe._dict({"item_code": "_BATCH ITEM Test For Reserve", "warehouse": "_Test Warehouse - _TC"}) + ) + + for batch in batches: + if batch.batch_no == batch_no and batch.warehouse == "_Test Warehouse - _TC": + self.assertEqual(batch.qty, 15) + + # POS Invoice 2, for the batch with bundle + pos_inv2 = create_pos_invoice( + item="_BATCH ITEM Test For Reserve", rate=300, qty=10, batch_no=batch_no, do_not_save=1 + ) + pos_inv2.append( + "payments", + {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3000}, + ) + pos_inv2.save() + pos_inv2.submit() + pos_inv2.reload() + self.assertTrue(pos_inv2.items[0].serial_and_batch_bundle) + + batches = get_auto_batch_nos( + frappe._dict({"item_code": "_BATCH ITEM Test For Reserve", "warehouse": "_Test Warehouse - _TC"}) + ) + + for batch in batches: + if batch.batch_no == batch_no and batch.warehouse == "_Test Warehouse - _TC": + self.assertEqual(batch.qty, 5) + +>>>>>>> d94802067b (fix: disable partial payment in pos (#45752)) def test_pos_batch_item_qty_validation(self): from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( create_batch_item_with_batch, @@ -788,8 +895,18 @@ class TestPOSInvoice(unittest.TestCase): batch_no="TestBatch 01", ) +<<<<<<< HEAD pos_inv1 = create_pos_invoice(item=item.name, rate=300, qty=1, do_not_submit=1) pos_inv1.items[0].batch_no = "TestBatch 01" +======= + pos_inv1 = create_pos_invoice( + item=item.name, rate=300, qty=1, do_not_submit=1, batch_no="TestBatch 01" + ) + pos_inv1.append( + "payments", + {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300}, + ) +>>>>>>> d94802067b (fix: disable partial payment in pos (#45752)) pos_inv1.save() pos_inv1.submit() diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py index 5f5427c0764..26066dd1c08 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py @@ -25,14 +25,17 @@ class TestPOSInvoiceMergeLog(unittest.TestCase): pos_inv = create_pos_invoice(rate=300, do_not_submit=1) pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300}) + pos_inv.save() pos_inv.submit() pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200}) + pos_inv2.save() pos_inv2.submit() pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1) pos_inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300}) + pos_inv3.save() pos_inv3.submit() consolidate_pos_invoices() @@ -58,14 +61,17 @@ class TestPOSInvoiceMergeLog(unittest.TestCase): pos_inv = create_pos_invoice(rate=300, do_not_submit=1) pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300}) + pos_inv.save() pos_inv.submit() pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200}) + pos_inv2.save() pos_inv2.submit() pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1) pos_inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300}) + pos_inv3.save() pos_inv3.submit() pos_inv_cn = make_sales_return(pos_inv.name) @@ -119,6 +125,11 @@ class TestPOSInvoiceMergeLog(unittest.TestCase): }, ) inv.insert() +<<<<<<< HEAD +======= + inv.payments[0].amount = inv.grand_total + inv.save() +>>>>>>> d94802067b (fix: disable partial payment in pos (#45752)) inv.submit() inv2 = create_pos_invoice(qty=1, rate=100, do_not_save=True) @@ -135,6 +146,11 @@ class TestPOSInvoiceMergeLog(unittest.TestCase): }, ) inv2.insert() +<<<<<<< HEAD +======= + inv2.payments[0].amount = inv.grand_total + inv2.save() +>>>>>>> d94802067b (fix: disable partial payment in pos (#45752)) inv2.submit() consolidate_pos_invoices() @@ -269,7 +285,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase): inv2.submit() inv3 = create_pos_invoice(qty=3, rate=600, do_not_save=True) - inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 1000}) + inv3.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 1800}) inv3.insert() inv3.submit() @@ -277,8 +293,8 @@ class TestPOSInvoiceMergeLog(unittest.TestCase): inv.load_from_db() consolidated_invoice = frappe.get_doc("Sales Invoice", inv.consolidated_invoice) - self.assertEqual(consolidated_invoice.outstanding_amount, 800) - self.assertNotEqual(consolidated_invoice.status, "Paid") + self.assertNotEqual(consolidated_invoice.outstanding_amount, 800) + self.assertEqual(consolidated_invoice.status, "Paid") finally: frappe.set_user("Administrator") @@ -414,6 +430,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase): do_not_submit=1, ) pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100}) + pos_inv.save() pos_inv.submit() pos_inv_cn = make_sales_return(pos_inv.name) @@ -428,6 +445,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase): do_not_submit=1, ) pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100}) + pos_inv2.save() pos_inv2.submit() consolidate_pos_invoices()