From 039ac0c5b4bb4aa3e582829c05faefd3d8e7c248 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 25 Aug 2022 07:06:49 +1000 Subject: [PATCH 01/13] Update VERSION.txt --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index 62f9457511f8..24de8a37b784 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -6 \ No newline at end of file +v5.5.16 From 7523df31bce65b8a282faa0a82385ad8ce804807 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 25 Aug 2022 07:08:38 +1000 Subject: [PATCH 02/13] Update VERSION.txt --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index 24de8a37b784..490f8f9f33f3 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -v5.5.16 +5.5.16 From 9d09424e5eaef307ad663431018e9d1006de7470 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Oct 2022 10:28:59 +1100 Subject: [PATCH 03/13] Merg PDFs --- app/Filters/QueryFilters.php | 11 +++++++- app/Services/PdfMaker/PdfMerge.php | 40 ++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 app/Services/PdfMaker/PdfMerge.php diff --git a/app/Filters/QueryFilters.php b/app/Filters/QueryFilters.php index 83fb8a36fdc6..87bfb3288bee 100644 --- a/app/Filters/QueryFilters.php +++ b/app/Filters/QueryFilters.php @@ -169,7 +169,7 @@ abstract class QueryFilters public function clientFilter() { if (auth()->guard('contact')->user()) { - return $this->builder->whereClientId(auth()->guard('contact')->user()->client->id); + return $this->builder->where('client_id', auth()->guard('contact')->user()->client->id); } } @@ -179,6 +179,15 @@ abstract class QueryFilters $created_at = date('Y-m-d H:i:s', $value); + if(is_string($created_at)){ + + $created_at = strtotime(str_replace("/","-",$created_at)); + + if(!$created_at) + return $this->builder; + + } + return $this->builder->where('created_at', '>=', $created_at); } diff --git a/app/Services/PdfMaker/PdfMerge.php b/app/Services/PdfMaker/PdfMerge.php new file mode 100644 index 000000000000..67d53b107103 --- /dev/null +++ b/app/Services/PdfMaker/PdfMerge.php @@ -0,0 +1,40 @@ +file_paths as $file) { + $pageCount = $pdf->setSourceFile($file); + for ($i = 0; $i < $pageCount; $i++) { + $tpl = $pdf->importPage($i + 1, '/MediaBox'); + $pdf->addPage(); + $pdf->useTemplate($tpl); + } + } + + return $pdf->Output('S'); + + } + +} From 602b6a6f38243ae93254b4e129c332a550d08494 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Oct 2022 17:52:29 +1100 Subject: [PATCH 04/13] Fixes for failed payments when the paypal credentials are incorrect --- app/PaymentDrivers/PayPalExpressPaymentDriver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/PaymentDrivers/PayPalExpressPaymentDriver.php b/app/PaymentDrivers/PayPalExpressPaymentDriver.php index 86cad72f4aca..c69f680dec2b 100644 --- a/app/PaymentDrivers/PayPalExpressPaymentDriver.php +++ b/app/PaymentDrivers/PayPalExpressPaymentDriver.php @@ -95,7 +95,7 @@ class PayPalExpressPaymentDriver extends BaseDriver return $response->redirect(); } - $this->sendFailureMail($response->getMessage() ?: ''); + // $this->sendFailureMail($response->getMessage() ?: ''); $message = [ 'server_response' => $response->getMessage(), From 3ec81ea04bafa83a679f3e4fdeb7a5c8ad0f3ee2 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Oct 2022 19:52:32 +1100 Subject: [PATCH 05/13] Fixes for stripe autobilling --- app/PaymentDrivers/Stripe/Charge.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/PaymentDrivers/Stripe/Charge.php b/app/PaymentDrivers/Stripe/Charge.php index 3c927e544baa..eb6bc14558e3 100644 --- a/app/PaymentDrivers/Stripe/Charge.php +++ b/app/PaymentDrivers/Stripe/Charge.php @@ -137,6 +137,9 @@ class Charge return false; } + if($response?->status != 'succeeded') + $this->stripe->processInternallyFailedPayment($this->stripe, new \Exception('Auto billing failed.',400)); + if ($cgt->gateway_type_id == GatewayType::SEPA) { $payment_method_type = PaymentType::SEPA; $status = Payment::STATUS_PENDING; From 4108868b19cea03f121037fd6468af528d5a2032 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Oct 2022 20:48:43 +1100 Subject: [PATCH 06/13] don't link entities when we are in a transaction --- app/Repositories/BaseRepository.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Repositories/BaseRepository.php b/app/Repositories/BaseRepository.php index 1595b422eda5..127387abbfff 100644 --- a/app/Repositories/BaseRepository.php +++ b/app/Repositories/BaseRepository.php @@ -304,8 +304,9 @@ class BaseRepository if (! $model->design_id) $model->design_id = $this->decodePrimaryKey($client->getSetting('invoice_design_id')); - //links tasks and expenses back to the invoice. - $model->service()->linkEntities()->save(); + //links tasks and expenses back to the invoice, but only if we are not in the middle of a transaction. + if (\DB::transactionLevel() == 0) + $model->service()->linkEntities()->save(); if($this->new_model) event('eloquent.created: App\Models\Invoice', $model); From a2814ad13b68289409e81dc72dc763e893d1532e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Oct 2022 21:37:22 +1100 Subject: [PATCH 07/13] Fixes for payment email preview --- app/Mail/Engine/PaymentEmailEngine.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php index 8e383090ad6f..951fe587a3e1 100644 --- a/app/Mail/Engine/PaymentEmailEngine.php +++ b/app/Mail/Engine/PaymentEmailEngine.php @@ -251,17 +251,17 @@ class PaymentEmailEngine extends BaseEmailEngine private function formatInvoiceField($field) { - $invoice = ''; + $invoicex = ''; foreach ($this->payment->invoices as $invoice) { $invoice_field = $invoice->{$field}; - $invoice .= ctrans('texts.invoice_number_short') . "{$invoice->number} {$invoice_field}"; + $invoicex .= ctrans('texts.invoice_number_short') . "{$invoice->number} {$invoice_field}"; } - return $invoice; + return $invoicex; } From c5a05efdc24caa045e6e6199d7699acd89fc877c Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 31 Oct 2022 07:37:52 +1100 Subject: [PATCH 08/13] Merge PDFs --- app/Http/Controllers/InvoiceController.php | 16 ++++++++++++++++ app/Services/PdfMaker/PdfMerge.php | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 8050c433af1b..5aec198f3815 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -40,6 +40,7 @@ use App\Models\Invoice; use App\Models\Quote; use App\Models\TransactionEvent; use App\Repositories\InvoiceRepository; +use App\Services\PdfMaker\PdfMerge; use App\Transformers\InvoiceTransformer; use App\Transformers\QuoteTransformer; use App\Utils\Ninja; @@ -588,6 +589,21 @@ class InvoiceController extends BaseController } + if($action == 'merge' && auth()->user()->can('view', $invoices->first())){ + + $paths = $invoices->map(function ($invoice){ + return $invoice->service()->getInvoicePdf(); + }); + + $merge = (new PdfMerge($paths->toArray()))->run(); + + + return response()->streamDownload(function () use ($merge) { + echo ($merge); + }, 'print.pdf', ['Content-Type' => 'application/pdf']); + + } + /* * Send the other actions to the switch */ diff --git a/app/Services/PdfMaker/PdfMerge.php b/app/Services/PdfMaker/PdfMerge.php index 67d53b107103..e4b2f50137b5 100644 --- a/app/Services/PdfMaker/PdfMerge.php +++ b/app/Services/PdfMaker/PdfMerge.php @@ -12,7 +12,9 @@ namespace App\Services\PdfMaker; +use Illuminate\Support\Facades\Storage; use \setasign\Fpdi\Fpdi; +use setasign\Fpdi\PdfParser\StreamReader; class PdfMerge { @@ -25,7 +27,7 @@ class PdfMerge $pdf = new FPDI(); foreach ($this->file_paths as $file) { - $pageCount = $pdf->setSourceFile($file); + $pageCount = $pdf->setSourceFile(StreamReader::createByString(Storage::get($file))); for ($i = 0; $i < $pageCount; $i++) { $tpl = $pdf->importPage($i + 1, '/MediaBox'); $pdf->addPage(); From 37682d6f305e7efb5160e6309d685ea3da0a8c12 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 31 Oct 2022 07:50:29 +1100 Subject: [PATCH 09/13] Merge PDFs --- app/Http/Controllers/CreditController.php | 15 +++++++++++++++ app/Http/Controllers/InvoiceController.php | 1 - app/Http/Controllers/PurchaseOrderController.php | 15 +++++++++++++++ app/Http/Controllers/QuoteController.php | 15 +++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/CreditController.php b/app/Http/Controllers/CreditController.php index 55a1d03aad8e..30104c8c9fd3 100644 --- a/app/Http/Controllers/CreditController.php +++ b/app/Http/Controllers/CreditController.php @@ -33,6 +33,7 @@ use App\Models\Client; use App\Models\Credit; use App\Models\Invoice; use App\Repositories\CreditRepository; +use App\Services\PdfMaker\PdfMerge; use App\Transformers\CreditTransformer; use App\Utils\Ninja; use App\Utils\TempFile; @@ -534,6 +535,20 @@ class CreditController extends BaseController return response()->json(['message' => ctrans('texts.sent_message')], 200); } + if($action == 'merge' && auth()->user()->can('view', $credits->first())){ + + $paths = $credits->map(function ($credit){ + return $credit->service()->getCreditPdf($credit->invitations->first()); + }); + + $merge = (new PdfMerge($paths->toArray()))->run(); + + return response()->streamDownload(function () use ($merge) { + echo ($merge); + }, 'print.pdf', ['Content-Type' => 'application/pdf']); + + } + $credits->each(function ($credit, $key) use ($action) { if (auth()->user()->can('edit', $credit)) { $this->performAction($credit, $action, true); diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 5aec198f3815..8e61ae7fdbf9 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -597,7 +597,6 @@ class InvoiceController extends BaseController $merge = (new PdfMerge($paths->toArray()))->run(); - return response()->streamDownload(function () use ($merge) { echo ($merge); }, 'print.pdf', ['Content-Type' => 'application/pdf']); diff --git a/app/Http/Controllers/PurchaseOrderController.php b/app/Http/Controllers/PurchaseOrderController.php index 83d8c9cd55cb..e417027f1b31 100644 --- a/app/Http/Controllers/PurchaseOrderController.php +++ b/app/Http/Controllers/PurchaseOrderController.php @@ -32,6 +32,7 @@ use App\Models\Client; use App\Models\Expense; use App\Models\PurchaseOrder; use App\Repositories\PurchaseOrderRepository; +use App\Services\PdfMaker\PdfMerge; use App\Transformers\ExpenseTransformer; use App\Transformers\PurchaseOrderTransformer; use App\Utils\Ninja; @@ -515,6 +516,20 @@ class PurchaseOrderController extends BaseController return response()->json(['message' => ctrans('texts.sent_message')], 200); } + if($action == 'merge' && auth()->user()->can('view', $purchase_orders->first())){ + + $paths = $purchase_orders->map(function ($purchase_order){ + return $purchase_order->service()->getPurchaseOrderPdf(); + }); + + $merge = (new PdfMerge($paths->toArray()))->run(); + + return response()->streamDownload(function () use ($merge) { + echo ($merge); + }, 'print.pdf', ['Content-Type' => 'application/pdf']); + + } + /* * Send the other actions to the switch */ diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index a42c9c09c8e3..fc8f6319329c 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -35,6 +35,7 @@ use App\Models\Invoice; use App\Models\Project; use App\Models\Quote; use App\Repositories\QuoteRepository; +use App\Services\PdfMaker\PdfMerge; use App\Transformers\InvoiceTransformer; use App\Transformers\ProjectTransformer; use App\Transformers\QuoteTransformer; @@ -561,6 +562,20 @@ class QuoteController extends BaseController return $this->listResponse(Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()); } + if($action == 'merge' && auth()->user()->can('view', $quotes->first())){ + + $paths = $quotes->map(function ($quote){ + return $quote->service()->getQuotePdf(); + }); + + $merge = (new PdfMerge($paths->toArray()))->run(); + + return response()->streamDownload(function () use ($merge) { + echo ($merge); + }, 'print.pdf', ['Content-Type' => 'application/pdf']); + + } + if($action == 'convert_to_project') { From a24f23995e4a96a24e843add210581b438492930 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 31 Oct 2022 09:35:46 +1100 Subject: [PATCH 10/13] QR codes for invoics as a variable --- app/Utils/HtmlEngine.php | 1 + app/Utils/Traits/Inviteable.php | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php index 4806a89d1d35..f38e8ca9de42 100644 --- a/app/Utils/HtmlEngine.php +++ b/app/Utils/HtmlEngine.php @@ -143,6 +143,7 @@ class HtmlEngine $data['$credit.datetime'] = &$data['$entity.datetime']; $data['$payment_button'] = ['value' => ''.ctrans('texts.pay_now').'', 'label' => ctrans('texts.pay_now')]; $data['$payment_link'] = ['value' => $this->invitation->getPaymentLink(), 'label' => ctrans('texts.pay_now')]; + $data['$payment_qrcode'] = ['value' => $this->invitation->getPaymentQrCode(), 'label' => ctrans('texts.pay_now')]; if ($this->entity_string == 'invoice' || $this->entity_string == 'recurring_invoice') { diff --git a/app/Utils/Traits/Inviteable.php b/app/Utils/Traits/Inviteable.php index 7e2e6fae1455..652850330b1e 100644 --- a/app/Utils/Traits/Inviteable.php +++ b/app/Utils/Traits/Inviteable.php @@ -13,6 +13,11 @@ namespace App\Utils\Traits; use App\Utils\Ninja; use Illuminate\Support\Str; +use BaconQrCode\Renderer\ImageRenderer; +use BaconQrCode\Renderer\Image\SvgImageBackEnd; +use BaconQrCode\Renderer\RendererStyle\RendererStyle; +use BaconQrCode\Writer; + /** * Class Inviteable. @@ -54,6 +59,24 @@ trait Inviteable return $domain.'/client/pay/'.$this->key; } + public function getPaymentQrCode() + { + + $renderer = new ImageRenderer( + new RendererStyle(300), + new SvgImageBackEnd() + ); + $writer = new Writer($renderer); + + $qr = $writer->writeString($this->getPaymentLink()); + + return " + + {$qr} + "; + + } + public function getUnsubscribeLink() { if (Ninja::isHosted()) { From 7d288fc4decbe50bafa6bea242bda35d05864968 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 31 Oct 2022 09:54:23 +1100 Subject: [PATCH 11/13] QR codes for invoics as a variable --- app/Utils/Traits/Inviteable.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/Utils/Traits/Inviteable.php b/app/Utils/Traits/Inviteable.php index 652850330b1e..8b6481bd1ff0 100644 --- a/app/Utils/Traits/Inviteable.php +++ b/app/Utils/Traits/Inviteable.php @@ -63,17 +63,15 @@ trait Inviteable { $renderer = new ImageRenderer( - new RendererStyle(300), + new RendererStyle(200), new SvgImageBackEnd() ); $writer = new Writer($renderer); $qr = $writer->writeString($this->getPaymentLink()); - return " - - {$qr} - "; + return " + {$qr}"; } From 5e5e0f5848fb84cbc119b90500312223ed2fc751 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 31 Oct 2022 11:10:36 +1100 Subject: [PATCH 12/13] Return reminders to dispatch --- app/Jobs/Util/ReminderJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Jobs/Util/ReminderJob.php b/app/Jobs/Util/ReminderJob.php index 403ef964a37e..b5ed69206c61 100644 --- a/app/Jobs/Util/ReminderJob.php +++ b/app/Jobs/Util/ReminderJob.php @@ -99,7 +99,7 @@ class ReminderJob implements ShouldQueue (Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) { $invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) { - EmailEntity::dispatchSync($invitation, $invitation->company, $reminder_template); + EmailEntity::dispatch($invitation, $invitation->company, $reminder_template); nlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}"); }); From 7f056f292f0e7fb866343e63374b793304df2f6d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 31 Oct 2022 12:05:16 +1100 Subject: [PATCH 13/13] QR Code Fixes --- app/Helpers/SwissQr/SwissQrGenerator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Helpers/SwissQr/SwissQrGenerator.php b/app/Helpers/SwissQr/SwissQrGenerator.php index 6d134adf90da..b3eb796bd409 100644 --- a/app/Helpers/SwissQr/SwissQrGenerator.php +++ b/app/Helpers/SwissQr/SwissQrGenerator.php @@ -112,7 +112,7 @@ class SwissQrGenerator } else { - $invoice_number = $this->invoice->number; + $invoice_number = iconv("UTF-8", "ASCII", $this->invoice->number); } if(strlen($this->company->present()->besr_id()) > 1) @@ -141,7 +141,7 @@ class SwissQrGenerator // Optionally, add some human-readable information about what the bill is for. $qrBill->setAdditionalInformation( QrBill\DataGroup\Element\AdditionalInformation::create( - $this->invoice->public_notes ? substr($this->invoice->public_notes, 0, 139) : ctrans('texts.invoice_number_placeholder', ['invoice' => $invoice_number]) + $this->invoice->public_notes ? substr($this->invoice->public_notes, 0, 139) : ctrans('texts.invoice_number_placeholder', ['invoice' => $this->invoice->number]) ) );