2026-07-03 MSP invoicing Improvement
Snapshot date: 2026-07-03.
Objective
Document the simple operational plan for yearly seat invoicing and mid-period seat prorates without adding an MSP billing run module.
The goal is to keep CRM as the practical source of truth for the current plan setup, while generated CRM/Xero invoices remain the accounting snapshot once approved in Xero.
Decision
Do not add MSP billing runs for this stage.
Use MSP_Invoice_Lines as the operational charge memory:
- recurring monthly items remain normal in-range invoice lines;
- yearly seat invoices are represented by a recurring annual seat invoice line
anchored by
Start_Date; - mid-period seat additions are represented by a bounded one-off prorate invoice line;
- devices remain manual invoice-line quantities for now.
This keeps the process visible to operators. The generator now uses two line applicability rules: annual seat Products recur yearly from their renewal-month anchor, and all other Products keep the existing date-overlap behavior.
Products
Products remain the main billing catalogue.
Required product data:
Product_CodeDefault_Invoice_LabelUnit_PriceXero_Account_Code
Yearly Seat Products
The yearly seat Products are the exact recurring annual set:
MSP-SEAT-ANNUAL-SB
MSP-SEAT-ANNUAL-L1
MSP-SEAT-ANNUAL-L2
MSP-SEAT-ANNUAL-L3
Reason: these Products are seat lines, so quantity is calculated from billing-eligible MSP Seats for the renewal invoice month, but their invoice-line applicability is yearly recurrence rather than simple date overlap.
The annual seat Product price should be the yearly seat price after any
standard annual discount. If the discount is client-specific, leave the Product
default as the normal annual price and use Unit_Price_Override on that plan's
invoice line.
Prorate Product
The prorate product should not start with MSP-SEAT-.
Recommended Product code:
MSP-PRORATE-SEAT
Reason: MSP-SEAT- products currently use calculated active-seat quantity. A
prorate charge is for a specific seat addition and should keep the invoice-line
Quantity, usually 1.
Yearly Seat Renewal Operation
When a plan bills seats yearly:
- Confirm the plan has current MSP Seats with correct
Billing_StartandBilling_Endvalues. - Create or update one annual seat
MSP_Invoice_Linesrecord. - Link it to the yearly seat Product, such as
MSP-SEAT-ANNUAL-L2. - Set
Start_Dateto the first day of the first renewal invoice month. This date is the renewal anchor, so avoid partial-month values such as2026-07-15. - Leave
End_Dateblank to renew every 12 months. FillEnd_Dateonly when the recurring annual charge should stop. - Leave
Quantityblank or use it only as a reference; the generated quantity comes from billing-eligible MSP Seats in the renewal invoice month. - Set
Description_Overrideto a base label if needed; the generator appends the covered annual period. Example generated description:
Annual managed service seats
Covered period: 2026-07-01 to 2027-06-30
- Generate or refresh the MSP invoice while the linked Xero invoice is still
DRAFT.
The generated invoice is the historical record. The recurring annual invoice line remains in CRM as the operational evidence for why each yearly charge appears.
Mid-Period Seat Prorate Operation
When a new seat is added during an annual seat period:
- Create the MSP Seat and set its
Billing_Startto the date it becomes billable. - Confirm the seat is linked to the correct Contact and Managed Services Plan.
- Create a one-off
MSP_Invoice_Linesrecord for the prorate. - Link it to
MSP-PRORATE-SEAT. - Set
Quantityto1. - Set
Unit_Price_Overrideto the calculated prorate amount. - Set
Start_Dateto the month the prorate should be invoiced. - Set
End_Dateto the last day of that same month so it only appears once. - Set
Description_Overrideto identify the person and covered period, for example:
Prorated annual seat charge for Jane Smith, 2026-10-15 to 2027-06-30
- Generate or refresh the MSP invoice while the linked Xero invoice is still
DRAFT.
The prorate invoice line is the simple charge memory. Before creating a prorate line, operators should search existing MSP Invoice Lines for the same person and covered period to avoid double charging.
Prorate Calculation
Use monthly proration unless the commercial agreement requires daily proration.
Recommended simple formula:
annual seat price * remaining full months / 12
If the customer should be charged for the current partial month, count that as a full remaining month. If the customer should not be charged until the next month, start the remaining-month count from the next month.
Daily proration can be used by exception:
annual seat price * remaining days in covered period / total days in covered period
Devices
Devices remain purely invoice-line based for now.
Use the normal device Product and set Quantity directly on the
MSP_Invoice_Lines record. Do not introduce a device registry or dynamic device
count for this stage.
When device details need to appear on the invoice, include them in
Description_Override.
Controls
- Do not add an MSP billing run module for this stage.
- Use
Start_Dateas the annual seat renewal-month anchor. It must be the first day of the invoice month. - Leave annual seat
End_Dateblank for ongoing yearly renewal, or fill it when the charge should stop. - Keep prorate lines bounded to one invoice month using
Start_DateandEnd_Date. - Use
MSP-SEAT-only for lines where quantity should be calculated from MSP Seats. - Use
MSP-PRORATE-SEATfor one-off prorates where quantity should remain manually controlled. - Do not approve or send from the middleware. Finance still reviews and approves in Xero.
- Once Xero is no longer
DRAFT, do not refresh the generated invoice. Use a new adjustment or credit process if a correction is needed.
Later Automation Option
If manual duplicate checks become unreliable, add a lightweight Charge_Key
field to MSP_Invoice_Lines.
Example:
plan_id|seat_id|annual-prorate|2026-10-15|2027-06-30
This would provide duplicate detection without introducing a full billing run module.