chore: resolve conflict

This commit is contained in:
Mihir Kandoi
2026-08-09 12:50:38 +05:30
parent 1a89609044
commit 206d291817

View File

@@ -2646,282 +2646,17 @@ class TestSalesOrder(AccountsTestMixin, FrappeTestCase):
so = make_sales_order(item_code=fg_item, qty=10, rate=50, warehouse=fg_warehouse, do_not_save=1)
self.assertRaises(frappe.ValidationError, so.save)
<<<<<<< HEAD
=======
@ERPNextTestSuite.change_settings(
"Stock Settings", {"enable_stock_reservation": 1, "use_serial_batch_fields": 0}
)
def test_product_bundle_reservation(self):
pb_item = make_item("Product Bundle Item", {"is_stock_item": 0})
simple_item = make_item("Simple Item", {"is_stock_item": 1})
sb_item = make_item(
"Serial Batch Item",
{
"is_stock_item": 1,
"has_serial_no": 1,
"has_batch_no": 1,
"create_new_batch": 1,
"batch_number_series": "BAT-TSBIFRM-.#####",
"serial_no_series": "SN-TSBIFRM-.#####",
},
)
make_product_bundle(pb_item.name, [simple_item.name, sb_item.name])
def test_sales_team_allocated_percentage_tolerates_floating_point_drift(self):
# 10.0 + 58.02 + 31.98 accumulates to 100.00000000000001 in binary floating point
so = make_sales_order(do_not_save=True)
for sales_person, percentage in (
("_Test Sales Person", 10.0),
("_Test Sales Person 1", 58.02),
("_Test Sales Person 2", 31.98),
):
so.append("sales_team", {"sales_person": sales_person, "allocated_percentage": percentage})
so.save()
warehouse = "_Test Warehouse - _TC"
make_stock_entry(
item_code=simple_item.name,
target=warehouse,
qty=10,
)
# two different stock entries on purpose to get two batches
make_stock_entry(
item_code=sb_item.name,
target=warehouse,
qty=5,
)
make_stock_entry(
item_code=sb_item.name,
target=warehouse,
qty=5,
)
so = make_sales_order(item_code=pb_item.name, do_not_submit=1)
so.reserve_stock = 1
for item in so.packed_items:
item.reserve_stock = 1
so.submit()
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
get_sre_reserved_batch_nos_details,
get_sre_reserved_qty_for_voucher_detail_no,
get_sre_reserved_serial_nos_details,
)
for item in so.packed_items:
self.assertEqual(
get_sre_reserved_qty_for_voucher_detail_no(item.item_code, "Sales Order", so.name, item.name),
item.qty,
)
sre_serial_nos = list(get_sre_reserved_serial_nos_details(sb_item.name, warehouse).keys())
sre_batch_nos = list(get_sre_reserved_batch_nos_details(sb_item.name, warehouse).keys())
dn = make_delivery_note(so.name, kwargs={"for_reserved_stock": True})
dn.save()
self.assertTrue(dn.packed_items[1].serial_and_batch_bundle)
from erpnext.stock.serial_batch_bundle import get_batches_from_bundle, get_serial_nos
serial_nos_in_bundle = get_serial_nos(dn.packed_items[1].serial_and_batch_bundle)
batches_in_bundle = list(get_batches_from_bundle(dn.packed_items[1].serial_and_batch_bundle).keys())
self.assertEqual(sre_serial_nos, serial_nos_in_bundle)
self.assertEqual(sre_batch_nos, batches_in_bundle)
dn.items[0].qty = 5
dn.save()
sabb_doc = frappe.get_doc("Serial and Batch Bundle", dn.packed_items[1].serial_and_batch_bundle)
sabb_doc.entries = sabb_doc.entries[:5]
sabb_doc.company = dn.company
sabb_doc.save()
dn.submit()
serial_nos = set(sre_serial_nos) - set(get_serial_nos(sabb_doc.name))
batch_nos = set(sre_batch_nos) - set(get_batches_from_bundle(sabb_doc.name).keys())
dn1 = make_delivery_note(so.name, kwargs={"for_reserved_stock": True})
dn1.save()
self.assertTrue(dn1.packed_items[1].serial_and_batch_bundle)
from erpnext.stock.serial_batch_bundle import get_batches_from_bundle, get_serial_nos
serial_nos_in_bundle = set(get_serial_nos(dn1.packed_items[1].serial_and_batch_bundle))
batches_in_bundle = set(get_batches_from_bundle(dn1.packed_items[1].serial_and_batch_bundle).keys())
self.assertEqual(serial_nos, serial_nos_in_bundle)
self.assertEqual(batch_nos, batches_in_bundle)
dn.cancel()
# test the same thing with sales invoice as well
si = make_sales_invoice(so.name)
si.update_stock = 1
si.save()
self.assertTrue(si.packed_items[1].serial_and_batch_bundle)
from erpnext.stock.serial_batch_bundle import get_batches_from_bundle, get_serial_nos
serial_nos_in_bundle = get_serial_nos(si.packed_items[1].serial_and_batch_bundle)
batches_in_bundle = list(get_batches_from_bundle(si.packed_items[1].serial_and_batch_bundle).keys())
self.assertEqual(sre_serial_nos, serial_nos_in_bundle)
self.assertEqual(sre_batch_nos, batches_in_bundle)
si.items[0].qty = 5
si.save()
sabb_doc = frappe.get_doc("Serial and Batch Bundle", si.packed_items[1].serial_and_batch_bundle)
sabb_doc.entries = sabb_doc.entries[:5]
sabb_doc.company = si.company
sabb_doc.save()
si.submit()
serial_nos = set(sre_serial_nos) - set(get_serial_nos(sabb_doc.name))
batch_nos = set(sre_batch_nos) - set(get_batches_from_bundle(sabb_doc.name).keys())
si1 = make_delivery_note(so.name, kwargs={"for_reserved_stock": True})
si1.save()
self.assertTrue(si1.packed_items[1].serial_and_batch_bundle)
from erpnext.stock.serial_batch_bundle import get_batches_from_bundle, get_serial_nos
serial_nos_in_bundle = set(get_serial_nos(si1.packed_items[1].serial_and_batch_bundle))
batches_in_bundle = set(get_batches_from_bundle(si1.packed_items[1].serial_and_batch_bundle).keys())
self.assertEqual(serial_nos, serial_nos_in_bundle)
self.assertEqual(batch_nos, batches_in_bundle)
def test_sales_team_contribution_follows_grant_commission(self):
"""Sales-person allocation tracks the grant-commission-eligible amount, not the gross total.
The Item "Grant Commission" flag includes an item in both Sales Partner and Sales Person
commission, so each sales person's allocated_amount is a share of
amount_eligible_for_commission rather than net_total.
"""
frappe.db.set_value("Item", "_Test Item", "grant_commission", 1)
frappe.db.set_value("Item", "_Test FG Item", "grant_commission", 0)
try:
so = make_sales_order(
do_not_save=True,
item_list=[
{"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC", "qty": 10, "rate": 100},
{
"item_code": "_Test FG Item",
"warehouse": "_Test Warehouse - _TC",
"qty": 10,
"rate": 100,
},
],
)
so.append(
"sales_team",
{"sales_person": "_Test Sales Person 1", "allocated_percentage": 60, "commission_rate": 10},
)
so.append(
"sales_team",
{"sales_person": "_Test Sales Person 2", "allocated_percentage": 40, "commission_rate": 0},
)
so.save()
self.assertEqual(so.net_total, 2000)
self.assertEqual(so.amount_eligible_for_commission, 1000) # only the grant_commission item
first, second = so.sales_team
# allocation follows the eligible amount (1000), not net_total (2000)
self.assertEqual(first.allocated_amount, 600)
self.assertEqual(first.incentives, 60) # 600 * 10%
self.assertEqual(second.allocated_amount, 400)
self.assertEqual(second.incentives, 0)
finally:
# grant_commission defaults to 1 for both items; restore
frappe.db.set_value("Item", "_Test Item", "grant_commission", 1)
frappe.db.set_value("Item", "_Test FG Item", "grant_commission", 1)
def test_sales_team_allocated_percentage_must_total_100(self):
with self.subTest("partial allocation is rejected"):
so = make_sales_order(do_not_save=True)
so.append("sales_team", {"sales_person": "_Test Sales Person 1", "allocated_percentage": 60})
self.assertRaises(frappe.ValidationError, so.save)
with self.subTest("allocation totalling 100 is accepted"):
so = make_sales_order(do_not_save=True)
so.append("sales_team", {"sales_person": "_Test Sales Person 1", "allocated_percentage": 60})
so.append("sales_team", {"sales_person": "_Test Sales Person 2", "allocated_percentage": 40})
so.save()
self.assertEqual(sum(d.allocated_percentage for d in so.sales_team), 100)
with self.subTest("floating-point drift in the total is tolerated"):
# 10.0 + 58.02 + 31.98 accumulates to 100.00000000000001 in binary floating point
so = make_sales_order(do_not_save=True)
for sales_person, percentage in (
("_Test Sales Person", 10.0),
("_Test Sales Person 1", 58.02),
("_Test Sales Person 2", 31.98),
):
so.append("sales_team", {"sales_person": sales_person, "allocated_percentage": percentage})
so.save()
def test_sales_team_disabled_sales_person_rejected(self):
frappe.db.set_value("Sales Person", "_Test Sales Person 2", "enabled", 0)
try:
so = make_sales_order(do_not_save=True)
so.append("sales_team", {"sales_person": "_Test Sales Person 2", "allocated_percentage": 100})
self.assertRaises(frappe.ValidationError, so.save)
finally:
frappe.db.set_value("Sales Person", "_Test Sales Person 2", "enabled", 1)
def test_sales_partner_commission(self):
"""Sales Partner commission: total_commission = amount_eligible_for_commission * rate / 100."""
frappe.db.set_value("Item", "_Test Item", "grant_commission", 1)
try:
so = make_sales_order(qty=10, rate=100, do_not_save=True)
so.sales_partner = "_Test Sales Partner India - 1"
so.commission_rate = 7
so.save()
self.assertEqual(so.amount_eligible_for_commission, 1000)
self.assertEqual(so.total_commission, 70) # 1000 * 7%
with self.subTest("commission rate above 100 is rejected"):
so.commission_rate = 101
self.assertRaises(frappe.ValidationError, so.save)
finally:
frappe.db.set_value("Item", "_Test Item", "grant_commission", 1)
def test_commission_fields_not_copied_on_duplicate(self):
"""Commission rate/amount fields are no_copy; only the sales partner carries to a copy."""
frappe.db.set_value("Item", "_Test Item", "grant_commission", 1)
try:
so = make_sales_order(qty=10, rate=100, do_not_save=True)
so.sales_partner = "_Test Sales Partner India - 1"
so.commission_rate = 7
so.save()
self.assertEqual(so.total_commission, 70)
# ignore_no_copy=False mirrors UI "Duplicate"/amend, which honour no_copy
duplicate = frappe.copy_doc(so, ignore_no_copy=False)
self.assertEqual(duplicate.sales_partner, "_Test Sales Partner India - 1")
self.assertFalse(duplicate.commission_rate)
self.assertFalse(duplicate.total_commission)
self.assertFalse(duplicate.amount_eligible_for_commission)
finally:
frappe.db.set_value("Item", "_Test Item", "grant_commission", 1)
def test_commission_rate_carried_through_mapper(self):
"""commission_rate is no_copy, but Make Delivery Note / Sales Invoice still carries it."""
from erpnext.selling.doctype.sales_order.mapper import make_delivery_note, make_sales_invoice
original = frappe.db.get_value("Item", "_Test Item", "grant_commission")
frappe.db.set_value("Item", "_Test Item", "grant_commission", 1)
try:
so = make_sales_order(qty=10, rate=100, do_not_save=True)
so.sales_partner = "_Test Sales Partner India - 1"
so.commission_rate = 7
so.submit()
# carried to the mapped (unsaved) documents even though the field is no_copy
self.assertEqual(make_delivery_note(so.name).commission_rate, 7)
self.assertEqual(make_sales_invoice(so.name).commission_rate, 7)
finally:
frappe.db.set_value("Item", "_Test Item", "grant_commission", original)
>>>>>>> 4afba94d1c (test: sales team allocation totalling 100 in floating point)
def compare_payment_schedules(doc, doc1, doc2):
for index, schedule in enumerate(doc1.get("payment_schedule")):