fix(workspace): insert importer link into ERPNext Invoicing Banking card
Replaces the standalone Bank Statements workspace (incorrect approach — ERPNext doesn't expose top-level apps as tiles automatically) with a runtime insertion of a single 'Bank Statement Importer' link into the existing 'Banking' card on the ERPNext-owned Invoicing workspace. Editing the workspace at runtime via after_migrate (not by overriding its JSON) is intentional: ERPNext resyncs that JSON on every `bench migrate`, so a file-level patch would be reverted. after_migrate runs AFTER the resync, so the inserted link stays. The insert is idempotent — it skips when the link is already present, when the Banking card break isn't there, or when Bank Statement Importer DocType doesn't exist yet.
This commit is contained in:
parent
c6c1394af6
commit
408102117c
|
|
@ -3,6 +3,73 @@
|
|||
import frappe
|
||||
|
||||
|
||||
def add_importer_link_to_invoicing_workspace():
|
||||
"""Insert a 'Bank Statement Importer' link into the existing 'Banking' card
|
||||
on the ERPNext 'Invoicing' workspace.
|
||||
|
||||
This intentionally edits an ERPNext-owned workspace at runtime rather than
|
||||
overriding its JSON file: ERPNext re-syncs the JSON on every `bench
|
||||
migrate`, so any direct file edit would be reverted. We run from
|
||||
after_migrate, which fires AFTER that resync, so this stays in place.
|
||||
|
||||
Idempotent — runs every migrate but only inserts when the link is missing.
|
||||
"""
|
||||
ws_name = "Invoicing"
|
||||
link_to = "Bank Statement Importer"
|
||||
card_label = "Banking"
|
||||
|
||||
if not frappe.db.exists("Workspace", ws_name):
|
||||
return
|
||||
if not frappe.db.exists("DocType", link_to):
|
||||
return
|
||||
|
||||
ws = frappe.get_doc("Workspace", ws_name)
|
||||
|
||||
if any(l.type == "Link" and l.link_to == link_to for l in ws.links):
|
||||
return
|
||||
|
||||
# Find the position of the "Banking" card break.
|
||||
banking_idx = None
|
||||
for i, link in enumerate(ws.links):
|
||||
if link.type == "Card Break" and (link.label or "").strip() == card_label:
|
||||
banking_idx = i
|
||||
break
|
||||
|
||||
if banking_idx is None:
|
||||
# No Banking card break — bail out instead of appending in a random spot.
|
||||
print(f"BI: '{card_label}' Card Break not found on '{ws_name}' workspace, skipping link insert")
|
||||
return
|
||||
|
||||
# Find the next Card Break — our link goes right before it (end of Banking
|
||||
# section). If Banking is the last card, append to the very end.
|
||||
next_card_idx = len(ws.links)
|
||||
for i in range(banking_idx + 1, len(ws.links)):
|
||||
if ws.links[i].type == "Card Break":
|
||||
next_card_idx = i
|
||||
break
|
||||
|
||||
# Append a row (Frappe auto-assigns parent fields), then move it into place.
|
||||
ws.append("links", {
|
||||
"label": link_to,
|
||||
"link_to": link_to,
|
||||
"link_type": "DocType",
|
||||
"type": "Link",
|
||||
"onboard": 0,
|
||||
"is_query_report": 0,
|
||||
"hidden": 0,
|
||||
})
|
||||
new_row = ws.links.pop()
|
||||
ws.links.insert(next_card_idx, new_row)
|
||||
for i, l in enumerate(ws.links):
|
||||
l.idx = i + 1
|
||||
|
||||
ws.flags.ignore_version = True
|
||||
ws.flags.ignore_permissions = True
|
||||
ws.save(ignore_permissions=True)
|
||||
frappe.db.commit()
|
||||
print(f"BI: added '{link_to}' link to '{card_label}' card on '{ws_name}' workspace")
|
||||
|
||||
|
||||
def link_kb_bank_accounts_to_bi():
|
||||
"""For every Bank Account that appears in Kapital Bank Settings.account_mappings,
|
||||
set bank_integration_type='Kapital Bank Settings' / bank_integration='Kapital Bank Settings'
|
||||
|
|
|
|||
|
|
@ -144,11 +144,13 @@ def after_migrate_combined():
|
|||
rename_bip_purposes,
|
||||
migrate_standard_field_codes_to_labels,
|
||||
copy_excel_preset_into_bank_integration,
|
||||
add_importer_link_to_invoicing_workspace,
|
||||
)
|
||||
link_kb_bank_accounts_to_bi()
|
||||
rename_bip_purposes()
|
||||
migrate_standard_field_codes_to_labels()
|
||||
copy_excel_preset_into_bank_integration()
|
||||
add_importer_link_to_invoicing_workspace()
|
||||
except Exception as e:
|
||||
print(f"BI: post-migrate sync failed: {e}")
|
||||
# REMOVED: Asset categories creation moved to setup_wizard_complete hook
|
||||
|
|
|
|||
|
|
@ -1,166 +0,0 @@
|
|||
{
|
||||
"app": "jey_erp",
|
||||
"charts": [],
|
||||
"content": "[{\"id\":\"bs_header_shortcuts\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"id\":\"bs_shortcut_importer\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Bank Statement Importer\",\"col\":3}},{\"id\":\"bs_shortcut_bt\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Bank Transaction\",\"col\":3}},{\"id\":\"bs_shortcut_brt\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Bank Reconciliation Tool\",\"col\":3}},{\"id\":\"bs_spacer\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"bs_header_masters\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Setup & Registry</b></span>\",\"col\":12}},{\"id\":\"bs_card_setup\",\"type\":\"card\",\"data\":{\"card_name\":\"Setup\",\"col\":4}},{\"id\":\"bs_card_registry\",\"type\":\"card\",\"data\":{\"card_name\":\"Registry\",\"col\":4}},{\"id\":\"bs_card_daily\",\"type\":\"card\",\"data\":{\"card_name\":\"Daily Use\",\"col\":4}}]",
|
||||
"creation": "2026-05-18 00:00:00.000000",
|
||||
"custom_blocks": [],
|
||||
"docstatus": 0,
|
||||
"doctype": "Workspace",
|
||||
"for_user": "",
|
||||
"hide_custom": 0,
|
||||
"icon": "accounting",
|
||||
"idx": 0,
|
||||
"is_hidden": 0,
|
||||
"label": "Bank Statements",
|
||||
"links": [
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Setup",
|
||||
"link_count": 0,
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Bank Statement Importer",
|
||||
"link_count": 0,
|
||||
"link_to": "Bank Statement Importer",
|
||||
"link_type": "DocType",
|
||||
"onboard": 1,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Bank",
|
||||
"link_count": 0,
|
||||
"link_to": "Bank",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Bank Account",
|
||||
"link_count": 0,
|
||||
"link_to": "Bank Account",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Daily Use",
|
||||
"link_count": 0,
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Bank Transaction",
|
||||
"link_count": 0,
|
||||
"link_to": "Bank Transaction",
|
||||
"link_type": "DocType",
|
||||
"onboard": 1,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Bank Reconciliation Tool",
|
||||
"link_count": 0,
|
||||
"link_to": "Bank Reconciliation Tool",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Registry",
|
||||
"link_count": 0,
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Counterparties (Customers)",
|
||||
"link_count": 0,
|
||||
"link_to": "Bank Integration Customer",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Counterparties (Suppliers)",
|
||||
"link_count": 0,
|
||||
"link_to": "Bank Integration Supplier",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Purpose Keywords",
|
||||
"link_count": 0,
|
||||
"link_to": "Bank Integration Purpose",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2026-05-18 00:00:00.000000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Jey Erp",
|
||||
"name": "Bank Statements",
|
||||
"number_cards": [],
|
||||
"owner": "Administrator",
|
||||
"parent_page": "Accounting",
|
||||
"public": 1,
|
||||
"quick_lists": [],
|
||||
"restrict_to_domain": "",
|
||||
"roles": [],
|
||||
"sequence_id": 6.0,
|
||||
"shortcuts": [
|
||||
{
|
||||
"color": "Blue",
|
||||
"doc_view": "List",
|
||||
"label": "Bank Statement Importer",
|
||||
"link_to": "Bank Statement Importer",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"color": "Green",
|
||||
"doc_view": "List",
|
||||
"label": "Bank Transaction",
|
||||
"link_to": "Bank Transaction",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"color": "Grey",
|
||||
"doc_view": "",
|
||||
"label": "Bank Reconciliation Tool",
|
||||
"link_to": "Bank Reconciliation Tool",
|
||||
"type": "DocType"
|
||||
}
|
||||
],
|
||||
"title": "Bank Statements",
|
||||
"type": "Workspace"
|
||||
}
|
||||
Loading…
Reference in New Issue