Merge pull request #32466 from rohitwaghchaure/allow-to-return-expired-batches
fix: not able to return sold expired batches
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 782e08e..ce44ae3 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -8,7 +8,7 @@
from frappe.model.dynamic_links import get_dynamic_link_map
from frappe.model.naming import make_autoname
from frappe.tests.utils import change_settings
-from frappe.utils import add_days, flt, getdate, nowdate
+from frappe.utils import add_days, flt, getdate, nowdate, today
import erpnext
from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
@@ -3196,6 +3196,37 @@
"Accounts Settings", "Accounts Settings", "unlink_payment_on_cancel_of_invoice", unlink_enabled
)
+ def test_batch_expiry_for_sales_invoice_return(self):
+ from erpnext.controllers.sales_and_purchase_return import make_return_doc
+ from erpnext.stock.doctype.item.test_item import make_item
+
+ item = make_item(
+ "_Test Batch Item For Return Check",
+ {
+ "is_purchase_item": 1,
+ "is_stock_item": 1,
+ "has_batch_no": 1,
+ "create_new_batch": 1,
+ "batch_number_series": "TBIRC.#####",
+ },
+ )
+
+ pr = make_purchase_receipt(qty=1, item_code=item.name)
+
+ batch_no = pr.items[0].batch_no
+ si = create_sales_invoice(qty=1, item_code=item.name, update_stock=1, batch_no=batch_no)
+
+ si.load_from_db()
+ batch_no = si.items[0].batch_no
+ self.assertTrue(batch_no)
+
+ frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1))
+
+ return_si = make_return_doc(si.doctype, si.name)
+ return_si.save().submit()
+
+ self.assertTrue(return_si.docstatus == 1)
+
def get_sales_invoice_for_e_invoice():
si = make_sales_invoice_for_ewaybill()
@@ -3289,6 +3320,7 @@
"serial_no": args.serial_no,
"conversion_factor": 1,
"incoming_rate": args.incoming_rate or 0,
+ "batch_no": args.batch_no or None,
},
)
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index 6bcab73..1b9f168 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -6,7 +6,7 @@
import frappe
from frappe.tests.utils import FrappeTestCase
-from frappe.utils import cstr, flt, nowdate, nowtime
+from frappe.utils import add_days, cstr, flt, nowdate, nowtime, today
from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.accounts.utils import get_balance_on
@@ -1091,6 +1091,36 @@
frappe.db.exists("GL Entry", {"voucher_no": dn.name, "voucher_type": dn.doctype})
)
+ def test_batch_expiry_for_delivery_note(self):
+ from erpnext.controllers.sales_and_purchase_return import make_return_doc
+ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
+
+ item = make_item(
+ "_Test Batch Item For Return Check",
+ {
+ "is_purchase_item": 1,
+ "is_stock_item": 1,
+ "has_batch_no": 1,
+ "create_new_batch": 1,
+ "batch_number_series": "TBIRC.#####",
+ },
+ )
+
+ pi = make_purchase_receipt(qty=1, item_code=item.name)
+
+ dn = create_delivery_note(qty=1, item_code=item.name, batch_no=pi.items[0].batch_no)
+
+ dn.load_from_db()
+ batch_no = dn.items[0].batch_no
+ self.assertTrue(batch_no)
+
+ frappe.db.set_value("Batch", batch_no, "expiry_date", add_days(today(), -1))
+
+ return_dn = make_return_doc(dn.doctype, dn.name)
+ return_dn.save().submit()
+
+ self.assertTrue(return_dn.docstatus == 1)
+
def create_delivery_note(**args):
dn = frappe.new_doc("Delivery Note")
@@ -1117,6 +1147,7 @@
"expense_account": args.expense_account or "Cost of Goods Sold - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"serial_no": args.serial_no,
+ "batch_no": args.batch_no or None,
"target_warehouse": args.target_warehouse,
},
)
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index f7f8cbe..c64370d 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -153,7 +153,9 @@
def validate_batch(self):
if self.batch_no and self.voucher_type != "Stock Entry":
- if self.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and self.actual_qty < 0:
+ if (self.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and self.actual_qty < 0) or (
+ self.voucher_type in ["Delivery Note", "Sales Invoice"] and self.actual_qty > 0
+ ):
return
expiry_date = frappe.db.get_value("Batch", self.batch_no, "expiry_date")