From 0bc3bc48518cf99c104562e8aeeb89e1cefc26c3 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Wed, 23 Apr 2025 12:30:59 +0530 Subject: [PATCH 1/4] fix: calculate useful days of asset's life correctly for existing asset (#47066) * fix: calculate useful days of asset's life correctly for existing asset * fix: test * fix: test case correction --- erpnext/assets/doctype/asset/asset.py | 66 +++++++++++++++------- erpnext/assets/doctype/asset/test_asset.py | 2 +- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 41df6361fad..9ad41be1254 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -635,38 +635,44 @@ class Asset(AccountsController): return add_days(self.available_for_use_date, -1) # if it returns True, depreciation_amount will not be equal for the first and last rows - def check_is_pro_rata(self, row, wdv_or_dd_non_yearly=False): + def check_is_pro_rata(asset_doc, row, wdv_or_dd_non_yearly=False): has_pro_rata = False # if not existing asset, from_date = available_for_use_date # otherwise, if number_of_depreciations_booked = 2, available_for_use_date = 01/01/2020 and frequency_of_depreciation = 12 # from_date = 01/01/2022 - from_date = self.get_modified_available_for_use_date(row, wdv_or_dd_non_yearly) - days = date_diff(row.depreciation_start_date, from_date) + 1 - - if wdv_or_dd_non_yearly: - total_days = get_total_days(row.depreciation_start_date, 12) + if row.depreciation_method in ("Straight Line", "Manual"): + prev_depreciation_start_date = get_last_day( + add_months( + row.depreciation_start_date, + (row.frequency_of_depreciation * -1) * asset_doc.number_of_depreciations_booked, + ) + ) + from_date = asset_doc.available_for_use_date + days = date_diff(prev_depreciation_start_date, from_date) + 1 + total_days = get_total_days(prev_depreciation_start_date, row.frequency_of_depreciation) else: - # if frequency_of_depreciation is 12 months, total_days = 365 + from_date = _get_modified_available_for_use_date(asset_doc, row, wdv_or_dd_non_yearly=False) + days = date_diff(row.depreciation_start_date, from_date) + 1 total_days = get_total_days(row.depreciation_start_date, row.frequency_of_depreciation) + if days <= 0: + frappe.throw( + _( + """Error: This asset already has {0} depreciation periods booked. + The `depreciation start` date must be at least {1} periods after the `available for use` date. + Please correct the dates accordingly.""" + ).format( + asset_doc.number_of_depreciations_booked, + asset_doc.number_of_depreciations_booked, + ) + ) + if days < total_days: has_pro_rata = True return has_pro_rata - def get_modified_available_for_use_date(self, row, wdv_or_dd_non_yearly=False): - if wdv_or_dd_non_yearly: - return add_months( - self.available_for_use_date, - (self.number_of_depreciations_booked * 12), - ) - else: - return add_months( - self.available_for_use_date, - (self.number_of_depreciations_booked * row.frequency_of_depreciation), - ) - def validate_asset_finance_books(self, row): if flt(row.expected_value_after_useful_life) >= flt(self.gross_purchase_amount): frappe.throw( @@ -1290,6 +1296,28 @@ def get_item_details(item_code, asset_category, gross_purchase_amount): return books +def _get_modified_available_for_use_date(asset_doc, row, wdv_or_dd_non_yearly=False): + """ + if Asset has opening booked depreciations = 9, + available for use date = 17-07-2023, + depreciation start date = 30-04-2024 + then from date should be 01-04-2024 + """ + if asset_doc.number_of_depreciations_booked > 0: + from_date = add_months( + asset_doc.available_for_use_date, + (asset_doc.number_of_depreciations_booked * row.frequency_of_depreciation) - 1, + ) + if is_last_day_of_the_month(row.depreciation_start_date): + return add_days(get_last_day(from_date), 1) + + # get from date when depreciation start date is not last day of the month + months_difference = month_diff(row.depreciation_start_date, from_date) - 1 + return add_days(add_months(row.depreciation_start_date, -1 * months_difference), 1) + else: + return asset_doc.available_for_use_date + + def get_asset_account(account_name, asset=None, asset_category=None, company=None): account = None if asset: diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 7007f212827..b89027578c5 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -1451,7 +1451,7 @@ class TestDepreciationBasics(AssetSetup): affects `value_after_depreciation` """ - asset = create_asset(calculate_depreciation=1) + asset = create_asset(calculate_depreciation=1, depreciation_start_date="2021-12-31") asset.opening_accumulated_depreciation = 2000 asset.number_of_depreciations_booked = 1 From 48748e71421e6cbd75912ed6551bf458da222ac5 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 25 Apr 2025 14:08:38 +0530 Subject: [PATCH 2/4] fix: item code not showing in the error message --- erpnext/stock/stock_ledger.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 58c2fb51339..2180cb8681e 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -1189,16 +1189,16 @@ class update_entries_after: ) in frappe.local.flags.currently_saving: msg = _("{0} units of {1} needed in {2} to complete this transaction.").format( abs(deficiency), - frappe.get_desk_link("Item", exceptions[0]["item_code"]), - frappe.get_desk_link("Warehouse", warehouse), + frappe.get_desk_link("Item", exceptions[0]["item_code"], show_title_with_name=True), + frappe.get_desk_link("Warehouse", warehouse, show_title_with_name=True), ) else: msg = _( "{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction." ).format( abs(deficiency), - frappe.get_desk_link("Item", exceptions[0]["item_code"]), - frappe.get_desk_link("Warehouse", warehouse), + frappe.get_desk_link("Item", exceptions[0]["item_code"], show_title_with_name=True), + frappe.get_desk_link("Warehouse", warehouse, show_title_with_name=True), exceptions[0]["posting_date"], exceptions[0]["posting_time"], frappe.get_desk_link(exceptions[0]["voucher_type"], exceptions[0]["voucher_no"]), @@ -1659,8 +1659,8 @@ def validate_negative_qty_in_future_sle(args, allow_negative_stock=False): if is_negative_with_precision(neg_sle): message = _("{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction.").format( abs(neg_sle[0]["qty_after_transaction"]), - frappe.get_desk_link("Item", args.item_code), - frappe.get_desk_link("Warehouse", args.warehouse), + frappe.get_desk_link("Item", args.item_code, show_title_with_name=True), + frappe.get_desk_link("Warehouse", args.warehouse, show_title_with_name=True), neg_sle[0]["posting_date"], neg_sle[0]["posting_time"], frappe.get_desk_link(neg_sle[0]["voucher_type"], neg_sle[0]["voucher_no"]), From 7130e5ccfb8c3dc121573aa27357a2c3a8d2838a Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sat, 26 Apr 2025 16:31:37 +0530 Subject: [PATCH 3/4] fix: allow to change valuation method from FIFO to Moving Average (cherry picked from commit b454ed4b8f7f4c549a6590ad93b4842bc3a5bda7) --- erpnext/stock/doctype/item/item.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 3543e42e217..3728e030542 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -916,6 +916,11 @@ class Item(Document): changed_fields = [ field for field in restricted_fields if cstr(self.get(field)) != cstr(values.get(field)) ] + + # Allow to change valuation method from FIFO to Moving Average not vice versa + if self.valuation_method == "Moving Average" and "valuation_method" in changed_fields: + changed_fields.remove("valuation_method") + if not changed_fields: return From 0c5c34409e82e9f290e3f7a4788b01144394fd46 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 29 Apr 2025 12:40:25 +0530 Subject: [PATCH 4/4] fix: remove invalid email account creation (backport #47318) (#47322) fix: remove invalid email account creation (#47318) (cherry picked from commit 7423e4187fd8bb43c1adda9ce4468c51d16df5b5) Co-authored-by: Diptanil Saha --- erpnext/setup/setup_wizard/operations/install_fixtures.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py index 0fe2b56a944..87152cae42f 100644 --- a/erpnext/setup/setup_wizard/operations/install_fixtures.py +++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py @@ -241,8 +241,6 @@ def install(country=None): {"doctype": "Issue Priority", "name": _("Low")}, {"doctype": "Issue Priority", "name": _("Medium")}, {"doctype": "Issue Priority", "name": _("High")}, - {"doctype": "Email Account", "email_id": "sales@example.com", "append_to": "Opportunity"}, - {"doctype": "Email Account", "email_id": "support@example.com", "append_to": "Issue"}, {"doctype": "Party Type", "party_type": "Customer", "account_type": "Receivable"}, {"doctype": "Party Type", "party_type": "Supplier", "account_type": "Payable"}, {"doctype": "Party Type", "party_type": "Employee", "account_type": "Payable"},