A vendor invoice tells you a great deal. It names the supplier, the buyer, the invoice number and date, the lines with their descriptions, quantities and prices, the tax, the total and the terms. Sometimes it carries a purchase order number, a ship-to address or the name of the person who ordered the work. What it almost never tells you is the one thing the ledger needs before the invoice can post: which general ledger account the cost lands in, and which cost center, project or department carries it.

That is not an omission by the supplier. The account belongs to the buyer’s chart of accounts, and the supplier has no reason to know it. The same box of printer toner is office supplies for one company, a cost of goods sold for a print shop and a project expense for a consultancy that bills it through. The invoice describes what was sold. The coding describes what the purchase means to the business that bought it.

So GL coding is a second job that sits next to extraction, not inside it. Extraction reads what the document says. Coding proposes where the cost belongs, from evidence that mostly lives outside the document. This piece describes where a coding suggestion should come from, how strong each signal is, when a suggestion has to go to a person, and what an extraction pipeline should hand to the accounts payable team so that the suggestion stays a suggestion until someone accepts it.

What the invoice gives you, and what it does not

Start by separating the facts the document carries from the decision the business makes. The document carries evidence that informs coding:

  • Supplier identity — name, tax ID, remit-to address. Once resolved to a supplier record, this is the key to every historical signal below.
  • Line descriptions — the words the supplier uses for what it sold. Useful, but written for the supplier’s catalogue, not the buyer’s ledger.
  • References — purchase order number, contract number, job or ticket number, the requester’s name.
  • Location and period — ship-to or service address, and the service period for recurring charges.
  • Amounts — line amounts, tax, freight and other charges, each of which may code differently.

None of these is an account. A pipeline that writes an account number into the extracted invoice as if it had been read from the page is mixing two kinds of value: one that can be checked against the source image, and one that cannot. The first should carry a page and region. The second should carry the reasons it was proposed.

Where a suggestion comes from

Coding signals are not equal. Some are decisions the business already made and recorded; others are inferences from text. A useful way to rank them is by how much of the decision was already taken by someone with authority to take it.

The purchase order. When an invoice is matched to a purchase order, the coding was decided when the order was raised and approved. Microsoft’s documentation for Dynamics 365 Finance describes this directly: for vendor invoices associated with a purchase order, the default financial dimensions on the invoice lines come from the corresponding purchase order lines. The invoice is not where the decision is made; it inherits it. A suggestion engine that ignores a matched PO and re-derives the account from the line description is overriding an approved decision with a guess.

The supplier’s posting history. For invoices without a purchase order — utilities, subscriptions, professional services, facilities — the strongest signal is usually how the same supplier’s invoices were coded before. If fourteen of the last fourteen invoices from a cleaning contractor posted to the same facilities account and the same cost center, the fifteenth probably belongs there too. History is stronger than the line text because it records what an accountant actually chose, not what the supplier chose to call the service.

Defaults on the supplier and account records. Many ledgers let a supplier record carry default dimensions, and let a main account carry default or fixed dimension values. Dynamics 365 documents that default dimensions come from several places, including master records such as vendor records, document headers and the main account, and that for an invoice not linked to a purchase order, the dimension on a line follows a stated priority when the same dimension is defined in more than one place. The lesson for a suggestion engine is not the specific order of one product. It is that the ledger already has precedence rules, and a suggestion should be produced inside them, not beside them.

The document itself. Line descriptions, ship-to addresses and requester names are the weakest signals, and the most tempting. They are useful as tie-breakers and as reasons to doubt a historical pattern: a familiar supplier billing a line the company has never seen before, or shipping to a site that belongs to another cost center. On their own, they are a starting point for a person, not a basis for posting.

Signal, suggestion, evidence, review

Put together, a coding suggestion is a small record with four parts: the signal it came from, the coding it proposes, the evidence a reviewer can check, and the condition under which it goes to review instead of being accepted. The table below shows the common cases.

Signal on or around the invoiceSuggested codingEvidence to keep with itWhen it goes to review
Invoice line matched to an approved purchase order lineThe account and dimensions on the PO linePO number and line, approver, match resultThe invoice line does not match the PO line, or the PO line has no coding
Non-PO invoice from a supplier with a stable posting historyThe account and cost center most often used for that supplier and that kind of lineHow many prior invoices agree, the date range, and the most recent postingHistory is split between accounts, is short, or the latest posting differs from the pattern
Supplier or account carries a default dimensionThe default, inside the ledger’s own precedence rulesWhich record supplied the defaultThe default conflicts with the history or with a document reference
Line text only, no history (new supplier or new kind of purchase)Candidate accounts ranked from the descriptionThe words that drove each candidateAlways: a cold start is a person’s decision
Ship-to, requester or job number points to a different cost center than historyBoth candidates, not oneThe document field and the historical pattern side by sideAlways: the signals disagree
Freight, tax or other charges on the invoiceCoding per the company’s charge rules, separate from the goods linesWhich charge, which ruleA charge with no rule, or an unallocated charge

Two rows end in “always”. That is deliberate. A system that has no history to lean on, or two signals that point in different directions, has nothing to resolve the decision with. Ranking candidates is useful; choosing between them silently is not.

A suggestion is not a selection

We have written before about a related failure in SAP invoice validation. In The OCR Was Right. SAP Still Said No. the point was that a system which silently substitutes the closest supplier, changes the company code, applies a default tax code or selects a “similar” cost center can produce a record that posts cleanly and says something the invoice did not. A successful post is not proof the choice was right.

Coding suggestions live on the same edge, and the rule carries over unchanged. A suggestion engine exists to save the accounts payable team from typing the obvious account fourteen times a month. It does not exist to make the fifteenth decision when the fifteenth invoice is different. The difference between the two is whether the proposed coding is shown as a proposal — with its evidence, open to correction — or written into the posting as if it were a fact.

The ledger draws a similar line of its own. Dynamics 365 distinguishes a dimension that is Not fixed, which uses a default value that can be overwritten, from one that is Fixed, where the system always applies the value regardless of what was defaulted or entered. Account structures and advanced rules then define which combinations of main account and dimension values are valid at all. Those controls belong to the finance team. A suggestion should be checked against them before it is shown, and a suggestion that fails them should be reported as failing, not replaced by the nearest combination that passes.

In practice that means three states for every coded line, not two:

  • Proposed — the pipeline’s suggestion, with signal and evidence, not yet accepted.
  • Accepted — a person or an explicit rule confirmed the proposal, and the record says which.
  • Corrected — a person changed the proposal, and the record keeps both the proposal and the correction.

The corrected state is the valuable one. It is the only place where the system learns that its signal was wrong, and the only evidence an auditor has that the suggestions were reviewed rather than rubber-stamped.

A worked example

Take a facilities management supplier that sends one invoice a month to a company with three offices. The October invoice has three lines.

Line 1: monthly janitorial service, main office, $4,200. No purchase order; the service runs under a contract. The supplier’s last fourteen invoices all carried this line, and all fourteen posted to the facilities services account with the main office cost center. The service period on the invoice is October, which matches the cadence. The suggestion is the same coding, with the evidence “14 of 14 prior postings, most recent September”. If the company’s policy allows it, a rule can accept this line without a person. Either way, the record says what accepted it.

Line 2: replacement compressor for rooftop unit, $8,400. The same supplier has billed repairs before, and history points to the repairs and maintenance expense account. But this line is twice the size of any previous repair, and its description names a component of a building system rather than a service. Whether it is an expense or something the company capitalises depends on the company’s own accounting policy and thresholds, which the invoice does not and cannot carry. The suggestion shows the historical account as a candidate and routes the line for review with the reason stated: amount outside the supplier’s historical range, description unlike prior lines. It does not pick an asset account on its own, and it does not quietly post the expense either.

Line 3: cleaning supplies, delivered to the second office, $310. History codes supplies from this supplier to the main office cost center, because almost every delivery went there. This one carries the second office’s address as the ship-to. The two signals disagree, and nothing on the document says which is right: the supplies may be for the second office, or the supplier may have used an old address. The suggestion shows both cost centers with their evidence and asks.

The invoice goes to the accounts payable clerk with one line already proposed with strong evidence and two lines flagged, each with a reason a person can act on in a few seconds. That is the work saved. The work not saved — deciding the compressor and the delivery — is the work that should not have been automated.

Patterns that show up across a batch

Single invoices are only part of the picture. Coding suggestions built on history also fail in ways that only appear across many invoices:

  • Inherited mistakes — one miscoded posting becomes the pattern for every invoice after it. A history signal should report how many postings agree and how recent they are, so that “3 of 3, all since July” reads differently from “40 of 41 over two years”.
  • Reorganisations — cost centers are merged, renamed or closed, and history keeps pointing at a code that no longer accepts postings. A suggestion has to be checked against the current valid combinations, not only against the past.
  • New suppliers — with no history, every line is a cold start. Treat the first invoices from a new supplier as the ones that set the pattern, and route them to a person accordingly.
  • Split lines — a single invoice line shared across departments by percentage or by headcount. The allocation is a rule the business owns; the suggestion should name the rule it applied, not just the resulting accounts.
  • Supplier drift — a supplier that starts billing a different kind of service under the same contract. The line text changes before the history does, which is exactly when the weak signal deserves weight.

What the extraction has to deliver

Coding sits downstream of extraction, but extraction decides whether coding can be done well. To support reviewable suggestions, an extracted invoice should carry, per line:

  • The source line — description, quantity, price and amount as printed, with page and region, so a reviewer can see what was actually billed.
  • The references — PO and PO line, contract, job number, requester and ship-to, each kept as its own field rather than folded into the description.
  • The proposed coding — account and dimensions, held apart from the extracted fields and labelled as a proposal.
  • The signal and its strength — which source produced the proposal and how much agreement stands behind it.
  • The alternatives — other candidates when signals disagree, with their evidence.
  • The review reason — a plain statement of why a line was not accepted automatically.
  • The decision record — accepted or corrected, by whom or by which rule, and when.

This is the shape Cogneris uses for finance work: GL-code and cost-center suggestion that maps extracted invoice data to your chart of accounts with override capability, per-vendor coding learned from your historical entries, and rule application that stays auditable. Suggestions ship with a confidence score, and accounts payable keeps final approval.

Keep the two jobs apart

An invoice is a supplier’s statement of what it sold and what it is owed. The GL account is the buyer’s statement of what that purchase means. Reading the first well is extraction. Proposing the second well is a separate job that leans on purchase orders, posting history and the ledger’s own rules, and gets weaker the more it leans on the invoice text alone.

Keep them apart in the data, and both get better. The extracted values stay checkable against the page. The proposed coding carries its evidence and its uncertainty. And when a proposal is wrong, the correction is recorded where the next suggestion can learn from it, instead of disappearing into a posting that looks as if it had always been right.

Sources