"""App setup: custom fields created/synced on migrate.""" import frappe from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from frappe.custom.doctype.property_setter.property_setter import make_property_setter from ns_app.api.statements import BILLED_UPTO_FIELD, LATE_FEE_NAMING_SERIES # Fee schedule/amounts live on ERPNext's Dunning Type; this adds the one thing # it lacks — the Item used to bill a late fee as a Sales Invoice. CUSTOM_FIELDS = { "Dunning Type": [ { "fieldname": "custom_late_fee_item", "label": "Late Fee Item", "fieldtype": "Link", "options": "Item", "insert_after": "income_account", "description": ( "Item used to bill a late-payment fee as a Sales Invoice when " "customer statements are generated." ), } ], "Sales Invoice": [ { "fieldname": BILLED_UPTO_FIELD, "label": "Late Fee Billed Upto", "fieldtype": "Date", "insert_after": "due_date", "read_only": 1, "print_hide": 1, # Must survive frappe.copy_doc() when the invoice is amended to add # another period's interest — it is what stops that period being # billed twice. "no_copy": 0, "description": ( "On a late-fee invoice, the date interest was last charged. The " "next statement run accrues interest from here." ), } ], } def _register_late_fee_naming_series(): """Add the late-fee series to Sales Invoice's naming_series options.""" field = frappe.get_meta("Sales Invoice").get_field("naming_series") options = [o for o in (field.options or "").split("\n")] if field else [] if LATE_FEE_NAMING_SERIES not in options: options.append(LATE_FEE_NAMING_SERIES) make_property_setter( "Sales Invoice", "naming_series", "options", "\n".join(options), "Text", validate_fields_for_doctype=False, ) def after_migrate(): create_custom_fields(CUSTOM_FIELDS) _register_late_fee_naming_series()