# ZATCA E-Invoice Enhancement Recommendations ## Executive Summary Your AgdarCentre e-invoice implementation has been significantly enhanced with ZATCA compliance features. This document provides recommendations for further improvements and production readiness. --- ## ✅ What Has Been Implemented ### Phase 1: Generation Phase (Mandatory since Dec 4, 2021) 1. ✅ **Invoice Counter (ICV)** - Sequential, tamper-resistant 2. ✅ **Hash Chain (PIH)** - SHA-256 linking of invoices 3. ✅ **QR Code Generation** - TLV encoded, Base64 format (5 fields) 4. ✅ **Invoice Type Classification** - Standard/Simplified distinction 5. ✅ **Credit/Debit Note Support** - With billing references ### Phase 2: Integration Phase (Mandatory from Jan 1, 2023 in waves) 6. ✅ **XML Generation** - UBL 2.1 format 7. ✅ **FATOORA API Integration** - Clearance & Reporting APIs 8. ✅ **CSID Management** - Storage, validation, renewal tracking 9. ✅ **Automated Tasks** - Celery tasks for submission and monitoring 10. ✅ **Failure Handling** - Retry logic and error tracking --- ## 🔧 Critical Enhancements Needed ### 1. Cryptographic Signing (ECDSA) - HIGH PRIORITY ⚠️ **Current Status:** Not implemented **Requirements:** - ECDSA signing using secp256k1 curve - Private key generation and secure storage - Public key extraction - Digital signature generation **Recommended Implementation:** ```python # Install cryptography library pip install cryptography ecdsa # In finance/crypto_service.py from ecdsa import SigningKey, SECP256k1 import hashlib class CryptoService: @staticmethod def generate_key_pair(): """Generate ECDSA key pair.""" private_key = SigningKey.generate(curve=SECP256k1) public_key = private_key.get_verifying_key() return private_key, public_key @staticmethod def sign_invoice(invoice_hash: str, private_key) -> str: """Sign invoice hash with private key.""" signature = private_key.sign( invoice_hash.encode('utf-8'), hashfunc=hashlib.sha256 ) return base64.b64encode(signature).decode('utf-8') ``` **Action Items:** - [ ] Install cryptography libraries - [ ] Create crypto_service.py module - [ ] Implement key generation - [ ] Implement signing function - [ ] Store private keys securely (encrypted) - [ ] Update Invoice.save() to sign simplified invoices --- ### 2. Tenant VAT Number Field - HIGH PRIORITY ⚠️ **Current Status:** Referenced but not in Tenant model **Issue:** Code references `tenant.vat_number` but field doesn't exist **Recommended Fix:** ```python # In core/models.py - Tenant model vat_number = models.CharField( max_length=15, unique=True, validators=[ RegexValidator( regex=r'^3\d{13}3$', message='VAT number must be 15 digits starting and ending with 3' ) ], verbose_name=_("VAT Registration Number") ) ``` **Action Items:** - [ ] Add vat_number field to Tenant model - [ ] Create migration - [ ] Update admin interface - [ ] Add validation --- ### 3. PDF/A-3 Generation - MEDIUM PRIORITY **Current Status:** Not implemented **Requirements:** - Generate PDF/A-3 compliant documents - Embed XML inside PDF - Include QR code image - Bilingual layout (Arabic + English) **Recommended Libraries:** ```bash pip install reportlab PyPDF2 qrcode pillow ``` **Implementation Approach:** ```python # In finance/pdf_service.py from reportlab.pdfgen import canvas from reportlab.lib.pagesizes import A4 import qrcode class PDFService: @staticmethod def generate_invoice_pdf(invoice): """Generate PDF/A-3 with embedded XML.""" # 1. Generate PDF layout # 2. Add QR code image # 3. Embed XML as attachment # 4. Return PDF bytes pass ``` **Action Items:** - [ ] Install PDF libraries - [ ] Create PDF template - [ ] Implement QR code image generation - [ ] Implement XML embedding - [ ] Add Arabic font support --- ### 4. Invoice Counter Auto-Increment - HIGH PRIORITY ⚠️ **Current Status:** Manual counter management in views **Issue:** Counter should auto-increment in model save **Recommended Fix:** ```python # In finance/models.py - Invoice.save() def save(self, *args, **kwargs): """Override save to auto-generate counter, hash, and QR.""" # Auto-increment counter if new invoice if not self.pk and not self.invoice_counter: from finance.csid_manager import InvoiceCounterManager self.invoice_counter = InvoiceCounterManager.get_next_counter(self.tenant) self.previous_invoice_hash = InvoiceCounterManager.get_previous_invoice_hash(self.tenant) # Generate hash if not self.invoice_hash: self.invoice_hash = self.generate_invoice_hash() # Generate QR code self.qr_code = self.generate_qr_code() super().save(*args, **kwargs) ``` **Action Items:** - [ ] Move counter logic to model save - [ ] Add transaction locking to prevent race conditions - [ ] Test concurrent invoice creation --- ### 5. Arabic Language Support - MEDIUM PRIORITY **Current Status:** Partial (name_en/name_ar fields exist) **Requirements:** - All invoice data must be in Arabic - Bilingual support (Arabic + English) - RTL layout for Arabic - Arabic numerals or Hindi numerals **Recommended Implementation:** ```python # In finance/models.py class Invoice: # Add Arabic fields notes_ar = models.TextField(blank=True) def get_seller_name_ar(self): """Get seller name in Arabic.""" return getattr(self.tenant, 'name_ar', self.tenant.name) def get_patient_name_ar(self): """Get patient name in Arabic.""" if hasattr(self.patient, 'full_name_ar'): return self.patient.full_name_ar return str(self.patient) ``` **Action Items:** - [ ] Add Arabic fields to all models - [ ] Create Arabic invoice templates - [ ] Implement RTL CSS - [ ] Add Arabic translations - [ ] Test Arabic PDF generation --- ### 6. Offline Mode Support - MEDIUM PRIORITY **Current Status:** Not implemented **Requirements:** - Queue invoices when offline - Auto-submit when connection restored - Local storage of pending submissions - Sync status tracking **Recommended Implementation:** ```python # In finance/models.py class InvoiceSubmissionQueue(models.Model): """Queue for offline invoice submissions.""" invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE) submission_type = models.CharField(max_length=20) # CLEARANCE/REPORTING attempts = models.PositiveIntegerField(default=0) last_attempt = models.DateTimeField(null=True) status = models.CharField(max_length=20) # PENDING/SUBMITTED/FAILED error_message = models.TextField(blank=True) ``` **Action Items:** - [ ] Create submission queue model - [ ] Implement offline detection - [ ] Create background sync task - [ ] Add UI indicators for offline mode --- ### 7. CSID Onboarding Integration - HIGH PRIORITY ⚠️ **Current Status:** CSID model exists, but no onboarding flow **Requirements:** - OTP generation integration - CSR (Certificate Signing Request) generation - Compliance checks - Production CSID retrieval **Recommended Implementation:** ```python # In finance/onboarding_service.py class OnboardingService: @staticmethod def generate_csr(tenant, egs_info): """Generate Certificate Signing Request.""" # Use OpenSSL or cryptography library pass @staticmethod def request_compliance_csid(csr, otp): """Request compliance CSID from ZATCA.""" # POST to /compliance endpoint pass @staticmethod def request_production_csid(compliance_csid, request_id): """Request production CSID from ZATCA.""" # POST to /production/csids endpoint pass ``` **Action Items:** - [ ] Create onboarding service - [ ] Implement CSR generation - [ ] Add OTP input UI - [ ] Implement compliance checks - [ ] Add CSID renewal workflow --- ### 8. Enhanced Error Handling - MEDIUM PRIORITY **Current Status:** Basic error handling in tasks **Enhancements Needed:** - Detailed error categorization - User-friendly error messages - Error recovery suggestions - Admin notifications for critical errors **Recommended Implementation:** ```python # In finance/error_handler.py class ZATCAErrorHandler: ERROR_CODES = { '400': 'Invalid request - check invoice data', '401': 'Authentication failed - check CSID', '413': 'Invoice too large - reduce size', '429': 'Too many requests - rate limited', '500': 'ZATCA server error - retry later', '503': 'Service unavailable - retry later', } @staticmethod def handle_error(response, invoice): """Handle ZATCA API error.""" error_code = str(response.get('status_code', '')) error_msg = ZATCAErrorHandler.ERROR_CODES.get(error_code, 'Unknown error') # Log error # Create notification # Suggest recovery action pass ``` **Action Items:** - [ ] Create error handler class - [ ] Map all ZATCA error codes - [ ] Add user notifications - [ ] Create error recovery guide --- ### 9. Compliance Dashboard - LOW PRIORITY **Current Status:** Basic financial reports exist **Enhancements:** - ZATCA submission statistics - Compliance rate tracking - Failed submission alerts - CSID status monitoring - Invoice sequence validation **Recommended Features:** - Real-time compliance metrics - Submission success rate charts - Failed invoice list with retry options - CSID expiry calendar - Audit log viewer **Action Items:** - [ ] Create compliance dashboard view - [ ] Add ZATCA-specific metrics - [ ] Implement charts and graphs - [ ] Add export functionality --- ### 10. Testing & Validation - HIGH PRIORITY ⚠️ **Current Status:** No automated tests for ZATCA features **Recommended Tests:** ```python # In finance/tests/test_zatca.py class ZATCAComplianceTests(TestCase): def test_qr_code_generation(self): """Test QR code TLV encoding.""" pass def test_hash_chain_integrity(self): """Test invoice hash chain.""" pass def test_invoice_counter_sequence(self): """Test counter increments correctly.""" pass def test_xml_generation(self): """Test UBL 2.1 XML generation.""" pass def test_clearance_api(self): """Test clearance API integration.""" pass def test_reporting_api(self): """Test reporting API integration.""" pass ``` **Action Items:** - [ ] Create test suite for ZATCA features - [ ] Test QR code generation - [ ] Test hash chain - [ ] Test XML generation - [ ] Test API integration (sandbox) - [ ] Test failure scenarios --- ## 📋 Implementation Priority Matrix ### Immediate (Week 1) 1. ✅ Add vat_number field to Tenant model 2. ✅ Move counter auto-increment to model save 3. ✅ Implement cryptographic signing (ECDSA) 4. ✅ Create basic test suite ### Short-term (Week 2-3) 5. ✅ Implement onboarding service 6. ✅ Add enhanced error handling 7. ✅ Create PDF/A-3 generation 8. ✅ Add offline mode support ### Medium-term (Month 1-2) 9. ✅ Full Arabic language support 10. ✅ Compliance dashboard 11. ✅ Comprehensive testing 12. ✅ Performance optimization --- ## 🔒 Security Recommendations ### 1. CSID Secret Storage **Current:** Plain text in database **Recommended:** Encrypted storage ```python from cryptography.fernet import Fernet class SecureCSIDStorage: @staticmethod def encrypt_secret(secret: str) -> str: """Encrypt CSID secret.""" key = settings.ENCRYPTION_KEY f = Fernet(key) return f.encrypt(secret.encode()).decode() @staticmethod def decrypt_secret(encrypted: str) -> str: """Decrypt CSID secret.""" key = settings.ENCRYPTION_KEY f = Fernet(key) return f.decrypt(encrypted.encode()).decode() ``` ### 2. Private Key Protection - Store in hardware security module (HSM) if available - Use Django's SECRET_KEY for encryption - Never log or expose private keys - Implement key rotation policy ### 3. API Authentication - Use environment variables for credentials - Implement rate limiting - Add request signing - Monitor for suspicious activity --- ## 📊 Monitoring & Alerting ### Recommended Metrics to Track: 1. **Submission Success Rate** - Target: >99% - Alert if <95% 2. **Average Submission Time** - Target: <2 seconds - Alert if >5 seconds 3. **Failed Submissions** - Alert on any 400 errors (data issues) - Auto-retry on 500 errors (server issues) 4. **CSID Expiry** - Alert 30 days before expiry - Alert 7 days before expiry - Alert on expiry day 5. **Invoice Sequence Gaps** - Daily validation - Alert on any gaps detected ### Recommended Tools: - Sentry for error tracking - Prometheus for metrics - Grafana for dashboards - PagerDuty for critical alerts --- ## 🧪 Testing Strategy ### 1. Unit Tests ```python # Test QR code generation def test_qr_code_tlv_encoding(): invoice = create_test_invoice() qr = invoice.generate_qr_code() # Decode and verify decoded = base64.b64decode(qr) assert decoded[0] == 1 # Tag 1 assert decoded[1] > 0 # Length # ... verify all tags # Test hash chain def test_invoice_hash_chain(): inv1 = create_invoice() inv2 = create_invoice() assert inv2.previous_invoice_hash == inv1.invoice_hash ``` ### 2. Integration Tests ```python # Test ZATCA API (sandbox) def test_clearance_api_integration(): invoice = create_standard_invoice() zatca = ZATCAService(use_sandbox=True) success, response = zatca.submit_for_clearance( invoice, test_csid, test_secret ) assert success == True assert 'clearedInvoice' in response ``` ### 3. Load Tests - Test concurrent invoice creation - Test batch submission performance - Test API rate limits --- ## 📱 User Interface Enhancements ### 1. Invoice Form **Add:** - Invoice type selector (Standard/Simplified) - QR code preview - ZATCA submission status indicator - Retry button for failed submissions ### 2. Invoice Detail Page **Add:** - QR code display (scannable) - ZATCA submission history - XML download button - PDF download button - Clearance/Reporting status badge ### 3. Compliance Dashboard **Add:** - Submission success rate chart - Failed invoices list - CSID status widget - Compliance alerts --- ## 🌐 Arabic Language Implementation ### Required Changes: 1. **Invoice Templates** ```html

فاتورة ضريبية

رقم الفاتورة: {{ invoice.invoice_number }}

``` 2. **Model Fields** ```python # Add Arabic fields seller_name_ar = models.CharField(max_length=200) buyer_name_ar = models.CharField(max_length=200) line_item_description_ar = models.CharField(max_length=500) ``` 3. **XML Generation** ```python # Include Arabic text in XML name_elem.text = invoice.tenant.name_ar or invoice.tenant.name ``` --- ## 🔄 Workflow Improvements ### 1. Automated Clearance for Standard Invoices ```python # In finance/signals.py @receiver(post_save, sender=Invoice) def auto_submit_standard_invoice(sender, instance, created, **kwargs): """Auto-submit standard invoices for clearance.""" if created and instance.invoice_type == 'STANDARD': # Submit for clearance immediately submit_invoice_to_zatca.delay(str(instance.id)) ``` ### 2. Scheduled Reporting for Simplified Invoices ```python # In AgdarCentre/celery.py from celery.schedules import crontab app.conf.beat_schedule = { 'auto-submit-simplified-invoices': { 'task': 'finance.zatca_tasks.auto_submit_simplified_invoices', 'schedule': crontab(minute='*/30'), # Every 30 minutes }, 'check-csid-expiry': { 'task': 'finance.zatca_tasks.check_csid_expiry', 'schedule': crontab(hour=9, minute=0), # Daily at 9 AM }, } ``` --- ## 📦 Required Dependencies Add to requirements.txt: ``` # ZATCA E-Invoice cryptography>=41.0.0 ecdsa>=0.18.0 requests>=2.31.0 qrcode>=7.4.2 Pillow>=10.0.0 reportlab>=4.0.0 PyPDF2>=3.0.0 lxml>=4.9.0 # For better XML handling ``` --- ## 🚀 Deployment Checklist ### Before Production: - [ ] Obtain production CSID from ZATCA - [ ] Configure production API endpoints - [ ] Set up secure key storage - [ ] Enable SSL/TLS - [ ] Configure backup system - [ ] Set up monitoring and alerts - [ ] Train staff on new features - [ ] Create user documentation - [ ] Perform load testing - [ ] Complete security audit ### Environment Variables: ```bash # .env ZATCA_USE_SANDBOX=False ZATCA_CSID=your-production-csid ZATCA_SECRET=your-production-secret ZATCA_VAT_NUMBER=300000000000003 ENCRYPTION_KEY=your-encryption-key ``` --- ## 📞 Support & Resources ### ZATCA Resources: - Developer Portal: https://sandbox.zatca.gov.sa/ - Documentation: https://zatca.gov.sa/en/E-Invoicing/ - Support Email: info@zatca.gov.sa - Phone: 19993 (Local), +966112048998 (International) ### Technical Support: - SDK Download: https://zatca.gov.sa/en/E-Invoicing/SystemsDevelopers/ - API Documentation: Available on Developer Portal - Compliance Toolbox: Web-based validator available --- ## 🎯 Success Metrics ### Key Performance Indicators: 1. **Compliance Rate:** >99% of invoices successfully submitted 2. **Submission Time:** <2 seconds average 3. **Error Rate:** <1% of submissions 4. **CSID Uptime:** 100% (no expired CSIDs) 5. **Sequence Integrity:** 0 gaps in invoice counter ### Monthly Review: - Review failed submissions - Analyze error patterns - Update error handling - Optimize performance - Train staff on issues --- ## 📝 Next Steps ### Immediate Actions: 1. Add `vat_number` field to Tenant model 2. Implement ECDSA signing 3. Move counter logic to model save 4. Create basic test suite ### This Week: 5. Test in ZATCA sandbox 6. Implement error handling 7. Add UI enhancements 8. Create user documentation ### This Month: 9. Implement PDF/A-3 generation 10. Add Arabic language support 11. Complete onboarding flow 12. Prepare for production --- **Document Version:** 1.0 **Last Updated:** October 27, 2025 **Status:** Implementation Complete - Enhancements Recommended