Skip to main content
DoneThat

AI Adoption GuideFinanceBudget

Capex vs opex classifier

LLM classifies spend requests against accounting policy and cites the rule applied.

Finance processPlanBudgetInvoiceCollectPayCloseReportAudit

By Don, DoneThat’s AI coach · updated

Return a cited class the controller can reject

A spend request is classified only when the model can point at the request fields it used and the capitalization-policy paragraph that decides capital versus operating. The useful output is a short packet: the class (capital, operating, or empty), the fields cited (description, project type, amount, whether the spend replaces or improves an existing asset), and a pointer to the policy paragraph a reviewer can open. The controller reads that packet and still owns the booking.

Empty is a valid class. If the loaded policy does not speak to the fact pattern, the field stays empty. Completeness is not the goal. A reproducible cite is the goal.

The class is not a journal line. It is not a useful life. It is not permission to create an asset record. Those steps happen after accounting accepts the class and posts in the ledger. Account-level help after the class is settled is a separate GL coding suggestion problem. It does not replace the policy cite.

Vendor invoice language does not override policy. "Capital equipment" on a supplier line is catalog copy, not an accounting conclusion.

Load the policy text with the spend request

Run the classifier only after both inputs sit in the same context. The working sequence is load the current policy and the request, classify only with a cite to both, leave class and life blank when the policy is silent, then let accounting post after the controller accepts or overrides.

Load the capitalization policy the controller actually applies this period: asset-class thresholds if they exist, repair versus betterment language, software and implementation guidance only if it is in that policy, and any explicit do-not-capitalize lists. Load the spend request as filed: description, business justification, amount, cost center, project or work-order identifiers, vendor name, and attachment text the requester treated as evidence.

Do not load last year's PDF if a later memo superseded the threshold. Do not load a slide that paraphrases the manual. The cite has to resolve to a paragraph the controller can open in the accounting manual.

ERP and planning systems hold the request, not the rule. Workday, SAP, Oracle, and Anaplan are where requisitions, projects, and budgets typically live. They do not decide whether a rooftop unit replacement is a betterment. Pull the request record from that stack, then overlay the policy document the accounting manual names.

If the request is a lease or a right-of-use arrangement, stop treating it as ordinary capex versus opex and send it down the lease accounting agent path. Mixing those questions produces a confident wrong class.

If the amount is a period-end estimate rather than an approved request, you are in accrual territory. Use accrual auto-suggestion for the estimate. Do not use this classifier to invent a capital asset so the estimate looks cleaner.

Classify with a citation, or leave the class empty

Match request fields to policy paragraphs. State a class only when the match is specific enough that a reviewer can reproduce it without guessing.

Take a facilities request titled "Replace RTU-4, Building C." The justification says the rooftop unit failed and the replacement has the same cooling capacity. The vendor quote header reads "Capital equipment: RTU package." The amount is on the request. Policy section 4.2 says expenditures that restore an existing asset to original condition are repairs and are operating; expenditures that increase capacity or extend useful life beyond the original estimate are capital.

The classifier should return operating. It should cite the request fields: replace, same capacity, failed unit. It should cite policy 4.2. It should ignore the vendor header. It should not propose a fifteen-year HVAC life. The policy did not ask for a life, and the class is not an asset master record.

If section 4.2 did not exist, and the policy only listed a dollar threshold for "machinery and equipment" without defining rooftop HVAC, the class stays empty. Empty means the policy is silent on this fact pattern. Do not invent a capitalization rule to fill the field. Do not borrow a threshold from another filer's footnotes. Do not round the request to meet a number that is not in the loaded policy.

When the purchase order is mixed (a repair plus a capacity upgrade on one line), say so. Classify the parts the policy can separate. Leave the remainder empty rather than forcing a single class onto a blended spend.

After a class is accepted, budget anomaly flagging can still fire. A correctly classified capital request can still sit in the wrong budget bucket or spike against the remaining capital envelope. Classification quality and budget-shape quality are different checks.

Posting stays in accounting, not in the classifier

The classifier does not post. Accounting posts.

Once the controller accepts capital, construction-in-progress treatment, depreciation start date, and useful life come from the asset policy and the asset register, not from a sentence the model added because registers usually have a life. Once the controller accepts operating, the expense hits the period under the existing close calendar. Neither outcome is finished until someone posts the entry, with the chart of accounts and the project or cost object the company actually uses.

Treating the class as the journal is a control failure. A capital flag is not a debit to construction in progress and a credit to accounts payable. An operating flag is not a debit to repairs and maintenance. Those mappings belong in posting rules and in the coding step after the class is locked.

Keep the classifier output attached to the request packet so audit can see what was proposed and what was overridden. If the controller changes operating to capital, the packet should show the override. It should not silently rewrite the cite to match the new class.

Mistakes that look like completeness

Three failure modes show up as helpfulness.

Capitalizing because the vendor invoice says asset. Supplier documents optimize for their catalog, not for your capitalization policy. If the model weights invoice nouns over request facts and policy verbs, you will capitalize repairs the policy calls operating.

Treating the class as the journal. A cited class is evidence for the reviewer. It is not a posting instruction and not an asset-creation step. If the workflow auto-creates an asset master from "capital," you have skipped the controller.

Inventing a useful life. Useful life is a measurement after you have an asset, under a different policy section if you have one. Filling ten years because HVAC lives appear in training data is fabricating a rule. If the loaded policy is silent on life, leave life empty the same way you leave class empty.

Also watch for threshold invention: writing "capitalize because it exceeds five thousand" when the loaded policy has no such number. Watch for software implementation capitalization when the policy only covers property, plant, and equipment. Watch for classifying a cloud subscription prepayment as capital because someone labeled the request "platform investment."

The quality bar is narrow. Return a classification that cites the request fields and the policy paragraph, or return empty when the policy does not decide. Anything else is a draft the controller should throw away before it reaches the ledger.

Is this worth automating for you?

Whether this pays back depends on how much time it takes your team today. Most teams estimate that from memory, and the estimate is usually wrong in one direction or the other.

DoneThat reconstructs where the time actually went, with no timers to forget, so you can measure the baseline before committing to a project and check the gain afterward.

Measure the baseline first