diff --git a/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py b/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py index 8e58d79b928..37dbd728636 100644 --- a/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py +++ b/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py @@ -10,15 +10,17 @@ def execute(): purchase_invoices = frappe.db.sql( """ select - parenttype as type, parent as name + PI.company, PI_ADV.parenttype as type, PI_ADV.parent as name from - `tabPurchase Invoice Advance` + `tabPurchase Invoice Advance` as PI_ADV join `tabPurchase Invoice` as PI + on + PI_ADV.parent = PI.name where - ref_exchange_rate = 1 - and docstatus = 1 - and ifnull(exchange_gain_loss, 0) != 0 + PI_ADV.ref_exchange_rate = 1 + and PI_ADV.docstatus = 1 + and ifnull(PI_ADV.exchange_gain_loss, 0) != 0 group by - parent + PI_ADV.parent """, as_dict=1, ) @@ -26,15 +28,17 @@ def execute(): sales_invoices = frappe.db.sql( """ select - parenttype as type, parent as name + SI.company, SI_ADV.parenttype as type, SI_ADV.parent as name from - `tabSales Invoice Advance` + `tabSales Invoice Advance` as SI_ADV join `tabSales Invoice` as SI + on + SI_ADV.parent = SI.name where - ref_exchange_rate = 1 - and docstatus = 1 - and ifnull(exchange_gain_loss, 0) != 0 + SI_ADV.ref_exchange_rate = 1 + and SI_ADV.docstatus = 1 + and ifnull(SI_ADV.exchange_gain_loss, 0) != 0 group by - parent + SI_ADV.parent """, as_dict=1, ) @@ -45,11 +49,21 @@ def execute(): message=json.dumps(purchase_invoices + sales_invoices, indent=2), ) - acc_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto") - if acc_frozen_upto: - frappe.db.set_single_value("Accounts Settings", "acc_frozen_upto", None) + original_frozen_dates = {} for invoice in purchase_invoices + sales_invoices: + company = invoice.company + + # Unfreeze only once per company + if company not in original_frozen_dates: + accounts_frozen_till_date = frappe.get_cached_value( + "Company", company, "accounts_frozen_till_date" + ) + original_frozen_dates[company] = accounts_frozen_till_date + + if accounts_frozen_till_date: + frappe.db.set_value("Company", company, "accounts_frozen_till_date", None) + try: doc = frappe.get_doc(invoice.type, invoice.name) doc.docstatus = 2 @@ -64,5 +78,6 @@ def execute(): frappe.db.rollback() print(f"Failed to correct gl entries of {invoice.name}") - if acc_frozen_upto: - frappe.db.set_single_value("Accounts Settings", "acc_frozen_upto", acc_frozen_upto) + for company, frozen_date in original_frozen_dates.items(): + if frozen_date: + frappe.db.set_value("Company", company, "accounts_frozen_till_date", frozen_date) diff --git a/erpnext/patches/v14_0/single_to_multi_dunning.py b/erpnext/patches/v14_0/single_to_multi_dunning.py index 3def5922c07..f3d514a61a1 100644 --- a/erpnext/patches/v14_0/single_to_multi_dunning.py +++ b/erpnext/patches/v14_0/single_to_multi_dunning.py @@ -9,43 +9,47 @@ def execute(): # Migrate schema of all uncancelled dunnings filters = {"docstatus": ("!=", 2)} + for company in frappe.get_all("Company", pluck="name"): + filters["company"] = company + can_edit_accounts_after = get_accounts_closing_date(company) + if can_edit_accounts_after: + # Get dunnings after the date when accounts were frozen/closed + filters["posting_date"] = (">", can_edit_accounts_after) - can_edit_accounts_after = get_accounts_closing_date() - if can_edit_accounts_after: - # Get dunnings after the date when accounts were frozen/closed - filters["posting_date"] = (">", can_edit_accounts_after) + all_dunnings = frappe.get_all("Dunning", filters=filters, pluck="name") - all_dunnings = frappe.get_all("Dunning", filters=filters, pluck="name") + for dunning_name in all_dunnings: + dunning = frappe.get_doc("Dunning", dunning_name) + if not dunning.sales_invoice: + # nothing we can do + continue - for dunning_name in all_dunnings: - dunning = frappe.get_doc("Dunning", dunning_name) - if not dunning.sales_invoice: - # nothing we can do - continue + if dunning.overdue_payments: + # something's already here, doesn't need patching + continue - if dunning.overdue_payments: - # something's already here, doesn't need patching - continue + payment_schedules = frappe.get_all( + "Payment Schedule", + filters={"parent": dunning.sales_invoice}, + fields=[ + "parent as sales_invoice", + "name as payment_schedule", + "payment_term", + "due_date", + "invoice_portion", + "payment_amount", + # at the time of creating this dunning, the full amount was outstanding + "payment_amount as outstanding", + "'0' as paid_amount", + "discounted_amount", + ], + ) - payment_schedules = frappe.get_all( - "Payment Schedule", - filters={"parent": dunning.sales_invoice}, - fields=[ - "parent as sales_invoice", - "name as payment_schedule", - "payment_term", - "due_date", - "invoice_portion", - "payment_amount", - # at the time of creating this dunning, the full amount was outstanding - "payment_amount as outstanding", - "'0' as paid_amount", - "discounted_amount", - ], - ) + dunning.extend("overdue_payments", payment_schedules) + dunning.validate() - dunning.extend("overdue_payments", payment_schedules) - dunning.validate() + dunning.flags.ignore_validate_update_after_submit = True + dunning.save() dunning.flags.ignore_validate_update_after_submit = True dunning.flags.ignore_links = True @@ -60,20 +64,21 @@ def execute(): make_reverse_gl_entries(voucher_type="Dunning", voucher_no=dunning.name) -def get_accounts_closing_date(): +def get_accounts_closing_date(company): """Get the date when accounts were frozen/closed""" - accounts_frozen_till = frappe.db.get_single_value( - "Accounts Settings", "acc_frozen_upto" - ) # always returns datetime.date + accounts_frozen_till_date = frappe.db.get_value("Company", company, "accounts_frozen_till_date") period_closing_date = frappe.db.get_value( - "Period Closing Voucher", {"docstatus": 1}, "period_end_date", order_by="period_end_date desc" + "Period Closing Voucher", + {"docstatus": 1, "company": company}, + "period_end_date", + order_by="period_end_date desc", ) # Set most recent frozen/closing date as filter - if accounts_frozen_till and period_closing_date: - can_edit_accounts_after = max(accounts_frozen_till, period_closing_date) + if accounts_frozen_till_date and period_closing_date: + can_edit_accounts_after = max(accounts_frozen_till_date, period_closing_date) else: - can_edit_accounts_after = accounts_frozen_till or period_closing_date + can_edit_accounts_after = accounts_frozen_till_date or period_closing_date return can_edit_accounts_after diff --git a/erpnext/patches/v15_0/recalculate_amount_difference_field.py b/erpnext/patches/v15_0/recalculate_amount_difference_field.py index d7b56c206d2..f3cece4c416 100644 --- a/erpnext/patches/v15_0/recalculate_amount_difference_field.py +++ b/erpnext/patches/v15_0/recalculate_amount_difference_field.py @@ -58,9 +58,9 @@ def execute(): ): posting_date = period_closing_voucher[0].period_end_date - acc_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto") - if acc_frozen_upto and getdate(acc_frozen_upto) > getdate(posting_date): - posting_date = acc_frozen_upto + acc_frozen_till_date = frappe.db.get_value("Company", company, "accounts_frozen_till_date") + if acc_frozen_till_date and getdate(acc_frozen_till_date) > getdate(posting_date): + posting_date = acc_frozen_till_date stock_frozen_upto = frappe.db.get_single_value("Stock Settings", "stock_frozen_upto") if stock_frozen_upto and getdate(stock_frozen_upto) > getdate(posting_date): 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 b7802290262..2fbe92a4c17 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -159,16 +159,19 @@ class RepostItemValuation(Document): return query[0][0] if query and query[0][0] else None def validate_accounts_freeze(self): - acc_settings = frappe.get_cached_doc("Accounts Settings") - if not acc_settings.acc_frozen_upto: + acc_frozen_till_date = frappe.db.get_value("Company", self.company, "accounts_frozen_till_date") + frozen_accounts_modifier = frappe.db.get_value( + "Company", self.company, "role_allowed_for_frozen_entries" + ) + if not acc_frozen_till_date: 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 + if getdate(self.posting_date) <= getdate(acc_frozen_till_date): + if frozen_accounts_modifier and frappe.session.user in get_users_with_role( + 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)) + frappe.throw(_("You cannot repost item valuation before {}").format(acc_frozen_till_date)) def reset_field_values(self): if self.based_on == "Transaction":