mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge pull request #8722 from turbo124/v5-develop
Refactor for e-invoicing
This commit is contained in:
commit
5e955567b1
@ -35,6 +35,7 @@ use App\Models\BankTransaction;
|
|||||||
use App\Models\QuoteInvitation;
|
use App\Models\QuoteInvitation;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use App\Models\CreditInvitation;
|
use App\Models\CreditInvitation;
|
||||||
|
use App\Models\RecurringInvoice;
|
||||||
use App\Models\InvoiceInvitation;
|
use App\Models\InvoiceInvitation;
|
||||||
use App\DataMapper\ClientSettings;
|
use App\DataMapper\ClientSettings;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
@ -61,8 +61,13 @@ class InvoiceItem
|
|||||||
|
|
||||||
public $tax_id = '';
|
public $tax_id = '';
|
||||||
|
|
||||||
|
public $task_id = '';
|
||||||
|
|
||||||
|
public $expense_id = '';
|
||||||
|
|
||||||
public static $casts = [
|
public static $casts = [
|
||||||
|
'task_id' => 'string',
|
||||||
|
'expense_id' => 'string',
|
||||||
'tax_id' => 'string',
|
'tax_id' => 'string',
|
||||||
'type_id' => 'string',
|
'type_id' => 'string',
|
||||||
'quantity' => 'float',
|
'quantity' => 'float',
|
||||||
|
@ -252,11 +252,20 @@ class InvoiceController extends Controller
|
|||||||
// create new archive
|
// create new archive
|
||||||
$zipFile = new \PhpZip\ZipFile();
|
$zipFile = new \PhpZip\ZipFile();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
foreach ($invoices as $invoice) {
|
foreach ($invoices as $invoice) {
|
||||||
//add it to the zip
|
|
||||||
$zipFile->addFromString(basename($invoice->pdf_file_path()), file_get_contents($invoice->pdf_file_path(null, 'url', true)));
|
if ($invoice->client->getSetting('enable_e_invoice')) {
|
||||||
|
$xml = $invoice->service()->getEInvoice();
|
||||||
|
$zipFile->addFromString($invoice->getFileName("xml"), $xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $invoice->service()->getRawInvoicePdf();
|
||||||
|
$zip_file_name = $invoice->getFileName();
|
||||||
|
$zipFile->addFromString($zip_file_name, $file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$filename = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip';
|
$filename = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip';
|
||||||
$filepath = sys_get_temp_dir().'/'.$filename;
|
$filepath = sys_get_temp_dir().'/'.$filename;
|
||||||
|
|
||||||
|
@ -850,6 +850,7 @@ class InvoiceController extends BaseController
|
|||||||
$invoice = $invitation->invoice;
|
$invoice = $invitation->invoice;
|
||||||
|
|
||||||
$file = $invoice->service()->getEInvoice($contact);
|
$file = $invoice->service()->getEInvoice($contact);
|
||||||
|
$file_name = $invoice->getFileName("xml");
|
||||||
|
|
||||||
$headers = ['Content-Type' => 'application/xml'];
|
$headers = ['Content-Type' => 'application/xml'];
|
||||||
|
|
||||||
@ -858,8 +859,8 @@ class InvoiceController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
return response()->streamDownload(function () use ($file) {
|
return response()->streamDownload(function () use ($file) {
|
||||||
echo Storage::get($file);
|
echo $file;
|
||||||
}, basename($file), $headers);
|
}, $file_name, $headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire;
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
use App\Services\Invoice\GetInvoiceEInvoice;
|
|
||||||
use App\Utils\Number;
|
use App\Utils\Number;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use App\Utils\HtmlEngine;
|
use App\Utils\HtmlEngine;
|
||||||
@ -22,6 +21,7 @@ use App\Models\QuoteInvitation;
|
|||||||
use App\Utils\VendorHtmlEngine;
|
use App\Utils\VendorHtmlEngine;
|
||||||
use App\Models\CreditInvitation;
|
use App\Models\CreditInvitation;
|
||||||
use App\Models\InvoiceInvitation;
|
use App\Models\InvoiceInvitation;
|
||||||
|
use App\Jobs\Invoice\CreateEInvoice;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use App\Models\PurchaseOrderInvitation;
|
use App\Models\PurchaseOrderInvitation;
|
||||||
use App\Models\RecurringInvoiceInvitation;
|
use App\Models\RecurringInvoiceInvitation;
|
||||||
@ -102,7 +102,7 @@ class PdfSlot extends Component
|
|||||||
|
|
||||||
$file_name = $this->entity->numberFormatter().'.xml';
|
$file_name = $this->entity->numberFormatter().'.xml';
|
||||||
|
|
||||||
$file = (new GetInvoiceEInvoice($this->entity))->run();
|
$file = (new CreateEInvoice($this->entity))->handle();
|
||||||
|
|
||||||
$headers = ['Content-Type' => 'application/xml'];
|
$headers = ['Content-Type' => 'application/xml'];
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ class StoreShopClientRequest extends Request
|
|||||||
$settings->currency_id = $this->getCurrencyCode($input['currency_code']);
|
$settings->currency_id = $this->getCurrencyCode($input['currency_code']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$input['settings'] = $settings;
|
$input['settings'] = (array)$settings;
|
||||||
|
|
||||||
if (isset($input['contacts'])) {
|
if (isset($input['contacts'])) {
|
||||||
foreach ($input['contacts'] as $key => $contact) {
|
foreach ($input['contacts'] as $key => $contact) {
|
||||||
|
@ -11,38 +11,38 @@
|
|||||||
|
|
||||||
namespace App\Jobs\Entity;
|
namespace App\Jobs\Entity;
|
||||||
|
|
||||||
use App\Exceptions\FilePermissionsFailure;
|
use App\Utils\Ninja;
|
||||||
use App\Jobs\Invoice\CreateEInvoice;
|
use App\Models\Quote;
|
||||||
use App\Jobs\Invoice\MergeEInvoice;
|
|
||||||
use App\Libraries\MultiDB;
|
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
use App\Models\CreditInvitation;
|
|
||||||
use App\Models\Design;
|
use App\Models\Design;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\InvoiceInvitation;
|
use App\Utils\HtmlEngine;
|
||||||
use App\Models\Quote;
|
use App\Libraries\MultiDB;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
use App\Models\QuoteInvitation;
|
use App\Models\QuoteInvitation;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\Models\CreditInvitation;
|
||||||
use App\Models\RecurringInvoice;
|
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 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 PdfDesignModel;
|
||||||
use App\Services\PdfMaker\Design as PdfMakerDesign;
|
use App\Services\PdfMaker\Design as PdfMakerDesign;
|
||||||
use App\Services\PdfMaker\PdfMaker as PdfMakerService;
|
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
|
class CreateEntityPdf implements ShouldQueue
|
||||||
{
|
{
|
||||||
@ -117,6 +117,7 @@ class CreateEntityPdf implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
$entity_design_id = '';
|
$entity_design_id = '';
|
||||||
|
$path = '';
|
||||||
|
|
||||||
if ($this->entity instanceof Invoice) {
|
if ($this->entity instanceof Invoice) {
|
||||||
$path = $this->client->invoice_filepath($this->invitation);
|
$path = $this->client->invoice_filepath($this->invitation);
|
||||||
@ -207,6 +208,11 @@ class CreateEntityPdf implements ShouldQueue
|
|||||||
info($maker->getCompiledHTML());
|
info($maker->getCompiledHTML());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($this->entity_string == "invoice" && $this->client->getSetting('enable_e_invoice'))
|
||||||
|
{
|
||||||
|
$pdf = $this->checkEInvoice($pdf);
|
||||||
|
}
|
||||||
|
|
||||||
if ($pdf) {
|
if ($pdf) {
|
||||||
try {
|
try {
|
||||||
Storage::disk($this->disk)->put($file_path, $pdf);
|
Storage::disk($this->disk)->put($file_path, $pdf);
|
||||||
@ -214,11 +220,7 @@ class CreateEntityPdf implements ShouldQueue
|
|||||||
throw new FilePermissionsFailure($e->getMessage());
|
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->invitation = null;
|
||||||
// $this->entity = null;
|
// $this->entity = null;
|
||||||
$this->company = null;
|
$this->company = null;
|
||||||
@ -227,10 +229,65 @@ class CreateEntityPdf implements ShouldQueue
|
|||||||
$maker = null;
|
$maker = null;
|
||||||
$state = null;
|
$state = null;
|
||||||
|
|
||||||
|
|
||||||
return $file_path;
|
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)
|
public function failed($e)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -11,42 +11,43 @@
|
|||||||
|
|
||||||
namespace App\Jobs\Entity;
|
namespace App\Jobs\Entity;
|
||||||
|
|
||||||
use App\Exceptions\FilePermissionsFailure;
|
use App\Utils\Ninja;
|
||||||
use App\Jobs\Invoice\MergeEInvoice;
|
use App\Models\Quote;
|
||||||
use App\Libraries\MultiDB;
|
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
use App\Models\CreditInvitation;
|
|
||||||
use App\Models\Design;
|
use App\Models\Design;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\InvoiceInvitation;
|
use App\Utils\HtmlEngine;
|
||||||
use App\Models\Quote;
|
use App\Libraries\MultiDB;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
use App\Models\QuoteInvitation;
|
use App\Models\QuoteInvitation;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\Models\CreditInvitation;
|
||||||
use App\Models\RecurringInvoice;
|
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 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 PdfDesignModel;
|
||||||
use App\Services\PdfMaker\Design as PdfMakerDesign;
|
use App\Services\PdfMaker\Design as PdfMakerDesign;
|
||||||
use App\Services\PdfMaker\PdfMaker as PdfMakerService;
|
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
|
class CreateRawPdf implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml, PdfMaker, MakesHash, PageNumbering;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml, PdfMaker, MakesHash, PageNumbering;
|
||||||
|
|
||||||
public $entity;
|
public Invoice | Credit | Quote | RecurringInvoice $entity;
|
||||||
|
|
||||||
public $company;
|
public $company;
|
||||||
|
|
||||||
@ -104,6 +105,7 @@ class CreateRawPdf implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
$entity_design_id = '';
|
$entity_design_id = '';
|
||||||
|
$path = '';
|
||||||
|
|
||||||
if ($this->entity instanceof Invoice) {
|
if ($this->entity instanceof Invoice) {
|
||||||
$path = $this->entity->client->invoice_filepath($this->invitation);
|
$path = $this->entity->client->invoice_filepath($this->invitation);
|
||||||
@ -203,18 +205,68 @@ class CreateRawPdf implements ShouldQueue
|
|||||||
if ($pdf) {
|
if ($pdf) {
|
||||||
$maker =null;
|
$maker =null;
|
||||||
$state = null;
|
$state = null;
|
||||||
if ($this->invitation->invoice->client->getSetting('enable_e_invoice') && $this->entity_string == "invoice"){
|
|
||||||
$filename = tempnam(sys_get_temp_dir(), 'InvoiceNinja').".pdf";
|
return $this->checkEInvoice($pdf);
|
||||||
file_put_contents($filename, $pdf);
|
|
||||||
(new \App\Services\Invoice\MergeEInvoice($this->invitation->invoice, $filename))->run();
|
|
||||||
return file_get_contents($filename);
|
|
||||||
};
|
|
||||||
return $pdf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new FilePermissionsFailure('Unable to generate the raw 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)
|
public function failed($e)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,7 @@ class CreateEInvoice implements ShouldQueue
|
|||||||
/**
|
/**
|
||||||
* Execute the job.
|
* Execute the job.
|
||||||
*
|
*
|
||||||
*
|
* @return string|ZugferdDocumentBuilder
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function handle(): string|ZugferdDocumentBuilder
|
public function handle(): string|ZugferdDocumentBuilder
|
||||||
{
|
{
|
||||||
@ -64,13 +63,18 @@ class CreateEInvoice implements ShouldQueue
|
|||||||
case "XInvoice-Extended":
|
case "XInvoice-Extended":
|
||||||
case "XInvoice-BasicWL":
|
case "XInvoice-BasicWL":
|
||||||
case "XInvoice-Basic":
|
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":
|
||||||
case "Facturae_3.2.1":
|
case "Facturae_3.2.1":
|
||||||
case "Facturae_3.2.2":
|
case "Facturae_3.2.2":
|
||||||
return (new FacturaEInvoice($this->invoice, str_replace("Facturae_", "", $e_invoice_type)))->run();
|
return (new FacturaEInvoice($this->invoice, str_replace("Facturae_", "", $e_invoice_type)))->run();
|
||||||
default:
|
default:
|
||||||
return (new ZugferdEInvoice($this->invoice, $this->returnObject))->run();
|
|
||||||
|
$zugferd = (new ZugferdEInvoice($this->invoice))->run();
|
||||||
|
|
||||||
|
return $this->returnObject ? $zugferd : $zugferd->getXml();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Jobs\Invoice;
|
|
||||||
|
|
||||||
use App\Models\ClientContact;
|
|
||||||
use App\Models\Invoice;
|
|
||||||
use horstoeko\zugferd\ZugferdDocumentPdfBuilder;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use horstoeko\zugferd\ZugferdDocumentReader;
|
|
||||||
|
|
||||||
class MergeEInvoice implements ShouldQueue
|
|
||||||
{
|
|
||||||
public function __construct(public Invoice $invoice, private string $pdf_path = "")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws \Exception
|
|
||||||
*/
|
|
||||||
public function handle(): void
|
|
||||||
{
|
|
||||||
$e_invoice_type = $this->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
|
|
||||||
{
|
|
||||||
$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");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -73,28 +73,19 @@ class ZipInvoices implements ShouldQueue
|
|||||||
$invitation = $this->invoices->first()->invitations->first();
|
$invitation = $this->invoices->first()->invitations->first();
|
||||||
$path = $this->invoices->first()->client->invoice_filepath($invitation);
|
$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 {
|
try {
|
||||||
|
|
||||||
|
|
||||||
foreach ($this->invoices as $invoice) {
|
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));
|
|
||||||
|
|
||||||
|
if ($invoice->client->getSetting('enable_e_invoice')) {
|
||||||
|
$xml = $invoice->service()->getEInvoice();
|
||||||
|
$zipFile->addFromString($invoice->getFileName("xml"), $xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$file = $invoice->service()->getRawInvoicePdf();
|
||||||
|
$zip_file_name = $invoice->getFileName();
|
||||||
|
$zipFile->addFromString($zip_file_name, $file);
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage::put($path.$file_name, $zipFile->outputAsString());
|
Storage::put($path.$file_name, $zipFile->outputAsString());
|
||||||
|
@ -18,7 +18,6 @@ use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
|
|||||||
use App\Utils\HtmlEngine;
|
use App\Utils\HtmlEngine;
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use Illuminate\Mail\Mailable;
|
use Illuminate\Mail\Mailable;
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
|
|
||||||
class TemplateEmail extends Mailable
|
class TemplateEmail extends Mailable
|
||||||
{
|
{
|
||||||
@ -111,7 +110,7 @@ class TemplateEmail extends Mailable
|
|||||||
if (Ninja::isHosted()) {
|
if (Ninja::isHosted()) {
|
||||||
$bccs = explode(',', str_replace(' ', '', $settings->bcc_email));
|
$bccs = explode(',', str_replace(' ', '', $settings->bcc_email));
|
||||||
$this->bcc(array_slice($bccs, 0, 2));
|
$this->bcc(array_slice($bccs, 0, 2));
|
||||||
//$this->bcc(reset($bccs)); //remove whitespace if any has been inserted.
|
//$this->bcc(reset($bccs)); //remove whitespace if any has been inserted.
|
||||||
} else {
|
} else {
|
||||||
$this->bcc(explode(',', str_replace(' ', '', $settings->bcc_email)));
|
$this->bcc(explode(',', str_replace(' ', '', $settings->bcc_email)));
|
||||||
}//remove whitespace if any has been inserted.
|
}//remove whitespace if any has been inserted.
|
||||||
@ -149,16 +148,21 @@ class TemplateEmail extends Mailable
|
|||||||
if ($this->invitation && $this->invitation->invoice && $settings->ubl_email_attachment && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
|
if ($this->invitation && $this->invitation->invoice && $settings->ubl_email_attachment && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
|
||||||
$ubl_string = (new CreateUbl($this->invitation->invoice))->handle();
|
$ubl_string = (new CreateUbl($this->invitation->invoice))->handle();
|
||||||
|
|
||||||
|
nlog("template {$ubl_string}");
|
||||||
|
|
||||||
if ($ubl_string) {
|
if ($ubl_string) {
|
||||||
$this->attachData($ubl_string, $this->invitation->invoice->getFileName('xml'));
|
$this->attachData($ubl_string, $this->invitation->invoice->getFileName('xml'));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if ($this->invitation && $this->invitation->invoice && $this->invitation->invoice->client->getSetting('enable_e_invoice') && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
|
if ($this->invitation && $this->invitation->invoice && $this->invitation->invoice->client->getSetting('enable_e_invoice') && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
|
||||||
|
$xml_string = $this->invitation->invoice->service()->getEInvoice($this->invitation->contact);
|
||||||
|
|
||||||
$xinvoice_filepath = $this->invitation->invoice->service()->getEInvoice($this->invitation->contact);
|
nlog("template {$xml_string}");
|
||||||
|
|
||||||
if(Storage::disk(config('filesystems.default'))->exists($xinvoice_filepath))
|
if($xml_string) {
|
||||||
$this->attach(Storage::disk(config('filesystems.default'))->path($xinvoice_filepath), ['as' => $this->invitation->invoice->getFileName("xml"), 'mime' => null]);
|
$this->attachData($xml_string, $this->invitation->invoice->getEFileName("xml"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +237,15 @@ class BaseModel extends Model
|
|||||||
return $this->numberFormatter().'.'.$extension;
|
return $this->numberFormatter().'.'.$extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $extension
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getEFileName($extension = 'pdf')
|
||||||
|
{
|
||||||
|
return ctrans("texts.e_invoice"). "_" . $this->numberFormatter().'.'.$extension;
|
||||||
|
}
|
||||||
|
|
||||||
public function numberFormatter()
|
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);
|
||||||
@ -276,6 +285,7 @@ class BaseModel extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the base64 encoded PDF string of the entity
|
* Returns the base64 encoded PDF string of the entity
|
||||||
|
* @deprecated - unused implementation
|
||||||
*/
|
*/
|
||||||
public function fullscreenPdfViewer($invitation = null): string
|
public function fullscreenPdfViewer($invitation = null): string
|
||||||
{
|
{
|
||||||
|
@ -322,10 +322,10 @@ class EmailDefaults
|
|||||||
}
|
}
|
||||||
/** E-Invoice xml file */
|
/** E-Invoice xml file */
|
||||||
if ($this->email->email_object->settings->enable_e_invoice && $this->email->email_object->entity instanceof Invoice) {
|
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))
|
if($xml_string)
|
||||||
$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"]]);
|
$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)) {
|
if (!$this->email->email_object->settings->document_email_attachment || !$this->email->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) {
|
||||||
|
@ -22,12 +22,13 @@ use horstoeko\zugferd\codelists\ZugferdDutyTaxFeeCategories;
|
|||||||
|
|
||||||
class ZugferdEInvoice extends AbstractService
|
class ZugferdEInvoice extends AbstractService
|
||||||
{
|
{
|
||||||
|
public ZugferdDocumentBuilder $xrechnung;
|
||||||
|
|
||||||
public function __construct(public Invoice $invoice, private readonly bool $returnObject = false, private array $tax_map = [])
|
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;
|
$company = $this->invoice->company;
|
||||||
@ -45,10 +46,9 @@ class ZugferdEInvoice extends AbstractService
|
|||||||
default => ZugferdProfiles::PROFILE_EN16931,
|
default => ZugferdProfiles::PROFILE_EN16931,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$this->xrechnung = ZugferdDocumentBuilder::CreateNew($profile);
|
||||||
|
|
||||||
$xrechnung = ZugferdDocumentBuilder::CreateNew($profile);
|
$this->xrechnung
|
||||||
|
|
||||||
$xrechnung
|
|
||||||
->setDocumentSupplyChainEvent(date_create($this->invoice->date))
|
->setDocumentSupplyChainEvent(date_create($this->invoice->date))
|
||||||
->setDocumentSeller($company->getSetting('name'))
|
->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"))
|
->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]));
|
->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)) {
|
if (!empty($this->invoice->public_notes)) {
|
||||||
$xrechnung->addDocumentNote($this->invoice->public_notes);
|
$this->xrechnung->addDocumentNote($this->invoice->public_notes);
|
||||||
}
|
}
|
||||||
if (empty($this->invoice->number)){
|
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 {
|
} 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)) {
|
if (!empty($this->invoice->po_number)) {
|
||||||
$xrechnung->setDocumentBuyerOrderReferencedDocument($this->invoice->po_number);
|
$this->xrechnung->setDocumentBuyerOrderReferencedDocument($this->invoice->po_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($client->routing_id)) {
|
if (empty($client->routing_id)) {
|
||||||
$xrechnung->setDocumentBuyerReference(ctrans("texts.xinvoice_no_buyers_reference"));
|
$this->xrechnung->setDocumentBuyerReference(ctrans("texts.xinvoice_no_buyers_reference"));
|
||||||
} else {
|
} else {
|
||||||
$xrechnung->setDocumentBuyerReference($client->routing_id);
|
$this->xrechnung->setDocumentBuyerReference($client->routing_id);
|
||||||
}
|
}
|
||||||
if (!empty($client->shipping_address1)){
|
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'), "/")) {
|
if (str_contains($company->getSetting('vat_number'), "/")) {
|
||||||
$xrechnung->addDocumentSellerTaxRegistration("FC", $company->getSetting('vat_number'));
|
$this->xrechnung->addDocumentSellerTaxRegistration("FC", $company->getSetting('vat_number'));
|
||||||
} else {
|
} else {
|
||||||
$xrechnung->addDocumentSellerTaxRegistration("VA", $company->getSetting('vat_number'));
|
$this->xrechnung->addDocumentSellerTaxRegistration("VA", $company->getSetting('vat_number'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$invoicing_data = $this->invoice->calc();
|
$invoicing_data = $this->invoice->calc();
|
||||||
@ -92,29 +92,29 @@ class ZugferdEInvoice extends AbstractService
|
|||||||
//Create line items and calculate taxes
|
//Create line items and calculate taxes
|
||||||
foreach ($this->invoice->line_items as $index => $item) {
|
foreach ($this->invoice->line_items as $index => $item) {
|
||||||
/** @var \App\DataMapper\InvoiceItem $item **/
|
/** @var \App\DataMapper\InvoiceItem $item **/
|
||||||
$xrechnung->addNewPosition($index)
|
$this->xrechnung->addNewPosition($index)
|
||||||
->setDocumentPositionGrossPrice($item->gross_line_total)
|
->setDocumentPositionGrossPrice($item->gross_line_total)
|
||||||
->setDocumentPositionNetPrice($item->line_total);
|
->setDocumentPositionNetPrice($item->line_total);
|
||||||
if (!empty($item->product_key)){
|
if (!empty($item->product_key)){
|
||||||
if (!empty($item->notes)){
|
if (!empty($item->notes)){
|
||||||
$xrechnung->setDocumentPositionProductDetails($item->product_key, $item->notes);
|
$this->xrechnung->setDocumentPositionProductDetails($item->product_key, $item->notes);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$xrechnung->setDocumentPositionProductDetails($item->product_key);
|
$this->xrechnung->setDocumentPositionProductDetails($item->product_key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!empty($item->notes)){
|
if (!empty($item->notes)){
|
||||||
$xrechnung->setDocumentPositionProductDetails($item->notes);
|
$this->xrechnung->setDocumentPositionProductDetails($item->notes);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$xrechnung->setDocumentPositionProductDetails("no product name defined");
|
$this->xrechnung->setDocumentPositionProductDetails("no product name defined");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isset($item->task_id)) {
|
if (isset($item->task_id)) {
|
||||||
$xrechnung->setDocumentPositionQuantity($item->quantity, "HUR");
|
$this->xrechnung->setDocumentPositionQuantity($item->quantity, "HUR");
|
||||||
} else {
|
} else {
|
||||||
$xrechnung->setDocumentPositionQuantity($item->quantity, "H87");
|
$this->xrechnung->setDocumentPositionQuantity($item->quantity, "H87");
|
||||||
}
|
}
|
||||||
$linenetamount = $item->line_total;
|
$linenetamount = $item->line_total;
|
||||||
if ($item->discount > 0) {
|
if ($item->discount > 0) {
|
||||||
@ -124,18 +124,18 @@ class ZugferdEInvoice extends AbstractService
|
|||||||
$linenetamount -= $linenetamount * ($item->discount / 100);
|
$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
|
// 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))) {
|
if (!(empty($item->tax_name1) && empty($item->tax_name2) && empty($item->tax_name3))) {
|
||||||
$taxtype = $this->getTaxType($item->tax_id);
|
$taxtype = $this->getTaxType($item->tax_id);
|
||||||
if (!empty($item->tax_name1)) {
|
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);
|
$this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate1);
|
||||||
} elseif (!empty($item->tax_name2)) {
|
} 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);
|
$this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate2);
|
||||||
} elseif (!empty($item->tax_name3)) {
|
} 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);
|
$this->addtoTaxMap($taxtype, $linenetamount, $item->tax_rate3);
|
||||||
} else {
|
} else {
|
||||||
nlog("Can't add correct tax position");
|
nlog("Can't add correct tax position");
|
||||||
@ -143,42 +143,45 @@ class ZugferdEInvoice extends AbstractService
|
|||||||
} else {
|
} else {
|
||||||
if (!empty($this->invoice->tax_name1)) {
|
if (!empty($this->invoice->tax_name1)) {
|
||||||
$taxtype = $this->getTaxType($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);
|
$this->addtoTaxMap($taxtype, $linenetamount, $this->invoice->tax_rate1);
|
||||||
} elseif (!empty($this->invoice->tax_name2)) {
|
} elseif (!empty($this->invoice->tax_name2)) {
|
||||||
$taxtype = $this->getTaxType($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);
|
$this->addtoTaxMap($taxtype, $linenetamount, $this->invoice->tax_rate2);
|
||||||
} elseif (!empty($this->invoice->tax_name3)) {
|
} elseif (!empty($this->invoice->tax_name3)) {
|
||||||
$taxtype = $this->getTaxType($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);
|
$this->addtoTaxMap($taxtype, $linenetamount, $this->invoice->tax_rate3);
|
||||||
} else {
|
} else {
|
||||||
$taxtype = ZugferdDutyTaxFeeCategories::ZERO_RATED_GOODS;
|
$taxtype = ZugferdDutyTaxFeeCategories::ZERO_RATED_GOODS;
|
||||||
$xrechnung->addDocumentPositionTax($taxtype, 'VAT', 0);
|
$this->xrechnung->addDocumentPositionTax($taxtype, 'VAT', 0);
|
||||||
$this->addtoTaxMap($taxtype, $linenetamount, 0);
|
$this->addtoTaxMap($taxtype, $linenetamount, 0);
|
||||||
nlog("Can't add correct tax position");
|
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){
|
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);
|
$this->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()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$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
|
// The validity can be checked using https://portal3.gefeg.com/invoice/validation or https://e-rechnung.bayern.de/app/#/upload
|
||||||
if ($this->returnObject){
|
return $this;
|
||||||
return $xrechnung;
|
|
||||||
}
|
}
|
||||||
return $client->e_invoice_filepath($this->invoice->invitations->first()) . $this->invoice->getFileName("xml");
|
|
||||||
|
/**
|
||||||
|
* Returns the XML document
|
||||||
|
* in string format
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getXml(): string
|
||||||
|
{
|
||||||
|
return $this->xrechnung->getContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getTaxType($name): string
|
private function getTaxType($name): string
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Invoice Ninja (https://invoiceninja.com).
|
|
||||||
*
|
|
||||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @license https://www.elastic.co/licensing/elastic-license
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Services\Invoice;
|
|
||||||
|
|
||||||
use App\Jobs\Invoice\CreateEInvoice;
|
|
||||||
use App\Models\ClientContact;
|
|
||||||
use App\Models\Invoice;
|
|
||||||
use App\Services\AbstractService;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
|
|
||||||
class GetInvoiceEInvoice extends AbstractService
|
|
||||||
{
|
|
||||||
public function __construct(public Invoice $invoice, public ?ClientContact $contact = null)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function run()
|
|
||||||
{
|
|
||||||
if (! $this->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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,7 +13,6 @@ namespace App\Services\Invoice;
|
|||||||
|
|
||||||
use App\Jobs\Entity\CreateEntityPdf;
|
use App\Jobs\Entity\CreateEntityPdf;
|
||||||
use App\Jobs\Invoice\CreateEInvoice;
|
use App\Jobs\Invoice\CreateEInvoice;
|
||||||
use App\Jobs\Invoice\MergeEInvoice;
|
|
||||||
use App\Models\ClientContact;
|
use App\Models\ClientContact;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Services\AbstractService;
|
use App\Services\AbstractService;
|
||||||
@ -49,10 +48,7 @@ class GetInvoicePdf extends AbstractService
|
|||||||
if (! $file) {
|
if (! $file) {
|
||||||
$file_path = (new CreateEntityPdf($invitation))->handle();
|
$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;
|
return $file_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ namespace App\Services\Invoice;
|
|||||||
|
|
||||||
use App\Events\Invoice\InvoiceWasArchived;
|
use App\Events\Invoice\InvoiceWasArchived;
|
||||||
use App\Jobs\Entity\CreateEntityPdf;
|
use App\Jobs\Entity\CreateEntityPdf;
|
||||||
|
use App\Jobs\Entity\CreateRawPdf;
|
||||||
use App\Jobs\Inventory\AdjustProductInventory;
|
use App\Jobs\Inventory\AdjustProductInventory;
|
||||||
use App\Jobs\Invoice\CreateEInvoice;
|
use App\Jobs\Invoice\CreateEInvoice;
|
||||||
use App\Libraries\Currency\Conversion\CurrencyApi;
|
use App\Libraries\Currency\Conversion\CurrencyApi;
|
||||||
@ -187,6 +188,13 @@ class InvoiceService
|
|||||||
return (new GetInvoicePdf($this->invoice, $contact))->run();
|
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)
|
public function getInvoiceDeliveryNote(Invoice $invoice, \App\Models\ClientContact $contact = null)
|
||||||
{
|
{
|
||||||
return (new GenerateDeliveryNote($invoice, $contact))->run();
|
return (new GenerateDeliveryNote($invoice, $contact))->run();
|
||||||
@ -194,13 +202,9 @@ class InvoiceService
|
|||||||
|
|
||||||
public function getEInvoice($contact = null)
|
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)
|
public function sendEmail($contact = null)
|
||||||
{
|
{
|
||||||
$send_email = new SendEmail($this->invoice, null, $contact);
|
$send_email = new SendEmail($this->invoice, null, $contact);
|
||||||
@ -464,13 +468,6 @@ class InvoiceService
|
|||||||
if ($force) {
|
if ($force) {
|
||||||
$this->invoice->invitations->each(function ($invitation) {
|
$this->invoice->invitations->each(function ($invitation) {
|
||||||
(new CreateEntityPdf($invitation))->handle();
|
(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;
|
return $this;
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Services\Invoice;
|
|
||||||
|
|
||||||
use App\Models\ClientContact;
|
|
||||||
use App\Models\Invoice;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
|
|
||||||
class MergeEInvoice
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Invoice $invoice
|
|
||||||
*/
|
|
||||||
public function __construct(public Invoice $invoice, public string $pdf_path = "")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function run(): void
|
|
||||||
{
|
|
||||||
if (!empty($this->pdf_path)) {
|
|
||||||
(new \App\Jobs\Invoice\MergeEInvoice($this->invoice, $this->pdf_path))->handle();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
(new \App\Jobs\Invoice\MergeEInvoice($this->invoice))->handle();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -79,7 +79,7 @@ trait Inviteable
|
|||||||
if (Ninja::isHosted()) {
|
if (Ninja::isHosted()) {
|
||||||
$domain = $this->company->domain();
|
$domain = $this->company->domain();
|
||||||
} else {
|
} else {
|
||||||
$domain = strlen($this->company->portal_domain) > 5 ? $this->company->portal_domain : config('ninja.app_url');
|
$domain = strlen($this->company->portal_domain ?? '') > 5 ? $this->company->portal_domain : config('ninja.app_url');
|
||||||
}
|
}
|
||||||
|
|
||||||
$entity_type = Str::snake(class_basename($this->entityType()));
|
$entity_type = Str::snake(class_basename($this->entityType()));
|
||||||
@ -94,7 +94,7 @@ trait Inviteable
|
|||||||
if (Ninja::isHosted()) {
|
if (Ninja::isHosted()) {
|
||||||
$domain = $this->company->domain();
|
$domain = $this->company->domain();
|
||||||
} else {
|
} else {
|
||||||
$domain = strlen($this->company->portal_domain) > 5 ? $this->company->portal_domain : config('ninja.app_url');
|
$domain = strlen($this->company->portal_domain ?? '') > 5 ? $this->company->portal_domain : config('ninja.app_url');
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($this->company->portal_mode) {
|
switch ($this->company->portal_mode) {
|
||||||
@ -119,7 +119,7 @@ trait Inviteable
|
|||||||
if (Ninja::isHosted()) {
|
if (Ninja::isHosted()) {
|
||||||
$domain = $this->company->domain();
|
$domain = $this->company->domain();
|
||||||
} else {
|
} else {
|
||||||
$domain = strlen($this->company->portal_domain) > 5 ? $this->company->portal_domain : config('ninja.app_url');
|
$domain = strlen($this->company->portal_domain ?? '') > 5 ? $this->company->portal_domain : config('ninja.app_url');
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($this->company->portal_mode) {
|
switch ($this->company->portal_mode) {
|
||||||
|
84
composer.lock
generated
84
composer.lock
generated
@ -424,16 +424,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "aws/aws-sdk-php",
|
"name": "aws/aws-sdk-php",
|
||||||
"version": "3.278.3",
|
"version": "3.279.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||||
"reference": "596534c0627d8b38597061341e99b460437d1a16"
|
"reference": "7b3d38cfccd393add0ea0ce281de91846967c61e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/596534c0627d8b38597061341e99b460437d1a16",
|
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7b3d38cfccd393add0ea0ce281de91846967c61e",
|
||||||
"reference": "596534c0627d8b38597061341e99b460437d1a16",
|
"reference": "7b3d38cfccd393add0ea0ce281de91846967c61e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -442,11 +442,11 @@
|
|||||||
"ext-pcre": "*",
|
"ext-pcre": "*",
|
||||||
"ext-simplexml": "*",
|
"ext-simplexml": "*",
|
||||||
"guzzlehttp/guzzle": "^6.5.8 || ^7.4.5",
|
"guzzlehttp/guzzle": "^6.5.8 || ^7.4.5",
|
||||||
"guzzlehttp/promises": "^1.4.0",
|
"guzzlehttp/promises": "^1.4.0 || ^2.0",
|
||||||
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
|
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
|
||||||
"mtdowling/jmespath.php": "^2.6",
|
"mtdowling/jmespath.php": "^2.6",
|
||||||
"php": ">=5.5",
|
"php": ">=7.2.5",
|
||||||
"psr/http-message": "^1.0"
|
"psr/http-message": "^1.0 || ^2.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"andrewsville/php-token-reflection": "^1.4",
|
"andrewsville/php-token-reflection": "^1.4",
|
||||||
@ -461,7 +461,7 @@
|
|||||||
"ext-sockets": "*",
|
"ext-sockets": "*",
|
||||||
"nette/neon": "^2.3",
|
"nette/neon": "^2.3",
|
||||||
"paragonie/random_compat": ">= 2",
|
"paragonie/random_compat": ">= 2",
|
||||||
"phpunit/phpunit": "^4.8.35 || ^5.6.3 || ^9.5",
|
"phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5",
|
||||||
"psr/cache": "^1.0",
|
"psr/cache": "^1.0",
|
||||||
"psr/simple-cache": "^1.0",
|
"psr/simple-cache": "^1.0",
|
||||||
"sebastian/comparator": "^1.2.3 || ^4.0",
|
"sebastian/comparator": "^1.2.3 || ^4.0",
|
||||||
@ -513,9 +513,9 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
||||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.278.3"
|
"source": "https://github.com/aws/aws-sdk-php/tree/3.279.0"
|
||||||
},
|
},
|
||||||
"time": "2023-08-15T18:07:55+00:00"
|
"time": "2023-08-16T18:18:34+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bacon/bacon-qr-code",
|
"name": "bacon/bacon-qr-code",
|
||||||
@ -2832,29 +2832,33 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/promises",
|
"name": "guzzlehttp/promises",
|
||||||
"version": "1.5.3",
|
"version": "2.0.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/guzzle/promises.git",
|
"url": "https://github.com/guzzle/promises.git",
|
||||||
"reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e"
|
"reference": "111166291a0f8130081195ac4556a5587d7f1b5d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e",
|
"url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d",
|
||||||
"reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e",
|
"reference": "111166291a0f8130081195ac4556a5587d7f1b5d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.5"
|
"php": "^7.2.5 || ^8.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/phpunit-bridge": "^4.4 || ^5.1"
|
"bamarni/composer-bin-plugin": "^1.8.1",
|
||||||
|
"phpunit/phpunit": "^8.5.29 || ^9.5.23"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"bamarni-bin": {
|
||||||
|
"bin-links": true,
|
||||||
|
"forward-command": false
|
||||||
|
}
|
||||||
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"files": [
|
|
||||||
"src/functions_include.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"GuzzleHttp\\Promise\\": "src/"
|
"GuzzleHttp\\Promise\\": "src/"
|
||||||
}
|
}
|
||||||
@ -2891,7 +2895,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/guzzle/promises/issues",
|
"issues": "https://github.com/guzzle/promises/issues",
|
||||||
"source": "https://github.com/guzzle/promises/tree/1.5.3"
|
"source": "https://github.com/guzzle/promises/tree/2.0.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -2907,7 +2911,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-05-21T12:31:43+00:00"
|
"time": "2023-08-03T15:11:55+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/psr7",
|
"name": "guzzlehttp/psr7",
|
||||||
@ -3344,16 +3348,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "horstoeko/zugferd",
|
"name": "horstoeko/zugferd",
|
||||||
"version": "v1.0.20",
|
"version": "v1.0.23",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/horstoeko/zugferd.git",
|
"url": "https://github.com/horstoeko/zugferd.git",
|
||||||
"reference": "725c130ec0a09d72cf54b3d819840f3959a5502c"
|
"reference": "bb55417be4c4de8deb0113e832feeaf7b4d3984e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/horstoeko/zugferd/zipball/725c130ec0a09d72cf54b3d819840f3959a5502c",
|
"url": "https://api.github.com/repos/horstoeko/zugferd/zipball/bb55417be4c4de8deb0113e832feeaf7b4d3984e",
|
||||||
"reference": "725c130ec0a09d72cf54b3d819840f3959a5502c",
|
"reference": "bb55417be4c4de8deb0113e832feeaf7b4d3984e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -3411,9 +3415,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/horstoeko/zugferd/issues",
|
"issues": "https://github.com/horstoeko/zugferd/issues",
|
||||||
"source": "https://github.com/horstoeko/zugferd/tree/v1.0.20"
|
"source": "https://github.com/horstoeko/zugferd/tree/v1.0.23"
|
||||||
},
|
},
|
||||||
"time": "2023-07-04T15:21:32+00:00"
|
"time": "2023-08-16T17:39:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "http-interop/http-factory-guzzle",
|
"name": "http-interop/http-factory-guzzle",
|
||||||
@ -5860,16 +5864,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "moneyphp/money",
|
"name": "moneyphp/money",
|
||||||
"version": "v4.1.1",
|
"version": "v4.2.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/moneyphp/money.git",
|
"url": "https://github.com/moneyphp/money.git",
|
||||||
"reference": "9682220995ffd396843be5b4ee1e5f2c2d6ecee2"
|
"reference": "f660ab7f1d7a4c2ffdd30f50c55ed2c95c26fc3f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/moneyphp/money/zipball/9682220995ffd396843be5b4ee1e5f2c2d6ecee2",
|
"url": "https://api.github.com/repos/moneyphp/money/zipball/f660ab7f1d7a4c2ffdd30f50c55ed2c95c26fc3f",
|
||||||
"reference": "9682220995ffd396843be5b4ee1e5f2c2d6ecee2",
|
"reference": "f660ab7f1d7a4c2ffdd30f50c55ed2c95c26fc3f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -5943,9 +5947,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/moneyphp/money/issues",
|
"issues": "https://github.com/moneyphp/money/issues",
|
||||||
"source": "https://github.com/moneyphp/money/tree/v4.1.1"
|
"source": "https://github.com/moneyphp/money/tree/v4.2.0"
|
||||||
},
|
},
|
||||||
"time": "2023-04-11T09:18:34+00:00"
|
"time": "2023-08-16T14:31:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
@ -6248,25 +6252,29 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "nesbot/carbon",
|
"name": "nesbot/carbon",
|
||||||
"version": "2.68.1",
|
"version": "2.69.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/briannesbitt/Carbon.git",
|
"url": "https://github.com/briannesbitt/Carbon.git",
|
||||||
"reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da"
|
"reference": "4308217830e4ca445583a37d1bf4aff4153fa81c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4f991ed2a403c85efbc4f23eb4030063fdbe01da",
|
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4308217830e4ca445583a37d1bf4aff4153fa81c",
|
||||||
"reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da",
|
"reference": "4308217830e4ca445583a37d1bf4aff4153fa81c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"php": "^7.1.8 || ^8.0",
|
"php": "^7.1.8 || ^8.0",
|
||||||
|
"psr/clock": "^1.0",
|
||||||
"symfony/polyfill-mbstring": "^1.0",
|
"symfony/polyfill-mbstring": "^1.0",
|
||||||
"symfony/polyfill-php80": "^1.16",
|
"symfony/polyfill-php80": "^1.16",
|
||||||
"symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0"
|
"symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0"
|
||||||
},
|
},
|
||||||
|
"provide": {
|
||||||
|
"psr/clock-implementation": "1.0"
|
||||||
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/dbal": "^2.0 || ^3.1.4",
|
"doctrine/dbal": "^2.0 || ^3.1.4",
|
||||||
"doctrine/orm": "^2.7",
|
"doctrine/orm": "^2.7",
|
||||||
@ -6346,7 +6354,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-06-20T18:29:04+00:00"
|
"time": "2023-08-03T09:00:52+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "nette/schema",
|
"name": "nette/schema",
|
||||||
|
@ -13,6 +13,7 @@ parameters:
|
|||||||
- 'app/DataMapper/Analytics/*'
|
- 'app/DataMapper/Analytics/*'
|
||||||
- 'app/PaymentDrivers/Authorize/*'
|
- 'app/PaymentDrivers/Authorize/*'
|
||||||
- 'app/Utils/Traits/*'
|
- 'app/Utils/Traits/*'
|
||||||
|
- 'resources/views/*'
|
||||||
universalObjectCratesClasses:
|
universalObjectCratesClasses:
|
||||||
- App\DataMapper\Tax\RuleInterface
|
- App\DataMapper\Tax\RuleInterface
|
||||||
- App\DataMapper\FeesAndLimits
|
- App\DataMapper\FeesAndLimits
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="flex flex-col items-end mb-2" x-data>
|
<div class="flex flex-row space-x-2 float-right mb-2" x-data>
|
||||||
<button wire:loading.attr="disabled" wire:click="downloadPdf" class="bg-primary text-white px-4 py-4 lg:px-2 lg:py-2 rounded" type="button">
|
<button wire:loading.attr="disabled" wire:click="downloadPdf" class="bg-primary text-white px-4 py-4 lg:px-2 lg:py-2 rounded" type="button">
|
||||||
<span class="mr-0">{{ ctrans('texts.download_pdf') }}</span>
|
<span class="mr-0">{{ ctrans('texts.download_pdf') }}</span>
|
||||||
<div wire:loading wire:target="downloadPdf">
|
<div wire:loading wire:target="downloadPdf">
|
||||||
@ -9,15 +9,17 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button wire:loading.attr="disabled" wire:click="downloadEInvoice" class="bg-primary text-white px-4 py-4 lg:px-2 lg:py-2 rounded" type="button">
|
@if($settings->enable_e_invoice && $entity_type == 'invoice')
|
||||||
<span>{{ ctrans('texts.download_e_invoice') }}</span>
|
<button wire:loading.attr="disabled" wire:click="downloadEInvoice" class="bg-primary text-white px-4 py-4 lg:px-2 lg:py-2 rounded" type="button">
|
||||||
<div wire:loading wire:target="downloadEInvoice">
|
<span>{{ ctrans('texts.download_e_invoice') }}</span>
|
||||||
<svg class="animate-spin h-5 w-5 text-blue" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
<div wire:loading wire:target="downloadEInvoice">
|
||||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
<svg class="animate-spin h-5 w-5 text-blue" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||||
</svg>
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||||
</div>
|
</svg>
|
||||||
</button>
|
</div>
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden lg:block">
|
<div class="hidden lg:block">
|
||||||
<div wire:init="getPdf()">
|
<div wire:init="getPdf()">
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
@csrf
|
@csrf
|
||||||
<button type="submit" onclick="setTimeout(() => this.disabled = true, 0); setTimeout(() => this.disabled = false, 5000); return true;" class="button button-primary bg-primary" name="action" value="download">{{ ctrans('texts.download') }}</button>
|
<button type="submit" onclick="setTimeout(() => this.disabled = true, 0); setTimeout(() => this.disabled = false, 5000); return true;" class="button button-primary bg-primary" name="action" value="download">{{ ctrans('texts.download') }}</button>
|
||||||
@csrf
|
@csrf
|
||||||
<button type="submit" onclick="setTimeout(() => this.disabled = true, 0); setTimeout(() => this.disabled = false, 5000); return true;" class="button button-primary bg-secondary" name="action-xml" value="download">{{ ctrans('texts.download_xml') }}</button>
|
|
||||||
@if(!empty(auth()->user()->client->service()->getPaymentMethods(0)))
|
@if(!empty(auth()->user()->client->service()->getPaymentMethods(0)))
|
||||||
<button onclick="setTimeout(() => this.disabled = true, 0); return true;" type="submit" class="button button-primary bg-primary" name="action" value="payment">{{ ctrans('texts.pay_now') }}</button>
|
<button onclick="setTimeout(() => this.disabled = true, 0); return true;" type="submit" class="button button-primary bg-primary" name="action" value="payment">{{ ctrans('texts.pay_now') }}</button>
|
||||||
@endif
|
@endif
|
||||||
|
@ -43,9 +43,7 @@ class EInvoiceTest extends TestCase
|
|||||||
$this->invoice->client->routing_id = 'DE123456789';
|
$this->invoice->client->routing_id = 'DE123456789';
|
||||||
$this->invoice->client->save();
|
$this->invoice->client->save();
|
||||||
$e_invoice = (new CreateEInvoice($this->invoice))->handle();
|
$e_invoice = (new CreateEInvoice($this->invoice))->handle();
|
||||||
(new \App\Jobs\Invoice\MergeEInvoice($this->invoice))->handle();
|
$this->assertIsString($e_invoice);
|
||||||
$this->assertNotNull($e_invoice);
|
|
||||||
$this->assertTrue(Storage::exists($e_invoice));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,7 +56,7 @@ class EInvoiceTest extends TestCase
|
|||||||
$this->invoice->client->save();
|
$this->invoice->client->save();
|
||||||
|
|
||||||
$e_invoice = (new CreateEInvoice($this->invoice))->handle();
|
$e_invoice = (new CreateEInvoice($this->invoice))->handle();
|
||||||
$document = ZugferdDocumentReader::readAndGuessFromFile(Storage::path($e_invoice));
|
$document = ZugferdDocumentReader::readAndGuessFromContent($e_invoice);
|
||||||
$document->getDocumentInformation($documentno, $documenttypecode, $documentdate, $documentcurrency, $taxcurrency, $taxname, $documentlangeuage, $rest);
|
$document->getDocumentInformation($documentno, $documenttypecode, $documentdate, $documentcurrency, $taxcurrency, $taxname, $documentlangeuage, $rest);
|
||||||
$this->assertEquals($this->invoice->number, $documentno);
|
$this->assertEquals($this->invoice->number, $documentno);
|
||||||
}
|
}
|
||||||
@ -69,9 +67,7 @@ class EInvoiceTest extends TestCase
|
|||||||
public function checkEmbededPDFFile()
|
public function checkEmbededPDFFile()
|
||||||
{
|
{
|
||||||
$pdf = (new CreateEntityPdf($this->invoice->invitations()->first()))->handle();
|
$pdf = (new CreateEntityPdf($this->invoice->invitations()->first()))->handle();
|
||||||
(new CreateEInvoice($this->invoice))->handle();
|
$document = ZugferdDocumentReader::readAndGuessFromContent($pdf);
|
||||||
(new \App\Jobs\Invoice\MergeEInvoice($this->invoice))->handle();
|
|
||||||
$document = ZugferdDocumentReader::readAndGuessFromFile($pdf);
|
|
||||||
$document->getDocumentInformation($documentno, $documenttypecode, $documentdate, $documentcurrency, $taxcurrency, $taxname, $documentlangeuage, $rest);
|
$document->getDocumentInformation($documentno, $documenttypecode, $documentdate, $documentcurrency, $taxcurrency, $taxname, $documentlangeuage, $rest);
|
||||||
$this->assertEquals($this->invoice->number, $documentno);
|
$this->assertEquals($this->invoice->number, $documentno);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user