diff --git a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js index 88f1c9069c82..5ebdf61db2ce 100644 --- a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js +++ b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js @@ -2,6 +2,21 @@ // For license information, please see license.txt frappe.ui.form.on("Journal Entry Template", { + onload: function(frm) { + if(frm.is_new()) { + frappe.call({ + type: "GET", + method: "erpnext.accounts.doctype.journal_entry_template.journal_entry_template.get_naming_series", + callback: function(r){ + if(r.message) { + frm.set_df_property("naming_series", "options", r.message.split("\n")); + frm.set_value("naming_series", r.message.split("\n")[0]); + frm.refresh_field("naming_series"); + } + } + }); + } + }, refresh: function(frm) { frappe.model.set_default_values(frm.doc); @@ -19,18 +34,6 @@ frappe.ui.form.on("Journal Entry Template", { return { filters: filters }; }); - - frappe.call({ - type: "GET", - method: "erpnext.accounts.doctype.journal_entry_template.journal_entry_template.get_naming_series", - callback: function(r){ - if(r.message){ - frm.set_df_property("naming_series", "options", r.message.split("\n")); - frm.set_value("naming_series", r.message.split("\n")[0]); - frm.refresh_field("naming_series"); - } - } - }); }, voucher_type: function(frm) { var add_accounts = function(doc, r) { diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index f959a4508d42..82f993910453 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1855,7 +1855,10 @@ def get_payment_entry( ): reference_doc = None doc = frappe.get_doc(dt, dn) - if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) >= 99.99: + over_billing_allowance = frappe.db.get_single_value("Accounts Settings", "over_billing_allowance") + if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) >= ( + 100.0 + over_billing_allowance + ): frappe.throw(_("Can only make payment against unbilled {0}").format(dt)) party_type = set_party_type(dt) diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 2a3fbc9bdd7f..d61330e0cfb6 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -524,11 +524,22 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters): additional_conditions.append("cost_center in %(cost_center)s") if filters.get("include_default_book_entries"): - additional_conditions.append( - "(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)" - ) + if filters.get("finance_book"): + if filters.get("company_fb") and cstr(filters.get("finance_book")) != cstr( + filters.get("company_fb") + ): + frappe.throw( + _("To use a different finance book, please uncheck 'Include Default Book Entries'") + ) + else: + additional_conditions.append("(finance_book in (%(finance_book)s) OR finance_book IS NULL)") + else: + additional_conditions.append("(finance_book in (%(company_fb)s) OR finance_book IS NULL)") else: - additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)") + if filters.get("finance_book"): + additional_conditions.append("(finance_book in (%(finance_book)s) OR finance_book IS NULL)") + else: + additional_conditions.append("(finance_book IS NULL)") if accounting_dimensions: for dimension in accounting_dimensions: diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index 2100f26c1ec8..57a9091cf9ba 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -176,7 +176,8 @@ frappe.query_reports["General Ledger"] = { { "fieldname": "include_default_book_entries", "label": __("Include Default Book Entries"), - "fieldtype": "Check" + "fieldtype": "Check", + "default": 1 }, { "fieldname": "show_cancelled_entries", diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 33d46bc901da..34534f883ed0 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -287,13 +287,23 @@ def get_conditions(filters): if filters.get("project"): conditions.append("project in %(project)s") - if filters.get("finance_book"): - if filters.get("include_default_book_entries"): - conditions.append( - "(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)" - ) + if filters.get("include_default_book_entries"): + if filters.get("finance_book"): + if filters.get("company_fb") and cstr(filters.get("finance_book")) != cstr( + filters.get("company_fb") + ): + frappe.throw( + _("To use a different finance book, please uncheck 'Include Default Book Entries'") + ) + else: + conditions.append("(finance_book in (%(finance_book)s) OR finance_book IS NULL)") + else: + conditions.append("(finance_book in (%(company_fb)s) OR finance_book IS NULL)") + else: + if filters.get("finance_book"): + conditions.append("(finance_book in (%(finance_book)s) OR finance_book IS NULL)") else: - conditions.append("finance_book in (%(finance_book)s)") + conditions.append("(finance_book IS NULL)") if not filters.get("show_cancelled_entries"): conditions.append("is_cancelled = 0") diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 61bc58009a6f..d2300cd12389 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -157,12 +157,23 @@ def get_rootwise_opening_balances(filters, report_type): if filters.project: additional_conditions += " and project = %(project)s" + company_fb = frappe.db.get_value("Company", filters.company, "default_finance_book") + if filters.get("include_default_book_entries"): - additional_conditions += ( - " AND (finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)" - ) + if filters.get("finance_book"): + if company_fb and cstr(filters.get("finance_book")) != cstr(company_fb): + frappe.throw( + _("To use a different finance book, please uncheck 'Include Default Book Entries'") + ) + else: + additional_conditions += " AND (finance_book in (%(finance_book)s) OR finance_book IS NULL)" + else: + additional_conditions += " AND (finance_book in (%(company_fb)s) OR finance_book IS NULL)" else: - additional_conditions += " AND (finance_book in (%(finance_book)s, '') OR finance_book IS NULL)" + if filters.get("finance_book"): + additional_conditions += " AND (finance_book in (%(finance_book)s) OR finance_book IS NULL)" + else: + additional_conditions += " AND (finance_book IS NULL)" accounting_dimensions = get_accounting_dimensions(as_list=False) @@ -174,7 +185,7 @@ def get_rootwise_opening_balances(filters, report_type): "year_start_date": filters.year_start_date, "project": filters.project, "finance_book": filters.finance_book, - "company_fb": frappe.db.get_value("Company", filters.company, "default_finance_book"), + "company_fb": company_fb, } if accounting_dimensions: diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py index 710c6cfacf32..f63773a8b7f0 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py @@ -119,7 +119,9 @@ def reschedule_depreciations(self, asset_value): if d.depreciation_method in ("Straight Line", "Manual"): end_date = max(s.schedule_date for s in asset.schedules if cint(s.finance_book_id) == d.idx) total_days = date_diff(end_date, self.date) - rate_per_day = flt(d.value_after_depreciation) / flt(total_days) + rate_per_day = flt(d.value_after_depreciation - d.expected_value_after_useful_life) / flt( + total_days + ) from_date = self.date else: no_of_depreciations = len( diff --git a/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py b/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py index de96a6c03232..38e05852ee8d 100644 --- a/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py +++ b/erpnext/manufacturing/report/quality_inspection_summary/quality_inspection_summary.py @@ -69,7 +69,7 @@ def get_columns(filters): "label": _("Id"), "fieldname": "name", "fieldtype": "Link", - "options": "Work Order", + "options": "Quality Inspection", "width": 100, }, {"label": _("Report Date"), "fieldname": "report_date", "fieldtype": "Date", "width": 150}, diff --git a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json index 5a7de37becbb..66070d02e5e9 100644 --- a/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json +++ b/erpnext/payroll/doctype/income_tax_slab/income_tax_slab.json @@ -67,7 +67,6 @@ "label": "Disabled" }, { - "depends_on": "allow_tax_exemption", "fieldname": "standard_tax_exemption_amount", "fieldtype": "Currency", "label": "Standard Tax Exemption Amount", @@ -104,7 +103,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2021-03-31 22:42:08.139520", + "modified": "2023-05-01 13:42:08.139520", "modified_by": "Administrator", "module": "Payroll", "name": "Income Tax Slab", diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py index a3ec0386ad59..d141ac68e21f 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py @@ -1331,6 +1331,7 @@ def get_total_exemption_amount(self, payroll_period, tax_slab): if declaration: total_exemption_amount = declaration + if tax_slab.standard_tax_exemption_amount: total_exemption_amount += flt(tax_slab.standard_tax_exemption_amount) return total_exemption_amount 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 14f5e548eccf..e197f302901d 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -5,7 +5,8 @@ from frappe import _ from frappe.exceptions import QueryDeadlockError, QueryTimeoutError from frappe.model.document import Document -from frappe.utils import cint, get_link_to_form, get_weekday, now, nowtime +from frappe.query_builder.functions import Max +from frappe.utils import cint, get_link_to_form, get_weekday, getdate, now, nowtime from frappe.utils.user import get_users_with_role from rq.timeouts import JobTimeoutException @@ -22,9 +23,57 @@ class RepostItemValuation(Document): def validate(self): + self.validate_period_closing_voucher() self.set_status(write=False) self.reset_field_values() self.set_company() + self.validate_accounts_freeze() + + def validate_period_closing_voucher(self): + year_end_date = self.get_max_year_end_date(self.company) + if year_end_date and getdate(self.posting_date) <= getdate(year_end_date): + msg = f"Due to period closing, you cannot repost item valuation before {year_end_date}" + frappe.throw(_(msg)) + + @staticmethod + def get_max_year_end_date(company): + data = frappe.get_all( + "Period Closing Voucher", fields=["fiscal_year"], filters={"docstatus": 1, "company": company} + ) + + if not data: + return + + fiscal_years = [d.fiscal_year for d in data] + table = frappe.qb.DocType("Fiscal Year") + + query = ( + frappe.qb.from_(table) + .select(Max(table.year_end_date)) + .where((table.name.isin(fiscal_years)) & (table.disabled == 0)) + ).run() + + return query[0][0] if query else None + + def validate_accounts_freeze(self): + acc_settings = frappe.db.get_value( + "Accounts Settings", + "Accounts Settings", + ["acc_frozen_upto", "frozen_accounts_modifier"], + as_dict=1, + ) + if not acc_settings.acc_frozen_upto: + return + if getdate(self.posting_date) <= getdate(acc_settings.acc_frozen_upto): + if ( + acc_settings.frozen_accounts_modifier + and frappe.session.user in get_users_with_role(acc_settings.frozen_accounts_modifier) + ): + frappe.msgprint(_("Caution: This might alter frozen accounts.")) + return + frappe.throw( + _("You cannot repost item valuation before {}").format(acc_settings.acc_frozen_upto) + ) def reset_field_values(self): if self.based_on == "Transaction": @@ -235,7 +284,7 @@ def _get_directly_dependent_vouchers(doc): def notify_error_to_stock_managers(doc, traceback): recipients = get_users_with_role("Stock Manager") if not recipients: - get_users_with_role("System Manager") + recipients = get_users_with_role("System Manager") subject = _("Error while reposting item valuation") message = ( diff --git a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py index edd2553d5d14..b9e2ed1beb96 100644 --- a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py @@ -272,3 +272,25 @@ def test_gl_complete_gl_reposting(self): [{"credit": 50, "debit": 0}], gle_filters={"account": "Stock In Hand - TCP1"}, ) + + def test_account_freeze_validation(self): + today = nowdate() + + riv = frappe.get_doc( + doctype="Repost Item Valuation", + item_code="_Test Item", + warehouse="_Test Warehouse - _TC", + based_on="Item and Warehouse", + posting_date=today, + posting_time="00:01:00", + ) + riv.flags.dont_run_in_test = True # keep it queued + + accounts_settings = frappe.get_doc("Accounts Settings") + accounts_settings.acc_frozen_upto = today + accounts_settings.frozen_accounts_modifier = "" + accounts_settings.save() + + self.assertRaises(frappe.ValidationError, riv.save) + accounts_settings.acc_frozen_upto = "" + accounts_settings.save()