Solution design draft for discussion, 20 October 2026

Telecare price change, synced to Business Central without the three-week watch

Today a daily batch re-prices MSD subscriptions for two weeks, resends each order to FIS, and someone watches it until go-live. The proposal: record the price change once, apply it once at go-live to every weekly, fortnightly and monthly subscription, and send Business Central one acknowledged message per subscription.

Today vs proposed

Today Pricebook changed by hand Daily batch finds MSD by product name runs every day for about two weeks Clone schedule and BT cancel old, update order line Resend whole order Order V2, one at a time FIS billing no acknowledgement Success is checked by watching the sync for about three weeks. Proposed Price Change one approved record Preview, once one line per subscription sign-off Apply once at go-live new schedule at new price Outbox, one per line AIS price-update topics Business Central acknowledgement and BC reference Then automatic checks: expected = applied = acknowledged, and nothing left at the old price.
The daily loop and the whole-order resend go away. Affected subscriptions are found once from their billing schedules, the price is applied once, and every line waits for Business Central to confirm it.
Why today needs watching
  • Each schedule holds only one Upcoming bill, and those appear as invoice dates roll on, so affected orders surface a few at a time and the batch has to run daily.
  • The FIS sync resends the whole order, one at a time, and nothing confirms it arrived.
  • The product is found by name (LIKE '%MSD%'), the date sits in a Custom Label, the order totals aren't updated, and nothing records what changed.
What the proposal changes
  • A price change is a business record covering every product it re-prices, with an approval. It updates the pricebook itself, so nobody edits prices one by one.
  • Every affected subscription is listed two weeks ahead, so Finance signs off on a number.
  • Each subscription switches at the start of its own billing period, whatever its frequency.
  • Business Central gets small, repeat-safe messages and confirms each one.

Timeline

19/0621/0623/06 25/0627/0629/06 01/0703/0705/07 07/0709/07 Price change Go-live Today Pricebook changed by hand Daily batch: re-price, resend to FIS Watch that FIS got every order Business and Finance checks Proposed Approve, update pricebook Preview and Finance sign-off Apply once, send to BC Reconcile (automatic) then first-bill checks per frequency
Dates follow the MSD example (price change 19/06, go-live 03/07). The system acts on three days. After that, automatic checks run when each frequency's first new-price bill is due (about one, two and four weeks later). Nobody has to watch.
Today: job or manual step Today: monitoring Proposed: system step

How it works, step by step

Six steps, each shown as the screen Finance or the system would see. Product names and today's prices are real; counts, new prices and order numbers are samples. Nobody edits the pricebook by hand: the Price Change does it.

1

Create the price change and set the new prices

About three weeks before go-live. Finance.
You
Create a Price Change, set the go-live date and click Add MSD products. Type one uplift (for example 4%) and click Fill new prices, then override any row that needs a different price.
The system
Adds every product funded by MSD, inactive ones included, with today's price from the pricebook. Fill sets each weekly price and works out fortnightly (× 2) and monthly (× 52 ÷ 12) from it, so the three always agree.
You check
Every row shows a tick. A red row means a typed price doesn't agree with the others in its group.
New Price ChangeDraft
Products (26)Add MSD productsUplift4.0%Fill new prices
ProductBillsOldNewPer weekCheck
Medical Alarm - MSD Funded - WeeklyWeekly$17.27$17.96$17.96✓
Medical Alarm - MSD Funded - FortnightlyFortnightly$34.54$35.29$17.65✗ typed over; 2 × weekly is $35.92
Medical Alarm - MSD Funded InAdvance - MonthlyMonthly$74.84$77.83$17.96✓
MSD Anywhere - Fortnightly inactive, still billingFortnightly$51.14$53.18$26.59✓
Securely - MSD Home - MonthlyMonthly$74.84$77.83$17.96✓
… 21 more products
1 price needs fixing before this can be sent for approval.
2

Approve and update the pricebook

Same day. Finance manager approves; then one click.
You
Approve, then click Update Pricebook.
The system
Writes every new price to its product's Standard Price Book entry in one go: all 26 or none. Orders placed from now on are sold at the new price. Existing customers don't change until go-live.
You check
26 of 26 entries updated. Until go-live, Restore Old Prices puts them all back if the change is cancelled.
PC-0007, MSD price change July 2026Approved by Finance manager
  1. Draft
  2. Approved
  3. Pricebook Updated
  4. Previewed
  5. Applied
  6. Synced
  7. Closed
✓ 26 of 26 pricebook entries updated. New orders from today use the new prices.
ProductPricebook beforePricebook now
Medical Alarm - MSD Funded - Weekly$17.27$17.96
Medical Alarm - MSD Funded - Fortnightly$34.54$35.92
Medical Alarm - MSD Funded InAdvance - Monthly$74.84$77.83
… 23 more
Writes the price incl GST and the price excl GST (÷ 1.15) on each entry.Restore Old Prices
3

Preview who changes, and sign off

About two weeks before go-live. Can be rerun until sign-off.
You
Click Run Preview, review, then Sign off.
The system
Creates one Price Change Line for every live subscription to these products. Separately it counts the live billing schedules for each product. The two counts must match in every cell.
You check
The grid is all ticks, and every exception has an answer.
Preview, PC-0007Run 19 Jun, 10:02
4,315Live subscriptions
4,315Lines created
26Products
0Missing products
Product groupWeeklyFortnightlyMonthly
Medical Alarm172 ✓2,751 ✓7 ✓
Medical Alarm Two Pendant4 ✓111 ✓none
MSD Anywhere (incl. old product codes)103 ✓945 ✓none
Securely Home19 ✓186 ✓1 ✓
Add-ons (mobile, extra pendant)1 ✓15 ✓none
Total2994,0088
  • !3 subscriptions are on a custom amount, not the list price. Finance confirms each one.
  • ✓12 are already at the new price (orders placed since the pricebook update). Their lines are marked Skipped.
  • ✓2 customers on a billing holiday are included; they pay the new price when billing resumes.
  • ✓1 subscription has an end date after go-live; it's re-priced until it ends.
Lines are linked to PC-0007 and can be opened in a report.Sign off preview
4

Apply at go-live

Go-live day, automatically (or one click).
The system
For each line, re-checks the subscription (a cancelled order is skipped with a reason) and finds the start of its next billing period. It ends the old billing schedule the day before and starts a new one at the new price on that day. It also updates the order line and order totals and makes the first bill at the new price. The section below shows each record change.
You check
Errors = 0. Every subscription keeps its own billing day.
Apply, PC-0007Go-live Fri 3 Jul 2026
4,300Applied
15Skipped, with reason
0Errors
Sample subscriptionOld schedule endsNew schedule startsFirst bill at new price
Weekly, in arrears, cycle starts TuesdayMon 6 JulTue 7 JulMon 13 Jul, $17.96
Fortnightly, in arrears, cycle started Wed 1 JulTue 14 JulWed 15 JulTue 28 Jul, $35.92
Monthly, in advance, on the 20thSun 19 JulMon 20 JulMon 20 Jul, $77.83
Skipped: 12 already at the new price, 2 orders cancelled since the preview, 1 moved to a non-MSD product.
5

Send each change to Business Central

Straight after Apply, automatically.
The system
Sends each applied line to Business Central through AIS: which subscription, the new price and the date it starts. Business Central replies with its reference and the line ticks to Confirmed. No reply means 3 automatic retries, then Failed.
Think of it as
Tracked parcels: Salesforce posts one, AIS delivers it, Business Central signs for it. A line isn't done until it's signed for.
You check
Failed = 0, or click Resend Failed.
Business Central sync, PC-0007Updated 3 Jul, 06:40
4,300Sent
4,295Confirmed by BC
0Waiting
5Failed
LineMessageResult
PCL-001201Weekly, $17.96 from 7 JulConfirmed, BC ref SUB-48213
PCL-001202Fortnightly, $35.92 from 15 JulConfirmed, BC ref SUB-48214
PCL-001203Monthly, $77.83 from 20 JulNo reply after 3 tries
Failed lines keep their error until resent.Resend Failed
6

Reconcile and close

The day after go-live, then automatically when each frequency's first new bill is due.
The system
Runs the checks and shows them as ticks. It also looks for anything still at the old price; that number must be 0.
You
Act only on what isn't ticked. Close the price change when everything is.
Reconciliation, PC-0007Status: Synced
  • ✓Every live subscription has a line (4,315 of 4,315)
  • ✓Every line applied, or skipped with a reason (4,300 + 15)
  • ✓Business Central confirmed every applied line (4,300 of 4,300, after resend)
  • ✓Nothing left at the old price (0 schedules, 0 upcoming bills)
  • ✓First weekly bills at the new price (checked Tue 14 Jul)
  • ✓First monthly bills at the new price (checked Tue 21 Jul)
  • …First fortnightly bills: check runs Wed 29 Jul
Close becomes available when every check is ticked.Close price change
Technical view: the same flow as a system sequence
Finance Salesforce (CC) AIS Business Central 1 Create, add products, approve 2 Update pricebook (new orders) 3 Preview: create the lines 4 Preview report for sign-off 5 Sign off Go-live day 6 Apply once (schedules, bills, order totals) Loop: each applied line 7 Price update, start date, key 8 Upsert subscription price 9 Acknowledge with BC reference 10 Line marked Acknowledged no ack: retry, then Failed 11 Reconciliation checks

Step 7 reuses the AIS topics already being built (cc.bsline.priceupdate, cc.bsschedule.priceupdate, cc.bsorder.priceupdate). The key (Price Change + OrderItem) makes a resend safe, because Business Central updates the same record instead of creating a second one.

How the records are created

Price Change and its product rows (step 1)

  • When: as soon as the new prices are known, at least three weeks before go-live. Created by Finance from the Price Changes tab with New.
  • Header (Price_Change__c): description, funder (MSD), go-live date and the price rule. Status starts at Draft.
  • Product rows (Price_Change_Product__c, one per product):
    • Add MSD products finds every product with the Funder = MSD definition attribute, active or not. That's the lookup the June draft in QA already uses (ProductController.getProductsByDefinitionAttributes).
    • As a safety net, any product with live schedules whose name contains MSD but whose funder isn't MSD is reported as missing.
    • Each row copies the product's frequency, and today's price from its Standard Price Book entry.
  • New prices, without typing 26 of them:
    • Fill new prices applies one uplift to each weekly price (rounded to the cent). It works out fortnightly as 2 × weekly and monthly as weekly × 52 ÷ 12 for the same service.
    • Finance can then type over any row, or paste a column of prices.
    • The price excluding GST is incl ÷ 1.15, kept to 4 decimals like today.
  • Before approval the record won't submit while a product is missing, a new price equals the old one, or the weekly, fortnightly and monthly prices disagree.

Updating the pricebook from the Price Change (step 2)

  • Update Pricebook is available once the Price Change is Approved. For each product row it updates that product's active Standard Price Book entry:
    • UnitPrice_GST_Inclusive__c = the new price incl GST;
    • UnitPrice = the new price excl GST;
    • Price_Excl_GST__c is a formula and follows.
  • All or nothing: all 26 entries are updated in one transaction. It then sets Pricebook_Update_Date__c and Status = Pricebook Updated.
  • Restore Old Prices (until Apply): writes the old prices back from the product rows, if the change is cancelled or postponed.
  • Edits outside the price change: if someone changes an in-scope pricebook price by hand afterwards, Apply sees that the pricebook no longer matches the product row and stops that product's lines.

Price Change Lines (step 3, Preview)

A batch reads the billing schedules, not the bills. That's why every subscription is found at once, whatever its frequency and wherever it is in its cycle. One line per schedule:

SELECT Id, Order_Product__c, Order_Product__r.OrderId, Order_Product__r.Product2Id, Account__c,
       Amount_to_be_billed__c, Billing_Start_Date__c, Billing_Frequency__c, Billing_Type__c,
       Quantity__c, Next_Billing_Date_Calculated__c, Order_Product__r.LineDiscountAmount__c
FROM   Billing_Schedule__c
WHERE  Order_Product__r.Product2Id IN :productsOnThisPriceChange
AND    Order_Product__r.Order.Status = 'Activated'
AND    Charge_Type__c = 'Recurring'
AND    Billing_Start_Date__c != null
AND    (Billing_End_Date__c = null OR Billing_End_Date__c >= :goLiveDate)
  • Filled on each line: its product row, Order, OrderItem, Account and old schedule.
    • Old_Amount__c is the schedule's amount; New_Amount__c is the product row's new price.
    • Also: discount, frequency, in advance or in arrears, next billing date and the forecast cutover date.
    • Apply Status = Pending, Sync Status = Not Sent.
  • Already at the new price (orders placed since the pricebook update): the line is marked Skipped, so the counts still add up.
  • Rerun-safe: lines are upserted on Idempotency_Key__c (Price Change + OrderItem), so a second preview updates lines instead of duplicating them.
  • Counted twice: live schedules per product are counted straight from Billing_Schedule__c into Live_Schedules__c and compared with Lines_Created__c.
  • Billing holidays: a holiday is its own schedule record (Charge Type = Billing Holiday). The customer's recurring schedule stays live, so it's included.
  • At Apply: the same query runs again, and any subscription activated since the preview gets a late line. The pricebook is checked against the product rows first.

What Apply does to the records

Example: a fortnightly, in-arrears subscription whose cycle started Wednesday 1 July. Go-live is Friday 3 July, the price goes from $34.54 to $35.92, and the rule is "billing periods starting on or after go-live". Its cutover is therefore Wednesday 15 July.

Order Billing schedules Bills (billing transactions) Order custom totals Updated: recalculated OrderItem (the line) $34.54 to $35.92 Updated Old Billing Schedule $34.54 a fortnight Updated: ends Tue 14 Jul New Billing Schedule $35.92 a fortnight Created: starts Wed 15 Jul Bill 1 to 14 Jul $34.54, Upcoming Left as is (old price) Bill 15 to 28 Jul only if already made here Cancelled Bill 15 to 28 Jul $35.92, Upcoming Created by Apply Bills from 29 Jul $35.92 each Created by the existing flow Price Change Line old + new schedule, cutover Updated: Applied The old schedule makes no more bills: its next period would start after its end date. Amber = existing record updated; teal = new record; dashed = only if present, or made later.
RecordActionFields (example values)
Old Billing ScheduleUpdatedBilling_End_Date__c: blank to 14 Jul (cutover − 1). Nothing else changes, so its history stays intact.
New Billing ScheduleCreatedA copy of the old one (account, bank and payment details, quantity, frequency, in arrears or in advance), with:
Billing_Start_Date__c = 15 Jul (cutover, so the customer keeps their Wednesday fortnight)
First_Payment_Date__c = 28 Jul (in arrears: end of the first period; in advance: the cutover date)
Amount_to_be_billed__c = $35.92; Billing_End_Date__c = blank, or the old end date if one was set
Upcoming bill on the old scheduleLeft or CancelledPeriod starts before cutover (1 to 14 Jul): left at the old price.
Period starts on or after cutover (possible for weekly customers): Status__c = Cancelled.
First bill on the new scheduleCreatedBilling_Period_Start_Date__c / End = 15 to 28 Jul; Status__c = Upcoming
Rate__c and Total_Amount_Value__c = $35.92; GST_Amount_Value__c = $4.69; List_Price_Value__c = $31.23
Discount_Amount_Value__c = the line discount; quantity, payment method, and payment date (in arrears: period end)
OrderItemUpdatedUnitPrice $30.03 to $31.23; LineGSTAmount__c $4.51 to $4.69; LineTotalAmount__c $34.54 to $35.92. LineDiscountAmount__c unchanged.
OrderUpdatedOrderSubTotalAmount__c, OrderTotalGSTAmount__c, OrderTotalAmount__c and OrderDiscountAmount__c recalculated from all the order's lines (base plus add-ons). These are plain number fields that today's batch leaves stale. The standard TotalAmount follows UnitPrice automatically.
Price Change LineUpdatedNew_Billing_Schedule__c, Cutover_Date__c = 15 Jul, Apply_Status__c = Applied, Applied_On__c. Then it joins the Business Central outbox.
All or nothing per line. Each line's changes are made together. If any one fails, that line's changes roll back, the line shows Error with the message, and the rest carry on.
Later bills need no new code. When a bill is submitted, the existing flow Create recurring Billing Transactions (BillingTransactionController) makes the next Upcoming bill on the same schedule. It prices it from the schedule's Amount_to_be_billed__c and the OrderItem, both of which are now at the new price.
Watch old bills in reports. Total_Amount__c, GST_Amount__c and Unit_Price__c on bills are formulas that read the OrderItem. After Apply, even paid bills show the new price in those fields. Reports and the AIS bill payload must use the stored …_Value__c fields.

Weekly, fortnightly and monthly: making sure every subscription is covered

MSD products come in weekly, fortnightly and monthly versions. Each version is its own product with its own price, for example Medical Alarm at $17.27 a week, $34.54 a fortnight and $74.84 a month. So the design works by product, never by name or frequency. Each subscription bills on a cycle counted from its own start date: the same weekday for weekly and fortnightly, the same date for monthly. The switch has to land on that cycle.

Mon 29 JunMon 6 Jul Mon 13 JulMon 20 Jul Go-live Fri 3 Jul Weekly in arrears, from Tuesday 30 Jun to 6 Jul 7 to 13 Jul new price from Tue 7 Jul Fortnightly in arrears, from Wednesday 1 to 14 Jul: started before go-live, old price 15 to 28 Jul new price from Wed 15 Jul Monthly in advance, on the 20th 20 Jun to 19 Jul, old price from 20 Jul new price from Mon 20 Jul old price period new price period bill date (in arrears: end of period; in advance: start)
Each subscription's new schedule starts on its own next cycle boundary, never on the go-live date itself. The billing-date formula counts cycles from Billing_Start_Date__c, so starting a weekly customer's new schedule on Friday 3 July would move their billing day. Today's batch gets this right by starting the new schedule at the upcoming bill's period start. The new Apply keeps that rule.

The one decision Finance needs to make

Most MSD subscriptions are billed in arrears, at the end of each period. That leaves one question: what price does the period that straddles go-live pay?

Recommended

Billing periods starting on or after go-live

Customers pay the new price only for service after go-live. It's the same rule for every frequency, in advance or in arrears. The first new-price bill comes up to one cycle after go-live (above: 7, 15 and 20 July).

What today's batch does

Bills dated on or after go-live

For in-arrears customers, the period that straddles go-live is billed in full at the new price. A fortnightly customer would pay the new price for up to 13 days of service before go-live (above: the whole 1 to 14 July period).

Five checks that prove nothing is missed

CheckWhenPasses when
Every product with live MSD subscriptions is on the price change, inactive (grandfathered) products includedAdding products, and again at previewMissing products = 0
Weekly, fortnightly and monthly prices agree: fortnightly = 2 × weekly, monthly = weekly × 52 ÷ 12. Today's prices follow this ($17.27, $34.54, $74.84).Before approvalEvery product row ticked
Every live subscription has a line, counted per product and frequency straight from the billing schedulesPreview, and again at ApplyLive schedules = lines, in every cell
Each line switches at the start of its own billing period, within one cycle of go-live (7, 14 or about 31 days)Apply0 exceptions
Nothing left at an old price: no live schedule or upcoming bill on these products at the old amountDay after go-live, then when each frequency's first new bill is due (about 1, 2 and 4 weeks)0 found

The three new objects

Price Change is the record Finance approves. Price Change Product holds one row per product with its old and new price, and is what Update Pricebook writes from, so nobody edits 26 pricebook entries by hand. MSD alone has 26 products across weekly, fortnightly and monthly. Price Change Line is one affected subscription: the audit row, the work list for Apply and the outbox for Business Central in one.

Price_Change__c Name PC-{0000} + 21 custom fields Effective_Date__cDate Price_Rule__cPicklist Status__cPicklist Approved_By__cLookup(User) Lines_Expected__cRoll-up count Lines_Acknowledged__cRoll-up count Left_At_Old_Price__cNumber + 14 more fields master-detail one row per product Price_Change_Product__c Name PCP-{000} + 14 custom fields Product__cLookup(Product2) Billing_Frequency__cText Old_Price_Incl_GST__cCurrency New_Price_Incl_GST__cCurrency Weekly_Equivalent__cFormula Live_Schedules__cNumber Lines_Created__cNumber + 7 more fields UserApproved_By__c Product2Product__c master-detail one per subscription lookup Price_Change_Line__c Name PCL-{000000} + 24 custom fields Price_Change__cMaster-detail Price_Change_Product__cLookup Order_Product__cLookup(OrderItem) Old_Billing_Schedule__cLookup New_Billing_Schedule__cLookup Billing_Frequency__cText Cutover_Date__cDate New_Amount__cCurrency Apply_Status__cPicklist Sync_Status__cPicklist Idempotency_Key__cText, unique + 13 more fields AccountAccount__c OrderOrder__c OrderItemOrder_Product__c Billing Scheduleold and new Billing_Schedule__c Arrows point from a record to the record it looks up. Amber type = roll-up summary on the header. Billing Schedule (amber box) is the existing object Apply ends and creates. Full field lists are below.
Three new objects, 59 custom fields in all (21 + 14 + 24), each with an auto-number Name. No new fields on existing objects.

Line status lifecycle

Apply_Status__c Sync_Status__c Skipped Lines_Skipped__c Pending Error Lines_Apply_Errors__c Applied Lines_Applied__c Sent Acknowledged Lines_Acknowledged__c Failed Lines_Sync_Failed__c order changed fails fixed, retry apply OK send BC confirms no ack after retries resend
The preview creates every line as Pending (counted by Lines_Expected__c). Amber names are the header roll-ups that count each state.

Field lists

Price_Change__c, Price Change

Name (auto-number PC-{0000}) + 21 custom fields: 13 entered or set by the process, 7 roll-ups, 1 formula
#FieldTypePurpose
What and when
1Description__cText(255)For example "MSD price change July 2026"
2Funder__cPicklist, requiredScope for Add MSD products: every product with this funder attribute, active or not
3Effective_Date__cDate, requiredGo-live date
4Price_Rule__cPicklist"Billing periods starting on or after go-live" (default) or "Bills dated on or after go-live"
5Pricebook_Update_Date__cDate/TimeSet by Update Pricebook; cleared by Restore Old Prices
Approval and status
6Status__cPicklistDraft, Approved, Pricebook Updated, Previewed, Applied, Synced, Closed, Cancelled
7Approved_By__cLookup(User)Finance approver of the prices
8Approved_On__cDate/Time
9Preview_Signed_Off_By__cLookup(User)Who signed off the preview
10Preview_Signed_Off_On__cDate/TimeSign-off locks the preview
Counts (roll-up summaries)
11Products_In_Scope__cRoll-up countProduct rows
12Lines_Expected__cRoll-up countAll lines
13Lines_Applied__cRoll-up countApply Status = Applied
14Lines_Skipped__cRoll-up countApply Status = Skipped
15Lines_Apply_Errors__cRoll-up countApply Status = Error
16Lines_Acknowledged__cRoll-up countSync Status = Acknowledged
17Lines_Sync_Failed__cRoll-up countSync Status = Failed
Checks (set by the check jobs)
18Missing_Products__cNumberMSD-named products with live subscriptions whose funder isn't MSD
19Left_At_Old_Price__cNumberLive schedules or upcoming bills on these products still at an old amount
20First_Bill_Checks__cText(255)For example "Weekly OK 14 Jul; Monthly OK 21 Jul; Fortnightly due 29 Jul"
21Reconciled__cFormula checkboxMissing = 0, expected = applied + skipped, applied = acknowledged, no errors or failures, nothing left at the old price

Price_Change_Product__c, Price Change Product

Name (auto-number PCP-{000}) + 14 custom fields: one row per product; the source for Update Pricebook
#FieldTypePurpose
1Price_Change__cMaster-detail(Price_Change__c)The parent price change
2Product__cLookup(Product2), requiredOne row per product (duplicates blocked)
3Product_Is_Active__cCheckboxCopied, so inactive products that still bill stand out
4Billing_Frequency__cText(3)Copied from the product: 1W, 2W or 1M
5Price_Group__cText(80)For example "Medical Alarm": links the weekly, fortnightly and monthly versions for Fill and the checks
6Old_Price_Excl_GST__cCurrency(16,4)From the pricebook when added; used by Restore Old Prices
7Old_Price_Incl_GST__cCurrency(16,2)From the pricebook when added
8New_Price_Excl_GST__cCurrency(16,4)Incl ÷ 1.15; written to the pricebook's UnitPrice
9New_Price_Incl_GST__cCurrency(16,2)Filled from the uplift or typed; written to UnitPrice_GST_Inclusive__c
10Weekly_Equivalent__cFormula currencyNew price ÷ 1, 2 or (52 ÷ 12)
11Price_Check__cText(255)"OK", or what's wrong, for example "2 × weekly is $35.92"
12Live_Schedules__cNumberCounted straight from Billing_Schedule__c at preview and Apply
13Lines_Created__cNumberLines the preview made for this product
14Coverage_OK__cFormula checkboxLive schedules = lines created

Price_Change_Line__c, Price Change Line

Name (auto-number PCL-{000000}) + 24 custom fields: 7 relationships, 7 amount and schedule, 3 apply, 7 sync
#FieldTypePurpose
Relationships
1Price_Change__cMaster-detail(Price_Change__c)The parent price change
2Price_Change_Product__cLookup(Price_Change_Product__c)The product row (and so the new price)
3Account__cLookup(Account)Customer, for reports and support
4Order__cLookup(Order)Order whose totals are recalculated
5Order_Product__cLookup(OrderItem)Subscription line being re-priced
6Old_Billing_Schedule__cLookup(Billing_Schedule__c)Ended the day before cutover
7New_Billing_Schedule__cLookup(Billing_Schedule__c)Created from cutover at the new price
Amount and schedule
8Old_Amount__cCurrency(16,2)The schedule's amount, per period incl GST
9New_Amount__cCurrency(16,2)The product row's new price, per period incl GST
10Discount_Amount__cCurrency(16,2)Line discount carried across
11Billing_Frequency__cText(3)1W, 2W or 1M
12Billing_Type__cText(2)AR (in arrears) or AD (in advance)
13Next_Billing_Date__cDateAt preview, for the Finance report
14Cutover_Date__cDateFirst day at the new price: the start of this subscription's first billing period under the price rule
Apply result
15Apply_Status__cPicklistPending, Applied, Skipped, Error
16Skip_Reason__cText(255)Already at the new price, cancelled, product changed, schedule ended
17Applied_On__cDate/Time
Business Central sync (the outbox)
18Sync_Status__cPicklistNot Sent, Sent, Acknowledged, Failed
19Sync_Attempts__cNumber(3,0)Automatic retry up to a set limit
20Last_Sent_On__cDate/Time
21Acknowledged_On__cDate/Time
22BC_Reference__cText(80)Business Central's id for the update
23Last_Error__cLong Text(32,768)Last apply or sync error
24Idempotency_Key__cText(80), unique, external IDPrice Change id + OrderItem id: no duplicate lines, a resend is safe, and AIS can return acknowledgements by upsert

Also needed: a Finance permission set (create, approve, update pricebook, view) and an integration permission for AIS to update the sync fields. Seven roll-ups is well under the per-object limit (25 by default).

Options for the Business Central side

Recommended now

A. Salesforce stays the billing engine

Salesforce re-prices schedules and bills as above. Business Central receives each subscription's new price with its cutover date, and invoices from Salesforce's bills. Least change, and it reuses the AIS topics being built.

Later option

B. Business Central owns subscription billing

Salesforce sends one price-list change per product (new price, go-live, price rule) and Business Central re-prices its own contracts. Fewest messages, but it needs Business Central subscription billing in scope.

Changes to what exists

  • Manual pricebook edits for price changes stop: the Price Change writes the Standard Price Book entries (and can restore them).
  • Retire TelecareMSDPriceChangeUpdateBatch, its schedule class and the MSDPriceDateChange label after the first run on the new design. Keep its one good rule: the new schedule starts at a period start.
  • June draft in QA (TelecarePriceChangeBatch, PriceChangeService; not in UAT or Prod): reuse its product lookup by funder attribute, then retire it. As written, it sets every schedule on an order to the whole order total, and adds bills with no dates or status.
  • AIS patch batches (OrderPatchHourlyBatch, OrderLinePatchHourlyBatch, BillingScheduleHourlyBatch) pick records changed in the last hour, so a failed run can miss changes. For price changes they send from the lines instead; the same outbox pattern would make the general sync safer.
  • No whole-order resend (Order V2) for price changes.

Risks and how the design handles them

  • A wrong price reaching new orders: prices are checked across frequencies and approved before Update Pricebook can run. If one is still wrong, Restore Old Prices puts the pricebook back until go-live.
  • Pricebook edited by hand after the update: Apply compares the pricebook with each product row and stops that product's lines until they match.
  • Billing day moves if a new schedule starts on go-live day. Apply starts it on the subscription's own cycle boundary, and check 4 proves it.
  • Volume: a price change touches every live MSD subscription, tens of thousands of lines. Apply and the sync run in batches. AIS returns acknowledgements in groups (an upsert of up to 200 lines per call on Idempotency_Key__c), so header roll-ups don't hit UNABLE_TO_LOCK_ROW.
  • Old bills show new prices in three formula fields. Reports and the AIS payload use the stored …_Value__c fields.
  • Orders that change between preview and go-live (cancel, downgrade, swap): Apply re-checks each line and skips with a reason; new subscriptions get late lines.
  • Custom amounts and discounts: the preview lists subscriptions not on the list price for Finance to confirm. Line discounts carry across as today.
  • GST: excl-GST prices are worked out from incl-GST at 15% and kept to 4 decimals, matching today's pricebook.
  • First use: a full rehearsal in UAT against the Business Central test environment, with the five checks signed off, before the first production price change.

Questions

For Finance
  1. Price rule: billing periods starting on or after go-live (recommended), or bills dated on or after go-live (today's behaviour)?
  2. Who approves the prices, and who signs off the preview?
  3. Is a single uplift for all MSD products the usual case, or are prices set per product?
For the Business Central and AIS team
  1. Who generates recurring invoices in the Business Central design: Salesforce bills (A) or Business Central subscription billing (B)?
  2. Can AIS or Business Central return an acknowledgement per message, with Business Central's reference, in groups?
  3. Can Business Central hold a future-dated price per subscription? Each subscription has its own cutover date.
  4. Will Business Central upsert on Salesforce ids (OrderItem, billing schedule), so a resend is safe?
  5. A price change covers every live MSD subscription. What is the AIS limit per hour?