DC

Insights

15 findings, ordered by commercial weightEvidence from the live BC tenant, 11 Aug 2026
Replaces: the audit deck nobody opens twice, and the spreadsheets built around it
4,500item locations priced below cost or with no cost at allRead the finding
1.5%of the forecasting engine's buying advice reaches an orderRead the finding
41.5average days late across 400 released ordersRead the finding
0 of 5approval workflows running, since June 2025Read the finding
Ask the findingsOne question, answered from the figures on this page and nowhere else.15 findings, all cited
The answer is built only from the figures above, each of which names the file and row it came from. Where the page does not hold an answer it says so rather than reaching for one, and no figure is ever estimated, extrapolated or rounded for effect.

What the evidence says is going wrong, ordered by what it costs, each with the action that closes it. Every number names the file it came from.

01Pricing and marginHighest impact

MSC are selling part of the range at a loss and the system does not stop them.

Defects by count, against 70,400 item locations4,500item locations priced at or below cost,or carrying no usable cost at allout of 70,400 across the two sitesSelling price at or below costapprox 2.5kCost price zero or negativeapprox 2.0kProduct description missingapprox 2.8k6.4 per cent of the item location estate, and any of it can be quoted, ordered and invoiced without a warningNetstock data quality dashboard, 11 Aug 2026. The 6.4 percent is the two red rows, 4.5k over 70.4k. Missing descriptions are a separate defect and are not in that count.
What to do

A margin floor on the price record, checked at the point of sale. It turns silent defects into a queue somebody clears once.

Why it ranks 01

Ranked first: it loses margin on every affected line today, and nothing stops it.

Source · msc-bc-audit/netstock-functionality-register.csv row NSF-012: score 97.75 percent, cost price <= 0 approx 2.0k, selling <= cost approx 2.5k, product descriptions missing approx 2.8k. Total item locations from NSF-016, approx 70.4k (EAST approx 27.9k, WEST approx 26.6k).
03Pricing and marginHighest impact

Two customers can hold two different prices for the same product and nothing in Business Central raises it. The pricing work already built finds them, and it treats a ten per cent spread as the point where somebody should look.

30%spread the rule calls high severity
15%the medium band starts here
2prices minimum before a SKU is looked at
max, minthe spread is measured against the lowest price
Severity bands, as the rule already defines themHigh, 30 per cent spread and above30%+Medium, 15 to 30 per cent15 to 30%Low, 10 to 15 per cent, the reporting floor10 to 15%The bands are the code's own, not a proposal. Variance is (max minus min) divided by min, so a line sold at 100 and at 200 reports 100 per cent.
Why it matters

Two buyers comparing notes is how this gets found today. The rule to find it first already exists and it is ours.

What to do

Run it on a schedule, group it by SKU and put the output in front of the person who owns the price. Carry the caveats with it: the rule buckets on the SKU alone, so unit of measure, currency, quantity break and effective date are not yet part of the key.

Why it ranks 03

Ranked third: it is the defect the pricing project was built to find, and the rule is already written.

Source · msc-data-project lib/pricing/discrepancyRules.ts lines 7 to 11 (variancePct >= 30 high, >= 15 medium, else low), line 15 (minVariancePct default 10), line 42 (a SKU needs at least 2 prices), lines 59 to 61 (averages to 4 decimal places, variance to 2). Same default at pages/api/reports/discrepancies.ts lines 13 to 14. Bucketing on SKU alone is visible in the same file.
04Pricing and marginHigh impact

The pricing estate behind the ladder runs to roughly 650,000 sales price lines, and the comparison that checks them holds no tolerance at all.

2,600pages per segment to read them, at 250 a page
4decimal places the unit price is held to
0tolerance in the price comparison
80price lists deep filled on every sync run
Why it matters

An exact comparison at that scale is honest but unforgiving. A rounding difference of a hundredth of a penny reads the same as a real conflict, so the tolerance is a business decision that has not been taken yet.

What to do

Set the tolerance where the business wants it, in one place, and state it on every report that uses it. The platform carries the figure so a finding cannot be argued with.

Why it ranks 04

Ranked fourth: it sizes every other pricing finding on this page.

Source · msc-data-project pages/reports/price-conflicts.tsx line 314: "Per-segment OData page cap. ~650k lines at pageSize 250 needs >= 2,600 pages per segment." This is the project's own working figure, written to size a page cap, and it is the only scale statement the repository commits. lib/pricing/comparePriceLists.ts line 39 compares with === and no tolerance. prisma/schema.prisma holds BcPriceLineCache.unitPrice as Decimal(12,4). lib/bc/sync.ts line 235 caps the page size at 250 and line 238 targets 80 price lists a run.
05Pricing and marginHigh impact

The price a customer pays is decided by a ladder where the first matching rule wins, not the best one, so a customer can hold a better rule further down and never get it.

13levels of price precedence, evaluated in order
13pricing methods in scope, cost plus to indexed
1stmatching rule wins, best or not
The top of the ladder, and where the everyday price sits1 Customer, contract, site, channel, productchecked first4 Customer, contract, productlevel 47 Customer, productlevel 710 Customer price listlevel 1013 Standard MSC pricechecked lastBars show position in the ladder, not value. Levels 2, 3, 5, 6, 8, 9, 11 and 12 sit between these, listed in the scope.
Why it matters

A ladder this deep is an asset only if a sales manager can read it before approving a discount.

What to do

Show the winning level on every priced line, by name, with the rule that beat the others. Scope chapter 14.4 already requires the record, so this needs a screen rather than a build.

Why it ranks 05

Ranked fifth: it sits under every priced line and nobody can explain a single one.

Source · docs/reference/product-scope-pricing-authority.md lines 9 to 27 (the thirteen levels, first applicable rule from 1 to 13 wins, not a best-price search) and lines 36 to 49 (thirteen pricing methods; price governance fields required by scope chapter 14.4). Source authority: mCentral OPS Product Scope, chapter 14, pages 24 and 25.
09Pricing and marginHigh impact

MSC govern what they sell for and not what they pay. Discount posting is switched off on both sides.

S-PLsales price list, last used 10 Jul 2026
PPLpurchase price list, never used
No Discountsposting setting, sales and purchases
Price list series in the tenant, by state
Active, sales S-PLStale, jobs J-PL, last used 11 Jul 2024Never used, purchases PPL
The three price list number series in the tenant, read on 11 Aug 2026.
Why it matters

With cost on vendor cards and discounts unposted, margin is something a person reconstructs in a spreadsheet after the invoice has gone.

What to do

Hold cost and price as one governed record, landed cost and rebates netted off, and show live margin on the quote. Price authority already exists, this is its missing half.

Why it ranks 09

Ranked ninth: it is why the margin defect above cannot be measured.

Source · msc-bc-audit/number-series-usage.csv rows 106 (S-PL, active, 10/07/2026), 67 (PPL, never) and 46 (J-PL, stale, 11/07/2024); data-migration-inventory.csv row 5 (S-PL active, PPL never, purchase prices possibly on vendor cards); 02-environment-and-modules.md lines 66 and 68 (discount posting No Discounts on both setups).
11Pricing and marginModerate

Underneath the ladder the live system prices from the site account, then the company account, then falls back to a default category without saying so.

Sell tosite account, asked first
Bill tocompany account, asked second
Materialscategory used when both are silent
Why it matters

Two sites of one customer can be charged differently and nothing on the order says so.

What to do

Make the fallback fail loudly. Every priced line names the record that priced it, and a line that reached the default waits for a person.

Why it ranks 11

Ranked eleventh: narrower than the ladder, and the fallback posts without asking.

Source · msc-bc-audit/al-source-findings.md line 35 (resolved from the customer price list, sell-to first, then bill-to, fallback item category Materials) and line 156 (lines are re-priced from the customer price group price list). Restated in docs/estate/appendix-b-bc-audit-distillation.md rows 93 and 342.
14Pricing and marginModerate

Changing a price used to stop the sales floor for a minute at a time. The webhook that published price changes ran synchronously.

60+seconds sales users were blocked
3price list line events firing a webhook
Why it matters

When maintaining a price is painful, prices stop being maintained. That is how a range drifts into selling below cost.

What to do

Keep price publication asynchronous and make price work quick: bulk jobs with preview, approve, apply and rollback.

Why it ranks 14

Ranked fourteenth: the outage was fixed. The habit it left behind was not.

Source · msc-bc-audit/al-source-findings.md lines 107 and 112 (price and ABL webhooks on price list line insert, modify and delete; blocking sales users for 60+ seconds on price updates); customisations.csv row EXT-010 BiApiExt; docs/estate/appendix-b-bc-audit-distillation.md line 82.
What it adds up toIf you read one thing on this page
Stop the leak

A margin floor checked at the point of sale. Highest value change on this page, and it is a rule, not a rebuild.

Show the price

Name the winning level on every line. Thirteen levels of precedence stop being a liability and start being the asset they should be.

Buy what the engine says

Moving stock MSC already own between two sites they run is the cheapest service fix available. Today none of it happens.

Bill sooner, prove control

Late orders, uncounted quotes and stalled approvals all fix the same way: the work goes back on a screen with a name against it.

Where these figures come fromIncluding how the order was decided

Two sources, and every card names its own. The pricing work already built at gitlab.personify.tech/msc/msc-data-project, read directly, file and line quoted. And the read only audit of the live MSUPPLY LIVE Business Central tenant of 11 Aug 2026, the Netstock UI audit of the same day, the AL source read from the tenant's own extensions, and Product Scope chapter 14.

The data project publishes rules, not results. Its findings tables are declared and never written, its seed creates nothing and every count it shows is computed live and discarded, so what it contributes here is its thresholds, its comparison rules and its own record of what is still to build. Its mock fixtures are never shown as findings.

Two caveats travel with the audit numbers and both stand on their cards. The 999 plus open quotes is a display ceiling, so a floor rather than a count. The 400 delayed orders was recorded at medium confidence. The 650,000 price lines is the data project's own working figure for the size of the job, written to size a page cap, not a verified count.

The order is a commercial judgement, not a measurement. Each finding states the basis for its placing, built only from the figures cited on it. No pound value is attached to a finding the source did not price.