mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-31 19:02:21 +02:00
perf: asset depreciation entry posting (#36461)
* perf: make post depr entries job daily_long * perf: optimise post_depreciation_entries and make_depreciation_entry * chore: more optimisation and dont fail all schedule dates if one date fails * chore: don't post entries before acc_frozen_upto * chore: using get_single_value * refactor: destructure asset object
This commit is contained in:
@@ -962,7 +962,9 @@ class Asset(AccountsController):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_manual_depreciation_entries(self):
|
def get_manual_depreciation_entries(self):
|
||||||
(_, _, depreciation_expense_account) = get_depreciation_accounts(self)
|
(_, _, depreciation_expense_account) = get_depreciation_accounts(
|
||||||
|
self.asset_category, self.company
|
||||||
|
)
|
||||||
|
|
||||||
gle = frappe.qb.DocType("GL Entry")
|
gle = frappe.qb.DocType("GL Entry")
|
||||||
|
|
||||||
@@ -1201,10 +1203,10 @@ def get_asset_account(account_name, asset=None, asset_category=None, company=Non
|
|||||||
def make_journal_entry(asset_name):
|
def make_journal_entry(asset_name):
|
||||||
asset = frappe.get_doc("Asset", asset_name)
|
asset = frappe.get_doc("Asset", asset_name)
|
||||||
(
|
(
|
||||||
fixed_asset_account,
|
_,
|
||||||
accumulated_depreciation_account,
|
accumulated_depreciation_account,
|
||||||
depreciation_expense_account,
|
depreciation_expense_account,
|
||||||
) = get_depreciation_accounts(asset)
|
) = get_depreciation_accounts(asset.asset_category, asset.company)
|
||||||
|
|
||||||
depreciation_cost_center, depreciation_series = frappe.get_cached_value(
|
depreciation_cost_center, depreciation_series = frappe.get_cached_value(
|
||||||
"Company", asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]
|
"Company", asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
from frappe.query_builder import Order
|
||||||
|
from frappe.query_builder.functions import Max, Min
|
||||||
from frappe.utils import (
|
from frappe.utils import (
|
||||||
add_months,
|
add_months,
|
||||||
cint,
|
cint,
|
||||||
@@ -36,9 +38,40 @@ def post_depreciation_entries(date=None):
|
|||||||
failed_asset_names = []
|
failed_asset_names = []
|
||||||
error_log_names = []
|
error_log_names = []
|
||||||
|
|
||||||
for asset_name in get_depreciable_assets(date):
|
depreciable_assets = get_depreciable_assets(date)
|
||||||
|
|
||||||
|
credit_and_debit_accounts_for_asset_category_and_company = {}
|
||||||
|
depreciation_cost_center_and_depreciation_series_for_company = (
|
||||||
|
get_depreciation_cost_center_and_depreciation_series_for_company()
|
||||||
|
)
|
||||||
|
|
||||||
|
accounting_dimensions = get_checks_for_pl_and_bs_accounts()
|
||||||
|
|
||||||
|
for asset in depreciable_assets:
|
||||||
|
asset_name, asset_category, asset_company, sch_start_idx, sch_end_idx = asset
|
||||||
|
|
||||||
|
if (
|
||||||
|
asset_category,
|
||||||
|
asset_company,
|
||||||
|
) not in credit_and_debit_accounts_for_asset_category_and_company:
|
||||||
|
credit_and_debit_accounts_for_asset_category_and_company.update(
|
||||||
|
{
|
||||||
|
(asset_category, asset_company): get_credit_and_debit_accounts_for_asset_category_and_company(
|
||||||
|
asset_category, asset_company
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
make_depreciation_entry(asset_name, date)
|
make_depreciation_entry(
|
||||||
|
asset_name,
|
||||||
|
date,
|
||||||
|
sch_start_idx,
|
||||||
|
sch_end_idx,
|
||||||
|
credit_and_debit_accounts_for_asset_category_and_company[(asset_category, asset_company)],
|
||||||
|
depreciation_cost_center_and_depreciation_series_for_company[asset_company],
|
||||||
|
accounting_dimensions,
|
||||||
|
)
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
frappe.db.rollback()
|
frappe.db.rollback()
|
||||||
@@ -54,115 +87,226 @@ def post_depreciation_entries(date=None):
|
|||||||
|
|
||||||
|
|
||||||
def get_depreciable_assets(date):
|
def get_depreciable_assets(date):
|
||||||
return frappe.db.sql_list(
|
a = frappe.qb.DocType("Asset")
|
||||||
"""select distinct a.name
|
ds = frappe.qb.DocType("Depreciation Schedule")
|
||||||
from tabAsset a, `tabDepreciation Schedule` ds
|
|
||||||
where a.name = ds.parent and a.docstatus=1 and ds.schedule_date<=%s and a.calculate_depreciation = 1
|
res = (
|
||||||
and a.status in ('Submitted', 'Partially Depreciated')
|
frappe.qb.from_(a)
|
||||||
and ifnull(ds.journal_entry, '')=''""",
|
.join(ds)
|
||||||
date,
|
.on(a.name == ds.parent)
|
||||||
|
.select(a.name, a.asset_category, a.company, Min(ds.idx) - 1, Max(ds.idx))
|
||||||
|
.where(a.calculate_depreciation == 1)
|
||||||
|
.where(a.docstatus == 1)
|
||||||
|
.where(a.status.isin(["Submitted", "Partially Depreciated"]))
|
||||||
|
.where(ds.journal_entry.isnull())
|
||||||
|
.where(ds.schedule_date <= date)
|
||||||
|
.groupby(a.name)
|
||||||
|
.orderby(a.creation, order=Order.desc)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
acc_frozen_upto = get_acc_frozen_upto()
|
||||||
|
if acc_frozen_upto:
|
||||||
|
res = res.where(ds.schedule_date > acc_frozen_upto)
|
||||||
|
|
||||||
|
res = res.run()
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def get_acc_frozen_upto():
|
||||||
|
acc_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto")
|
||||||
|
|
||||||
|
if not acc_frozen_upto:
|
||||||
|
return
|
||||||
|
|
||||||
|
frozen_accounts_modifier = frappe.db.get_single_value(
|
||||||
|
"Accounts Settings", "frozen_accounts_modifier"
|
||||||
|
)
|
||||||
|
|
||||||
|
if frozen_accounts_modifier not in frappe.get_roles() or frappe.session.user == "Administrator":
|
||||||
|
return getdate(acc_frozen_upto)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def get_credit_and_debit_accounts_for_asset_category_and_company(asset_category, company):
|
||||||
|
(
|
||||||
|
_,
|
||||||
|
accumulated_depreciation_account,
|
||||||
|
depreciation_expense_account,
|
||||||
|
) = get_depreciation_accounts(asset_category, company)
|
||||||
|
|
||||||
|
credit_account, debit_account = get_credit_and_debit_accounts(
|
||||||
|
accumulated_depreciation_account, depreciation_expense_account
|
||||||
|
)
|
||||||
|
|
||||||
|
return (credit_account, debit_account)
|
||||||
|
|
||||||
|
|
||||||
|
def get_depreciation_cost_center_and_depreciation_series_for_company():
|
||||||
|
company_names = frappe.db.get_all("Company", pluck="name")
|
||||||
|
|
||||||
|
res = {}
|
||||||
|
|
||||||
|
for company_name in company_names:
|
||||||
|
depreciation_cost_center, depreciation_series = frappe.get_cached_value(
|
||||||
|
"Company", company_name, ["depreciation_cost_center", "series_for_depreciation_entry"]
|
||||||
|
)
|
||||||
|
res.update({company_name: (depreciation_cost_center, depreciation_series)})
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_depreciation_entry(asset_name, date=None):
|
def make_depreciation_entry(
|
||||||
|
asset_name,
|
||||||
|
date=None,
|
||||||
|
sch_start_idx=None,
|
||||||
|
sch_end_idx=None,
|
||||||
|
credit_and_debit_accounts=None,
|
||||||
|
depreciation_cost_center_and_depreciation_series=None,
|
||||||
|
accounting_dimensions=None,
|
||||||
|
):
|
||||||
frappe.has_permission("Journal Entry", throw=True)
|
frappe.has_permission("Journal Entry", throw=True)
|
||||||
|
|
||||||
if not date:
|
if not date:
|
||||||
date = today()
|
date = today()
|
||||||
|
|
||||||
asset = frappe.get_doc("Asset", asset_name)
|
asset = frappe.get_doc("Asset", asset_name)
|
||||||
(
|
|
||||||
fixed_asset_account,
|
|
||||||
accumulated_depreciation_account,
|
|
||||||
depreciation_expense_account,
|
|
||||||
) = get_depreciation_accounts(asset)
|
|
||||||
|
|
||||||
depreciation_cost_center, depreciation_series = frappe.get_cached_value(
|
if credit_and_debit_accounts:
|
||||||
"Company", asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]
|
credit_account, debit_account = credit_and_debit_accounts
|
||||||
)
|
else:
|
||||||
|
credit_account, debit_account = get_credit_and_debit_accounts_for_asset_category_and_company(
|
||||||
|
asset.asset_category, asset.company
|
||||||
|
)
|
||||||
|
|
||||||
|
if depreciation_cost_center_and_depreciation_series:
|
||||||
|
depreciation_cost_center, depreciation_series = depreciation_cost_center_and_depreciation_series
|
||||||
|
else:
|
||||||
|
depreciation_cost_center, depreciation_series = frappe.get_cached_value(
|
||||||
|
"Company", asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]
|
||||||
|
)
|
||||||
|
|
||||||
depreciation_cost_center = asset.cost_center or depreciation_cost_center
|
depreciation_cost_center = asset.cost_center or depreciation_cost_center
|
||||||
|
|
||||||
accounting_dimensions = get_checks_for_pl_and_bs_accounts()
|
if not accounting_dimensions:
|
||||||
|
accounting_dimensions = get_checks_for_pl_and_bs_accounts()
|
||||||
|
|
||||||
for d in asset.get("schedules"):
|
depreciation_posting_error = None
|
||||||
if not d.journal_entry and getdate(d.schedule_date) <= getdate(date):
|
|
||||||
je = frappe.new_doc("Journal Entry")
|
|
||||||
je.voucher_type = "Depreciation Entry"
|
|
||||||
je.naming_series = depreciation_series
|
|
||||||
je.posting_date = d.schedule_date
|
|
||||||
je.company = asset.company
|
|
||||||
je.finance_book = d.finance_book
|
|
||||||
je.remark = "Depreciation Entry against {0} worth {1}".format(asset_name, d.depreciation_amount)
|
|
||||||
|
|
||||||
credit_account, debit_account = get_credit_and_debit_accounts(
|
for d in asset.get("schedules")[sch_start_idx or 0 : sch_end_idx or len(asset.get("schedules"))]:
|
||||||
accumulated_depreciation_account, depreciation_expense_account
|
try:
|
||||||
|
_make_journal_entry_for_depreciation(
|
||||||
|
asset,
|
||||||
|
date,
|
||||||
|
d,
|
||||||
|
sch_start_idx,
|
||||||
|
sch_end_idx,
|
||||||
|
depreciation_cost_center,
|
||||||
|
depreciation_series,
|
||||||
|
credit_account,
|
||||||
|
debit_account,
|
||||||
|
accounting_dimensions,
|
||||||
)
|
)
|
||||||
|
frappe.db.commit()
|
||||||
credit_entry = {
|
except Exception as e:
|
||||||
"account": credit_account,
|
frappe.db.rollback()
|
||||||
"credit_in_account_currency": d.depreciation_amount,
|
depreciation_posting_error = e
|
||||||
"reference_type": "Asset",
|
|
||||||
"reference_name": asset.name,
|
|
||||||
"cost_center": depreciation_cost_center,
|
|
||||||
}
|
|
||||||
|
|
||||||
debit_entry = {
|
|
||||||
"account": debit_account,
|
|
||||||
"debit_in_account_currency": d.depreciation_amount,
|
|
||||||
"reference_type": "Asset",
|
|
||||||
"reference_name": asset.name,
|
|
||||||
"cost_center": depreciation_cost_center,
|
|
||||||
}
|
|
||||||
|
|
||||||
for dimension in accounting_dimensions:
|
|
||||||
if asset.get(dimension["fieldname"]) or dimension.get("mandatory_for_bs"):
|
|
||||||
credit_entry.update(
|
|
||||||
{
|
|
||||||
dimension["fieldname"]: asset.get(dimension["fieldname"])
|
|
||||||
or dimension.get("default_dimension")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if asset.get(dimension["fieldname"]) or dimension.get("mandatory_for_pl"):
|
|
||||||
debit_entry.update(
|
|
||||||
{
|
|
||||||
dimension["fieldname"]: asset.get(dimension["fieldname"])
|
|
||||||
or dimension.get("default_dimension")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
je.append("accounts", credit_entry)
|
|
||||||
|
|
||||||
je.append("accounts", debit_entry)
|
|
||||||
|
|
||||||
je.flags.ignore_permissions = True
|
|
||||||
je.flags.planned_depr_entry = True
|
|
||||||
je.save()
|
|
||||||
|
|
||||||
d.db_set("journal_entry", je.name)
|
|
||||||
|
|
||||||
if not je.meta.get_workflow():
|
|
||||||
je.submit()
|
|
||||||
idx = cint(d.finance_book_id)
|
|
||||||
finance_books = asset.get("finance_books")[idx - 1]
|
|
||||||
finance_books.value_after_depreciation -= d.depreciation_amount
|
|
||||||
finance_books.db_update()
|
|
||||||
|
|
||||||
asset.db_set("depr_entry_posting_status", "Successful")
|
|
||||||
|
|
||||||
asset.set_status()
|
asset.set_status()
|
||||||
|
|
||||||
return asset
|
if not depreciation_posting_error:
|
||||||
|
asset.db_set("depr_entry_posting_status", "Successful")
|
||||||
|
return asset
|
||||||
|
|
||||||
|
raise depreciation_posting_error
|
||||||
|
|
||||||
|
|
||||||
def get_depreciation_accounts(asset):
|
def _make_journal_entry_for_depreciation(
|
||||||
|
asset,
|
||||||
|
date,
|
||||||
|
depr_schedule,
|
||||||
|
sch_start_idx,
|
||||||
|
sch_end_idx,
|
||||||
|
depreciation_cost_center,
|
||||||
|
depreciation_series,
|
||||||
|
credit_account,
|
||||||
|
debit_account,
|
||||||
|
accounting_dimensions,
|
||||||
|
):
|
||||||
|
if not (sch_start_idx and sch_end_idx) and not (
|
||||||
|
not depr_schedule.journal_entry and getdate(depr_schedule.schedule_date) <= getdate(date)
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
|
je = frappe.new_doc("Journal Entry")
|
||||||
|
je.voucher_type = "Depreciation Entry"
|
||||||
|
je.naming_series = depreciation_series
|
||||||
|
je.posting_date = depr_schedule.schedule_date
|
||||||
|
je.company = asset.company
|
||||||
|
je.finance_book = depr_schedule.finance_book
|
||||||
|
je.remark = "Depreciation Entry against {0} worth {1}".format(
|
||||||
|
asset.name, depr_schedule.depreciation_amount
|
||||||
|
)
|
||||||
|
|
||||||
|
credit_entry = {
|
||||||
|
"account": credit_account,
|
||||||
|
"credit_in_account_currency": depr_schedule.depreciation_amount,
|
||||||
|
"reference_type": "Asset",
|
||||||
|
"reference_name": asset.name,
|
||||||
|
"cost_center": depreciation_cost_center,
|
||||||
|
}
|
||||||
|
|
||||||
|
debit_entry = {
|
||||||
|
"account": debit_account,
|
||||||
|
"debit_in_account_currency": depr_schedule.depreciation_amount,
|
||||||
|
"reference_type": "Asset",
|
||||||
|
"reference_name": asset.name,
|
||||||
|
"cost_center": depreciation_cost_center,
|
||||||
|
}
|
||||||
|
|
||||||
|
for dimension in accounting_dimensions:
|
||||||
|
if asset.get(dimension["fieldname"]) or dimension.get("mandatory_for_bs"):
|
||||||
|
credit_entry.update(
|
||||||
|
{
|
||||||
|
dimension["fieldname"]: asset.get(dimension["fieldname"])
|
||||||
|
or dimension.get("default_dimension")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if asset.get(dimension["fieldname"]) or dimension.get("mandatory_for_pl"):
|
||||||
|
debit_entry.update(
|
||||||
|
{
|
||||||
|
dimension["fieldname"]: asset.get(dimension["fieldname"])
|
||||||
|
or dimension.get("default_dimension")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
je.append("accounts", credit_entry)
|
||||||
|
|
||||||
|
je.append("accounts", debit_entry)
|
||||||
|
|
||||||
|
je.flags.ignore_permissions = True
|
||||||
|
je.flags.planned_depr_entry = True
|
||||||
|
je.save()
|
||||||
|
|
||||||
|
depr_schedule.db_set("journal_entry", je.name)
|
||||||
|
|
||||||
|
if not je.meta.get_workflow():
|
||||||
|
je.submit()
|
||||||
|
idx = cint(depr_schedule.finance_book_id)
|
||||||
|
finance_books = asset.get("finance_books")[idx - 1]
|
||||||
|
finance_books.value_after_depreciation -= depr_schedule.depreciation_amount
|
||||||
|
finance_books.db_update()
|
||||||
|
|
||||||
|
|
||||||
|
def get_depreciation_accounts(asset_category, company):
|
||||||
fixed_asset_account = accumulated_depreciation_account = depreciation_expense_account = None
|
fixed_asset_account = accumulated_depreciation_account = depreciation_expense_account = None
|
||||||
|
|
||||||
accounts = frappe.db.get_value(
|
accounts = frappe.db.get_value(
|
||||||
"Asset Category Account",
|
"Asset Category Account",
|
||||||
filters={"parent": asset.asset_category, "company_name": asset.company},
|
filters={"parent": asset_category, "company_name": company},
|
||||||
fieldname=[
|
fieldname=[
|
||||||
"fixed_asset_account",
|
"fixed_asset_account",
|
||||||
"accumulated_depreciation_account",
|
"accumulated_depreciation_account",
|
||||||
@@ -178,7 +322,7 @@ def get_depreciation_accounts(asset):
|
|||||||
|
|
||||||
if not accumulated_depreciation_account or not depreciation_expense_account:
|
if not accumulated_depreciation_account or not depreciation_expense_account:
|
||||||
accounts = frappe.get_cached_value(
|
accounts = frappe.get_cached_value(
|
||||||
"Company", asset.company, ["accumulated_depreciation_account", "depreciation_expense_account"]
|
"Company", company, ["accumulated_depreciation_account", "depreciation_expense_account"]
|
||||||
)
|
)
|
||||||
|
|
||||||
if not accumulated_depreciation_account:
|
if not accumulated_depreciation_account:
|
||||||
@@ -193,7 +337,7 @@ def get_depreciation_accounts(asset):
|
|||||||
):
|
):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Please set Depreciation related Accounts in Asset Category {0} or Company {1}").format(
|
_("Please set Depreciation related Accounts in Asset Category {0} or Company {1}").format(
|
||||||
asset.asset_category, asset.company
|
asset_category, company
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -533,8 +677,8 @@ def get_gl_entries_on_asset_disposal(
|
|||||||
|
|
||||||
|
|
||||||
def get_asset_details(asset, finance_book=None):
|
def get_asset_details(asset, finance_book=None):
|
||||||
fixed_asset_account, accumulated_depr_account, depr_expense_account = get_depreciation_accounts(
|
fixed_asset_account, accumulated_depr_account, _ = get_depreciation_accounts(
|
||||||
asset
|
asset.asset_category, asset.company
|
||||||
)
|
)
|
||||||
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(asset.company)
|
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(asset.company)
|
||||||
depreciation_cost_center = asset.cost_center or depreciation_cost_center
|
depreciation_cost_center = asset.cost_center or depreciation_cost_center
|
||||||
|
|||||||
@@ -50,10 +50,10 @@ class AssetValueAdjustment(Document):
|
|||||||
def make_depreciation_entry(self):
|
def make_depreciation_entry(self):
|
||||||
asset = frappe.get_doc("Asset", self.asset)
|
asset = frappe.get_doc("Asset", self.asset)
|
||||||
(
|
(
|
||||||
fixed_asset_account,
|
_,
|
||||||
accumulated_depreciation_account,
|
accumulated_depreciation_account,
|
||||||
depreciation_expense_account,
|
depreciation_expense_account,
|
||||||
) = get_depreciation_accounts(asset)
|
) = get_depreciation_accounts(asset.asset_category, asset.company)
|
||||||
|
|
||||||
depreciation_cost_center, depreciation_series = frappe.get_cached_value(
|
depreciation_cost_center, depreciation_series = frappe.get_cached_value(
|
||||||
"Company", asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]
|
"Company", asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]
|
||||||
|
|||||||
@@ -432,7 +432,6 @@ scheduler_events = {
|
|||||||
"erpnext.controllers.accounts_controller.update_invoice_status",
|
"erpnext.controllers.accounts_controller.update_invoice_status",
|
||||||
"erpnext.accounts.doctype.fiscal_year.fiscal_year.auto_create_fiscal_year",
|
"erpnext.accounts.doctype.fiscal_year.fiscal_year.auto_create_fiscal_year",
|
||||||
"erpnext.projects.doctype.task.task.set_tasks_as_overdue",
|
"erpnext.projects.doctype.task.task.set_tasks_as_overdue",
|
||||||
"erpnext.assets.doctype.asset.depreciation.post_depreciation_entries",
|
|
||||||
"erpnext.stock.doctype.serial_no.serial_no.update_maintenance_status",
|
"erpnext.stock.doctype.serial_no.serial_no.update_maintenance_status",
|
||||||
"erpnext.buying.doctype.supplier_scorecard.supplier_scorecard.refresh_scorecards",
|
"erpnext.buying.doctype.supplier_scorecard.supplier_scorecard.refresh_scorecards",
|
||||||
"erpnext.setup.doctype.company.company.cache_companies_monthly_sales_history",
|
"erpnext.setup.doctype.company.company.cache_companies_monthly_sales_history",
|
||||||
@@ -459,6 +458,7 @@ scheduler_events = {
|
|||||||
"erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall.create_process_loan_security_shortfall",
|
"erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall.create_process_loan_security_shortfall",
|
||||||
"erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
|
"erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
|
||||||
"erpnext.crm.utils.open_leads_opportunities_based_on_todays_event",
|
"erpnext.crm.utils.open_leads_opportunities_based_on_todays_event",
|
||||||
|
"erpnext.assets.doctype.asset.depreciation.post_depreciation_entries",
|
||||||
],
|
],
|
||||||
"monthly_long": [
|
"monthly_long": [
|
||||||
"erpnext.accounts.deferred_revenue.process_deferred_accounting",
|
"erpnext.accounts.deferred_revenue.process_deferred_accounting",
|
||||||
|
|||||||
Reference in New Issue
Block a user