From 47a622d0cb14f896cfc58154d37976cb6e729436 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 10 Jan 2025 18:19:48 +0530 Subject: [PATCH 1/4] fix: delivery_document_no column issue (cherry picked from commit 61efb2bb39a720b2d0fc98ff714b4477fcaa6dc5) # Conflicts: # erpnext/accounts/doctype/sales_invoice/sales_invoice.py # erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py (cherry picked from commit 0df18080c7277bb773134f7fbcfab0fb0c6a1ba4) --- .../doctype/sales_invoice/sales_invoice.py | 7 ++-- .../sales_invoice_item/sales_invoice_item.py | 38 +++++++++++++++++++ .../doctype/delivery_note/delivery_note.py | 6 --- erpnext/stock/doctype/serial_no/serial_no.py | 15 -------- 4 files changed, 42 insertions(+), 24 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index cb501c1ffbc..ee18410a57b 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -321,9 +321,7 @@ class SalesInvoice(SellingController): self.set_against_income_account() self.validate_time_sheets_are_submitted() self.validate_multiple_billing("Delivery Note", "dn_detail", "amount") - if not self.is_return: - self.validate_serial_numbers() - else: + if self.is_return: self.timesheets = [] self.update_packing_list() self.set_billing_hours_and_amount() @@ -1706,6 +1704,7 @@ class SalesInvoice(SellingController): self.set("write_off_amount", reference_doc.get("write_off_amount")) self.due_date = None +<<<<<<< HEAD def validate_serial_numbers(self): """ validate serial number agains Delivery Note and Sales Invoice @@ -1753,6 +1752,8 @@ class SalesInvoice(SellingController): ) ) +======= +>>>>>>> 61efb2bb39 (fix: delivery_document_no column issue) def update_project(self): unique_projects = list(set([d.project for d in self.get("items") if d.project])) if self.project and self.project not in unique_projects: diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py index b7b0873c76b..b96445e2c3a 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py @@ -3,6 +3,13 @@ from frappe.model.document import Document +<<<<<<< HEAD +======= +from frappe.utils.data import cint + +from erpnext.assets.doctype.asset.depreciation import get_disposal_account_and_cost_center +from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos +>>>>>>> 61efb2bb39 (fix: delivery_document_no column issue) class SalesInvoiceItem(Document): @@ -93,4 +100,35 @@ class SalesInvoiceItem(Document): weight_uom: DF.Link | None # end: auto-generated types +<<<<<<< HEAD pass +======= + def validate_cost_center(self, company: str): + cost_center_company = frappe.get_cached_value("Cost Center", self.cost_center, "company") + if cost_center_company != company: + frappe.throw( + _("Row #{0}: Cost Center {1} does not belong to company {2}").format( + frappe.bold(self.idx), frappe.bold(self.cost_center), frappe.bold(company) + ) + ) + + def set_actual_qty(self): + if self.item_code and self.warehouse: + self.actual_qty = ( + frappe.db.get_value( + "Bin", {"item_code": self.item_code, "warehouse": self.warehouse}, "actual_qty" + ) + or 0 + ) + + def set_income_account_for_fixed_asset(self, company: str): + """Set income account for fixed asset item based on company's disposal account and cost center.""" + if not self.is_fixed_asset: + return + + disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(company) + + self.income_account = disposal_account + if not self.cost_center: + self.cost_center = depreciation_cost_center +>>>>>>> 61efb2bb39 (fix: delivery_document_no column issue) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 2b4dad137c2..76e5b4ea972 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -12,7 +12,6 @@ from frappe.utils import cint, flt from erpnext.controllers.accounts_controller import get_taxes_and_charges, merge_taxes from erpnext.controllers.selling_controller import SellingController -from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no form_grid_templates = {"items": "templates/form_grid/item_grid.html"} @@ -980,11 +979,6 @@ def make_sales_invoice(source_name, target_doc=None, args=None): def update_item(source_doc, target_doc, source_parent): target_doc.qty = to_make_invoice_qty_map[source_doc.name] - if source_doc.serial_no and source_parent.per_billed > 0 and not source_parent.is_return: - target_doc.serial_no = get_delivery_note_serial_no( - source_doc.item_code, target_doc.qty, source_parent.name - ) - def get_pending_qty(item_row): pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 4c693d8efec..54f96fb7b10 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -169,21 +169,6 @@ def update_maintenance_status(): frappe.db.set_value("Serial No", doc.name, "maintenance_status", doc.maintenance_status) -def get_delivery_note_serial_no(item_code, qty, delivery_note): - serial_nos = "" - dn_serial_nos = frappe.db.sql_list( - f""" select name from `tabSerial No` - where item_code = %(item_code)s and delivery_document_no = %(delivery_note)s - and sales_invoice is null limit {cint(qty)}""", - {"item_code": item_code, "delivery_note": delivery_note}, - ) - - if dn_serial_nos and len(dn_serial_nos) > 0: - serial_nos = "\n".join(dn_serial_nos) - - return serial_nos - - @frappe.whitelist() def auto_fetch_serial_number( qty: int, From 120bccdad3c19ae88f0e1bbf159d9995c87084a1 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Sat, 11 Jan 2025 10:59:26 +0530 Subject: [PATCH 2/4] chore: fix conflicts (cherry picked from commit 9426a3218465a9fac751b48a7d83b170f6d259f3) --- .../sales_invoice_item/sales_invoice_item.py | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py index b96445e2c3a..b7b0873c76b 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py @@ -3,13 +3,6 @@ from frappe.model.document import Document -<<<<<<< HEAD -======= -from frappe.utils.data import cint - -from erpnext.assets.doctype.asset.depreciation import get_disposal_account_and_cost_center -from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos ->>>>>>> 61efb2bb39 (fix: delivery_document_no column issue) class SalesInvoiceItem(Document): @@ -100,35 +93,4 @@ class SalesInvoiceItem(Document): weight_uom: DF.Link | None # end: auto-generated types -<<<<<<< HEAD pass -======= - def validate_cost_center(self, company: str): - cost_center_company = frappe.get_cached_value("Cost Center", self.cost_center, "company") - if cost_center_company != company: - frappe.throw( - _("Row #{0}: Cost Center {1} does not belong to company {2}").format( - frappe.bold(self.idx), frappe.bold(self.cost_center), frappe.bold(company) - ) - ) - - def set_actual_qty(self): - if self.item_code and self.warehouse: - self.actual_qty = ( - frappe.db.get_value( - "Bin", {"item_code": self.item_code, "warehouse": self.warehouse}, "actual_qty" - ) - or 0 - ) - - def set_income_account_for_fixed_asset(self, company: str): - """Set income account for fixed asset item based on company's disposal account and cost center.""" - if not self.is_fixed_asset: - return - - disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(company) - - self.income_account = disposal_account - if not self.cost_center: - self.cost_center = depreciation_cost_center ->>>>>>> 61efb2bb39 (fix: delivery_document_no column issue) From 85c2d32de69bc87322e34f4dca876860ac9c282c Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Sat, 11 Jan 2025 11:00:20 +0530 Subject: [PATCH 3/4] chore: fix conflicts (cherry picked from commit bb170c024fcce26ef64e0afc2c30344f2b63e98a) --- .../doctype/sales_invoice/sales_invoice.py | 50 ------------------- 1 file changed, 50 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index ee18410a57b..174a80d4d75 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1704,56 +1704,6 @@ class SalesInvoice(SellingController): self.set("write_off_amount", reference_doc.get("write_off_amount")) self.due_date = None -<<<<<<< HEAD - def validate_serial_numbers(self): - """ - validate serial number agains Delivery Note and Sales Invoice - """ - self.set_serial_no_against_delivery_note() - self.validate_serial_against_delivery_note() - - def set_serial_no_against_delivery_note(self): - for item in self.items: - if item.serial_no and item.delivery_note and item.qty != len(get_serial_nos(item.serial_no)): - item.serial_no = get_delivery_note_serial_no(item.item_code, item.qty, item.delivery_note) - - def validate_serial_against_delivery_note(self): - """ - validate if the serial numbers in Sales Invoice Items are same as in - Delivery Note Item - """ - - for item in self.items: - if not item.delivery_note or not item.dn_detail: - continue - - serial_nos = frappe.db.get_value("Delivery Note Item", item.dn_detail, "serial_no") or "" - dn_serial_nos = set(get_serial_nos(serial_nos)) - - serial_nos = item.serial_no or "" - si_serial_nos = set(get_serial_nos(serial_nos)) - serial_no_diff = si_serial_nos - dn_serial_nos - - if serial_no_diff: - dn_link = frappe.utils.get_link_to_form("Delivery Note", item.delivery_note) - serial_no_msg = ", ".join(frappe.bold(d) for d in serial_no_diff) - - msg = _("Row #{0}: The following Serial Nos are not present in Delivery Note {1}:").format( - item.idx, dn_link - ) - msg += " " + serial_no_msg - - frappe.throw(msg=msg, title=_("Serial Nos Mismatch")) - - if item.serial_no and cint(item.qty) != len(si_serial_nos): - frappe.throw( - _("Row #{0}: {1} Serial numbers required for Item {2}. You have provided {3}.").format( - item.idx, item.qty, item.item_code, len(si_serial_nos) - ) - ) - -======= ->>>>>>> 61efb2bb39 (fix: delivery_document_no column issue) def update_project(self): unique_projects = list(set([d.project for d in self.get("items") if d.project])) if self.project and self.project not in unique_projects: From b75c7364d605c0ac88f633d22d4e3d25d09c555c Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sat, 11 Jan 2025 11:06:13 +0530 Subject: [PATCH 4/4] fix: test case (cherry picked from commit 7d66e4efb0bdb7c109347ea7504b09f08858bfcb) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 174a80d4d75..c9a36e4aece 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -39,7 +39,7 @@ from erpnext.controllers.selling_controller import SellingController from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data from erpnext.setup.doctype.company.company import update_company_current_month_sales from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so -from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no, get_serial_nos +from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos form_grid_templates = {"items": "templates/form_grid/item_grid.html"}