From 0faa116f9799f6d921ce8868a8f8eac1756ae008 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 4 Jan 2022 16:36:08 +0530 Subject: [PATCH 1/2] fix(patch): serial no whitespace trimming old data can contain trailing/leading whitespace which doesn't work well with code to find last SLE for serial no. --- erpnext/patches.txt | 1 + .../v13_0/trim_whitespace_from_serial_nos.py | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 99741eb078..c5e4f7e8a9 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -279,6 +279,7 @@ erpnext.patches.v13_0.add_custom_field_for_south_africa #2 erpnext.patches.v13_0.update_recipient_email_digest erpnext.patches.v13_0.shopify_deprecation_warning erpnext.patches.v13_0.remove_bad_selling_defaults +erpnext.patches.v13_0.trim_whitespace_from_serial_nos erpnext.patches.v13_0.migrate_stripe_api erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries erpnext.patches.v13_0.einvoicing_deprecation_warning diff --git a/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py b/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py new file mode 100644 index 0000000000..4f112550c5 --- /dev/null +++ b/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py @@ -0,0 +1,61 @@ +import frappe + +from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + + +def execute(): + broken_sles = frappe.db.sql(""" + select name, serial_no + from `tabStock Ledger Entry` + where + is_cancelled = 0 + and (serial_no like %s or serial_no like %s or serial_no like %s or serial_no like %s) + """, + ( + " %", # leading whitespace + "% ", # trailing whitespace + "%\n %", # leading whitespace on newline + "% \n%", # trailing whitespace on newline + ), + as_dict=True, + ) + + frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sles) + + if not broken_sles: + return + + broken_serial_nos = set() + + for sle in broken_sles: + serial_no_list = get_serial_nos(sle.serial_no) + correct_sr_no = "\n".join(serial_no_list) + + if correct_sr_no == sle.serial_no: + continue + + frappe.db.set_value("Stock Ledger Entry", sle.name, "serial_no", correct_sr_no, update_modified=False) + broken_serial_nos.update(serial_no_list) + + if not broken_serial_nos: + return + + broken_sr_no_records = [sr[0] for sr in frappe.db.sql(""" + select name + from `tabSerial No` + where status='Active' + and coalesce(purchase_document_type, '') = '' + and name in %s """, (list(broken_serial_nos),) + )] + + frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sr_no_records) + + patch_savepoint = "serial_no_patch" + for serial_no in broken_sr_no_records: + try: + frappe.db.savepoint(patch_savepoint) + sn = frappe.get_doc("Serial No", serial_no) + sn.update_serial_no_reference() + sn.db_update() + except Exception: + frappe.db.rollback(save_point=patch_savepoint) From cbaa8fdade4aad306887b23cef9bfeaa17ff07c0 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 10 Jan 2022 16:09:43 +0530 Subject: [PATCH 2/2] refactor: convert query to ORM --- .../v13_0/trim_whitespace_from_serial_nos.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py b/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py index 4f112550c5..8a9633d896 100644 --- a/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py +++ b/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py @@ -27,6 +27,7 @@ def execute(): broken_serial_nos = set() + # patch SLEs for sle in broken_sles: serial_no_list = get_serial_nos(sle.serial_no) correct_sr_no = "\n".join(serial_no_list) @@ -40,13 +41,16 @@ def execute(): if not broken_serial_nos: return - broken_sr_no_records = [sr[0] for sr in frappe.db.sql(""" - select name - from `tabSerial No` - where status='Active' - and coalesce(purchase_document_type, '') = '' - and name in %s """, (list(broken_serial_nos),) - )] + # Patch serial No documents if they don't have purchase info + # Purchase info is used for fetching incoming rate + broken_sr_no_records = frappe.get_list("Serial No", + filters={ + "status":"Active", + "name": ("in", broken_serial_nos), + "purchase_document_type": ("is", "not set") + }, + pluck="name", + ) frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sr_no_records)