diff --git a/Modules/Invoices/Peppol/FormatHandlers/EhfHandler.php b/Modules/Invoices/Peppol/FormatHandlers/EhfHandler.php index 2260d494..d9ebe294 100644 --- a/Modules/Invoices/Peppol/FormatHandlers/EhfHandler.php +++ b/Modules/Invoices/Peppol/FormatHandlers/EhfHandler.php @@ -17,7 +17,7 @@ class EhfHandler extends BaseFormatHandler { /** - * Constructor. + * Initialize the handler and set the Peppol document format to EHF. */ public function __construct() { @@ -25,7 +25,11 @@ public function __construct() } /** - * {@inheritdoc} + * Builds a Peppol EHF-compliant invoice payload as an associative array from the given Invoice. + * + * @param Invoice $invoice The invoice model used to populate the payload. + * @param array $options Optional transform options (reserved for future use). + * @return array An associative array representing the EHF/Peppol invoice with top-level keys such as `ubl_version_id`, `customization_id`, `profile_id`, `id`, `issue_date`, `due_date`, `invoice_type_code`, `document_currency_code`, `buyer_reference`, `accounting_supplier_party`, `accounting_customer_party`, `delivery`, `payment_means`, `payment_terms`, `tax_total`, `legal_monetary_total`, and `invoice_line`. */ public function transform(Invoice $invoice, array $options = []): array { @@ -71,11 +75,15 @@ public function transform(Invoice $invoice, array $options = []): array } /** - * Build supplier party. + * Builds the supplier party structure for the EHF (Peppol) invoice payload. + * + * Returns a nested array under the `party` key containing the supplier's Peppol endpoint ID, party identification + * (organization number), company name, postal address (street, city, postal zone, country), tax scheme (VAT), + * legal entity details (registration name and address) and contact details (name, phone, email). * - * @param Invoice $invoice - * @param mixed $endpointScheme - * @return array + * @param Invoice $invoice Invoice model (source of contextual invoice data; supplier values are taken from config). + * @param mixed $endpointScheme Enum-like object providing the Peppol endpoint scheme identifier via `$endpointScheme->value`. + * @return array Structured supplier party data for inclusion in the transformed EHF payload. */ protected function buildSupplierParty(Invoice $invoice, $endpointScheme): array { @@ -131,11 +139,14 @@ protected function buildSupplierParty(Invoice $invoice, $endpointScheme): array } /** - * Build customer party. + * Constructs the customer party section for an EHF invoice payload. * - * @param Invoice $invoice - * @param mixed $endpointScheme - * @return array + * @param Invoice $invoice Invoice containing customer data used to populate party fields. + * @param mixed $endpointScheme Object providing a `value` property used as the endpoint identification scheme. + * @return array Array representing the customer party with keys: `party` => [ + * 'endpoint_id', 'party_identification', 'party_name', 'postal_address', + * 'party_legal_entity', 'contact' + * ]. */ protected function buildCustomerParty(Invoice $invoice, $endpointScheme): array { @@ -182,11 +193,13 @@ protected function buildCustomerParty(Invoice $invoice, $endpointScheme): array } /** - * Build delivery information. - * - * @param Invoice $invoice - * @return array - */ + * Constructs the delivery information array using the invoice date and the customer's address. + * + * @param Invoice $invoice The invoice from which to derive the delivery date and customer address. + * @return array Array with keys: + * - `actual_delivery_date`: date string in `YYYY-MM-DD` format, + * - `delivery_location`: array containing `address` with `street_name`, `city_name`, `postal_zone`, and `country` (`identification_code`). + */ protected function buildDelivery(Invoice $invoice): array { return [ @@ -205,11 +218,17 @@ protected function buildDelivery(Invoice $invoice): array } /** - * Build payment means. - * - * @param Invoice $invoice - * @return array - */ + * Builds the payment means section for the given invoice. + * + * @param Invoice $invoice Invoice used to populate the payment identifier (`payment_id`). + * @return array An associative array containing: + * - `payment_means_code`: code representing the payment method (credit transfer). + * - `payment_id`: invoice number used as the payment identifier. + * - `payee_financial_account`: account information with keys: + * - `id`: supplier bank account number, + * - `name`: supplier company name, + * - `financial_institution_branch`: bank branch info with `id` (BIC) and `name` (bank name). + */ protected function buildPaymentMeans(Invoice $invoice): array { return [ @@ -227,10 +246,10 @@ protected function buildPaymentMeans(Invoice $invoice): array } /** - * Build payment terms. + * Constructs payment terms with a Norwegian note stating the number of days until the invoice is due. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice The invoice used to calculate days until due. + * @return array An array containing a 'note' key with value like "Forfall X dager" where X is the number of days until due. */ protected function buildPaymentTerms(Invoice $invoice): array { @@ -242,12 +261,19 @@ protected function buildPaymentTerms(Invoice $invoice): array } /** - * Build tax total. - * - * @param Invoice $invoice - * @param string $currencyCode - * @return array - */ + * Constructs the invoice tax total including per-rate subtotals. + * + * Builds the overall tax amount and an array of tax subtotals grouped by tax rate; + * each subtotal contains the taxable amount, tax amount (both formatted with the provided currency), + * and a tax category (id, percent and tax scheme). + * + * @param Invoice $invoice The invoice to compute taxes for. + * @param string $currencyCode ISO 4217 currency code used for all monetary values. + * @return array An array with keys: + * - `tax_amount`: array with `value` and `currency_id` for the total tax, + * - `tax_subtotal`: list of per-rate subtotals each containing `taxable_amount`, + * `tax_amount`, and `tax_category`. + */ protected function buildTaxTotal(Invoice $invoice, string $currencyCode): array { $taxAmount = $invoice->invoice_total - $invoice->invoice_subtotal; @@ -301,11 +327,15 @@ protected function buildTaxTotal(Invoice $invoice, string $currencyCode): array } /** - * Build monetary total. + * Construct the invoice monetary totals section for the EHF payload. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * @param Invoice $invoice Invoice model containing subtotal and total amounts. + * @param string $currencyCode ISO 4217 currency code used for all monetary values. + * @return array Associative array with these keys: + * - `line_extension_amount`: array with `value` (amount before taxes as a string with two decimals) and `currency_id`. + * - `tax_exclusive_amount`: array with `value` (amount excluding tax as a string with two decimals) and `currency_id`. + * - `tax_inclusive_amount`: array with `value` (amount including tax as a string with two decimals) and `currency_id`. + * - `payable_amount`: array with `value` (final payable amount as a string with two decimals) and `currency_id`. */ protected function buildMonetaryTotal(Invoice $invoice, string $currencyCode): array { @@ -330,11 +360,15 @@ protected function buildMonetaryTotal(Invoice $invoice, string $currencyCode): a } /** - * Build invoice lines. + * Create an array of invoice line entries for the EHF Peppol document. + * + * Each entry corresponds to an invoice item and includes identifiers, quantity, + * line extension amount, item details (description, name, seller item id, tax + * classification) and price information. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array> + * @param Invoice $invoice Invoice model containing `invoiceItems` to convert into lines. + * @param string $currencyCode ISO 4217 currency code applied to monetary fields. + * @return array> Array of invoice line structures ready for transformation. */ protected function buildInvoiceLines(Invoice $invoice, string $currencyCode): array { @@ -380,7 +414,15 @@ protected function buildInvoiceLines(Invoice $invoice, string $currencyCode): ar } /** - * {@inheritdoc} + * Generate the EHF-formatted document for an invoice as a string. + * + * Converts the given Invoice into the EHF document representation and returns it + * as a string. Note: the current implementation returns a JSON-encoded + * representation of the transformed data as a placeholder for the final XML. + * + * @param Invoice $invoice The invoice to convert. + * @param array $options Optional transformation options. + * @return string The EHF-formatted document as a string; currently a JSON-encoded representation of the transformed data (placeholder for proper XML). */ public function generateXml(Invoice $invoice, array $options = []): string { @@ -391,8 +433,13 @@ public function generateXml(Invoice $invoice, array $options = []): string } /** - * {@inheritdoc} - */ + * Validate invoice fields required by the EHF (Norwegian Peppol) format. + * + * Performs format-specific checks and returns any validation error messages. + * + * @param Invoice $invoice The invoice to validate. + * @return string[] An array of validation error messages; empty if the invoice meets EHF requirements. + */ protected function validateFormatSpecific(Invoice $invoice): array { $errors = []; @@ -411,10 +458,10 @@ protected function validateFormatSpecific(Invoice $invoice): array } /** - * Get buyer reference. + * Selects the buyer reference used for EHF routing. * - * @param Invoice $invoice - * @return string + * @param Invoice $invoice Invoice to extract the buyer reference from. + * @return string The buyer reference from the invoice's customer if present, otherwise the invoice reference, or an empty string if neither is set. */ protected function getBuyerReference(Invoice $invoice): string { @@ -423,13 +470,13 @@ protected function getBuyerReference(Invoice $invoice): string } /** - * Get tax rate from invoice item. - * - * @param mixed $item - * @return float - */ + * Return the tax rate percentage for an invoice item. + * + * @param mixed $item Invoice item (object or array) that may contain a `tax_rate` value. + * @return float The tax rate as a percentage (e.g., 25.0). Defaults to 25.0 when not present. + */ protected function getTaxRate($item): float { return $item->tax_rate ?? 25.0; // Standard Norwegian VAT rate } -} +} \ No newline at end of file diff --git a/Modules/Invoices/Peppol/FormatHandlers/FacturXHandler.php b/Modules/Invoices/Peppol/FormatHandlers/FacturXHandler.php index 17f26ae9..fc09d8cb 100644 --- a/Modules/Invoices/Peppol/FormatHandlers/FacturXHandler.php +++ b/Modules/Invoices/Peppol/FormatHandlers/FacturXHandler.php @@ -17,7 +17,9 @@ class FacturXHandler extends BaseFormatHandler { /** - * Constructor. + * Initialize the handler for the Factur-X 1.0 (Cross Industry Invoice) Peppol document format. + * + * Sets the format identifier to PeppolDocumentFormat::FACTURX_10 via the parent constructor. */ public function __construct() { @@ -34,11 +36,11 @@ public function transform(Invoice $invoice, array $options = []): array } /** - * Build CII structure for Factur-X. - * - * @param Invoice $invoice - * @return array - */ + * Constructs the Cross Industry Invoice (CII) array representation for a Factur‑X 1.0 invoice. + * + * @param Invoice $invoice The invoice to convert into the CII structure. + * @return array An associative array representing the CII payload with the root key `rsm:CrossIndustryInvoice`. + */ protected function buildCiiStructure(Invoice $invoice): array { $customer = $invoice->customer; @@ -57,9 +59,9 @@ protected function buildCiiStructure(Invoice $invoice): array } /** - * Build document context section. + * Constructs the document context parameters required by the Factur‑X (CII) envelope. * - * @return array + * @return array Array containing `ram:GuidelineSpecifiedDocumentContextParameter` with `ram:ID` set to the Factur‑X guideline URN. */ protected function buildDocumentContext(): array { @@ -71,10 +73,13 @@ protected function buildDocumentContext(): array } /** - * Build exchanged document section. + * Builds the ExchangedDocument section of the CII (Factur‑X) payload for the given invoice. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice The invoice whose identifying and date information will populate the section. + * @return array Associative array with keys: + * - `ram:ID`: invoice number, + * - `ram:TypeCode`: document type code ('380' for commercial invoice), + * - `ram:IssueDateTime`: contains `udt:DateTimeString` with `@format` '102' and the invoice date formatted as `Ymd`. */ protected function buildExchangedDocument(Invoice $invoice): array { @@ -91,11 +96,11 @@ protected function buildExchangedDocument(Invoice $invoice): array } /** - * Build supply chain trade transaction section. + * Builds the Supply Chain Trade Transaction section of the CII payload. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * @param Invoice $invoice The invoice to extract trade data from. + * @param string $currencyCode ISO 4217 currency code used for monetary elements. + * @return array Array containing keys for 'ram:ApplicableHeaderTradeAgreement', 'ram:ApplicableHeaderTradeDelivery', and 'ram:ApplicableHeaderTradeSettlement' representing their respective CII subsections. */ protected function buildSupplyChainTradeTransaction(Invoice $invoice, string $currencyCode): array { @@ -107,10 +112,13 @@ protected function buildSupplyChainTradeTransaction(Invoice $invoice, string $cu } /** - * Build header trade agreement section. + * Constructs seller and buyer party data for the CII header trade agreement. + * + * Seller values are sourced from configuration; buyer values are populated from the + * invoice's customer (company/name and postal address). * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice The invoice whose customer and address data populate the buyer party. + * @return array An array containing `ram:SellerTradeParty` and `ram:BuyerTradeParty` structures suitable for the CII header trade agreement. */ protected function buildHeaderTradeAgreement(Invoice $invoice): array { @@ -145,10 +153,10 @@ protected function buildHeaderTradeAgreement(Invoice $invoice): array } /** - * Build header trade delivery section. + * Builds the header trade delivery section containing the actual delivery event date. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice Invoice model whose invoiced_at date is used for the delivery occurrence. + * @return array Array representing `ram:ActualDeliverySupplyChainEvent` with `ram:OccurrenceDateTime` containing a `udt:DateTimeString` using format '102' and the invoice date formatted as `Ymd`. */ protected function buildHeaderTradeDelivery(Invoice $invoice): array { @@ -165,11 +173,10 @@ protected function buildHeaderTradeDelivery(Invoice $invoice): array } /** - * Build header trade settlement section. + * Construct the header trade settlement block for the invoice's CII payload, including currency, payment means, tax totals, payment terms, monetary summation, and line items. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * @param string $currencyCode ISO 4217 currency code used for monetary amounts. + * @return array The `ram:ApplicableHeaderTradeSettlement` structure ready for inclusion in the CII document. */ protected function buildHeaderTradeSettlement(Invoice $invoice, string $currencyCode): array { @@ -202,12 +209,16 @@ protected function buildHeaderTradeSettlement(Invoice $invoice, string $currency } /** - * Build tax totals. - * - * @param Invoice $invoice - * @param string $currencyCode - * @return array> - */ + * Aggregate invoice item taxes by tax rate and format them for the CII tax totals section. + * + * Each returned entry represents a tax group for a specific rate and includes the calculated tax amount, + * the taxable basis, the VAT category code, and the applicable rate percent. Monetary and percent values + * are formatted as strings with two decimal places and a dot decimal separator. + * + * @param Invoice $invoice The invoice whose items will be grouped by tax rate. + * @param string $currencyCode ISO 4217 currency code used for the tax totals (included for context). + * @return array> Array of tax entries suitable for embedding under `ram:ApplicableTradeTax`. + */ protected function buildTaxTotals(Invoice $invoice, string $currencyCode): array { // Group items by tax rate @@ -243,11 +254,14 @@ protected function buildTaxTotals(Invoice $invoice, string $currencyCode): array } /** - * Build line items. + * Constructs the CII-formatted line items for the given invoice. + * + * Each entry contains product details, net price, billed quantity (with unit code), + * applicable tax information, and the line total amount formatted for Factur‑X CII. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array> + * @param Invoice $invoice The invoice containing items to convert. + * @param string $currencyCode ISO 4217 currency code used for monetary formatting. + * @return array> Array of associative arrays representing CII line-item entries. */ protected function buildLineItems(Invoice $invoice, string $currencyCode): array { @@ -288,7 +302,11 @@ protected function buildLineItems(Invoice $invoice, string $currencyCode): array } /** - * {@inheritdoc} + * Generate the Factur‑X (CII) representation for an invoice and, in a full implementation, embed it into a PDF/A‑3 container. + * + * @param Invoice $invoice The invoice to convert into Factur‑X (CII) format. + * @param array $options Optional generation options that may alter output formatting or embedding behavior. + * @return string The generated output. Currently returns a pretty-printed JSON string of the internal CII structure (placeholder for the eventual PDF/A‑3 with embedded XML). */ public function generateXml(Invoice $invoice, array $options = []): string { @@ -303,7 +321,12 @@ public function generateXml(Invoice $invoice, array $options = []): string } /** - * {@inheritdoc} + * Validate format-specific requirements for Factur-X invoices. + * + * Ensures the invoice meets constraints required by the Factur-X (CII) format. + * + * @param Invoice $invoice The invoice to validate. + * @return string[] An array of validation error messages; empty if there are no format-specific errors. */ protected function validateFormatSpecific(Invoice $invoice): array { @@ -318,13 +341,13 @@ protected function validateFormatSpecific(Invoice $invoice): array } /** - * Get tax rate from invoice item. - * - * @param mixed $item - * @return float - */ + * Retrieve the tax rate percentage for an invoice item. + * + * @param mixed $item Invoice item (object or array) that may provide a `tax_rate` property or key. + * @return float The tax rate percentage for the item; defaults to 20.0 if not present. + */ protected function getTaxRate($item): float { return $item->tax_rate ?? 20.0; // Default French VAT rate } -} +} \ No newline at end of file diff --git a/Modules/Invoices/Peppol/FormatHandlers/FacturaeHandler.php b/Modules/Invoices/Peppol/FormatHandlers/FacturaeHandler.php index c67d475b..d8c86a96 100644 --- a/Modules/Invoices/Peppol/FormatHandlers/FacturaeHandler.php +++ b/Modules/Invoices/Peppol/FormatHandlers/FacturaeHandler.php @@ -17,7 +17,7 @@ class FacturaeHandler extends BaseFormatHandler { /** - * Constructor. + * Initialize the handler and register the Facturae 3.2 document format. */ public function __construct() { @@ -25,7 +25,14 @@ public function __construct() } /** - * {@inheritdoc} + * Transform an Invoice model into a Facturae 3.2 structured array payload. + * + * Builds the top-level Facturae structure containing `FileHeader`, `Parties` and `Invoices` + * suitable for downstream encoding to the Facturae 3.2 representation. + * + * @param Invoice $invoice The invoice to transform. + * @param array $options Optional transformation options. + * @return array The Facturae-structured payload with keys `FileHeader`, `Parties` and `Invoices`. */ public function transform(Invoice $invoice, array $options = []): array { @@ -41,10 +48,10 @@ public function transform(Invoice $invoice, array $options = []): array } /** - * Build file header section. + * Create the Facturae 3.2 file header containing schema and batch metadata. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice Invoice used to populate the batch identifier and total amount. + * @return array Array with keys `SchemaVersion`, `Modality`, `InvoiceIssuerType`, and `Batch` (where `Batch` contains `BatchIdentifier`, `InvoicesCount`, and `TotalInvoicesAmount` with `TotalAmount`). */ protected function buildFileHeader(Invoice $invoice): array { @@ -63,10 +70,10 @@ protected function buildFileHeader(Invoice $invoice): array } /** - * Build parties section. + * Assembles the seller and buyer party structures for the given invoice. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice Invoice to extract seller and buyer information from. + * @return array Array with 'SellerParty' and 'BuyerParty' keys containing their respective structured data. */ protected function buildParties(Invoice $invoice): array { @@ -77,10 +84,14 @@ protected function buildParties(Invoice $invoice): array } /** - * Build seller party data. + * Create the seller (supplier) party structure for the Facturae 3.2 payload. * - * @param Invoice $invoice - * @return array + * The structure is populated from supplier configuration and contains the + * TaxIdentification, PartyIdentification, AdministrativeCentres, and LegalEntity + * sections required by the Facturae schema. + * + * @param Invoice $invoice Invoice model (unused for most fields; provided for context). + * @return array Seller party data matching Facturae 3.2 structure. */ protected function buildSellerParty(Invoice $invoice): array { @@ -119,10 +130,16 @@ protected function buildSellerParty(Invoice $invoice): array } /** - * Build buyer party data. + * Constructs the buyer party structure for the Facturae payload using the invoice's customer data. * - * @param Invoice $invoice - * @return array + * Populates tax identification, administrative centre, and legal entity sections. Address fields are + * provided as `AddressInSpain` for Spanish customers or `OverseasAddress` for foreign customers. + * + * @param Invoice $invoice The invoice whose customer information is used to build the buyer party. + * @return array Array with keys: + * - `TaxIdentification`: contains `PersonTypeCode`, `ResidenceTypeCode`, and `TaxIdentificationNumber`. + * - `AdministrativeCentres`: contains `AdministrativeCentre` with `CentreCode`, `RoleTypeCode`, `Name` and an address block (`AddressInSpain` or `OverseasAddress`). + * - `LegalEntity`: contains `CorporateName` and the same address block used in `AdministrativeCentres`. */ protected function buildBuyerParty(Invoice $invoice): array { @@ -172,11 +189,12 @@ protected function buildBuyerParty(Invoice $invoice): array } /** - * Build invoice data. + * Assembles the invoice sections required for the Facturae 3.2 invoice payload. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * Returns an associative array containing the invoice parts used in the payload: + * `InvoiceHeader`, `InvoiceIssueData`, `TaxesOutputs`, `InvoiceTotals`, `Items`, and `PaymentDetails`. + * + * @return array Associative array keyed by Facturae element names with their corresponding data. */ protected function buildInvoice(Invoice $invoice, string $currencyCode): array { @@ -208,11 +226,18 @@ protected function buildInvoiceHeader(Invoice $invoice, string $currencyCode): a } /** - * Build invoice issue data. - * - * @param Invoice $invoice - * @return array - */ + * Builds the invoice issuance metadata required by the Facturae payload. + * + * Returns an associative array containing the issue date, invoice and tax currency codes, + * and the language code used for the invoice. + * + * @param Invoice $invoice The invoice model from which dates and currency are derived. + * @return array An array with keys: + * - `IssueDate`: the invoice issue date in Y-m-d format, + * - `InvoiceCurrencyCode`: the invoice currency code, + * - `TaxCurrencyCode`: the tax currency code, + * - `LanguageName`: the language code (e.g., 'es'). + */ protected function buildInvoiceIssueData(Invoice $invoice): array { return [ @@ -224,11 +249,11 @@ protected function buildInvoiceIssueData(Invoice $invoice): array } /** - * Build taxes outputs section. + * Assemble tax output entries grouped by tax rate for the Facturae payload. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * @param Invoice $invoice The invoice whose items will be grouped by tax rate to produce tax entries. + * @param string $currencyCode The currency code used when formatting monetary amounts. + * @return array An array with a `Tax` key containing a list of tax group entries. Each entry includes a `Tax` structure with `TaxTypeCode`, `TaxRate`, `TaxableBase['TotalAmount']`, and `TaxAmount['TotalAmount']` formatted as strings with two decimal places. */ protected function buildTaxesOutputs(Invoice $invoice, string $currencyCode): array { @@ -270,11 +295,18 @@ protected function buildTaxesOutputs(Invoice $invoice, string $currencyCode): ar } /** - * Build invoice totals. + * Assembles invoice total amounts formatted for the Facturae payload. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * @param Invoice $invoice The invoice model providing subtotal and total amounts. + * @param string $currencyCode The invoice currency code (used for context; amounts are formatted to two decimals). + * @return array An associative array with the following keys: + * - `TotalGrossAmount`: subtotal formatted with 2 decimals. + * - `TotalGrossAmountBeforeTaxes`: subtotal formatted with 2 decimals. + * - `TotalTaxOutputs`: tax amount (invoice total minus subtotal) formatted with 2 decimals. + * - `TotalTaxesWithheld`: taxes withheld, represented as `'0.00'`. + * - `InvoiceTotal`: invoice total formatted with 2 decimals. + * - `TotalOutstandingAmount`: outstanding amount formatted with 2 decimals. + * - `TotalExecutableAmount`: executable amount formatted with 2 decimals. */ protected function buildInvoiceTotals(Invoice $invoice, string $currencyCode): array { @@ -292,11 +324,11 @@ protected function buildInvoiceTotals(Invoice $invoice, string $currencyCode): a } /** - * Build invoice items. + * Map invoice items to Facturae 3.2 `InvoiceLine` structures. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * @param Invoice $invoice The invoice whose items will be converted into line entries. + * @param string $currencyCode Currency ISO code used for monetary formatting. + * @return array An array with the key `InvoiceLine` containing a list of line entries formatted for Facturae (each entry includes quantities, unit price, totals and tax breakdowns). */ protected function buildItems(Invoice $invoice, string $currencyCode): array { @@ -332,11 +364,14 @@ protected function buildItems(Invoice $invoice, string $currencyCode): array } /** - * Build payment details. + * Constructs the payment details structure containing a single installment. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * @param Invoice $invoice The invoice used to populate the installment due date and amount. + * @param string $currencyCode The currency code (ISO 4217) associated with the installment amount. + * @return array An array with an 'Installment' entry containing: + * - 'InstallmentDueDate' (string, Y-m-d), + * - 'InstallmentAmount' (string, formatted with two decimals), + * - 'PaymentMeans' (string, payment method code, e.g. '04' for transfer). */ protected function buildPaymentDetails(Invoice $invoice, string $currencyCode): array { @@ -350,7 +385,11 @@ protected function buildPaymentDetails(Invoice $invoice, string $currencyCode): } /** - * {@inheritdoc} + * Produce a Facturae 3.2 XML representation for the given invoice. + * + * @param Invoice $invoice The invoice to convert. + * @param array $options Optional transform options. + * @return string A string containing the Facturae 3.2 XML payload for the invoice. Current implementation returns a pretty-printed JSON representation of the prepared payload as a placeholder. */ public function generateXml(Invoice $invoice, array $options = []): string { @@ -361,8 +400,11 @@ public function generateXml(Invoice $invoice, array $options = []): string } /** - * {@inheritdoc} - */ + * Validate Facturae-specific requirements for the given invoice. + * + * @param Invoice $invoice The invoice to validate. + * @return string[] An array of validation error messages; empty if no errors. + */ protected function validateFormatSpecific(Invoice $invoice): array { $errors = []; @@ -376,10 +418,10 @@ protected function validateFormatSpecific(Invoice $invoice): array } /** - * Extract series code from invoice number. + * Extracts the leading alphabetic series code from an invoice number. * - * @param string $invoiceNumber - * @return string + * @param string $invoiceNumber Invoice identifier that may start with a letter-based series. + * @return string The extracted series code (leading uppercase letters), or 'A' if none are present. */ protected function extractSeriesCode(string $invoiceNumber): string { @@ -392,14 +434,14 @@ protected function extractSeriesCode(string $invoiceNumber): string } /** - * Get tax rate from invoice item. + * Retrieve the tax rate for an invoice item. * - * @param mixed $item - * @return float + * @param mixed $item Invoice item expected to contain a `tax_rate` property or key. + * @return float The tax rate to apply; `21.0` if the item does not specify one. */ protected function getTaxRate($item): float { // Default Spanish VAT rate is 21% return $item->tax_rate ?? 21.0; } -} +} \ No newline at end of file diff --git a/Modules/Invoices/Peppol/FormatHandlers/FatturaPaHandler.php b/Modules/Invoices/Peppol/FormatHandlers/FatturaPaHandler.php index 846c3828..f2c38ab3 100644 --- a/Modules/Invoices/Peppol/FormatHandlers/FatturaPaHandler.php +++ b/Modules/Invoices/Peppol/FormatHandlers/FatturaPaHandler.php @@ -17,7 +17,7 @@ class FatturaPaHandler extends BaseFormatHandler { /** - * Constructor. + * Initialize the handler configured for the FatturaPA 1.2 Peppol document format. */ public function __construct() { @@ -25,8 +25,16 @@ public function __construct() } /** - * {@inheritdoc} - */ + * Convert an Invoice into the FatturaPA 1.2 data structure. + * + * Builds the top-level array expected for a FatturaElettronica document containing header and body sections. + * + * @param Invoice $invoice The invoice to transform. + * @param array $options Optional transformation flags and overrides. + * @return array An associative array with keys: + * - `FatturaElettronicaHeader`: header data for the electronic invoice. + * - `FatturaElettronicaBody`: body data for the electronic invoice. + */ public function transform(Invoice $invoice, array $options = []): array { $customer = $invoice->customer; @@ -39,10 +47,10 @@ public function transform(Invoice $invoice, array $options = []): array } /** - * Build FatturaPA header section. + * Build the FatturaPA electronic invoice header for the given invoice. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice The invoice used to populate header sections. + * @return array Array with 'DatiTrasmissione', 'CedentePrestatore' and 'CessionarioCommittente' entries. */ protected function buildHeader(Invoice $invoice): array { @@ -54,10 +62,10 @@ protected function buildHeader(Invoice $invoice): array } /** - * Build transmission data section. + * Constructs the FatturaPA DatiTrasmissione (transmission data) for the given invoice. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice The invoice used to populate transmission fields. + * @return array Array containing `IdTrasmittente` (with `IdPaese` and `IdCodice`), `ProgressivoInvio`, `FormatoTrasmissione`, and `CodiceDestinatario`. */ protected function buildTransmissionData(Invoice $invoice): array { @@ -73,11 +81,25 @@ protected function buildTransmissionData(Invoice $invoice): array } /** - * Build supplier data section. - * - * @param Invoice $invoice - * @return array - */ + * Constructs the supplier (CedentePrestatore) data structure required by FatturaPA header. + * + * The returned array contains the supplier fiscal and registry information under `DatiAnagrafici` + * and the supplier address under `Sede`. + * + * @param Invoice $invoice Invoice instance (unused directly; kept for interface consistency). + * @return array Array with keys: + * - `DatiAnagrafici`: [ + * `IdFiscaleIVA` => ['IdPaese' => string, 'IdCodice' => string], + * `Anagrafica` => ['Denominazione' => string|null], + * `RegimeFiscale` => string + * ] + * - `Sede`: [ + * `Indirizzo` => string|null, + * `CAP` => string|null, + * `Comune` => string|null, + * `Nazione` => string + * ] + */ protected function buildSupplierData(Invoice $invoice): array { return [ @@ -101,10 +123,14 @@ protected function buildSupplierData(Invoice $invoice): array } /** - * Build customer data section. + * Constructs the customer data structure used in the FatturaPA header. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice Invoice containing the customer information. + * @return array Array with keys: + * - `DatiAnagrafici`: contains `CodiceFiscale` (customer tax code or empty string) + * and `Anagrafica` with `Denominazione` (company name or customer name). + * - `Sede`: contains address fields `Indirizzo`, `CAP`, `Comune`, and `Nazione` + * (country code, defaults to "IT" when absent). */ protected function buildCustomerData(Invoice $invoice): array { @@ -127,11 +153,14 @@ protected function buildCustomerData(Invoice $invoice): array } /** - * Build FatturaPA body section. + * Assembles the body section of a FatturaPA 1.2 document. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * @param Invoice $invoice The invoice to convert into FatturaPA body data. + * @param string $currencyCode ISO 4217 currency code to format monetary fields. + * @return array Associative array with keys: + * - `DatiGenerali`: general document data, + * - `DatiBeniServizi`: line items and tax summary, + * - `DatiPagamento`: payment terms and details. */ protected function buildBody(Invoice $invoice, string $currencyCode): array { @@ -143,10 +172,14 @@ protected function buildBody(Invoice $invoice, string $currencyCode): array } /** - * Build general invoice data. + * Builds the 'DatiGeneraliDocumento' section for a FatturaPA invoice. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice The invoice to extract general document fields from. + * @return array Array with a single key 'DatiGeneraliDocumento' containing: + * - 'TipoDocumento' (document type code), + * - 'Divisa' (currency code), + * - 'Data' (invoice date in 'Y-m-d' format), + * - 'Numero' (invoice number). */ protected function buildGeneralData(Invoice $invoice): array { @@ -161,11 +194,21 @@ protected function buildGeneralData(Invoice $invoice): array } /** - * Build items data section. + * Construct the items section with detailed line entries and the aggregated tax summary. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * Each line in `DettaglioLinee` contains numeric and descriptive fields for a single invoice item. + * + * @param Invoice $invoice The invoice whose items will be converted into line entries. + * @param string $currencyCode ISO 4217 currency code used for the line amounts. + * @return array An array with two keys: + * - `DettaglioLinee`: array of line entries, each containing: + * - `NumeroLinea`: line number (1-based). + * - `Descrizione`: item description. + * - `Quantita`: quantity formatted with two decimals. + * - `PrezzoUnitario`: unit price formatted with two decimals. + * - `PrezzoTotale`: total price for the line formatted with two decimals. + * - `AliquotaIVA`: VAT rate for the line formatted with two decimals. + * - `DatiRiepilogo`: tax summary grouped by VAT rate (base and tax amounts). */ protected function buildItemsData(Invoice $invoice, string $currencyCode): array { @@ -187,11 +230,17 @@ protected function buildItemsData(Invoice $invoice, string $currencyCode): array } /** - * Build tax summary. - * - * @param Invoice $invoice - * @return array> - */ + * Builds the VAT summary grouped by VAT rate. + * + * Groups invoice items by their VAT rate and returns an array of summary entries. + * Each entry contains: + * - `AliquotaIVA`: VAT rate as a string formatted with two decimals. + * - `ImponibileImporto`: taxable base amount as a string formatted with two decimals. + * - `Imposta`: tax amount as a string formatted with two decimals. + * + * @param Invoice $invoice The invoice to summarize. + * @return array> Array of summary entries keyed numerically. + */ protected function buildTaxSummary(Invoice $invoice): array { // Group items by tax rate @@ -225,10 +274,12 @@ protected function buildTaxSummary(Invoice $invoice): array } /** - * Build payment data section. + * Assemble the payment section for the FatturaPA body. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice Invoice used to obtain the payment due date and amount. + * @return array Payment data with keys: + * - 'CondizioniPagamento': payment condition code, + * - 'DettaglioPagamento': array of payment entries each containing 'ModalitaPagamento', 'DataScadenzaPagamento', and 'ImportoPagamento'. */ protected function buildPaymentData(Invoice $invoice): array { @@ -245,8 +296,12 @@ protected function buildPaymentData(Invoice $invoice): array } /** - * {@inheritdoc} - */ + * Generate the FatturaPA-compliant XML representation for the given invoice. + * + * @param Invoice $invoice The invoice to convert. + * @param array $options Optional transformation options. + * @return string The FatturaPA XML as a string; currently returns a JSON-formatted string of the transformed data as a placeholder. + */ public function generateXml(Invoice $invoice, array $options = []): string { $data = $this->transform($invoice, $options); @@ -256,8 +311,11 @@ public function generateXml(Invoice $invoice, array $options = []): string } /** - * {@inheritdoc} - */ + * Validate FatturaPA-specific requirements for the given invoice. + * + * @param Invoice $invoice The invoice to validate. + * @return string[] List of validation error messages; empty array if there are no validation errors. + */ protected function validateFormatSpecific(Invoice $invoice): array { $errors = []; @@ -276,10 +334,10 @@ protected function validateFormatSpecific(Invoice $invoice): array } /** - * Extract ID code from VAT number (remove country prefix). + * Return the VAT identifier without the country prefix. * - * @param string|null $vatNumber - * @return string + * @param string|null $vatNumber VAT number possibly prefixed with a country code (e.g., "IT12345678901"). + * @return string The VAT identifier with any leading "IT" removed; returns an empty string when the input is null or empty. */ protected function extractIdCodice(?string $vatNumber): string { @@ -292,14 +350,14 @@ protected function extractIdCodice(?string $vatNumber): string } /** - * Get VAT rate from invoice item. - * - * @param mixed $item - * @return float - */ + * Obtain the VAT rate percentage for an invoice item. + * + * @param mixed $item Invoice item expected to expose a numeric `tax_rate` property (percentage). + * @return float The VAT percentage to apply (uses the item's `tax_rate` if present, otherwise 22.0). + */ protected function getVatRate($item): float { // Assuming the item has a tax_rate or we use default Italian VAT rate return $item->tax_rate ?? 22.0; // 22% is standard Italian VAT } -} +} \ No newline at end of file diff --git a/Modules/Invoices/Peppol/FormatHandlers/OioublHandler.php b/Modules/Invoices/Peppol/FormatHandlers/OioublHandler.php index fbe4bd79..2cb20cc6 100644 --- a/Modules/Invoices/Peppol/FormatHandlers/OioublHandler.php +++ b/Modules/Invoices/Peppol/FormatHandlers/OioublHandler.php @@ -17,7 +17,7 @@ class OioublHandler extends BaseFormatHandler { /** - * Constructor. + * Initialize the handler for the OIOUBL Peppol document format. */ public function __construct() { @@ -25,8 +25,18 @@ public function __construct() } /** - * {@inheritdoc} - */ + * Builds an OIOUBL 2.0 representation of the given invoice as an associative array. + * + * The returned array contains the core OIOUBL document fields and nested sections: + * ubl_version_id, customization_id, profile_id, id, issue_date, invoice_type_code, + * document_currency_code, accounting_cost, accounting_supplier_party, + * accounting_customer_party, payment_means, payment_terms, tax_total, + * legal_monetary_total, and invoice_line. + * + * @param Invoice $invoice The invoice to transform. + * @param array $options Optional transform options. + * @return array The invoice represented as an OIOUBL-structured associative array. + */ public function transform(Invoice $invoice, array $options = []): array { $customer = $invoice->customer; @@ -67,11 +77,11 @@ public function transform(Invoice $invoice, array $options = []): array } /** - * Build supplier party. + * Construct the supplier party block for the OIOUBL document using configured supplier data and the provided endpoint scheme. * - * @param Invoice $invoice - * @param mixed $endpointScheme - * @return array + * @param Invoice $invoice The invoice being transformed (unused except for context). + * @param mixed $endpointScheme Endpoint scheme object whose `value` property is used as the endpoint scheme identifier. + * @return array Array representing the supplier `party` structure for the OIOUBL document. */ protected function buildSupplierParty(Invoice $invoice, $endpointScheme): array { @@ -121,11 +131,14 @@ protected function buildSupplierParty(Invoice $invoice, $endpointScheme): array } /** - * Build customer party. + * Construct the OIOUBL customer party block for the invoice. + * + * Builds a nested array representing the customer party including endpoint identification, + * party identification (DK:CVR), party name, postal address, legal entity, and contact details. * - * @param Invoice $invoice - * @param mixed $endpointScheme - * @return array + * @param Invoice $invoice The invoice containing customer information. + * @param mixed $endpointScheme An object with a `value` property used as the endpoint scheme identifier. + * @return array Nested array representing the customer party section of the OIOUBL document. */ protected function buildCustomerParty(Invoice $invoice, $endpointScheme): array { @@ -168,10 +181,15 @@ protected function buildCustomerParty(Invoice $invoice, $endpointScheme): array } /** - * Build payment means. + * Constructs the payment means section for the given invoice. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice The invoice to build payment means for. + * @return array An associative array with keys: + * - `payment_means_code`: string, code '31' for international bank transfer. + * - `payment_due_date`: string, due date in `YYYY-MM-DD` format. + * - `payment_id`: string, the invoice number. + * - `payee_financial_account`: array with `id` (account identifier) and + * `financial_institution_branch` containing `id` (bank SWIFT/BIC). */ protected function buildPaymentMeans(Invoice $invoice): array { @@ -189,11 +207,13 @@ protected function buildPaymentMeans(Invoice $invoice): array } /** - * Build payment terms. - * - * @param Invoice $invoice - * @return array - */ + * Build payment terms for the invoice, including a human-readable note and settlement period. + * + * @param Invoice $invoice The invoice to derive payment terms from. + * @return array An array containing: + * - `note` (string): A message like "Payment due within X days". + * - `settlement_period` (array): Contains `end_date` (string, YYYY-MM-DD) for the settlement end. + */ protected function buildPaymentTerms(Invoice $invoice): array { $daysUntilDue = $invoice->invoiced_at->diffInDays($invoice->invoice_due_at); @@ -207,12 +227,20 @@ protected function buildPaymentTerms(Invoice $invoice): array } /** - * Build tax total. - * - * @param Invoice $invoice - * @param string $currencyCode - * @return array - */ + * Builds the invoice-level tax total and per-rate tax subtotals. + * + * Computes the total tax (invoice total minus invoice subtotal), groups invoice items by tax rate, + * and produces a list of tax subtotals for each rate with taxable base and tax amount. + * + * @param Invoice $invoice The invoice used to compute tax bases and amounts. + * @param string $currencyCode ISO currency code to attach to monetary values. + * @return array An array containing: + * - `tax_amount`: ['value' => string (formatted to 2 decimals), 'currency_id' => string] + * - `tax_subtotal`: array of entries each with: + * - `taxable_amount`: ['value' => string (2 decimals), 'currency_id' => string] + * - `tax_amount`: ['value' => string (2 decimals), 'currency_id' => string] + * - `tax_category`: ['id' => 'S'|'Z', 'percent' => float, 'tax_scheme' => ['id' => 'VAT']] + */ protected function buildTaxTotal(Invoice $invoice, string $currencyCode): array { $taxAmount = $invoice->invoice_total - $invoice->invoice_subtotal; @@ -266,11 +294,15 @@ protected function buildTaxTotal(Invoice $invoice, string $currencyCode): array } /** - * Build monetary total. + * Construct the monetary totals section for the given invoice. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * @param Invoice $invoice The invoice to derive totals from. + * @param string $currencyCode Currency code used for all returned amounts. + * @return array An associative array with keys: + * - `line_extension_amount`: array with `value` (subtotal as string formatted to 2 decimals) and `currency_id`. + * - `tax_exclusive_amount`: array with `value` (subtotal) and `currency_id`. + * - `tax_inclusive_amount`: array with `value` (total amount) and `currency_id`. + * - `payable_amount`: array with `value` (total amount) and `currency_id`. */ protected function buildMonetaryTotal(Invoice $invoice, string $currencyCode): array { @@ -297,11 +329,16 @@ protected function buildMonetaryTotal(Invoice $invoice, string $currencyCode): a } /** - * Build invoice lines. + * Convert invoice items into an array of OIOUBL invoice line entries. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array> + * Each line entry contains: sequential `id`; `invoiced_quantity` with value and unit code; `line_extension_amount` + * and `price` values annotated with the provided currency; `accounting_cost`; and an `item` block including + * description, name, seller item id and a `classified_tax_category` (id 'S' for taxed lines, 'Z' for zero rate) + * with the tax percent and tax scheme. + * + * @param Invoice $invoice The invoice whose items will be converted into lines. + * @param string $currencyCode ISO currency code used for monetary values in each line. + * @return array> Array of invoice line structures suitable for OIOUBL output. */ protected function buildInvoiceLines(Invoice $invoice, string $currencyCode): array { @@ -345,7 +382,14 @@ protected function buildInvoiceLines(Invoice $invoice, string $currencyCode): ar } /** - * {@inheritdoc} + * Generate an OIOUBL XML representation of the given invoice. + * + * Converts the invoice into the OIOUBL structure and returns it as an XML string. + * Currently this method returns a JSON-formatted placeholder of the transformed data. + * + * @param Invoice $invoice The invoice to convert. + * @param array $options Additional options forwarded to the transform step. + * @return string The OIOUBL XML string, or a JSON-formatted placeholder of the transformed data. */ public function generateXml(Invoice $invoice, array $options = []): string { @@ -356,7 +400,12 @@ public function generateXml(Invoice $invoice, array $options = []): string } /** - * {@inheritdoc} + * Validate OIOUBL-specific invoice requirements. + * + * Checks that a supplier CVR (VAT number) is configured and that the invoice's customer has a Peppol ID. + * + * @param Invoice $invoice The invoice to validate. + * @return array Array of validation error messages; empty if there are no violations. */ protected function validateFormatSpecific(Invoice $invoice): array { @@ -375,11 +424,11 @@ protected function validateFormatSpecific(Invoice $invoice): array return $errors; } - /** - * Get accounting cost code. + / ** + * Uses the invoice reference as the OIOUBL accounting cost code. * - * @param Invoice $invoice - * @return string + * @param Invoice $invoice The invoice to read the reference from. + * @return string The invoice reference used as accounting cost, or an empty string if none. */ protected function getAccountingCost(Invoice $invoice): string { @@ -388,24 +437,24 @@ protected function getAccountingCost(Invoice $invoice): string } /** - * Get line accounting cost code. - * - * @param mixed $item - * @return string - */ + * Retrieve the accounting cost code for a single invoice line. + * + * @param mixed $item Invoice line item object; expected to have an `accounting_cost` property. + * @return string The line's accounting cost code, or an empty string if none is set. + */ protected function getLineAccountingCost($item): string { return $item->accounting_cost ?? ''; } /** - * Get tax rate from invoice item. - * - * @param mixed $item - * @return float - */ + * Return the tax rate for an invoice item, defaulting to 25.0 if the item does not specify one. + * + * @param mixed $item Invoice line item object; may provide a `tax_rate` property. + * @return float The tax rate as a percentage (e.g., 25.0). + */ protected function getTaxRate($item): float { return $item->tax_rate ?? 25.0; // Standard Danish VAT rate } -} +} \ No newline at end of file diff --git a/Modules/Invoices/Peppol/FormatHandlers/ZugferdHandler.php b/Modules/Invoices/Peppol/FormatHandlers/ZugferdHandler.php index 85cea861..5f7502ca 100644 --- a/Modules/Invoices/Peppol/FormatHandlers/ZugferdHandler.php +++ b/Modules/Invoices/Peppol/FormatHandlers/ZugferdHandler.php @@ -17,9 +17,11 @@ class ZugferdHandler extends BaseFormatHandler { /** - * Constructor. + * Create a ZugferdHandler for the specified Peppol document format. * - * @param PeppolDocumentFormat|null $format Defaults to ZUGFeRD 2.0 + * If null, the handler defaults to ZUGFERD 2.0 (Factur‑X compatible). + * + * @param PeppolDocumentFormat|null $format The target ZUGFeRD/Factur‑X format or null to use the default. */ public function __construct(?PeppolDocumentFormat $format = null) { @@ -27,7 +29,11 @@ public function __construct(?PeppolDocumentFormat $format = null) } /** - * {@inheritdoc} + * Builds a ZUGFeRD (CII) document structure for the provided invoice using the handler's configured format. + * + * @param Invoice $invoice The invoice to transform into a ZUGFeRD payload. + * @param array $options Optional transformation options (unused by default; implementation-specific). + * @return array An associative array representing the ZUGFeRD (CII) document structure conforming to either ZUGFeRD 1.0 or 2.0 depending on the handler configuration. */ public function transform(Invoice $invoice, array $options = []): array { @@ -86,10 +92,10 @@ protected function buildZugferd20Structure(Invoice $invoice): array } /** - * Build header exchanged document (ZUGFeRD 1.0). + * Create the HeaderExchangedDocument structure for ZUGFeRD 1.0 using invoice data. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice Invoice whose number and issue date populate the header. + * @return array Associative array representing the HeaderExchangedDocument (ID, Name, TypeCode, IssueDateTime). */ protected function buildHeaderExchangedDocument(Invoice $invoice): array { @@ -107,9 +113,9 @@ protected function buildHeaderExchangedDocument(Invoice $invoice): array } /** - * Build document context (ZUGFeRD 2.0). + * Builds the ZUGFeRD 2.0 document context identifying the basic-compliance guideline. * - * @return array + * @return array Associative array containing `ram:GuidelineSpecifiedDocumentContextParameter` with `ram:ID` set to the ZUGFeRD 2.0 basic-profile URN. */ protected function buildDocumentContext20(): array { @@ -121,11 +127,14 @@ protected function buildDocumentContext20(): array } /** - * Build exchanged document (ZUGFeRD 2.0). - * - * @param Invoice $invoice - * @return array - */ + * Constructs the ZUGFeRD 2.0 ExchangedDocument block from the invoice metadata. + * + * @param Invoice $invoice Invoice providing the document ID and issue date. + * @return array Associative array with keys: + * - `ram:ID` (invoice number), + * - `ram:TypeCode` (invoice type code, "380"), + * - `ram:IssueDateTime` containing `udt:DateTimeString` with `@format` "102" and the issue date in `Ymd` format. + */ protected function buildExchangedDocument20(Invoice $invoice): array { return [ @@ -141,11 +150,13 @@ protected function buildExchangedDocument20(Invoice $invoice): array } /** - * Build supply chain trade transaction (ZUGFeRD 1.0). + * Assembles the ApplicableSupplyChainTradeTransaction structure for ZUGFeRD 1.0. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * @param string $currencyCode ISO 4217 currency code used for monetary amount fields. + * @return array Nested array with keys: + * - 'ApplicableSupplyChainTradeAgreement' => seller/buyer trade party blocks, + * - 'ApplicableSupplyChainTradeDelivery' => delivery event block, + * - 'ApplicableSupplyChainTradeSettlement' => settlement and monetary summation block. */ protected function buildSupplyChainTradeTransaction10(Invoice $invoice, string $currencyCode): array { @@ -173,10 +184,13 @@ protected function buildSupplyChainTradeTransaction20(Invoice $invoice, string $ } /** - * Build trade agreement (ZUGFeRD 1.0). + * Builds the ZUGFeRD 1.0 trade agreement section containing seller and buyer party information. * - * @param Invoice $invoice - * @return array + * The returned array contains keyed blocks for `SellerTradeParty` and `BuyerTradeParty`, including + * postal address fields and, for the seller, a tax registration entry with VAT scheme ID. + * + * @param Invoice $invoice Invoice object used to source buyer details. + * @return array Associative array representing the ApplicableSupplyChainTradeTransaction trade agreement portion for ZUGFeRD 1.0. */ protected function buildTradeAgreement10(Invoice $invoice): array { @@ -249,10 +263,10 @@ protected function buildTradeAgreement20(Invoice $invoice): array } /** - * Build trade delivery (ZUGFeRD 1.0). + * Builds the ZUGFeRD 1.0 ActualDeliverySupplyChainEvent using the invoice's issue date. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice The invoice whose invoiced_at date is used for the occurrence date. + * @return array Array representing the ActualDeliverySupplyChainEvent with a `DateTimeString` in format `102` (YYYYMMDD). */ protected function buildTradeDelivery10(Invoice $invoice): array { @@ -269,10 +283,10 @@ protected function buildTradeDelivery10(Invoice $invoice): array } /** - * Build trade delivery (ZUGFeRD 2.0). + * Builds the trade delivery block for ZUGFeRD 2.0 with the delivery occurrence date. * - * @param Invoice $invoice - * @return array + * @param Invoice $invoice Invoice whose `invoiced_at` date is used as the occurrence date. + * @return array Associative array representing `ram:ActualDeliverySupplyChainEvent` with `ram:OccurrenceDateTime` containing `udt:DateTimeString` (format `102`) set to the invoice's `invoiced_at` in `Ymd` format. */ protected function buildTradeDelivery20(Invoice $invoice): array { @@ -289,11 +303,15 @@ protected function buildTradeDelivery20(Invoice $invoice): array } /** - * Build trade settlement (ZUGFeRD 1.0). + * Constructs the trade settlement section for a ZUGFeRD 1.0 invoice. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * The resulting array contains invoice currency, payment means (SEPA), applicable tax totals, + * payment terms with due date, and the monetary summation (line total, tax basis, tax total, + * grand total, and due payable amounts). + * + * @param Invoice $invoice The invoice to derive settlement values from. + * @param string $currencyCode ISO 4217 currency code used for monetary amounts. + * @return array Array representing the SpecifiedTradeSettlement structure for ZUGFeRD 1.0. */ protected function buildTradeSettlement10(Invoice $invoice, string $currencyCode): array { @@ -339,11 +357,18 @@ protected function buildTradeSettlement10(Invoice $invoice, string $currencyCode } /** - * Build trade settlement (ZUGFeRD 2.0). + * Build the ZUGFeRD 2.0 trade settlement section for the given invoice. * - * @param Invoice $invoice - * @param string $currencyCode - * @return array + * Returns an associative array containing the settlement information: + * - `ram:InvoiceCurrencyCode` + * - `ram:SpecifiedTradeSettlementPaymentMeans` (TypeCode "58" for SEPA) + * - `ram:ApplicableTradeTax` (per-rate tax totals) + * - `ram:SpecifiedTradePaymentTerms` (due date as `udt:DateTimeString` format 102) + * - `ram:SpecifiedTradeSettlementHeaderMonetarySummation` (line, tax, grand and due payable amounts) + * + * @param Invoice $invoice Invoice model providing amounts and dates. + * @param string $currencyCode ISO 4217 currency code used for monetary elements. + * @return array Associative array representing the ZUGFeRD 2.0 settlement structure. */ protected function buildTradeSettlement20(Invoice $invoice, string $currencyCode): array { @@ -376,11 +401,18 @@ protected function buildTradeSettlement20(Invoice $invoice, string $currencyCode ]; } - /** - * Build tax totals (ZUGFeRD 1.0). + /**** + * Builds tax total entries for ZUGFeRD 1.0 grouped by tax rate. * - * @param Invoice $invoice - * @return array> + * Each entry contains: + * - `CalculatedAmount`: array with `@currencyID` and numeric string value (`#`). + * - `TypeCode`: tax type (always `'VAT'`). + * - `BasisAmount`: array with `@currencyID` and numeric string value (`#`). + * - `CategoryCode`: `'S'` for taxable rates greater than zero, `'Z'` for zero rate. + * - `ApplicablePercent`: tax rate as a numeric string. + * + * @param Invoice $invoice Invoice used to compute tax groups. + * @return array Array of tax total entries suitable for ZUGFeRD 1.0. */ protected function buildTaxTotals10(Invoice $invoice): array { @@ -407,11 +439,15 @@ protected function buildTaxTotals10(Invoice $invoice): array } /** - * Build tax totals (ZUGFeRD 2.0). - * - * @param Invoice $invoice - * @return array> - */ + * Build the ZUGFeRD 2.0 tax total entries grouped by tax rate. + * + * Produces an array of RAM tax nodes where each entry contains formatted strings for + * `ram:CalculatedAmount`, `ram:BasisAmount`, and `ram:RateApplicablePercent`, plus + * `ram:TypeCode` and `ram:CategoryCode` (\"S\" for taxable rates > 0, \"Z\" for zero rate). + * + * @param Invoice $invoice Invoice to derive tax groups from. + * @return array> List of tax entries suitable for inclusion in a ZUGFeRD 2.0 payload. + */ protected function buildTaxTotals20(Invoice $invoice): array { $taxGroups = $this->groupTaxesByRate($invoice); @@ -431,10 +467,14 @@ protected function buildTaxTotals20(Invoice $invoice): array } /** - * Group taxes by rate. + * Groups invoice tax bases and tax amounts by tax rate. * - * @param Invoice $invoice - * @return array> + * Builds an associative array keyed by tax rate (percentage) where each value contains + * the cumulative 'base' (taxable amount) and 'amount' (calculated tax) for that rate, + * using the invoice currency values. + * + * @param Invoice $invoice The invoice whose items will be grouped. + * @return array> Associative array keyed by tax rate with keys 'base' and 'amount' holding totals as floats. */ protected function groupTaxesByRate(Invoice $invoice): array { @@ -458,7 +498,13 @@ protected function groupTaxesByRate(Invoice $invoice): array } /** - * {@inheritdoc} + * Generate a string representation of the invoice's ZUGFeRD data. + * + * Converts the given invoice into the format-specific ZUGFeRD structure and returns it as a string. + * + * @param Invoice $invoice The invoice to convert into ZUGFeRD format. + * @param array $options Optional format-specific options. + * @return string The pretty-printed JSON representation of the transformed ZUGFeRD data (placeholder for the actual XML embedding). */ public function generateXml(Invoice $invoice, array $options = []): string { @@ -469,7 +515,10 @@ public function generateXml(Invoice $invoice, array $options = []): string } /** - * {@inheritdoc} + * Perform ZUGFeRD-specific validation on an invoice. + * + * @param Invoice $invoice The invoice to validate. + * @return string[] Array of validation error messages; empty if the invoice passes ZUGFeRD-specific checks. */ protected function validateFormatSpecific(Invoice $invoice): array { @@ -484,13 +533,13 @@ protected function validateFormatSpecific(Invoice $invoice): array } /** - * Get tax rate from invoice item. - * - * @param mixed $item - * @return float - */ + * Retrieve the tax rate percent from an invoice item. + * + * @param mixed $item Invoice line item object or array expected to contain a `tax_rate` value. + * @return float The tax rate as a percentage (e.g., 19.0). Returns 19.0 if the item has no `tax_rate`. + */ protected function getTaxRate($item): float { return $item->tax_rate ?? 19.0; // Default German VAT rate } -} +} \ No newline at end of file