From 527781a588a986223716cf838f6a6a4c1a1882c3 Mon Sep 17 00:00:00 2001 From: Sanket322 Date: Fri, 12 Jul 2024 18:58:14 +0530 Subject: [PATCH 01/18] fix: remove proprietorship and update it with individual (cherry picked from commit c8ad6d1b2c4407992fc415dc7ee1d0b7b2613eca) --- erpnext/buying/doctype/supplier/supplier.json | 2 +- erpnext/buying/doctype/supplier/supplier.py | 2 +- erpnext/patches.txt | 1 + .../patches/v14_0/update_proprietorship_to_individual.py | 7 +++++++ erpnext/selling/doctype/customer/customer.json | 2 +- erpnext/selling/doctype/customer/customer.py | 2 +- 6 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 erpnext/patches/v14_0/update_proprietorship_to_individual.py diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index 79ba6a721e3..c70b3e4081a 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -174,7 +174,7 @@ "fieldname": "supplier_type", "fieldtype": "Select", "label": "Supplier Type", - "options": "Company\nIndividual\nProprietorship\nPartnership", + "options": "Company\nIndividual\nPartnership", "reqd": 1 }, { diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py index ff5385dd961..bccab8b01e0 100644 --- a/erpnext/buying/doctype/supplier/supplier.py +++ b/erpnext/buying/doctype/supplier/supplier.py @@ -65,7 +65,7 @@ class Supplier(TransactionBase): supplier_name: DF.Data supplier_primary_address: DF.Link | None supplier_primary_contact: DF.Link | None - supplier_type: DF.Literal["Company", "Individual", "Proprietorship", "Partnership"] + supplier_type: DF.Literal["Company", "Individual", "Partnership"] tax_category: DF.Link | None tax_id: DF.Data | None tax_withholding_category: DF.Link | None diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 158d68ff275..e31e69d9edd 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -261,6 +261,7 @@ erpnext.patches.v15_0.delete_saudi_doctypes erpnext.patches.v14_0.show_loan_management_deprecation_warning erpnext.patches.v14_0.clear_reconciliation_values_from_singles execute:frappe.rename_doc("Report", "TDS Payable Monthly", "Tax Withholding Details", force=True) +erpnext.patches.v14_0.update_proprietorship_to_individual [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') diff --git a/erpnext/patches/v14_0/update_proprietorship_to_individual.py b/erpnext/patches/v14_0/update_proprietorship_to_individual.py new file mode 100644 index 00000000000..dc4ec15e86b --- /dev/null +++ b/erpnext/patches/v14_0/update_proprietorship_to_individual.py @@ -0,0 +1,7 @@ +import frappe + + +def execute(): + for doctype in ["Customer", "Supplier"]: + field = doctype.lower() + "_type" + frappe.db.set_value(doctype, {field: "Proprietorship"}, field, "Individual") diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index 6ed42d3b4de..af32f4ecf84 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -134,7 +134,7 @@ "label": "Customer Type", "oldfieldname": "customer_type", "oldfieldtype": "Select", - "options": "Company\nIndividual\nProprietorship\nPartnership", + "options": "Company\nIndividual\nPartnership", "reqd": 1 }, { diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 8ce67cc659a..71f0022df14 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -52,7 +52,7 @@ class Customer(TransactionBase): customer_pos_id: DF.Data | None customer_primary_address: DF.Link | None customer_primary_contact: DF.Link | None - customer_type: DF.Literal["Company", "Individual", "Proprietorship", "Partnership"] + customer_type: DF.Literal["Company", "Individual", "Partnership"] default_bank_account: DF.Link | None default_commission_rate: DF.Float default_currency: DF.Link | None From 18500b8e3a887649413294be9d7960b8981e01e9 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 21:36:47 +0530 Subject: [PATCH 02/18] fix: not able to save QC (backport #42371) (#42373) fix: not able to save QC (#42371) (cherry picked from commit 62fb495a650494bf68bbf6717dd6f53e56ad43f7) Co-authored-by: rohitwaghchaure --- erpnext/stock/doctype/quality_inspection/quality_inspection.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py index 536a88fb868..60f048673fb 100644 --- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py +++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py @@ -242,6 +242,9 @@ class QualityInspection(Document): # numeric readings for i in range(1, 11): field = "reading_" + str(i) + if reading.get(field) is None: + continue + data[field] = parse_float(reading.get(field)) data["mean"] = self.calculate_mean(reading) From 0a41ccda9935d5096c235d43111a9283d7287760 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 17 Jul 2024 15:27:58 +0530 Subject: [PATCH 03/18] fix: missing cr/dr notes on payment reconciliation (cherry picked from commit a30af68e9e71752f8317e23c9865d0f38d18512e) --- .../doctype/payment_reconciliation/payment_reconciliation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index a2f355ad329..8481fd8ffa4 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -267,6 +267,7 @@ class PaymentReconciliation(Document): conditions.append(doc.docstatus == 1) conditions.append(doc[frappe.scrub(self.party_type)] == self.party) conditions.append(doc.is_return == 1) + conditions.append(doc.outstanding_amount != 0) if self.payment_name: conditions.append(doc.name.like(f"%{self.payment_name}%")) From 3f820734b67194e448c5124cff5ad02ffbfac0e2 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 17 Jul 2024 17:51:11 +0530 Subject: [PATCH 04/18] test: payment filter should not affect dr/cr notes (cherry picked from commit 2d686c06ea213cbd6e7a5cf7173a5a4bddbcc67b) --- .../test_payment_reconciliation.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py index a5295585221..5aa411158a8 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py @@ -1805,6 +1805,46 @@ class TestPaymentReconciliation(FrappeTestCase): ] self.assertEqual(pl_entries, expected_ple) + def test_cr_note_payment_limit_filter(self): + transaction_date = nowdate() + amount = 100 + + for _ in range(6): + self.create_sales_invoice(qty=1, rate=amount, posting_date=transaction_date) + cr_note = self.create_sales_invoice( + qty=-1, rate=amount, posting_date=transaction_date, do_not_save=True, do_not_submit=True + ) + cr_note.is_return = 1 + cr_note = cr_note.save().submit() + + pr = self.create_payment_reconciliation() + + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 6) + self.assertEqual(len(pr.payments), 6) + invoices = [x.as_dict() for x in pr.get("invoices")] + payments = [x.as_dict() for x in pr.get("payments")] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.reconcile() + + pr.get_unreconciled_entries() + self.assertEqual(pr.get("invoices"), []) + self.assertEqual(pr.get("payments"), []) + + self.create_sales_invoice(qty=1, rate=amount, posting_date=transaction_date) + cr_note = self.create_sales_invoice( + qty=-1, rate=amount, posting_date=transaction_date, do_not_save=True, do_not_submit=True + ) + cr_note.is_return = 1 + cr_note = cr_note.save().submit() + + # Limit should not affect in fetching the unallocated cr_note + pr.invoice_limit = 5 + pr.payment_limit = 5 + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 1) + self.assertEqual(len(pr.payments), 1) + def make_customer(customer_name, currency=None): if not frappe.db.exists("Customer", customer_name): From 886256c86b94aaf2e91e4ca6c6652bd503bb2ca2 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 17 Jul 2024 21:23:56 +0530 Subject: [PATCH 05/18] fix: Show the rows in AR/AP report where outstanding equals to 0.01 (cherry picked from commit e1dedc5402896e07c8392e0ac3160b5b98a26222) --- .../report/accounts_receivable/accounts_receivable.py | 8 ++++---- erpnext/patches.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 64dba0183dc..30775c7fa66 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -288,13 +288,13 @@ class ReceivablePayableReport: must_consider = False if self.filters.get("for_revaluation_journals"): - if (abs(row.outstanding) > 0.0 / 10**self.currency_precision) or ( - abs(row.outstanding_in_account_currency) > 0.0 / 10**self.currency_precision + if (abs(row.outstanding) >= 0.0 / 10**self.currency_precision) or ( + abs(row.outstanding_in_account_currency) >= 0.0 / 10**self.currency_precision ): must_consider = True else: - if (abs(row.outstanding) > 1.0 / 10**self.currency_precision) and ( - (abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision) + if (abs(row.outstanding) >= 1.0 / 10**self.currency_precision) and ( + (abs(row.outstanding_in_account_currency) >= 1.0 / 10**self.currency_precision) or (row.voucher_no in self.err_journals) ): must_consider = True diff --git a/erpnext/patches.txt b/erpnext/patches.txt index e31e69d9edd..e1c2878e9bd 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -254,7 +254,6 @@ erpnext.patches.v13_0.reset_corrupt_defaults erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair erpnext.patches.v15_0.delete_taxjar_doctypes erpnext.patches.v15_0.delete_ecommerce_doctypes -erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets erpnext.patches.v14_0.update_reference_due_date_in_journal_entry erpnext.patches.v15_0.saudi_depreciation_warning erpnext.patches.v15_0.delete_saudi_doctypes @@ -264,6 +263,7 @@ execute:frappe.rename_doc("Report", "TDS Payable Monthly", "Tax Withholding Deta erpnext.patches.v14_0.update_proprietorship_to_individual [post_model_sync] +erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') erpnext.patches.v14_0.update_posting_datetime_and_dropped_indexes #22-02-2024 erpnext.patches.v14_0.rename_ongoing_status_in_sla_documents From 0dae0a05d41105055f212043bf7fa6c6cd9d9388 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 18 Jul 2024 12:58:09 +0530 Subject: [PATCH 06/18] test: AR/AP report on miniscule outstanding (cherry picked from commit bb9e42cce278c1ad6760f721cf8417c041c85b4a) --- .../test_accounts_receivable.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py index a65e424173c..5e2adc42d84 100644 --- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py @@ -955,3 +955,32 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase): self.assertEqual( expected_data, [row.invoiced, row.outstanding, row.remaining_balance, row.future_amount] ) + + def test_accounts_receivable_output_for_minor_outstanding(self): + """ + AR/AP should report miniscule outstanding of 0.01. Or else there will be slight difference with General Ledger/Trial Balance + """ + filters = { + "company": self.company, + "report_date": today(), + "range1": 30, + "range2": 60, + "range3": 90, + "range4": 120, + } + + # check invoice grand total and invoiced column's value for 3 payment terms + si = self.create_sales_invoice(no_payment_schedule=True) + + pe = get_payment_entry("Sales Invoice", si.name, bank_account=self.cash, party_amount=99.99) + pe.paid_from = self.debit_to + pe.save().submit() + report = execute(filters) + + expected_data_after_payment = [100, 100, 99.99, 0.01] + self.assertEqual(len(report[1]), 1) + row = report[1][0] + self.assertEqual( + expected_data_after_payment, + [row.invoice_grand_total, row.invoiced, row.paid, row.outstanding], + ) From aee2cc2e033b429a98bda6a54562a652a4d17f9f Mon Sep 17 00:00:00 2001 From: hiteshprajapati Date: Thu, 20 Jun 2024 14:11:18 +0530 Subject: [PATCH 07/18] fix: Don't allow negative amount on Payment Request #41905 (cherry picked from commit b823aa66bf95821a9b569c891a71085493c3ac49) # Conflicts: # erpnext/accounts/doctype/payment_request/payment_request.json --- .../accounts/doctype/payment_request/payment_request.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index 66b5c4b983e..3872b0777cf 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -144,6 +144,7 @@ "fieldname": "grand_total", "fieldtype": "Currency", "label": "Amount", + "non_negative": 1, "options": "currency" }, { @@ -395,7 +396,11 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], +<<<<<<< HEAD "modified": "2023-09-27 09:51:42.277638", +======= + "modified": "2024-06-20 13:54:55.245774", +>>>>>>> b823aa66bf (fix: Don't allow negative amount on Payment Request #41905) "modified_by": "Administrator", "module": "Accounts", "name": "Payment Request", @@ -433,4 +438,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} From a9146efc178ea235640cf961a3312a7fe6b2d7f5 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 19 Jul 2024 10:36:42 +0530 Subject: [PATCH 08/18] chore: resolve conflict --- erpnext/accounts/doctype/payment_request/payment_request.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index 3872b0777cf..0537ee6d3a3 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -396,11 +396,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], -<<<<<<< HEAD - "modified": "2023-09-27 09:51:42.277638", -======= "modified": "2024-06-20 13:54:55.245774", ->>>>>>> b823aa66bf (fix: Don't allow negative amount on Payment Request #41905) "modified_by": "Administrator", "module": "Accounts", "name": "Payment Request", From 709be13e8288d12204fc30109273293fb4d44582 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:49:39 +0530 Subject: [PATCH 09/18] fix: Purchase Order Analysis Report Data (backport #42387) (#42394) fix: Purchase Order Analysis Report Data (#42387) (cherry picked from commit 67bf9bec474f9969e6f4e033a760fbe197db6a95) Co-authored-by: rohitwaghchaure --- .../purchase_order_analysis/purchase_order_analysis.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py index cf5e0ca3f8f..7df96064a0c 100644 --- a/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py +++ b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.py @@ -46,9 +46,9 @@ def get_data(filters): frappe.qb.from_(po) .from_(po_item) .left_join(pi_item) - .on(pi_item.po_detail == po_item.name) + .on(pi_item.po_detail == po_item.name & pi_item.docstatus == 1) .left_join(pi) - .on(pi.name == pi_item.parent) + .on(pi.name == pi_item.parent & pi.docstatus == 1) .select( po.transaction_date.as_("date"), po_item.schedule_date.as_("required_date"), @@ -72,7 +72,6 @@ def get_data(filters): po_item.name, ) .where((po_item.parent == po.name) & (po.status.notin(("Stopped", "Closed"))) & (po.docstatus == 1)) - .where(pi.docstatus == 1) .groupby(po_item.name) .orderby(po.transaction_date) ) From 54791e938bd56eb81f7d8d923381a006998919fe Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:49:56 +0530 Subject: [PATCH 10/18] fix: rounding issue causing incorrect quantity in SE (backport #42380) (#42395) fix: rounding issue causing incorrect quantity in SE (#42380) (cherry picked from commit e1b9b432c37aeddcba9731d2cfe11f845621d4fd) Co-authored-by: rohitwaghchaure --- erpnext/stock/doctype/stock_entry/stock_entry.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 36f6f354bdf..14e0fdf6388 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -2354,17 +2354,22 @@ class StockEntry(StockController): return [d.item_code for d in job_card_items] def add_to_stock_entry_detail(self, item_dict, bom_no=None): + precision = frappe.get_precision("Stock Entry Detail", "qty") for d in item_dict: item_row = item_dict[d] - stock_uom = item_row.get("stock_uom") or frappe.db.get_value("Item", d, "stock_uom") + + child_qty = flt(item_row["qty"], precision) + if not self.is_return and child_qty <= 0: + continue se_child = self.append("items") + stock_uom = item_row.get("stock_uom") or frappe.db.get_value("Item", d, "stock_uom") se_child.s_warehouse = item_row.get("from_warehouse") se_child.t_warehouse = item_row.get("to_warehouse") se_child.item_code = item_row.get("item_code") or cstr(d) se_child.uom = item_row["uom"] if item_row.get("uom") else stock_uom se_child.stock_uom = stock_uom - se_child.qty = flt(item_row["qty"], se_child.precision("qty")) + se_child.qty = child_qty se_child.allow_alternative_item = item_row.get("allow_alternative_item", 0) se_child.subcontracted_item = item_row.get("main_item_code") se_child.cost_center = item_row.get("cost_center") or get_default_cost_center( From 0052ca9173198a251ce731939e7c13a31ea213bb Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 19 Jul 2024 16:31:58 +0530 Subject: [PATCH 11/18] test: basic test case for item-wise purchase register (cherry picked from commit c3c5d3f61563e1915f07f2a95a43b5aa3393dfb8) --- .../test_item_wise_purchase_register.py | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 erpnext/accounts/report/item_wise_purchase_register/test_item_wise_purchase_register.py diff --git a/erpnext/accounts/report/item_wise_purchase_register/test_item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/test_item_wise_purchase_register.py new file mode 100644 index 00000000000..3884854ba7f --- /dev/null +++ b/erpnext/accounts/report/item_wise_purchase_register/test_item_wise_purchase_register.py @@ -0,0 +1,63 @@ +import frappe +from frappe.tests.utils import FrappeTestCase +from frappe.utils import getdate, today + +from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice +from erpnext.accounts.report.item_wise_purchase_register.item_wise_purchase_register import execute +from erpnext.accounts.test.accounts_mixin import AccountsTestMixin + + +class TestItemWisePurchaseRegister(AccountsTestMixin, FrappeTestCase): + def setUp(self): + self.create_company() + self.create_supplier() + self.create_item() + + def tearDown(self): + frappe.db.rollback() + + def create_purchase_invoice(self, do_not_submit=False): + pi = make_purchase_invoice( + item=self.item, + company=self.company, + supplier=self.supplier, + is_return=False, + update_stock=False, + do_not_save=1, + rate=100, + price_list_rate=100, + qty=1, + ) + + pi = pi.save() + if not do_not_submit: + pi = pi.submit() + return pi + + def test_basic_report_output(self): + pi = self.create_purchase_invoice() + + filters = frappe._dict({"from_date": today(), "to_date": today(), "company": self.company}) + report = execute(filters) + + self.assertEqual(len(report[1]), 1) + + expected_result = { + "item_code": pi.items[0].item_code, + "invoice": pi.name, + "posting_date": getdate(), + "supplier": pi.supplier, + "credit_to": pi.credit_to, + "company": self.company, + "expense_account": pi.items[0].expense_account, + "stock_qty": 1.0, + "stock_uom": pi.items[0].stock_uom, + "rate": 100.0, + "amount": 100.0, + "total_tax": 0, + "total": 100.0, + "currency": "INR", + } + + report_output = {k: v for k, v in report[1][0].items() if k in expected_result} + self.assertDictEqual(report_output, expected_result) From 29fc975fb8830f3ce0dbed5e5797bd100718de9b Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Fri, 19 Jul 2024 19:10:33 +0530 Subject: [PATCH 12/18] fix: set filter to show only submitted asset (cherry picked from commit 69b8e10e20ec4e0dfc52ddc3918a9c36a5f1c676) --- .../doctype/asset_maintenance/asset_maintenance.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.js b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.js index 83dabab8935..ec1ca942a42 100644 --- a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.js +++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.js @@ -3,6 +3,15 @@ frappe.ui.form.on("Asset Maintenance", { setup: (frm) => { + frm.set_query("asset_name", function () { + return { + filters: { + company: frm.doc.company, + docstatus: 1, + }, + }; + }); + frm.set_query("assign_to", "asset_maintenance_tasks", function (doc) { return { query: "erpnext.assets.doctype.asset_maintenance.asset_maintenance.get_team_members", From 22b17de2b4adfc2383e2ed3ba1377c2febd2b54c Mon Sep 17 00:00:00 2001 From: HENRY Florian Date: Fri, 19 Jul 2024 12:52:11 +0200 Subject: [PATCH 13/18] feat: add make_regional_gl_entries override for Sales Invoice (#42399) * feat: add make_regional_gl_entries override for Sales Invoice and Stock Controler * chore: remove regionnal override for stock management (cherry picked from commit 1bbe020cfde623a234ba71f9b9ca81bcf6b7253c) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 7694c23236b..0d48cf229e5 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1213,6 +1213,8 @@ class SalesInvoice(SellingController): self.make_precision_loss_gl_entry(gl_entries) self.make_discount_gl_entries(gl_entries) + gl_entries = make_regional_gl_entries(gl_entries, self) + # merge gl entries before adding pos entries gl_entries = merge_similar_entries(gl_entries) @@ -2226,6 +2228,11 @@ def make_inter_company_purchase_invoice(source_name, target_doc=None): return make_inter_company_transaction("Sales Invoice", source_name, target_doc) +@erpnext.allow_regional +def make_regional_gl_entries(gl_entries, doc): + return gl_entries + + def make_inter_company_transaction(doctype, source_name, target_doc=None): if doctype in ["Sales Invoice", "Sales Order"]: source_doc = frappe.get_doc(doctype, source_name) From 8da28dcfb29ad5f922bd9d24215fe95c2909feb9 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 20 Jul 2024 11:12:17 +0530 Subject: [PATCH 14/18] fix: Consider adding warranty period to serial nos (backport #42051) (#42182) fix: Consider adding warranty period to serial nos (#42051) (cherry picked from commit 55e2b876a2efba5914cb3e6688958e5b488f3a17) Co-authored-by: Syed Mujeer Hashmi --- .../serial_and_batch_bundle/serial_and_batch_bundle.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 741d1fdfae9..3ada8f0bbcd 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1098,7 +1098,9 @@ def create_serial_nos(item_code, serial_nos): def make_serial_nos(item_code, serial_nos): - item = frappe.get_cached_value("Item", item_code, ["description", "item_code"], as_dict=1) + item = frappe.get_cached_value( + "Item", item_code, ["description", "item_code", "item_name", "warranty_period"], as_dict=1 + ) serial_nos = [d.get("serial_no") for d in serial_nos if d.get("serial_no")] existing_serial_nos = frappe.get_all("Serial No", filters={"name": ("in", serial_nos)}) @@ -1123,6 +1125,7 @@ def make_serial_nos(item_code, serial_nos): item.item_code, item.item_name, item.description, + item.warranty_period or 0, "Inactive", ) ) @@ -1137,6 +1140,7 @@ def make_serial_nos(item_code, serial_nos): "item_code", "item_name", "description", + "warranty_period", "status", ] From 555be2be11623d8fd8018ab3a2807e07a1050cf6 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sun, 21 Jul 2024 00:00:14 +0530 Subject: [PATCH 15/18] fix: serial and batch bundle for POS Invoice (backport #41491) (#42396) * fix: serial and batch bundle for POS Invoice (#41491) (cherry picked from commit e5dfc5e545fa3c9ea7e77c99116aac01521e37a6) # Conflicts: # erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json * chore: fix conflicts --------- Co-authored-by: rohitwaghchaure --- .../test_pos_closing_entry.py | 92 +++++++++++++++++++ .../doctype/pos_invoice/pos_invoice.py | 19 +++- .../doctype/pos_invoice/test_pos_invoice.py | 9 +- .../pos_invoice_item/pos_invoice_item.json | 8 +- .../pos_invoice_merge_log.py | 8 ++ .../page/point_of_sale/pos_controller.js | 1 + .../page/point_of_sale/pos_item_details.js | 4 +- .../serial_and_batch_bundle.py | 6 +- erpnext/stock/serial_batch_bundle.py | 17 ++++ 9 files changed, 149 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py index 6319d5dfb02..e2084e89c43 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py @@ -17,6 +17,10 @@ from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_inv from erpnext.accounts.doctype.pos_opening_entry.test_pos_opening_entry import create_opening_entry from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile from erpnext.selling.page.point_of_sale.point_of_sale import get_items +from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle import ( + get_batch_from_bundle, +) from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry @@ -179,6 +183,94 @@ class TestPOSClosingEntry(unittest.TestCase): accounting_dimension_department.save() disable_dimension() + def test_merging_into_sales_invoice_for_batched_item(self): + frappe.flags.print_message = False + from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import ( + init_user_and_profile, + ) + from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import ( + consolidate_pos_invoices, + ) + from erpnext.stock.doctype.batch.batch import get_batch_qty + + frappe.db.sql("delete from `tabPOS Invoice`") + item_doc = make_item( + "_Test Item With Batch FOR POS Merge Test", + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "batch_number_series": "BATCH-PM-POS-MERGE-.####", + "create_new_batch": 1, + }, + ) + + item_code = item_doc.name + se = make_stock_entry( + target="_Test Warehouse - _TC", + item_code=item_code, + qty=10, + basic_rate=100, + use_serial_batch_fields=0, + ) + batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle) + + test_user, pos_profile = init_user_and_profile() + opening_entry = create_opening_entry(pos_profile, test_user.name) + + pos_inv = create_pos_invoice( + item_code=item_code, qty=5, rate=300, use_serial_batch_fields=1, batch_no=batch_no + ) + pos_inv2 = create_pos_invoice( + item_code=item_code, qty=5, rate=300, use_serial_batch_fields=1, batch_no=batch_no + ) + + batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty") + self.assertEqual(batch_qty, 10) + + batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code) + self.assertEqual(batch_qty_with_pos, 0.0) + + pcv_doc = make_closing_entry_from_opening(opening_entry) + pcv_doc.submit() + + piv_merge = frappe.db.get_value("POS Invoice Merge Log", {"pos_closing_entry": pcv_doc.name}, "name") + + self.assertTrue(piv_merge) + piv_merge_doc = frappe.get_doc("POS Invoice Merge Log", piv_merge) + self.assertTrue(piv_merge_doc.pos_invoices[0].pos_invoice) + self.assertTrue(piv_merge_doc.pos_invoices[1].pos_invoice) + + pos_inv.load_from_db() + self.assertTrue(pos_inv.consolidated_invoice) + pos_inv2.load_from_db() + self.assertTrue(pos_inv2.consolidated_invoice) + + batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty") + self.assertEqual(batch_qty, 0.0) + + batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code) + self.assertEqual(batch_qty_with_pos, 0.0) + + frappe.flags.print_message = True + + pcv_doc.reload() + pcv_doc.cancel() + + batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty") + self.assertEqual(batch_qty, 10) + + batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code) + self.assertEqual(batch_qty_with_pos, 0.0) + + pos_inv.reload() + pos_inv2.reload() + + pos_inv.cancel() + pos_inv2.cancel() + + batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code) + self.assertEqual(batch_qty_with_pos, 10.0) + def init_user_and_profile(**args): user = "test@example.com" diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 34a31d52dd0..ef4db1dac98 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -229,7 +229,9 @@ class POSInvoice(SalesInvoice): self.check_phone_payments() self.set_status(update=True) self.make_bundle_for_sales_purchase_return() - self.submit_serial_batch_bundle() + for table_name in ["items", "packed_items"]: + self.make_bundle_using_old_serial_batch_fields(table_name) + self.submit_serial_batch_bundle(table_name) if self.coupon_code: from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count @@ -283,10 +285,11 @@ class POSInvoice(SalesInvoice): {"is_cancelled": 1, "voucher_no": ""}, ) + frappe.get_doc("Serial and Batch Bundle", row.serial_and_batch_bundle).cancel() row.db_set("serial_and_batch_bundle", None) - def submit_serial_batch_bundle(self): - for item in self.items: + def submit_serial_batch_bundle(self, table_name): + for item in self.get(table_name): if item.serial_and_batch_bundle: doc = frappe.get_doc("Serial and Batch Bundle", item.serial_and_batch_bundle) @@ -355,10 +358,16 @@ class POSInvoice(SalesInvoice): error_msg = [] for d in self.get("items"): error_msg = "" - if d.get("has_serial_no") and not d.serial_and_batch_bundle: + if d.get("has_serial_no") and ( + (not d.use_serial_batch_fields and not d.serial_and_batch_bundle) + or (d.use_serial_batch_fields and not d.serial_no) + ): error_msg = f"Row #{d.idx}: Please select Serial No. for item {bold(d.item_code)}" - elif d.get("has_batch_no") and not d.serial_and_batch_bundle: + elif d.get("has_batch_no") and ( + (not d.use_serial_batch_fields and not d.serial_and_batch_bundle) + or (d.use_serial_batch_fields and not d.batch_no) + ): error_msg = f"Row #{d.idx}: Please select Batch No. for item {bold(d.item_code)}" if error_msg: diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py index 1fca0495098..f210a6434cf 100644 --- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py @@ -780,8 +780,6 @@ class TestPOSInvoice(unittest.TestCase): pos_inv1.submit() pos_inv1.reload() - self.assertFalse(pos_inv1.items[0].serial_and_batch_bundle) - batches = get_auto_batch_nos( frappe._dict({"item_code": "_BATCH ITEM Test For Reserve", "warehouse": "_Test Warehouse - _TC"}) ) @@ -957,7 +955,7 @@ def create_pos_invoice(**args): pos_inv.set_missing_values() bundle_id = None - if args.get("batch_no") or args.get("serial_no"): + if not args.use_serial_batch_fields and (args.get("batch_no") or args.get("serial_no")): type_of_transaction = args.type_of_transaction or "Outward" if pos_inv.is_return: @@ -998,6 +996,9 @@ def create_pos_invoice(**args): "expense_account": args.expense_account or "Cost of Goods Sold - _TC", "cost_center": args.cost_center or "_Test Cost Center - _TC", "serial_and_batch_bundle": bundle_id, + "use_serial_batch_fields": args.use_serial_batch_fields, + "serial_no": args.serial_no if args.use_serial_batch_fields else None, + "batch_no": args.batch_no if args.use_serial_batch_fields else None, } # append in pos invoice items without item_code by checking flag without_item_code if args.without_item_code: @@ -1023,6 +1024,8 @@ def create_pos_invoice(**args): pos_inv.insert() if not args.do_not_submit: pos_inv.submit() + if args.use_serial_batch_fields: + pos_inv.reload() else: pos_inv.payment_schedule = [] else: diff --git a/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json index b92579eb799..828fc30db6e 100644 --- a/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json +++ b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json @@ -634,7 +634,6 @@ "depends_on": "eval:doc.use_serial_batch_fields === 1", "fieldname": "batch_no", "fieldtype": "Link", - "hidden": 1, "label": "Batch No", "options": "Batch", "print_hide": 1 @@ -655,7 +654,6 @@ "depends_on": "eval:doc.use_serial_batch_fields === 1", "fieldname": "serial_no", "fieldtype": "Text", - "hidden": 1, "in_list_view": 1, "label": "Serial No", "oldfieldname": "serial_no", @@ -827,7 +825,7 @@ "read_only": 1 }, { - "depends_on": "eval:doc.use_serial_batch_fields === 1", + "depends_on": "eval:doc.use_serial_batch_fields === 0 || doc.serial_and_batch_bundle", "fieldname": "serial_and_batch_bundle", "fieldtype": "Link", "label": "Serial and Batch Bundle", @@ -853,7 +851,7 @@ ], "istable": 1, "links": [], - "modified": "2024-02-25 15:50:17.140269", + "modified": "2024-05-07 15:56:53.343317", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice Item", @@ -863,4 +861,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py index e8f94b880e2..2cf204dd347 100644 --- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py +++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py @@ -131,6 +131,7 @@ class POSInvoiceMergeLog(Document): pos_invoice_docs = [frappe.get_cached_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices] self.update_pos_invoices(pos_invoice_docs) + self.serial_and_batch_bundle_reference_for_pos_invoice() self.cancel_linked_invoices() def process_merging_into_sales_invoice(self, data): @@ -191,6 +192,7 @@ class POSInvoiceMergeLog(Document): for i in items: if ( i.item_code == item.item_code + and not i.serial_and_batch_bundle and not i.serial_no and not i.batch_no and i.uom == item.uom @@ -312,6 +314,12 @@ class POSInvoiceMergeLog(Document): doc.set_status(update=True) doc.save() + def serial_and_batch_bundle_reference_for_pos_invoice(self): + for d in self.pos_invoices: + pos_invoice = frappe.get_doc("POS Invoice", d.pos_invoice) + for table_name in ["items", "packed_items"]: + pos_invoice.set_serial_and_batch_bundle(table_name) + def cancel_linked_invoices(self): for si_name in [self.consolidated_invoice, self.consolidated_credit_note]: if not si_name: diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js index 864ceffa8b1..000a79b70a0 100644 --- a/erpnext/selling/page/point_of_sale/pos_controller.js +++ b/erpnext/selling/page/point_of_sale/pos_controller.js @@ -583,6 +583,7 @@ erpnext.PointOfSale.Controller = class { new_item["serial_no"] = serial_no; } + new_item["use_serial_batch_fields"] = 1; if (field === "serial_no") new_item["qty"] = value.split(`\n`).length || 0; item_row = this.frm.add_child("items", new_item); diff --git a/erpnext/selling/page/point_of_sale/pos_item_details.js b/erpnext/selling/page/point_of_sale/pos_item_details.js index f89b70ef45b..4673eaa9858 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_details.js +++ b/erpnext/selling/page/point_of_sale/pos_item_details.js @@ -101,7 +101,8 @@ erpnext.PointOfSale.ItemDetails = class { const serialized = item_row.has_serial_no; const batched = item_row.has_batch_no; - const no_bundle_selected = !item_row.serial_and_batch_bundle; + const no_bundle_selected = + !item_row.serial_and_batch_bundle && !item_row.serial_no && !item_row.batch_no; if ((serialized && no_bundle_selected) || (batched && no_bundle_selected)) { frappe.show_alert({ @@ -403,6 +404,7 @@ erpnext.PointOfSale.ItemDetails = class { frappe.model.set_value(item_row.doctype, item_row.name, { serial_and_batch_bundle: r.name, qty: Math.abs(r.total_qty), + use_serial_batch_fields: 0, }); } }); diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 3ada8f0bbcd..9b65e11f430 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -935,6 +935,9 @@ class SerialandBatchBundle(Document): self.validate_voucher_no_docstatus() def validate_voucher_no_docstatus(self): + if self.voucher_type == "POS Invoice": + return + if frappe.db.get_value(self.voucher_type, self.voucher_no, "docstatus") == 1: msg = f"""The {self.voucher_type} {bold(self.voucher_no)} is in submitted state, please cancel it first""" @@ -1722,6 +1725,7 @@ def get_reserved_batches_for_pos(kwargs) -> dict: "`tabPOS Invoice Item`.warehouse", "`tabPOS Invoice Item`.name as child_docname", "`tabPOS Invoice`.name as parent_docname", + "`tabPOS Invoice Item`.use_serial_batch_fields", "`tabPOS Invoice Item`.serial_and_batch_bundle", ], filters=[ @@ -1735,7 +1739,7 @@ def get_reserved_batches_for_pos(kwargs) -> dict: ids = [ pos_invoice.serial_and_batch_bundle for pos_invoice in pos_invoices - if pos_invoice.serial_and_batch_bundle + if pos_invoice.serial_and_batch_bundle and not pos_invoice.use_serial_batch_fields ] if ids: diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 2207b2e3c74..4880adab921 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -246,6 +246,9 @@ class SerialBatchBundle: frappe.throw(_(msg)) def delink_serial_and_batch_bundle(self): + if self.is_pos_transaction(): + return + update_values = { "serial_and_batch_bundle": "", } @@ -295,8 +298,22 @@ class SerialBatchBundle: self.cancel_serial_and_batch_bundle() def cancel_serial_and_batch_bundle(self): + if self.is_pos_transaction(): + return + frappe.get_cached_doc("Serial and Batch Bundle", self.sle.serial_and_batch_bundle).cancel() + def is_pos_transaction(self): + if ( + self.sle.voucher_type == "Sales Invoice" + and self.sle.serial_and_batch_bundle + and frappe.get_cached_value( + "Serial and Batch Bundle", self.sle.serial_and_batch_bundle, "voucher_type" + ) + == "POS Invoice" + ): + return True + def submit_serial_and_batch_bundle(self): doc = frappe.get_doc("Serial and Batch Bundle", self.sle.serial_and_batch_bundle) self.validate_actual_qty(doc) From 926fd41a2b4b5b08883383f9dbe5e3df701b0e04 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:06:56 +0530 Subject: [PATCH 16/18] fix: qty in the 'Serial No Ledger' report (backport #42429) (#42433) fix: qty in the 'Serial No Ledger' report (#42429) (cherry picked from commit be2648245b4d3f980f14506af187797a16ec80e6) Co-authored-by: rohitwaghchaure --- erpnext/stock/report/serial_no_ledger/serial_no_ledger.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py b/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py index 894a740c177..c927f3d6d9e 100644 --- a/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py +++ b/erpnext/stock/report/serial_no_ledger/serial_no_ledger.py @@ -157,6 +157,7 @@ def get_data(filters): { "serial_no": bundle_data.get("serial_no"), "valuation_rate": bundle_data.get("valuation_rate"), + "qty": args.qty, } ) From 72bc539ffdca0594d2175ba967c1285b691c74ac Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Sat, 20 Jul 2024 00:44:31 +0200 Subject: [PATCH 17/18] fix: provide initial value for `.reduce()` call Fixes the error "TypeError: Reduce of empty array with no initial value" (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Reduce_of_empty_array_with_no_initial_value#invalid_cases) (cherry picked from commit 65f80abf2fef35f355e66c89cbfb10be2aafb59f) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 1df21b7ebc4..797d00fe3ec 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -157,7 +157,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends ( const payment_is_overdue = doc.payment_schedule .map((row) => Date.parse(row.due_date) < Date.now()) - .reduce((prev, current) => prev || current); + .reduce((prev, current) => prev || current, false); if (payment_is_overdue) { this.frm.add_custom_button( From ffacf4222b0401f19a3986ff9d29d513084a6e32 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Wed, 17 Jul 2024 19:19:31 +0530 Subject: [PATCH 18/18] fix: correct validation for depreciation posting date (cherry picked from commit da4ed90a3e2af9831b93e55607449e173241b604) --- erpnext/assets/doctype/asset/asset.js | 7 ++----- erpnext/assets/doctype/asset/asset.py | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index c05adf6bb86..f8fafd133ba 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -775,11 +775,8 @@ frappe.ui.form.on("Asset Finance Book", { depreciation_start_date: function (frm, cdt, cdn) { const book = locals[cdt][cdn]; - if ( - frm.doc.available_for_use_date && - book.depreciation_start_date == frm.doc.available_for_use_date - ) { - frappe.msgprint(__("Depreciation Posting Date should not be equal to Available for Use Date.")); + if (frm.doc.available_for_use_date && book.depreciation_start_date < frm.doc.available_for_use_date) { + frappe.msgprint(__("Depreciation Posting Date cannot be before Available-for-use Date")); book.depreciation_start_date = ""; frm.refresh_field("finance_books"); } diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index e69fb728520..bc10ca80e8b 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -267,10 +267,10 @@ class Asset(AccountsController): frappe.throw(_("Available for use date is required")) for d in self.finance_books: - if d.depreciation_start_date == self.available_for_use_date: + if getdate(d.depreciation_start_date) < getdate(self.available_for_use_date): frappe.throw( _( - "Row #{}: Depreciation Posting Date should not be equal to Available for Use Date." + "Depreciation Row {0}: Depreciation Posting Date cannot be before Available-for-use Date" ).format(d.idx), title=_("Incorrect Date"), )