From 475831bf7022bbad71ea1a056817e0169ed92a11 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 2 Mar 2022 13:26:30 +1100 Subject: [PATCH 1/7] Refactor for bulk downloads --- app/Http/Controllers/CreditController.php | 19 ++++++ app/Http/Controllers/QuoteController.php | 2 +- app/Jobs/Invoice/ZipInvoices.php | 83 ++++++++++++++++------- 3 files changed, 77 insertions(+), 27 deletions(-) diff --git a/app/Http/Controllers/CreditController.php b/app/Http/Controllers/CreditController.php index 82e6c7e022..4268046da8 100644 --- a/app/Http/Controllers/CreditController.php +++ b/app/Http/Controllers/CreditController.php @@ -26,6 +26,7 @@ use App\Http\Requests\Credit\UpdateCreditRequest; use App\Http\Requests\Credit\UploadCreditRequest; use App\Jobs\Entity\EmailEntity; use App\Jobs\Invoice\EmailCredit; +use App\Jobs\Invoice\ZipInvoices; use App\Models\Account; use App\Models\Client; use App\Models\Credit; @@ -511,6 +512,24 @@ class CreditController extends BaseController return response()->json(['message' => ctrans('texts.no_credits_found')]); } + /* + * Download Invoice/s + */ + + if ($action == 'bulk_download' && $credits->count() > 1) { + $credits->each(function ($invoice) { + if (auth()->user()->cannot('view', $credit)) { + nlog("access denied"); + return response()->json(['message' => ctrans('text.access_denied')]); + } + }); + + ZipInvoices::dispatch($credits, $credits->first()->company, auth()->user()); + + return response()->json(['message' => ctrans('texts.sent_message')], 200); + } + + $credits->each(function ($credit, $key) use ($action) { if (auth()->user()->can('edit', $credit)) { $this->performAction($credit, $action, true); diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index 5836d2091c..cc24d53384 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -527,7 +527,7 @@ class QuoteController extends BaseController * Download Invoice/s */ - if ($action == 'download' && $quotes->count() >= 1) { + if ($action == 'bulk_download' && $quotes->count() >= 1) { $quotes->each(function ($quote) { if (auth()->user()->cannot('view', $quote)) { return response()->json(['message'=> ctrans('texts.access_denied')]); diff --git a/app/Jobs/Invoice/ZipInvoices.php b/app/Jobs/Invoice/ZipInvoices.php index 18fa2f0b95..8edf82b567 100644 --- a/app/Jobs/Invoice/ZipInvoices.php +++ b/app/Jobs/Invoice/ZipInvoices.php @@ -70,40 +70,71 @@ class ZipInvoices implements ShouldQueue public function handle() { # create new zip object - $zip = new ZipArchive(); - - $invitation = $this->invoices->first()->invitations->first(); - $path = $this->invoices->first()->client->invoice_filepath($invitation); + $zipFile = new \PhpZip\ZipFile(); $file_name = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip'; - - $tmp_file = @tempnam('.', ''); - $zip->open($tmp_file , ZipArchive::OVERWRITE); + $invitation = $this->invoices->invitations->first(); + $path = $this->invoices->first()->client->invoice_filepath($invitation); - # loop through each file - foreach ($this->invoices as $invoice) { + try{ - $inv = $invoice->invitations->first(); + foreach ($this->invoices as $invoice) { + + $download_file = file_get_contents($invoice->pdf_file_path($invitation, 'url', true)); + $zipFile->addFromString(basename($invoice->pdf_file_path($invitation)), $download_file); - # download file - $download_file = file_get_contents($invoice->pdf_file_path($inv, 'url', true)); + } - #add it to the zip - $zip->addFromString(basename($invoice->pdf_file_path($inv)), $download_file); + Storage::put($path.$file_name, $zipFile->outputAsString()); + + $nmo = new NinjaMailerObject; + $nmo->mailable = new DownloadInvoices(Storage::url($path.$file_name), $this->company); + $nmo->to_user = $this->user; + $nmo->settings = $this->settings; + $nmo->company = $this->company; + + NinjaMailerJob::dispatch($nmo); + + UnlinkFile::dispatch(config('filesystems.default'), $path.$file_name)->delay(now()->addHours(1)); + + + } + catch(\PhpZip\Exception\ZipException $e){ + // handle exception + } + finally{ + $zipFile->close(); } - # close zip - $zip->close(); - - Storage::put($path.$file_name, file_get_contents($tmp_file)); - $nmo = new NinjaMailerObject; - $nmo->mailable = new DownloadInvoices(Storage::url($path.$file_name), $this->company); - $nmo->to_user = $this->user; - $nmo->settings = $this->settings; - $nmo->company = $this->company; + } + + private function zipFiles() + { + + $zipFile = new \PhpZip\ZipFile(); + $file_name = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip'; + $invitation = $this->invoices->invitations->first(); + $path = $this->invoices->first()->client->invoice_filepath($invitation); + + try{ + + foreach ($this->invoices as $invoice) { - NinjaMailerJob::dispatch($nmo); - - UnlinkFile::dispatch(config('filesystems.default'), $path.$file_name)->delay(now()->addHours(1)); + $download_file = file_get_contents($invoice->pdf_file_path($invitation, 'url', true)); + $zipFile->addFromString(basename($invoice->pdf_file_path($invitation)), $download_file); + + } + + Storage::put($path.$file_name, $zipFile->outputAsString()); + + + } + catch(\PhpZip\Exception\ZipException $e){ + // handle exception + } + finally{ + $zipFile->close(); + } + } } From 1b256dba9b36bbf85da6a483dbfe2d89bdd6500a Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 2 Mar 2022 13:51:38 +1100 Subject: [PATCH 2/7] refactor for bulk downloads --- app/Http/Controllers/CreditController.php | 7 +- app/Http/Controllers/QuoteController.php | 3 +- app/Jobs/Credit/ZipCredits.php | 115 ++++++++++++++++++++++ app/Jobs/Invoice/ZipInvoices.php | 34 +------ app/Jobs/Quote/ZipQuotes.php | 114 +++++++++++++++++++++ app/Mail/DownloadCredits.php | 53 ++++++++++ app/Mail/DownloadInvoices.php | 9 ++ app/Mail/DownloadQuotes.php | 53 ++++++++++ resources/lang/en/texts.php | 3 + 9 files changed, 357 insertions(+), 34 deletions(-) create mode 100644 app/Jobs/Credit/ZipCredits.php create mode 100644 app/Jobs/Quote/ZipQuotes.php create mode 100644 app/Mail/DownloadCredits.php create mode 100644 app/Mail/DownloadQuotes.php diff --git a/app/Http/Controllers/CreditController.php b/app/Http/Controllers/CreditController.php index 4268046da8..081cdde4c9 100644 --- a/app/Http/Controllers/CreditController.php +++ b/app/Http/Controllers/CreditController.php @@ -24,6 +24,7 @@ use App\Http\Requests\Credit\ShowCreditRequest; use App\Http\Requests\Credit\StoreCreditRequest; use App\Http\Requests\Credit\UpdateCreditRequest; use App\Http\Requests\Credit\UploadCreditRequest; +use App\Jobs\Credit\ZipCredits; use App\Jobs\Entity\EmailEntity; use App\Jobs\Invoice\EmailCredit; use App\Jobs\Invoice\ZipInvoices; @@ -506,7 +507,7 @@ class CreditController extends BaseController $ids = request()->input('ids'); - $credits = Credit::withTrashed()->whereIn('id', $this->transformKeys($ids)); + $credits = Credit::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get(); if (! $credits) { return response()->json(['message' => ctrans('texts.no_credits_found')]); @@ -517,14 +518,14 @@ class CreditController extends BaseController */ if ($action == 'bulk_download' && $credits->count() > 1) { - $credits->each(function ($invoice) { + $credits->each(function ($credit) { if (auth()->user()->cannot('view', $credit)) { nlog("access denied"); return response()->json(['message' => ctrans('text.access_denied')]); } }); - ZipInvoices::dispatch($credits, $credits->first()->company, auth()->user()); + ZipCredits::dispatch($credits, $credits->first()->company, auth()->user()); return response()->json(['message' => ctrans('texts.sent_message')], 200); } diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index cc24d53384..6f14b3a18b 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -27,6 +27,7 @@ use App\Http\Requests\Quote\StoreQuoteRequest; use App\Http\Requests\Quote\UpdateQuoteRequest; use App\Http\Requests\Quote\UploadQuoteRequest; use App\Jobs\Invoice\ZipInvoices; +use App\Jobs\Quote\ZipQuotes; use App\Models\Account; use App\Models\Client; use App\Models\Invoice; @@ -534,7 +535,7 @@ class QuoteController extends BaseController } }); - ZipInvoices::dispatch($quotes, $quotes->first()->company, auth()->user()); + ZipQuotes::dispatch($quotes, $quotes->first()->company, auth()->user()); return response()->json(['message' => ctrans('texts.sent_message')], 200); } diff --git a/app/Jobs/Credit/ZipCredits.php b/app/Jobs/Credit/ZipCredits.php new file mode 100644 index 0000000000..79d46bfe98 --- /dev/null +++ b/app/Jobs/Credit/ZipCredits.php @@ -0,0 +1,115 @@ +credits = $credits; + + $this->company = $company; + + $this->user = $user; + + $this->settings = $company->settings; + } + + /** + * Execute the job. + * + * @return void + * @throws \ZipStream\Exception\FileNotFoundException + * @throws \ZipStream\Exception\FileNotReadableException + * @throws \ZipStream\Exception\OverflowException + */ + + public function handle() + { + MultiDB::setDb($this->company->db); + + # create new zip object + $zipFile = new \PhpZip\ZipFile(); + $file_name = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.credits')).'.zip'; + $invitation = $this->credits->first()->invitations->first(); + $path = $this->credits->first()->client->quote_filepath($invitation); + + try{ + + foreach ($this->credits as $credit) { + + $download_file = file_get_contents($credit->pdf_file_path($invitation, 'url', true)); + $zipFile->addFromString(basename($credit->pdf_file_path($invitation)), $download_file); + + } + + Storage::put($path.$file_name, $zipFile->outputAsString()); + + $nmo = new NinjaMailerObject; + $nmo->mailable = new DownloadCredits(Storage::url($path.$file_name), $this->company); + $nmo->to_user = $this->user; + $nmo->settings = $this->settings; + $nmo->company = $this->company; + + NinjaMailerJob::dispatch($nmo); + + UnlinkFile::dispatch(config('filesystems.default'), $path.$file_name)->delay(now()->addHours(1)); + + + } + catch(\PhpZip\Exception\ZipException $e){ + // handle exception + } + finally{ + $zipFile->close(); + } + + + } + +} diff --git a/app/Jobs/Invoice/ZipInvoices.php b/app/Jobs/Invoice/ZipInvoices.php index 8edf82b567..77336159cd 100644 --- a/app/Jobs/Invoice/ZipInvoices.php +++ b/app/Jobs/Invoice/ZipInvoices.php @@ -14,6 +14,7 @@ namespace App\Jobs\Invoice; use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerObject; use App\Jobs\Util\UnlinkFile; +use App\Libraries\MultiDB; use App\Mail\DownloadInvoices; use App\Models\Company; use App\Models\User; @@ -69,10 +70,12 @@ class ZipInvoices implements ShouldQueue public function handle() { + MultiDB::setDb($this->company->db); + # create new zip object $zipFile = new \PhpZip\ZipFile(); $file_name = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip'; - $invitation = $this->invoices->invitations->first(); + $invitation = $this->invoices->first()->invitations->first(); $path = $this->invoices->first()->client->invoice_filepath($invitation); try{ @@ -108,33 +111,4 @@ class ZipInvoices implements ShouldQueue } - private function zipFiles() - { - - $zipFile = new \PhpZip\ZipFile(); - $file_name = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.invoices')).'.zip'; - $invitation = $this->invoices->invitations->first(); - $path = $this->invoices->first()->client->invoice_filepath($invitation); - - try{ - - foreach ($this->invoices as $invoice) { - - $download_file = file_get_contents($invoice->pdf_file_path($invitation, 'url', true)); - $zipFile->addFromString(basename($invoice->pdf_file_path($invitation)), $download_file); - - } - - Storage::put($path.$file_name, $zipFile->outputAsString()); - - - } - catch(\PhpZip\Exception\ZipException $e){ - // handle exception - } - finally{ - $zipFile->close(); - } - - } } diff --git a/app/Jobs/Quote/ZipQuotes.php b/app/Jobs/Quote/ZipQuotes.php new file mode 100644 index 0000000000..8c40a97623 --- /dev/null +++ b/app/Jobs/Quote/ZipQuotes.php @@ -0,0 +1,114 @@ +quotes = $quotes; + + $this->company = $company; + + $this->user = $user; + + $this->settings = $company->settings; + } + + /** + * Execute the job. + * + * @return void + * @throws \ZipStream\Exception\FileNotFoundException + * @throws \ZipStream\Exception\FileNotReadableException + * @throws \ZipStream\Exception\OverflowException + */ + + public function handle() + { + MultiDB::setDb($this->company->db); + + # create new zip object + $zipFile = new \PhpZip\ZipFile(); + $file_name = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.quotes')).'.zip'; + $invitation = $this->quotes->first()->invitations->first(); + $path = $this->quotes->first()->client->quote_filepath($invitation); + + try{ + + foreach ($this->quotes as $quote) { + + $download_file = file_get_contents($quote->pdf_file_path($invitation, 'url', true)); + $zipFile->addFromString(basename($quote->pdf_file_path($invitation)), $download_file); + + } + + Storage::put($path.$file_name, $zipFile->outputAsString()); + + $nmo = new NinjaMailerObject; + $nmo->mailable = new DownloadQuotes(Storage::url($path.$file_name), $this->company); + $nmo->to_user = $this->user; + $nmo->settings = $this->settings; + $nmo->company = $this->company; + + NinjaMailerJob::dispatch($nmo); + + UnlinkFile::dispatch(config('filesystems.default'), $path.$file_name)->delay(now()->addHours(1)); + + + } + catch(\PhpZip\Exception\ZipException $e){ + // handle exception + } + finally{ + $zipFile->close(); + } + + + } + +} diff --git a/app/Mail/DownloadCredits.php b/app/Mail/DownloadCredits.php new file mode 100644 index 0000000000..85b8b1e9c7 --- /dev/null +++ b/app/Mail/DownloadCredits.php @@ -0,0 +1,53 @@ +file_path = $file_path; + + $this->company = $company; + } + + /** + * Build the message. + */ + public function build() + { + + App::setLocale($this->company->getLocale()); + + return $this->from(config('mail.from.address'), config('mail.from.name')) + ->subject(ctrans('texts.download_files')) + ->view('email.admin.download_credits', [ + 'url' => $this->file_path, + 'logo' => $this->company->present()->logo, + 'whitelabel' => $this->company->account->isPaid() ? true : false, + 'settings' => $this->company->settings, + 'greeting' => $this->company->present()->name(), + ]); + } +} diff --git a/app/Mail/DownloadInvoices.php b/app/Mail/DownloadInvoices.php index ba82d325a7..51846f667c 100644 --- a/app/Mail/DownloadInvoices.php +++ b/app/Mail/DownloadInvoices.php @@ -1,4 +1,13 @@ file_path = $file_path; + + $this->company = $company; + } + + /** + * Build the message. + */ + public function build() + { + + App::setLocale($this->company->getLocale()); + + return $this->from(config('mail.from.address'), config('mail.from.name')) + ->subject(ctrans('texts.download_files')) + ->view('email.admin.download_quotes', [ + 'url' => $this->file_path, + 'logo' => $this->company->present()->logo, + 'whitelabel' => $this->company->account->isPaid() ? true : false, + 'settings' => $this->company->settings, + 'greeting' => $this->company->present()->name(), + ]); + } +} diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index d6679f4db6..900e67e712 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -4566,6 +4566,9 @@ $LANG = array( 'upgrade_to_add_company' => 'Upgrade your plan to add companies', 'file_saved_in_downloads_folder' => 'The file has been saved in the downloads folder', 'small' => 'Small', + 'quotes_backup_subject' => 'Your quotes are ready for download', + 'credits_backup_subject' => 'Your credits are ready for download', + ); return $LANG; From 8e33463bf7d20d5cd0b8e63c425754734dbcda59 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 2 Mar 2022 14:17:45 +1100 Subject: [PATCH 3/7] Fixes for bulk downloading pdfs --- app/Jobs/Credit/ZipCredits.php | 8 ++++++++ app/Jobs/Invoice/ZipInvoices.php | 9 +++++++++ app/Jobs/Quote/ZipQuotes.php | 10 ++++++++++ 3 files changed, 27 insertions(+) diff --git a/app/Jobs/Credit/ZipCredits.php b/app/Jobs/Credit/ZipCredits.php index 79d46bfe98..81e6d8518c 100644 --- a/app/Jobs/Credit/ZipCredits.php +++ b/app/Jobs/Credit/ZipCredits.php @@ -11,6 +11,7 @@ namespace App\Jobs\Credit; +use App\Jobs\Entity\CreateEntityPdf; use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerObject; use App\Jobs\Util\UnlinkFile; @@ -79,6 +80,13 @@ class ZipCredits implements ShouldQueue $invitation = $this->credits->first()->invitations->first(); $path = $this->credits->first()->client->quote_filepath($invitation); + + $this->credits->each(function ($credit){ + + CreateEntityPdf::dispatchNow($credit->invitations()->first()); + + }); + try{ foreach ($this->credits as $credit) { diff --git a/app/Jobs/Invoice/ZipInvoices.php b/app/Jobs/Invoice/ZipInvoices.php index 77336159cd..476307dca8 100644 --- a/app/Jobs/Invoice/ZipInvoices.php +++ b/app/Jobs/Invoice/ZipInvoices.php @@ -11,6 +11,7 @@ namespace App\Jobs\Invoice; +use App\Jobs\Entity\CreateEntityPdf; use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerObject; use App\Jobs\Util\UnlinkFile; @@ -40,6 +41,8 @@ class ZipInvoices implements ShouldQueue public $settings; + public $tries = 1; + /** * @param $invoices * @param Company $company @@ -78,6 +81,12 @@ class ZipInvoices implements ShouldQueue $invitation = $this->invoices->first()->invitations->first(); $path = $this->invoices->first()->client->invoice_filepath($invitation); + $this->invoices->each(function ($invoice){ + + CreateEntityPdf::dispatchNow($invoice->invitations()->first()); + + }); + try{ foreach ($this->invoices as $invoice) { diff --git a/app/Jobs/Quote/ZipQuotes.php b/app/Jobs/Quote/ZipQuotes.php index 8c40a97623..50bce4607e 100644 --- a/app/Jobs/Quote/ZipQuotes.php +++ b/app/Jobs/Quote/ZipQuotes.php @@ -11,6 +11,7 @@ namespace App\Jobs\Quote; +use App\Jobs\Entity\CreateEntityPdf; use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerObject; use App\Jobs\Util\UnlinkFile; @@ -40,6 +41,8 @@ class ZipQuotes implements ShouldQueue public $settings; + public $tries = 1; + /** * @param $invoices * @param Company $company @@ -78,6 +81,13 @@ class ZipQuotes implements ShouldQueue $invitation = $this->quotes->first()->invitations->first(); $path = $this->quotes->first()->client->quote_filepath($invitation); + + $this->quotes->each(function ($quote){ + + CreateEntityPdf::dispatchNow($quote->invitations()->first()); + + }); + try{ foreach ($this->quotes as $quote) { From bdeb31d4b4ca0b6cb1f47dd5d694dd40456de1a0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 3 Mar 2022 09:22:31 +1100 Subject: [PATCH 4/7] Fixes for wave imports --- app/Import/Providers/Wave.php | 4 ++ .../Transformer/Wave/InvoiceTransformer.php | 39 ++++++++++++++++--- app/PaymentDrivers/Stripe/CreditCard.php | 4 +- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/app/Import/Providers/Wave.php b/app/Import/Providers/Wave.php index bed0e1fdf6..c4f1a106cc 100644 --- a/app/Import/Providers/Wave.php +++ b/app/Import/Providers/Wave.php @@ -140,6 +140,10 @@ class Wave extends BaseImport implements ImportInterface $entity_type = 'vendor'; $data = $this->getCsvData($entity_type); + + if(!is_array($data)) + return; + $data = $this->preTransform($data, $entity_type); if (empty($data)) { diff --git a/app/Import/Transformer/Wave/InvoiceTransformer.php b/app/Import/Transformer/Wave/InvoiceTransformer.php index 7b8e4e8e6d..68e40115b3 100644 --- a/app/Import/Transformer/Wave/InvoiceTransformer.php +++ b/app/Import/Transformer/Wave/InvoiceTransformer.php @@ -31,19 +31,30 @@ class InvoiceTransformer extends BaseTransformer { throw new ImportException( 'Invoice number already exists' ); } + if(array_key_exists('Invoice Date', $invoice_data)) + $date_key = 'Invoice Date'; + else + $date_key = 'Transaction Date'; + + if(array_key_exists('Customer Name', $invoice_data)) + $customer_key = 'Customer Name'; + else + $customer_key = 'Customer'; + $transformed = [ 'company_id' => $this->company->id, - 'client_id' => $this->getClient( $customer_name = $this->getString( $invoice_data, 'Customer' ), null ), + 'client_id' => $this->getClient( $customer_name = $this->getString( $invoice_data, $customer_key ), null ), 'number' => $invoice_number = $this->getString( $invoice_data, 'Invoice Number' ), - 'date' => date( 'Y-m-d', strtotime( $invoice_data['Transaction Date'] ) ) ?: now()->format('Y-m-d'), //27-01-2022 + 'date' => date( 'Y-m-d', strtotime( $invoice_data[$date_key] ) ) ?: now()->format('Y-m-d'), //27-01-2022 'currency_id' => $this->getCurrencyByCode( $invoice_data, 'Currency' ), 'status_id' => Invoice::STATUS_SENT, + 'due_date' => array_key_exists('Due Date', $invoice_data) ? date( 'Y-m-d', strtotime( $invoice_data['Due Date'] ) ) : null, ]; $line_items = []; $payments = []; foreach ( $line_items_data as $record ) { - if ( $record['Account Type'] === 'Income' ) { + if (array_key_exists('Account Type', $record) && $record['Account Type'] === 'Income' ) { $description = $this->getString( $record, 'Transaction Line Description' ); // Remove duplicate data from description @@ -63,13 +74,31 @@ class InvoiceTransformer extends BaseTransformer { 'quantity' => 1, ]; - } elseif ( $record['Account Type'] === 'System Receivable Invoice' ) { + } elseif (array_key_exists('Account Type', $record) && $record['Account Type'] === 'System Receivable Invoice' ) { // This is a payment $payments[] = [ - 'date' => date( 'Y-m-d', strtotime( $invoice_data['Transaction Date'] ) ), + 'date' => date( 'Y-m-d', strtotime( $invoice_data[$date_key] ) ), 'amount' => $this->getFloat( $record, 'Amount (One column)' ), ]; } + else { + //could be a generate invoices.csv file + $line_items[] = [ + 'notes' => 'Imported Invoice', + 'cost' => $this->getFloat( $record, 'Invoice Total' ), + 'tax_name1' => 'Tax', + 'tax_rate1' => round($this->getFloat( $record, 'Invoice Tax Total' ) / $this->getFloat( $record, 'Invoice Total' ) * 100,2), + 'quantity' => 1, + ]; + + if($record['Invoice Paid'] > 0){ + $payments[] = [ + 'date' => date( 'Y-m-d', strtotime( $record['Last Payment Date'] ) ), + 'amount' => $this->getFloat( $record, 'Invoice Paid' ), + ]; + } + + } } $transformed['line_items'] = $line_items; diff --git a/app/PaymentDrivers/Stripe/CreditCard.php b/app/PaymentDrivers/Stripe/CreditCard.php index 7f8451224c..6b7766a189 100644 --- a/app/PaymentDrivers/Stripe/CreditCard.php +++ b/app/PaymentDrivers/Stripe/CreditCard.php @@ -60,7 +60,9 @@ class CreditCard { - $description = $this->stripe->decodeUnicodeString(ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number')) . " for client {$this->stripe->client->present()->name()}"; + // $description = $this->stripe->decodeUnicodeString(ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number')) . " for client {$this->stripe->client->present()->name()}"; + $invoice_numbers = collect($data['invoices'])->pluck('invoice_number')->implode(','); + $description = "Invoices: {$invoice_numbers} for {$data['total']['amount_with_fee']} for client {$this->stripe->client->present()->name()}"; $payment_intent_data = [ From b73dc6769291e4f6df56e2faa897203a0577fef3 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 3 Mar 2022 11:51:44 +1100 Subject: [PATCH 5/7] Forward to correct login location - contacts --- app/Http/Controllers/Auth/ContactLoginController.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Auth/ContactLoginController.php b/app/Http/Controllers/Auth/ContactLoginController.php index f39544ea7f..fedc5910fd 100644 --- a/app/Http/Controllers/Auth/ContactLoginController.php +++ b/app/Http/Controllers/Auth/ContactLoginController.php @@ -149,7 +149,9 @@ class ContactLoginController extends Controller return redirect(session()->get('url.intended')); } - return redirect(route('client.dashboard')); + $this->setRedirectPath(); + + return redirect($this->redirectTo); } public function logout() From 84b3575022b39c6da5dd9bb0072bc7a6f62e0f13 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 3 Mar 2022 12:23:55 +1100 Subject: [PATCH 6/7] Fixes for plain email template --- resources/views/email/template/plain.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/email/template/plain.blade.php b/resources/views/email/template/plain.blade.php index 194bb06620..2d267ff864 100644 --- a/resources/views/email/template/plain.blade.php +++ b/resources/views/email/template/plain.blade.php @@ -5,7 +5,7 @@ - Invoice Ninja +
From c8d0bb93d8a1c221d7f272dc7a20cb48ece49ae0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 3 Mar 2022 12:55:29 +1100 Subject: [PATCH 7/7] Fixes for Stripe SEPA --- public/js/clients/payments/stripe-sepa.js | 2 +- public/mix-manifest.json | 2 +- resources/js/clients/payments/stripe-sepa.js | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/public/js/clients/payments/stripe-sepa.js b/public/js/clients/payments/stripe-sepa.js index 308730e5e6..660c32a249 100644 --- a/public/js/clients/payments/stripe-sepa.js +++ b/public/js/clients/payments/stripe-sepa.js @@ -1,2 +1,2 @@ /*! For license information please see stripe-sepa.js.LICENSE.txt */ -(()=>{var e,t,n,a;function o(e,t){for(var n=0;n svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),a.stripe.confirmSepaDebitPayment(document.querySelector("meta[name=pi-client-secret").content,{payment_method:document.querySelector("input[name=token]").value}).then((function(e){return e.error?a.handleFailure(e.error.message):a.handleSuccess(e)}));else{if(""===document.getElementById("sepa-name").value)return document.getElementById("sepa-name").focus(),e.textContent=document.querySelector("meta[name=translation-name-required]").content,void(e.hidden=!1);if(""===document.getElementById("sepa-email-address").value)return document.getElementById("sepa-email-address").focus(),e.textContent=document.querySelector("meta[name=translation-email-required]").content,void(e.hidden=!1);if(!document.getElementById("sepa-mandate-acceptance").checked)return e.textContent=document.querySelector("meta[name=translation-terms-required]").content,void(e.hidden=!1);document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),a.stripe.confirmSepaDebitPayment(document.querySelector("meta[name=pi-client-secret").content,{payment_method:{sepa_debit:a.iban,billing_details:{name:document.getElementById("sepa-name").value,email:document.getElementById("sepa-email-address").value}}}).then((function(e){return e.error?a.handleFailure(e.error.message):a.handleSuccess(e)}))}}))})),this.key=t,this.errors=document.getElementById("errors"),this.stripeConnect=n}var t,n,a;return t=e,(n=[{key:"handleSuccess",value:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.paymentIntent);var t=document.querySelector('input[name="token-billing-checkbox"]:checked');t&&(document.querySelector('input[name="store_card"]').value=t.value),document.getElementById("server-response").submit()}},{key:"handleFailure",value:function(e){var t=document.getElementById("errors");t.textContent="",t.textContent=e,t.hidden=!1,document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden")}}])&&o(t.prototype,n),a&&o(t,a),e}();new c(null!==(e=null===(t=document.querySelector('meta[name="stripe-publishable-key"]'))||void 0===t?void 0:t.content)&&void 0!==e?e:"",null!==(n=null===(a=document.querySelector('meta[name="stripe-account-id"]'))||void 0===a?void 0:a.content)&&void 0!==n?n:"").setupStripe().handle()})(); \ No newline at end of file +(()=>{var e,t,n,a;function o(e,t){for(var n=0;n svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),a.stripe.confirmSepaDebitPayment(document.querySelector("meta[name=pi-client-secret").content,{payment_method:document.querySelector("input[name=token]").value}).then((function(e){return e.error?a.handleFailure(e.error.message):a.handleSuccess(e)}));else{if(""===document.getElementById("sepa-name").value)return document.getElementById("sepa-name").focus(),e.textContent=document.querySelector("meta[name=translation-name-required]").content,void(e.hidden=!1);if(""===document.getElementById("sepa-email-address").value)return document.getElementById("sepa-email-address").focus(),e.textContent=document.querySelector("meta[name=translation-email-required]").content,void(e.hidden=!1);if(!document.getElementById("sepa-mandate-acceptance").checked)return e.textContent=document.querySelector("meta[name=translation-terms-required]").content,void(e.hidden=!1);document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),a.stripe.confirmSepaDebitPayment(document.querySelector("meta[name=pi-client-secret").content,{payment_method:{sepa_debit:a.iban,billing_details:{name:document.getElementById("sepa-name").value,email:document.getElementById("sepa-email-address").value}}}).then((function(e){return e.error?a.handleFailure(e.error.message):a.handleSuccess(e)}))}}))})),this.key=t,this.errors=document.getElementById("errors"),this.stripeConnect=n}var t,n,a;return t=e,(n=[{key:"handleSuccess",value:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.paymentIntent);var t=document.querySelector('input[name="token-billing-checkbox"]:checked');t&&(document.querySelector('input[name="store_card"]').value=t.value),document.querySelector("input[name=token]").value.length>2&&(document.querySelector('input[name="store_card"]').value=!1),document.getElementById("server-response").submit()}},{key:"handleFailure",value:function(e){var t=document.getElementById("errors");t.textContent="",t.textContent=e,t.hidden=!1,document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden")}}])&&o(t.prototype,n),a&&o(t,a),e}();new c(null!==(e=null===(t=document.querySelector('meta[name="stripe-publishable-key"]'))||void 0===t?void 0:t.content)&&void 0!==e?e:"",null!==(n=null===(a=document.querySelector('meta[name="stripe-account-id"]'))||void 0===a?void 0:a.content)&&void 0!==n?n:"").setupStripe().handle()})(); \ No newline at end of file diff --git a/public/mix-manifest.json b/public/mix-manifest.json index d3da8113ba..9c8af41f9f 100755 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -27,7 +27,7 @@ "/js/clients/payments/square-credit-card.js": "/js/clients/payments/square-credit-card.js?id=8f05ce6bd2d6cae7e5f2", "/js/clients/statements/view.js": "/js/clients/statements/view.js?id=4ed4c8a09803ddd0a9a7", "/js/clients/payments/razorpay-aio.js": "/js/clients/payments/razorpay-aio.js?id=c36ab5621413ef1de7c8", - "/js/clients/payments/stripe-sepa.js": "/js/clients/payments/stripe-sepa.js?id=da7b16ffaf5645535c7c", + "/js/clients/payments/stripe-sepa.js": "/js/clients/payments/stripe-sepa.js?id=9134495bcbfdd3e25aef", "/js/clients/payment_methods/authorize-checkout-card.js": "/js/clients/payment_methods/authorize-checkout-card.js?id=61becda97682c7909f29", "/js/clients/payments/stripe-giropay.js": "/js/clients/payments/stripe-giropay.js?id=2a973971ed2b890524ee", "/js/clients/payments/stripe-acss.js": "/js/clients/payments/stripe-acss.js?id=41367f4e80e52a0ab436", diff --git a/resources/js/clients/payments/stripe-sepa.js b/resources/js/clients/payments/stripe-sepa.js index 35ea27a43d..cea9e96e9c 100644 --- a/resources/js/clients/payments/stripe-sepa.js +++ b/resources/js/clients/payments/stripe-sepa.js @@ -97,8 +97,6 @@ class ProcessSEPA { document.getElementById('pay-now').addEventListener('click', (e) => { - console.log(document.querySelector('input[name=token]').value); - if (document.querySelector('input[name=token]').value.length !== 0) { document.getElementById('pay-now').disabled = true; @@ -199,6 +197,10 @@ class ProcessSEPA { tokenBillingCheckbox.value; } + if(document.querySelector('input[name=token]').value.length > 2){ + document.querySelector('input[name="store_card"]').value = false; + } + document.getElementById('server-response').submit(); }