Skip to content

Commit

Permalink
refactor: allow users to configure interval for Semi-Auto payment rec…
Browse files Browse the repository at this point in the history
…onciliation (#45211)

* refactor: configurable interval for reconciliation trigger

* refactor: set default value for interval

* refactor: configurable queue size

* refactor: use patch to setup default cron job

* refactor: use 'after_migrate' to setup cron for reconciliation

User specified interval will be used

* chore: type casting

* refactor: use scheduler_event to persist cron

* chore: rename field

* chore: use configured queue size

* chore: remove unwanted field
  • Loading branch information
ruthra-kumar authored Jan 14, 2025
1 parent aea69af commit ce9c606
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 4 deletions.
30 changes: 28 additions & 2 deletions erpnext/accounts/doctype/accounts_settings/accounts_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@
"show_payment_schedule_in_print",
"currency_exchange_section",
"allow_stale",
"column_break_yuug",
"stale_days",
"section_break_jpd0",
"auto_reconcile_payments",
"stale_days",
"auto_reconciliation_job_trigger",
"reconciliation_queue_size",
"column_break_resa",
"invoicing_settings_tab",
"accounts_transactions_settings_section",
"over_billing_allowance",
Expand Down Expand Up @@ -489,14 +493,36 @@
"fieldname": "create_pr_in_draft_status",
"fieldtype": "Check",
"label": "Create in Draft Status"
},
{
"fieldname": "column_break_yuug",
"fieldtype": "Column Break"
},
{
"fieldname": "column_break_resa",
"fieldtype": "Column Break"
},
{
"default": "15",
"description": "Interval should be between 1 to 59 MInutes",
"fieldname": "auto_reconciliation_job_trigger",
"fieldtype": "Int",
"label": "Auto Reconciliation Job Trigger"
},
{
"default": "5",
"description": "Documents Processed on each trigger. Queue Size should be between 5 and 100",
"fieldname": "reconciliation_queue_size",
"fieldtype": "Int",
"label": "Reconciliation Queue Size"
}
],
"icon": "icon-cog",
"idx": 1,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2024-07-26 06:48:52.714630",
"modified": "2025-01-13 17:38:39.661320",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
Expand Down
19 changes: 19 additions & 0 deletions erpnext/accounts/doctype/accounts_settings/accounts_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from frappe.model.document import Document
from frappe.utils import cint

from erpnext.accounts.utils import sync_auto_reconcile_config
from erpnext.stock.utils import check_pending_reposting


Expand All @@ -27,6 +28,7 @@ class AccountsSettings(Document):
allow_multi_currency_invoices_against_single_party_account: DF.Check
allow_stale: DF.Check
auto_reconcile_payments: DF.Check
auto_reconciliation_job_trigger: DF.Int
automatically_fetch_payment_terms: DF.Check
automatically_process_deferred_accounting_entry: DF.Check
book_asset_depreciation_entry_automatically: DF.Check
Expand All @@ -51,6 +53,7 @@ class AccountsSettings(Document):
over_billing_allowance: DF.Currency
post_change_gl_entries: DF.Check
receivable_payable_remarks_length: DF.Int
reconciliation_queue_size: DF.Int
role_allowed_to_over_bill: DF.Link | None
round_row_wise_tax: DF.Check
show_balance_in_coa: DF.Check
Expand Down Expand Up @@ -90,6 +93,8 @@ def validate(self):
if clear_cache:
frappe.clear_cache()

self.validate_and_sync_auto_reconcile_config()

def validate_stale_days(self):
if not self.allow_stale and cint(self.stale_days) <= 0:
frappe.msgprint(
Expand All @@ -114,3 +119,17 @@ def enable_payment_schedule_in_print(self):
def validate_pending_reposts(self):
if self.acc_frozen_upto:
check_pending_reposting(self.acc_frozen_upto)

def validate_and_sync_auto_reconcile_config(self):
if self.has_value_changed("auto_reconciliation_job_trigger"):
if (
cint(self.auto_reconciliation_job_trigger) > 0
and cint(self.auto_reconciliation_job_trigger) < 60
):
sync_auto_reconcile_config(self.auto_reconciliation_job_trigger)
else:
frappe.throw(_("Cron Interval should be between 1 and 59 Min"))

if self.has_value_changed("reconciliation_queue_size"):
if cint(self.reconciliation_queue_size) < 5 or cint(self.reconciliation_queue_size) > 100:
frappe.throw(_("Queue Size should be between 5 and 100"))
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ def trigger_reconciliation_for_queued_docs():

docs_to_trigger = []
unique_filters = set()
queue_size = 5
queue_size = frappe.db.get_single_value("Accounts Settings", "reconciliation_queue_size") or 5

fields = ["company", "party_type", "party", "receivable_payable_account", "default_advance_account"]

Expand Down
35 changes: 35 additions & 0 deletions erpnext/accounts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2284,3 +2284,38 @@ def run_ledger_health_checks():
doc.general_and_payment_ledger_mismatch = True
doc.checked_on = run_date
doc.save()


def sync_auto_reconcile_config(auto_reconciliation_job_trigger: int = 15):
auto_reconciliation_job_trigger = auto_reconciliation_job_trigger or frappe.db.get_single_value(
"Accounts Settings", "auto_reconciliation_job_trigger"
)
method = "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.trigger_reconciliation_for_queued_docs"

sch_event = frappe.get_doc(
"Scheduler Event", {"scheduled_against": "Process Payment Reconciliation", "method": method}
)
if frappe.db.get_value("Scheduled Job Type", {"method": method}):
frappe.get_doc(
"Scheduled Job Type",
{
"method": method,
},
).update(
{
"cron_format": f"0/{auto_reconciliation_job_trigger} * * * *",
"scheduler_event": sch_event.name,
}
).save()
else:
frappe.get_doc(
{
"doctype": "Scheduled Job Type",
"method": method,
"scheduler_event": sch_event.name,
"cron_format": f"0/{auto_reconciliation_job_trigger} * * * *",
"create_log": True,
"stopped": False,
"frequency": "Cron",
}
).save()
1 change: 0 additions & 1 deletion erpnext/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,6 @@
"cron": {
"0/15 * * * *": [
"erpnext.manufacturing.doctype.bom_update_log.bom_update_log.resume_bom_cost_update_jobs",
"erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.trigger_reconciliation_for_queued_docs",
],
"0/30 * * * *": [
"erpnext.utilities.doctype.video.video.update_youtube_data",
Expand Down
1 change: 1 addition & 0 deletions erpnext/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,4 @@ erpnext.patches.v15_0.update_cc_in_process_statement_of_accounts
erpnext.patches.v15_0.refactor_closing_stock_balance #5
erpnext.patches.v15_0.update_asset_status_to_work_in_progress
erpnext.patches.v15_0.migrate_checkbox_to_select_for_reconciliation_effect
erpnext.patches.v15_0.sync_auto_reconcile_config
26 changes: 26 additions & 0 deletions erpnext/patches/v15_0/sync_auto_reconcile_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import frappe

from erpnext.accounts.utils import sync_auto_reconcile_config


def execute():
"""
Set default Cron Interval and Queue size
"""
frappe.db.set_single_value("Accounts Settings", "auto_reconciliation_job_trigger", 15)
frappe.db.set_single_value("Accounts Settings", "reconciliation_queue_size", 5)

# Create Scheduler Event record if it doesn't exist
method = "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.trigger_reconciliation_for_queued_docs"
if not frappe.db.get_all(
"Scheduler Event", {"scheduled_against": "Process Payment Reconciliation", "method": method}
):
frappe.get_doc(
{
"doctype": "Scheduler Event",
"scheduled_against": "Process Payment Reconciliation",
"method": method,
}
).save()

sync_auto_reconcile_config(15)

0 comments on commit ce9c606

Please sign in to comment.