From d2b5f6902cb7fd585e38605ff6d7191023e722ff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Nov 2025 12:32:44 +0000 Subject: [PATCH 1/3] Initial plan From 87edec399fee1d5bc4b9de2f8ab78b86a6e1a9a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Nov 2025 12:45:35 +0000 Subject: [PATCH 2/3] Add RegimeType enum for VAT regime keys (ClaveRegimen) Co-authored-by: Eseperio <5459366+Eseperio@users.noreply.github.com> --- README.md | 3 + src/models/BreakdownDetail.php | 11 ++- src/models/enums/RegimeType.php | 114 +++++++++++++++++++++++++++++ src/services/InvoiceSerializer.php | 2 +- 4 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 src/models/enums/RegimeType.php diff --git a/README.md b/README.md index 10bb4a1..5025c23 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ use eseperio\verifactu\models\enums\TaxType; use eseperio\verifactu\models\enums\YesNoType; use eseperio\verifactu\models\enums\HashType; use eseperio\verifactu\models\enums\OperationQualificationType; +use eseperio\verifactu\models\enums\RegimeType; // After calling Verifactu::config(...) @@ -150,6 +151,7 @@ $invoice->invoiceWithoutRecipient = YesNoType::NO; $breakdown = new Breakdown(); $detail = new BreakdownDetail(); $detail->taxType = TaxType::IVA; +$detail->regimeKey = RegimeType::GENERAL; // General regime operation $detail->taxRate = 21.00; $detail->taxableBase = 100.00; $detail->taxAmount = 21.00; @@ -609,6 +611,7 @@ The library uses enum classes for type-safe constants: * **OperationQualificationType:** Tax operation qualifications * **PeriodType:** Month or quarter periods * **RectificationType:** Types of invoice rectifications +* **RegimeType:** Special regime keys for VAT (ClaveRegimen) - General regime, exports, travel agencies, cash basis, etc. * **YesNoType:** Yes/No values for boolean fields * **GeneratorType:** Invoice generator types * **ThirdPartyOrRecipientType:** Types of third parties or recipients diff --git a/src/models/BreakdownDetail.php b/src/models/BreakdownDetail.php index a3d5178..cb99630 100644 --- a/src/models/BreakdownDetail.php +++ b/src/models/BreakdownDetail.php @@ -6,6 +6,7 @@ use eseperio\verifactu\models\enums\ExemptOperationType; use eseperio\verifactu\models\enums\OperationQualificationType; +use eseperio\verifactu\models\enums\RegimeType; use eseperio\verifactu\models\enums\TaxType; /** @@ -24,7 +25,7 @@ class BreakdownDetail extends Model /** * Regime key (ClaveRegimen, optional). - * @var string|null + * @var RegimeType|null */ public $regimeKey; @@ -83,7 +84,6 @@ public function rules(): array { return [ [['taxableBase'], 'required'], - [['regimeKey'], 'string'], [['taxRate', 'taxableBase', 'costBasedTaxableBase', 'taxAmount', 'equivalenceSurchargeRate', 'equivalenceSurchargeAmount'], fn($value): bool|string => (is_null($value) || is_float($value) || is_int($value)) ? true : 'Must be a number or null.'], [['operationQualification', 'exemptOperation'], function ($value, $model): string|bool { // Either operationQualification or exemptOperation must be set @@ -100,6 +100,13 @@ public function rules(): array return ($value instanceof TaxType) ? true : 'Must be an instance of TaxType.'; }], + ['regimeKey', function ($value): bool|string { + if ($value === null) { + return true; + } + + return ($value instanceof RegimeType) ? true : 'Must be an instance of RegimeType.'; + }], ['operationQualification', function ($value): bool|string { if ($value === null) { return true; diff --git a/src/models/enums/RegimeType.php b/src/models/enums/RegimeType.php new file mode 100644 index 0000000..d37a9fd --- /dev/null +++ b/src/models/enums/RegimeType.php @@ -0,0 +1,114 @@ +regimeKey)) { - $detalleDesglose->appendChild($doc->createElementNS(self::SF_NAMESPACE, 'sf:ClaveRegimen', (string) $detail->regimeKey)); + $detalleDesglose->appendChild($doc->createElementNS(self::SF_NAMESPACE, 'sf:ClaveRegimen', (string) $detail->regimeKey->value)); } // Either CalificacionOperacion or OperacionExenta (one is required) From 11e2a9dea4aa60ec04ca196739a854c026272f26 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Nov 2025 12:46:38 +0000 Subject: [PATCH 3/3] Make regimeKey null check consistent with other enum checks Co-authored-by: Eseperio <5459366+Eseperio@users.noreply.github.com> --- src/services/InvoiceSerializer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/InvoiceSerializer.php b/src/services/InvoiceSerializer.php index 8af2b90..685b1a7 100644 --- a/src/services/InvoiceSerializer.php +++ b/src/services/InvoiceSerializer.php @@ -214,7 +214,7 @@ public static function toInvoiceXml(InvoiceSubmission $invoice, bool $validate = } // ClaveRegimen (optional) - if (!empty($detail->regimeKey)) { + if ($detail->regimeKey) { $detalleDesglose->appendChild($doc->createElementNS(self::SF_NAMESPACE, 'sf:ClaveRegimen', (string) $detail->regimeKey->value)); }