From ff5cad1cd617a23d6ffc9903f29d713a8db8d949 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 15 Sep 2022 13:15:34 +0530 Subject: [PATCH 01/54] fix: calculate depreciation properly on asset sale entry and scrap entry --- .../doctype/sales_invoice/sales_invoice.py | 15 ++-- erpnext/assets/doctype/asset/depreciation.py | 89 ++++++++++++++++++- erpnext/controllers/accounts_controller.py | 83 ----------------- 3 files changed, 97 insertions(+), 90 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 608f0828fe..4207156187 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -22,9 +22,12 @@ from erpnext.accounts.general_ledger import get_round_off_account_and_cost_cente from erpnext.accounts.party import get_due_date, get_party_account, get_party_details from erpnext.accounts.utils import get_account_currency from erpnext.assets.doctype.asset.depreciation import ( + depreciate_asset, get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal, get_gl_entries_on_asset_regain, + reset_depreciation_schedule, + reverse_depreciation_entry_made_after_disposal, ) from erpnext.controllers.accounts_controller import validate_account_head from erpnext.controllers.selling_controller import SellingController @@ -1086,18 +1089,20 @@ class SalesInvoice(SellingController): asset.db_set("disposal_date", None) if asset.calculate_depreciation: - self.reverse_depreciation_entry_made_after_disposal(asset) - self.reset_depreciation_schedule(asset) + posting_date = frappe.db.get_value("Sales Invoice", self.return_against, "posting_date") + reverse_depreciation_entry_made_after_disposal(asset, posting_date) + reset_depreciation_schedule(asset, self.posting_date) else: + if asset.calculate_depreciation: + depreciate_asset(asset, self.posting_date) + asset.reload() + fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( asset, item.base_net_amount, item.finance_book ) asset.db_set("disposal_date", self.posting_date) - if asset.calculate_depreciation: - self.depreciate_asset(asset) - for gle in fixed_asset_gl_entries: gle["against"] = self.customer gl_entries.append(self.get_gl_dict(gle, item=item)) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 74386384c5..0299e28c11 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -4,11 +4,12 @@ import frappe from frappe import _ -from frappe.utils import cint, flt, getdate, today +from frappe.utils import add_months, cint, flt, getdate, nowdate, today from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( get_checks_for_pl_and_bs_accounts, ) +from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry def post_depreciation_entries(date=None, commit=True): @@ -196,6 +197,11 @@ def scrap_asset(asset_name): _("Asset {0} cannot be scrapped, as it is already {1}").format(asset.name, asset.status) ) + date = today() + + depreciate_asset(asset, date) + asset.reload() + depreciation_series = frappe.get_cached_value( "Company", asset.company, "series_for_depreciation_entry" ) @@ -203,7 +209,7 @@ def scrap_asset(asset_name): je = frappe.new_doc("Journal Entry") je.voucher_type = "Journal Entry" je.naming_series = depreciation_series - je.posting_date = today() + je.posting_date = date je.company = asset.company je.remark = "Scrap Entry for asset {0}".format(asset_name) @@ -225,6 +231,9 @@ def scrap_asset(asset_name): def restore_asset(asset_name): asset = frappe.get_doc("Asset", asset_name) + reverse_depreciation_entry_made_after_disposal(asset, asset.disposal_date) + reset_depreciation_schedule(asset, asset.disposal_date) + je = asset.journal_entry_for_scrap asset.db_set("disposal_date", None) @@ -235,6 +244,82 @@ def restore_asset(asset_name): asset.set_status() +def depreciate_asset(asset, date): + asset.flags.ignore_validate_update_after_submit = True + asset.prepare_depreciation_data(date_of_disposal=date) + asset.save() + + make_depreciation_entry(asset.name, date) + + +def reset_depreciation_schedule(asset, date): + asset.flags.ignore_validate_update_after_submit = True + + # recreate original depreciation schedule of the asset + asset.prepare_depreciation_data(date_of_return=date) + + modify_depreciation_schedule_for_asset_repairs(asset) + asset.save() + + +def modify_depreciation_schedule_for_asset_repairs(asset): + asset_repairs = frappe.get_all( + "Asset Repair", filters={"asset": asset.name}, fields=["name", "increase_in_asset_life"] + ) + + for repair in asset_repairs: + if repair.increase_in_asset_life: + asset_repair = frappe.get_doc("Asset Repair", repair.name) + asset_repair.modify_depreciation_schedule() + asset.prepare_depreciation_data() + + +def reverse_depreciation_entry_made_after_disposal(asset, date): + row = -1 + finance_book = asset.get("schedules")[0].get("finance_book") + for schedule in asset.get("schedules"): + if schedule.finance_book != finance_book: + row = 0 + finance_book = schedule.finance_book + else: + row += 1 + + if schedule.schedule_date == date: + if not disposal_was_made_on_original_schedule_date( + asset, schedule, row, date + ) or disposal_happens_in_the_future(date): + + reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) + reverse_journal_entry.posting_date = nowdate() + frappe.flags.is_reverse_depr_entry = True + reverse_journal_entry.submit() + + frappe.flags.is_reverse_depr_entry = False + asset.flags.ignore_validate_update_after_submit = True + schedule.journal_entry = None + asset.save() + + +# if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone +def disposal_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_disposal): + for finance_book in asset.get("finance_books"): + if schedule.finance_book == finance_book.finance_book: + orginal_schedule_date = add_months( + finance_book.depreciation_start_date, row * cint(finance_book.frequency_of_depreciation) + ) + + if orginal_schedule_date == posting_date_of_disposal: + return True + return False + + +def disposal_happens_in_the_future(posting_date_of_disposal): + if posting_date_of_disposal > getdate(): + return True + + return False + + def get_gl_entries_on_asset_regain(asset, selling_amount=0, finance_book=None): ( fixed_asset_account, diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 938de63f33..e9d3c7afba 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -38,7 +38,6 @@ from erpnext.accounts.party import ( validate_party_frozen_disabled, ) from erpnext.accounts.utils import get_account_currency, get_fiscal_years, validate_fiscal_year -from erpnext.assets.doctype.asset.depreciation import make_depreciation_entry from erpnext.buying.utils import update_last_purchase_rate from erpnext.controllers.print_settings import ( set_print_templates_for_item_table, @@ -1886,88 +1885,6 @@ class AccountsController(TransactionBase): _("Select finance book for the item {0} at row {1}").format(item.item_code, item.idx) ) - def depreciate_asset(self, asset): - asset.flags.ignore_validate_update_after_submit = True - asset.prepare_depreciation_data(date_of_disposal=self.posting_date) - asset.save() - - make_depreciation_entry(asset.name, self.posting_date) - - def reset_depreciation_schedule(self, asset): - asset.flags.ignore_validate_update_after_submit = True - - # recreate original depreciation schedule of the asset - asset.prepare_depreciation_data(date_of_return=self.posting_date) - - self.modify_depreciation_schedule_for_asset_repairs(asset) - asset.save() - - def modify_depreciation_schedule_for_asset_repairs(self, asset): - asset_repairs = frappe.get_all( - "Asset Repair", filters={"asset": asset.name}, fields=["name", "increase_in_asset_life"] - ) - - for repair in asset_repairs: - if repair.increase_in_asset_life: - asset_repair = frappe.get_doc("Asset Repair", repair.name) - asset_repair.modify_depreciation_schedule() - asset.prepare_depreciation_data() - - def reverse_depreciation_entry_made_after_disposal(self, asset): - from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry - - posting_date_of_original_disposal = self.get_posting_date_of_disposal_entry() - - row = -1 - finance_book = asset.get("schedules")[0].get("finance_book") - for schedule in asset.get("schedules"): - if schedule.finance_book != finance_book: - row = 0 - finance_book = schedule.finance_book - else: - row += 1 - - if schedule.schedule_date == posting_date_of_original_disposal: - if not self.disposal_was_made_on_original_schedule_date( - asset, schedule, row, posting_date_of_original_disposal - ) or self.disposal_happens_in_the_future(posting_date_of_original_disposal): - - reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) - reverse_journal_entry.posting_date = nowdate() - frappe.flags.is_reverse_depr_entry = True - reverse_journal_entry.submit() - - frappe.flags.is_reverse_depr_entry = False - asset.flags.ignore_validate_update_after_submit = True - schedule.journal_entry = None - asset.save() - - def get_posting_date_of_disposal_entry(self): - if self.doctype == "Sales Invoice" and self.return_against: - return frappe.db.get_value("Sales Invoice", self.return_against, "posting_date") - else: - return self.posting_date - - # if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone - def disposal_was_made_on_original_schedule_date( - self, asset, schedule, row, posting_date_of_disposal - ): - for finance_book in asset.get("finance_books"): - if schedule.finance_book == finance_book.finance_book: - orginal_schedule_date = add_months( - finance_book.depreciation_start_date, row * cint(finance_book.frequency_of_depreciation) - ) - - if orginal_schedule_date == posting_date_of_disposal: - return True - return False - - def disposal_happens_in_the_future(self, posting_date_of_disposal): - if posting_date_of_disposal > getdate(): - return True - - return False - @frappe.whitelist() def get_tax_rate(account_head): From 11ac20e5ee1f9ba00bbccd15388144dc4b4eea83 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 15 Sep 2022 22:43:18 +0530 Subject: [PATCH 02/54] fix: asset tests --- erpnext/assets/doctype/asset/depreciation.py | 2 +- erpnext/assets/doctype/asset/test_asset.py | 52 ++++++++++++++------ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 0299e28c11..9f378407f6 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -220,7 +220,7 @@ def scrap_asset(asset_name): je.flags.ignore_permissions = True je.submit() - frappe.db.set_value("Asset", asset_name, "disposal_date", today()) + frappe.db.set_value("Asset", asset_name, "disposal_date", date) frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name) asset.set_status("Scrapped") diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index e7af9bd5bc..bdda509e91 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -4,7 +4,16 @@ import unittest import frappe -from frappe.utils import add_days, add_months, cstr, flt, get_last_day, getdate, nowdate +from frappe.utils import ( + add_days, + add_months, + cstr, + flt, + get_first_day, + get_last_day, + getdate, + nowdate, +) from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice from erpnext.assets.doctype.asset.asset import make_sales_invoice, split_asset @@ -178,17 +187,20 @@ class TestAsset(AssetSetup): self.assertEqual(doc.items[0].is_fixed_asset, 1) def test_scrap_asset(self): + date = nowdate() + purchase_date = add_months(get_first_day(date), -2) + asset = create_asset( calculate_depreciation=1, - available_for_use_date="2020-01-01", - purchase_date="2020-01-01", + available_for_use_date=purchase_date, + purchase_date=purchase_date, expected_value_after_useful_life=10000, total_number_of_depreciations=10, frequency_of_depreciation=1, submit=1, ) - post_depreciation_entries(date=add_months("2020-01-01", 4)) + post_depreciation_entries(date=add_months(purchase_date, 2)) scrap_asset(asset.name) @@ -196,10 +208,15 @@ class TestAsset(AssetSetup): self.assertEqual(asset.status, "Scrapped") self.assertTrue(asset.journal_entry_for_scrap) + pro_rata_amount, _, _ = asset.get_pro_rata_amt( + asset.finance_books[0], 9000, add_months(get_last_day(purchase_date), 1), date + ) + pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount")) + expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 36000.0, 0.0), + ("_Test Accumulated Depreciations - _TC", 18000.0 + pro_rata_amount, 0.0), ("_Test Fixed Asset - _TC", 0.0, 100000.0), - ("_Test Gain/Loss on Asset Disposal - _TC", 64000.0, 0.0), + ("_Test Gain/Loss on Asset Disposal - _TC", 82000.0 - pro_rata_amount, 0.0), ) gle = frappe.db.sql( @@ -217,18 +234,20 @@ class TestAsset(AssetSetup): self.assertEqual(asset.status, "Partially Depreciated") def test_gle_made_by_asset_sale(self): + date = nowdate() + purchase_date = add_months(get_first_day(date), -2) + asset = create_asset( calculate_depreciation=1, - available_for_use_date="2020-06-06", - purchase_date="2020-01-01", + available_for_use_date=purchase_date, + purchase_date=purchase_date, expected_value_after_useful_life=10000, - total_number_of_depreciations=3, - frequency_of_depreciation=10, - depreciation_start_date="2020-12-31", + total_number_of_depreciations=10, + frequency_of_depreciation=1, submit=1, ) - post_depreciation_entries(date="2021-01-01") + post_depreciation_entries(date=add_months(purchase_date, 2)) si = make_sales_invoice(asset=asset.name, item_code="Macbook Pro", company="_Test Company") si.customer = "_Test Customer" @@ -239,10 +258,15 @@ class TestAsset(AssetSetup): self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold") + pro_rata_amount, _, _ = asset.get_pro_rata_amt( + asset.finance_books[0], 9000, add_months(get_last_day(purchase_date), 1), date + ) + pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount")) + expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 20490.2, 0.0), + ("_Test Accumulated Depreciations - _TC", 18000.0 + pro_rata_amount, 0.0), ("_Test Fixed Asset - _TC", 0.0, 100000.0), - ("_Test Gain/Loss on Asset Disposal - _TC", 54509.8, 0.0), + ("_Test Gain/Loss on Asset Disposal - _TC", 57000.0 - pro_rata_amount, 0.0), ("Debtors - _TC", 25000.0, 0.0), ) From 5a8b28c1943d24b7aedf7b96c57fe93d2b5ea5f6 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 15 Sep 2022 22:52:25 +0530 Subject: [PATCH 03/54] fix: refactor asset capitilization --- .../doctype/asset_capitalization/asset_capitalization.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 2e6f0ad7b0..30ff0601e4 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -12,8 +12,11 @@ from six import string_types import erpnext from erpnext.assets.doctype.asset.depreciation import ( + depreciate_asset, get_gl_entries_on_asset_disposal, get_value_after_depreciation_on_disposal_date, + reset_depreciation_schedule, + reverse_depreciation_entry_made_after_disposal, ) from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import ( @@ -424,7 +427,7 @@ class AssetCapitalization(StockController): asset = self.get_asset(item) if asset.calculate_depreciation: - self.depreciate_asset(asset) + depreciate_asset(asset, self.posting_date) asset.reload() fixed_asset_gl_entries = get_gl_entries_on_asset_disposal( @@ -516,8 +519,8 @@ class AssetCapitalization(StockController): self.set_consumed_asset_status(asset) if asset.calculate_depreciation: - self.reverse_depreciation_entry_made_after_disposal(asset) - self.reset_depreciation_schedule(asset) + reverse_depreciation_entry_made_after_disposal(asset, self.posting_date) + reset_depreciation_schedule(asset, self.posting_date) def get_asset(self, item): asset = frappe.get_doc("Asset", item.asset) From 43a3400221118cb6ad86c6ef15e201d07bc1941e Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Thu, 15 Sep 2022 23:25:04 +0530 Subject: [PATCH 04/54] fix: fix restore asset value after depreciation --- erpnext/assets/doctype/asset/depreciation.py | 9 ++++++++ erpnext/assets/doctype/asset/test_asset.py | 24 +++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 9f378407f6..e4765634c8 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -297,9 +297,18 @@ def reverse_depreciation_entry_made_after_disposal(asset, date): frappe.flags.is_reverse_depr_entry = False asset.flags.ignore_validate_update_after_submit = True schedule.journal_entry = None + depreciation_amount = get_depreciation_amount_in_je(reverse_journal_entry) + asset.finance_books[0].value_after_depreciation += depreciation_amount asset.save() +def get_depreciation_amount_in_je(journal_entry): + if journal_entry.accounts[0].debit_in_account_currency: + return journal_entry.accounts[0].debit_in_account_currency + else: + return journal_entry.accounts[0].credit_in_account_currency + + # if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone def disposal_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_disposal): for finance_book in asset.get("finance_books"): diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index bdda509e91..f72b5249a4 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -201,17 +201,29 @@ class TestAsset(AssetSetup): ) post_depreciation_entries(date=add_months(purchase_date, 2)) + asset.load_from_db() + + accumulated_depr_amount = flt( + asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation, + asset.precision("gross_purchase_amount"), + ) + self.assertEquals(accumulated_depr_amount, 18000.0) scrap_asset(asset.name) - asset.load_from_db() - self.assertEqual(asset.status, "Scrapped") - self.assertTrue(asset.journal_entry_for_scrap) + accumulated_depr_amount = flt( + asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation, + asset.precision("gross_purchase_amount"), + ) pro_rata_amount, _, _ = asset.get_pro_rata_amt( asset.finance_books[0], 9000, add_months(get_last_day(purchase_date), 1), date ) pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount")) + self.assertEquals(accumulated_depr_amount, 18000.00 + pro_rata_amount) + + self.assertEqual(asset.status, "Scrapped") + self.assertTrue(asset.journal_entry_for_scrap) expected_gle = ( ("_Test Accumulated Depreciations - _TC", 18000.0 + pro_rata_amount, 0.0), @@ -233,6 +245,12 @@ class TestAsset(AssetSetup): self.assertFalse(asset.journal_entry_for_scrap) self.assertEqual(asset.status, "Partially Depreciated") + accumulated_depr_amount = flt( + asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation, + asset.precision("gross_purchase_amount"), + ) + self.assertEquals(accumulated_depr_amount, 18000.0) + def test_gle_made_by_asset_sale(self): date = nowdate() purchase_date = add_months(get_first_day(date), -2) From e683cccf3520812b6f031ce780bf8575e5f6c8db Mon Sep 17 00:00:00 2001 From: Ernesto Ruiz Date: Mon, 26 Sep 2022 07:59:13 -0600 Subject: [PATCH 05/54] fix: add translate function to book appointment html --- erpnext/www/book_appointment/index.html | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/erpnext/www/book_appointment/index.html b/erpnext/www/book_appointment/index.html index 207175f89d..ad964d9370 100644 --- a/erpnext/www/book_appointment/index.html +++ b/erpnext/www/book_appointment/index.html @@ -12,8 +12,8 @@
-

Book an appointment

-

Select the date and your timezone

+

{{ _("Book an appointment") }}

+

{{ _("Select the date and your timezone") }}

@@ -31,7 +31,7 @@
- +
@@ -39,24 +39,24 @@
-

Add details

-

Selected date is at +

{{ _("Add details") }}

+

{{ _("Selected date is") }} {{ _("at") }}

- + - + + placeholder="{{ _('Notes') }}">
-
-
+
+
From 728ef46048d04b17a583c018d4201e868aa20605 Mon Sep 17 00:00:00 2001 From: Ernesto Ruiz Date: Mon, 26 Sep 2022 08:01:48 -0600 Subject: [PATCH 06/54] fix: add translate function to book appointment index.js --- erpnext/www/book_appointment/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/www/book_appointment/index.js b/erpnext/www/book_appointment/index.js index 5562cbd471..46ac15518c 100644 --- a/erpnext/www/book_appointment/index.js +++ b/erpnext/www/book_appointment/index.js @@ -69,7 +69,7 @@ function on_date_or_timezone_select() { window.selected_timezone = timezone.value; update_time_slots(date_picker.value, timezone.value); let lead_text = document.getElementById('lead-text'); - lead_text.innerHTML = "Select Time" + lead_text.innerHTML = __("Select Time") } async function get_time_slots(date, timezone) { @@ -89,7 +89,7 @@ async function update_time_slots(selected_date, selected_timezone) { clear_time_slots(); if (window.slots.length <= 0) { let message_div = document.createElement('p'); - message_div.innerHTML = "There are no slots available on this date"; + message_div.innerHTML = __("There are no slots available on this date"); timeslot_container.appendChild(message_div); return } @@ -128,7 +128,7 @@ function get_slot_layout(time) { let start_time_string = moment(time).tz(timezone).format("LT"); let end_time = moment(time).tz(timezone).add(window.appointment_settings.appointment_duration, 'minutes'); let end_time_string = end_time.format("LT"); - return `${start_time_string}
to ${end_time_string}`; + return `${start_time_string}
${__("to") } ${end_time_string}`; } function select_time() { @@ -227,9 +227,9 @@ async function submit() { }, callback: (response)=>{ if (response.message.status == "Unverified") { - frappe.show_alert("Please check your email to confirm the appointment") + frappe.show_alert(__("Please check your email to confirm the appointment")) } else { - frappe.show_alert("Appointment Created Successfully"); + frappe.show_alert(__("Appointment Created Successfully")); } setTimeout(()=>{ let redirect_url = "/"; @@ -239,7 +239,7 @@ async function submit() { window.location.href = redirect_url;},5000) }, error: (err)=>{ - frappe.show_alert("Something went wrong please try again"); + frappe.show_alert(__("Something went wrong please try again")); button.disabled = false; } }); From 499ce5139c16b7ac60eb7f062919a3298dca739a Mon Sep 17 00:00:00 2001 From: Ernesto Ruiz Date: Mon, 26 Sep 2022 08:04:14 -0600 Subject: [PATCH 07/54] fix: add translate function to book appointment verify html --- erpnext/www/book_appointment/verify/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/www/book_appointment/verify/index.html b/erpnext/www/book_appointment/verify/index.html index 9bcd3d202e..58c07e85cc 100644 --- a/erpnext/www/book_appointment/verify/index.html +++ b/erpnext/www/book_appointment/verify/index.html @@ -8,11 +8,11 @@ {% if success==True %}
- Your email has been verified and your appointment has been scheduled + {{ _("Your email has been verified and your appointment has been scheduled") }}
{% else %}
- Verification failed please check the link + {{ _("Verification failed please check the link") }}
{% endif %} {% endblock%} From 21095502b9fe0edfb4828a5b918c9375b81f1cc0 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 26 Sep 2022 17:41:30 +0530 Subject: [PATCH 08/54] chore: clean up purchase invoice and purchase invoice item 1. remove discount accounting related fields from purchase invoice and purchase invoice item 2. clean buying settings doctype --- .../purchase_invoice/purchase_invoice.json | 9 +-- .../purchase_invoice/purchase_invoice.py | 15 ----- .../purchase_invoice_item.json | 9 +-- .../buying_settings/buying_settings.json | 10 +-- .../buying_settings/buying_settings.py | 62 ------------------- 5 files changed, 3 insertions(+), 102 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 986fc038c6..3020e6dc6e 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -98,7 +98,6 @@ "section_break_44", "apply_discount_on", "base_discount_amount", - "additional_discount_account", "column_break_46", "additional_discount_percentage", "discount_amount", @@ -1387,12 +1386,6 @@ "print_hide": 1, "read_only": 1 }, - { - "fieldname": "additional_discount_account", - "fieldtype": "Link", - "label": "Additional Discount Account", - "options": "Account" - }, { "default": "0", "fieldname": "ignore_default_payment_terms_template", @@ -1445,7 +1438,7 @@ "idx": 204, "is_submittable": 1, "links": [], - "modified": "2022-09-13 23:39:54.525037", + "modified": "2022-09-27 11:07:55.766844", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index d185300289..2b633cb8c3 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -669,9 +669,6 @@ class PurchaseInvoice(BuyingController): exchange_rate_map, net_rate_map = get_purchase_document_details(self) - enable_discount_accounting = cint( - frappe.db.get_single_value("Buying Settings", "enable_discount_accounting") - ) provisional_accounting_for_non_stock_items = cint( frappe.db.get_value( "Company", self.company, "enable_provisional_accounting_for_non_stock_items" @@ -1159,9 +1156,6 @@ class PurchaseInvoice(BuyingController): def make_tax_gl_entries(self, gl_entries): # tax table gl entries valuation_tax = {} - enable_discount_accounting = cint( - frappe.db.get_single_value("Buying Settings", "enable_discount_accounting") - ) for tax in self.get("taxes"): amount, base_amount = self.get_tax_amounts(tax, None) @@ -1249,15 +1243,6 @@ class PurchaseInvoice(BuyingController): ) ) - @property - def enable_discount_accounting(self): - if not hasattr(self, "_enable_discount_accounting"): - self._enable_discount_accounting = cint( - frappe.db.get_single_value("Buying Settings", "enable_discount_accounting") - ) - - return self._enable_discount_accounting - def make_internal_transfer_gl_entries(self, gl_entries): if self.is_internal_transfer() and flt(self.base_total_taxes_and_charges): account_currency = get_account_currency(self.unrealized_profit_loss_account) diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 7fa2fe2a66..fca7e3a887 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -74,7 +74,6 @@ "manufacturer_part_no", "accounting", "expense_account", - "discount_account", "col_break5", "is_fixed_asset", "asset_location", @@ -860,12 +859,6 @@ "print_hide": 1, "read_only": 1 }, - { - "fieldname": "discount_account", - "fieldtype": "Link", - "label": "Discount Account", - "options": "Account" - }, { "fieldname": "product_bundle", "fieldtype": "Link", @@ -877,7 +870,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2022-06-17 05:31:10.520171", + "modified": "2022-09-27 10:54:23.980713", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index aad26075f2..28158a31b9 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -20,7 +20,6 @@ "maintain_same_rate", "allow_multiple_items", "bill_for_rejected_quantity_in_purchase_invoice", - "enable_discount_accounting", "subcontract", "backflush_raw_materials_of_subcontract_based_on", "column_break_11", @@ -134,13 +133,6 @@ { "fieldname": "column_break_12", "fieldtype": "Column Break" - }, - { - "default": "0", - "description": "If enabled, additional ledger entries will be made for discounts in a separate Discount Account", - "fieldname": "enable_discount_accounting", - "fieldtype": "Check", - "label": "Enable Discount Accounting for Buying" } ], "icon": "fa fa-cog", @@ -148,7 +140,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2022-09-01 18:01:34.994657", + "modified": "2022-09-27 10:50:27.050252", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.py b/erpnext/buying/doctype/buying_settings/buying_settings.py index 7b18cdbedc..be1ebdeb64 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.py +++ b/erpnext/buying/doctype/buying_settings/buying_settings.py @@ -5,15 +5,10 @@ import frappe -from frappe.custom.doctype.property_setter.property_setter import make_property_setter from frappe.model.document import Document -from frappe.utils import cint class BuyingSettings(Document): - def on_update(self): - self.toggle_discount_accounting_fields() - def validate(self): for key in ["supplier_group", "supp_master_name", "maintain_same_rate", "buying_price_list"]: frappe.db.set_default(key, self.get(key, "")) @@ -26,60 +21,3 @@ class BuyingSettings(Document): self.get("supp_master_name") == "Naming Series", hide_name_field=False, ) - - def toggle_discount_accounting_fields(self): - enable_discount_accounting = cint(self.enable_discount_accounting) - - make_property_setter( - "Purchase Invoice Item", - "discount_account", - "hidden", - not (enable_discount_accounting), - "Check", - validate_fields_for_doctype=False, - ) - if enable_discount_accounting: - make_property_setter( - "Purchase Invoice Item", - "discount_account", - "mandatory_depends_on", - "eval: doc.discount_amount", - "Code", - validate_fields_for_doctype=False, - ) - else: - make_property_setter( - "Purchase Invoice Item", - "discount_account", - "mandatory_depends_on", - "", - "Code", - validate_fields_for_doctype=False, - ) - - make_property_setter( - "Purchase Invoice", - "additional_discount_account", - "hidden", - not (enable_discount_accounting), - "Check", - validate_fields_for_doctype=False, - ) - if enable_discount_accounting: - make_property_setter( - "Purchase Invoice", - "additional_discount_account", - "mandatory_depends_on", - "eval: doc.discount_amount", - "Code", - validate_fields_for_doctype=False, - ) - else: - make_property_setter( - "Purchase Invoice", - "additional_discount_account", - "mandatory_depends_on", - "", - "Code", - validate_fields_for_doctype=False, - ) From 1f6205e1ea569dd25ac298f10812f6e9f44409ef Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 27 Sep 2022 15:37:41 +0530 Subject: [PATCH 09/54] fix: Add return against indexes for POS Invoice --- erpnext/accounts/doctype/pos_invoice/pos_invoice.json | 2 +- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json index b126d57400..6f8b3822c2 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json @@ -1553,7 +1553,7 @@ "icon": "fa fa-file-text", "is_submittable": 1, "links": [], - "modified": "2022-03-22 13:00:24.166684", + "modified": "2022-09-27 13:00:24.166684", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice", diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 6e3a0766f1..a5e4d9a6dd 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -740,3 +740,7 @@ def add_return_modes(doc, pos_profile): ]: payment_mode = get_mode_of_payment_info(mode_of_payment, doc.company) append_payment(payment_mode[0]) + + +def on_doctype_update(): + frappe.db.add_index("POS Invoice", ["customer", "is_return", "return_against"]) From e39e088f18177ab4a189da60c18d57b92a6f8aff Mon Sep 17 00:00:00 2001 From: Maharshi Patel Date: Tue, 27 Sep 2022 15:44:38 +0530 Subject: [PATCH 10/54] fix: POS only validate QTY if is_stock_item POS invoice raised " Item not available " validation error even though item is non_stock. --- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 6e3a0766f1..539127095e 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -239,14 +239,14 @@ class POSInvoice(SalesInvoice): frappe.bold(d.warehouse), frappe.bold(d.qty), ) - if flt(available_stock) <= 0: + if is_stock_item and flt(available_stock) <= 0: frappe.throw( _("Row #{}: Item Code: {} is not available under warehouse {}.").format( d.idx, item_code, warehouse ), title=_("Item Unavailable"), ) - elif flt(available_stock) < flt(d.qty): + elif is_stock_item and flt(available_stock) < flt(d.qty): frappe.throw( _( "Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. Available quantity {}." From cbfe28286acc9319901aeaa2c77fa50e95c0e481 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 27 Sep 2022 16:22:59 +0530 Subject: [PATCH 11/54] fix: Add return against indexes for POS Invoice --- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index a5e4d9a6dd..9eded8a777 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -743,4 +743,4 @@ def add_return_modes(doc, pos_profile): def on_doctype_update(): - frappe.db.add_index("POS Invoice", ["customer", "is_return", "return_against"]) + frappe.db.add_index("POS Invoice", ["return_against"]) From 14e2d31619dd0b88aed7d8f67c6b3fd32c350a5f Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 27 Sep 2022 20:19:01 +0530 Subject: [PATCH 12/54] test: adding test_asset_with_maintenance_required_status_after_sale --- erpnext/assets/doctype/asset/test_asset.py | 35 +++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index e7af9bd5bc..6838885694 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -7,7 +7,11 @@ import frappe from frappe.utils import add_days, add_months, cstr, flt, get_last_day, getdate, nowdate from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice -from erpnext.assets.doctype.asset.asset import make_sales_invoice, split_asset +from erpnext.assets.doctype.asset.asset import ( + make_sales_invoice, + split_asset, + update_maintenance_status, +) from erpnext.assets.doctype.asset.depreciation import ( post_depreciation_entries, restore_asset, @@ -258,6 +262,34 @@ class TestAsset(AssetSetup): si.cancel() self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated") + def test_asset_with_maintenance_required_status_after_sale(self): + asset = create_asset( + calculate_depreciation=1, + available_for_use_date="2020-06-06", + purchase_date="2020-01-01", + expected_value_after_useful_life=10000, + total_number_of_depreciations=3, + frequency_of_depreciation=10, + maintenance_required=1, + depreciation_start_date="2020-12-31", + submit=1, + ) + + post_depreciation_entries(date="2021-01-01") + + si = make_sales_invoice(asset=asset.name, item_code="Macbook Pro", company="_Test Company") + si.customer = "_Test Customer" + si.due_date = nowdate() + si.get("items")[0].rate = 25000 + si.insert() + si.submit() + + self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold") + + update_maintenance_status() + + self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold") + def test_asset_splitting(self): asset = create_asset( calculate_depreciation=1, @@ -1376,6 +1408,7 @@ def create_asset(**args): "number_of_depreciations_booked": args.number_of_depreciations_booked or 0, "gross_purchase_amount": args.gross_purchase_amount or 100000, "purchase_receipt_amount": args.purchase_receipt_amount or 100000, + "maintenance_required": args.maintenance_required or 0, "warehouse": args.warehouse or "_Test Warehouse - _TC", "available_for_use_date": args.available_for_use_date or "2020-06-06", "location": args.location or "Test Location", From c6a7de0e545746556a7e80e0bd4dcf46159d3f24 Mon Sep 17 00:00:00 2001 From: anandbaburajan Date: Tue, 27 Sep 2022 20:43:08 +0530 Subject: [PATCH 13/54] chore: add blank lines --- erpnext/assets/doctype/asset/depreciation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index b6e86cdd5a..97941706aa 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -243,6 +243,7 @@ def restore_asset(asset_name): asset.set_status() + def depreciate_asset(asset, date): asset.flags.ignore_validate_update_after_submit = True asset.prepare_depreciation_data(date_of_disposal=date) @@ -327,6 +328,7 @@ def disposal_happens_in_the_future(posting_date_of_disposal): return False + def get_gl_entries_on_asset_regain( asset, selling_amount=0, finance_book=None, voucher_type=None, voucher_no=None ): From 82a2f31ada358d896943d04bdb517ac33b9e2d7a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 27 Sep 2022 22:12:32 +0530 Subject: [PATCH 14/54] fix: Move subscription process to hourly long quque --- erpnext/hooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index a08feb4447..6ef77f3f5b 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -391,12 +391,12 @@ scheduler_events = { "erpnext.crm.doctype.social_media_post.social_media_post.process_scheduled_social_media_posts", ], "hourly": [ - "erpnext.accounts.doctype.subscription.subscription.process_all", "erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.automatic_synchronization", "erpnext.projects.doctype.project.project.hourly_reminder", "erpnext.projects.doctype.project.project.collect_project_status", ], "hourly_long": [ + "erpnext.accounts.doctype.subscription.subscription.process_all", "erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.repost_entries", "erpnext.bulk_transaction.doctype.bulk_transaction_log.bulk_transaction_log.retry_failing_transaction", ], From e392ea1104fee5add5c893c4e092edb6ad21f486 Mon Sep 17 00:00:00 2001 From: Maharshi Patel Date: Tue, 27 Sep 2022 23:44:56 +0530 Subject: [PATCH 15/54] fix: POS properly validate stock for bundle products Stock availability was not calculated properly for Product Bundle with non stock item so i have added logic to properly calculate that as well. --- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 9 ++++++--- erpnext/selling/page/point_of_sale/pos_controller.js | 4 ++-- erpnext/selling/page/point_of_sale/pos_item_details.js | 5 +++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 539127095e..54a3e934b2 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -632,11 +632,12 @@ def get_stock_availability(item_code, warehouse): pos_sales_qty = get_pos_reserved_qty(item_code, warehouse) return bin_qty - pos_sales_qty, is_stock_item else: - is_stock_item = False + is_stock_item = True if frappe.db.exists("Product Bundle", item_code): return get_bundle_availability(item_code, warehouse), is_stock_item else: - # Is a service item + is_stock_item = False + # Is a service item or non_stock item return 0, is_stock_item @@ -650,7 +651,9 @@ def get_bundle_availability(bundle_item_code, warehouse): available_qty = item_bin_qty - item_pos_reserved_qty max_available_bundles = available_qty / item.qty - if bundle_bin_qty > max_available_bundles: + if bundle_bin_qty > max_available_bundles and frappe.get_value( + "Item", item.item_code, "is_stock_item" + ): bundle_bin_qty = max_available_bundles pos_sales_qty = get_pos_reserved_qty(bundle_item_code, warehouse) diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js index da7576e08d..24375d8252 100644 --- a/erpnext/selling/page/point_of_sale/pos_controller.js +++ b/erpnext/selling/page/point_of_sale/pos_controller.js @@ -660,7 +660,7 @@ erpnext.PointOfSale.Controller = class { } else { return; } - } else if (available_qty < qty_needed) { + } else if (is_stock_item && available_qty < qty_needed) { frappe.throw({ message: __('Stock quantity not enough for Item Code: {0} under warehouse {1}. Available quantity {2}.', [bold_item_code, bold_warehouse, bold_available_qty]), indicator: 'orange' @@ -694,7 +694,7 @@ erpnext.PointOfSale.Controller = class { callback(res) { if (!me.item_stock_map[item_code]) me.item_stock_map[item_code] = {}; - me.item_stock_map[item_code][warehouse] = res.message[0]; + me.item_stock_map[item_code][warehouse] = res.message; } }); } 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 b75ffb235e..f9b5bb2e45 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_details.js +++ b/erpnext/selling/page/point_of_sale/pos_item_details.js @@ -242,13 +242,14 @@ erpnext.PointOfSale.ItemDetails = class { if (this.value) { me.events.form_updated(me.current_item, 'warehouse', this.value).then(() => { me.item_stock_map = me.events.get_item_stock_map(); - const available_qty = me.item_stock_map[me.item_row.item_code] && me.item_stock_map[me.item_row.item_code][this.value]; + const available_qty = me.item_stock_map[me.item_row.item_code][this.value][0]; + const is_stock_item = Boolean(me.item_stock_map[me.item_row.item_code][this.value][1]); if (available_qty === undefined) { me.events.get_available_stock(me.item_row.item_code, this.value).then(() => { // item stock map is updated now reset warehouse me.warehouse_control.set_value(this.value); }) - } else if (available_qty === 0) { + } else if (available_qty === 0 && is_stock_item) { me.warehouse_control.set_value(''); const bold_item_code = me.item_row.item_code.bold(); const bold_warehouse = this.value.bold(); From f42a8e4e039174f220003e07da1b7225cfa4315a Mon Sep 17 00:00:00 2001 From: Maharshi Patel Date: Wed, 28 Sep 2022 12:54:00 +0530 Subject: [PATCH 16/54] fix: fetch swift_number in payment_request There isn't direct link between payment_request and bank so swift_number wasn't fetched using Fetch form. I fixed it by fetching swift_number on_change of bank_account. --- .../accounts/doctype/payment_request/payment_request.js | 7 +++++++ .../accounts/doctype/payment_request/payment_request.json | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.js b/erpnext/accounts/doctype/payment_request/payment_request.js index 901ef1987b..da66edc9fe 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.js +++ b/erpnext/accounts/doctype/payment_request/payment_request.js @@ -9,6 +9,13 @@ frappe.ui.form.on("Payment Request", { query: "erpnext.setup.doctype.party_type.party_type.get_party_type", }; }); + }, + "bank_account": function(frm) { + frappe.db.get_value('Bank', frm.doc.bank, ['swift_number']) + .then(r => { + let values = r.message; + frm.set_value('swift_number', values.swift_number) + }) } }) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json index 2ee356aaf4..33edb63fbf 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.json +++ b/erpnext/accounts/doctype/payment_request/payment_request.json @@ -219,7 +219,6 @@ "label": "Branch Code" }, { - "fetch_from": "bank.swift_number", "fieldname": "swift_number", "fieldtype": "Read Only", "label": "SWIFT Number" @@ -366,7 +365,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2020-09-18 12:24:14.178853", + "modified": "2022-09-28 12:39:30.160837", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Request", From 0439e41a44db1c5e4319feae11a38728e6fba8f8 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 28 Sep 2022 14:54:53 +0530 Subject: [PATCH 17/54] fix: Item details fetching on making transaction from item dashboard --- erpnext/stock/doctype/item/item.js | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 7e1476d240..e61f0f514e 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -10,6 +10,31 @@ frappe.ui.form.on("Item", { frm.add_fetch('attribute', 'to_range', 'to_range'); frm.add_fetch('attribute', 'increment', 'increment'); frm.add_fetch('tax_type', 'tax_rate', 'tax_rate'); + + frm.make_methods = { + 'Sales Order': () => { + open_form(frm, "Sales Order", "Sales Order Item", "items"); + }, + 'Delivery Note': () => { + open_form(frm, "Delivery Note", "Delivery Note Item", "items"); + }, + 'Sales Invoice': () => { + open_form(frm, "Sales Invoice", "Sales Invoice Item", "items"); + }, + 'Purchase Order': () => { + open_form(frm, "Purchase Order", "Purchase Order Item", "items"); + }, + 'Purchase Receipt': () => { + open_form(frm, "Purchase Receipt", "Purchase Receipt Item", "items"); + }, + 'Purchase Invoice': () => { + open_form(frm, "Purchase Invoice", "Purchase Invoice Item", "items"); + }, + 'Material Request': () => { + open_form(frm, "Material Request", "Material Request Item", "items"); + }, + }; + }, onload: function(frm) { erpnext.item.setup_queries(frm); @@ -858,3 +883,17 @@ frappe.tour['Item'] = [ ]; + +function open_form(frm, doctype, child_doctype, parentfield) { + frappe.model.with_doctype(doctype, () => { + let new_doc = frappe.model.get_new_doc(doctype); + + let new_child_doc = frappe.model.add_child(new_doc, child_doctype, parentfield); + new_child_doc.item_code = frm.doc.name; + new_child_doc.item_name = frm.doc.item_name; + new_child_doc.uom = frm.doc.stock_uom; + new_child_doc.description = frm.doc.description; + + frappe.ui.form.make_quick_entry(doctype, null, null, new_doc); + }); +} From be623ce8e8e9c25d2327383c057b5e810b28c4a7 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 28 Sep 2022 15:36:59 +0530 Subject: [PATCH 18/54] fix: Disbursement Account in patch to update old loans --- erpnext/patches/v13_0/update_old_loans.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/patches/v13_0/update_old_loans.py b/erpnext/patches/v13_0/update_old_loans.py index a1d40b739e..0bd3fcdec4 100644 --- a/erpnext/patches/v13_0/update_old_loans.py +++ b/erpnext/patches/v13_0/update_old_loans.py @@ -100,6 +100,7 @@ def execute(): "mode_of_payment": loan.mode_of_payment, "loan_account": loan.loan_account, "payment_account": loan.payment_account, + "disbursement_account": loan.payment_account, "interest_income_account": loan.interest_income_account, "penalty_income_account": loan.penalty_income_account, }, @@ -190,6 +191,7 @@ def create_loan_type(loan, loan_type_name, penalty_account): loan_type_doc.company = loan.company loan_type_doc.mode_of_payment = loan.mode_of_payment loan_type_doc.payment_account = loan.payment_account + loan_type_doc.disbursement_account = loan.payment_account loan_type_doc.loan_account = loan.loan_account loan_type_doc.interest_income_account = loan.interest_income_account loan_type_doc.penalty_income_account = penalty_account From 80080a3d7bc2e4a69c7a18742ce89534920ab118 Mon Sep 17 00:00:00 2001 From: Sagar Sharma Date: Wed, 28 Sep 2022 15:40:07 +0530 Subject: [PATCH 19/54] fix: show `Make Purchase Invoice` button based on permission --- erpnext/templates/pages/order.html | 2 +- erpnext/templates/pages/order.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html index a10870db27..ec1d49788b 100644 --- a/erpnext/templates/pages/order.html +++ b/erpnext/templates/pages/order.html @@ -18,7 +18,7 @@
diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html index f56dc3a454..dc9ee234d9 100644 --- a/erpnext/templates/includes/macros.html +++ b/erpnext/templates/includes/macros.html @@ -1,5 +1,5 @@ {% macro product_image_square(website_image, css_class="") %} -
-
+
{% if d.thumbnail or d.image %} {{ product_image(d.thumbnail or d.image, no_border=True) }} {% else %} @@ -18,6 +18,9 @@
{{ html2text(d.description) | truncate(140) }}
+ + {{ _("Qty ") }}({{ d.get_formatted("qty") }}) +
{% endmacro %} diff --git a/erpnext/templates/includes/order/order_taxes.html b/erpnext/templates/includes/order/order_taxes.html index b821e6253d..0060ab39cc 100644 --- a/erpnext/templates/includes/order/order_taxes.html +++ b/erpnext/templates/includes/order/order_taxes.html @@ -1,84 +1,111 @@ {% if doc.taxes %} - - - {{ _("Net Total") }} - - - {{ doc.get_formatted("net_total") }} - - +
+
+
+ {{ _("Net Total") }} +
+
+ {{ doc.get_formatted("net_total") }} +
+
+
{% endif %} {% for d in doc.taxes %} {% if d.base_tax_amount %} - - - {{ d.description }} - - - {{ d.get_formatted("base_tax_amount") }} - - +
+
+
+ {{ d.description }} +
+
+ {{ doc.get_formatted("net_total") }} +
+
+
{% endif %} {% endfor %} {% if doc.doctype == 'Quotation' %} {% if doc.coupon_code %} - - - {{ _("Savings") }} - - - {% set tot_quotation_discount = [] %} - {%- for item in doc.items -%} - {% if tot_quotation_discount.append((((item.price_list_rate * item.qty) - * item.discount_percentage) / 100)) %} - {% endif %} - {% endfor %} - {{ frappe.utils.fmt_money((tot_quotation_discount | sum),currency=doc.currency) }} - - +
+
+
+ {{ _("Savings") }} +
+
+ {% set tot_quotation_discount = [] %} + {%- for item in doc.items -%} + {% if tot_quotation_discount.append((((item.price_list_rate * item.qty) + * item.discount_percentage) / 100)) %} + {% endif %} + {% endfor %} + {{ frappe.utils.fmt_money((tot_quotation_discount | sum),currency=doc.currency) }}
+
+
{% endif %} {% endif %} {% if doc.doctype == 'Sales Order' %} {% if doc.coupon_code %} - - - {{ _("Applied Coupon Code") }} - - - - {%- for row in frappe.get_all(doctype="Coupon Code", - fields=["coupon_code"], filters={ "name":doc.coupon_code}) -%} - {{ row.coupon_code }} - {% endfor %} - - - - - - {{ _("Savings") }} - - - - {% set tot_SO_discount = [] %} - {%- for item in doc.items -%} - {% if tot_SO_discount.append((((item.price_list_rate * item.qty) - * item.discount_percentage) / 100)) %}{% endif %} - {% endfor %} - {{ frappe.utils.fmt_money((tot_SO_discount | sum),currency=doc.currency) }} - - - +
+
+
+ {{ _("Total Amount") }} +
+
+ + {% set total_amount = [] %} + {%- for item in doc.items -%} + {% if total_amount.append((item.price_list_rate * item.qty)) %}{% endif %} + {% endfor %} + {{ frappe.utils.fmt_money((total_amount | sum),currency=doc.currency) }} + +
+
+
+
+
+
+ {{ _("Applied Coupon Code") }} +
+
+ + {%- for row in frappe.get_all(doctype="Coupon Code", + fields=["coupon_code"], filters={ "name":doc.coupon_code}) -%} + {{ row.coupon_code }} + {% endfor %} + +
+
+
+
+
+
+ {{ _("Savings") }} +
+
+ + {% set tot_SO_discount = [] %} + {%- for item in doc.items -%} + {% if tot_SO_discount.append((((item.price_list_rate * item.qty) + * item.discount_percentage) / 100)) %}{% endif %} + {% endfor %} + {{ frappe.utils.fmt_money((tot_SO_discount | sum),currency=doc.currency) }} + +
+
+
{% endif %} {% endif %} - - - {{ _("Grand Total") }} - - - {{ doc.get_formatted("grand_total") }} - - +
+
+
+ {{ _("Grand Total") }} +
+
+ {{ doc.get_formatted("grand_total") }} +
+
+
diff --git a/erpnext/templates/includes/transaction_row.html b/erpnext/templates/includes/transaction_row.html index 3cfb8d8440..72d498c998 100644 --- a/erpnext/templates/includes/transaction_row.html +++ b/erpnext/templates/includes/transaction_row.html @@ -1,20 +1,22 @@
-
+
- - {{ doc.name }} + {{ doc.name }}
{{ frappe.utils.global_date_format(doc.modified) }}
-
+
+ {{doc.status}} +
+
{{ doc.items_preview }}
{% if doc.get('grand_total') %} -
+
{{ doc.get_formatted("grand_total") }}
{% endif %} diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html index ec1d49788b..6b354b2fab 100644 --- a/erpnext/templates/pages/order.html +++ b/erpnext/templates/pages/order.html @@ -5,149 +5,159 @@ {% include "templates/includes/breadcrumbs.html" %} {% endblock %} -{% block title %}{{ doc.name }}{% endblock %} +{% block title %} + {{ doc.name }} +{% endblock %} {% block header %} -

{{ doc.name }}

+

{{ doc.name }}

{% endblock %} {% block header_actions %} -
{% endif %} -
{% if doc.terms %}
-

{{ doc.terms }}

+
+

{{ doc.terms }}

{% endif %} {% endblock %} {% block script %} - + -{% endblock %} +{% endblock %} \ No newline at end of file From 518ab93e039d68827506c3ac92db3c09aea644e3 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 4 Oct 2022 12:35:59 +0530 Subject: [PATCH 47/54] refactor: remove duplicate entries on remarks migration patch --- ...grate_remarks_from_gl_to_payment_ledger.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py b/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py index 062d24b78b..fd2a2a39cc 100644 --- a/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py +++ b/erpnext/patches/v14_0/migrate_remarks_from_gl_to_payment_ledger.py @@ -3,6 +3,29 @@ from frappe import qb from frappe.utils import create_batch +def remove_duplicate_entries(pl_entries): + unique_vouchers = set() + for x in pl_entries: + unique_vouchers.add( + (x.company, x.account, x.party_type, x.party, x.voucher_type, x.voucher_no, x.gle_remarks) + ) + + entries = [] + for x in unique_vouchers: + entries.append( + frappe._dict( + company=x[0], + account=x[1], + party_type=x[2], + party=x[3], + voucher_type=x[4], + voucher_no=x[5], + gle_remarks=x[6], + ) + ) + return entries + + def execute(): if frappe.reload_doc("accounts", "doctype", "payment_ledger_entry"): @@ -34,6 +57,8 @@ def execute(): .run(as_dict=True) ) + pl_entries = remove_duplicate_entries(pl_entries) + if pl_entries: # split into multiple batches, update and commit for each batch batch_size = 1000 From aaabba9b1e93ab90fd2afa9fb7b404b10fe8a3a4 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 5 Oct 2022 10:58:21 +0530 Subject: [PATCH 48/54] fix: TooManyWritesError during reposting of stock --- .../doctype/repost_item_valuation/repost_item_valuation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index c4705246b3..d6f9bae5da 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -128,6 +128,9 @@ def repost(doc): if not frappe.db.exists("Repost Item Valuation", doc.name): return + # This is to avoid TooManyWritesError in case of large reposts + frappe.db.MAX_WRITES_PER_TRANSACTION *= 4 + doc.set_status("In Progress") if not frappe.flags.in_test: frappe.db.commit() From 0e4017cbe51394986046818946d8f6ac39798182 Mon Sep 17 00:00:00 2001 From: HENRY Florian Date: Wed, 5 Oct 2022 14:49:44 +0200 Subject: [PATCH 49/54] chore: update fr translation (#32385) --- erpnext/translations/fr.csv | 61 +++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv index b2074618a6..7989bf7ebc 100644 --- a/erpnext/translations/fr.csv +++ b/erpnext/translations/fr.csv @@ -785,7 +785,7 @@ Default BOM for {0} not found,Nomenclature par défaut {0} introuvable, Default BOM not found for Item {0} and Project {1},La nomenclature par défaut n'a pas été trouvée pour l'Article {0} et le Projet {1}, Default Letter Head,En-Tête de Courrier par Défaut, Default Tax Template,Modèle de Taxes par Défaut, -Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.,L’Unité de Mesure par Défaut pour l’Article {0} ne peut pas être modifiée directement parce que vous avez déjà fait une (des) transaction (s) avec une autre unité de mesure. Vous devez créer un nouvel article pour utiliser une UDM par défaut différente., +Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.,L’Unité de Mesure par Défaut pour l’Article {0} ne peut pas être modifiée directement parce que vous avez déjà fait une (des) transaction (s) avec une autre unité de mesure. Vous devez créer un nouvel article pour utiliser une UdM par défaut différente., Default Unit of Measure for Variant '{0}' must be same as in Template '{1}',L’Unité de mesure par défaut pour la variante '{0}' doit être la même que dans le Modèle '{1}', Default settings for buying transactions.,Paramètres par défaut pour les transactions d'achat., Default settings for selling transactions.,Paramètres par défaut pour les transactions de vente., @@ -838,7 +838,7 @@ Difference Account,Compte d’Écart, "Difference Account must be a Asset/Liability type account, since this Stock Reconciliation is an Opening Entry","Le Compte d’Écart doit être un compte de type Actif / Passif, puisque cette Réconciliation de Stock est une écriture d'à-nouveau", Difference Amount,Écart de Montant, Difference Amount must be zero,L’Écart de Montant doit être égal à zéro, -Different UOM for items will lead to incorrect (Total) Net Weight value. Make sure that Net Weight of each item is in the same UOM.,Différentes UDM pour les articles conduira à un Poids Net (Total) incorrect . Assurez-vous que le Poids Net de chaque article a la même unité de mesure ., +Different UOM for items will lead to incorrect (Total) Net Weight value. Make sure that Net Weight of each item is in the same UOM.,Différentes UdM pour les articles conduira à un Poids Net (Total) incorrect . Assurez-vous que le Poids Net de chaque article a la même unité de mesure ., Direct Expenses,Charges Directes, Direct Income,Revenu direct, Disable,Désactiver, @@ -1409,7 +1409,7 @@ Lab Test,Test de laboratoire, Lab Test Report,Rapport de test de laboratoire, Lab Test Sample,Échantillon de test de laboratoire, Lab Test Template,Modèle de test de laboratoire, -Lab Test UOM,UDM de test de laboratoire, +Lab Test UOM,UdM de test de laboratoire, Lab Tests and Vital Signs,Tests de laboratoire et signes vitaux, Lab result datetime cannot be before testing datetime,La date et l'heure du résultat de laboratoire ne peuvent pas être avant la date et l'heure du test, Lab testing datetime cannot be before collection datetime,La date et l'heure du test de laboratoire ne peuvent pas être avant la date et l'heure de collecte, @@ -2806,7 +2806,7 @@ Stock Received But Not Billed,Stock Reçus Mais Non Facturés, Stock Reports,Rapports de stock, Stock Summary,Résumé du Stock, Stock Transactions,Transactions du Stock, -Stock UOM,UDM du Stock, +Stock UOM,UdM du Stock, Stock Value,Valeur du Stock, Stock balance in Batch {0} will become negative {1} for Item {2} at Warehouse {3},Solde du stock dans le Lot {0} deviendra négatif {1} pour l'Article {2} à l'Entrepôt {3}, Stock cannot be updated against Delivery Note {0},Stock ne peut pas être mis à jour pour le Bon de Livraison {0}, @@ -3161,9 +3161,9 @@ Trial Period End Date Cannot be before Trial Period Start Date,La date de fin de Trialling,Essai, Type of Business,Type de commerce, Types of activities for Time Logs,Types d'activités pour Journaux de Temps, -UOM,UDM, -UOM Conversion factor is required in row {0},Facteur de conversion de l'UDM est obligatoire dans la ligne {0}, -UOM coversion factor required for UOM: {0} in Item: {1},Facteur de coversion UDM requis pour l'UDM : {0} dans l'Article : {1}, +UOM,UdM, +UOM Conversion factor is required in row {0},Facteur de conversion de l'UdM est obligatoire dans la ligne {0}, +UOM coversion factor required for UOM: {0} in Item: {1},Facteur de coversion UdM requis pour l'UdM : {0} dans l'Article : {1}, URL,URL, Unable to find DocType {0},Impossible de trouver le DocType {0}, Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually,Impossible de trouver le taux de change pour {0} à {1} pour la date clé {2}. Veuillez créer une entrée de taux de change manuellement, @@ -3294,7 +3294,7 @@ Wednesday,Mercredi, Week,Semaine, Weekdays,Jours de la semaine, Weekly,Hebdomadaire, -"Weight is mentioned,\nPlease mention ""Weight UOM"" too","Poids est mentionné,\nVeuillez aussi mentionner ""UDM de Poids""", +"Weight is mentioned,\nPlease mention ""Weight UOM"" too","Poids est mentionné,\nVeuillez aussi mentionner ""UdM de Poids""", Welcome email sent,Email de bienvenue envoyé, Welcome to ERPNext,Bienvenue sur ERPNext, What do you need help with?,Avec quoi avez vous besoin d'aide ?, @@ -4938,12 +4938,15 @@ Is Cumulative,Est cumulatif, Coupon Code Based,Code de coupon basé, Discount on Other Item,Remise sur un autre article, Apply Rule On Other,Appliquer la règle sur autre, -Party Information,Informations sur la fête, +Party Information,Informations sur le tier, Quantity and Amount,Quantité et montant, Min Qty,Qté Min, Max Qty,Qté Max, -Min Amt,Min Amt, -Max Amt,Max Amt, +Min Amt,Montant Min, +Max Amt,Montant Max, +"If rate is zero them item will be treated as ""Free Item""",Si le prix est à 0 alors l'article sera traité comme article gratuit +Is Recursive,Est récursif +"Discounts to be applied in sequential ranges like buy 1 get 1, buy 2 get 2, buy 3 get 3 and so on",La remise sera appliquée séquentiellement telque : acheter 1 => recupérer 1, acheter 2 => recupérer 2, acheter 3 => recupérer 3, etc... Period Settings,Paramètres de période, Margin,Marge, Margin Type,Type de Marge, @@ -5053,7 +5056,7 @@ Quantity and Rate,Quantité et Prix, Received Qty,Qté Reçue, Accepted Qty,Quantité acceptée, Rejected Qty,Qté Rejetée, -UOM Conversion Factor,Facteur de Conversion de l'UDM, +UOM Conversion Factor,Facteur de Conversion de l'UdM, Discount on Price List Rate (%),Remise sur la Liste des Prix (%), Price List Rate (Company Currency),Taux de la Liste de Prix (Devise Société), Rate (Company Currency),Prix (Devise Société), @@ -5085,7 +5088,7 @@ Purchase Receipt Detail,Détail du reçu d'achat, Item Weight Details,Détails du poids de l'article, Weight Per Unit,Poids par unité, Total Weight,Poids total, -Weight UOM,UDM de Poids, +Weight UOM,UdM de Poids, Page Break,Saut de Page, Consider Tax or Charge for,Tenir Compte de la Taxe et des Frais pour, Valuation and Total,Valorisation et Total, @@ -5153,7 +5156,7 @@ Advance amount,Montant de l'Avance, Sales Invoice Item,Article de la Facture de Vente, Customer's Item Code,Code de l'Article du Client, Brand Name,Nom de la Marque, -Qty as per Stock UOM,Qté par UDM du Stock, +Qty as per Stock UOM,Qté par UdM du Stock, Discount and Margin,Remise et Marge, Rate With Margin,Prix Avec Marge, Discount (%) on Price List Rate with Margin,Remise (%) sur le prix de la Liste de Prix avec la Marge, @@ -5501,7 +5504,7 @@ Blanket Order Rate,Prix unitaire de commande avec limites, Returned Qty,Qté Retournée, Purchase Order Item Supplied,Article Fourni depuis la Commande d'Achat, BOM Detail No,N° de Détail de la nomenclature, -Stock Uom,UDM du Stock, +Stock Uom,UdM du Stock, Raw Material Item Code,Code d’Article de Matière Première, Supplied Qty,Qté Fournie, Purchase Receipt Item Supplied,Articles Fournis du Reçus d’Achat, @@ -6149,7 +6152,7 @@ Drug Name / Description,Nom / description du médicament, Dosage,Dosage, Dosage by Time Interval,Dosage par intervalle de temps, Interval,Intervalle, -Interval UOM,UDM d'Intervalle, +Interval UOM,UdM d'Intervalle, Hour,Heure, Update Schedule,Mettre à Jour le Calendrier, Exercise,Exercice, @@ -7023,7 +7026,7 @@ Petrol,Essence, Diesel,Diesel, Natural Gas,Gaz Naturel, Electric,Électrique, -Fuel UOM,UDM Carburant, +Fuel UOM,UdM Carburant, Last Carbon Check,Dernière Vérification Carbone, Wheels,Roues, Doors,Portes, @@ -7182,7 +7185,7 @@ Item to be manufactured or repacked,Article à produire ou à réemballer, Quantity of item obtained after manufacturing / repacking from given quantities of raw materials,Quantité d'article obtenue après production / reconditionnement des quantités données de matières premières, Set rate of sub-assembly item based on BOM,Définir le prix des articles de sous-assemblage en fonction de la nomenclature, Allow Alternative Item,Autoriser un article alternatif, -Item UOM,UDM de l'Article, +Item UOM,UdM de l'Article, Conversion Rate,Taux de Conversion, Rate Of Materials Based On,Prix des Matériaux Basé sur, With Operations,Avec des Opérations, @@ -7926,7 +7929,7 @@ Territory Manager,Responsable Régional, For reference,Pour référence, Territory Targets,Objectifs Régionaux, Set Item Group-wise budgets on this Territory. You can also include seasonality by setting the Distribution.,Définir des budgets par Groupes d'Articles sur ce Territoire. Vous pouvez également inclure de la saisonnalité en définissant la Répartition., -UOM Name,Nom UDM, +UOM Name,Nom UdM, Check this to disallow fractions. (for Nos),Cochez cette case pour interdire les fractions. (Pour les numéros), Website Item Group,Groupe d'Articles du Site Web, Cross Listing of Item in multiple groups,Liste Croisée d'Articles dans plusieurs groupes, @@ -8198,10 +8201,10 @@ To Package No.,Au N° de Paquet, If more than one package of the same type (for print),Si plus d'un paquet du même type (pour l'impression), Package Weight Details,Détails du Poids du Paquet, The net weight of this package. (calculated automatically as sum of net weight of items),Le poids net de ce paquet. (Calculé automatiquement comme la somme du poids net des articles), -Net Weight UOM,UDM Poids Net, +Net Weight UOM,UdM Poids Net, Gross Weight,Poids Brut, The gross weight of the package. Usually net weight + packaging material weight. (for print),Le poids brut du colis. Habituellement poids net + poids du matériau d'emballage. (Pour l'impression), -Gross Weight UOM,UDM du Poids Brut, +Gross Weight UOM,UdM du Poids Brut, Packing Slip Item,Article Emballé, DN Detail,Détail du Bon de Livraison, STO-PICK-.YYYY.-,STO-PICK-.YYYY.-, @@ -8215,7 +8218,7 @@ Pick List Item,Élément de la liste de choix, Picked Qty,Quantité choisie, Price List Master,Données de Base des Listes de Prix, Price List Name,Nom de la Liste de Prix, -Price Not UOM Dependent,Prix non dépendant de l'UOM, +Price Not UOM Dependent,Prix non dépendant de l'UdM, Applicable for Countries,Applicable pour les Pays, Price List Country,Pays de la Liste des Prix, MAT-PRE-.YYYY.-,MAT-PRE-YYYY.-, @@ -8294,7 +8297,7 @@ Purchase Receipt No,N° du Reçu d'Achat, Inspection Required,Inspection obligatoire, From BOM,Depuis la nomenclature, For Quantity,Pour la Quantité, -As per Stock UOM,Selon UDM du Stock, +As per Stock UOM,Selon UdM du Stock, Including items for sub assemblies,Incluant les articles pour des sous-ensembles, Default Source Warehouse,Entrepôt Source par Défaut, Source Warehouse Address,Adresse de l'entrepôt source, @@ -8309,7 +8312,7 @@ Total Additional Costs,Total des Coûts Additionnels, Customer or Supplier Details,Détails du Client ou du Fournisseur, Per Transferred,Par transféré, Stock Entry Detail,Détails de l'Écriture de Stock, -Basic Rate (as per Stock UOM),Prix de base (comme l’UDM du Stock), +Basic Rate (as per Stock UOM),Prix de base (comme l’UdM du Stock), Basic Amount,Montant de Base, Additional Cost,Frais Supplémentaire, Serial No / Batch,N° de Série / Lot, @@ -8339,7 +8342,7 @@ Quantity Difference,Différence de Quantité, Amount Difference,Différence de Montant, Item Naming By,Nomenclature d'Article Par, Default Item Group,Groupe d'Éléments par Défaut, -Default Stock UOM,UDM par Défaut des Articles, +Default Stock UOM,UdM par Défaut des Articles, Sample Retention Warehouse,Entrepôt de stockage des échantillons, Default Valuation Method,Méthode de Valorisation par Défaut, Show Barcode Field,Afficher Champ Code Barre, @@ -8353,8 +8356,8 @@ Stock Frozen Upto,Stock Gelé Jusqu'au, Batch Identification,Identification par lots, Use Naming Series,Utiliser la série de noms, Naming Series Prefix,Préfix du nom de série, -UOM Category,Catégorie d'unité de mesure (UDM), -UOM Conversion Detail,Détails de Conversion de l'UDM, +UOM Category,Catégorie d'unité de mesure (UdM), +UOM Conversion Detail,Détails de Conversion de l'UdM, Variant Field,Champ de Variante, A logical Warehouse against which stock entries are made.,Un Entrepôt logique dans lequel les entrées en stock sont faites., Warehouse Detail,Détail de l'Entrepôt, @@ -9869,8 +9872,8 @@ Allowed Items,Articles autorisés Party Specific Item,Restriction d'article disponible Restrict Items Based On,Type de critére de restriction Based On Value,critére de restriction -Unit of Measure (UOM),Unité de mesure (UDM), -Unit Of Measure (UOM),Unité de mesure (UDM), +Unit of Measure (UOM),Unité de mesure (UdM), +Unit Of Measure (UOM),Unité de mesure (UdM), CRM Settings,Paramètres CRM Do Not Explode,Ne pas décomposer Quick Access, Accés rapides From 8d1db0ea3db008d753048ca53356846af44de775 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 6 Oct 2022 11:28:26 +0530 Subject: [PATCH 50/54] fix: single column indexes (#32425) refactor: move single column indexes to doctypes --- erpnext/accounts/doctype/pos_invoice/pos_invoice.json | 5 +++-- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 4 ---- erpnext/e_commerce/doctype/website_item/website_item.json | 8 +++++--- erpnext/e_commerce/doctype/website_item/website_item.py | 3 --- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json index 6f8b3822c2..eedaaaf338 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json @@ -343,7 +343,8 @@ "no_copy": 1, "options": "POS Invoice", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "default": "0", @@ -1553,7 +1554,7 @@ "icon": "fa fa-file-text", "is_submittable": 1, "links": [], - "modified": "2022-09-27 13:00:24.166684", + "modified": "2022-09-30 03:49:50.455199", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice", diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index fbe0ef39f8..54a3e934b2 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -743,7 +743,3 @@ def add_return_modes(doc, pos_profile): ]: payment_mode = get_mode_of_payment_info(mode_of_payment, doc.company) append_payment(payment_mode[0]) - - -def on_doctype_update(): - frappe.db.add_index("POS Invoice", ["return_against"]) diff --git a/erpnext/e_commerce/doctype/website_item/website_item.json b/erpnext/e_commerce/doctype/website_item/website_item.json index c5775ee907..6556eabf4a 100644 --- a/erpnext/e_commerce/doctype/website_item/website_item.json +++ b/erpnext/e_commerce/doctype/website_item/website_item.json @@ -188,7 +188,8 @@ "in_list_view": 1, "label": "Item Group", "options": "Item Group", - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "default": "1", @@ -234,7 +235,8 @@ "fieldname": "brand", "fieldtype": "Link", "label": "Brand", - "options": "Brand" + "options": "Brand", + "search_index": 1 }, { "collapsible": 1, @@ -346,7 +348,7 @@ "index_web_pages_for_search": 1, "links": [], "make_attachments_public": 1, - "modified": "2022-09-13 04:05:11.614087", + "modified": "2022-09-30 04:01:52.090732", "modified_by": "Administrator", "module": "E-commerce", "name": "Website Item", diff --git a/erpnext/e_commerce/doctype/website_item/website_item.py b/erpnext/e_commerce/doctype/website_item/website_item.py index c0f8c79283..3e5d5f768f 100644 --- a/erpnext/e_commerce/doctype/website_item/website_item.py +++ b/erpnext/e_commerce/doctype/website_item/website_item.py @@ -403,9 +403,6 @@ def on_doctype_update(): # since route is a Text column, it needs a length for indexing frappe.db.add_index("Website Item", ["route(500)"]) - frappe.db.add_index("Website Item", ["item_group"]) - frappe.db.add_index("Website Item", ["brand"]) - def check_if_user_is_customer(user=None): from frappe.contacts.doctype.contact.contact import get_contact_name From 07c4a7483869a06c1e00a2a71c1909fcf5cd9ed6 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 6 Oct 2022 13:01:53 +0530 Subject: [PATCH 51/54] chore: drop stale demo page (#32515) --- erpnext/templates/pages/demo.html | 77 ------------------------------- 1 file changed, 77 deletions(-) delete mode 100644 erpnext/templates/pages/demo.html diff --git a/erpnext/templates/pages/demo.html b/erpnext/templates/pages/demo.html deleted file mode 100644 index f9934a33f3..0000000000 --- a/erpnext/templates/pages/demo.html +++ /dev/null @@ -1,77 +0,0 @@ -{% extends "templates/web.html" %} - -{% block script %} - -{% endblock %} - -{% block style %} - -{% endblock %} - -{% block title %} -{{ _("ERPNext Demo") }} -{% endblock %} - -{% block page_content %} -
- -
- - {{ _("ERPNext Demo") }} -
- -

Some functionality is disabled for the demo and the data will be cleared regularly.

-
-
- - -

Start a free 14-day trial -

- -{% endblock %} From 8376fbc9826e3fa7dc9a28365d96e92a2f6f52d9 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 6 Oct 2022 20:35:33 +0530 Subject: [PATCH 52/54] fix: Explicitly update modified (#32519) * fix: Explicitly update modified required after https://github.com/frappe/frappe/pull/18301 * chore: fix broken translations --- erpnext/stock/doctype/bin/bin.py | 11 +++++++---- erpnext/stock/stock_ledger.py | 2 +- erpnext/translations/fr.csv | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index 548df318fa..c28f45aed4 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -37,8 +37,10 @@ class Bin(Document): self.set_projected_qty() - self.db_set("reserved_qty_for_production", flt(self.reserved_qty_for_production)) - self.db_set("projected_qty", self.projected_qty) + self.db_set( + "reserved_qty_for_production", flt(self.reserved_qty_for_production), update_modified=True + ) + self.db_set("projected_qty", self.projected_qty, update_modified=True) def update_reserved_qty_for_sub_contracting(self, subcontract_doctype="Subcontracting Order"): # reserved qty @@ -118,9 +120,9 @@ class Bin(Document): else: reserved_qty_for_sub_contract = 0 - self.db_set("reserved_qty_for_sub_contract", reserved_qty_for_sub_contract) + self.db_set("reserved_qty_for_sub_contract", reserved_qty_for_sub_contract, update_modified=True) self.set_projected_qty() - self.db_set("projected_qty", self.projected_qty) + self.db_set("projected_qty", self.projected_qty, update_modified=True) def on_doctype_update(): @@ -193,4 +195,5 @@ def update_qty(bin_name, args): "planned_qty": planned_qty, "projected_qty": projected_qty, }, + update_modified=True, ) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 50309647de..9ca40c3675 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -1053,7 +1053,7 @@ class update_entries_after(object): updated_values = {"actual_qty": data.qty_after_transaction, "stock_value": data.stock_value} if data.valuation_rate is not None: updated_values["valuation_rate"] = data.valuation_rate - frappe.db.set_value("Bin", bin_name, updated_values) + frappe.db.set_value("Bin", bin_name, updated_values, update_modified=True) def get_previous_sle_of_current_voucher(args, exclude_current_voucher=False): diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv index 7989bf7ebc..3ba5ade629 100644 --- a/erpnext/translations/fr.csv +++ b/erpnext/translations/fr.csv @@ -4946,7 +4946,7 @@ Min Amt,Montant Min, Max Amt,Montant Max, "If rate is zero them item will be treated as ""Free Item""",Si le prix est à 0 alors l'article sera traité comme article gratuit Is Recursive,Est récursif -"Discounts to be applied in sequential ranges like buy 1 get 1, buy 2 get 2, buy 3 get 3 and so on",La remise sera appliquée séquentiellement telque : acheter 1 => recupérer 1, acheter 2 => recupérer 2, acheter 3 => recupérer 3, etc... +"Discounts to be applied in sequential ranges like buy 1 get 1, buy 2 get 2, buy 3 get 3 and so on","La remise sera appliquée séquentiellement telque : acheter 1 => recupérer 1, acheter 2 => recupérer 2, acheter 3 => recupérer 3, etc..." Period Settings,Paramètres de période, Margin,Marge, Margin Type,Type de Marge, From abf5b6be3ea13f0d00664e25e7b1742429d4f5e2 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 7 Oct 2022 14:04:36 +0530 Subject: [PATCH 53/54] fix: Tax withholding related fixes --- .../tax_withholding_category/tax_withholding_category.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index 84c2c9a3c3..61f52a18aa 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -425,7 +425,10 @@ def get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers): ): # Get net total again as TDS is calculated on net total # Grand is used to just check for threshold breach - net_total = frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(net_total)") or 0.0 + net_total = 0 + if vouchers: + net_total = frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(net_total)") + net_total += inv.net_total supp_credit_amt = net_total - cumulative_threshold From 781d160c684f9c04b1c799449e484abff3e07d8a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 7 Oct 2022 14:22:40 +0530 Subject: [PATCH 54/54] fix: Do not add tax withheld vouchers post tax withheding in one document --- .../accounts/doctype/purchase_invoice/purchase_invoice.json | 3 ++- .../tax_withholding_category/tax_withholding_category.py | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 3020e6dc6e..1e477776e2 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -1430,6 +1430,7 @@ "fieldname": "tax_withheld_vouchers", "fieldtype": "Table", "label": "Tax Withheld Vouchers", + "no_copy": 1, "options": "Tax Withheld Vouchers", "read_only": 1 } @@ -1438,7 +1439,7 @@ "idx": 204, "is_submittable": 1, "links": [], - "modified": "2022-09-27 11:07:55.766844", + "modified": "2022-10-07 14:19:14.214157", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index 61f52a18aa..7eddd81ee0 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -249,6 +249,9 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N ) else: tax_amount = net_total * tax_details.rate / 100 if net_total > 0 else 0 + + # once tds is deducted, not need to add vouchers in the invoice + voucher_wise_amount = {} else: tax_amount = get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers)