Reviewers (PMD-3368) :
- Oleksandr Zaluhovskyi
Dev===> not needed because this will be covered by PortaOne Workflows approach- Kseniia Kriukova
- Dmitriy Manshilin
PO===> not needed because this will be covered by PortaOne Workflows approach- Alyona Zaluhovska as part of DOCS-7164
User Story
As a CSP operating in Malawi, I need my post-paid customer invoices to be automatically submitted to the MRA (Malawi Revenue Authority) EIS (Electronic Invoicing System) upon generation — to comply with mandatory VAT e-invoicing regulations and avoid penalties for non-compliance.
As a post-paid customer of a Malawi CSP, I want to scan a QR code on my invoice to confirm it is accepted by MRA — so I can use it as a valid tax receipt.
Example of Use
On 2025-02-01 at 00:15:00, PortaBilling completes the billing cycle for January 2025 and generates invoice INV-2025-000456 for customer "Blantyre Medical Supplies Ltd" (Customer ID 102345) totaling MWK 1,250,000.00 (including MWK 175,206.61 VAT at 16.5%). The EIS integration service automatically transmits this invoice details to MRA EIS via the API. MRA validates the invoice and returns an invoice validation URL (e.g. "https://eservices.mra.mw/doc/v/?vc=90241313200014&c=fdd8d5ccc06a49d6a1efbf7e3896f0b4") which must be converted to a QR code by the EIS integration service to appear at the bottom of invoice.
Current Solution
For pre-paid customers invoicing is done via custom built (by CSP) SAP integration and agreed by CSP to remain unchanged.
For post-paid customers, a 3rd party application currently collects invoices from PortaBilling, parses them, and reports the invoice data to the MRA. The application then stamps the invoices and saves them in a remote directory (outside of PortaBilling) so invoices are ready to be delivered to end customers.
This process of reporting to the MRA and stamping invoices should be decommissioned in favor of using the EIS system and an MRA-approved QR code instead of a stamp.
Additional information:
- Taxation is disabled in the system
- VAT and excise included into the prices
- There is a princeXML based invoice template (prepared by PortaOne in scope of PMD-2367 ), which back-calculates VAT and excise from the xDRs and shows charges summaries and aging details
Business Model
The Malawi Revenue Authority has mandated that all VAT-registered taxpayers must use the Electronic Invoicing System (EIS) to transmit detailed sales transaction data in real-time. This replaces the legacy Electronic Fiscal Devices (EFDs) that transmitted summarized Z-reports once daily via FTP. Non-compliance results in penalties up to MWK 5,000,000 and potential business license suspension.
Financial Flow
- VAT Collection: CSP collects 16.5% VAT on all taxable services (voice calls, data bundles, messaging, subscriptions). For a typical monthly billing cycle with MWK 500,000,000 in taxable revenue, VAT collected equals MWK 82,500,000.
- Remittance Deadline: VAT must be remitted to MRA by the 25th of the next month. Integration ensures accurate tracking and reporting.
- Penalty Avoidance: Late or incorrect submissions incur MWK 300,000 penalty plus 2% interest per month on outstanding VAT.
Technology (systems involved)
- PortaBilling: Core billing system with customer records, xDRs, and invoice generation
- MRA EIS API: REST API at https://eis-api.mra.mw/ accepting JSON payloads over HTTPS
- MRA EIS Portal: https://eis-portal.mra.mw/ for terminal registration and configuration management
High-Level Scope of Integration Flows
- Terminal Onboarding: One-time activation using Terminal Activation Code (TAC) obtained from MRA portal. TAC is exchanged for terminal configuration including API tokens.
- Configuration Sync: Daily call to "Get Latest Configuration" endpoint to retrieve current tax rates and parameters.
- Invoice Transmission: Real-time POST to sale transaction endpoint with invoice details; receive invoice validation URL in response.
Key MRA Data Objects
| Field | Example Value |
|---|---|
| terminalId | "3a6d3703-1c39-41e8-98ce-b38d9574540d" |
| invoiceDateTime | 2025-05-28T06:57:11.368Z |
| invoiceNumber | INV-2025-000456 |
| sellerTIN | 5000123456 (The Taxpayer Identification Number of the seller) |
| buyerTIN | 1000234567 (Taxpayer Identification Number) |
| buyerName | Blantyre Medical Supplies Ltd |
| invoiceTotal | 1074793.39 (MWK) |
| totalVAT | 152223.95 (16.5% VAT) |
| invoiceLineItems[] | Array of line items with productCode, description, quantity, unitPrice, taxRateId, ... |
| validationURL | https://eservices.mra.mw/doc/v/?vc=90241313200014&c=fdd8d5ccc06a49d6a1efbf7e3896f0b4 (returned by MRA) |
Stakeholders and Their Benefits
| Stakeholder | Benefit |
|---|---|
| CSP Finance Team | Instant compliance status visibility |
| CSP Management | Zero compliance risk; avoided penalties of MWK 5,000,000+; uninterrupted operations |
| CSP Customers | Valid QR-coded invoices for VAT claims; instant invoice verification via MRA portal |
| CSP PortaBilling Administrator | Automated workflow; centralized configuration; comprehensive audit logs |
| Malawi Revenue Authority | Real-time tax data; reduced fraud; improved compliance monitoring |
Use Cases
Use Case #1: Terminal Onboarding and Activation
Role: PortaBilling System Administrator
Preconditions:
- CSP has registered as a taxpayer with MRA (TIN: 5000123456)
- CSP has applied for EIS terminal via MRA portal and received Terminal Activation Code: TAC-2025-CSP-00001
- PortaBilling system is running on server pb.csp.mw
- EIS integration service is deployed and interconnected with PortaBilling and MRA API
- Administrator "admin@csp.mw" has "EIS Configuration" permission in EIS integration service
- EIS integration service is certified by MRA with Product ID: PO-EIS-2025-001, Version: 1.0.0
- Default customer class "business" (i_customer_class 1) is configured in PortaBilling with regular invoicing
Use Scenario #1.1: Successful Terminal Activation
- At 2025-01-10 09:00:00, Administrator logs into EIS integration service UI with credentials "admin@csp.mw"
- Administrator navigates to MRA EIS Terminals and opens "New Terminal" form
- Administrator enters Terminal Activation Code "TAC-2025-CSP-00001" and clicks "Activate Terminal"
- At 2025-01-10 09:00:03, EIS integration service sends POST request to https://eis-api.mra.mw/api/v1/onboarding/activate-terminal with TAC and Product ID
- At 2025-01-10 09:00:05, MRA API returns HTTP 200 with terminal configuration including terminalId "3a6d3703-1c39-41e8-98ce-b38d9574540d", terminalCredentials and configuration
- EIS integration service stores terminal id, credentials and configuration in EIS integration service storage
- At 2025-01-10 09:00:06, system sends POST to /api/v1/onboarding/terminal-activated-confirmation to acknowledge successful activation
- TAC "TAC-2025-CSP-00001" is marked as consumed in MRA and cannot be reused
- Administrator can see a new entry in MRA EIS Terminals:
- terminalId: "3a6d3703-1c39-41e8-98ce-b38d9574540d"
- terminalLabel: "Primary" (could be "Reseller A")
- status: "Terminal is now fully activated and ready for use!"
- activation performed by admin@csp.mw
- created at 2025-01-10 09:00:06
- Administrator can see a new entry in MRA EIS Configurations and other related entries in MRA EIS Tax Rates
- id: 1
- terminalId: "3a6d3703-1c39-41e8-98ce-b38d9574540d"
- globalConfiguration.versionNo: 1
- etc
- Administrator navigates to "Customer Classes" in EIS integration service UI to configure the terminal for certain PortaBilling customer classes. Administrator adds a mapping record
- i_customer_class: 1
- terminalLabel: "Primary" (dropdown select from MRA EIS Terminals)
Use Scenario #1.2: Terminal Activation with invalid Terminal Activation Code (TAC)
- At 2025-01-10 09:15:00, Administrator enters incorrect TAC "TAC-2025-CSP-99999" and clicks "Activate Terminal"
- At 2025-01-10 09:15:02, EIS integration service sends POST to activation endpoint
- At 2025-01-10 09:15:03, MRA API returns HTTP 400 with error code "INVALID_TAC" and message "Terminal Activation Code not found or expired"
- EIS integration service displays error: "Activation failed: Terminal Activation Code not found or expired. Please verify the code or request a new one from MRA portal."
- Error logged: "EIS activation failed - INVALID_TAC - by admin@csp.mw at 2025-01-10 09:15:03"
- Administrator can retry with correct TAC without system lockout
Use Case #2: Defining product codes of the MRA EIS
Preliminary it will be similar to https://wiki.portaone.com/x/wYgtBg
Roles: CSP, PortaBilling, EIS
Use Scenario #2.1: Product Codes for default Voice Calls service, Usage Charges
- CSP creates new Tax Code in PortaBilling:
- code: 400000001, description: Voice Calls
- CSP creates new Product Code in EIS platform:
- code: 400000001, name: Voice Calls
- same as tax code above, i.e. 1:1 mapping
- note integer for code value
- code: 400000001, name: Voice Calls
- CSP updates a mapping record in "PortaBilling Default Services" table in EIS integration service
- service name: Voice Calls, tax code: 400000001
- This ensures the mapping between charges for default voice usage and EIS product code
Use Scenario #2.2: Product Codes for any Subscription Charges
- CSP creates new Tax Codes in PortaBilling:
- code: 200000001, description: Co-siting
- code: 300000003, description: Data
- code: 500000002, description: Fixed Line Rental
- CSP creates new Product Codes in EIS platform:
- code: 200000001, name: Co-siting
- same as tax code above, i.e. 1:1 mapping
- note integer for code value
- code: 300000003, name: Data
- same as tax code above, i.e. 1:1 mapping
- note integer for code value
- code: 500000002, name: Fixed Line Rental
- same as tax code above, i.e. 1:1 mapping
- note integer for code value
- code: 200000001, name: Co-siting
- CSP creates subscriptions in PortaBilling
- name: "Co-siting Lilongwe" (offering name), tax code for activation/regular/cancellation fees: 200000001
- name: "BusinessCONNECT 886Mbps" (offering name), tax code for activation/regular/cancellation fees: 300000003
- name: "Fixed Line Rental" (offering name), tax code for activation/regular/cancellation fees: 500000002
- This ensures the mapping between subscription charges and EIS product code
Use Scenario #2.3: Product Codes for custom service, Usage Charges
- CSP creates new Tax Code in PortaBilling:
- code: 700000001, description: Communication Service
- CSP creates new Product Code in EIS platform:
- code: 700000001, name: Communication Service
- same as tax code above, i.e. 1:1 mapping
- note integer for code value
- code: 700000001, name: Communication Service
- CSP updates "Communication Service" record in "PortaBilling Services" in PortaBilling
- tax code: 700000001
- This ensures the mapping between charges for custom service usage and EIS product code
Use Scenario #2.4: Product Codes for any Manual/API Charges
Ideally, CSP manages all charges in subscription activation fee so it would be handled by #2.2
- Following #2.3
- CSP applies a manual/API charge for the customer in PortaBilling
- Service: "Communication Service"
- This ensures the mapping between manual/api charges and EIS product code
Use Case #3: Invoice Transmission to MRA EIS
Roles: CSP, EIS, EIS integration service
Preconditions:
- EIS integration service is activated with VAT tax 16.5%
- Customer "Blantyre Medical Supplies Ltd" (Customer ID 102345) has xDRs totaling MWK 1074793.39 (incl. VAT) for the billing period January 1-31, 2025
- PortaBilling invoice template (made via custom html template) includes placeholder for the QR code to be inserted
Use Scenario #3.1: Successful Monthly Invoice Submission, Modification & Delivery
- At the end of billing period PortaBilling regular invoice "11" is generated for Customer ID 102345
- PortaBilling delivers "Invoice/New" event for invoice "11" to the EIS integration service
- EIS integration service immediately acknowledges event for further async processing
- EIS integration service queries invoice "11" data via multiple PortaBilling API requests, e.g.
- Invoice/get_invoice_info
- Customer/get_transactions_total_info
- Customer/get_customer_xdrs filtered by subscriptions service type
- ...
- EIS integration service back-calculates the 16.5% VAT from xDR and total amount (1074793.39 / (116.5%) = 152223.95)
- EIS integration service successfully constructs the JSON payload according to the MRA EIS API specification.
- Headers
PortaBilling Property
PortaBilling Value
EIS Property EIS Value Transformation Rule Invoice No. 11 - - - - -
invoiceHeader.invoiceDateTime 2025-02-01T00:00:00.000Z Now().Format - - invoiceHeader.invoiceNumber EpkAXQ-B-JYec-B Calculated to meet EIS requirements during submission - - invoiceHeader.sellerTIN 5000123456 1:1 from EIS integration service configuration (e.g. cross-reference lookup based on customer class and configuration earlier received via EIS API). - - invoiceHeader.siteId SITE001 same as above - - invoiceHeader.globalConfigVersion 1 same as above - - invoiceHeader.taxpayerConfigVersion 2 same as above - - invoiceHeader.terminalConfigVersion 3 same as above - - invoiceHeader.paymentMethod - not sent as this is not known for the invoice (vs receipt) - Line Items
PortaBilling Property
PortaBilling Value
EIS Property EIS Value Transformation Rule Tax Code, mapped from Subscription fee/Service of xDR 200000001 (/ 400000001 / 300000003) invoiceLineItems[].productCode 200000001 (/ 400000001 / 300000003) 1:1, must match registered product codes Tax Code Description Co-siting (/ Voice Calls / Data) invoiceLineItems[].description Co-siting (/ Voice Calls / Data) 1:1 xDR Charged Amount, aggregated per Tax Code 1000000 (/ 74793 / 0.39) invoiceLineItems[].unitPrice 858369.1 (/ 64200 / 0.33) 1:1 - - invoiceLineItems[].quantity 1 Always xDR Charged Amount, aggregated per Tax Code 1000000 (/ 74793 / 0.39) invoiceLineItems[].total 858369.1 (/ 64200 / 0.33) 1:1 xDR Charged Amount, aggregated per Tax Code 1000000 (/ 74793 / 0.39) invoiceLineItems[].totalVAT 141,630.9 (/ 10593 / 0.06) back-calculated with tax rate for taxRateId below - - invoiceLineItems[].taxRateId A 1:1 from EIS integration service configuration (e.g. cross-reference lookup based on customer class) - - invoiceLineItems[].isProduct false Always since CSP is selling service ONLY - Summary
EIS Property EIS Value Transformation Rule invoiceSummary.taxBreakDown[].rateId A select invoiceLineItems[].taxRateId group by invoiceLineItems[].taxRateId invoiceSummary.taxBreakDown[].taxableAmount 922569.43 select sum (invoiceLineItems[].total) group by invoiceLineItems[].taxRateId invoiceSummary.taxBreakDown[].taxAmount 152223.95 select sum (invoiceLineItems[].totalVAT) group by invoiceLineItems[].taxRateId invoiceSummary.totalVAT 152223.95 select sum (invoiceLineItems[].totalVAT) invoiceSummary.invoiceTotal 1074793.39 sum (invoiceLineItems[].total + invoiceLineItems[].totalVAT) invoiceSummary.amountTendered 0 Always
- Headers
- CSP optionally reviews the above data before it reaches MRA EIS.
- CSP manually adjusts the data, e.g.
- merges multiple line items with the same product code into single line item
- merges negative line items (refunds) into positive line items
- EIS integration service creates audit record about the change (who, when, what)
- CSP manually adjusts the data, e.g.
- EIS integration service / CSP schedules invoice submission in EIS integration service
- EIS integration service sends POST to https://eis-api.mra.mw/api/sale with signed payload
- MRA API returns HTTP 200 with validationURL "https://eservices.mra.mw/doc/v/?vc=90241313200014&c=fdd8d5ccc06a49d6a1efbf7e3896f0b4"
- EIS integration service downloads the "invoice-11" PDF and puts the encoded validation URL as QR code to the previously defined placeholder position on each page of invoice
- EIS integration service saves the modified result to "invoice-11-EpkAXQ-B-JYec-B" PDF to the internal storage
- CSP conducts extra review of modified MDF before it goes to e-mail inbox of customer "Blantyre Medical Supplies Ltd"
- review → download → edit offline → upload is feasible
- EIS integration service creates audit record about the change (who, when, what)
- CSP schedules invoice delivery in EIS integration service
- The "invoice-11-EpkAXQ-B-JYec-B" PDF reaches e-mail inbox of customer "Blantyre Medical Supplies Ltd
Use Scenario #3.2: MRA EIS is not responding (alternative to #3.1)
- Continuation of Use Scenario #3.1 after step 8
- MRA EIS does not respond (or returns 408 request timeout code)
- EIS integration service creates notification to the CSP of unsuccessful MRA report delivery for the invoice "11"
- EIS integration service (or CSP manager) schedules retry attempt for the invoice "11" after an hour
Use Scenario #3.3: There are charges with unmatched EIS Product Codes (alternative to #3.1)
- Continuation of Use Scenario #3.1 after step 5
EIS integration service is not able to map found xDR charge to any EIS Product Codes, however it creates header and line item records for matched charges
- EIS integration service sets invoice "11" to "Review" status and populates "Status Message" or record notes with details of unmatched charge
CSP reviews the data before it reaches MRA EIS.
- As an unfortunate result of mapping mistakes in UC#2, CSP finds that PortaBilling Invoice "11" Total is more than invoiceSummary.invoiceTotal
- CSP reviews details of unmatched charge
- If applicable, CSP fixes the root cause - the missing mapping as per UC#2
- CSP manually adjusts the data in NocoDB tables, e.g. invoiceLineItems[] and invoiceSummary for Invoice "11"
- EIS integration service creates audit record about the change (who, when, what)
- CSP schedules invoice submission in EIS integration service
Use Case #4: Assurance and Reporting
Preconditions:
- EIS integration active for 30+ days with transaction history
- 2,847 invoices transmitted in January 2025 totaling MWK 487,500,000
- Administrator "admin@csp.mw" needs to prepare monthly compliance report
Use Scenario #4.1: Monthly EIS Compliance View
- At 2025-02-02 09:00:00, Administrator navigates to "Sales Transactions" in EIS integration service UI
- Administrator creates view "January 2025"
- EIS integration service queries transaction logs for date range 2025-01-01 to 2025-01-31
- View displays: Total invoices: 2,847; Successful transmissions: 2,842 (99.82%); Failed/Pending: 5; Total amount: MWK 487,500,000; VAT collected: MWK 69,045,064.38
- Administrator selects 5 failed invoices to attempt resubmission
- Failed invoices retried; 4 succeed, 1 remains failed (invalid item code requiring manual correction)
- Successful transmissions rate updated to 99.96% (2,846/2,847)
- Administrator clicks "Export to Excel" for MRA submission records
- Excel export contains columns: Invoice Number, Customer Name, Amount, VAT, Transmission Date, Validation URL, Status
Other Requirements
- OR-1 It should be possible to update EIS integration service configuration to reflect occasional updates to tax rate
Non-functional Requirements
- Performance:
- System generates 550 invoices during billing period closure.
- No customer exceeds more than 1000 subscription charges per billing period
- Availability:
- EIS integration service must achieve 99.9% uptime monthly
- Security:
- API credentials must not appear in logs; use token masking (show first 4 and last 4 characters only)
- Audit and Logging:
- All EIS transactions must be logged with: timestamp, invoice_id, amount, MRA_response_code, duration_ms, user_id
- All EIS records must be retained for 7 years per VAT Act requirements, therefore logs must be retained for 7 years
- Failed transmission attempts must be logged with full error details for troubleshooting
- Compliance:
- Integration must pass MRA API Compliance Certification before production deployment
- According to EIS rep, irrelevant tests will be skipped. They decide on the scope to skip during the first test session
- QR codes must be generated for validationURL that is received on successful online submission
- All amounts must be transmitted in Malawi Kwacha (MWK)
- Integration must pass MRA API Compliance Certification before production deployment