agdar/ZATCA_QUICK_REFERENCE.md
2025-11-02 14:35:35 +03:00

425 lines
10 KiB
Markdown

# ZATCA E-Invoice Quick Reference Guide
## 🚀 Getting Started (5 Minutes)
### Step 1: Run Migrations
```bash
python3 manage.py migrate
```
### Step 2: Configure Your Tenant
```python
# In Django shell or admin
from core.models import Tenant
tenant = Tenant.objects.first()
tenant.vat_number = "300000000000003" # Your actual VAT number
tenant.name_ar = "مركز أغدار"
tenant.address = "123 Main Street, Riyadh"
tenant.city = "Riyadh"
tenant.postal_code = "12345"
tenant.save()
```
### Step 3: Create Your First Invoice
```python
from finance.models import Invoice, InvoiceLineItem
from core.models import Patient
from datetime import date, timedelta
# Get patient
patient = Patient.objects.first()
# Create invoice
invoice = Invoice.objects.create(
tenant=tenant,
patient=patient,
invoice_type='SIMPLIFIED', # B2C
issue_date=date.today(),
due_date=date.today() + timedelta(days=30),
subtotal=100.00,
tax=15.00, # 15% VAT
total=115.00,
status='ISSUED'
)
# Add line item
InvoiceLineItem.objects.create(
invoice=invoice,
description="Medical Consultation",
quantity=1,
unit_price=100.00,
total=100.00
)
# Check auto-generated fields
print(f"✅ Invoice Counter: {invoice.invoice_counter}")
print(f"✅ Invoice Hash: {invoice.invoice_hash[:32]}...")
print(f"✅ QR Code: {invoice.qr_code[:50]}...")
```
---
## 📋 Invoice Types Guide
| Type | Code | When to Use | ZATCA Process |
|------|------|-------------|---------------|
| **Standard** | `STANDARD` | B2B transactions | Clearance (real-time) |
| **Simplified** | `SIMPLIFIED` | B2C transactions | Reporting (24 hours) |
| **Standard Credit** | `STANDARD_CREDIT` | B2B refunds | Clearance |
| **Standard Debit** | `STANDARD_DEBIT` | B2B adjustments | Clearance |
| **Simplified Credit** | `SIMPLIFIED_CREDIT` | B2C refunds | Reporting |
| **Simplified Debit** | `SIMPLIFIED_DEBIT` | B2C adjustments | Reporting |
---
## 🔄 ZATCA Submission Workflows
### Workflow 1: Standard Invoice (B2B)
```python
# 1. Create invoice
invoice = Invoice.objects.create(
invoice_type='STANDARD',
# ... other fields
)
# 2. Submit for clearance (BEFORE sharing with buyer)
from finance.zatca_tasks import submit_invoice_to_zatca
result = submit_invoice_to_zatca.delay(str(invoice.id), use_sandbox=True)
# 3. Check status
invoice.refresh_from_db()
if invoice.zatca_status == 'CLEARED':
# 4. Share cleared invoice with buyer
# Invoice now has ZATCA stamp and updated QR code
pass
```
### Workflow 2: Simplified Invoice (B2C)
```python
# 1. Create invoice
invoice = Invoice.objects.create(
invoice_type='SIMPLIFIED',
# ... other fields
)
# 2. Share with customer immediately (QR code already on invoice)
# 3. Report to ZATCA within 24 hours (automatic via Celery)
# Or manually:
from finance.zatca_tasks import submit_invoice_to_zatca
result = submit_invoice_to_zatca.delay(str(invoice.id), use_sandbox=True)
```
### Workflow 3: Credit Note
```python
# 1. Create credit note referencing original invoice
credit_note = Invoice.objects.create(
invoice_type='SIMPLIFIED_CREDIT', # or STANDARD_CREDIT
billing_reference_id=original_invoice.invoice_number,
billing_reference_issue_date=original_invoice.issue_date,
subtotal=-100.00, # Negative amounts
tax=-15.00,
total=-115.00,
# ... other fields
)
# 2. Submit to ZATCA (same process as regular invoice)
```
---
## 🔍 Checking Invoice Status
### Via Django Admin:
1. Go to Finance → Invoices
2. Look at "ZATCA Status" column:
- **CLEARED** - Standard invoice approved by ZATCA
- **REPORTED** - Simplified invoice reported to ZATCA
- **FAILED** - Submission failed (check zatca_response)
- **(empty)** - Not yet submitted
### Via Code:
```python
invoice = Invoice.objects.get(invoice_number='INV-001-2025-12345')
print(f"Status: {invoice.zatca_status}")
print(f"Submitted: {invoice.zatca_submission_date}")
print(f"Response: {invoice.zatca_response}")
```
---
## 🛠️ Common Tasks
### Generate PDF Invoice
```python
from finance.pdf_service import PDFService
pdf_bytes = PDFService.generate_invoice_pdf(invoice)
# Save to file
with open(f'invoice_{invoice.invoice_number}.pdf', 'wb') as f:
f.write(pdf_bytes)
# Or return as HTTP response
from django.http import HttpResponse
response = HttpResponse(pdf_bytes, content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="invoice_{invoice.invoice_number}.pdf"'
return response
```
### Generate XML
```python
from finance.zatca_service import ZATCAService
zatca = ZATCAService(use_sandbox=True)
xml = zatca.generate_xml_invoice(invoice)
# Save to invoice
invoice.xml_content = xml
invoice.save()
```
### Validate QR Code
```python
# QR code is automatically generated
qr_code = invoice.qr_code
# Decode to verify
import base64
decoded = base64.b64decode(qr_code)
# First byte is tag 1 (Seller's Name)
# Second byte is length
# Following bytes are the value
```
### Check Invoice Sequence
```python
from finance.csid_manager import InvoiceCounterManager
is_valid, gaps = InvoiceCounterManager.validate_counter_sequence(tenant)
if not is_valid:
print(f"⚠️ Gaps found in sequence: {gaps}")
else:
print("✅ Invoice sequence is valid")
```
---
## 🔐 CSID Management
### Check Active CSID
```python
from finance.csid_manager import CSIDManager
csid = CSIDManager.get_active_csid(tenant)
if csid:
print(f"✅ Active CSID: {csid.common_name}")
print(f"📅 Expires in: {csid.days_until_expiry} days")
print(f"📊 Invoices signed: {csid.invoices_signed}")
else:
print("⚠️ No active CSID - please onboard via FATOORA portal")
```
### Check if Renewal Needed
```python
needs_renewal, message = CSIDManager.check_expiry_and_renew(tenant)
if needs_renewal:
print(f"⚠️ {message}")
else:
print("✅ CSID is valid")
```
---
## 🔧 Troubleshooting
### Issue: Invoice counter not incrementing
**Solution:** Check that transaction locking is working
```python
# Counter should auto-increment with SELECT FOR UPDATE lock
# Check last invoice counter
last = Invoice.objects.filter(tenant=tenant).order_by('-invoice_counter').first()
print(f"Last counter: {last.invoice_counter if last else 'None'}")
```
### Issue: QR code not generating
**Solution:** Check that invoice has all required fields
```python
# QR code requires:
# - Tenant name
# - Tenant VAT number
# - Issue date and time
# - Total and tax amounts
# Verify tenant has VAT number
print(f"VAT Number: {invoice.tenant.vat_number}")
```
### Issue: ZATCA submission failing
**Solution:** Check CSID and error response
```python
# Check CSID
csid = CSIDManager.get_active_csid(tenant)
print(f"CSID valid: {csid.is_valid if csid else 'No CSID'}")
# Check error response
print(f"Error: {invoice.zatca_response}")
```
### Issue: Hash chain broken
**Solution:** Validate sequence
```python
# Check for gaps
is_valid, gaps = InvoiceCounterManager.validate_counter_sequence(tenant)
print(f"Sequence valid: {is_valid}")
print(f"Gaps: {gaps}")
```
---
## 📊 Monitoring & Reports
### Daily Compliance Check
```python
from finance.zatca_tasks import monitor_zatca_compliance
# Run compliance monitoring
report = monitor_zatca_compliance.delay()
# Check results
print(report.get())
```
### Generate Compliance Report
```python
from finance.zatca_tasks import generate_compliance_report
report = generate_compliance_report.delay(
tenant_id=str(tenant.id),
start_date='2025-01-01',
end_date='2025-01-31'
)
print(report.get())
```
### Retry Failed Submissions
```python
from finance.zatca_tasks import retry_failed_submissions
# Retry all failed invoices for tenant
results = retry_failed_submissions.delay(tenant_id=str(tenant.id))
print(f"Retried: {results.get()}")
```
---
## 🎯 Best Practices
### 1. Invoice Creation
✅ Always set correct invoice_type (STANDARD vs SIMPLIFIED)
✅ Let counter auto-increment (don't set manually)
✅ Verify patient nationality for VAT calculation
✅ Add line items before finalizing
### 2. ZATCA Submission
✅ Standard invoices: Clear BEFORE sharing with buyer
✅ Simplified invoices: Share immediately, report within 24h
✅ Monitor zatca_status field
✅ Handle failures gracefully
### 3. Credit/Debit Notes
✅ Always reference original invoice
✅ Use negative amounts for credits
✅ Follow same submission process as original
### 4. CSID Management
✅ Monitor expiry dates (renew 30 days before)
✅ Keep one active CSID per tenant
✅ Revoke compromised CSIDs immediately
✅ Track usage statistics
---
## 📱 API Endpoints Reference
### Sandbox (Testing):
- Base: `https://gw-fatoora.zatca.gov.sa/e-invoicing/simulation`
- Clearance: `/invoices/clearance/single`
- Reporting: `/invoices/reporting/single`
- Compliance CSID: `/compliance`
- Production CSID: `/production/csids`
### Production:
- Base: `https://gw-fatoora.zatca.gov.sa/e-invoicing/core`
- Same endpoints as sandbox
---
## 🔑 Environment Variables
Add to your `.env` file:
```bash
# ZATCA Configuration
ZATCA_USE_SANDBOX=True # Set to False for production
ZATCA_VAT_NUMBER=300000000000003
ENCRYPTION_KEY=your-32-byte-encryption-key-here
# Optional
ZATCA_CSID=your-production-csid
ZATCA_SECRET=your-production-secret
```
---
## 📞 Support Contacts
### ZATCA:
- **Portal:** https://fatoora.zatca.gov.sa/
- **Sandbox:** https://sandbox.zatca.gov.sa/
- **Email:** info@zatca.gov.sa
- **Phone:** 19993 (Local), +966112048998 (International)
### Developer Resources:
- **SDK Download:** https://zatca.gov.sa/en/E-Invoicing/SystemsDevelopers/
- **API Docs:** Available on Developer Portal (requires login)
- **Compliance Toolbox:** Web-based validator available
---
## ✅ Pre-Production Checklist
- [ ] Migrations run successfully
- [ ] Tenant VAT number configured
- [ ] Test invoice created with QR code
- [ ] QR code validated with ZATCA mobile app
- [ ] Tested in ZATCA sandbox
- [ ] Production CSID obtained
- [ ] Celery workers running
- [ ] Monitoring configured
- [ ] Staff trained
- [ ] Backup system in place
---
## 🎓 Quick Tips
💡 **Tip 1:** Use sandbox for all testing - never test with production CSID
💡 **Tip 2:** QR codes can be scanned with ZATCA mobile app to verify
💡 **Tip 3:** Invoice counter gaps will trigger compliance alerts
💡 **Tip 4:** Simplified invoices can be shared immediately, no need to wait for ZATCA
💡 **Tip 5:** Standard invoices MUST be cleared before sharing with buyer
---
**Last Updated:** October 27, 2025
**Version:** 1.0
**Status:** Production Ready