From 1bff207e6cc12309888648d896271465ad76ad87 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 15 Nov 2023 10:15:14 +1100 Subject: [PATCH 1/7] Fixes for activity insertions --- app/Models/Activity.php | 4 ++-- app/Services/Payment/RefundPayment.php | 3 ++- app/Services/Pdf/PdfBuilder.php | 3 ++- app/Utils/Traits/Payment/Refundable.php | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/Models/Activity.php b/app/Models/Activity.php index 772c234e695a..e8b1a7f05d2b 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -451,8 +451,8 @@ class Activity extends StaticModel ':subscription' => $translation = [substr($variable, 1) => [ 'label' => $this?->subscription?->number ?? '', 'hashed_id' => $this->subscription->hashed_id ?? '' ]], ':recurring_invoice' => $translation = [substr($variable, 1) =>[ 'label' => $this?->recurring_invoice?->number ??'', 'hashed_id' => $this->recurring_invoice->hashed_id ?? '']], ':recurring_expense' => $translation = [substr($variable, 1) => [ 'label' => $this?->recurring_expense?->number ??'', 'hashed_id' => $this->recurring_expense->hashed_id ?? '']], - ':payment_amount' => $translation = [substr($variable, 1) =>[ 'label' => Number::formatMoney($this?->payment?->amount, $this?->payment?->client) ?? '', 'hashed_id' => '']], - ':adjustment' => $translation = [substr($variable, 1) =>[ 'label' => Number::formatMoney($this?->payment?->refunded, $this?->payment?->client) ?? '', 'hashed_id' => '']], + ':payment_amount' => $translation = [substr($variable, 1) =>[ 'label' => Number::formatMoney($this?->payment?->amount, $this?->payment?->client ?? $this->company) ?? '', 'hashed_id' => '']], + ':adjustment' => $translation = [substr($variable, 1) =>[ 'label' => Number::formatMoney($this?->payment?->refunded, $this?->payment?->client ?? $this->company) ?? '', 'hashed_id' => '']], ':ip' => $translation = [ 'ip' => $this->ip ?? ''], ':contact' => $translation = $this->resolveContact(), default => $translation = [], diff --git a/app/Services/Payment/RefundPayment.php b/app/Services/Payment/RefundPayment.php index b06833eeff0d..82e2781e40a6 100644 --- a/app/Services/Payment/RefundPayment.php +++ b/app/Services/Payment/RefundPayment.php @@ -149,7 +149,8 @@ class RefundPayment $fields->user_id = $this->payment->user_id; $fields->company_id = $this->payment->company_id; $fields->activity_type_id = Activity::REFUNDED_PAYMENT; - // $fields->credit_id = $this->credit_note->id; // TODO + $fields->client_id = $this->payment->client_id; + // $fields->credit_id // TODO $fields->notes = $notes; if (isset($this->refund_data['invoices'])) { diff --git a/app/Services/Pdf/PdfBuilder.php b/app/Services/Pdf/PdfBuilder.php index 9b19192e1bcf..ef2328955d56 100644 --- a/app/Services/Pdf/PdfBuilder.php +++ b/app/Services/Pdf/PdfBuilder.php @@ -843,8 +843,9 @@ class PdfBuilder */ public function processTaxColumns(string $type): void { + $column_type = 'product'; + if ($type == 'product') { - $column_type = 'product'; $type_id = 1; } diff --git a/app/Utils/Traits/Payment/Refundable.php b/app/Utils/Traits/Payment/Refundable.php index 442c1dfdad8f..7a7098bb0684 100644 --- a/app/Utils/Traits/Payment/Refundable.php +++ b/app/Utils/Traits/Payment/Refundable.php @@ -208,6 +208,7 @@ trait Refundable $fields->company_id = $this->company_id; $fields->activity_type_id = Activity::REFUNDED_PAYMENT; $fields->credit_id = $credit_id; + $fields->client_id = $this->client_id; if (isset($data['invoices'])) { foreach ($data['invoices'] as $invoice) { From cddba28bfbeee39b700e33aee5e7da7fd655dece Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 15 Nov 2023 10:16:20 +1100 Subject: [PATCH 2/7] Fixes for activity insertions --- app/Repositories/Migration/PaymentMigrationRepository.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Repositories/Migration/PaymentMigrationRepository.php b/app/Repositories/Migration/PaymentMigrationRepository.php index 6fb6b3455c26..1f19b172bfe5 100644 --- a/app/Repositories/Migration/PaymentMigrationRepository.php +++ b/app/Repositories/Migration/PaymentMigrationRepository.php @@ -167,6 +167,7 @@ class PaymentMigrationRepository extends BaseRepository $fields = new stdClass; $fields->payment_id = $payment->id; + $fields->client_id = $payment->client_id; $fields->user_id = $payment->user_id; $fields->company_id = $payment->company_id; $fields->activity_type_id = Activity::CREATE_PAYMENT; From 5033f746397c0ee7f5a8792f03bd2f766514fa54 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 15 Nov 2023 13:25:34 +1100 Subject: [PATCH 3/7] Fixes for activity insertions --- app/Listeners/Invoice/InvoicePaidActivity.php | 2 +- app/Services/Client/Statement.php | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/Listeners/Invoice/InvoicePaidActivity.php b/app/Listeners/Invoice/InvoicePaidActivity.php index 836136aad0e0..f942b867a3ee 100644 --- a/app/Listeners/Invoice/InvoicePaidActivity.php +++ b/app/Listeners/Invoice/InvoicePaidActivity.php @@ -49,7 +49,7 @@ class InvoicePaidActivity implements ShouldQueue $fields->user_id = $user_id; $fields->invoice_id = $event->invoice->id; - $fields->client_id = $event->invoice->client_id; + $fields->client_id = $event->payment->client_id; $fields->company_id = $event->invoice->company_id; $fields->activity_type_id = Activity::PAID_INVOICE; $fields->payment_id = $event->payment->id; diff --git a/app/Services/Client/Statement.php b/app/Services/Client/Statement.php index 556baf76f84f..41a2f7127ca6 100644 --- a/app/Services/Client/Statement.php +++ b/app/Services/Client/Statement.php @@ -62,6 +62,7 @@ class Statement $html = new HtmlEngine($this->getInvitation()); $variables = []; + $variables = $html->generateLabelsAndValues(); if($this->client->getSetting('statement_design_id') != '') { @@ -72,9 +73,7 @@ class Statement return $this->templateStatement($variables); } - - $variables = $html->generateLabelsAndValues(); - + if ($this->getDesign()->is_custom) { $this->options['custom_partials'] = \json_decode(\json_encode($this->getDesign()->design), true); @@ -154,11 +153,13 @@ class Statement $statement_design_id = $this->client->getSetting('statement_design_id'); } - $template = Design::where('id', $this->decodePrimaryKey($statement_design_id)) + $template = Design::query() + ->where('id', $this->decodePrimaryKey($statement_design_id)) ->where('company_id', $this->client->company_id) ->first(); - - $ts = $template->service()->build([ + + $ts = $template->service(); + $ts->build([ 'variables' => collect([$variables]), 'invoices' => $this->getInvoices()->get(), 'payments' => $this->options['show_payments_table'] ? $this->getPayments()->get() : collect([]), @@ -166,6 +167,7 @@ class Statement 'aging' => $this->options['show_aging_table'] ? $this->getAging() : collect([]), ]); + // $ts->overrideVariables([$variables]); $html = $ts->getHtml(); return $this->convertToPdf($html); From 3ad01c89804cd91f5b40e80a29ea5daf634d6aa0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 15 Nov 2023 13:37:06 +1100 Subject: [PATCH 4/7] Sort processing for stacks --- app/Services/Template/TemplateService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Services/Template/TemplateService.php b/app/Services/Template/TemplateService.php index 771885405fb6..84c67de969ee 100644 --- a/app/Services/Template/TemplateService.php +++ b/app/Services/Template/TemplateService.php @@ -119,9 +119,9 @@ class TemplateService { $this->compose() ->processData($data) - ->parseGlobalStacks() ->parseNinjaBlocks() ->processVariables($data) + ->parseGlobalStacks() ->parseVariables(); return $this; From ad69d3d7baa77e06d240f7dc6f82915939f85d7d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 15 Nov 2023 14:57:07 +1100 Subject: [PATCH 5/7] Adjustments for Template Parsing --- app/Http/Controllers/PreviewController.php | 141 --------------- app/Jobs/Entity/CreateRawPdf.php | 194 +-------------------- app/Services/Client/Statement.php | 4 +- app/Services/Pdf/PdfBuilder.php | 15 +- app/Services/Pdf/PdfConfiguration.php | 2 +- app/Services/Template/TemplateService.php | 10 +- 6 files changed, 19 insertions(+), 347 deletions(-) diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index 27e76dddccc9..0e0e2a420c58 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -28,7 +28,6 @@ use App\Utils\HostedPDF\NinjaPdf; use Illuminate\Support\Facades\DB; use App\Services\PdfMaker\PdfMaker; use Illuminate\Support\Facades\App; -use Illuminate\Support\Facades\Cache; use App\Utils\Traits\MakesInvoiceHtml; use Turbo124\Beacon\Facades\LightLogs; use App\Utils\Traits\Pdf\PageNumbering; @@ -84,141 +83,6 @@ class PreviewController extends BaseController $pdf = $ps->boot()->getPdf(); - - if (Ninja::isHosted()) { - LightLogs::create(new LivePreview()) - ->increment() - ->batch(); - } - - /** Return PDF */ - return response()->streamDownload(function () use ($pdf) { - echo $pdf; - }, 'preview.pdf', [ - 'Content-Disposition' => 'inline', - 'Content-Type' => 'application/pdf', - 'Cache-Control:' => 'no-cache', - 'Server-Timing' => microtime(true)-$start - ]); - - } - - /** - * Refactor - 2023-10-19 - * - * New method does not require Transactions. - * - * @param PreviewInvoiceRequest $request - * @return mixed - */ - public function livexx(PreviewInvoiceRequest $request): mixed - { - - if (Ninja::isHosted() && !in_array($request->getHost(), ['preview.invoicing.co','staging.invoicing.co'])) { - return response()->json(['message' => 'This server cannot handle this request.'], 400); - } - - $start = microtime(true); - - /** Build models */ - $invitation = $request->resolveInvitation(); - $client = $request->getClient(); - $settings = $client->getMergedSettings(); - - /** Set translations */ - App::forgetInstance('translator'); - $t = app('translator'); - App::setLocale($invitation->contact->preferredLocale()); - $t->replace(Ninja::transformTranslations($settings)); - - $entity_prop = str_replace("recurring_", "", $request->entity); - $entity_obj = $invitation->{$request->entity}; - $entity_obj->fill($request->all()); - - /** Update necessary objecty props */ - if(!$entity_obj->id) { - $entity_obj->design_id = intval($this->decodePrimaryKey($settings->{$entity_prop."_design_id"})); - $entity_obj->footer = empty($entity_obj->footer) ? $settings->{$entity_prop."_footer"} : $entity_obj->footer; - $entity_obj->terms = empty($entity_obj->terms) ? $settings->{$entity_prop."_terms"} : $entity_obj->terms; - $entity_obj->public_notes = empty($entity_obj->public_notes) ? $request->getClient()->public_notes : $entity_obj->public_notes; - $invitation->{$request->entity} = $entity_obj; - } - - if(empty($entity_obj->design_id)) { - $entity_obj->design_id = intval($this->decodePrimaryKey($settings->{$entity_prop."_design_id"})); - } - - /** Generate variables */ - $html = new HtmlEngine($invitation); - $html->settings = $settings; - $variables = $html->generateLabelsAndValues(); - - $design = \App\Models\Design::query()->withTrashed()->find($entity_obj->design_id ?? 2); - - if ($design->is_custom) { - $options = [ - 'custom_partials' => json_decode(json_encode($design->design), true), - ]; - $template = new PdfMakerDesign(PdfDesignModel::CUSTOM, $options); - } else { - $template = new PdfMakerDesign(strtolower($design->name)); - } - - $state = [ - 'template' => $template->elements([ - 'client' => $client, - 'entity' => $entity_obj, - 'pdf_variables' => (array) $settings->pdf_variables, - '$product' => $design->design->product, - 'variables' => $variables, - ]), - 'variables' => $variables, - 'options' => [ - 'all_pages_header' => $client->getSetting('all_pages_header'), - 'all_pages_footer' => $client->getSetting('all_pages_footer'), - 'client' => $entity_obj->client ?? [], - 'vendor' => $entity_obj->vendor ?? [], - $request->input('entity')."s" => [$entity_obj], - ], - 'process_markdown' => $client->company->markdown_enabled, - ]; - - $maker = new PdfMaker($state); - - $maker - ->design($template) - ->build(); - - /** Generate HTML */ - $html = $maker->getCompiledHTML(true); - - if (request()->query('html') == 'true') { - return $html; - } - - //if phantom js...... inject here.. - if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { - return (new Phantom)->convertHtmlToPdf($html); - } - - /** @var \App\Models\User $user */ - $user = auth()->user(); - $company = $user->company(); - - if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { - - $pdf = (new NinjaPdf())->build($html); - $numbered_pdf = $this->pageNumbering($pdf, $company); - - if ($numbered_pdf) { - $pdf = $numbered_pdf; - } - - return $pdf; - } - - $pdf = (new PreviewPdf($html, $company))->handle(); - if (Ninja::isHosted()) { LightLogs::create(new LivePreview()) ->increment() @@ -429,11 +293,6 @@ class PreviewController extends BaseController } - private function stubTemplateData() - { - - } - private function blankEntity() { diff --git a/app/Jobs/Entity/CreateRawPdf.php b/app/Jobs/Entity/CreateRawPdf.php index 70c5754f9243..57e214784071 100644 --- a/app/Jobs/Entity/CreateRawPdf.php +++ b/app/Jobs/Entity/CreateRawPdf.php @@ -11,34 +11,23 @@ namespace App\Jobs\Entity; -use App\Utils\Ninja; use App\Models\Quote; use App\Models\Credit; -use App\Models\Design; use App\Models\Invoice; -use App\Utils\HtmlEngine; use App\Models\PurchaseOrder; use App\Models\QuoteInvitation; use App\Utils\Traits\MakesHash; use App\Models\CreditInvitation; use App\Models\RecurringInvoice; use App\Services\Pdf\PdfService; -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 App\Models\PurchaseOrderInvitation; use App\Utils\Traits\Pdf\PageNumbering; use App\Exceptions\FilePermissionsFailure; use App\Models\RecurringInvoiceInvitation; -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; class CreateRawPdf { @@ -79,8 +68,6 @@ class CreateRawPdf $this->entity_string = 'purchase_order'; } - $this->company = $invitation->company; - $this->contact = $invitation->contact; } private function resolveType(): string @@ -112,191 +99,12 @@ class CreateRawPdf ]); $pdf = $ps->boot()->getPdf(); - return $pdf; nlog("pdf timer = ". $ps->execution_time); - - /* Forget the singleton*/ - App::forgetInstance('translator'); - - /* Init a new copy of the translator*/ - $t = app('translator'); - /* Set the locale*/ - App::setLocale($this->contact->preferredLocale()); - - /* Set customized translations _NOW_ */ - $t->replace(Ninja::transformTranslations($this->entity->client->getMergedSettings())); - - if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { - return (new Phantom)->generate($this->invitation, true); - } - - $entity_design_id = ''; - $path = ''; - - if ($this->entity instanceof Invoice) { - $path = $this->entity->client->invoice_filepath($this->invitation); - $entity_design_id = 'invoice_design_id'; - } elseif ($this->entity instanceof Quote) { - $path = $this->entity->client->quote_filepath($this->invitation); - $entity_design_id = 'quote_design_id'; - } elseif ($this->entity instanceof Credit) { - $path = $this->entity->client->credit_filepath($this->invitation); - $entity_design_id = 'credit_design_id'; - } elseif ($this->entity instanceof RecurringInvoice) { - $path = $this->entity->client->recurring_invoice_filepath($this->invitation); - $entity_design_id = 'invoice_design_id'; - } - - $file_path = $path.$this->entity->numberFormatter().'.pdf'; - - $entity_design_id = $this->entity->design_id ? $this->entity->design_id : $this->decodePrimaryKey($this->entity->client->getSetting($entity_design_id)); - - $design = Design::query()->withTrashed()->find($entity_design_id); - - /* Catch all in case migration doesn't pass back a valid design */ - if (! $design) { - $design = Design::query()->find(2); - } - - $html = new HtmlEngine($this->invitation); - - if ($design->is_custom) { - $options = [ - 'custom_partials' => json_decode(json_encode($design->design), true), - ]; - $template = new PdfMakerDesign(PdfDesignModel::CUSTOM, $options); - } else { - $template = new PdfMakerDesign(strtolower($design->name)); - } - - $variables = $html->generateLabelsAndValues(); - - $state = [ - 'template' => $template->elements([ - 'client' => $this->entity->client, - 'entity' => $this->entity, - 'pdf_variables' => (array) $this->entity->company->settings->pdf_variables, - '$product' => $design->design->product, - 'variables' => $variables, - ]), - 'variables' => $variables, - 'options' => [ - 'all_pages_header' => $this->entity->client->getSetting('all_pages_header'), - 'all_pages_footer' => $this->entity->client->getSetting('all_pages_footer'), - 'client' => $this->entity->client, - 'entity' => $this->entity, - 'variables' => $variables, - ], - 'process_markdown' => $this->entity->client->company->markdown_enabled, - ]; - - $maker = new PdfMakerService($state); - - $maker - ->design($template) - ->build(); - - $pdf = null; - - try { - if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { - $pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true)); - - $finfo = new \finfo(FILEINFO_MIME); - - //fallback in case hosted PDF fails. - if ($finfo->buffer($pdf) != 'application/pdf; charset=binary') { - $pdf = $this->makePdf(null, null, $maker->getCompiledHTML(true)); - - $numbered_pdf = $this->pageNumbering($pdf, $this->company); - - if ($numbered_pdf) { - $pdf = $numbered_pdf; - } - } - } else { - $pdf = $this->makePdf(null, null, $maker->getCompiledHTML(true)); - - $numbered_pdf = $this->pageNumbering($pdf, $this->company); - - if ($numbered_pdf) { - $pdf = $numbered_pdf; - } - } - } catch (\Exception $e) { - nlog(print_r($e->getMessage(), 1)); - } - - if (config('ninja.log_pdf_html')) { - info($maker->getCompiledHTML()); - } - - if ($pdf) { - $maker =null; - $state = null; - - return $this->checkEInvoice($pdf); - } + return $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 || !$this->company->getSetting('enable_e_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/Services/Client/Statement.php b/app/Services/Client/Statement.php index 41a2f7127ca6..53c15a736901 100644 --- a/app/Services/Client/Statement.php +++ b/app/Services/Client/Statement.php @@ -158,8 +158,7 @@ class Statement ->where('company_id', $this->client->company_id) ->first(); - $ts = $template->service(); - $ts->build([ + $ts = $template->service()->build([ 'variables' => collect([$variables]), 'invoices' => $this->getInvoices()->get(), 'payments' => $this->options['show_payments_table'] ? $this->getPayments()->get() : collect([]), @@ -167,7 +166,6 @@ class Statement 'aging' => $this->options['show_aging_table'] ? $this->getAging() : collect([]), ]); - // $ts->overrideVariables([$variables]); $html = $ts->getHtml(); return $this->convertToPdf($html); diff --git a/app/Services/Pdf/PdfBuilder.php b/app/Services/Pdf/PdfBuilder.php index ef2328955d56..1ebf44467a45 100644 --- a/app/Services/Pdf/PdfBuilder.php +++ b/app/Services/Pdf/PdfBuilder.php @@ -65,11 +65,11 @@ class PdfBuilder public function build(): self { $this->getTemplate() - ->buildSections() - ->getEmptyElements() - ->updateElementProperties() - ->parseTwigElements() - ->updateVariables(); + ->buildSections() + ->getEmptyElements() + ->updateElementProperties() + ->parseTwigElements() + ->updateVariables(); return $this; } @@ -1680,6 +1680,7 @@ class PdfBuilder } if ($contains_html) { + // If the element contains the HTML, we gonna display it as is. Backend is going to // encode it for us, preventing any errors on the processing stage. // Later, we decode this using Javascript so it looks like it's normal HTML being injected. @@ -1688,9 +1689,11 @@ class PdfBuilder $_child = $this->document->createElement($child['element'], ''); $_child->setAttribute('data-state', 'encoded-html'); $_child->nodeValue = htmlspecialchars($child['content']); + + } else { // .. in case string doesn't contain any HTML, we'll just return - // raw $content. + // raw $content $_child = $this->document->createElement($child['element'], isset($child['content']) ? htmlspecialchars($child['content']) : ''); } diff --git a/app/Services/Pdf/PdfConfiguration.php b/app/Services/Pdf/PdfConfiguration.php index 3b97e841c1ab..a5783fbb4a8c 100644 --- a/app/Services/Pdf/PdfConfiguration.php +++ b/app/Services/Pdf/PdfConfiguration.php @@ -276,7 +276,7 @@ class PdfConfiguration { $design_id = $this->entity->design_id ?: $this->decodePrimaryKey($this->settings_object->getSetting($this->entity_design_id)); - $this->design = Design::withTrashed()->find($design_id ?? 2); + $this->design = Design::withTrashed()->find($design_id) ?? Design::withTrashed()->find(2); return $this; } diff --git a/app/Services/Template/TemplateService.php b/app/Services/Template/TemplateService.php index 84c67de969ee..0528bd133246 100644 --- a/app/Services/Template/TemplateService.php +++ b/app/Services/Template/TemplateService.php @@ -99,7 +99,11 @@ class TemplateService }); $this->twig->addFunction($function); - $filter = new \Twig\TwigFilter('sum', function (array $array, string $column) { + $filter = new \Twig\TwigFilter('sum', function (?array $array, ?string $column) { + + if(!is_array($array)) + return 0; + return array_sum(array_column($array, $column)); }); @@ -1424,11 +1428,11 @@ class TemplateService $_child = $this->document->createElement($child['element'], ''); $_child->setAttribute('data-state', 'encoded-html'); $_child->nodeValue = htmlspecialchars($child['content']); + } else { // .. in case string doesn't contain any HTML, we'll just return // raw $content. - - $_child = $this->document->createElement($child['element'], isset($child['content']) ? htmlspecialchars($child['content']) : ''); + $_child = $this->document->createElement($child['element'], isset($child['content']) ? $child['content'] : ''); } $element->appendChild($_child); From 1c15f923ae611a526a1965f1c26916a99b669d46 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 15 Nov 2023 15:36:24 +1100 Subject: [PATCH 6/7] Fixes for timezone offsets --- app/Http/Requests/Payment/StorePaymentRequest.php | 2 +- app/Models/Client.php | 8 +------- app/Models/Company.php | 7 ++++++- app/PaymentDrivers/BaseDriver.php | 2 +- app/Services/Credit/CreditService.php | 2 +- app/Services/Invoice/AutoBillInvoice.php | 2 +- app/Services/Invoice/MarkPaid.php | 2 +- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/app/Http/Requests/Payment/StorePaymentRequest.php b/app/Http/Requests/Payment/StorePaymentRequest.php index 4c2788908b9a..75769fda1a5f 100644 --- a/app/Http/Requests/Payment/StorePaymentRequest.php +++ b/app/Http/Requests/Payment/StorePaymentRequest.php @@ -93,7 +93,7 @@ class StorePaymentRequest extends Request } if (! isset($input['date'])) { - $input['date'] = now()->addSeconds($user->company()->timezone()->utc_offset)->format('Y-m-d'); + $input['date'] = now()->addSeconds($user->company()->utc_offset())->format('Y-m-d'); } if (! isset($input['idempotency_key'])) { diff --git a/app/Models/Client.php b/app/Models/Client.php index bb83e7297552..c5e41724cf8d 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -776,14 +776,8 @@ class Client extends BaseModel implements HasLocalePreference return 0; } - $timezone = $this->company->timezone(); + $offset -= $this->company->utc_offset(); - //2023-11-08 adjustments for DST - date_default_timezone_set('GMT'); - $date = new \DateTime("now", new \DateTimeZone($timezone->name)); - $offset -= $date->getOffset(); - -// $offset -= $timezone->utc_offset; $offset += ($entity_send_time * 3600); return $offset; diff --git a/app/Models/Company.php b/app/Models/Company.php index 2f10c9d9ae2a..9ab2e5a280a7 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -911,9 +911,14 @@ class Company extends BaseModel public function utc_offset(): int { + $offset = 0; $timezone = $this->timezone(); - return $timezone->utc_offset ?? 0; + date_default_timezone_set('GMT'); + $date = new \DateTime("now", new \DateTimeZone($timezone->name)); + $offset = $date->getOffset(); + + return $offset; } public function timezone_offset(): int diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index d1e2eddc6ec3..6bba73c0cb67 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -325,7 +325,7 @@ class BaseDriver extends AbstractPaymentDriver $payment->company_gateway_id = $this->company_gateway->id; $payment->status_id = $status; $payment->currency_id = $this->client->getSetting('currency_id'); - $payment->date = Carbon::now()->addSeconds($this->client->company->timezone()->utc_offset)->format('Y-m-d'); + $payment->date = Carbon::now()->addSeconds($this->client->company->utc_offset())->format('Y-m-d'); $payment->gateway_type_id = $data['gateway_type_id']; $client_contact = $this->getContact(); diff --git a/app/Services/Credit/CreditService.php b/app/Services/Credit/CreditService.php index a6c5bbcdef69..d96efd669705 100644 --- a/app/Services/Credit/CreditService.php +++ b/app/Services/Credit/CreditService.php @@ -119,7 +119,7 @@ class CreditService $payment->type_id = PaymentType::CREDIT; $payment->is_manual = true; $payment->currency_id = $this->credit->client->getSetting('currency_id'); - $payment->date = now()->addSeconds($this->credit->company->timezone()->utc_offset)->format('Y-m-d'); + $payment->date = now()->addSeconds($this->credit->company->utc_offset())->format('Y-m-d'); $payment->saveQuietly(); $payment->number = $payment->client->getNextPaymentNumber($payment->client, $payment); diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index 1464d3f0dbff..1d9aaf7d4f9a 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -182,7 +182,7 @@ class AutoBillInvoice extends AbstractService // $payment->applied = $amount; $payment->client_id = $this->invoice->client_id; $payment->currency_id = $this->invoice->client->getSetting('currency_id'); - $payment->date = now()->addSeconds($this->invoice->company->timezone()->utc_offset)->format('Y-m-d'); + $payment->date = now()->addSeconds($this->invoice->company->utc_offset())->format('Y-m-d'); $payment->status_id = Payment::STATUS_COMPLETED; $payment->type_id = PaymentType::CREDIT; $payment->service()->applyNumber()->save(); diff --git a/app/Services/Invoice/MarkPaid.php b/app/Services/Invoice/MarkPaid.php index 8899377af7a4..3ecd0acb1d0b 100644 --- a/app/Services/Invoice/MarkPaid.php +++ b/app/Services/Invoice/MarkPaid.php @@ -72,7 +72,7 @@ class MarkPaid extends AbstractService $payment->is_manual = true; if ($this->invoice->company->timezone()) { - $payment->date = now()->addSeconds($this->invoice->company->timezone()->utc_offset)->format('Y-m-d'); + $payment->date = now()->addSeconds($this->invoice->company->utc_offset())->format('Y-m-d'); } $payment_type_id = $this->invoice->client->getSetting('payment_type_id'); From 42ab91932839f969c8d98d6705374f83d4454706 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 15 Nov 2023 16:14:53 +1100 Subject: [PATCH 7/7] v5.7.50 --- VERSION.txt | 2 +- config/ninja.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index de824ef2c595..4cc3a81cbfba 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.7.49 \ No newline at end of file +5.7.50 \ No newline at end of file diff --git a/config/ninja.php b/config/ninja.php index 2728bc291033..ae4470c341f9 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -15,8 +15,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => env('APP_VERSION','5.7.49'), - 'app_tag' => env('APP_TAG','5.7.49'), + 'app_version' => env('APP_VERSION','5.7.50'), + 'app_tag' => env('APP_TAG','5.7.50'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false),