mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-04-02 14:24:27 -04:00
Implementation of UBL 2.1 invoice generation to comply with Belgium's 2026 Peppol mandate. Key changes: - Add num-num/ubl-invoice dependency via composer.json - Create Ubl_generator library to convert OSPOS sale data to UBL format - Create country_helper.php to map country names to ISO 3166-1 alpha-2 codes - Extend Email_lib to support multiple attachments for PDF+UBL emails - Add getUblInvoice() method in Sales controller for UBL download - Modify getSendPdf() to optionally attach UBL based on invoice_format config - Add database migration for invoice_format configuration (pdf_only/ubl_only/both) - Add UBL download button to invoice view - Add UBL download link to sales manage table - Add language keys for UBL-related UI elements Data mapping: - Company name/address -> Supplier Party - account_number -> Company VAT number - Customer address/country -> Customer Party with ISO country code - Customer tax_id -> Customer VAT number - Cart items -> InvoiceLines - Taxes -> TaxCategory and TaxTotal - Totals -> LegalMonetaryTotal Features: - Generate valid UBL 2.1 XML invoices - Download UBL from invoice view and manage table - Email with PDF, UBL, or both based on configuration - Support for multiple customer countries with ISO code mapping - Graceful handling of missing optional customer fields
75 lines
1.9 KiB
PHP
75 lines
1.9 KiB
PHP
<?php
|
|
|
|
namespace App\Libraries\InvoiceAttachment;
|
|
|
|
class InvoiceAttachmentGenerator
|
|
{
|
|
/** @var InvoiceAttachment[] */
|
|
private array $attachments = [];
|
|
|
|
/**
|
|
* Register an attachment generator.
|
|
*/
|
|
public function register(InvoiceAttachment $attachment): self
|
|
{
|
|
$this->attachments[] = $attachment;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Create generator with attachments based on config.
|
|
* Factory method that instantiates the right attachments.
|
|
*
|
|
* @param string $invoiceFormat Config value: 'pdf_only', 'ubl_only', or 'both'
|
|
* @return self
|
|
*/
|
|
public static function createFromConfig(string $invoiceFormat): self
|
|
{
|
|
$generator = new self();
|
|
|
|
if (in_array($invoiceFormat, ['pdf_only', 'both'], true)) {
|
|
$generator->register(new PdfAttachment());
|
|
}
|
|
|
|
if (in_array($invoiceFormat, ['ubl_only', 'both'], true)) {
|
|
$generator->register(new UblAttachment());
|
|
}
|
|
|
|
return $generator;
|
|
}
|
|
|
|
/**
|
|
* Generate all applicable attachments for a sale.
|
|
*
|
|
* @param array $saleData The sale data
|
|
* @param string $type The document type
|
|
* @return string[] Array of file paths to generated attachments
|
|
*/
|
|
public function generateAttachments(array $saleData, string $type): array
|
|
{
|
|
$files = [];
|
|
|
|
foreach ($this->attachments as $attachment) {
|
|
if ($attachment->isApplicableForType($type, $saleData)) {
|
|
$filepath = $attachment->generate($saleData, $type);
|
|
if ($filepath !== null) {
|
|
$files[] = $filepath;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $files;
|
|
}
|
|
|
|
/**
|
|
* Clean up temporary attachment files.
|
|
*
|
|
* @param string[] $files
|
|
*/
|
|
public static function cleanup(array $files): void
|
|
{
|
|
foreach ($files as $file) {
|
|
@unlink($file);
|
|
}
|
|
}
|
|
} |