- Home
- Apps
- SaaS Tools
- Thailand e-Tax Invoice & Receipt
Illustrative previewA build-to-order Odoo module that turns a posted customer invoice or receipt into a digitally signed,
ETDA-conformant Thai e-Tax document, delivers it to the buyer, and keeps a compliant archive. ECOSIRE scopes, builds, installs and supports it on your Odoo 17.0, 18.0 or 19.0.
What is Thailand e-Tax Invoice & Receipt?
A build-to-order Odoo module that turns a posted customer invoice or receipt into a digitally signed, ETDA-conformant Thai e-Tax document, delivers it to the buyer, and keeps a compliant archive. ECOSIRE scopes, builds, installs and supports it on your Odoo 17.0, 18.0 or 19.0. Built to order by ECOSIRE for Odoo 17, 18, 19 — indicative price from $999.00 USD; request a quote for a scoped proposal.
Key Features
Built to order, done for you
No DIY setup — a working app, built, installed and supported by ECOSIRE.
- 1
You order
Start with a one-time build price. We scope it with you at kickoff.
- 2
We build & install
ECOSIRE builds, configures and installs it on your Odoo.
- 3
Go live + support
You go live in about one working week, with two weeks of go-live support. Defects in the code we deliver are fixed free of charge.
Technical Specifications
- Odoo Compatibility
- Odoo 17, Odoo 18, Odoo 19
- Editions
- Enterprise & Community
- License
- Licence confirmation required
- Python Requirement
- Python 3.10+
- Database
- PostgreSQL 12+
About this Product
Thailand's e-Tax Invoice & Receipt regime pushes work that finance teams used to do informally into a signed, machine-readable, archivable process. A posted account.move has to become a document carrying a correct 13-digit Tax ID, a branch code, Thai and English party names, a VAT breakdown that reconciles to the ledger, and a digital signature a recipient or auditor can verify years later. Odoo core models none of that. account.move has no branch code, no Thai legal-name field separate from the display name, nowhere to keep a signature or a provider document reference, and no state that distinguishes "posted in the ledger" from "accepted as an e-Tax document". Teams end up exporting to spreadsheets, re-keying into a portal, and reconciling two sets of numbers at month end — which is exactly where the errors and the audit exposure live.
What we build is a Thai localisation layer that sits on top of your existing accounting flow rather than beside it. A new model — typically l10n_th.etax.document — is created from the posted move and carries its own lifecycle: draft, signed, submitted, accepted, rejected, cancelled. Company and partner records gain the fields the format actually requires (Tax ID with checksum validation, branch code defaulting to 00000 for head office, Thai legal name, address decomposed into the sub-district / district / province structure the schema expects), enforced with @api.constrains so a bad master-data record fails at save time instead of at submission time. Tax mapping is configuration, not code: each account.tax maps to its Thai tax category (7% VAT, zero-rated, exempt, out-of-scope), so the XML is generated from what you actually posted and totals always tie back to the journal entry.
One posting produces both outputs. The machine format comes from a serializer that reads the mapped master data and tax lines and validates the result against the schema before anything is signed, with field-level errors surfaced on the record. The human-readable copy is a QWeb report designed for Thai typography and the required legal wording, rendering the document reference and a verification QR code on the PDF. Signing runs through a pluggable adapter — your certificate in a configured keystore, or your chosen service provider / e-Tax agent called over its API — so the signing route is a configuration choice, not a rewrite. Delivery to the buyer is queued through the standard mail layer with the signed artefacts attached, and every attempt, response payload and error is written to the chatter of the source invoice, where an accountant would actually look for it.
Rejections are treated as a normal path, not an exception. A rejected document returns to the operator queue with the provider's reason code and message on the record; the correction workflow either re-issues once the underlying data is fixed or produces the appropriate credit/debit document linked back to the original, so the chain of references stays intact for audit reconstruction. Signed XML, the rendered PDF and the raw signing response are stored as immutable attachments with a retention policy and a scheduled action that flags anything approaching the end of its statutory retention window. Access is controlled with ir.model.access.csv plus record rules — issuers create and submit, auditors get read-only across companies, and the archive is never editable from the UI. Dashboards and filtered list views show what is pending, signed, rejected or overdue, and everything is reachable over XML-RPC/JSON-RPC if issuance is driven from an upstream POS or billing system.
This is build-to-order, not a download. We start with a scoping call to confirm your Odoo version and edition, whether you sign in-house or through a service provider, your branch structure, and how invoices reach buyers today. From confirmed scope, typical delivery is one working week: we build against your series, install on a staging database restored from your production data, run UAT with your finance team on real documents, then go live with a rollback plan in hand. You receive the source code and the git repository, so nothing here is a black box you cannot maintain.
What you get
- Installable module source code built and tested for your exact Odoo series (17.0, 18.0 or 19.0) and edition
- Installation and configuration on your environment: tax category mapping, company and branch master data, signing credentials, delivery settings
- Technical documentation covering the data model, `__manifest__.py` dependencies, security matrix, signing adapter interface and the RPC surface
- End-user guide plus a live training session for the finance team covering issuance, rejection handling and correction documents
- UAT on a staging database restored from your production data, with a documented test script and a rollback plan agreed before go-live
- Post-go-live support window for defect fixes and configuration adjustments within the delivered scope
- Handover of the private git repository with full commit history, so your team or another vendor can maintain it
- Written compatibility and upgrade note for your next Odoo major version
Who this is for
Finance Manager / Chief Accountant, Thai entity
Owns the VAT return and the audit file. Needs every issued e-Tax document to tie back to a journal entry with no manual reconciliation, and needs to produce a specific signed document for an auditor in minutes rather than days.
Accounts Receivable / Billing Team Lead
Issues dozens to hundreds of invoices and receipts a month. Needs issuance to be a button on the invoice they already post, a clear queue of what was rejected and why, and a correction path that does not mean re-keying into a portal.
IT / ERP Manager running Odoo in Thailand
Responsible for the Odoo instance and its upgrade path. Wants a module that follows Odoo conventions — proper models, `ir.model.access.csv`, record rules, QWeb reports, no monkey-patched core — with source and git repo handed over, and a clear answer on the next major version.
Regional Finance Controller, multi-country group
Runs several Odoo companies across the region and needs Thailand handled to the same standard as the group's other localisations: consistent master data, read-only cross-company audit access, and reporting that rolls up without a country-specific spreadsheet.
How Thailand e-Tax Invoice & Receipt Compares
| Criterion | ECOSIRE | Custom Build | Competitor | Odoo Native |
|---|---|---|---|---|
| Fit to your Thai setup (branches, tax mapping, signing route) | Built to your confirmed scope — your branch structure, tax mapping, and certificate or provider | Fits perfectly if the spec is right, but you write and own the spec | Fits the vendor's assumed setup; unusual branch or provider arrangements need workarounds | No Thai e-Tax concept at all — no branch code, no Thai legal-name field, no signing |
| Odoo version and edition coverage | Built and tested against your exact series — 17.0, 18.0 or 19.0, Community or Enterprise | Whatever your team targets; the port to the next major is your project | Often lags a major version; edition support varies by listing | Core accounting only — identical across versions and unhelpful for this requirement |
| Time to a first signed document | Typically one working week from confirmed scope, including staging UAT | Months of internal analysis, build and testing before the first signed document | Installs in minutes, then weeks of configuration and gap-closing before it is usable | Never reaches a signed document without additional software |
| Rejection and correction handling | Explicit rejected state, reason code on the record, operator queue and a linked correction or credit workflow | Frequently the first thing cut from scope, then rebuilt after the first audit finding | Usually a status flag; the correction path and reference chain are often manual | Not applicable — no submission means no rejection to handle |
| Audit trail and archiving | Immutable signed XML, PDF and provider response as attachments, with retention flags and chatter logging on the source invoice | Depends entirely on how disciplined the internal build was | Documents are stored, but retention policy and provider-response capture are commonly out of scope | Standard attachments and chatter, with none of the e-Tax artefacts to store |
| Reconciliation with the ledger | Generated from mapped `account.tax` lines on the posted move, so totals tie to the journal entry by construction | Achievable, but the tax mapping layer is a common source of month-end discrepancies | Often re-derives totals with its own logic, creating a second source of truth | Ledger is correct; there is simply no e-Tax document to reconcile against |
| Source code and ownership | Full source plus the private git repository handed over — maintainable by you or any vendor | You own everything, including every future defect and version port | Frequently licence-locked or obfuscated; you cannot change it or take it elsewhere | Open source, but nothing here to own for this requirement |
| Support after go-live | Post-go-live support window on delivered scope, then an explicit ongoing agreement with priced changes | Whoever built it — and their availability after they change roles | Shared ticket queue; regulatory changes arrive whenever the vendor ships them | Odoo support covers core accounting, not Thai e-Tax compliance |
Frequently Asked Questions about Thailand e-Tax Invoice & Receipt
How long does delivery take, and can I download it today?
No — this is build-to-order, not an existing apps.odoo.com download. We build it for your Odoo version, edition and signing setup. Typical delivery is one working week from confirmed scope, covering development against your series, installation on staging, UAT with your finance team, and go-live. The clock starts when scope is agreed, not when you first enquire; a large branch structure or an unusual service-provider integration can extend it, and we say so before you commit.
Do we need our own digital certificate, or can we sign through a service provider?
Either. The signing layer is a pluggable adapter chosen in configuration: a certificate you hold in a configured keystore, or the API of the e-Tax service provider or agent you already work with. Tell us which route you are taking at the scoping call — it changes the integration work, not the rest of the module. If you have not decided, we can build the adapter interface and wire the second option later without reworking the document model.
Which Odoo versions and editions does this support?
We build for Odoo 17.0, 18.0 and 19.0, Community or Enterprise. We build and test against the one series you actually run rather than shipping a multi-version compatibility layer, because Thai localisation touches accounting internals that differ between majors. If you are mid-upgrade, say so at scoping and we plan delivery around your target version.
What happens to invoices we posted before the module goes live?
That is a scoping decision, not an assumption. We can leave historical moves untouched and start issuing from a cut-over date, or build a controlled backfill that creates e-Tax documents for a defined range of already-posted invoices. Backfilling has compliance implications for dates and references, so we agree the approach with your accountant in writing before building it.
What happens when a document is rejected?
Rejection is a normal state in the workflow, not a crash. The provider's reason code and message are stored on the document, the record returns to an operator queue with a dedicated filter, and the correction workflow either re-issues after the underlying data is fixed or produces a linked credit or debit document. The original and its corrections stay referenced to each other so the chain can be reconstructed during an audit.
How do support and updates work after go-live?
Delivery includes a post-go-live support window for defect fixes and configuration adjustments within the delivered scope. Beyond that, ongoing support and enhancements run under a separate agreement. Regulatory changes to the format or signing requirements are treated as new scope rather than free updates — we quote a change before doing it, and because you hold the git repository you are never locked into us to make it.
Will this conflict with the standard Odoo Thai localisation or our existing customisations?
We build it as a proper module that depends on your existing accounting and localisation modules through `__manifest__.py` and extends models rather than patching core. Before quoting we review your installed module list and anything that touches `account.move`, invoice reports or the mail layer, and call out conflicts at scoping. UAT runs on a staging copy of your real database precisely so integration surprises appear before go-live, not after.
Related Modules

Tax Return / VAT Report Builder
Configurable VAT/GST return builder for Odoo with tax-grid mapping, box logic and audit drill-down to source invoices.

Telegram Bot & CRM Integration
Connect a Telegram bot to Odoo for two-way chat, lead capture, order/ticket notifications and subscriber broadcasts. Built, installed and supported by ECOSIRE.

Tier-Based Approval Validation
A build-to-order Odoo module that enforces multi-tier approval sign-off on any record type before it can advance or be validated. ECOSIRE scopes, builds, installs, and supports it for your Odoo 17, 18, or 19 instance.

TikTok Lead Generation Connector
Capture TikTok Instant Form submissions straight into Odoo CRM with attribution, auto-assignment and dedup. Built to order for Odoo 17/18/19.
Thailand e-Tax Invoice & Receipt
A build-to-order Odoo module that turns a posted customer invoice or receipt into a digitally signed, ETDA-conformant Thai e-Tax document, delivers it to the buyer, and keeps a compliant archive. ECOSIRE scopes, builds, installs and supports it on your Odoo 17.0, 18.0 or 19.0.
- Dedicated `l10n_th.etax.document` model with an explicit lifecycle (`draft` → `signed` → `submitted` → `accepted`/`rejected`/`cancelled`) kept separate from the `account.move` posting state
- Thai master-data extension on `res.company` and `res.partner`: 13-digit Tax ID with checksum validation, branch code defaulting to `00000` for head office, Thai legal name, and sub-district/district/province address decomposition
- `@api.constrains` validation on Tax ID, branch code and required address parts, so bad master data is rejected at save time rather than at submission
- Configurable mapping from each `account.tax` to its Thai tax category (7% VAT, zero-rated, exempt, out-of-scope), so document totals are derived from posted lines and reconcile to the journal entry