mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-13 10:11:20 +00:00
fix: disable partial payment in pos (#45752)
* fix: disable partial payment in pos
* test: disable partial payment
* test: removed print statement
* test: using save method to auto calculate paid_amount
* test: paid_amount calculation using save method
* test: added save method to calculate paid_amount
* test: outstanding amount
* test: added test for partial payments in pos invoice
* fix: custom validation error for partial payment
* test: using partial payment validation
* fix: validate only on submit
(cherry picked from commit d94802067b)
# Conflicts:
# erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py
# erpnext/accounts/doctype/pos_invoice/pos_invoice.py
# erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
# erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py
This commit is contained in:
@@ -29,10 +29,12 @@ class TestPOSClosingEntry(unittest.TestCase):
|
|||||||
|
|
||||||
pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500})
|
||||||
|
pos_inv1.save()
|
||||||
pos_inv1.submit()
|
pos_inv1.submit()
|
||||||
|
|
||||||
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
|
||||||
|
pos_inv2.save()
|
||||||
pos_inv2.submit()
|
pos_inv2.submit()
|
||||||
|
|
||||||
pcv_doc = make_closing_entry_from_opening(opening_entry)
|
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.total_quantity, 2)
|
||||||
self.assertEqual(pcv_doc.net_total, 6700)
|
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):
|
def test_cancelling_of_pos_closing_entry(self):
|
||||||
test_user, pos_profile = init_user_and_profile()
|
test_user, pos_profile = init_user_and_profile()
|
||||||
opening_entry = create_opening_entry(pos_profile, test_user.name)
|
opening_entry = create_opening_entry(pos_profile, test_user.name)
|
||||||
|
|
||||||
pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3500})
|
||||||
|
pos_inv1.save()
|
||||||
pos_inv1.submit()
|
pos_inv1.submit()
|
||||||
|
|
||||||
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
|
||||||
|
pos_inv2.save()
|
||||||
pos_inv2.submit()
|
pos_inv2.submit()
|
||||||
|
|
||||||
pcv_doc = make_closing_entry_from_opening(opening_entry)
|
pcv_doc = make_closing_entry_from_opening(opening_entry)
|
||||||
@@ -90,6 +146,145 @@ class TestPOSClosingEntry(unittest.TestCase):
|
|||||||
pos_inv1.load_from_db()
|
pos_inv1.load_from_db()
|
||||||
self.assertEqual(pos_inv1.status, "Paid")
|
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):
|
def init_user_and_profile(**args):
|
||||||
user = "test@example.com"
|
user = "test@example.com"
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ from erpnext.stock.doctype.serial_no.serial_no import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PartialPaymentValidationError(frappe.ValidationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class POSInvoice(SalesInvoice):
|
class POSInvoice(SalesInvoice):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@@ -55,7 +59,11 @@ class POSInvoice(SalesInvoice):
|
|||||||
self.validate_payment_amount()
|
self.validate_payment_amount()
|
||||||
self.validate_loyalty_transaction()
|
self.validate_loyalty_transaction()
|
||||||
self.validate_company_with_pos_company()
|
self.validate_company_with_pos_company()
|
||||||
|
<<<<<<< HEAD
|
||||||
self.validate_duplicate_serial_no()
|
self.validate_duplicate_serial_no()
|
||||||
|
=======
|
||||||
|
self.validate_full_payment()
|
||||||
|
>>>>>>> d94802067b (fix: disable partial payment in pos (#45752))
|
||||||
if self.coupon_code:
|
if self.coupon_code:
|
||||||
from erpnext.accounts.doctype.pricing_rule.utils import validate_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:
|
if self.redeem_loyalty_points and self.loyalty_program and self.loyalty_points:
|
||||||
validate_loyalty_points(self, 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):
|
def set_status(self, update=False, status=None, update_modified=True):
|
||||||
if self.is_new():
|
if self.is_new():
|
||||||
if self.get("amended_from"):
|
if self.get("amended_from"):
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import unittest
|
|||||||
|
|
||||||
import frappe
|
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.pos_profile.test_pos_profile import make_pos_profile
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
from erpnext.stock.doctype.item.test_item import make_item
|
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.get("items")[0].serial_no = serial_nos[0] + "\n" + serial_nos[1]
|
||||||
pos.append(
|
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()
|
pos.insert()
|
||||||
@@ -317,12 +317,30 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
# partial return 1
|
# partial return 1
|
||||||
pos_return1.get("items")[0].qty = -1
|
pos_return1.get("items")[0].qty = -1
|
||||||
|
<<<<<<< HEAD
|
||||||
pos_return1.get("items")[0].serial_no = serial_nos[0]
|
pos_return1.get("items")[0].serial_no = serial_nos[0]
|
||||||
pos_return1.insert()
|
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()
|
pos_return1.submit()
|
||||||
|
|
||||||
# partial return 2
|
# partial return 2
|
||||||
pos_return2 = make_sales_return(pos.name)
|
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].qty, -1)
|
||||||
self.assertEqual(pos_return2.get("items")[0].serial_no, serial_nos[1])
|
self.assertEqual(pos_return2.get("items")[0].serial_no, serial_nos[1])
|
||||||
|
|
||||||
@@ -355,6 +373,15 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
inv.payments = []
|
inv.payments = []
|
||||||
self.assertRaises(frappe.ValidationError, inv.insert)
|
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):
|
def test_serialized_item_transaction(self):
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
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
|
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"
|
"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(
|
lpe = frappe.get_doc(
|
||||||
"Loyalty Point Entry",
|
"Loyalty Point Entry",
|
||||||
@@ -623,7 +656,13 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# add 10 loyalty points
|
# 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(
|
before_lp_details = get_loyalty_program_details_with_points(
|
||||||
"Test Loyalty Customer", company="_Test Company", loyalty_program="Test Single Loyalty"
|
"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()
|
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 = 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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 270})
|
||||||
|
pos_inv.save()
|
||||||
pos_inv.submit()
|
pos_inv.submit()
|
||||||
|
|
||||||
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
|
||||||
|
pos_inv2.save()
|
||||||
pos_inv2.submit()
|
pos_inv2.submit()
|
||||||
|
|
||||||
consolidate_pos_invoices()
|
consolidate_pos_invoices()
|
||||||
@@ -692,6 +733,7 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
"included_in_print_rate": 1,
|
"included_in_print_rate": 1,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
pos_inv.save()
|
||||||
pos_inv.submit()
|
pos_inv.submit()
|
||||||
|
|
||||||
pos_inv2 = create_pos_invoice(rate=300, qty=2, do_not_submit=1)
|
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,
|
"included_in_print_rate": 1,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
pos_inv2.save()
|
||||||
pos_inv2.submit()
|
pos_inv2.submit()
|
||||||
|
|
||||||
consolidate_pos_invoices()
|
consolidate_pos_invoices()
|
||||||
@@ -760,6 +803,7 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
"included_in_print_rate": 1,
|
"included_in_print_rate": 1,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
pos_inv2.save()
|
||||||
pos_inv2.submit()
|
pos_inv2.submit()
|
||||||
|
|
||||||
consolidate_pos_invoices()
|
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")
|
rounded_total = frappe.db.get_value("Sales Invoice", pos_inv2.consolidated_invoice, "rounded_total")
|
||||||
self.assertEqual(rounded_total, 400)
|
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):
|
def test_pos_batch_item_qty_validation(self):
|
||||||
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
|
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
|
||||||
create_batch_item_with_batch,
|
create_batch_item_with_batch,
|
||||||
@@ -788,8 +895,18 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
batch_no="TestBatch 01",
|
batch_no="TestBatch 01",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
pos_inv1 = create_pos_invoice(item=item.name, rate=300, qty=1, do_not_submit=1)
|
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.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.save()
|
||||||
pos_inv1.submit()
|
pos_inv1.submit()
|
||||||
|
|
||||||
|
|||||||
@@ -25,14 +25,17 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
|
|||||||
|
|
||||||
pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300})
|
||||||
|
pos_inv.save()
|
||||||
pos_inv.submit()
|
pos_inv.submit()
|
||||||
|
|
||||||
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
|
||||||
|
pos_inv2.save()
|
||||||
pos_inv2.submit()
|
pos_inv2.submit()
|
||||||
|
|
||||||
pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300})
|
||||||
|
pos_inv3.save()
|
||||||
pos_inv3.submit()
|
pos_inv3.submit()
|
||||||
|
|
||||||
consolidate_pos_invoices()
|
consolidate_pos_invoices()
|
||||||
@@ -58,14 +61,17 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
|
|||||||
|
|
||||||
pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300})
|
||||||
|
pos_inv.save()
|
||||||
pos_inv.submit()
|
pos_inv.submit()
|
||||||
|
|
||||||
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200})
|
||||||
|
pos_inv2.save()
|
||||||
pos_inv2.submit()
|
pos_inv2.submit()
|
||||||
|
|
||||||
pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1)
|
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.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300})
|
||||||
|
pos_inv3.save()
|
||||||
pos_inv3.submit()
|
pos_inv3.submit()
|
||||||
|
|
||||||
pos_inv_cn = make_sales_return(pos_inv.name)
|
pos_inv_cn = make_sales_return(pos_inv.name)
|
||||||
@@ -119,6 +125,11 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
inv.insert()
|
inv.insert()
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
inv.payments[0].amount = inv.grand_total
|
||||||
|
inv.save()
|
||||||
|
>>>>>>> d94802067b (fix: disable partial payment in pos (#45752))
|
||||||
inv.submit()
|
inv.submit()
|
||||||
|
|
||||||
inv2 = create_pos_invoice(qty=1, rate=100, do_not_save=True)
|
inv2 = create_pos_invoice(qty=1, rate=100, do_not_save=True)
|
||||||
@@ -135,6 +146,11 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
inv2.insert()
|
inv2.insert()
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
inv2.payments[0].amount = inv.grand_total
|
||||||
|
inv2.save()
|
||||||
|
>>>>>>> d94802067b (fix: disable partial payment in pos (#45752))
|
||||||
inv2.submit()
|
inv2.submit()
|
||||||
|
|
||||||
consolidate_pos_invoices()
|
consolidate_pos_invoices()
|
||||||
@@ -269,7 +285,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
|
|||||||
inv2.submit()
|
inv2.submit()
|
||||||
|
|
||||||
inv3 = create_pos_invoice(qty=3, rate=600, do_not_save=True)
|
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.insert()
|
||||||
inv3.submit()
|
inv3.submit()
|
||||||
|
|
||||||
@@ -277,8 +293,8 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
|
|||||||
|
|
||||||
inv.load_from_db()
|
inv.load_from_db()
|
||||||
consolidated_invoice = frappe.get_doc("Sales Invoice", inv.consolidated_invoice)
|
consolidated_invoice = frappe.get_doc("Sales Invoice", inv.consolidated_invoice)
|
||||||
self.assertEqual(consolidated_invoice.outstanding_amount, 800)
|
self.assertNotEqual(consolidated_invoice.outstanding_amount, 800)
|
||||||
self.assertNotEqual(consolidated_invoice.status, "Paid")
|
self.assertEqual(consolidated_invoice.status, "Paid")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
frappe.set_user("Administrator")
|
frappe.set_user("Administrator")
|
||||||
@@ -414,6 +430,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
|
|||||||
do_not_submit=1,
|
do_not_submit=1,
|
||||||
)
|
)
|
||||||
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100})
|
pos_inv.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100})
|
||||||
|
pos_inv.save()
|
||||||
pos_inv.submit()
|
pos_inv.submit()
|
||||||
|
|
||||||
pos_inv_cn = make_sales_return(pos_inv.name)
|
pos_inv_cn = make_sales_return(pos_inv.name)
|
||||||
@@ -428,6 +445,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
|
|||||||
do_not_submit=1,
|
do_not_submit=1,
|
||||||
)
|
)
|
||||||
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100})
|
pos_inv2.append("payments", {"mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100})
|
||||||
|
pos_inv2.save()
|
||||||
pos_inv2.submit()
|
pos_inv2.submit()
|
||||||
|
|
||||||
consolidate_pos_invoices()
|
consolidate_pos_invoices()
|
||||||
|
|||||||
Reference in New Issue
Block a user