From 7351494447a4e83181fa293d468cbd4a6a982e58 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 14 Jan 2026 12:32:22 +1100 Subject: [PATCH] Updates for PEPPOL invoices --- app/Helpers/SwissQr/SwissQrGenerator.php | 4 ++-- app/Models/BaseModel.php | 2 +- app/Models/Invoice.php | 2 +- app/Services/EDocument/Standards/Peppol.php | 19 +++++++++++-------- phpstan.neon | 1 + 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/app/Helpers/SwissQr/SwissQrGenerator.php b/app/Helpers/SwissQr/SwissQrGenerator.php index 0859f7271a..33b627d22a 100644 --- a/app/Helpers/SwissQr/SwissQrGenerator.php +++ b/app/Helpers/SwissQr/SwissQrGenerator.php @@ -112,11 +112,11 @@ class SwissQrGenerator // Add payment reference // This is what you will need to identify incoming payments. - if (stripos($this->invoice->number, "Live") === 0) { + if (stripos($this->invoice->number ?? '', "Live") === 0) { // we're currently in preview status. Let's give a dummy reference for now $invoice_number = "123456789"; } else { - $tempInvoiceNumber = $this->invoice->number; + $tempInvoiceNumber = $this->invoice->number ?? ''; $tempInvoiceNumber = preg_replace('/[^A-Za-z0-9]/', '', $tempInvoiceNumber); // $tempInvoiceNumber = substr($tempInvoiceNumber, 1); diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php index e9bae19646..4356e00253 100644 --- a/app/Models/BaseModel.php +++ b/app/Models/BaseModel.php @@ -279,7 +279,7 @@ class BaseModel extends Model public function numberFormatter() { - $number = strlen($this->number) >= 1 ? $this->translate_entity() . "_" . $this->number : class_basename($this) . "_" . Str::random(5); + $number = strlen($this->number ?? '') >= 1 ? $this->translate_entity() . "_" . $this->number : class_basename($this) . "_" . Str::random(5); $formatted_number = mb_ereg_replace("([^\w\s\d\-_~,;\[\]\(\).])", '', $number); diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index d6d8124b1d..ea84fe7cf2 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -38,7 +38,7 @@ use App\Utils\Number; * App\Models\Invoice * * @property int $id - * @property object|null $e_invoice + * @property object|array|null $e_invoice * @property int $client_id * @property int $user_id * @property int|null $location_id diff --git a/app/Services/EDocument/Standards/Peppol.php b/app/Services/EDocument/Standards/Peppol.php index 19c04e168a..b7fabbc46b 100644 --- a/app/Services/EDocument/Standards/Peppol.php +++ b/app/Services/EDocument/Standards/Peppol.php @@ -65,7 +65,7 @@ class Peppol extends AbstractService * */ - private ?string $override_vat_number; + private string $override_vat_number = ''; /** @var array $InvoiceTypeCodes */ private array $InvoiceTypeCodes = [ @@ -657,7 +657,8 @@ class Peppol extends AbstractService $tax_type = 'S'; break; case Product::PRODUCT_TYPE_REDUCED_TAX: - $tax_type = 'AA'; + // $tax_type = 'AA'; + $tax_type = 'S'; //2026-01-14 - using AA breaks PEPPOL VALIDATION!! break; case Product::PRODUCT_TYPE_EXEMPT: $tax_type = 'E'; @@ -759,10 +760,12 @@ class Peppol extends AbstractService $this->globalTaxCategories = [$taxCategory]; if ($this->tax_category_id == 'O' && isset($this->p_invoice->AccountingSupplierParty->Party->PartyTaxScheme)) { + nlog("unset 1"); unset($this->p_invoice->AccountingSupplierParty->Party->PartyTaxScheme); } if ($this->tax_category_id == 'O' && isset($this->p_invoice->AccountingCustomerParty->Party->PartyTaxScheme)) { + nlog("unset 2"); unset($this->p_invoice->AccountingCustomerParty->Party->PartyTaxScheme); } @@ -1032,18 +1035,18 @@ class Peppol extends AbstractService $party->PartyName[] = $party_name; if (strlen($this->company->settings->vat_number ?? '') > 1) { - + $pi = new PartyIdentification(); $vatID = new ID(); $vatID->schemeID = $this->resolveScheme(); - $vatID->value = $this->override_vat_number ?? preg_replace("/[^a-zA-Z0-9]/", "", $this->invoice->company->settings->vat_number); //todo if we are cross border - switch to the supplier local vat number + $vatID->value = strlen($this->override_vat_number ?? '') > 1 ? $this->override_vat_number : preg_replace("/[^a-zA-Z0-9]/", "", $this->invoice->company->settings->vat_number); //todo if we are cross border - switch to the supplier local vat number $pi->ID = $vatID; $party->PartyIdentification[] = $pi; $pts = new \InvoiceNinja\EInvoice\Models\Peppol\PartyTaxSchemeType\PartyTaxScheme(); $companyID = new \InvoiceNinja\EInvoice\Models\Peppol\IdentifierType\CompanyID(); - $companyID->value = $this->override_vat_number ?? preg_replace("/[^a-zA-Z0-9]/", "", $this->invoice->company->settings->vat_number); + $companyID->value = strlen($this->override_vat_number ?? '') > 1 ? $this->override_vat_number : preg_replace("/[^a-zA-Z0-9]/", "", $this->invoice->company->settings->vat_number); //todo if we are cross border - switch to the supplier local vat number $pts->CompanyID = $companyID; $ts = new TaxScheme(); @@ -1498,9 +1501,9 @@ class Peppol extends AbstractService $category_id->value = $this->getTaxType($grouped_tax['tax_id']); // Standard rate // Temp fix for reduced tax rate categorization. - if($grouped_tax['tax_rate'] < 15 && $grouped_tax['tax_rate'] >= 0) { - $category_id->value = 'AA'; - } + // if($grouped_tax['tax_rate'] < 15 && $grouped_tax['tax_rate'] >= 0) { + // $category_id->value = 'AA'; + // } $tax_category->ID = $category_id; diff --git a/phpstan.neon b/phpstan.neon index 0b2d3fd189..20d5a7cbdd 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -30,6 +30,7 @@ parameters: - \Stripe\Collection reportUnmatchedIgnoredErrors: false ignoreErrors: + - '#\Saxon\SaxonProcessor#' - '#Array has 2 duplicate keys with value#' - '#Call to an undefined method#' - '#makeHidden#'