generateZATCAXml static method
Generate a ZATCA-compliant XML string for the invoice data.
Implementation
static XmlDocument generateZATCAXml(BaseInvoice invoice, Supplier supplier) {
final builder = XmlBuilder();
final formatter = NumberFormat("#.##");
builder.processing('xml', 'version="1.0" encoding="UTF-8"');
builder.element(
'Invoice',
nest: () {
builder.attribute(
'xmlns',
'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2',
);
builder.attribute(
'xmlns:cac',
'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
);
builder.attribute(
'xmlns:cbc',
'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
);
builder.attribute(
'xmlns:ext',
'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2',
);
builder.element('cbc:ProfileID', nest: invoice.profileID);
builder.element('cbc:ID', nest: invoice.invoiceNumber);
builder.element('cbc:UUID', nest: invoice.uuid);
builder.element('cbc:IssueDate', nest: invoice.issueDate);
builder.element('cbc:IssueTime', nest: invoice.issueTime);
builder.element(
'cbc:InvoiceTypeCode',
nest: () {
builder.attribute(
'name',
invoice.invoiceType.invoiceRelationType.value,
);
builder.text(invoice.invoiceType.code);
},
);
// builder.element(
// 'cbc:Note',
// nest: () {
// builder.attribute('languageID', 'ar');
// builder.text(data.note);
// },
// );
builder.element('cbc:DocumentCurrencyCode', nest: invoice.currencyCode);
builder.element('cbc:TaxCurrencyCode', nest: invoice.taxCurrencyCode);
if (invoice is DBInvoice) {
builder.element(
'cac:BillingReference',
nest: () {
builder.element(
'cac:InvoiceDocumentReference',
nest: () {
builder.element(
'cbc:ID',
nest: () {
builder.text(
invoice.cancellation.canceledSerialInvoiceNumber,
);
},
);
},
);
},
);
}
builder.element(
'cac:AdditionalDocumentReference',
nest: () {
builder.element('cbc:ID', nest: 'ICV');
builder.element('cbc:UUID', nest: '1');
},
);
builder.element(
'cac:AdditionalDocumentReference',
nest: () {
builder.element('cbc:ID', nest: 'PIH');
builder.element(
'cac:Attachment',
nest: () {
builder.element(
'cbc:EmbeddedDocumentBinaryObject',
nest: invoice.previousInvoiceHash,
attributes: {'mimeCode': 'text/plain'},
);
},
);
},
);
// Supplier
builder.element(
'cac:AccountingSupplierParty',
nest: () {
builder.element(
'cac:Party',
nest: () {
builder.element(
'cac:PartyIdentification',
nest: () {
builder.element(
'cbc:ID',
nest: () {
builder.attribute('schemeID', 'CRN');
builder.text(supplier.companyCRN);
},
);
},
);
builder.element(
'cac:PostalAddress',
nest: () {
builder.element(
'cbc:StreetName',
nest: supplier.location.street,
);
builder.element(
'cbc:BuildingNumber',
nest: supplier.location.building,
);
builder.element(
'cbc:PlotIdentification',
nest: supplier.location.plotIdentification,
);
builder.element(
'cbc:CitySubdivisionName',
nest: supplier.location.citySubdivision,
);
builder.element(
'cbc:CityName',
nest: supplier.location.city,
);
builder.element(
'cbc:PostalZone',
nest: supplier.location.postalZone,
);
builder.element(
'cac:Country',
nest: () {
builder.element(
'cbc:IdentificationCode',
nest: supplier.location.countryCode,
);
},
);
},
);
builder.element(
'cac:PartyTaxScheme',
nest: () {
builder.element('cbc:CompanyID', nest: supplier.companyID);
builder.element(
'cac:TaxScheme',
nest: () {
builder.element('cbc:ID', nest: 'VAT');
},
);
},
);
builder.element(
'cac:PartyLegalEntity',
nest: () {
builder.element(
'cbc:RegistrationName',
nest: supplier.registrationName,
);
},
);
},
);
},
);
// Customer
builder.element(
'cac:AccountingCustomerParty',
nest: () {
builder.element(
'cac:Party',
nest: () {
builder.element(
'cac:PartyIdentification',
nest: () {
builder.element(
'cbc:ID',
nest: () {
builder.attribute('schemeID', 'CRN');
builder.text('');
},
);
},
);
builder.element(
'cac:PostalAddress',
nest: () {
builder.element(
'cbc:StreetName',
nest: invoice.customer!.address.street,
);
builder.element(
'cbc:BuildingNumber',
nest: invoice.customer!.address.building,
);
builder.element(
'cbc:CitySubdivisionName',
nest: invoice.customer!.address.citySubdivision,
);
builder.element(
'cbc:CityName',
nest: invoice.customer!.address.city,
);
builder.element(
'cbc:PostalZone',
nest: invoice.customer!.address.postalZone,
);
builder.element(
'cac:Country',
nest: () {
builder.element(
'cbc:IdentificationCode',
nest: invoice.customer!.address.countryCode,
);
},
);
},
);
builder.element(
'cac:PartyTaxScheme',
nest: () {
builder.element(
'cbc:CompanyID',
nest: invoice.customer!.companyID,
);
builder.element(
'cac:TaxScheme',
nest: () {
builder.element('cbc:ID', nest: 'VAT');
},
);
},
);
builder.element(
'cac:PartyLegalEntity',
nest: () {
builder.element(
'cbc:RegistrationName',
nest: invoice.customer!.registrationName,
);
},
);
},
);
},
);
if (invoice is Invoice) {
builder.element(
'cac:Delivery',
nest: () {
builder.element(
'cbc:ActualDeliveryDate',
nest: invoice.actualDeliveryDate,
);
},
);
}
if (invoice is DBInvoice) {
builder.element(
'cac:PaymentMeans',
nest: () {
builder.element(
'cbc:PaymentMeansCode',
nest: invoice.cancellation.paymentMethod.value,
);
builder.element(
'cbc:InstructionNote',
nest: invoice.cancellation.reason,
);
},
);
}
// Totals
builder.element(
'cac:TaxTotal',
nest: () {
builder.element(
'cbc:TaxAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(invoice.taxAmount.toStringAsFixed(2));
},
);
builder.element(
'cac:TaxSubtotal',
nest: () {
builder.element(
'cbc:TaxableAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(
formatter.format(invoice.totalAmount - invoice.taxAmount),
);
},
);
builder.element(
'cbc:TaxAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(formatter.format(invoice.taxAmount));
},
);
builder.element(
'cac:TaxCategory',
nest: () {
builder.element(
'cbc:ID',
nest: () {
builder.attribute('schemeAgencyID', '6');
builder.attribute('schemeID', 'UN/ECE 5305');
builder.text('S');
},
);
builder.element('cbc:Percent', nest: '15');
builder.element(
'cac:TaxScheme',
nest: () {
builder.element(
'cbc:ID',
nest: () {
builder.attribute('schemeAgencyID', '6');
builder.attribute('schemeID', 'UN/ECE 5153');
builder.text('VAT');
},
);
},
);
},
);
},
);
},
);
builder.element(
'cac:TaxTotal',
nest: () {
builder.element(
'cbc:TaxAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(invoice.taxAmount.toStringAsFixed(2));
},
);
},
);
builder.element(
'cac:LegalMonetaryTotal',
nest: () {
double taxableAmount = invoice.totalAmount - invoice.taxAmount;
builder.element(
'cbc:LineExtensionAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(taxableAmount.toStringAsFixed(2));
},
);
builder.element(
'cbc:TaxExclusiveAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(formatter.format(taxableAmount));
},
);
builder.element(
'cbc:TaxInclusiveAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(invoice.totalAmount.toStringAsFixed(2));
},
);
builder.element(
'cbc:PrepaidAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text('0');
},
);
builder.element(
'cbc:PayableAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(invoice.totalAmount.toStringAsFixed(2));
},
);
},
);
// Invoice Lines
for (var line in invoice.invoiceLines) {
builder.element(
'cac:InvoiceLine',
nest: () {
builder.element('cbc:ID', nest: line.id);
builder.element(
'cbc:InvoicedQuantity',
nest: () {
builder.attribute('unitCode', line.unitCode);
builder.text(line.quantity);
},
);
builder.element(
'cbc:LineExtensionAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(line.lineExtensionAmount.toStringAsFixed(2));
},
);
builder.element(
'cac:TaxTotal',
nest: () {
builder.element(
'cbc:TaxAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(line.taxAmount.toStringAsFixed(2));
},
);
double roundingAmount = line.roundingAmount;
builder.element(
'cbc:RoundingAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(roundingAmount.toStringAsFixed(2));
},
);
},
);
builder.element(
'cac:Item',
nest: () {
builder.element('cbc:Name', nest: line.itemName);
builder.element(
'cac:ClassifiedTaxCategory',
nest: () {
builder.element('cbc:ID', nest: 'S');
builder.element(
'cbc:Percent',
nest: formatter.format(line.taxPercent),
);
builder.element(
'cac:TaxScheme',
nest: () {
builder.element('cbc:ID', nest: 'VAT');
},
);
},
);
},
);
builder.element(
'cac:Price',
nest: () {
builder.element(
'cbc:PriceAmount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(
line.taxExclusiveDiscountAppliedPrice.toStringAsFixed(
14,
),
);
},
);
if (line.discounts.isNotEmpty) {
builder.element(
'cac:AllowanceCharge',
nest: () {
for (var discount in line.discounts) {
builder.element('cbc:ChargeIndicator', nest: 'false');
builder.element(
'cbc:AllowanceChargeReason',
nest: discount.reason,
);
builder.element(
'cbc:Amount',
nest: () {
builder.attribute('currencyID', 'SAR');
builder.text(discount.amount.toStringAsFixed(14));
},
);
/// Required when the discount is a percentage.
// builder.element(
// 'cbc:BaseAmount',
// nest: () {
// builder.attribute('currencyID', 'SAR');
// builder.text(line.taxExclusivePrice.toString());
// },
// );
}
},
);
}
},
);
},
);
}
},
);
/// Build the XML document
final document = builder.buildDocument();
return document;
}