Skip to content
The margin report and the profit and loss don't agree

The margin report and the profit and loss don't agree

“The margin report and the profit and loss don’t agree” — that is ordinary: the cost stored on a finalised sales line is rewritten whenever a back-dated purchase lands, while no sales document posts a cost-of-sales journal at all, so the ledger follows on a different timetable and only when month-end is re-run for the affected months.

Your gross profit report says something different from the profit and loss. Or worse: it says something different from what it said last week, for a quarter that closed months ago.

Both are usually the same cause seen from two angles. A check of about thirty seconds tells you which figure moved, and a short table covers the other ways the two part company.

The 30-second check

Read three things: the margin report’s cost, the same branch on the live profit and loss, and the moment the ledger’s cost of sales was written. For GadgetSphere that is March 2026 at GS-KV-01. The margin report says gross margin RM 61,400; the copy you printed on 2 April said RM 63,800, and the March profit and loss has not moved since the month was closed that evening.

  1. The margin report’s cost. In the Sales Report applet, run SR By Item Code for branch GS-KV-01, 1 to 31 March, with Calculate Base On left at its default, the moving average. The footer reads Sales Amount RM 412,000, Sales Cost RM 350,600 and GP RM 61,400.
  2. The same branch on the live profit and loss. In the Financial Report applet, run the Profit Loss Report: Group By Branch, tick GS-KV-01, the same dates, Cost Type MA. In the GS-KV-01 column, read the row labelled Inventory Cost under Cost Of Goods Sold.
  3. The moment the ledger’s cost of sales was written. In Ledger And Journal, find the journal described AUTO CREATED FROM COGS PROCESSING with Transaction Date 31 March. Its Branch column is blank, and its Created Date is when month-end last ran: 2 April, 18:05.
Inventory Cost (step 2)The cost-of-sales journal (step 3)What it meansNext
RM 350,600, the same as the margin reportCreated after the last purchase dated in March was keyedPass. Both reports read the cost stored on the same sales lines today, and the ledger has seen every March purchase. Whatever still differs from the statements is either two measurements of one month or one of the six causes belowWhy the ledger does not follow, then the six other ways
RM 350,600Created 2 April, 18:05 — and a purchase dated in March was keyed after thatThe ledger’s figure is older than the cost on the lines. In the Purchase Invoice listing, search with Created Date from 2 April: an invoice for 40 ultraportable laptops, dated 10 March and keyed on 9 April, comes back. It rewrote the stored cost on March’s later laptop sales, and that is the RM 2,400 your margin lostWhat to do about it
RM 350,600Not thereMonth-end ran and wrote no cost of salesThe first row of the table
Not RM 350,600AnyThe two reports are not reading the same lines. The margin report counts trade-in lines and files each sale under its document’s branch; the Profit Loss Report leaves trade-ins out and files each line under its own branch. Or the two were run at different times, and a back-dated purchase moved the stored cost in betweenRun both again, one straight after the other

Gross profit can still differ when the cost agrees. The Profit Loss Report takes its sales from posted journals, so a credit note counts there and not on SR By Item Code, and a sale whose journal failed counts on the margin report and not there. Its Total Cost of Goods Sold also adds any posted journal on a cost-of-sales account other than the purchases accounts, which is why it can sit above Inventory Cost.

What actually happened

When you finalise a document that moves stock, the chain posts the stock movement first, then works out what that stock cost, then writes the cost back onto the document line. Moving average and FIFO both land there, side by side, so a report can read a column instead of replaying a history.

Here is the part nobody expects: the cost stored on a finalised document line is not final.

Post a purchase invoice dated back into a month you have closed, and a replay walks forward through every later movement of that item and rewrites the stored cost on each one’s document line — with no filter for posting status and none for a locked period. Two queues keep that affordable. One replays the moving-average chain forward from the back-dated line. It is a queue, not part of your save, so the rewrite is not instant — expect a margin report to keep moving for a while after you post the back-dated document, and do not read the two minutes after the post as the final answer. The other is a FIFO dirty list keyed on company and item, keeping only the earliest dirty point, so an item edited fifty times is replayed once rather than fifty times. That FIFO replay does not run by itself, though: it is a repair somebody starts, and no schedule starts it for you. If your company reports on FIFO, the moving-average cost on the line catches up on its own and the FIFO cost waits until the rebuild is run. Your system administrator asks BigLedger support to run it.

So last quarter’s gross margin genuinely can move after the fact, and correctly so — you have just learned what that stock really cost.

Why the ledger does not follow

What does not move is the general ledger. No journal is reposted by either replay path. In fact no sales document posts a cost-of-sales journal at all.

Cost of sales is a month-end computation: opening stock, plus purchases, less purchase returns, minus closing stock. Month-end also takes the other side of a stock adjustment or a moving-average reset back out, so a stock-take write-off stays on its adjustment account rather than in cost of sales (When cost of goods sold reaches the ledger states the formula once). The closing stock is valued from whichever cost column your company’s Inventory Closing Base On setting names, defaulting to moving average.

Two consequences are invisible from either report. The figure is company-wide. The journal month-end writes carries an account and an amount, and no branch, so the ledger holds no GS-KV-01 cost of sales at all; the only branch-level cost BigLedger has is the cost on the sales lines, which both reports in the check read. And it is stock arithmetic, not a sum of sales. Anything that changed the value of the stock counts, whether or not anyone sold anything.

Follow that through and you have the sequence that produces the question:

  1. A back-dated purchase lands.
  2. The stored cost on last quarter’s sales lines is rewritten by the replay. Your sales and margin reports, which read those columns, change.
  3. The general ledger does not move, because no journal was posted.
  4. The two come back together only when somebody re-runs month-end for the affected months — which deletes the old cost-of-sales journal and posts a new one.

“The margin report and the P&L don’t agree” is, nine times in ten, exactly this, with step 4 not yet done.

What to do about it

  1. Find the back-dated document. In the Purchase Invoice applet, search with Created Date from the Created Date of the month’s cost-of-sales journal. Every invoice that comes back was keyed after the ledger’s figure was written, whatever date it carries; the ones dated inside a closed month are the cause.
  2. Re-run Month End Processing for the earliest affected month, then every month after it, in order. That is what reposts cost of sales. If your Inventory Closing Base On is FIFO, have the FIFO rebuild run first, or month-end values closing stock from FIFO costs that have not caught up.
  3. Then regenerate any Financial Report snapshot covering those months, or the statements will keep showing the old figures.
  4. Read both reports again. If they now agree, the rebuild was the missing step — and it is part of the correction, not an optional extra.
A locked period does not stop the cost replay. The replay updates later document lines with no posting-status filter and no period filter. Locking a period protects it from new documents; it does not freeze the costs already written on the documents inside it. If a figure must not move, take it from the ledger, not from a margin report.

Six other ways the two figures part company

The check sends you here when the cost on the lines agrees and the ledger’s figure still does not, and the timing is not the reason. Each of these leaves the margin report right and the profit and loss out.

What you seeCauseFix
March has no cost of sales on the Profit And Loss tab of the Financial Report snapshot, and step 3 finds no journal — or March’s figure vanished the day somebody pressed PROCESS againThe company has no Cost of goods sold or no Stock balance default GL code, so the cost-of-sales journal does not balance and is refused. The close discards the refusal and reports success, and on a re-run it has already deleted the old journal. With no Purchase default the journal is written, counting March’s purchases as zeroIn the Chart of Account applet, on GadgetSphere’s Default GL Codes, map Stock balance to INV-STOCK-CONTROL and Cost of goods sold to COST-DEFAULT on the Stock sub-tab, and Purchase to EXPENSE-PURCHASES. Then PROCESS March and look for the journal again
The ledger’s cost of sales is short by one supplier invoice — RM 88,000 for a distributor’s delivery of wireless audio — although the margin report already reflects it. In the Financial Report applet, Error Checking › Stock Flow Report for GadgetSphere and March shows a Difference of RM 88,000 on the Purchases rowThe invoice’s stock job ran, so the goods are on the shelf and in the moving average, but its journal job failed and nothing reached EXPENSE-PURCHASES. Month-end counts purchases only from posted journals on that accountClick the Difference to list the invoices behind it; the one whose Amount Acc is zero has no journal. Fix what failed it, then run Trace Document on it: the failed Missing Journal check shows Resolve, which writes the journal. Where Posting Journal reads POSTED but the amount is wrong, Repost builds it again from the document. Then PROCESS March
The same Purchases Difference, and the invoice’s journal is there — on another accountThe purchase went to an item’s or a line’s own GL code, which month-end does not countSee the other cause below
March’s ledger cost of sales is lower than the lines suggest by the value of goods received in late March, and April’s is higher by the same amountThe goods came in on a GRN Stock In and the supplier’s invoice is dated April. The stock-in puts the goods into stock and the moving average at once but posts to the received-not-invoiced accounts; the purchase reaches the Purchase account only with the invoice. So March’s closing stock holds goods that March’s purchases do notNothing is broken, and the two months correct each other over the quarter. If March must stand on its own, whoever closes the month decides whether to wait for the supplier’s invoice before closing it, or to key a manual closing value without those goods (The goods you received but were not billed for)
The ledger’s cost of sales is out by roughly the gap between your FIFO and moving-average costsInventory Closing Base On is FIFO and the margin report is on its default, the moving average. Or the FIFO costs are behind, because the FIFO rebuild has not been run since a back-dated purchaseCompare like with like: run SR By Item Code with Calculate Base On set to FIFO. If the FIFO figures are behind, have the rebuild run, then PROCESS the month
The ledger’s cost of sales moved by a round figure that matches no documentA manual closing stock value for the month. The company’s fiscal-year stock values in the Chart of Account applet (Edit Closing Stock Balance) hold a system and a manual figure; with Select Manual ticked and a manual figure in it, month-end uses that figure for closing stock and for next month’s openingOpen the month there, see which figure is selected and who keyed it. Whether it stands is for whoever signs the month to decide

Two things look like causes and are not. A returned laptop comes back into stock at the average standing just before the return — RM 2,950, not the RM 3,100 it left at — so RM 150 of cost stays behind (Sales Return explains why). It stays on both sides: the margin report nets the return at RM 2,950, and closing stock rises by the same RM 2,950. A sale or purchase in US dollars is the same story. Finalising it makes a ringgit copy, and the stock, the journal and both reports all work from that copy (Purchase Invoice shows the mechanism).

The other cause: purchases on their own GL code

Month-end counts purchases only on the company’s default Purchase and Purchase Return codes. That is a setup rule — one purchases account per company — so a purchase posted to an item’s or a line’s own GL code is not counted in cost of sales, and re-running month-end does not change that. What the P&L then shows depends on how that account is classified. If its GL category is Purchases (or Purchases Returns), the P&L leaves it out as it leaves out the default, and cost of sales comes out short. Under any other category in a cost-of-goods-sold section, the P&L shows it as a raw purchase. Either way the P&L can disagree with the margin report. Post all purchases to the default Purchase code.

What this comparison leans on, and what leans on it

What must exist before the two can agree. Three background jobs and a handful of settings. The stock job writes the cost back onto each sales line after it goes FINAL, and until it has, both reports read an empty cost. The journal job posts each purchase invoice to the Purchase account, and month-end reads purchases from there and nowhere else. Month-end itself needs the Stock balance, Cost of goods sold and Purchase defaults on the company in the Chart of Account applet, and values closing stock on the basis Inventory Closing Base On names.

What becomes possible once they agree. A month whose cost of sales you can stand behind. The retained-earnings, closing and opening journals that Month End Processing writes after it carry that figure forward, and the snapshot you regenerate afterwards is the one you file.

Its siblings, and when to use which. When two numbers don’t tally is the general triage; start there when you are not sure the margin is the figure that moved. Which figures BigLedger stores, and which it works out fresh is the same stored-against-live split in four other places. Closing the Month on Stock is the stock side of the same close: cut-off, the valuation basis, a manual closing value. And when the trouble is a quantity rather than a cost, use The stock quantity shows zero and there is stock on the shelf instead of this page.

What breaks elsewhere if this is wrong. Re-processing March rewrites April’s opening, so every later closed month is stale until you PROCESS each one in order and regenerate the snapshots that include them. A purchase back-dated into a closed quarter moves the margin on every later sale of that item, locked period or not. And a re-run that fails has already deleted the month’s previous cost of sales.

What it pairs with in practice. You will use it alongside three screens of the Financial Report applet — the Profit Loss Report (the live, branch-level figure), the Stock Flow Report (purchases month-end will not count) and Trace Document (one document’s missing or wrong journal) — and the journal listing in Ledger And Journal, which shows whether, and when, the cost-of-sales journal was written. The margin report itself is the Sales Report applet.

What success looks like

Run these for the month you corrected. Together they take about two minutes.

  1. The 30-second check passes. Inventory Cost for GS-KV-01 equals the margin report’s Sales Cost, and step 3’s journal is there, created after the last purchase dated in March was keyed.
  2. The Stock Flow Report’s Purchases row for GadgetSphere and March shows no Difference — or only the tax on the month’s purchase invoices, which the document side counts and the Purchase account does not.
  3. Each ledger has its closing and opening journals for March as well as the cost-of-sales journal, because a close that fails still reports success. The Financial Report applet has that minute-long check.
  4. Hand the comparison to whoever signs the month, not to the person who re-ran it. They read the cost-of-sales journal’s Created Date against the last purchase keyed for the month. When a purchase lands in a month they have already signed, the person who keys it tells them, because the margin report will simply move without a message.

When it is a support matter

The margin report and the ledger still disagree after month-end has been re-run for every affected month, in order. At that point it is no longer a timing difference. Report it with the item, the months, and the two figures.

A negative unit cost on an inventory or costing report is something else, and it is not a data error. Moving-average unit cost is the balance’s total value divided by its quantity. Let a negative adjustment take an item’s quantity below zero and that division can come out negative — an arithmetical artefact of costing stock you did not have, not a loss and not corruption. The transaction chain underneath is intact. Treat a negative unit cost as a flag that the item went short, and fix the quantity.

What this page cannot tell you

  • When the cost on a given line was last rewritten. The line carries the cost, not the history of the cost.
  • How long a replay takes. It is queued and finishes when it finishes.
  • Why one line’s cost is what it is. Both reports show the stored cost, not how it was worked out; Costing internals has the formula as coded.

Related documentation

Last updated on