From 2ba713eeb84a7b3c70afb13ce8cde9e79a691527 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 16 Aug 2023 19:55:35 +1000 Subject: [PATCH] Refactor for einvoicing --- app/Http/Controllers/InvoiceController.php | 5 +- app/Http/Livewire/PdfSlot.php | 5 +- app/Jobs/Entity/CreateEntityPdf.php | 117 +++++++++++++----- app/Jobs/Entity/CreateRawPdf.php | 110 +++++++++++----- app/Jobs/Invoice/CreateEInvoice.php | 10 +- app/Jobs/Invoice/MergeEInvoice.php | 70 ----------- app/Jobs/Invoice/ZipInvoices.php | 22 +--- app/Models/BaseModel.php | 1 + app/Services/Email/EmailDefaults.php | 6 +- .../Invoice/EInvoice/ZugferdEInvoice.php | 88 ++++++------- app/Services/Invoice/GetInvoiceEInvoice.php | 52 -------- app/Services/Invoice/GetInvoicePdf.php | 6 +- app/Services/Invoice/InvoiceService.php | 21 ++-- 13 files changed, 242 insertions(+), 271 deletions(-) delete mode 100644 app/Jobs/Invoice/MergeEInvoice.php delete mode 100644 app/Services/Invoice/GetInvoiceEInvoice.php diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index ec86da941082..626c22df9acc 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -850,6 +850,7 @@ class InvoiceController extends BaseController $invoice = $invitation->invoice; $file = $invoice->service()->getEInvoice($contact); + $file_name = $invoice->getFileName("xml"); $headers = ['Content-Type' => 'application/xml']; @@ -858,8 +859,8 @@ class InvoiceController extends BaseController } return response()->streamDownload(function () use ($file) { - echo Storage::get($file); - }, basename($file), $headers); + echo $file; + }, $file_name, $headers); } /** diff --git a/app/Http/Livewire/PdfSlot.php b/app/Http/Livewire/PdfSlot.php index 0990ac3ec76d..3a44b5b3a8bd 100644 --- a/app/Http/Livewire/PdfSlot.php +++ b/app/Http/Livewire/PdfSlot.php @@ -12,7 +12,6 @@ namespace App\Http\Livewire; -use App\Services\Invoice\GetInvoiceEInvoice; use App\Utils\Number; use Livewire\Component; use App\Utils\HtmlEngine; @@ -22,10 +21,12 @@ use App\Models\QuoteInvitation; use App\Utils\VendorHtmlEngine; use App\Models\CreditInvitation; use App\Models\InvoiceInvitation; +use App\Jobs\Invoice\CreateEInvoice; use Illuminate\Support\Facades\Cache; use App\Models\PurchaseOrderInvitation; use App\Models\RecurringInvoiceInvitation; use App\Jobs\Vendor\CreatePurchaseOrderPdf; +use App\Services\Invoice\GetInvoiceEInvoice; use App\Services\PdfMaker\Designs\Utilities\DesignHelpers; class PdfSlot extends Component @@ -102,7 +103,7 @@ class PdfSlot extends Component $file_name = $this->entity->numberFormatter().'.xml'; - $file = (new GetInvoiceEInvoice($this->entity))->run(); + $file = (new CreateEInvoice($this->entity))->handle(); $headers = ['Content-Type' => 'application/xml']; diff --git a/app/Jobs/Entity/CreateEntityPdf.php b/app/Jobs/Entity/CreateEntityPdf.php index 6fdf3d7f309e..7ef89d2c3e81 100644 --- a/app/Jobs/Entity/CreateEntityPdf.php +++ b/app/Jobs/Entity/CreateEntityPdf.php @@ -11,38 +11,38 @@ namespace App\Jobs\Entity; -use App\Exceptions\FilePermissionsFailure; -use App\Jobs\Invoice\CreateEInvoice; -use App\Jobs\Invoice\MergeEInvoice; -use App\Libraries\MultiDB; +use App\Utils\Ninja; +use App\Models\Quote; use App\Models\Credit; -use App\Models\CreditInvitation; use App\Models\Design; use App\Models\Invoice; -use App\Models\InvoiceInvitation; -use App\Models\Quote; +use App\Utils\HtmlEngine; +use App\Libraries\MultiDB; +use Illuminate\Bus\Queueable; use App\Models\QuoteInvitation; +use App\Utils\Traits\MakesHash; +use App\Models\CreditInvitation; use App\Models\RecurringInvoice; +use App\Utils\PhantomJS\Phantom; +use App\Models\InvoiceInvitation; +use App\Utils\HostedPDF\NinjaPdf; +use App\Utils\Traits\Pdf\PdfMaker; +use Illuminate\Support\Facades\App; +use App\Jobs\Invoice\CreateEInvoice; +use App\Utils\Traits\NumberFormatter; +use App\Utils\Traits\MakesInvoiceHtml; +use Illuminate\Queue\SerializesModels; +use App\Utils\Traits\Pdf\PageNumbering; +use Illuminate\Support\Facades\Storage; +use Illuminate\Queue\InteractsWithQueue; +use App\Exceptions\FilePermissionsFailure; use App\Models\RecurringInvoiceInvitation; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Bus\Dispatchable; +use horstoeko\zugferd\ZugferdDocumentPdfBuilder; use App\Services\PdfMaker\Design as PdfDesignModel; use App\Services\PdfMaker\Design as PdfMakerDesign; use App\Services\PdfMaker\PdfMaker as PdfMakerService; -use App\Utils\HostedPDF\NinjaPdf; -use App\Utils\HtmlEngine; -use App\Utils\Ninja; -use App\Utils\PhantomJS\Phantom; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\MakesInvoiceHtml; -use App\Utils\Traits\NumberFormatter; -use App\Utils\Traits\Pdf\PageNumbering; -use App\Utils\Traits\Pdf\PdfMaker; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Foundation\Bus\Dispatchable; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Facades\App; -use Illuminate\Support\Facades\Storage; class CreateEntityPdf implements ShouldQueue { @@ -117,7 +117,8 @@ class CreateEntityPdf implements ShouldQueue } $entity_design_id = ''; - + $path = ''; + if ($this->entity instanceof Invoice) { $path = $this->client->invoice_filepath($this->invitation); $entity_design_id = 'invoice_design_id'; @@ -207,6 +208,11 @@ class CreateEntityPdf implements ShouldQueue info($maker->getCompiledHTML()); } + if($this->entity_string == "invoice" && $this->client->getSetting('enable_e_invoice')) + { + $pdf = $this->checkEInvoice($pdf); + } + if ($pdf) { try { Storage::disk($this->disk)->put($file_path, $pdf); @@ -214,11 +220,7 @@ class CreateEntityPdf implements ShouldQueue throw new FilePermissionsFailure($e->getMessage()); } } - if ($this->entity_string == "invoice" && $this->client->getSetting('enable_e_invoice')){ - (new CreateEInvoice($this->entity))->handle(); - (new MergeEInvoice($this->entity))->handle(); - - } + $this->invitation = null; // $this->entity = null; $this->company = null; @@ -227,10 +229,65 @@ class CreateEntityPdf implements ShouldQueue $maker = null; $state = null; - return $file_path; } + /** + * Switch to determine if we need to embed the xml into the PDF itself + * + * @param string $pdf + * @return string + */ + private function checkEInvoice(string $pdf): string + { + if(!$this->entity instanceof Invoice) + return $pdf; + + $e_invoice_type = $this->entity->client->getSetting('e_invoice_type'); + + switch ($e_invoice_type) { + case "EN16931": + case "XInvoice_2_2": + case "XInvoice_2_1": + case "XInvoice_2_0": + case "XInvoice_1_0": + case "XInvoice-Extended": + case "XInvoice-BasicWL": + case "XInvoice-Basic": + return $this->embedEInvoiceZuGFerD($pdf) ?? $pdf; + //case "Facturae_3.2": + //case "Facturae_3.2.1": + //case "Facturae_3.2.2": + // + default: + return $pdf; + } + + } + + /** + * Embed the .xml file into the PDF + * + * @param string $pdf + * @return string + */ + private function embedEInvoiceZuGFerD(string $pdf): string + { + try { + + $e_rechnung = (new CreateEInvoice($this->entity, true))->handle(); + $pdfBuilder = new ZugferdDocumentPdfBuilder($e_rechnung, $pdf); + $pdfBuilder->generateDocument(); + return $pdfBuilder->downloadString(basename($this->entity->getFileName())); + + } catch (\Exception $e) { + nlog("E_Invoice Merge failed - " . $e->getMessage()); + } + + return $pdf; + } + + public function failed($e) { } diff --git a/app/Jobs/Entity/CreateRawPdf.php b/app/Jobs/Entity/CreateRawPdf.php index 8c3b4d77f7f0..921879021c61 100644 --- a/app/Jobs/Entity/CreateRawPdf.php +++ b/app/Jobs/Entity/CreateRawPdf.php @@ -11,42 +11,43 @@ namespace App\Jobs\Entity; -use App\Exceptions\FilePermissionsFailure; -use App\Jobs\Invoice\MergeEInvoice; -use App\Libraries\MultiDB; +use App\Utils\Ninja; +use App\Models\Quote; use App\Models\Credit; -use App\Models\CreditInvitation; use App\Models\Design; use App\Models\Invoice; -use App\Models\InvoiceInvitation; -use App\Models\Quote; +use App\Utils\HtmlEngine; +use App\Libraries\MultiDB; +use Illuminate\Bus\Queueable; use App\Models\QuoteInvitation; +use App\Utils\Traits\MakesHash; +use App\Models\CreditInvitation; use App\Models\RecurringInvoice; +use App\Utils\PhantomJS\Phantom; +use App\Models\InvoiceInvitation; +use App\Utils\HostedPDF\NinjaPdf; +use App\Utils\Traits\Pdf\PdfMaker; +use Illuminate\Support\Facades\App; +use App\Jobs\Invoice\CreateEInvoice; +use App\Utils\Traits\NumberFormatter; +use App\Utils\Traits\MakesInvoiceHtml; +use Illuminate\Queue\SerializesModels; +use App\Utils\Traits\Pdf\PageNumbering; +use Illuminate\Queue\InteractsWithQueue; +use App\Exceptions\FilePermissionsFailure; use App\Models\RecurringInvoiceInvitation; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Bus\Dispatchable; +use horstoeko\zugferd\ZugferdDocumentPdfBuilder; use App\Services\PdfMaker\Design as PdfDesignModel; use App\Services\PdfMaker\Design as PdfMakerDesign; use App\Services\PdfMaker\PdfMaker as PdfMakerService; -use App\Utils\HostedPDF\NinjaPdf; -use App\Utils\HtmlEngine; -use App\Utils\Ninja; -use App\Utils\PhantomJS\Phantom; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\MakesInvoiceHtml; -use App\Utils\Traits\NumberFormatter; -use App\Utils\Traits\Pdf\PageNumbering; -use App\Utils\Traits\Pdf\PdfMaker; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Foundation\Bus\Dispatchable; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Facades\App; class CreateRawPdf implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml, PdfMaker, MakesHash, PageNumbering; - public $entity; + public Invoice | Credit | Quote | RecurringInvoice $entity; public $company; @@ -104,6 +105,7 @@ class CreateRawPdf implements ShouldQueue } $entity_design_id = ''; + $path = ''; if ($this->entity instanceof Invoice) { $path = $this->entity->client->invoice_filepath($this->invitation); @@ -203,17 +205,67 @@ class CreateRawPdf implements ShouldQueue if ($pdf) { $maker =null; $state = null; - if ($this->invitation->invoice->client->getSetting('enable_e_invoice') && $this->entity_string == "invoice"){ - $filename = tempnam(sys_get_temp_dir(), 'InvoiceNinja').".pdf"; - file_put_contents($filename, $pdf); - (new \App\Services\Invoice\MergeEInvoice($this->invitation->invoice, $filename))->run(); - return file_get_contents($filename); - }; - return $pdf; + + return $this->checkEInvoice($pdf); } throw new FilePermissionsFailure('Unable to generate the raw PDF'); } + + /** + * Switch to determine if we need to embed the xml into the PDF itself + * + * @param string $pdf + * @return string + */ + private function checkEInvoice(string $pdf): string + { + if(!$this->entity instanceof Invoice) + return $pdf; + + $e_invoice_type = $this->entity->client->getSetting('e_invoice_type'); + + switch ($e_invoice_type) { + case "EN16931": + case "XInvoice_2_2": + case "XInvoice_2_1": + case "XInvoice_2_0": + case "XInvoice_1_0": + case "XInvoice-Extended": + case "XInvoice-BasicWL": + case "XInvoice-Basic": + return $this->embedEInvoiceZuGFerD($pdf) ?? $pdf; + //case "Facturae_3.2": + //case "Facturae_3.2.1": + //case "Facturae_3.2.2": + // + default: + return $pdf; + } + + } + + /** + * Embed the .xml file into the PDF + * + * @param string $pdf + * @return string + */ + private function embedEInvoiceZuGFerD(string $pdf): string + { + try { + + $e_rechnung = (new CreateEInvoice($this->entity, true))->handle(); + $pdfBuilder = new ZugferdDocumentPdfBuilder($e_rechnung, $pdf); + $pdfBuilder->generateDocument(); + return $pdfBuilder->downloadString(basename($this->entity->getFileName())); + + } catch (\Exception $e) { + nlog("E_Invoice Merge failed - " . $e->getMessage()); + } + + return $pdf; + } public function failed($e) { diff --git a/app/Jobs/Invoice/CreateEInvoice.php b/app/Jobs/Invoice/CreateEInvoice.php index 3988c688b4c8..c68662c4b108 100644 --- a/app/Jobs/Invoice/CreateEInvoice.php +++ b/app/Jobs/Invoice/CreateEInvoice.php @@ -37,7 +37,6 @@ class CreateEInvoice implements ShouldQueue /** * Execute the job. * - * * @return string|ZugferdDocumentBuilder */ public function handle(): string|ZugferdDocumentBuilder @@ -64,13 +63,18 @@ class CreateEInvoice implements ShouldQueue case "XInvoice-Extended": case "XInvoice-BasicWL": case "XInvoice-Basic": - return (new ZugferdEInvoice($this->invoice, $this->returnObject))->run(); + $zugferd = (new ZugferdEInvoice($this->invoice))->run(); + + return $this->returnObject ? $zugferd->xrechnung : $zugferd->getXml(); case "Facturae_3.2": case "Facturae_3.2.1": case "Facturae_3.2.2": return (new FacturaEInvoice($this->invoice, str_replace("Facturae_", "", $e_invoice_type)))->run(); default: - return (new ZugferdEInvoice($this->invoice, $this->returnObject))->run(); + + $zugferd = (new ZugferdEInvoice($this->invoice))->run(); + + return $this->returnObject ? $zugferd : $zugferd->getXml(); } diff --git a/app/Jobs/Invoice/MergeEInvoice.php b/app/Jobs/Invoice/MergeEInvoice.php deleted file mode 100644 index cae7d110682b..000000000000 --- a/app/Jobs/Invoice/MergeEInvoice.php +++ /dev/null @@ -1,70 +0,0 @@ -invoice->client->getSetting('e_invoice_type'); - switch ($e_invoice_type) { - case "EN16931": - case "XInvoice_2_2": - case "XInvoice_2_1": - case "XInvoice_2_0": - case "XInvoice_1_0": - case "XInvoice-Extended": - case "XInvoice-BasicWL": - case "XInvoice-Basic": - $this->embedEInvoiceZuGFerD(); - //case "Facturae_3.2": - //case "Facturae_3.2.1": - //case "Facturae_3.2.2": - // - default: - $this->embedEInvoiceZuGFerD(); - break; - } - } - - /** - * @throws \Exception - */ - private function embedEInvoiceZuGFerD(): void - { - try { - $filepath_pdf = !empty($this->pdf_path) ? $this->pdf_path : $this->invoice->service()->getInvoicePdf(); - $disk = config('filesystems.default'); - $e_rechnung = (new CreateEInvoice($this->invoice, true))->handle(); - if (!empty($this->pdf_path)) { - $realpath_pdf = $filepath_pdf; - } else { - $realpath_pdf = Storage::disk($disk)->path($filepath_pdf); - } - if (file_exists($realpath_pdf)) { - $pdfBuilder = new ZugferdDocumentPdfBuilder($e_rechnung, $realpath_pdf); - $pdfBuilder->generateDocument(); - $pdfBuilder->saveDocument($realpath_pdf); - } else { - nlog("E_Invoice Merge failed - file to merge not found"); - } - - } catch (\Exception $e) { - nlog("E_Invoice Merge failed - " . $e->getMessage()); - } - } -} diff --git a/app/Jobs/Invoice/ZipInvoices.php b/app/Jobs/Invoice/ZipInvoices.php index c257e647ccb8..25722b6f6fb2 100644 --- a/app/Jobs/Invoice/ZipInvoices.php +++ b/app/Jobs/Invoice/ZipInvoices.php @@ -73,28 +73,12 @@ class ZipInvoices implements ShouldQueue $invitation = $this->invoices->first()->invitations->first(); $path = $this->invoices->first()->client->invoice_filepath($invitation); - $this->invoices->each(function ($invoice) { - (new CreateEntityPdf($invoice->invitations()->first()))->handle(); - if ($invoice->client->getSetting('enable_e_invoice')){ - (new CreateEInvoice($invoice))->handle(); - (new MergeEInvoice($invoice))->handle(); - } - }); - try { foreach ($this->invoices as $invoice) { - $file = $invoice->service()->getInvoicePdf(); - $zip_file_name = basename($file); - $zipFile->addFromString($zip_file_name, Storage::get($file)); - - if($invoice->client->getSetting('enable_e_invoice')){ - - $xinvoice = $invoice->service()->getEInvoice(); - $xinvoice_zip_file_name = basename($xinvoice); - $zipFile->addFromString($xinvoice_zip_file_name, Storage::get($xinvoice)); - - } + $file = $invoice->service()->getRawInvoicePdf(); + $zip_file_name = $invoice->getFileName(); + $zipFile->addFromString($zip_file_name, $file); } Storage::put($path.$file_name, $zipFile->outputAsString()); diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php index 7f8c0d4bca69..bd55d0684203 100644 --- a/app/Models/BaseModel.php +++ b/app/Models/BaseModel.php @@ -276,6 +276,7 @@ class BaseModel extends Model /** * Returns the base64 encoded PDF string of the entity + * @deprecated - unused implementation */ public function fullscreenPdfViewer($invitation = null): string { diff --git a/app/Services/Email/EmailDefaults.php b/app/Services/Email/EmailDefaults.php index a374ddfa353c..e2d833fa9e31 100644 --- a/app/Services/Email/EmailDefaults.php +++ b/app/Services/Email/EmailDefaults.php @@ -322,10 +322,10 @@ class EmailDefaults } /** E-Invoice xml file */ if ($this->email->email_object->settings->enable_e_invoice && $this->email->email_object->entity instanceof Invoice) { - $xinvoice_path = $this->email->email_object->entity->service()->getEInvoice(); + $xml_string = $this->email->email_object->entity->service()->getEInvoice(); - if(Storage::disk(config('filesystems.default'))->exists($xinvoice_path)) - $this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode(Storage::get($xinvoice_path)), 'name' => explode(".", $this->email->email_object->entity->getFileName('xml'))[0]."-e_invoice.xml"]]); + if($xml_string) + $this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode($xml_string), 'name' => explode(".", $this->email->email_object->entity->getFileName('xml'))[0]."-e_invoice.xml"]]); } if (!$this->email->email_object->settings->document_email_attachment || !$this->email->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) { diff --git a/app/Services/Invoice/EInvoice/ZugferdEInvoice.php b/app/Services/Invoice/EInvoice/ZugferdEInvoice.php index 3baf14128f8b..0410422a4d7e 100644 --- a/app/Services/Invoice/EInvoice/ZugferdEInvoice.php +++ b/app/Services/Invoice/EInvoice/ZugferdEInvoice.php @@ -22,12 +22,13 @@ use horstoeko\zugferd\codelists\ZugferdDutyTaxFeeCategories; class ZugferdEInvoice extends AbstractService { + public ZugferdDocumentBuilder $xrechnung; public function __construct(public Invoice $invoice, private readonly bool $returnObject = false, private array $tax_map = []) { } - public function run(): string|ZugferdDocumentBuilder + public function run(): self { $company = $this->invoice->company; @@ -45,10 +46,9 @@ class ZugferdEInvoice extends AbstractService default => ZugferdProfiles::PROFILE_EN16931, }; + $this->xrechnung = ZugferdDocumentBuilder::CreateNew($profile); - $xrechnung = ZugferdDocumentBuilder::CreateNew($profile); - - $xrechnung + $this->xrechnung ->setDocumentSupplyChainEvent(date_create($this->invoice->date)) ->setDocumentSeller($company->getSetting('name')) ->setDocumentSellerAddress($company->getSetting("address1"), $company->getSetting("address2"), "", $company->getSetting("postal_code"), $company->getSetting("city"), $company->country()->iso_3166_2, $company->getSetting("state")) @@ -59,32 +59,32 @@ class ZugferdEInvoice extends AbstractService ->addDocumentPaymentTerm(ctrans("texts.xinvoice_payable", ['payeddue' => date_create($this->invoice->date)->diff(date_create($this->invoice->due_date))->format("%d"), 'paydate' => $this->invoice->due_date])); if (!empty($this->invoice->public_notes)) { - $xrechnung->addDocumentNote($this->invoice->public_notes); + $this->xrechnung->addDocumentNote($this->invoice->public_notes); } if (empty($this->invoice->number)){ - $xrechnung->setDocumentInformation("DRAFT", "380", date_create($this->invoice->date), $this->invoice->client->getCurrencyCode()); + $this->xrechnung->setDocumentInformation("DRAFT", "380", date_create($this->invoice->date), $this->invoice->client->getCurrencyCode()); } else { - $xrechnung->setDocumentInformation($this->invoice->number, "380", date_create($this->invoice->date), $this->invoice->client->getCurrencyCode()); + $this->xrechnung->setDocumentInformation($this->invoice->number, "380", date_create($this->invoice->date), $this->invoice->client->getCurrencyCode()); } if (!empty($this->invoice->po_number)) { - $xrechnung->setDocumentBuyerOrderReferencedDocument($this->invoice->po_number); + $this->xrechnung->setDocumentBuyerOrderReferencedDocument($this->invoice->po_number); } if (empty($client->routing_id)) { - $xrechnung->setDocumentBuyerReference(ctrans("texts.xinvoice_no_buyers_reference")); + $this->xrechnung->setDocumentBuyerReference(ctrans("texts.xinvoice_no_buyers_reference")); } else { - $xrechnung->setDocumentBuyerReference($client->routing_id); + $this->xrechnung->setDocumentBuyerReference($client->routing_id); } if (!empty($client->shipping_address1)){ - $xrechnung->setDocumentShipToAddress($client->shipping_address1, $client->shipping_address2, "", $client->shipping_postal_code, $client->shipping_city, $client->shipping_country->iso_3166_2, $client->shipping_state); + $this->xrechnung->setDocumentShipToAddress($client->shipping_address1, $client->shipping_address2, "", $client->shipping_postal_code, $client->shipping_city, $client->shipping_country->iso_3166_2, $client->shipping_state); } - $xrechnung->addDocumentPaymentMean(68, ctrans("texts.xinvoice_online_payment")); + $this->xrechnung->addDocumentPaymentMean(68, ctrans("texts.xinvoice_online_payment")); if (str_contains($company->getSetting('vat_number'), "/")) { - $xrechnung->addDocumentSellerTaxRegistration("FC", $company->getSetting('vat_number')); + $this->xrechnung->addDocumentSellerTaxRegistration("FC", $company->getSetting('vat_number')); } else { - $xrechnung->addDocumentSellerTaxRegistration("VA", $company->getSetting('vat_number')); + $this->xrechnung->addDocumentSellerTaxRegistration("VA", $company->getSetting('vat_number')); } $invoicing_data = $this->invoice->calc(); @@ -92,29 +92,29 @@ class ZugferdEInvoice extends AbstractService //Create line items and calculate taxes foreach ($this->invoice->line_items as $index => $item) { /** @var \App\DataMapper\InvoiceItem $item **/ - $xrechnung->addNewPosition($index) + $this->xrechnung->addNewPosition($index) ->setDocumentPositionGrossPrice($item->gross_line_total) ->setDocumentPositionNetPrice($item->line_total); if (!empty($item->product_key)){ if (!empty($item->notes)){ - $xrechnung->setDocumentPositionProductDetails($item->product_key, $item->notes); + $this->xrechnung->setDocumentPositionProductDetails($item->product_key, $item->notes); } else { - $xrechnung->setDocumentPositionProductDetails($item->product_key); + $this->xrechnung->setDocumentPositionProductDetails($item->product_key); } } else { if (!empty($item->notes)){ - $xrechnung->setDocumentPositionProductDetails($item->notes); + $this->xrechnung->setDocumentPositionProductDetails($item->notes); } else { - $xrechnung->setDocumentPositionProductDetails("no product name defined"); + $this->xrechnung->setDocumentPositionProductDetails("no product name defined"); } } if (isset($item->task_id)) { - $xrechnung->setDocumentPositionQuantity($item->quantity, "HUR"); + $this->xrechnung->setDocumentPositionQuantity($item->quantity, "HUR"); } else { - $xrechnung->setDocumentPositionQuantity($item->quantity, "H87"); + $this->xrechnung->setDocumentPositionQuantity($item->quantity, "H87"); } $linenetamount = $item->line_total; if ($item->discount > 0) { @@ -124,18 +124,18 @@ class ZugferdEInvoice extends AbstractService $linenetamount -= $linenetamount * ($item->discount / 100); } } - $xrechnung->setDocumentPositionLineSummation($linenetamount); + $this->xrechnung->setDocumentPositionLineSummation($linenetamount); // According to european law, each line item can only have one tax rate if (!(empty($item->tax_name1) && empty($item->tax_name2) && empty($item->tax_name3))) { $taxtype = $this->getTaxType($item->tax_id); if (!empty($item->tax_name1)) { - $xrechnung->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate1); + $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate1); $this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate1); } elseif (!empty($item->tax_name2)) { - $xrechnung->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate2); + $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate2); $this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate2); } elseif (!empty($item->tax_name3)) { - $xrechnung->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate3); + $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $item->tax_rate3); $this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate3); } else { nlog("Can't add correct tax position"); @@ -143,45 +143,45 @@ class ZugferdEInvoice extends AbstractService } else { if (!empty($this->invoice->tax_name1)) { $taxtype = $this->getTaxType($this->invoice->tax_name1); - $xrechnung->addDocumentPositionTax($taxtype, 'VAT', $this->invoice->tax_rate1); + $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $this->invoice->tax_rate1); $this->addtoTaxMap($taxtype, $linenetamount, $this->invoice->tax_rate1); } elseif (!empty($this->invoice->tax_name2)) { $taxtype = $this->getTaxType($this->invoice->tax_name2); - $xrechnung->addDocumentPositionTax($taxtype, 'VAT', $this->invoice->tax_rate2); + $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $this->invoice->tax_rate2); $this->addtoTaxMap($taxtype, $linenetamount, $this->invoice->tax_rate2); } elseif (!empty($this->invoice->tax_name3)) { $taxtype = $this->getTaxType($this->invoice->tax_name3); - $xrechnung->addDocumentPositionTax($taxtype, 'VAT', $this->invoice->tax_rate3); + $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', $this->invoice->tax_rate3); $this->addtoTaxMap($taxtype, $linenetamount, $this->invoice->tax_rate3); } else { $taxtype = ZugferdDutyTaxFeeCategories::ZERO_RATED_GOODS; - $xrechnung->addDocumentPositionTax($taxtype, 'VAT', 0); + $this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', 0); $this->addtoTaxMap($taxtype, $linenetamount, 0); nlog("Can't add correct tax position"); } } } - $xrechnung->setDocumentSummation($this->invoice->amount, $this->invoice->balance, $invoicing_data->getSubTotal(), $invoicing_data->getTotalSurcharges(), $invoicing_data->getTotalDiscount(), $invoicing_data->getSubTotal(), $invoicing_data->getItemTotalTaxes(), 0.0, $this->invoice->amount-$this->invoice->balance); + $this->xrechnung->setDocumentSummation($this->invoice->amount, $this->invoice->balance, $invoicing_data->getSubTotal(), $invoicing_data->getTotalSurcharges(), $invoicing_data->getTotalDiscount(), $invoicing_data->getSubTotal(), $invoicing_data->getItemTotalTaxes(), 0.0, $this->invoice->amount-$this->invoice->balance); foreach ($this->tax_map as $item){ - $xrechnung->addDocumentTax($item["tax_type"], "VAT", $item["net_amount"], $item["tax_rate"]*$item["net_amount"], $item["tax_rate"]*100); - } - $disk = config('filesystems.default'); - - if (!Storage::disk($disk)->exists($client->e_invoice_filepath($this->invoice->invitations->first()))) { - Storage::makeDirectory($client->e_invoice_filepath($this->invoice->invitations->first())); + $this->xrechnung->addDocumentTax($item["tax_type"], "VAT", $item["net_amount"], $item["tax_rate"]*$item["net_amount"], $item["tax_rate"]*100); } - $xrechnung->writeFile(Storage::disk($disk)->path($client->e_invoice_filepath($this->invoice->invitations->first()) . $this->invoice->getFileName("xml"))); // The validity can be checked using https://portal3.gefeg.com/invoice/validation or https://e-rechnung.bayern.de/app/#/upload - if ($this->returnObject){ - return $xrechnung; - } - - throw new \Exception("Invalid e invoice object"); - - // return $client->e_invoice_filepath($this->invoice->invitations->first()) . $this->invoice->getFileName("xml"); + return $this; + + } + + /** + * Returns the XML document + * in string format + * + * @return string + */ + public function getXml(): string + { + return $this->xrechnung->getContent(); } private function getTaxType($name): string diff --git a/app/Services/Invoice/GetInvoiceEInvoice.php b/app/Services/Invoice/GetInvoiceEInvoice.php deleted file mode 100644 index 0434b6917fd0..000000000000 --- a/app/Services/Invoice/GetInvoiceEInvoice.php +++ /dev/null @@ -1,52 +0,0 @@ -contact) { - $this->contact = $this->invoice->client->primary_contact()->first() ?: $this->invoice->client->contacts()->first(); - } - - $invitation = $this->invoice->invitations->where('client_contact_id', $this->contact->id)->first(); - - if (! $invitation) { - $invitation = $this->invoice->invitations->first(); - } - - $file_path = $this->invoice->client->e_invoice_filepath($this->invoice->invitations->first()). $this->invoice->getFileName("xml"); - - // $disk = 'public'; - $disk = config('filesystems.default'); - - $file = Storage::disk($disk)->exists($file_path); - - if (! $file) { - $file_path = (new CreateEInvoice($this->invoice))->handle(); - (new \App\Jobs\Invoice\MergeEInvoice($this->invoice))->handle(); - - } - return $file_path; - } -} diff --git a/app/Services/Invoice/GetInvoicePdf.php b/app/Services/Invoice/GetInvoicePdf.php index 8044e8a290d6..9211a15bb8fd 100644 --- a/app/Services/Invoice/GetInvoicePdf.php +++ b/app/Services/Invoice/GetInvoicePdf.php @@ -13,7 +13,6 @@ namespace App\Services\Invoice; use App\Jobs\Entity\CreateEntityPdf; use App\Jobs\Invoice\CreateEInvoice; -use App\Jobs\Invoice\MergeEInvoice; use App\Models\ClientContact; use App\Models\Invoice; use App\Services\AbstractService; @@ -49,10 +48,7 @@ class GetInvoicePdf extends AbstractService if (! $file) { $file_path = (new CreateEntityPdf($invitation))->handle(); } - if ($this->invoice->client->getSetting('enable_e_invoice')){ - (new CreateEInvoice($this->invoice))->handle(); - (new MergeEInvoice($this->invoice, $file_path))->handle(); - } + return $file_path; } } diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index d350d28a597c..148f0cae88d5 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -13,6 +13,7 @@ namespace App\Services\Invoice; use App\Events\Invoice\InvoiceWasArchived; use App\Jobs\Entity\CreateEntityPdf; +use App\Jobs\Entity\CreateRawPdf; use App\Jobs\Inventory\AdjustProductInventory; use App\Jobs\Invoice\CreateEInvoice; use App\Libraries\Currency\Conversion\CurrencyApi; @@ -187,6 +188,13 @@ class InvoiceService return (new GetInvoicePdf($this->invoice, $contact))->run(); } + public function getRawInvoicePdf($contact = null) + { + $invitation = $contact ? $this->invoice->invitations()->where('contact_id', $contact->id)->first() : $this->invoice->invitations()->first(); + + return (new CreateRawPdf($invitation, $invitation->company->db))->handle(); + } + public function getInvoiceDeliveryNote(Invoice $invoice, \App\Models\ClientContact $contact = null) { return (new GenerateDeliveryNote($invoice, $contact))->run(); @@ -194,13 +202,9 @@ class InvoiceService public function getEInvoice($contact = null) { - return (new GetInvoiceEInvoice($this->invoice, $contact))->run(); + return (new CreateEInvoice($this->invoice))->handle(); } - public function mergeEInvoice($contact = null): void - { - (new MergeEInvoice($this->invoice, $contact))->run(); - } public function sendEmail($contact = null) { $send_email = new SendEmail($this->invoice, null, $contact); @@ -464,13 +468,6 @@ class InvoiceService if ($force) { $this->invoice->invitations->each(function ($invitation) { (new CreateEntityPdf($invitation))->handle(); - - if ($invitation->invoice->client->getSetting('enable_e_invoice') && $invitation instanceof InvoiceInvitation) - { - (new CreateEInvoice($invitation->invoice))->handle(); - (new MergeEInvoice($invitation->invoice))->run(); - } - }); return $this;