User guide
How to use Egypt ETA e-Receipt, screen by screen.
Building a receipt
Create it from a posted customer invoice. The receipt is built in ETA's documented v1.2 structure, and local validation runs first.
Local validation refuses, with the field named:
- a product with no ETA item code;
- a unit of measure with no ETA unit code;
- a blank payment-method code.
Finding these here costs a field. Finding them at the Authority costs a filing.
Reading it before you send it
The Document tab holds the v1.2 JSON exactly as it will be submitted. Read one properly the first few times — it is what the Authority judges, and it makes every later rejection message legible.
The Lines tab shows item codes and unit codes per line, which is where an uncoded product becomes obvious.
The chain
Each receipt references the one before it from the same till, by previousUUID.
The receipt form shows its own UUID and its predecessor's. The till form shows the chain position and the last UUID the Authority accepted.
Four rules that follow:
The chain links receipt to receipt, not receipt to whatever happened to be accepted last. A batch built before any of it is submitted forms a proper chain among itself.
A receipt cannot be submitted before the one it follows. Trying is refused, with the reason.
A mismatch halts the till. Not a warning. Once a receipt is skipped, every later one references a predecessor the Authority never received — continuing turns one problem into a day of them.
Cancelled and rejected receipts are skipped when the chain is computed. Neither was ever accepted.
When a till halts
A banner on the till, and an activity so somebody is actually told.
Resuming is a deliberate act restricted to an e-Receipt Manager. It is a decision about tax filings, not a button to clear a red banner — work out which receipt was skipped and why before pressing it.
Submitting
By hand at first. The two scheduled jobs ship disabled, and should stay that way until you have built a receipt, read it, submitted it and watched it come back with a real status.
A module that began filing on install would submit unchecked documents under your tax registration.
202 is not a filing
ETA documents its reply as "accepted for further processing" and states that validation is not complete when it answers.
So a submitted receipt sits in Submitted until a status read from the Authority moves it. It is not filed because you got a 202, and this module will not tell you it is.
Statuses
ETA publishes only valid verbatim. Anything unrecognised is stored exactly as received, flagged in the chatter, and leaves the state alone.
That is deliberate: inventing a meaning for a status the Authority has not documented is how you end up confidently wrong about what is filed.
The unsigned warning
A receipt that is ready but unsigned says so, plainly, on the form.
ETA requires a CAdES-BES signature from an eSeal certificate, and that certificate lives on a token or HSM outside Odoo. No signature, no submission — the module refuses rather than sending something that will be rejected.
It is an honest state and worth seeing rather than hiding.
Five things it refuses to do
- Report a 202 as a filing.
- Submit without a signature.
- Guess a code. An uncoded product, a missing unit code or a blank payment method are refused by local validation with the field named.
- Invent a status. Unrecognised statuses are stored as received.
- Cancel a submitted receipt locally. Changing a state in Odoo would not cancel it at the Authority, and the two records would then disagree.
- File two receipts for one invoice. The same revenue filed twice is not fixed by a correction.
Verification status
No call has ever been made to the Egyptian Tax Authority. There are no base URLs, client credentials or eSeal certificate on the development account. The suite runs against a mock ETA service replaying the documented shapes.
One thing deserves naming plainly: the uuid canonicalisation in this module is not ETA's published algorithm. ETA's CanonicalJSON rules live inside its Integration Toolkit rather than on the documentation site. What is implemented here is deterministic and makes the chain coherent and testable, but the hash used in a live submission must come from the signing service, which holds the eSeal and implements the Authority's actual rules.
The code says so where it matters, and so does this page.