diff --git a/app/Filters/PaymentFilters.php b/app/Filters/PaymentFilters.php index 6d6fe844f927..550af5850e84 100644 --- a/app/Filters/PaymentFilters.php +++ b/app/Filters/PaymentFilters.php @@ -36,7 +36,7 @@ class PaymentFilters extends QueryFilters $query->where('amount', 'like', '%'.$filter.'%') ->orWhere('date', 'like', '%'.$filter.'%') ->orWhere('number','like', '%'.$filter.'%') - ->owWhere('transaction_reference', 'like', '%'.$filter.'%') + ->orWhere('transaction_reference', 'like', '%'.$filter.'%') ->orWhere('custom_value1', 'like', '%'.$filter.'%') ->orWhere('custom_value2', 'like', '%'.$filter.'%') ->orWhere('custom_value3', 'like', '%'.$filter.'%') diff --git a/app/Models/Company.php b/app/Models/Company.php index 5b6c849a3bf4..f4aff444c365 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -98,7 +98,6 @@ use Laracasts\Presenter\PresentableTrait; * @property string|null $matomo_url * @property int|null $matomo_id * @property bool $enable_e_invoice - * @property string $e_invoice_type * @property int $enabled_expense_tax_rates * @property int $invoice_task_project * @property int $report_include_deleted diff --git a/app/Services/Invoice/EInvoice/FacturaE.php b/app/Services/Invoice/EInvoice/FacturaE.php new file mode 100644 index 000000000000..54c8a5f3b2c4 --- /dev/null +++ b/app/Services/Invoice/EInvoice/FacturaE.php @@ -0,0 +1,270 @@ +setNumber('', $this->invoice->number); + $fac->setIssueDate($this->invoice->date); + $fac->setBuyer($this->buildBuyer()); + $fac->setSeller($this->buildSeller()); + $fac = $this->buildItems($fac); + + } + + private function buildItems(Facturae $fac): Facturae + { + + foreach($this->invoice->line_items as $item) + { + $fac->addItem(new FacturaeItem([ + 'description' => $item->notes, + 'quantity' => $item->quantity, + 'unitPrice' => $item->cost, + 'discountsAndRebates' => $item->discount, + 'charges' => 0, + 'taxes' => $this->buildRatesForItem($item), + 'specialTaxableEvent' => FacturaeItem::SPECIAL_TAXABLE_EVENT_NON_SUBJECT, + 'specialTaxableEventReason' => '', + 'specialTaxableEventReasonDescription' => '', + ])); + + } + + return $fac; + + } + + private function buildRatesForItem(\stdClass $item): array + { + $data = []; + + if (strlen($item->tax_name1) > 1) { + + $data[] = [$this->resolveTaxCode($item->tax_name1) => $item->tax_rate1]; + + } + + if (strlen($item->tax_name2) > 1) { + + $data[] = [$this->resolveTaxCode($item->tax_name2) => $item->tax_rate2]; + + } + + if (strlen($item->tax_name3) > 1) { + + $data[] = [$this->resolveTaxCode($item->tax_name3) => $item->tax_rate3]; + + } + + return $data; + } + + private function resolveTaxCode(string $tax_name) + { + return match (strtoupper($tax_name)) { + 'IVA' => Facturae::TAX_IVA, + 'IPSI' => Facturae::TAX_IPSI, + 'IGIC' => Facturae::TAX_IGIC, + 'IRPF' => Facturae::TAX_IRPF, + 'IRNR' => Facturae::TAX_IRNR, + 'ISS' => Facturae::TAX_ISS, + 'REIVA' => Facturae::TAX_REIVA, + 'REIGIC' => Facturae::TAX_REIGIC, + 'REIPSI' => Facturae::TAX_REIPSI, + 'IPS' => Facturae::TAX_IPS, + 'RLEA' => Facturae::TAX_RLEA, + 'IVPEE' => Facturae::TAX_IVPEE, + 'IPCNG' => Facturae::TAX_IPCNG, + 'IACNG' => Facturae::TAX_IACNG, + 'IDEC' => Facturae::TAX_IDEC, + 'ILTCAC' => Facturae::TAX_ILTCAC, + 'IGFEI' => Facturae::TAX_IGFEI, + 'ISS' => Facturae::TAX_ISS, + 'IMGSN' => Facturae::TAX_IMGSN, + 'IMSN' => Facturae::TAX_IMSN, + 'IMPN' => Facturae::TAX_IMPN, + 'IIIMAB' => Facturae::TAX_IIIMAB, + 'ICIO' => Facturae::TAX_ICIO, + 'IECDPCAC' => Facturae::TAX_IECDPCAC, + 'IGTECM' => Facturae::TAX_IGTECM, + 'IE' => Facturae::TAX_IE, + 'RA' => Facturae::TAX_RA, + 'ITPAJD' => Facturae::TAX_ITPAJD, + 'OTHER' => Facturae::TAX_OTHER, + 'IMVDN' => Facturae::TAX_IMVDN, + default => Facturae::TAX_IVA, + + }; + } + + private function buildSeller(): FacturaeParty + { + $company = $this->invoice->company; + + $seller = new FacturaeParty([ + "isLegalEntity" => true, // Se asume true si se omite + "taxNumber" => $company->settings->vat_number, + "name" => $company->present()->name(), + "address" => $company->settings->address1, + "postCode" => $company->settings->postal_code, + "town" => $company->settings->city, + "province" => $company->settings->state, + "countryCode" => $company->country()->iso_3166_3, // Se asume España si se omite + "book" => "0", // Libro + "merchantRegister" => "RG", // Registro Mercantil + "sheet" => "1", // Hoja + "folio" => "2", // Folio + "section" => "3", // Sección + "volume" => "4", // Tomo + "email" => $company->settings->email, + "phone" => $company->settings->phone, + "fax" => "", + "website" => $company->settings->website, + "contactPeople" => $company->owner()->present()->name(), + // "cnoCnae" => "04647", // Clasif. Nacional de Act. Económicas + // "ineTownCode" => "280796" // Cód. de municipio del INE + ]); + + return $seller; + } + + private function buildBuyer(): FacturaeParty + { + + $buyer = new FacturaeParty([ + "isLegalEntity" => $this->invoice->client->has_valid_vat_number, + "taxNumber" => $this->invoice->client->vat_number, + "name" => $this->invoice->client->present()->name(), + "firstSurname" => $this->invoice->client->present()->first_name(), + "lastSurname" => $this->invoice->client->present()->last_name(), + "address" => $this->invoice->client->address1, + "postCode" => $this->invoice->client->postal_code, + "town" => $this->invoice->client->city, + "province" => $this->invoice->client->state, + "countryCode" => $this->invoice->client->country->iso_3166_3, // Se asume España si se omite + "email" => $this->invoice->client->present()->email(), + "phone" => $this->invoice->client->present()->phone(), + "fax" => "", + "website" => $this->invoice->client->present()->website(), + "contactPeople" => $this->invoice->client->present()->first_name()." ".$this->invoice->client->present()->last_name(), + // "cnoCnae" => "04791", // Clasif. Nacional de Act. Económicas + // "ineTownCode" => "280796" // Cód. de municipio del INE + ]); + + return $buyer; + } + +} \ No newline at end of file diff --git a/composer.json b/composer.json index 55098e1af312..5df1d2c211cc 100644 --- a/composer.json +++ b/composer.json @@ -53,9 +53,11 @@ "halaxa/json-machine": "^0.7.0", "hashids/hashids": "^4.0", "hedii/laravel-gelf-logger": "^7.0", + "horstoeko/zugferd": "^1", "imdhemy/laravel-purchases": "^1.7", "intervention/image": "^2.5", "invoiceninja/inspector": "^1.0", + "josemmo/facturae-php": "^1.7", "laracasts/presenter": "^0.2.1", "laravel/framework": "^9.3", "laravel/slack-notification-channel": "^2.2", @@ -91,7 +93,6 @@ "turbo124/predis": "1.1.11", "twilio/sdk": "^6.40", "webpatser/laravel-countries": "dev-master#75992ad", - "horstoeko/zugferd":"^1", "wepay/php-sdk": "^0.3" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 3cca89da5501..0ee6552a5c38 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "732ddc1c902c8a5a0412d8424df2ba6a", + "content-hash": "7482363bb2c3f9f8fb07bbd3d517597b", "packages": [ { "name": "adrienrn/php-mimetyper", @@ -4026,6 +4026,63 @@ ], "time": "2023-02-17T17:40:48+00:00" }, + { + "name": "josemmo/facturae-php", + "version": "v1.7.6", + "source": { + "type": "git", + "url": "https://github.com/josemmo/Facturae-PHP.git", + "reference": "fb876dd4b4515e0cd85b1be61f676bfee9a80f65" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/josemmo/Facturae-PHP/zipball/fb876dd4b4515e0cd85b1be61f676bfee9a80f65", + "reference": "fb876dd4b4515e0cd85b1be61f676bfee9a80f65", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "symfony/phpunit-bridge": "*" + }, + "suggest": { + "ext-curl": "For communicating with remote TSA Servers and SOAP Web Services", + "ext-fileinfo": "For getting MIME types when using FacturaeFile", + "ext-openssl": "For signing and timestamping both invoices and SOAP requests", + "lib-libxml": "For parsing SOAP XML responses for FACe and FACeB2B" + }, + "type": "library", + "autoload": { + "psr-4": { + "josemmo\\Facturae\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "josemmo", + "email": "josemmo@pm.me", + "homepage": "https://github.com/josemmo" + } + ], + "description": "Librería para la generación, firma y envío de facturas electrónicas", + "homepage": "https://github.com/josemmo/Facturae-PHP", + "keywords": [ + "face", + "faceb2b", + "facturae", + "xades" + ], + "support": { + "issues": "https://github.com/josemmo/Facturae-PHP/issues", + "source": "https://github.com/josemmo/Facturae-PHP/tree/v1.7.6" + }, + "time": "2023-03-25T10:09:02+00:00" + }, { "name": "khanamiryan/qrcode-detector-decoder", "version": "1.0.6",