From 0b1727cf79fd84b5a9b499695ab28dd74a2e5a3f Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 3 Oct 2022 12:06:32 +0530 Subject: [PATCH] fix: not able to return sold expired batches --- .../sales_invoice/test_sales_invoice.py | 34 ++++++++++++++++++- .../delivery_note/test_delivery_note.py | 33 +++++++++++++++++- .../stock_ledger_entry/stock_ledger_entry.py | 4 ++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 782e08e33b..ce44ae304b 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 @@ import frappe 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 @@ class TestSalesInvoice(unittest.TestCase): "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 @@ def create_sales_invoice(**args): "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 6bcab737b3..1b9f16814c 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 json 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 @@ class TestDeliveryNote(FrappeTestCase): 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 @@ def create_delivery_note(**args): "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 f7f8cbe4ee..c64370dcdf 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 @@ class StockLedgerEntry(Document): 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")