The CRM says sixty-two, the DMS says fifty-eight, and the manager trusts neither
In short
Two systems reporting different sold counts are usually both right, because they are counting different events on different dates — booked, delivered, funded. Prove it by reconciling a single month deal by deal into 4 buckets: in one system only, in the other only, in both with different dates, in both agreeing. The bucket sizes name the cause immediately.
Key takeaways
- Reconcile at record level. An aggregate comparison can tell you there is a gap and nothing about what caused it.
- 4 buckets are enough: CRM only, DMS only, both with different dates, both agreeing. The shape is the diagnosis.
- Booked, delivered and funded are 3 different events, and a store can be 10 days apart on the same deal.
- A CRM count higher than a DMS count is the normal direction, because the CRM records intent and the DMS records money.
- Back-dating at month end means the same month is a different number on the 1st and on the 6th. Stamp the run.
- Write the definition where the query can read it, not in a document. Undocumented definitions drift back within a quarter.
Sixty-two and fifty-eight are almost never 62 real deals and 4 missing ones. In nearly every store the gap is definitional: the CRM is counting deals a salesperson marked sold, the DMS is counting deals the office posted, and those are different events happening on different days. Prove that before anyone starts hunting for lost records, because the hunt costs a week and finds nothing.
The proof is a record-level reconciliation of one month at one store. Not a total against a total — a list of deal identifiers from each system, matched, and sorted into 4 buckets. The bucket sizes tell you the cause faster than any conversation with either vendor, and the exercise is small enough to finish in an afternoon.
Sixty-two minus fifty-eight is four buckets, not one gap
Pull both lists for a single closed month, at a single store, and match them on whatever key the 2 systems share — usually a deal number, sometimes a VIN plus a customer surname. Then count.
- Export every deal the CRM counts in the month, with its identifier, VIN, customer, salesperson and the date the CRM used to place it in that month.
- Export every deal the DMS counts in the same month, with the same columns and the date the DMS used.
- Match on the shared key. Where there is no shared key, match on VIN, then fall back to customer surname plus deal date within 7 days, and mark those matches as inferred.
- Sort every deal into exactly 1 of 4 buckets: in the CRM only, in the DMS only, in both but placed in different months, or in both and agreeing.
- Count each bucket and check the arithmetic closes. Agreeing plus different-month plus CRM-only must equal the CRM total; agreeing plus different-month plus DMS-only must equal the DMS total.
- Read the individual rows in the 3 non-agreeing buckets. There will be fewer than 15 of them, and each one has a specific, findable story.
What the size of each bucket tells you immediately
| Bucket | Most likely cause | Confirming test | Where the fix lives |
|---|---|---|---|
| Both, different months, and the count is small and stable | Different events: one system stamps booking, the other delivery or funding | Check the day gap on each straddler; a consistent 2 to 10 days is the signature | Report definition, not the data |
| CRM only, several per month | Deals that died after being marked sold, or transactions never keyed into the CRM's counterpart | Read the current status of each in the CRM; look for cancelled, unwound or still-open | CRM hygiene, plus a status the report has to exclude |
| DMS only, a handful | Sales that skipped the CRM entirely — walk-ins, fleet, wholesale, staff purchases | Ask which channels are exempt from CRM entry, and count them separately | Process, and a documented exclusion in the report |
| Both, different months, and the count is large or erratic | Back-dating at month end, or a loader that never re-reads rows it already has | Re-run the same month a week later and compare the totals | Your pipeline, and the month-end close process |
| Either only, in the dozens | Not a definition problem. A broken sync, a parse fault, or an entitlement change | Group the unmatched by date and salesperson; a clean cut-off means a break, not a definition | The integration |
The last row is the one worth ruling out first, because it is the only one that is genuinely a defect. A field-shift caused by a new column in the export will happily move a date value into the wrong column and produce dozens of deals in the wrong month, which reads exactly like a definition dispute until you look at the file — the diagnosis in the export gained a column overnight.
Booked, delivered, funded: one word, three events
The word sold does not identify an event. At least 3 candidate events sit behind it, and a store can be 10 days apart on the same deal between the first and the last.
- Booked. The customer has agreed and signed. This is what a salesperson marks, and it is what a CRM naturally counts, because a CRM exists to track intent through to commitment.
- Delivered. The vehicle physically leaves with the customer. This is the event most managers mean when they say the month's number, and it can trail booking by days when a vehicle is being prepped, located or fitted with accessories.
- Posted or funded. The office has completed the paperwork and the deal has hit the ledger. This is what the DMS counts, because the DMS is an accounting system first, and financing or documentation can hold it back further.
- Unwound. The deal is reversed after any of the above. Whether an unwound deal disappears, flips negative or keeps its original row is a per-system behaviour that has to be established rather than assumed.
None of these is the correct definition. They serve different purposes: a salesperson's pay plan and a manager's daily board reasonably run on booking, and an accounts department reasonably runs on posting. The failure is not having 2 definitions. It is having 2 definitions that nobody has written down, so that every report inherits whichever one its author happened to assume.
Which date each system stamps, and which one your report used
A deal record carries several dates and they rarely agree. Before comparing anything, establish which column each system's own report is filtering on, and then make sure your report is filtering on the one you intended rather than the one that happened to be convenient.
| Date | What it marks | Watch out for |
|---|---|---|
| Contract or booking date | When the customer signed | Editable by staff after the fact, so it is the one most often back-dated |
| Delivery date | When the vehicle went out | Sometimes blank until the office closes the deal, so filtering on it hides open deals |
| Posting or accounting date | When the deal hit the ledger | Driven by the day-end convention, so a Saturday evening deal can post on Monday |
| Row last-modified | When anything on the record changed | Useless for counting. It moves when a clerk fixes a spelling. |
The service side has exactly the same disease under different names, which is worth mentioning because teams often assume sales reporting is uniquely messy. Whether a given job counts as one operation or two, and whether a particular repair obliges a further procedure, is a definitional question with money attached — the same shape of argument as which repairs trigger a calibration.
The month-end back-date, and why the gap closes by the fifth
Run the same month's report on the 1st and again on the 6th and you will often get 2 different numbers. That is not a bug in either system. Deals signed in the final days are posted in the first days of the next month with the previous month's date, and the office deliberately holds the period open to let that happen.
A month is not closed on the last day of the month. It is closed when the office says it is, and any report that quotes it before then is quoting a moving figure.
- Stamp every report with the load it was computed from and the date that load arrived. A figure without a provenance stamp cannot be compared with the same figure quoted last week.
- Do not lock a month in your own warehouse before the store's office has closed it. Ask the controller how many days they allow, and use that number.
- Make sure your loader actually re-reads rows it has already seen, or back-dated corrections will never reach you at all — the row-hash comparison in building a change stream from a full nightly file.
- If one system's count stops moving entirely while the other keeps changing, suspect the sync rather than the definitions. A write path running under a named person's login stops silently the day that person's password changes, which is the argument in the integration ran under a person's login.
Writing the definition where the report can read it
The reconciliation is worth doing once. Making it stay done is a different job, and a document does not achieve it — definitions written in a document drift back within a quarter because nothing enforces them.
- Name the metric for its event, not for the outcome. 'Units delivered, delivery date, this store' is a name nobody can misread. 'Sales' is not.
- Encode the definition in one place — a view, a model, a single query — and make every dashboard read from it rather than reimplementing the filter.
- State the exclusions in the metric itself: unwound deals, wholesale, staff purchases, fleet. An exclusion that lives only in someone's head is a future 4-unit gap.
- Publish both numbers side by side where both are legitimate, with the bridge between them shown. A manager who can see the 3 straddlers stops distrusting both systems.
- Re-run the 4-bucket reconciliation monthly and automatically, and alert only when the non-agreeing buckets change shape. Under 15 exceptions a month is a healthy store; a sudden 40 is an integration incident.
That last item is a small, specific build: 2 extracts, a matcher, 4 counts and an exception list emailed to whoever owns the number. It is the sort of narrowly scoped internal product we take on under MVP and product builds, and it is worth doing before a group-level dashboard is attempted rather than after. The rest of this silo sits under DMS, CRM and shop-system integration, inside our automotive work.
Frequently asked questions
Short answers to the follow-ups this page tends to raise.
Why does the CRM show more sales than the DMS?
Because the CRM records commitment and the DMS records money, and commitment happens first. A salesperson marks a deal sold when the customer signs; the office posts it when the paperwork clears, which can be several days later and sometimes in the following month. Deals that die between those 2 points stay counted in the CRM unless the report explicitly excludes them.
How do I reconcile deal counts between a CRM and a DMS?
Take one closed month at one store, export the deal list from each system with identifiers and dates, match them, and sort every deal into 4 buckets: CRM only, DMS only, both with different months, both agreeing. The arithmetic must close against both totals. The relative sizes of the 3 non-agreeing buckets tell you whether you have a definition difference, a process gap or a broken integration.
Is a 4-unit gap between two dealership systems a problem?
Usually not, if it is stable and explainable. A store with a handful of straddling deals, a few cancellations and a couple of channels that bypass the CRM will show a small persistent gap every month, and that is normal. The gap becomes a problem when its size or shape changes suddenly, which is the signal an integration has broken rather than a definition drifting.
Which system should be treated as the source of truth for sold units?
The DMS, for any number that has to reconcile to the accounts, because it is where the money is recorded. The CRM remains the better source for activity and pipeline. The workable arrangement is to publish both, name each one for the event it counts, and show the bridge between them rather than picking a winner and hiding the other.
- dms integration
- crm
- reporting
- reconciliation
The work behind this page
Builds from our portfolio that this page draws on.
Read next
- Yesterday's export does not match today's copy of yesterdayA figure that was right on Tuesday is different on Wednesday. Four things cause that, three of them at the vendor and one in your loader, and the only thing that separates them is the raw files themselves.diagnostic
- The deal was voided in the DMS and it is still open in your appA voided deal or a deleted repair order never announces itself. It simply stops appearing in tonight's file, which looks identical to a truncated transfer — so the inference needs a health check before anyone trusts it.diagnostic
- The DMS and the CRM each believe they own the customerSample twenty customers who both bought and serviced, and count how many link on an identifier both systems actually store. The failure rate tells you whether this is drift or a missing design.diagnostic
- Data brokers in the dealership stack: who is actually sending you the fileBetween the dealership's system of record and your build sits a party with its own schema, its own cadence and an authorisation only the dealer can sign or revoke.definition
- Four times a repair-order number changes, and what to key on insteadAn RO number identifies a document at one store on one day. Four ordinary events renumber, duplicate or supersede it, and a fifth problem makes it repeat outright.definition
- The export gained a column overnight and the parser did not noticeThe vendor adding a column is normal. A loader that trusts field position is the defect, and the fix is three assertions that run before the first row is parsed.diagnostic
Working on something in this space?
Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.
Start the conversation