2026-05-29 MSP Invoice Line CRM Implementation Plan
Snapshot date: 2026-05-29. Updated: 2026-06-25 for Product default price/account-code behavior.
Objective
Make MSP_Invoice_Lines easy to manage in Zoho CRM while keeping billing and
accounting rules in middleware.
CRM users edit controlled source data, including invoice-line billing dates:
Start_DateEnd_Date
Line_Type is removed from the operational process. Invoice behavior is derived
from the linked Product.
Middleware Changes To Deploy First
Deploy the app version containing these endpoints:
POST /zoho/msp-invoices/reconcile-linePOST /zoho/msp-invoices/reconcile-plan-lines
Both routes use the existing inbound auth:
Authorization: Bearer <MIDDLEWARE_API_TOKEN>
The app now:
- derives invoice line behavior from Product code, not
Line_Type; - treats invoice-line
Start_Date/End_Dateas the source of truth for monthly applicability; - excludes lines missing
Start_Dateand reports them for review; - leaves
Start_DateandEnd_Dateunchanged during reconciliation; - leaves price and Xero account-code override fields unchanged so blank values use linked Product defaults.
CRM Variables
Confirm these CRM variables exist:
MIDDLEWARE_BASE_URLMIDDLEWARE_API_TOKEN
MIDDLEWARE_BASE_URL should not have a trailing slash.
Deluge Functions
Create or update these standalone functions from zoho_crm/deluge/:
standalone.reconcile_msp_invoice_linestandalone.reconcile_msp_plan_invoice_lines
Create these automation wrapper functions:
automation.call_reconcile_msp_invoice_lineautomation.call_reconcile_msp_plan_invoice_lines
The wrappers only pass the CRM record ID to middleware. Do not add billing logic to Deluge.
Product Module Setup
Confirm Products have:
Product_CodeDefault_Invoice_LabelUnit_PriceXero_Account_Code
Product-level Unit_Price and Xero_Account_Code are generation defaults.
Invoice-line override fields win only when filled.
Expected product defaults:
| Product group | Default account |
|---|---|
MSP-BASE |
202.5 |
MSP-DEVICE |
202.5 |
MSP-DISCOUNT |
202.5 |
MSP-NFP-DISCOUNT |
220 |
| License/security/subscription products | 211 |
MSP Invoice Lines Layout
Expose these fields to staff:
NamePlanStart_DateEnd_DateProductQuantityUnit_Price_OverrideDescription_OverrideSort_OrderXero_Account_Code_Override
Remove Active and Line_Type from the layout and process. If Zoho allows
safe deletion, delete them after confirming the middleware deployment is live.
Otherwise leave them hidden until a later cleanup.
Recommended defaults:
Start_Date: the first month the line should invoiceEnd_Date: blankUnit_Price_Override: blank unless this line needs a custom priceXero_Account_Code_Override: blank unless this line needs a custom account
Blank price/account-code override fields are preserved so invoice generation can use Product defaults.
MSP Invoice Line Workflow
Create a workflow rule on MSP_Invoice_Lines.
Trigger:
- on create;
- on edit when any of these fields changes:
PlanStart_DateEnd_DateProductQuantityUnit_Price_OverrideDescription_OverrideSort_OrderXero_Account_Code_Override
Action:
- custom function:
automation.call_reconcile_msp_invoice_line - argument: current record ID
The middleware route is idempotent and should return skipped when there is no
line-level compatibility work to do. Date reconciliation is now a compatibility
no-op; invoice generation reads the operator-maintained date range directly.
Managed Services Plan Workflow
Create a workflow rule on Managed_Services_Plans.
Trigger:
- on edit when
Plan_Typechanges.
Action:
- custom function:
automation.call_reconcile_msp_plan_invoice_lines - argument: current record ID
The middleware no longer updates account-code override fields from this route. Blank override fields use Product defaults during invoice generation.
Price and Account Rules
Invoice generation resolves price and account code in this order:
| Value | First source | Fallback source |
|---|---|---|
| Unit price | MSP_Invoice_Lines.Unit_Price_Override |
Product Unit_Price |
| Account code | MSP_Invoice_Lines.Xero_Account_Code_Override |
Product Xero_Account_Code |
If a line has no override and the linked Product is missing the matching
default, generation returns needs_review and does not guess.
Date Rules
Staff manage invoice-line billing dates directly.
Start_Dateis required. Invoice lines missingStart_Dateare excluded and reported for review.End_Dateis optional. BlankEnd_Datemeans ongoing.- Invoice generation includes a line only when its
Start_Date/End_Daterange overlaps the invoice month. - Middleware does not set or clear invoice-line dates.
This does not create historical replacement lines. It is intentionally the simple workflow agreed for now.
Acceptance Tests
After deployment and CRM setup:
- Create an
MSP_Invoice_Linesrecord for an L2 plan usingMSP-BASE. Confirm middleware does not set or clearStart_DateorEnd_Date, and price/account-code overrides stay blank unless staff entered them. - Leave
Start_Dateblank and generate a preview. Confirm the line is excluded and reported for review. - Set
Start_Dateinside the invoice month and leaveEnd_Dateblank. Confirm the line is included. - Set
End_Datebefore the invoice month. Confirm the line is excluded. - Create a license/security/subscription line linked to a Product whose
Xero_Account_Codeis211. Leave both override fields blank. - Generate or refresh a draft MSP invoice. Confirm the line uses the Product price and account code and there are no missing product price/account-code review issues.
Rollback
If a workflow misbehaves:
- Disable the two new CRM workflow rules.
- Leave generated line data in place.
- Fix middleware or Deluge wrapper.
- Re-enable workflows and run a manual edit/save on affected records, or call the reconcile endpoint directly for the impacted record IDs.