Reviewers (PMD-3368) :

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

FieldExample Value
terminalId"3a6d3703-1c39-41e8-98ce-b38d9574540d"
invoiceDateTime2025-05-28T06:57:11.368Z
invoiceNumberINV-2025-000456 
sellerTIN5000123456 (The Taxpayer Identification Number of the seller)
buyerTIN1000234567 (Taxpayer Identification Number)
buyerNameBlantyre Medical Supplies Ltd
invoiceTotal1074793.39 (MWK)
totalVAT152223.95 (16.5% VAT)
invoiceLineItems[]Array of line items with productCode, description, quantity, unitPrice, taxRateId, ...
validationURLhttps://eservices.mra.mw/doc/v/?vc=90241313200014&c=fdd8d5ccc06a49d6a1efbf7e3896f0b4 (returned by MRA)

Stakeholders and Their Benefits

StakeholderBenefit
CSP Finance TeamInstant compliance status visibility
CSP ManagementZero compliance risk; avoided penalties of MWK 5,000,000+; uninterrupted operations
CSP CustomersValid QR-coded invoices for VAT claims; instant invoice verification via MRA portal
CSP PortaBilling AdministratorAutomated workflow; centralized configuration; comprehensive audit logs
Malawi Revenue AuthorityReal-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

  1. At 2025-01-10 09:00:00, Administrator logs into EIS integration service UI with credentials "admin@csp.mw"
  2. Administrator navigates to MRA EIS Terminals and opens "New Terminal" form
  3. Administrator enters Terminal Activation Code "TAC-2025-CSP-00001" and clicks "Activate Terminal"
  4. 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
  5. 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
  6. EIS integration service stores terminal id, credentials and configuration in EIS integration service storage
  7. At 2025-01-10 09:00:06, system sends POST to /api/v1/onboarding/terminal-activated-confirmation to acknowledge successful activation
  8. TAC "TAC-2025-CSP-00001" is marked as consumed in MRA and cannot be reused 
  9. 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
  10. 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
  11. 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)

  1. At 2025-01-10 09:15:00, Administrator enters incorrect TAC "TAC-2025-CSP-99999" and clicks "Activate Terminal"
  2. At 2025-01-10 09:15:02, EIS integration service sends POST to activation endpoint
  3. 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"
  4. 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."
  5. Error logged: "EIS activation failed - INVALID_TAC - by admin@csp.mw at 2025-01-10 09:15:03"
  6. 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

  1. CSP creates new Tax Code in PortaBilling:
    • code: 400000001, description: Voice Calls
  2. 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
  3. CSP updates a mapping record in "PortaBilling Default Services" table in EIS integration service
    • service name: Voice Calls, tax code: 400000001
  4. This ensures the mapping between charges for default voice usage and EIS product code

Use Scenario #2.2: Product Codes for any Subscription Charges

  1. CSP creates new Tax Codes in PortaBilling:
    • code: 200000001, description: Co-siting
    • code: 300000003, description: Data
    • code: 500000002, description: Fixed Line Rental
  2. 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
  3. 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
  4. This ensures the mapping between subscription charges and EIS product code

Use Scenario #2.3: Product Codes for custom service, Usage Charges

  1. CSP creates new Tax Code in PortaBilling:
    • code: 700000001, description: Communication Service
  2. 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
  3. CSP updates "Communication Service" record in "PortaBilling Services" in PortaBilling
    • tax code: 700000001
  4. 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

  1. Following #2.3
  2. CSP applies a manual/API charge for the customer in PortaBilling
    • Service: "Communication Service"
  3. 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

  1. At the end of billing period PortaBilling regular invoice "11" is generated for Customer ID 102345
  2. PortaBilling delivers "Invoice/New" event for invoice "11" to the EIS integration service
  3. EIS integration service immediately acknowledges event for further async processing
  4. EIS integration service queries invoice "11" data via multiple PortaBilling API requests, e.g.
    1. Invoice/get_invoice_info
    2. Customer/get_transactions_total_info
    3. Customer/get_customer_xdrs filtered by subscriptions service type
    4. ...
  5. EIS integration service back-calculates the 16.5% VAT from xDR and total amount (1074793.39 / (116.5%) = 152223.95) 
  6. EIS integration service successfully constructs the JSON payload according to the MRA EIS API specification.
    • Headers

      PortaBilling Property

      PortaBilling Value

      EIS PropertyEIS ValueTransformation Rule
      Invoice No.11---
      -

      -

      invoiceHeader.invoiceDateTime2025-02-01T00:00:00.000ZNow().Format
      --invoiceHeader.invoiceNumberEpkAXQ-B-JYec-BCalculated to meet EIS requirements during submission
      --invoiceHeader.sellerTIN50001234561:1 from EIS integration service configuration (e.g. cross-reference lookup based on customer class and configuration earlier received via EIS API).
      -- invoiceHeader.siteId SITE001same as above
      -- invoiceHeader.globalConfigVersion 1same as above
      --invoiceHeader.taxpayerConfigVersion2same as above
      --invoiceHeader.terminalConfigVersion3same as above
      -- invoiceHeader.paymentMethod -not sent as this is not known for the invoice (vs receipt)
    • Line Items

      PortaBilling Property

      PortaBilling Value

      EIS PropertyEIS ValueTransformation Rule
      Tax Code, mapped from Subscription fee/Service of xDR200000001 (/ 400000001 / 300000003)invoiceLineItems[].productCode200000001 (/ 400000001 / 300000003)1:1, must match registered product codes
      Tax Code DescriptionCo-siting (/ Voice Calls / Data)invoiceLineItems[].descriptionCo-siting (/ Voice Calls / Data)1:1 
      xDR Charged Amount, aggregated per Tax Code1000000 (/ 74793 / 0.39)invoiceLineItems[].unitPrice858369.1 (/ 64200 / 0.33)1:1
      --invoiceLineItems[].quantity1Always
      xDR Charged Amount, aggregated per Tax Code1000000 (/ 74793 / 0.39)invoiceLineItems[].total858369.1 (/ 64200 / 0.33)1:1
      xDR Charged Amount, aggregated per Tax Code1000000 (/ 74793 / 0.39)invoiceLineItems[].totalVAT141,630.9 (/ 10593 / 0.06)back-calculated with tax rate for taxRateId below
      --invoiceLineItems[].taxRateIdA1:1 from EIS integration service configuration (e.g. cross-reference lookup based on customer class)
      --invoiceLineItems[].isProductfalseAlways since CSP is selling service ONLY
    • Summary 
      EIS PropertyEIS ValueTransformation Rule
      invoiceSummary.taxBreakDown[].rateIdAselect invoiceLineItems[].taxRateId group by invoiceLineItems[].taxRateId
      invoiceSummary.taxBreakDown[].taxableAmount922569.43select sum (invoiceLineItems[].total) group by invoiceLineItems[].taxRateId
      invoiceSummary.taxBreakDown[].taxAmount152223.95select sum (invoiceLineItems[].totalVAT) group by invoiceLineItems[].taxRateId
      invoiceSummary.totalVAT152223.95select sum (invoiceLineItems[].totalVAT)
      invoiceSummary.invoiceTotal1074793.39sum (invoiceLineItems[].total + invoiceLineItems[].totalVAT)
      invoiceSummary.amountTendered0Always
  7. 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)
  8. EIS integration service / CSP schedules invoice submission in EIS integration service
  9. EIS integration service sends POST to https://eis-api.mra.mw/api/sale with signed payload
  10. MRA API returns HTTP 200 with validationURL "https://eservices.mra.mw/doc/v/?vc=90241313200014&c=fdd8d5ccc06a49d6a1efbf7e3896f0b4"
  11. 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
  12. EIS integration service saves the modified result to "invoice-11-EpkAXQ-B-JYec-B" PDF to the internal storage
  13. 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)
  14. CSP schedules invoice delivery in EIS integration service
  15. 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)

  1. Continuation of Use Scenario #3.1 after step 8
  2. MRA EIS does not respond (or returns 408 request timeout code)
  3. EIS integration service creates notification to the CSP of unsuccessful MRA report delivery for the invoice "11"
  4. 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)

  1. Continuation of Use Scenario #3.1 after step 5
  2. 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

  3. EIS integration service sets invoice "11" to "Review" status and populates "Status Message" or record notes with details of unmatched charge
  4. 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)
  5. 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

  1. At 2025-02-02 09:00:00, Administrator navigates to "Sales Transactions" in EIS integration service UI
  2. Administrator creates view "January 2025"
  3. EIS integration service queries transaction logs for date range 2025-01-01 to 2025-01-31
  4. 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
  5. Administrator selects 5 failed invoices to attempt resubmission
  6. Failed invoices retried; 4 succeed, 1 remains failed (invalid item code requiring manual correction)
  7. Successful transmissions rate updated to 99.96% (2,846/2,847)
  8. Administrator clicks "Export to Excel" for MRA submission records
  9. 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)