mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-09 15:29:30 +00:00
fix(stock): recalculate delivery note billing after return (#58869)
(cherry picked from commit f864333afa)
# Conflicts:
# erpnext/stock/doctype/delivery_note/services/billing_status.py
This commit is contained in:
@@ -740,6 +740,9 @@ class DeliveryNote(SellingController):
|
|||||||
|
|
||||||
def update_billing_status(self, update_modified=True):
|
def update_billing_status(self, update_modified=True):
|
||||||
updated_delivery_notes = [self.name]
|
updated_delivery_notes = [self.name]
|
||||||
|
if self.is_return and self.return_against:
|
||||||
|
updated_delivery_notes.append(self.return_against)
|
||||||
|
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.si_detail and not d.so_detail:
|
if d.si_detail and not d.so_detail:
|
||||||
d.db_set("billed_amt", d.amount, update_modified=update_modified)
|
d.db_set("billed_amt", d.amount, update_modified=update_modified)
|
||||||
@@ -748,7 +751,12 @@ class DeliveryNote(SellingController):
|
|||||||
|
|
||||||
for dn in set(updated_delivery_notes):
|
for dn in set(updated_delivery_notes):
|
||||||
dn_doc = self if (dn == self.name) else frappe.get_doc("Delivery Note", dn)
|
dn_doc = self if (dn == self.name) else frappe.get_doc("Delivery Note", dn)
|
||||||
dn_doc.update_billing_percentage(update_modified=update_modified)
|
update_dn_modified = update_modified and dn != self.return_against
|
||||||
|
dn_doc.update_billing_percentage(update_modified=update_dn_modified)
|
||||||
|
if dn == self.return_against:
|
||||||
|
dn_doc.load_from_db()
|
||||||
|
dn_doc.set_status(update=True, update_modified=False)
|
||||||
|
dn_doc.notify_update()
|
||||||
|
|
||||||
self.load_from_db()
|
self.load_from_db()
|
||||||
|
|
||||||
|
|||||||
@@ -1049,6 +1049,56 @@ class TestDeliveryNote(FrappeTestCase):
|
|||||||
self.assertEqual(dn.per_billed, 100)
|
self.assertEqual(dn.per_billed, 100)
|
||||||
self.assertEqual(dn.status, "Completed")
|
self.assertEqual(dn.status, "Completed")
|
||||||
|
|
||||||
|
def test_dn_is_completed_when_unbilled_item_is_returned(self):
|
||||||
|
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_return
|
||||||
|
|
||||||
|
make_stock_entry(target="_Test Warehouse - _TC", qty=1, basic_rate=100)
|
||||||
|
make_stock_entry(item_code="_Test Item 2", target="_Test Warehouse - _TC", qty=1, basic_rate=100)
|
||||||
|
|
||||||
|
dn = create_delivery_note(do_not_submit=True)
|
||||||
|
dn.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": "_Test Item 2",
|
||||||
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
|
"qty": 1,
|
||||||
|
"rate": 100,
|
||||||
|
"conversion_factor": 1,
|
||||||
|
"allow_zero_valuation_rate": 1,
|
||||||
|
"expense_account": "Cost of Goods Sold - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
dn.submit()
|
||||||
|
|
||||||
|
si = make_sales_invoice(dn.name)
|
||||||
|
si.set("items", [item for item in si.items if item.item_code == "_Test Item"])
|
||||||
|
si.insert()
|
||||||
|
si.submit()
|
||||||
|
|
||||||
|
dn.reload()
|
||||||
|
self.assertEqual(dn.per_billed, 50)
|
||||||
|
self.assertEqual(dn.status, "Partially Billed")
|
||||||
|
|
||||||
|
return_dn = make_sales_return(dn.name)
|
||||||
|
return_dn.set("items", [item for item in return_dn.items if item.item_code == "_Test Item 2"])
|
||||||
|
return_dn.insert()
|
||||||
|
# Mimic the submit request, which reconstructs the document from client data.
|
||||||
|
return_dn = frappe.get_doc(return_dn.as_dict())
|
||||||
|
return_dn.submit()
|
||||||
|
|
||||||
|
dn.reload()
|
||||||
|
self.assertEqual(dn.items[1].returned_qty, 1)
|
||||||
|
self.assertEqual(dn.per_billed, 100)
|
||||||
|
self.assertEqual(dn.status, "Completed")
|
||||||
|
|
||||||
|
return_dn.cancel()
|
||||||
|
|
||||||
|
dn.reload()
|
||||||
|
self.assertEqual(dn.items[1].returned_qty, 0)
|
||||||
|
self.assertEqual(dn.per_billed, 50)
|
||||||
|
self.assertEqual(dn.status, "Partially Billed")
|
||||||
|
|
||||||
def test_dn_billing_status_case2(self):
|
def test_dn_billing_status_case2(self):
|
||||||
# SO -> SI and SO -> DN1, DN2
|
# SO -> SI and SO -> DN1, DN2
|
||||||
from erpnext.selling.doctype.sales_order.sales_order import (
|
from erpnext.selling.doctype.sales_order.sales_order import (
|
||||||
|
|||||||
Reference in New Issue
Block a user