437 lines
12 KiB
Markdown
437 lines
12 KiB
Markdown
# ZATCA E-Invoice Implementation Summary
|
|
|
|
## Overview
|
|
This document summarizes the implementation of ZATCA e-invoice requirements for the AgdarCentre healthcare platform.
|
|
|
|
## Implementation Date
|
|
October 27, 2025
|
|
|
|
## Phase 1: Generation Phase (COMPLETED ✅)
|
|
|
|
### 1. Invoice Counter (ICV)
|
|
**Status:** ✅ Implemented
|
|
|
|
**Location:** `finance/models.py` - Invoice model
|
|
|
|
**Features:**
|
|
- Sequential counter field (`invoice_counter`)
|
|
- Tamper-resistant (cannot be reset)
|
|
- Database indexed for performance
|
|
- Default value of 1 for new invoices
|
|
|
|
**Code:**
|
|
```python
|
|
invoice_counter = models.PositiveIntegerField(
|
|
editable=False,
|
|
db_index=True,
|
|
default=1,
|
|
verbose_name=_("Invoice Counter"),
|
|
help_text=_("Sequential counter per EGS unit, cannot be reset")
|
|
)
|
|
```
|
|
|
|
### 2. Hash Chain (PIH - Previous Invoice Hash)
|
|
**Status:** ✅ Implemented
|
|
|
|
**Location:** `finance/models.py` - Invoice model
|
|
|
|
**Features:**
|
|
- SHA-256 hashing algorithm
|
|
- Current invoice hash (`invoice_hash`)
|
|
- Previous invoice hash (`previous_invoice_hash`)
|
|
- Automatic hash generation on save
|
|
- Links invoices in an unbreakable chain
|
|
|
|
**Code:**
|
|
```python
|
|
def generate_invoice_hash(self):
|
|
"""Generate SHA-256 hash of invoice data."""
|
|
hash_data = {
|
|
'invoice_number': self.invoice_number,
|
|
'invoice_counter': self.invoice_counter,
|
|
'issue_date': str(self.issue_date),
|
|
'issue_time': str(self.issue_time),
|
|
'total': str(self.total),
|
|
'tax': str(self.tax),
|
|
'patient_id': str(self.patient.id) if self.patient else '',
|
|
}
|
|
json_str = json.dumps(hash_data, sort_keys=True)
|
|
hash_bytes = hashlib.sha256(json_str.encode('utf-8')).digest()
|
|
return hash_bytes.hex()
|
|
```
|
|
|
|
### 3. QR Code Generation
|
|
**Status:** ✅ Implemented
|
|
|
|
**Location:** `finance/models.py` - Invoice model
|
|
|
|
**Features:**
|
|
- TLV (Tag-Length-Value) encoding
|
|
- Base64 encoded output
|
|
- **Phase 1 Fields (5 tags):**
|
|
1. Seller's Name
|
|
2. VAT Registration Number
|
|
3. Timestamp (ISO 8601 format)
|
|
4. Invoice Total (with VAT)
|
|
5. VAT Total
|
|
- **Phase 2 Ready (tags 6-9):**
|
|
6. Hash of XML invoice
|
|
7. ECDSA signature
|
|
8. ECDSA public key
|
|
9. ECDSA signature of cryptographic stamp's public key
|
|
|
|
**Code:**
|
|
```python
|
|
def generate_qr_code(self):
|
|
"""Generate ZATCA-compliant QR code in TLV format."""
|
|
def encode_tlv(tag, value):
|
|
value_bytes = str(value).encode('utf-8')
|
|
length = len(value_bytes)
|
|
return bytes([tag, length]) + value_bytes
|
|
|
|
# Tag 1-5: Phase 1 fields
|
|
# Tag 6-9: Phase 2 fields (if available)
|
|
# ...
|
|
qr_code_base64 = base64.b64encode(tlv_data).decode('utf-8')
|
|
return qr_code_base64
|
|
```
|
|
|
|
### 4. Invoice Type Classification
|
|
**Status:** ✅ Implemented
|
|
|
|
**Location:** `finance/models.py` - Invoice model
|
|
|
|
**Features:**
|
|
- 6 invoice types supported:
|
|
- `STANDARD` - Standard Tax Invoice (B2B)
|
|
- `SIMPLIFIED` - Simplified Tax Invoice (B2C)
|
|
- `STANDARD_DEBIT` - Standard Debit Note
|
|
- `STANDARD_CREDIT` - Standard Credit Note
|
|
- `SIMPLIFIED_DEBIT` - Simplified Debit Note
|
|
- `SIMPLIFIED_CREDIT` - Simplified Credit Note
|
|
|
|
**Code:**
|
|
```python
|
|
class InvoiceType(models.TextChoices):
|
|
STANDARD = 'STANDARD', _('Standard Tax Invoice (B2B)')
|
|
SIMPLIFIED = 'SIMPLIFIED', _('Simplified Tax Invoice (B2C)')
|
|
STANDARD_DEBIT = 'STANDARD_DEBIT', _('Standard Debit Note')
|
|
STANDARD_CREDIT = 'STANDARD_CREDIT', _('Standard Credit Note')
|
|
SIMPLIFIED_DEBIT = 'SIMPLIFIED_DEBIT', _('Simplified Debit Note')
|
|
SIMPLIFIED_CREDIT = 'SIMPLIFIED_CREDIT', _('Simplified Credit Note')
|
|
```
|
|
|
|
### 5. Credit/Debit Note Support
|
|
**Status:** ✅ Implemented
|
|
|
|
**Location:** `finance/models.py` - Invoice model
|
|
|
|
**Features:**
|
|
- Billing reference ID field
|
|
- Billing reference issue date
|
|
- Helper property to identify credit/debit notes
|
|
|
|
**Code:**
|
|
```python
|
|
billing_reference_id = models.CharField(
|
|
max_length=50,
|
|
blank=True,
|
|
verbose_name=_("Billing Reference ID"),
|
|
help_text=_("Reference to original invoice for credit/debit notes")
|
|
)
|
|
|
|
@property
|
|
def is_credit_or_debit_note(self):
|
|
"""Check if this is a credit or debit note."""
|
|
return self.invoice_type in [
|
|
self.InvoiceType.STANDARD_CREDIT,
|
|
self.InvoiceType.STANDARD_DEBIT,
|
|
self.InvoiceType.SIMPLIFIED_CREDIT,
|
|
self.InvoiceType.SIMPLIFIED_DEBIT,
|
|
]
|
|
```
|
|
|
|
## Phase 2: Integration Phase (COMPLETED ✅)
|
|
|
|
### 1. XML Generation Service (UBL 2.1)
|
|
**Status:** ✅ Implemented
|
|
|
|
**Location:** `finance/zatca_service.py` - ZATCAService class
|
|
|
|
**Features:**
|
|
- Full UBL 2.1 XML generation
|
|
- Proper namespace handling
|
|
- Support for all invoice types
|
|
- Includes:
|
|
- UBL Extensions (signatures, QR code)
|
|
- Invoice identification (IRN, UUID)
|
|
- Supplier/Customer party information
|
|
- Tax totals and breakdowns
|
|
- Line items with tax details
|
|
- Billing references for credit/debit notes
|
|
|
|
**Key Methods:**
|
|
- `generate_xml_invoice()` - Main XML generation
|
|
- `_add_ubl_extensions()` - Add signatures and QR
|
|
- `_add_supplier_party()` - Seller information
|
|
- `_add_customer_party()` - Buyer information
|
|
- `_add_tax_total()` - VAT calculations
|
|
- `_add_invoice_lines()` - Line items
|
|
|
|
### 2. FATOORA API Integration
|
|
**Status:** ✅ Implemented
|
|
|
|
**Location:** `finance/zatca_service.py` - ZATCAService class
|
|
|
|
**Features:**
|
|
- **Clearance API** (for Standard Invoices - B2B)
|
|
- Real-time submission before sharing with buyer
|
|
- Returns cleared invoice with ZATCA stamp
|
|
- Endpoint: `/invoices/clearance/single`
|
|
|
|
- **Reporting API** (for Simplified Invoices - B2C)
|
|
- Submit within 24 hours of generation
|
|
- Near real-time validation
|
|
- Endpoint: `/invoices/reporting/single`
|
|
|
|
- **Environment Support:**
|
|
- Sandbox: `https://gw-fatoora.zatca.gov.sa/e-invoicing/simulation`
|
|
- Production: `https://gw-fatoora.zatca.gov.sa/e-invoicing/core`
|
|
|
|
**Key Methods:**
|
|
```python
|
|
def submit_for_clearance(self, invoice, csid: str, secret: str) -> Tuple[bool, Dict]:
|
|
"""Submit standard invoice for clearance."""
|
|
# Returns (success, response_data)
|
|
|
|
def submit_for_reporting(self, invoice, csid: str, secret: str) -> Tuple[bool, Dict]:
|
|
"""Submit simplified invoice for reporting."""
|
|
# Returns (success, response_data)
|
|
```
|
|
|
|
### 3. Phase 2 Preparation Fields
|
|
**Status:** ✅ Implemented
|
|
|
|
**Location:** `finance/models.py` - Invoice model
|
|
|
|
**Features:**
|
|
- `cryptographic_stamp` - For ECDSA signatures
|
|
- `zatca_status` - Clearance/Reporting status
|
|
- `zatca_submission_date` - Submission timestamp
|
|
- `zatca_response` - JSON field for API responses
|
|
- `xml_content` - UBL 2.1 XML storage
|
|
- `issue_time` - Precise timestamp
|
|
|
|
## Database Schema Changes
|
|
|
|
### New Fields Added to Invoice Model:
|
|
1. `invoice_counter` - PositiveIntegerField (indexed)
|
|
2. `invoice_type` - CharField with choices
|
|
3. `billing_reference_id` - CharField
|
|
4. `billing_reference_issue_date` - DateField
|
|
5. `issue_time` - TimeField
|
|
6. `invoice_hash` - CharField (64 chars)
|
|
7. `previous_invoice_hash` - CharField (64 chars)
|
|
8. `qr_code` - TextField
|
|
9. `cryptographic_stamp` - TextField
|
|
10. `zatca_status` - CharField
|
|
11. `zatca_submission_date` - DateTimeField
|
|
12. `zatca_response` - JSONField
|
|
13. `xml_content` - TextField
|
|
|
|
### Indexes Added:
|
|
- `invoice_counter` - For performance
|
|
- `invoice_type, status` - For filtering
|
|
|
|
## VAT Handling
|
|
|
|
**Current Implementation:**
|
|
- 15% VAT applied to non-Saudi patients
|
|
- 0% VAT for Saudi citizens (national ID starts with '1')
|
|
- Automatic VAT calculation in invoice model
|
|
|
|
**Code:**
|
|
```python
|
|
@property
|
|
def should_apply_vat(self):
|
|
"""Determine if VAT should be applied to this invoice."""
|
|
return not self.is_saudi_patient
|
|
|
|
@property
|
|
def is_saudi_patient(self):
|
|
"""Check if patient is Saudi based on national ID."""
|
|
if self.patient and self.patient.national_id:
|
|
return self.patient.national_id.startswith('1')
|
|
return False
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### 1. Generate XML for Invoice
|
|
```python
|
|
from finance.zatca_service import ZATCAService
|
|
|
|
# Initialize service (sandbox mode)
|
|
zatca = ZATCAService(use_sandbox=True)
|
|
|
|
# Generate XML
|
|
xml_content = zatca.generate_xml_invoice(invoice)
|
|
|
|
# Save to invoice
|
|
invoice.xml_content = xml_content
|
|
invoice.save()
|
|
```
|
|
|
|
### 2. Submit Standard Invoice for Clearance
|
|
```python
|
|
from finance.zatca_service import ZATCAService
|
|
|
|
zatca = ZATCAService(use_sandbox=True)
|
|
|
|
# Submit for clearance (B2B)
|
|
success, response = zatca.submit_for_clearance(
|
|
invoice=invoice,
|
|
csid='your-csid-here',
|
|
secret='your-secret-here'
|
|
)
|
|
|
|
if success:
|
|
# Update invoice with ZATCA response
|
|
invoice.zatca_status = 'CLEARED'
|
|
invoice.zatca_response = response
|
|
invoice.zatca_submission_date = timezone.now()
|
|
invoice.save()
|
|
```
|
|
|
|
### 3. Submit Simplified Invoice for Reporting
|
|
```python
|
|
from finance.zatca_service import ZATCAService
|
|
|
|
zatca = ZATCAService(use_sandbox=True)
|
|
|
|
# Submit for reporting (B2C)
|
|
success, response = zatca.submit_for_reporting(
|
|
invoice=invoice,
|
|
csid='your-csid-here',
|
|
secret='your-secret-here'
|
|
)
|
|
|
|
if success:
|
|
# Update invoice with ZATCA response
|
|
invoice.zatca_status = 'REPORTED'
|
|
invoice.zatca_response = response
|
|
invoice.zatca_submission_date = timezone.now()
|
|
invoice.save()
|
|
```
|
|
|
|
## Remaining Work (Future Enhancements)
|
|
|
|
### 1. Cryptographic Signing (ECDSA)
|
|
- Implement ECDSA signing with secp256k1 curve
|
|
- Generate and manage private/public key pairs
|
|
- Sign simplified invoices before submission
|
|
|
|
### 2. CSID Management
|
|
- Create model to store CSIDs
|
|
- Implement CSID renewal process
|
|
- Handle CSID expiration
|
|
- Secure storage of private keys
|
|
|
|
### 3. PDF/A-3 Generation
|
|
- Generate PDF/A-3 with embedded XML
|
|
- Include QR code in PDF
|
|
- Proper formatting for invoices
|
|
|
|
### 4. Failure Handling
|
|
- Implement retry logic for failed submissions
|
|
- Offline mode support
|
|
- Queue system for pending submissions
|
|
- Error logging and monitoring
|
|
|
|
### 5. Arabic Language Support
|
|
- Full bilingual support (Arabic + English)
|
|
- Arabic invoice templates
|
|
- RTL layout support
|
|
|
|
### 6. Compliance Audit Logging
|
|
- Track all ZATCA submissions
|
|
- Log all API responses
|
|
- Audit trail for invoice changes
|
|
- Compliance reporting
|
|
|
|
## Testing Recommendations
|
|
|
|
### 1. Unit Tests
|
|
- Test QR code generation
|
|
- Test hash chain integrity
|
|
- Test XML generation
|
|
- Test invoice counter sequence
|
|
|
|
### 2. Integration Tests
|
|
- Test ZATCA API integration (sandbox)
|
|
- Test clearance workflow
|
|
- Test reporting workflow
|
|
- Test error handling
|
|
|
|
### 3. End-to-End Tests
|
|
- Complete invoice lifecycle
|
|
- Credit/debit note workflow
|
|
- Multi-invoice scenarios
|
|
|
|
## Security Considerations
|
|
|
|
1. **CSID Storage:** Store CSIDs and secrets securely (encrypted)
|
|
2. **Private Keys:** Never export private keys
|
|
3. **API Credentials:** Use environment variables
|
|
4. **Audit Logging:** Log all ZATCA interactions
|
|
5. **Data Validation:** Validate all inputs before submission
|
|
|
|
## Compliance Checklist
|
|
|
|
- [x] Invoice Counter (ICV) - Sequential, tamper-resistant
|
|
- [x] Previous Invoice Hash (PIH) - SHA-256 chain
|
|
- [x] QR Code - TLV encoded, Base64
|
|
- [x] Invoice Types - Standard/Simplified distinction
|
|
- [x] Credit/Debit Notes - Billing references
|
|
- [x] XML Generation - UBL 2.1 format
|
|
- [x] Clearance API - Standard invoices (B2B)
|
|
- [x] Reporting API - Simplified invoices (B2C)
|
|
- [ ] ECDSA Signing - secp256k1 curve
|
|
- [ ] CSID Management - Storage and renewal
|
|
- [ ] PDF/A-3 Generation - With embedded XML
|
|
- [ ] Offline Mode - Queue and retry
|
|
- [ ] Arabic Support - Full bilingual
|
|
- [ ] Audit Logging - Compliance tracking
|
|
|
|
## References
|
|
|
|
1. **ZATCA Documentation:**
|
|
- E-Invoicing Detailed Technical Guideline
|
|
- User Manual Developer Portal Manual Version 3
|
|
- Fatoora Portal User Manual
|
|
|
|
2. **API Endpoints:**
|
|
- Sandbox: https://gw-fatoora.zatca.gov.sa/e-invoicing/simulation
|
|
- Production: https://gw-fatoora.zatca.gov.sa/e-invoicing/core
|
|
|
|
3. **Standards:**
|
|
- UBL 2.1 (Universal Business Language)
|
|
- ISO 8601 (Date/Time format)
|
|
- SHA-256 (Hashing algorithm)
|
|
- ECDSA secp256k1 (Cryptographic signing)
|
|
|
|
## Support
|
|
|
|
For issues or questions:
|
|
- ZATCA Support: https://zatca.gov.sa
|
|
- Developer Portal: https://sandbox.zatca.gov.sa/
|
|
- Email: info@zatca.gov.sa
|
|
- Phone: 19993 (Local), +966112048998 (International)
|
|
|
|
---
|
|
|
|
**Document Version:** 1.0
|
|
**Last Updated:** October 27, 2025
|
|
**Author:** Cline AI Assistant
|
|
**Project:** AgdarCentre Healthcare Platform
|