From 36845a87e0fb86cf1d385a9e17c3d925c62898d2 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Tue, 22 Mar 2022 17:41:49 +0530 Subject: [PATCH] fix(pos): remove returned sr. nos. from pos reserved sr. nos. list (cherry picked from commit f2ae63cbfdc0262f45ccae5991927e49e5c38c4c) # Conflicts: # erpnext/accounts/doctype/pos_invoice/pos_invoice.py # erpnext/stock/doctype/serial_no/serial_no.py --- .../doctype/pos_invoice/pos_invoice.json | 4 +- .../doctype/pos_invoice/pos_invoice.py | 10 ++- .../doctype/pos_invoice/test_pos_invoice.py | 72 +++++++++++++++++++ erpnext/stock/doctype/serial_no/serial_no.py | 55 +++++++++++++- 4 files changed, 137 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json index 0c6e7edeb02..b8500270d1a 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json @@ -264,7 +264,6 @@ "print_hide": 1 }, { - "allow_on_submit": 1, "default": "0", "fieldname": "is_return", "fieldtype": "Check", @@ -1573,7 +1572,7 @@ "icon": "fa fa-file-text", "is_submittable": 1, "links": [], - "modified": "2021-10-05 12:11:53.871828", + "modified": "2022-03-22 13:00:24.166684", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice", @@ -1623,6 +1622,7 @@ "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], "timeline_field": "customer", "title_field": "title", "track_changes": 1, diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index a9be620b993..8df2e3587df 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -17,7 +17,11 @@ from erpnext.accounts.doctype.sales_invoice.sales_invoice import ( ) from erpnext.accounts.party import get_due_date, get_party_account from erpnext.stock.doctype.batch.batch import get_batch_qty, get_pos_reserved_batch_qty -from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos, get_serial_nos +from erpnext.stock.doctype.serial_no.serial_no import ( + get_delivered_serial_nos, + get_pos_reserved_serial_nos, + get_serial_nos, +) class POSInvoice(SalesInvoice): @@ -179,12 +183,16 @@ class POSInvoice(SalesInvoice): ) def validate_delivered_serial_nos(self, item): +<<<<<<< HEAD serial_nos = get_serial_nos(item.serial_no) delivered_serial_nos = frappe.db.get_list( "Serial No", {"item_code": item.item_code, "name": ["in", serial_nos], "sales_invoice": ["is", "set"]}, pluck="name", ) +======= + delivered_serial_nos = get_delivered_serial_nos(item.serial_no) +>>>>>>> f2ae63cbfd (fix(pos): remove returned sr. nos. from pos reserved sr. nos. list) if delivered_serial_nos: bold_delivered_serial_nos = frappe.bold(", ".join(delivered_serial_nos)) diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py index ee35614cdce..0925614cbc7 100644 --- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py @@ -765,6 +765,78 @@ class TestPOSInvoice(unittest.TestCase): pos_inv.delete() pr.delete() + def test_delivered_serial_no_case(self): + from erpnext.accounts.doctype.pos_invoice_merge_log.test_pos_invoice_merge_log import ( + init_user_and_profile, + ) + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + from erpnext.stock.doctype.serial_no.test_serial_no import get_serial_nos + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item + + frappe.db.savepoint('before_test_delivered_serial_no_case') + try: + se = make_serialized_item() + serial_no = get_serial_nos(se.get("items")[0].serial_no)[0] + + dn = create_delivery_note( + item_code="_Test Serialized Item With Series", serial_no=serial_no + ) + + delivery_document_no = frappe.db.get_value("Serial No", serial_no, "delivery_document_no") + self.assertEquals(delivery_document_no, dn.name) + + init_user_and_profile() + + pos_inv = create_pos_invoice( + item_code="_Test Serialized Item With Series", + serial_no=serial_no, + qty=1, + rate=100, + do_not_submit=True + ) + + self.assertRaises(frappe.ValidationError, pos_inv.submit) + + finally: + frappe.db.rollback(save_point='before_test_delivered_serial_no_case') + frappe.set_user("Administrator") + + def test_returned_serial_no_case(self): + from erpnext.accounts.doctype.pos_invoice_merge_log.test_pos_invoice_merge_log import ( + init_user_and_profile, + ) + from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos + from erpnext.stock.doctype.serial_no.test_serial_no import get_serial_nos + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item + + frappe.db.savepoint('before_test_returned_serial_no_case') + try: + se = make_serialized_item() + serial_no = get_serial_nos(se.get("items")[0].serial_no)[0] + + init_user_and_profile() + + pos_inv = create_pos_invoice( + item_code="_Test Serialized Item With Series", + serial_no=serial_no, + qty=1, + rate=100, + ) + + pos_return = make_sales_return(pos_inv.name) + pos_return.flags.ignore_validate = True + pos_return.insert() + pos_return.submit() + + pos_reserved_serial_nos = get_pos_reserved_serial_nos({ + 'item_code': '_Test Serialized Item With Series', + 'warehouse': '_Test Warehouse - _TC' + }) + self.assertTrue(serial_no not in pos_reserved_serial_nos) + + finally: + frappe.db.rollback(save_point='before_test_returned_serial_no_case') + frappe.set_user("Administrator") def create_pos_invoice(**args): args = frappe._dict(args) diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index bc30878789f..e9a5d53fdd7 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -820,11 +820,35 @@ def auto_fetch_serial_number( return sorted([d.get("name") for d in serial_numbers]) +def get_delivered_serial_nos(serial_nos): + ''' + Returns serial numbers that delivered from the list of serial numbers + ''' + from frappe.query_builder.functions import Coalesce + + SerialNo = frappe.qb.DocType("Serial No") + serial_nos = get_serial_nos(serial_nos) + query = ( + frappe.qb + .from_(SerialNo) + .select(SerialNo.name) + .where( + (SerialNo.name.isin(serial_nos)) + & (Coalesce(SerialNo.delivery_document_type, "") != "") + ) + ) + + result = query.run() + if result and len(result) > 0: + delivered_serial_nos = [row[0] for row in result] + return delivered_serial_nos + @frappe.whitelist() def get_pos_reserved_serial_nos(filters): if isinstance(filters, str): filters = json.loads(filters) +<<<<<<< HEAD pos_transacted_sr_nos = frappe.db.sql( """select item.serial_no as serial_no from `tabPOS Invoice` p, `tabPOS Invoice Item` item @@ -839,10 +863,39 @@ def get_pos_reserved_serial_nos(filters): filters, as_dict=1, ) +======= + POSInvoice = frappe.qb.DocType("POS Invoice") + POSInvoiceItem = frappe.qb.DocType("POS Invoice Item") + query = frappe.qb.from_( + POSInvoice + ).from_( + POSInvoiceItem + ).select( + POSInvoice.is_return, + POSInvoiceItem.serial_no + ).where( + (POSInvoice.name == POSInvoiceItem.parent) + & (POSInvoice.docstatus == 1) + & (POSInvoiceItem.docstatus == 1) + & (POSInvoiceItem.item_code == filters.get('item_code')) + & (POSInvoiceItem.warehouse == filters.get('warehouse')) + & (POSInvoiceItem.serial_no.isnotnull()) + & (POSInvoiceItem.serial_no != '') + ) + + pos_transacted_sr_nos = query.run(as_dict=True) +>>>>>>> f2ae63cbfd (fix(pos): remove returned sr. nos. from pos reserved sr. nos. list) reserved_sr_nos = [] + returned_sr_nos = [] for d in pos_transacted_sr_nos: - reserved_sr_nos += get_serial_nos(d.serial_no) + if d.is_return == 0: + reserved_sr_nos += get_serial_nos(d.serial_no) + elif d.is_return == 1: + returned_sr_nos += get_serial_nos(d.serial_no) + + for sr_no in returned_sr_nos: + reserved_sr_nos.remove(sr_no) return reserved_sr_nos