← Back to Blog
AI by

How a Hanoi Distributor Cut Invoice Processing from 4 Hours to 12 Minutes

How a Hanoi Distributor Cut Invoice Processing from 4 Hours to 12 Minutes

A Hanoi-based distributor was spending 4 staff-hours a day keying in vendor invoices. A Document AI pipeline brought that to 12 minutes. Here is what it took.

Key Takeaways: A mid-sized FMCG distributor in Hanoi was manually keying 200+ Vietnamese tax invoices (hóa đơn GTGT) per day into Odoo — an operation that consumed four staff-hours and produced a steady stream of data entry errors. A Document AI pipeline reduced that to 12 minutes of supervised review. The pipeline handles mixed input formats (PDF e-invoices, scanned paper, phone photos), extracts structured data including mã số thuế and line-item detail, and pushes validated records directly to account.move and account.move.line. The accuracy rate on clean e-invoices is 98.3%. On poor-quality scans with stamps or handwriting, it drops to around 87% — and those go to a human queue.


Four accounting staff. Four hours a day. Typing vendor invoice data into Odoo.

That was the situation at a consumer goods distributor headquartered in Hanoi. They handle roughly 230 vendor invoices on a busy day — pharmaceuticals, packaged food, household goods — spread across 80+ suppliers. Some arrive as PDF e-invoices from the supplier’s e-invoicing platform. Some come as scanned paper. A meaningful number arrive as phone photos taken by a field procurement rep after signing off a delivery.

The manual process worked, technically. But it was slow, error-prone, and entirely dependent on two people who understood the quirks of Vietnamese tax invoices well enough to catch the edge cases that mattered.

When the Vietnamese government accelerated the e-invoicing mandate under Decree 123/2020 and Circular 78/2021, the incoming volume of structured PDF invoices increased significantly — which actually made the data entry problem worse, not better, because structured data sitting inside a PDF is still invisible to Odoo until someone types it in.

This is the story of the pipeline that fixed it.

What Vietnamese Tax Invoices Actually Require

Before building anything, it’s worth understanding what a hóa đơn GTGT actually contains, because the field structure matters for extraction design.

A compliant Vietnamese VAT invoice has a fixed set of required fields: the seller’s mã số thuế (tax identification number), the buyer’s mã số thuế, the mã hóa đơn điện tử (e-invoice code issued by the tax authority), the invoice series (ký hiệu mẫu số), issue date, line items with unit prices, applicable VAT rate, and totals. Since the e-invoice mandate, well-formed PDFs from major e-invoicing platforms — VNPT, Viettel, MISA — follow a reasonably consistent layout.

The complication is that Vietnam uses multiple VAT rates simultaneously: 0%, 5%, and 10%, and some goods are VAT-exempt. A single invoice can carry line items at different rates. The extraction pipeline has to parse not just amounts, but which rate applies to which line.

Paper invoices and phone photos introduce a second layer of complexity: stamps, handwritten corrections, physical damage, and variable print quality from laser vs. dot-matrix printers. Both are still common in Vietnam, particularly with smaller suppliers in provinces outside Hanoi and Ho Chi Minh City.

The Extraction Pipeline

The pipeline runs as a background service triggered when invoices land in a shared email inbox or are uploaded to an SFTP folder. It has four stages.

Stage 1: Classification and pre-processing. Each incoming document is classified as e-invoice PDF, scanned paper, or phone photo. E-invoice PDFs from certified platforms are parsed directly as structured PDFs — no OCR needed for the machine-readable layer, though the visual layer is checked as a fallback. Scanned documents go through image pre-processing: deskewing, contrast normalization, and binarization tuned for the kind of faded thermal paper common in Vietnamese receipts.

Stage 2: OCR. For documents requiring OCR, the pipeline uses a Vietnamese-tuned OCR modelA mathematical function trained on data that maps inputs to outputs. In ML, a model is the artifact produced after training — it encapsulates learned patterns and is used to make predictions or…. Generic OCR models handle Vietnamese poorly — the language uses a Latin alphabet with a diacritic system of 134 characters, and the tonal marks are small and frequently damaged in low-quality scans. Getting this right required moving away from the default cloud OCR offering and fine-tuningThe process of further training a pre-trained LLM on a smaller, task-specific dataset to adapt it to a particular domain or behavior. Fine-tuning is more efficient than training from scratch and… on a corpus of Vietnamese documents.

Stage 3: LLMA neural network trained on vast amounts of text data to understand and generate human language. LLMs use the Transformer architecture and can perform a wide range of tasks — summarization,… structured extraction. OCR output feeds into a structured extraction step. The modelA mathematical function trained on data that maps inputs to outputs. In ML, a model is the artifact produced after training — it encapsulates learned patterns and is used to make predictions or… is prompted to extract a fixed JSON schema: seller TIN, buyer TIN, e-invoice code, invoice series, date, and a line-item array with description, quantity, unit price, VAT rate, and line total. The schema is strict — fields are typed and validated against known patterns. A mã số thuế, for example, is 10 or 13 digits with a specific check-digit rule, so any extraction that doesn’t satisfy that constraint is flagged immediately.

Stage 4: Validation and confidence scoring. Before anything goes to Odoo, each extracted record is scored against several checks: field completeness, numeric consistency (line totals must sum to invoice total within rounding tolerance), TIN format validity, and — where available — cross-reference against the known supplier list in Odoo. The output is a confidence band: auto-post, review-required, or reject.

Records scoring in the auto-post band skip human review entirely and are written to Odoo directly. review-required records go to a lightweight web UI where a reviewer can correct fields and approve. reject flags are escalated with the original document attached.

Edge Cases That Broke Early Versions

The pipeline took three iterations to reach production accuracy. The early failures are worth knowing about.

Stamps on key fields. Vietnamese vendors routinely stamp the company seal directly over the tax authority validation box at the bottom of the invoice. In many cases, the e-invoice code — which is required for tax deductibility — is partially or fully obscured. The first version of the pipeline was extracting “CONG TY TNHH ABC” (the company name from the stamp) as the e-invoice code, which is a confident extraction of the wrong thing. Fix: the extraction promptThe input text provided to an LLM to guide its response. Prompt design — choosing words, structure, and examples — significantly affects output quality. Also referred to as the user message or query. was updated to anchor the e-invoice code field by its labelThe ground-truth output or target value associated with a training example in supervised learning. Labels are what the model is trained to predict (e.g., spam/not-spam, price, sentiment). text rather than position, and a post-extraction regex validates the extracted value against the expected format (alphanumeric, 20–32 characters, specific prefix patterns by platform).

Handwritten quantity corrections. Delivery receipts sometimes have handwritten corrections over the printed quantity — a box of 24 scratched out and rewritten as 20. OCR picks up both values; the LLMA neural network trained on vast amounts of text data to understand and generate human language. LLMs use the Transformer architecture and can perform a wide range of tasks — summarization,… has to be told explicitly to prefer the handwritten value when one exists. Getting this right required examples in the few-shot promptThe input text provided to an LLM to guide its response. Prompt design — choosing words, structure, and examples — significantly affects output quality. Also referred to as the user message or query. rather than instruction alone.

Scanned invoices from older dot-matrix printers. Some provincial suppliers still use dot-matrix printers from the early 2000s. The character definition is poor, and the OCR accuracy on these is low enough that they now bypass the main OCR pipeline entirely and route directly to human review. Trying to force extraction on them degraded the overall accuracy metrics without producing useful results.

Multi-rate VAT on a single invoice. The extraction initially stored a single VAT rate per invoice, which is wrong for invoices with mixed-rate line items. Fixing this required restructuring the line-item schema and updating the Odoo integration to write separate account.move.line records per VAT bucket, each linked to the correct tax account.

Pushing Results to Odoo

Validated records are written to Odoo through the JSON-RPC API. Each invoice creates one account.move record in draft state with the following fields populated: partner (matched by mã số thuế against res.partner), invoice date, reference (using the e-invoice code), and journal.

Line items become account.move.line records. Each line carries the product (matched by description against the product catalogue using a fuzzy match with a confidence threshold), quantity, unit price, and tax (account.tax). The tax mapping is explicit: 0%, 5%, and 10% VAT each map to a specific tax record in Odoo’s chart of accounts; exempt items map to a null tax.

One design decision: invoices are posted in draft, not confirmed. The accounting team reviews the Odoo draft queue — not the Document AI review queue — and confirms in bulk. This keeps the review step inside the tool the accountants already use, rather than requiring them to learn a new interface. The transition from 4 hours of data entry to 12 minutes of bulk confirmation happened partly because the confirmation step in Odoo is fast when the data is already correct.

The Numbers After 90 Days

After 90 days in production, processing 5,800 invoices:

  • 98.3% field-level accuracy on clean e-invoice PDFs from certified platforms
  • 87.1% accuracy on scanned paper and phone photos (these account for about 22% of volume)
  • 91.4% overall auto-post rate — meaning 91% of invoices required no human correction at all
  • Average processing time: 12 minutes/day for review and bulk confirmation, down from 4 hours
  • Error rate in Odoo: dropped from approximately 3 per 100 invoices (manual entry) to 0.4 per 100 (post-AI, including reviewed records)

The 8.6% of invoices that required human review are now handled by one person in the review queue rather than two people doing full manual entry. The second accountant was reassigned to AP reconciliation, which had been backlogged for three months.

What the numbers don’t show: the system now catches invoices where the supplier’s mã số thuế doesn’t match the registered name — a common fraud vector in B2B Vietnam. That check wasn’t in the original scope; it emerged naturally from the validation layer.


At Trobz, we’ve deployed Document AI pipelines for invoice processing, expense receipts, and shipping documents across several Vietnam-based clients. If you’re dealing with similar volumes — whether it’s hóa đơn GTGT, import declarations, or mixed-format documents — we’re happy to walk through what the architecture would look like for your setup. Get in touch.

Ready to put AI to work?

Let's explore how Trobz AI can automate your processes, enhance your ERP, and help your team make better decisions — faster.