Skip to content

ETA Document Flow

Egyptian Tax Authority (ETA) documents share one policy: EtaActionPolicy in the shared library. The same rules disable Actions in Blazor (EtaActionGate / EtaActionMenuItem) and reject illegal calls on the API.

This guide documents implemented behavior for:

  • E-Invoices — sent invoices (Direction = Sent, Kind = Invoice)
  • E-Received Invoices — inbound supplier invoices (Direction = Received, Kind = Invoice)
  • E-Receipts — sent receipts (Kind = Receipt; use return, not cancel)

Parent hub: Target Document Flow.

  • Draft / Validated / Queued
  • Submitted
  • Valid
  • Invalid / Rejected
  • Cancelled / Returned

#Status catalog

Statuses are stored as strings on the document and mapped to EtaDocumentStatus.

Status Invoices Receipts Meaning
Draft Yes Yes Editable local draft
Validated Yes Yes Passed local/pre-ETA validation
Queued — Yes Accepted offline; waiting to submit
Submitted Yes Yes Sent; awaiting authority result
Valid Yes Yes Accepted by ETA
Invalid Yes Yes Refused by ETA; fix and resubmit
Rejected Yes Yes* Counterparty refused (invoice-centric)
Cancelled Yes — Issuer cancelled at ETA
Returned — Yes Fully reversed by return receipt

* Receipts do not use recipient Reject / Decline Cancellation; reverse with Create Return Or Cancel Receipt.

#Lifecycle overview

Core path — prepare, submit, ETA result

flowchart TB
  subgraph Prepare["1 - Prepare"]
    direction TB
    Draft[Draft]
    Validated[Validated]
    Queued[Queued - receipts]
    Draft -->|Validate| Validated
  end

  subgraph Authority["2 - Authority"]
    Submitted[Submitted]
  end

  subgraph Result["3 - Result"]
    direction TB
    Valid[Valid]
    Invalid[Invalid]
  end

  Start((Create)) --> Draft
  Draft -->|Submit| Submitted
  Validated -->|Submit| Submitted
  Queued -->|Submit| Submitted
  Submitted -->|ETA accept| Valid
  Submitted -->|ETA refuse| Invalid
  Draft -.->|Submit refused| Invalid
  Validated -.->|Submit refused| Invalid
  Invalid -->|Edit| Draft
  Invalid -->|Resubmit| Submitted

  class Start egkStart
  class Draft,Validated,Queued egkDraft
  class Submitted egkActive
  class Valid egkSuccess
  class Invalid egkError

Terminal paths from Valid — cancel, reject, or return

flowchart TB
  Valid[Valid]
  Valid -->|Cancel on ETA| Cancelled[Cancelled]
  Valid -->|Reject invoice| Rejected[Rejected]
  Valid -->|Create return| Returned[Returned]
  Cancelled --> DoneNode((Done))
  Rejected --> DoneNode
  Returned --> DoneNode

  class Valid egkSuccess
  class Cancelled,Rejected,Returned egkTerminal
  class DoneNode egkStart

#Direction split (invoices)

ETA gives each side one reversal verb. Receipts use Create Return Or Cancel Receipt, not Cancel On Eta.

Issuer vs recipient reversal actions

flowchart TB
  subgraph Issuer["Issuer - E-Invoices"]
    direction TB
    S1[Valid] -->|Cancel on ETA| S2[Cancelled]
    S1 -->|Decline rejection| S3[Reinstate / clear pending]
  end
  subgraph Recipient["Recipient - E-Received Invoices"]
    direction TB
    R1[Valid] -->|Reject invoice| R2[Rejected]
    R1 -->|Decline cancellation| R3[Reinstate / clear pending]
  end

  class S1,R1 egkSuccess
  class S2,R2 egkTerminal
  class S3,R3 egkActive
Verb (UI label) Who Policy action
Cancel On Eta Issuer Cancel
Decline Rejection Issuer DeclineRejection
Reject Invoice Recipient Reject
Decline Cancellation Recipient DeclineCancellation
Create Return Or Cancel Receipt Receipt issuer IssueReturn
Create Credit Note Invoice issuer IssueCreditNote

#Action availability matrix

Legend: Y = allowed when other flags permit · — = never for this kind/direction · C = conditional (see notes)

Sent e-invoice matrix
Action (UI) Draft Validated Submitted Valid Invalid Rejected Cancelled
Edit / Delete / Line Items Y Y — — Y — —
Validate Y Y — — Y — —
Submit Y Y — — Y — —
Sync Status C¹ C¹ C¹ C¹ C¹ C¹ C¹
Cancel On Eta — — — C² — — —
Decline Rejection — — — C³ — C³ C³
Create Credit Note — — — C⁴ — — —
Duplicate Y Y Y Y Y Y Y
Eta Pdf C¹ C¹ C¹ C¹ C¹ C¹ C¹

¹ Requires ETA document UUID (HasEtaUuid).
² Valid only; blocked if pending cancellation, pending rejection, or reversal window closed.
³ Requires pending rejection or status Rejected/Cancelled per decline rules; blocked if already declined, no rejection, wrong direction, or decline window closed while still Valid.
⁴ Valid only and not fully credited; no cancellation deadline (credit note remains available after the cancel window).

Received e-invoice & e-receipt matrices

#Received e-invoice

Action (UI) Valid Other statuses
Reject Invoice C⁵ Denied (not submitted / wrong status / already reversed)
Decline Cancellation C⁶ See decline rules
Sync / Eta Pdf C¹ C¹
Submit / Cancel / Credit Note — Sender-only or N/A

⁵ Valid only; within rejection window; no pending rejection.
⁶ Pending cancellation or status Cancelled; receiver only; one decline; window rules as in policy.

#E-receipt

Action (UI) Draft / Validated / Queued / Invalid Submitted Valid Returned
Edit / Delete Y — — —
Validate / Submit Y — — —
Create Return Or Cancel Receipt — — C⁷ —
Cancel On Eta — — — — (receipts use return)
Duplicate Y Y Y Y

⁷ Valid and not fully returned.

#Decision trees

#When is Cancel On Eta enabled?

Cancel On Eta — policy gates

flowchart TB
  A[Cancel On Eta] --> B{Kind = Invoice?}
  B -->|No| X1[Denied - use return]
  B -->|Yes| C{Direction = Sent?}
  C -->|No| X2[Denied - sender only]
  C -->|Yes| D{Pending cancellation?}
  D -->|Yes| X3[Denied - already requested]
  D -->|No| E{Pending rejection?}
  E -->|Yes| X4[Denied - rejection pending]
  E -->|No| F{Status = Valid?}
  F -->|No| X5[Denied - not Valid]
  F -->|Yes| G{Reversal window closed?}
  G -->|Yes| X6[Denied - window closed]
  G -->|No| OK[Allowed]

  class A egkActive
  class B,C,D,E,F,G egkDecision
  class OK egkSuccess
  class X1,X2,X3,X4,X5,X6 egkError

#When is Decline Rejection enabled?

Decline Rejection — policy gates

flowchart TB
  A[Decline Rejection] --> B{Invoice + Sent?}
  B -->|No| X1[Denied - wrong kind]
  B -->|Yes| C{Has ETA UUID?}
  C -->|No| X2[Denied - not submitted]
  C -->|Yes| D{Already declined?}
  D -->|Yes| X3[Denied - already declined]
  D -->|No| E{Pending rejection or Rejected?}
  E -->|No| X4[Denied - no rejection]
  E -->|Yes| F{Status}
  F -->|Valid| G{Decline window closed?}
  G -->|Yes| X5[Denied - window closed]
  G -->|No| OK[Allowed]
  F -->|Rejected or Cancelled| OK
  F -->|Other| X4

  class A egkActive
  class B,C,D,E,F,G egkDecision
  class OK egkSuccess
  class X1,X2,X3,X4,X5 egkError

#After-action UI behavior (ETA screens)

Step Behavior
1 Action runs through API (/{id}/validate, /submit, /cancel, /decline-rejection, /reject, /decline-cancellation, /return, /sync-status, …)
2 ETA actions stay disabled for the round trip and the refresh that follows, so nothing can be launched against a row already known to be out of date
3 The row and the status counters above it are re-read from the server on every outcome — accepted, refused, or failed
4 If composer/details open: refetch invoice/receipt/received invoice by id
5 Gate(row, action) / DeclineRejectionGate / DeclineCancellationGate re-run on the new StatusId, UUID, and ETA date flags
6 A multi-row selection is re-pointed at the reloaded rows, so bulk buttons gate on the new statuses; rows the reload no longer returns drop out of the selection
7 Disabled items remain visible with localized denial tooltips

A refused action refreshes the same as an accepted one. A refusal usually means the document had already moved on — cancelled by someone else, or past its window — which is exactly the case where the row on screen is the stale thing that offered the action. A refused submission also still writes to the document: the reason ETA gave, and the attempt in the audit trail. So the screen after a refusal shows the authority's current answer rather than the state you clicked from, and no manual refresh is needed to find out what is still possible.

Validate is included in this, despite the read-only name: a draft that passes validation is promoted to Validated and saved, which changes what the Actions menu should offer.

EntityTable CanUpdateEntityFunc / CanDeleteEntityFunc also call EtaActionPolicy so built-in Edit/Delete match the Actions menu.

#Scenario catalog

Scenario Resulting status / flags User next step
Create Draft Edit lines, Validate, Submit
Validate success Often Validated Submit
Submit success Submitted then sync to Valid / Invalid Sync Status if needed
ETA invalid Invalid Edit, Validate, Submit
Cancel accepted Pending cancel → Cancelled Decline not available to issuer
Reject accepted Pending reject → Rejected Issuer may Decline Rejection inside window
Decline Rejection success Pending cleared; document reinstated Continue as Valid
Decline Cancellation success Pending cleared; document reinstated Recipient keeps invoice
Full credit note Source stays Valid; FullyCredited Credit note action disabled
Full return Source → Returned or FullyReturned Return action disabled
Duplicate New Draft Unrelated to source lock

#Sequence: submit sent invoice

Submit path — gate → API → ETA → UI sync

sequenceDiagram
  autonumber
  participant UI as Invoices grid
  participant Gate as EtaActionGate
  participant API as Invoice API
  participant Svc as Submission service
  participant ETA as Tax authority
  participant DB as Database

  UI->>Gate: Evaluate Submit
  Gate-->>UI: Allow or deny + tooltip
  UI->>API: POST /{id}/submit
  API->>Svc: SubmitInvoiceToEta
  Svc->>DB: Read invoice
  Svc->>ETA: Submit document
  ETA-->>Svc: UUID / validation result
  Svc->>DB: Persist StatusId + UUID
  API-->>UI: Outcome
  UI->>UI: Reload grid + re-gate Actions

#Denial reasons (tooltips)

Denial keys resolve through the module localizer. Examples:

  • Action Denied Locked By Eta
  • Action Denied Already Submitted
  • Action Denied Only Valid Can Be Cancelled
  • Action Denied Cancellation Already Requested
  • Action Denied Decline Window Closed
  • Action Denied Decline Rejection Is Sender Only
  • Action Denied Decline Cancellation Is Receiver Only
  • Action Denied Receipts Use Return

#Official PDF archival

ETA portal PDFs may disappear after a short retention window. EGKits therefore archives the official English and Arabic printouts locally as soon as a document is eligible:

  • Sales (E-Invoices) — after status sync once a UUID exists and the document was submitted to ETA
  • Received (E-Received Invoices) — after retrieval for Valid / Rejected / Cancelled documents

Work runs on Hangfire (eta-pdf-archive:drain / eta-pdf-archive:reconcile). The invoice UI Documents / Archive panel shows EN/AR status and allows View / Download / Retry without exposing server paths. Details: Document Archive Document Flow.

#ERP integration: AR ↔ ETA bridge and historical back-fill

E-invoices are the fiscal mirror of Accounts Receivable documents, never a second business transaction. Every ETA document raised by the bridge carries PartnerId, ArInvoiceId / ArCreditNoteId and SourceModule = AccountsReceivable; every AR document raised from an ETA document carries SourceModule = EtaBackfill and the key ETA:{uuid}.

Two directions, one document each way

flowchart LR
  AR[AR Invoice Sent] -->|bridge, key AR-{invoiceId}| EI[E-invoice draft]
  EI -->|AutoValidate / AutoSubmit| ETA((ETA))
  ETA -->|Valid / Cancelled / Rejected| AR
  H[Historical ETA document Valid] -->|back-fill, key ETA:{uuid}| ARH[AR Invoice / Credit Note]
  ARH --> GL[GL journal on issue date]

  class AR,ARH,GL egkSuccess
  class EI egkDraft
  class H egkActive
Rule Behavior
Bridge opt-in Per company through ETA bridge settings (Enabled, AutoValidate, AutoSubmit, default activity / country / tax sub-type / EG code, RequireProductEgCode, B2C id threshold). No setting or Enabled = false → AR posts normally, nothing is mirrored.
One live document A redelivered AR event finds the existing non-final e-invoice and stops. Only an Invalid / Rejected / Cancelled mirror leaves room for a Re-issue ({number}-R2, key AR-{id}-R2).
Refusals Business gaps (no tax id on a B2B customer, no EG code, no exchange rate, missing branch) are logged, raised in the ETA inbox and notified. The AR invoice stays valid; fix the data and re-issue.
Status sync to AR Valid → audit row. Cancelled on an unpaid Sent/Overdue invoice → the AR invoice is cancelled. Cancelled with receipts, Rejected, Invalid → the AR invoice is flagged for review and the creator is notified. Credit notes behave the same way.
Back-fill Back-fill page (/ei/backfill): resolve receivers to trading partners (tax id, then name; create missing customers with code C{taxId}), raise AR documents for Valid documents without an AR link in batches with dry run, tolerance and blockers, post the GL journals on the ETA issue dates, import historical receipts from Excel, and reconcile ETA / AR / GL per month. Back-filled AR invoices are never mirrored back to ETA.
Withholding ETA T4 withholding is not part of the AR receivable; it is settled by a receipt with method WHT mapped to a GL account.
Currency Back-filled documents are booked in EGP at the ETA exchange rate; live bridge documents convert foreign AR invoices with the GL rate table.

Guides: Sales Document Flow (hand-off), Recurring Document Flow (periodic generation).

#E-invoice or e-receipt? One decision for every sale

EGKITS decides the ETA document type once, in the same place, for invoices, POS sales, credit notes and recurring contracts. The e-receipt is a fiscal mirror exactly like the e-invoice: it never posts revenue, tax, receivables or cash on its own.

Document-type decision

flowchart TB
  S((Sale)) --> B{Bridge enabled?}
  B -->|No| N[No ETA document]
  B -->|Yes| C{Channel}
  C -->|Point of sale| R[E-receipt]
  C -->|Invoice| T{Business with tax id or foreign?}
  T -->|Yes| I[E-invoice]
  T -->|Individual| P{Consumer document setting}
  P -->|E-invoice| I
  P -->|E-receipt| R
  P -->|None| N

  class S egkStart
  class I,R egkSuccess
  class N egkTerminal
Rule Behavior
Point of sale Always an e-receipt, whoever the buyer is.
Business or foreign receiver Always an e-invoice on the invoice channel.
Individual Follows ETA bridge settings → Consumer document (E-invoice, E-receipt, None). A national id stored on an individual is printed on the receipt; it never turns the sale into an e-invoice.
Links Every e-receipt carries the POS transaction or the AR invoice / credit note it mirrors, plus the customer. A receipt belongs to exactly one commercial document; the E-Receipt details page and the POS / AR pages link both ways.
Credit notes A credit note on an invoice mirrored as an e-receipt produces a return receipt (never an ETA credit note); over-returning the source receipt is rejected.
Retries Redelivered events, job retries and restarts find the linked receipt and stop — one business event, one receipt, one validation.
Status sync E-receipt Valid → audit on the AR invoice / recurring occurrence completed; Rejected / Invalid → AR invoice flagged, creator notified, occurrence pending review.
Linkage audit Back-fill → ERP / ETA linkage audit lists, per document, ERP transactions without an ETA document, ETA documents without an ERP link, duplicate UUIDs, wrong document types, E-Received documents without a supplier, tax differences, and missing or duplicate GL postings / stock movements — each with a link to the document to fix.

Reconnecting to the server…

This page stays right here while we reconnect.

Still waiting? You can reload the page.