mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-13 14:41:53 +00:00
Merge pull request #56335 from aerele/fix/skip-over-allowance-for-non-stock-items
fix: skip over-allowance qty validation for non-stock items
This commit is contained in:
@@ -3046,6 +3046,24 @@ class TestPurchaseInvoice(ERPNextTestSuite, StockTestMixin):
|
||||
# Test 4 - Since this PI is overbilled by 130% and only 120% is allowed, it will fail
|
||||
self.assertRaises(frappe.ValidationError, pi.submit)
|
||||
|
||||
@ERPNextTestSuite.change_settings("Accounts Settings", {"over_billing_allowance": 0})
|
||||
def test_non_stock_item_over_billing_against_po_is_blocked(self):
|
||||
service_item = create_item(
|
||||
"_Test Service Item Non Stock PI",
|
||||
is_stock_item=0,
|
||||
is_purchase_item=1,
|
||||
).name
|
||||
|
||||
po = create_purchase_order(item_code=service_item, qty=5, rate=100, do_not_save=False)
|
||||
po.submit()
|
||||
|
||||
pi = make_pi_from_po(po.name)
|
||||
pi.items[0].qty = 10 # overbill by 100 %
|
||||
pi.save()
|
||||
|
||||
with self.assertRaises(frappe.ValidationError):
|
||||
pi.submit()
|
||||
|
||||
def test_discount_percentage_not_set_when_amount_is_manually_set(self):
|
||||
pi = make_purchase_invoice(do_not_save=True)
|
||||
discount_amount = 7
|
||||
|
||||
@@ -4126,6 +4126,51 @@ class TestSalesInvoice(ERPNextTestSuite):
|
||||
self.assertIn("cannot overbill", str(err.exception).lower())
|
||||
dn.cancel()
|
||||
|
||||
@ERPNextTestSuite.change_settings("Accounts Settings", {"over_billing_allowance": 0})
|
||||
def test_non_stock_item_over_billing_against_so_is_blocked(self):
|
||||
from erpnext.selling.doctype.sales_order.mapper import make_sales_invoice as make_si_from_so
|
||||
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||
|
||||
service_item = create_item(
|
||||
"_Test Service Item Non Stock SI",
|
||||
is_stock_item=0,
|
||||
).name
|
||||
|
||||
so = make_sales_order(item_code=service_item, qty=5, rate=100)
|
||||
so.submit()
|
||||
|
||||
si = make_si_from_so(so.name)
|
||||
si.items[0].qty = 10 # overbill by 100 %
|
||||
si.save()
|
||||
|
||||
with self.assertRaises(frappe.ValidationError):
|
||||
si.submit()
|
||||
|
||||
@ERPNextTestSuite.change_settings("Accounts Settings", {"over_billing_allowance": 0})
|
||||
def test_non_stock_item_over_billing_against_so_from_quotation_is_blocked(self):
|
||||
from erpnext.selling.doctype.quotation.mapper import make_sales_order as make_so_from_quotation
|
||||
from erpnext.selling.doctype.quotation.test_quotation import make_quotation
|
||||
from erpnext.selling.doctype.sales_order.mapper import make_sales_invoice as make_si_from_so
|
||||
|
||||
service_item = create_item(
|
||||
"_Test Service Item Non Stock SI Quot",
|
||||
is_stock_item=0,
|
||||
).name
|
||||
|
||||
quotation = make_quotation(item_code=service_item, qty=5, rate=100)
|
||||
|
||||
so = make_so_from_quotation(quotation.name)
|
||||
so.delivery_date = frappe.utils.add_days(frappe.utils.today(), 7)
|
||||
so.insert()
|
||||
so.submit()
|
||||
|
||||
si = make_si_from_so(so.name)
|
||||
si.items[0].qty = 10 # overbill by 100 %
|
||||
si.save()
|
||||
|
||||
with self.assertRaises(frappe.ValidationError):
|
||||
si.submit()
|
||||
|
||||
@ERPNextTestSuite.change_settings(
|
||||
"Accounts Settings",
|
||||
{
|
||||
|
||||
@@ -384,15 +384,17 @@ class StatusUpdater(Document):
|
||||
|
||||
def fetch_items_with_pending_qty(self, args, item_field, items):
|
||||
doctype = frappe.qb.DocType(args["target_dt"])
|
||||
item_field = doctype[item_field]
|
||||
item_field_col = doctype[item_field]
|
||||
target_ref_field = doctype[args["target_ref_field"]]
|
||||
target_field = doctype[args["target_field"]]
|
||||
|
||||
return (
|
||||
is_qty_check = "qty" in args["target_ref_field"]
|
||||
|
||||
query = (
|
||||
frappe.qb.from_(doctype)
|
||||
.select(
|
||||
doctype.name,
|
||||
item_field.as_("item_code"),
|
||||
item_field_col.as_("item_code"),
|
||||
target_ref_field,
|
||||
target_field,
|
||||
doctype.parenttype,
|
||||
@@ -401,9 +403,18 @@ class StatusUpdater(Document):
|
||||
.where(target_ref_field < target_field)
|
||||
.where(doctype.name.isin(items))
|
||||
.where(doctype.docstatus == 1)
|
||||
.run(as_dict=True)
|
||||
)
|
||||
|
||||
if is_qty_check:
|
||||
item_table = frappe.qb.DocType("Item")
|
||||
query = (
|
||||
query.join(item_table)
|
||||
.on(item_table.name == item_field_col)
|
||||
.where(item_table.is_stock_item == 1)
|
||||
)
|
||||
|
||||
return query.run(as_dict=True)
|
||||
|
||||
def check_overflow_with_allowance(self, item, args):
|
||||
"""
|
||||
Checks if there is overflow considering a relaxation allowance.
|
||||
|
||||
Reference in New Issue
Block a user