Luxembourg VAT Declarations (eCDF)
Generate Luxembourg quarterly VAT declarations (TVA_DECT) in eCDF XML format for AED submission.
Quick Start
-
Copy the example config:
cp vat_config.example.json vat_config.json -
Edit
vat_config.jsonwith your company details:MatrNbr: Your matricule numberRCSNbr: Your RCS numberVATNbr: Your VAT numbereCDFPrefix: Your eCDF prefix
-
Prepare your CSV file with expenses (see
example_csv_format.md) -
Run the generator:
python3 generate_vat_declarations.py
Files
generate_vat_declarations.py- Main scriptvat_config.example.json- Configuration templateexample_csv_format.md- CSV format documentationFIELD_FORMULAS.md- eCDF field formulas reference
Critical Lessons Learned
⚠️ CRITICAL: This skill documents hard-learned lessons from fixing VAT declaration errors. Read completely before generating XML.
Overview
Generate Luxembourg quarterly VAT declarations (TVA_DECT) in eCDF XML format for AED submission. Based on painful real-world debugging of validation errors.
Critical Lessons Learned (READ FIRST)
1. Field Order is CRITICAL
The eCDF validator checks exact field sequence, not just presence. One field out of order = rejection.
Correct Order:
Numeric 012-105 → Choice 204/205/491/492/493 → Numeric 403/418/453 → Numeric 042/416/417/451/452
Common Mistake:
<!-- WRONG - 042 at wrong position -->
<NumericField id="042">0,00</NumericField>
<Choice id="204">1</Choice>
<!-- CORRECT -->
<Choice id="204">1</Choice>
<Choice id="205">0</Choice>
<Choice id="491">0</Choice>
<Choice id="492">0</Choice>
<Choice id="493">0</Choice>
<NumericField id="403">0</NumericField>
<NumericField id="418">0</NumericField>
<NumericField id="453">0</NumericField>
<NumericField id="042">0,00</NumericField>
<NumericField id="416">0,00</NumericField>
<NumericField id="417">0,00</NumericField>
<NumericField id="451">0,00</NumericField>
<NumericField id="452">0,00</NumericField>
2. Fields 491/492/493 - Year Dependent
⚠️ Important: These fields may or may not be required depending on the declaration year:
For 2024 declarations: Only 204 and 205 are needed
<Choice id="204">1</Choice>
<Choice id="205">0</Choice>
For 2025+ declarations: All 5 Choice fields may be required
<Choice id="204">1</Choice>
<Choice id="205">0</Choice>
<Choice id="491">0</Choice>
<Choice id="492">0</Choice>
<Choice id="493">0</Choice>
Error if wrong: "Les champs suivants ne sont pas autorisés, ou mal placés: 491, 492, 493"
Solution: Try without 491/492/493 first. If you get this error, add them.
3. Rounding is a Trap
The validator adds rounded XML values to check formulas, not raw float values.
Example of failure:
462 = 3.513900 → XML shows "3,51"
464 = 11.281427 → XML shows "11,28"
Validator computes: 3,51 + 11,28 = 14,79
But if you calculate from unrounded:
410 = 3.513900 + 11.281427 = 14.795327 → XML shows "14,80"
14,80 ≠ 14,79 → VALIDATION ERROR!
Solution: Calculate derived fields from already-rounded components:
field_410 = round(field_462, 2) + round(field_464, 2)
4. Formula Reference (eCDF Requirements)
| Field | Formula | Notes |
|---|---|---|
| 409 | 436 + 435 + 463 + 765 | Total services requiring reverse charge |
| 410 | 462 + 464 + 766 | Total VAT on services received |
| 076 | 046 + 056 + 407 + 410 + 768 + 227 | Total output VAT |
| 093 | 458 + 459 + 460 + 090 + 461 + 092 + 228 | Total input VAT |
| 461 | 464 + 462 + 766 | Deductible reverse charge |
| 463 | 751 + 951 + 753 + 953 + 755 + 955 + 441 + 445 | Non-EU base |
| 464 | 752 + 952 + 754 + 954 + 756 + 956 + 442 | Non-EU VAT |
5. Invoice Categorization Matters
Common mistake: Labeling coworking as "Rent - No VAT" when it's actually services with 17% VAT.
Real example:
- The Office City invoices said "Rent" but were actually "Coworking + Business Address"
- Difference: €59.13/month × 12 months = €709.56 in claimable VAT nearly lost!
Always verify actual VAT amount on PDF, don't rely on description.
Usage
Quick Start
# See generate_vat_declarations.py for full implementation
python3 generate_vat_declarations.py
Required Files
-
CSV file with columns:
- Quarter, Provider, Total Amount (EUR), VAT Rate, VAT Amount, Net Amount, Currency, Notes
-
Company config (vat_config.json):
{
"company": {
"MatrNbr": "YOUR_MATRICULE_NUMBER",
"RCSNbr": "YOUR_RCS_NUMBER",
"VATNbr": "YOUR_VAT_NUMBER",
"eCDFPrefix": "YOUR_ECDF_PREFIX"
}
}
VAT Categories
| Provider Type | Fields | Treatment |
|---|---|---|
| Luxembourg suppliers | 458 | Direct VAT deduction |
| Non-EU services (USA) | 751/752/463/464/461 | Reverse charge at 17% |
| EU services (France, etc) | 741/742/436/462/461 | Reverse charge at 17% |
Validation Checklist
Before submitting, verify:
- All 5 Choice fields present (204, 205, 491, 492, 493)
- Choice fields in correct position (after 105, before 403)
- Fields 042/416/417/451/452 at very end
- Fields 403/418/453 as integers ("0" not "0,00")
- Formulas validate with rounded values
- No negative values where not expected
- Exchange rates applied for USD invoices
Error Messages Decoded
| Error | Meaning | Fix |
|---|---|---|
| "Champs 491, 492, 493 non autorisés ou mal placés" | Choice fields missing/wrong position | Add all 5 Choice fields in correct order |
| "Champ 409 = champs (436 + 435 + 463 + 765)" | Formula error for field 409 | Calculate from rounded components |
| "Champ 410 = champs (462 + 464 + 766)" | Formula error for field 410 | Calculate from rounded components |
| "Champ 076 = champs (046 + 056 + 407 + 410 + 768 + 227)" | Formula error for field 076 | Set 076 = 410 for expense-only declarations |
Files in This Skill
generate_vat_declarations.py- Working script with all fixesvat_config.json- Company configuration templateexample_csv_format.md- CSV column requirements
Real-World Debugging Tips
- Test one quarter first - Don't generate all 4 until one passes
- Check exact error message - It tells you which field and expected formula
- Compare with working reference - Line-by-line diff of XML structure
- Watch for floating point - Python float math can cause 0.01 rounding errors
- Verify invoice PDFs - Don't trust descriptions, check actual VAT amounts
Generated With
- Date: 2024-01-29
- Tested: Successfully validated all 4 quarters 2024
- Total VAT recovered: €1,154.29 (was €372.85 before fixes)
