From 6192e014c62dbd227eb3aa22eacf5454ab06c145 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 8 Dec 2023 12:11:53 +1100 Subject: [PATCH 01/14] Add case for transaction searches --- app/Filters/InvoiceFilters.php | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index a3feeb040047..08a6e5c6923f 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -147,15 +147,22 @@ class InvoiceFilters extends QueryFilters public function upcoming(): Builder { return $this->builder->whereIn('status_id', [Invoice::STATUS_PARTIAL, Invoice::STATUS_SENT]) - ->whereNull('due_date') - ->orWhere(function ($q) { - $q->where('due_date', '>=', now()->startOfDay()->subSecond())->where('partial', 0); - }) - ->orWhere(function ($q) { - $q->where('partial_due_date', '>=', now()->startOfDay()->subSecond())->where('partial', '>', 0); - }) - ->orderByRaw('ISNULL(due_date), due_date '. 'desc') - ->orderByRaw('ISNULL(partial_due_date), partial_due_date '. 'desc'); + ->where('is_deleted', 0) + ->where('balance', '>', 0) + ->where(function ($query) { + + $query->whereNull('due_date') + ->orWhere(function ($q) { + $q->where('due_date', '>=', now()->startOfDay()->subSecond())->where('partial', 0); + }) + ->orWhere(function ($q) { + $q->where('partial_due_date', '>=', now()->startOfDay()->subSecond())->where('partial', '>', 0); + }); + + }) + ->orderByRaw('ISNULL(due_date), due_date '. 'desc') + ->orderByRaw('ISNULL(partial_due_date), partial_due_date '. 'desc'); + } /** From ddcaead160e04bce9a867f825c97542dc2cb8c64 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 8 Dec 2023 12:57:34 +1100 Subject: [PATCH 02/14] Add checks for subdomain validation --- app/DataProviders/Domains.php | 3 ++- app/Http/Controllers/SubdomainController.php | 6 ++++++ tests/Unit/DomainCheckTest.php | 16 ++++++++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app/DataProviders/Domains.php b/app/DataProviders/Domains.php index 814baeebad0f..84ef923ed259 100644 --- a/app/DataProviders/Domains.php +++ b/app/DataProviders/Domains.php @@ -12,7 +12,8 @@ namespace App\DataProviders; -class Domains { +class Domains +{ private static array $verify_domains = [ '0-00.usa.cc', diff --git a/app/Http/Controllers/SubdomainController.php b/app/Http/Controllers/SubdomainController.php index 3800935ac85c..902fe115cfe7 100644 --- a/app/Http/Controllers/SubdomainController.php +++ b/app/Http/Controllers/SubdomainController.php @@ -30,6 +30,12 @@ class SubdomainController extends BaseController return response()->json(['message' => ctrans('texts.subdomain_is_not_available')], 401); } + + if (!preg_match('/^[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?$/', request()->input('subdomain'))) { + return response()->json(['message' => ctrans('texts.subdomain_is_not_available')], 401); + } + + return response()->json(['message' => 'Domain available'], 200); } } diff --git a/tests/Unit/DomainCheckTest.php b/tests/Unit/DomainCheckTest.php index 81bf7fd07757..ccd51be7deb4 100644 --- a/tests/Unit/DomainCheckTest.php +++ b/tests/Unit/DomainCheckTest.php @@ -28,8 +28,20 @@ class DomainCheckTest extends TestCase public function testDomainCheck() { - $this->assertTrue(in_array('yopmail.com', Domains::getDomains())); - $this->assertFalse(in_array('invoiceninja.com', Domains::getDomains())); + $this->assertTrue(in_array('yopmail.com', \App\DataProviders\Domains::getDomains())); + $this->assertFalse(in_array('invoiceninja.com', \App\DataProviders\Domains::getDomains())); } + + public function testSubdomainValidation() + { + $this->assertFalse($this->checker('invoiceninja')); + $this->assertFalse($this->checker('hello')); + $this->assertTrue($this->checker('nasty.pasty')); + } + + public function checker($subdomain) + { + return (!preg_match('/^[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?$/', $subdomain)); + } } From 82bcd84c4300a38286db61337fa6de4e10262185 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 8 Dec 2023 22:59:55 +1100 Subject: [PATCH 03/14] Set appropriate date format for payment factory --- app/Http/Controllers/PaymentController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 10b8af7dcb38..951b2a3c77e1 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -155,6 +155,7 @@ class PaymentController extends BaseController $user = auth()->user(); $payment = PaymentFactory::create($user->company()->id, $user->id); + $payment->date = now()->addSeconds($user->company()->utc_offset())->format('Y-m-d'); return $this->itemResponse($payment); } From 6727f602a1b25d825ad2ecd3a7e6db8cea18f4a7 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 9 Dec 2023 09:42:15 +1100 Subject: [PATCH 04/14] Twilio --- app/Http/Controllers/TwilioController.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Http/Controllers/TwilioController.php b/app/Http/Controllers/TwilioController.php index 39b7f726372c..c43ba09d7365 100644 --- a/app/Http/Controllers/TwilioController.php +++ b/app/Http/Controllers/TwilioController.php @@ -21,6 +21,7 @@ use Twilio\Rest\Client; class TwilioController extends BaseController { + public function __construct() { parent::__construct(); @@ -38,6 +39,10 @@ class TwilioController extends BaseController $account = $user->company()->account; + if(stripos($request->phone, '+21') !== false) { + return response()->json(['message' => 'This phone number is not supported'], 400); + } + if (MultiDB::hasPhoneNumber($request->phone)) { return response()->json(['message' => 'This phone number has already been verified with another account'], 400); } From 1f2d608742753882604bd8e9b0115e5ca704e112 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 9 Dec 2023 11:03:31 +1100 Subject: [PATCH 05/14] fixes for upcoming --- app/Filters/InvoiceFilters.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index 08a6e5c6923f..f0ef5257bf32 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -153,10 +153,10 @@ class InvoiceFilters extends QueryFilters $query->whereNull('due_date') ->orWhere(function ($q) { - $q->where('due_date', '>=', now()->startOfDay()->subSecond())->where('partial', 0); + $q->where('due_date', '>=', now()->startOfDay()->subSecond())->where('partial', 0)->company(); }) ->orWhere(function ($q) { - $q->where('partial_due_date', '>=', now()->startOfDay()->subSecond())->where('partial', '>', 0); + $q->where('partial_due_date', '>=', now()->startOfDay()->subSecond())->where('partial', '>', 0)->company(); }); }) From 56fe16e5a8bbff1c533555898c06b5ef0bd01183 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 9 Dec 2023 11:27:24 +1100 Subject: [PATCH 06/14] Improvements for upcoming filters --- app/Filters/InvoiceFilters.php | 40 ++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index f0ef5257bf32..df04af1d072a 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -146,22 +146,25 @@ class InvoiceFilters extends QueryFilters */ public function upcoming(): Builder { - return $this->builder->whereIn('status_id', [Invoice::STATUS_PARTIAL, Invoice::STATUS_SENT]) - ->where('is_deleted', 0) - ->where('balance', '>', 0) - ->where(function ($query) { - - $query->whereNull('due_date') - ->orWhere(function ($q) { - $q->where('due_date', '>=', now()->startOfDay()->subSecond())->where('partial', 0)->company(); - }) - ->orWhere(function ($q) { - $q->where('partial_due_date', '>=', now()->startOfDay()->subSecond())->where('partial', '>', 0)->company(); - }); - }) - ->orderByRaw('ISNULL(due_date), due_date '. 'desc') - ->orderByRaw('ISNULL(partial_due_date), partial_due_date '. 'desc'); + return $this->builder->where(function ($query) { + $query->whereIn('status_id', [Invoice::STATUS_PARTIAL, Invoice::STATUS_SENT]) + ->where('is_deleted', 0) + ->where('balance', '>', 0) + ->where(function ($query) { + + $query->whereNull('due_date') + ->orWhere(function ($q) { + $q->where('due_date', '>=', now()->startOfDay()->subSecond())->where('partial', 0); + }) + ->orWhere(function ($q) { + $q->where('partial_due_date', '>=', now()->startOfDay()->subSecond())->where('partial', '>', 0); + }); + + }) + ->orderByRaw('ISNULL(due_date), due_date ' . 'desc') + ->orderByRaw('ISNULL(partial_due_date), partial_due_date ' . 'desc'); + }); } @@ -172,13 +175,18 @@ class InvoiceFilters extends QueryFilters */ public function overdue(): Builder { - return $this->builder->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + return $this->builder->where(function ($query) { + + $query->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) ->where('is_deleted', 0) + ->where('balance', '>', 0) ->where(function ($query) { $query->where('due_date', '<', now()) ->orWhere('partial_due_date', '<', now()); }) ->orderBy('due_date', 'ASC'); + }); + } /** From 3a5730e884b6f2b96d6ecacfbb3e78555c88022c Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 9 Dec 2023 11:52:42 +1100 Subject: [PATCH 07/14] Fixes for import validation --- app/Http/Requests/Import/ImportRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Requests/Import/ImportRequest.php b/app/Http/Requests/Import/ImportRequest.php index 4cc8ff93489c..44c6fe6d869e 100644 --- a/app/Http/Requests/Import/ImportRequest.php +++ b/app/Http/Requests/Import/ImportRequest.php @@ -37,7 +37,7 @@ class ImportRequest extends Request 'column_map' => 'required_with:hash|array', 'skip_header' => 'required_with:hash|boolean', 'files.*' => 'file|mimes:csv,txt', - 'bank_integration_id' => 'bail|required_if:column_map,bank_transaction|min:2' + 'bank_integration_id' => 'bail|required_with:column_map,bank_transaction|min:2' ]; } } From 0e10e99cb7b49e883ae18f9eca4cca8ca3078bef Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 9 Dec 2023 12:04:55 +1100 Subject: [PATCH 08/14] Update request rules for imports --- app/Http/Requests/Import/ImportRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Requests/Import/ImportRequest.php b/app/Http/Requests/Import/ImportRequest.php index 44c6fe6d869e..541f4f1c422c 100644 --- a/app/Http/Requests/Import/ImportRequest.php +++ b/app/Http/Requests/Import/ImportRequest.php @@ -37,7 +37,7 @@ class ImportRequest extends Request 'column_map' => 'required_with:hash|array', 'skip_header' => 'required_with:hash|boolean', 'files.*' => 'file|mimes:csv,txt', - 'bank_integration_id' => 'bail|required_with:column_map,bank_transaction|min:2' + 'bank_integration_id' => 'bail|required_with:column_map.bank_transaction|min:2' ]; } } From 23fb0d4cda43568f04c7e68afb7b124b24ed9669 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 10 Dec 2023 13:22:51 +1100 Subject: [PATCH 09/14] Updates for readme --- app/Http/Controllers/TwilioController.php | 20 +++++++++++++++++++- app/Jobs/PostMark/ProcessPostmarkWebhook.php | 12 +++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/TwilioController.php b/app/Http/Controllers/TwilioController.php index c43ba09d7365..ed6044995b12 100644 --- a/app/Http/Controllers/TwilioController.php +++ b/app/Http/Controllers/TwilioController.php @@ -22,6 +22,11 @@ use Twilio\Rest\Client; class TwilioController extends BaseController { + private array $invalid_codes = [ + '+21', + '+17152567760', + ]; + public function __construct() { parent::__construct(); @@ -39,7 +44,7 @@ class TwilioController extends BaseController $account = $user->company()->account; - if(stripos($request->phone, '+21') !== false) { + if(!$this->checkPhoneValidity($request->phone)) { return response()->json(['message' => 'This phone number is not supported'], 400); } @@ -70,6 +75,19 @@ class TwilioController extends BaseController return response()->json(['message' => 'Code sent.'], 200); } + private function checkPhoneValidity($phone) + { + foreach($this->invalid_codes as $code){ + + if(stripos($phone, $code) !== false) { + return false; + } + + return true; + + } + } + /** * Show the form for creating a new resource. * diff --git a/app/Jobs/PostMark/ProcessPostmarkWebhook.php b/app/Jobs/PostMark/ProcessPostmarkWebhook.php index b66c27144965..a1b54aff4b81 100644 --- a/app/Jobs/PostMark/ProcessPostmarkWebhook.php +++ b/app/Jobs/PostMark/ProcessPostmarkWebhook.php @@ -305,14 +305,20 @@ class ProcessPostmarkWebhook implements ShouldQueue if($sl) { $this->updateSystemLog($sl, $data); + + if (config('ninja.notification.slack')) { + $this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja(); + } + return; } (new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); - if (config('ninja.notification.slack')) { - $this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja(); - } +if (config('ninja.notification.slack')) { + $this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja(); +} + } private function discoverInvitation($message_id) From 145e2efe3ca5893463fdf8227aefa6bf410282e7 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 11 Dec 2023 09:25:58 +1100 Subject: [PATCH 10/14] Fixes for report names --- app/Services/Scheduler/EmailReport.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/app/Services/Scheduler/EmailReport.php b/app/Services/Scheduler/EmailReport.php index 9b8acf793445..c73cd0034200 100644 --- a/app/Services/Scheduler/EmailReport.php +++ b/app/Services/Scheduler/EmailReport.php @@ -84,20 +84,20 @@ class EmailReport 'client_balance' => $export = (new ClientBalanceReport($this->scheduler->company, $data)), 'client_sales' => $export = (new ClientSalesReport($this->scheduler->company, $data)), 'user_sales' => $export = (new UserSalesReport($this->scheduler->company, $data)), - 'clients' => $export = (new ClientExport($this->scheduler->company, $data)), - 'client_contacts' => $export = (new ContactExport($this->scheduler->company, $data)), - 'credits' => $export = (new CreditExport($this->scheduler->company, $data)), - 'documents' => $export = (new DocumentExport($this->scheduler->company, $data)), - 'expenses' => $export = (new ExpenseExport($this->scheduler->company, $data)), - 'invoices' => $export = (new InvoiceExport($this->scheduler->company, $data)), - 'invoice_items' => $export = (new InvoiceItemExport($this->scheduler->company, $data)), - 'quotes' => $export = (new QuoteExport($this->scheduler->company, $data)), - 'quote_items' => $export = (new QuoteItemExport($this->scheduler->company, $data)), - 'recurring_invoices' => $export = (new RecurringInvoiceExport($this->scheduler->company, $data)), - 'payments' => $export = (new PaymentExport($this->scheduler->company, $data)), - 'products' => $export = (new ProductExport($this->scheduler->company, $data)), - 'tasks' => $export = (new TaskExport($this->scheduler->company, $data)), 'profitloss' => $export = (new ProfitLoss($this->scheduler->company, $data)), + 'client' => $export = (new ClientExport($this->scheduler->company, $data)), + 'client_contact' => $export = (new ContactExport($this->scheduler->company, $data)), + 'credit' => $export = (new CreditExport($this->scheduler->company, $data)), + 'document' => $export = (new DocumentExport($this->scheduler->company, $data)), + 'expense' => $export = (new ExpenseExport($this->scheduler->company, $data)), + 'invoice' => $export = (new InvoiceExport($this->scheduler->company, $data)), + 'invoice_item' => $export = (new InvoiceItemExport($this->scheduler->company, $data)), + 'quote' => $export = (new QuoteExport($this->scheduler->company, $data)), + 'quote_item' => $export = (new QuoteItemExport($this->scheduler->company, $data)), + 'recurring_invoice' => $export = (new RecurringInvoiceExport($this->scheduler->company, $data)), + 'payment' => $export = (new PaymentExport($this->scheduler->company, $data)), + 'product' => $export = (new ProductExport($this->scheduler->company, $data)), + 'task' => $export = (new TaskExport($this->scheduler->company, $data)), default => $export = false, }; From 934a643dc492f87baf75fe31bd80f642b6069b3e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 11 Dec 2023 09:28:39 +1100 Subject: [PATCH 11/14] Updates for report names --- app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php | 4 ++-- app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php b/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php index 4e197ad50e44..1d13a9fafb1a 100644 --- a/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php +++ b/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php @@ -42,12 +42,12 @@ class StoreSchedulerRequest extends Request 'template' => 'bail|required|string', 'parameters' => 'bail|array', 'parameters.clients' => ['bail','sometimes', 'array', new ValidClientIds()], - 'parameters.date_range' => 'bail|sometimes|string|in:last7_days,last30_days,last365_days,this_month,last_month,this_quarter,last_quarter,this_year,last_year,all_time,custom', + 'parameters.date_range' => 'bail|sometimes|string|in:last7_days,last30_days,last365_days,this_month,last_month,this_quarter,last_quarter,this_year,last_year,all_time,custom,all', 'parameters.start_date' => ['bail', 'sometimes', 'date:Y-m-d', 'required_if:parameters.date_rate,custom'], 'parameters.end_date' => ['bail', 'sometimes', 'date:Y-m-d', 'required_if:parameters.date_rate,custom', 'after_or_equal:parameters.start_date'], 'parameters.entity' => ['bail', 'sometimes', 'string', 'in:invoice,credit,quote,purchase_order'], 'parameters.entity_id' => ['bail', 'sometimes', 'string'], - 'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report','in:ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,clients,client_contacts,credits,documents,expenses,invoices,invoice_items,quotes,quote_items,recurring_invoices,payments,products,tasks'], + 'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report','in:ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,client,client_contact,credit,document,expense,invoice,invoice_item,quote,quote_item,recurring_invoice,payment,product,task'], 'parameters.date_key' => ['bail','sometimes', 'string'], 'parameters.status' => ['bail','sometimes', 'string', 'in:all,draft,paid,unpaid,overdue'], ]; diff --git a/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php b/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php index f4054949fc85..0e58285ef1ff 100644 --- a/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php +++ b/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php @@ -39,12 +39,12 @@ class UpdateSchedulerRequest extends Request 'template' => 'bail|required|string', 'parameters' => 'bail|array', 'parameters.clients' => ['bail','sometimes', 'array', new ValidClientIds()], - 'parameters.date_range' => 'bail|sometimes|string|in:last7_days,last30_days,last365_days,this_month,last_month,this_quarter,last_quarter,this_year,last_year,all_time,custom', + 'parameters.date_range' => 'bail|sometimes|string|in:last7_days,last30_days,last365_days,this_month,last_month,this_quarter,last_quarter,this_year,last_year,all_time,custom,all', 'parameters.start_date' => ['bail', 'sometimes', 'date:Y-m-d', 'required_if:parameters.date_rate,custom'], 'parameters.end_date' => ['bail', 'sometimes', 'date:Y-m-d', 'required_if:parameters.date_rate,custom', 'after_or_equal:parameters.start_date'], 'parameters.entity' => ['bail', 'sometimes', 'string', 'in:invoice,credit,quote,purchase_order'], 'parameters.entity_id' => ['bail', 'sometimes', 'string'], - 'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report', 'in:ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,clients,client_contacts,credits,documents,expenses,invoices,invoice_items,quotes,quote_items,recurring_invoices,payments,products,tasks'], + 'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report', 'in:ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,client,client_contact,credit,document,expense,invoice,invoice_item,quote,quote_item,recurring_invoice,payment,product,task'], 'parameters.date_key' => ['bail','sometimes', 'string'], ]; From 1126c8518fc51be404a453fde0a262eb2b6abe28 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 11 Dec 2023 10:00:04 +1100 Subject: [PATCH 12/14] Minor cleanup --- app/Jobs/Util/ReminderJob.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/Jobs/Util/ReminderJob.php b/app/Jobs/Util/ReminderJob.php index b6f0c7b00580..e4cab43e6aff 100644 --- a/app/Jobs/Util/ReminderJob.php +++ b/app/Jobs/Util/ReminderJob.php @@ -307,8 +307,6 @@ class ReminderJob implements ShouldQueue /**Refresh Invoice values*/ $invoice = $invoice->calc()->getInvoice(); - // nlog('adjusting client balance and invoice balance by #'.$invoice->number.' '.($invoice->balance - $temp_invoice_balance)); - // $invoice->client->service()->updateBalance($invoice->balance - $temp_invoice_balance); $invoice->ledger()->updateInvoiceBalance($invoice->balance - $temp_invoice_balance, "Late Fee Adjustment for invoice {$invoice->number}"); $invoice->client->service()->calculateBalance(); From 4c4d18fbe8a00becfd4d8b7741a1d79376e036ab Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 11 Dec 2023 13:14:05 +1100 Subject: [PATCH 13/14] Working on email reports --- .../TaskScheduler/StoreSchedulerRequest.php | 6 +- .../TaskScheduler/UpdateSchedulerRequest.php | 4 + app/Services/Scheduler/EmailReport.php | 2 +- composer.lock | 86 +++++++++---------- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php b/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php index 1d13a9fafb1a..6dfaf8423402 100644 --- a/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php +++ b/app/Http/Requests/TaskScheduler/StoreSchedulerRequest.php @@ -47,7 +47,7 @@ class StoreSchedulerRequest extends Request 'parameters.end_date' => ['bail', 'sometimes', 'date:Y-m-d', 'required_if:parameters.date_rate,custom', 'after_or_equal:parameters.start_date'], 'parameters.entity' => ['bail', 'sometimes', 'string', 'in:invoice,credit,quote,purchase_order'], 'parameters.entity_id' => ['bail', 'sometimes', 'string'], - 'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report','in:ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,client,client_contact,credit,document,expense,invoice,invoice_item,quote,quote_item,recurring_invoice,payment,product,task'], + 'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report','in:ar_detailed,ar_summary,client_balance,tax_summary,profitloss,client_sales,user_sales,product_sales,activity,client,contact,client_contact,credit,document,expense,invoice,invoice_item,quote,quote_item,recurring_invoice,payment,product,task'], 'parameters.date_key' => ['bail','sometimes', 'string'], 'parameters.status' => ['bail','sometimes', 'string', 'in:all,draft,paid,unpaid,overdue'], ]; @@ -67,6 +67,10 @@ class StoreSchedulerRequest extends Request $input['frequency_id'] = 0; } + if(isset($input['parameters']) && isset($input['parameters']['clients'])) { + $input['parameters']['clients'] = []; + } + $this->replace($input); } } diff --git a/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php b/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php index 0e58285ef1ff..81a8ad492643 100644 --- a/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php +++ b/app/Http/Requests/TaskScheduler/UpdateSchedulerRequest.php @@ -63,6 +63,10 @@ class UpdateSchedulerRequest extends Request $input['frequency_id'] = 0; } + if(isset($input['parameters']) && isset($input['parameters']['clients'])) { + $input['parameters']['clients'] = []; + } + $this->replace($input); diff --git a/app/Services/Scheduler/EmailReport.php b/app/Services/Scheduler/EmailReport.php index c73cd0034200..2a251f8f1786 100644 --- a/app/Services/Scheduler/EmailReport.php +++ b/app/Services/Scheduler/EmailReport.php @@ -70,7 +70,7 @@ class EmailReport 'report_keys' => [] ]; - if (count($this->scheduler->parameters['clients']) >= 1) { + if (isset($this->scheduler->parameters['clients']) && count($this->scheduler->parameters['clients']) >= 1) { $data['clients'] = $this->transformKeys($this->scheduler->parameters['clients']); } diff --git a/composer.lock b/composer.lock index 27dc537efdb9..a35b4329b536 100644 --- a/composer.lock +++ b/composer.lock @@ -485,16 +485,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.293.5", + "version": "3.293.7", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "f2002e52b382b45231da3f9552033f769acfebd8" + "reference": "3bf86ba8b9bbea2b298f89e6f5edc58de276690b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f2002e52b382b45231da3f9552033f769acfebd8", - "reference": "f2002e52b382b45231da3f9552033f769acfebd8", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3bf86ba8b9bbea2b298f89e6f5edc58de276690b", + "reference": "3bf86ba8b9bbea2b298f89e6f5edc58de276690b", "shasum": "" }, "require": { @@ -574,9 +574,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.293.5" + "source": "https://github.com/aws/aws-sdk-php/tree/3.293.7" }, - "time": "2023-12-06T19:09:15+00:00" + "time": "2023-12-08T19:11:21+00:00" }, { "name": "bacon/bacon-qr-code", @@ -6576,16 +6576,16 @@ }, { "name": "nesbot/carbon", - "version": "2.72.0", + "version": "2.72.1", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "a6885fcbad2ec4360b0e200ee0da7d9b7c90786b" + "reference": "2b3b3db0a2d0556a177392ff1a3bf5608fa09f78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/a6885fcbad2ec4360b0e200ee0da7d9b7c90786b", - "reference": "a6885fcbad2ec4360b0e200ee0da7d9b7c90786b", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/2b3b3db0a2d0556a177392ff1a3bf5608fa09f78", + "reference": "2b3b3db0a2d0556a177392ff1a3bf5608fa09f78", "shasum": "" }, "require": { @@ -6679,7 +6679,7 @@ "type": "tidelift" } ], - "time": "2023-11-28T10:13:25+00:00" + "time": "2023-12-08T23:47:49+00:00" }, { "name": "nette/schema", @@ -6831,16 +6831,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.17.1", + "version": "v4.18.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", "shasum": "" }, "require": { @@ -6881,9 +6881,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" }, - "time": "2023-08-13T19:53:39+00:00" + "time": "2023-12-10T21:03:43+00:00" }, { "name": "nunomaduro/termwind", @@ -13841,23 +13841,23 @@ }, { "name": "tijsverkoyen/css-to-inline-styles", - "version": "2.2.6", + "version": "v2.2.7", "source": { "type": "git", "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", - "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c" + "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/c42125b83a4fa63b187fdf29f9c93cb7733da30c", - "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/83ee6f38df0a63106a9e4536e3060458b74ccedb", + "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "php": "^5.5 || ^7.0 || ^8.0", - "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0" }, "require-dev": { "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10" @@ -13888,9 +13888,9 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "support": { "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", - "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.6" + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.2.7" }, - "time": "2023-01-03T09:29:04+00:00" + "time": "2023-12-08T13:03:43+00:00" }, { "name": "turbo124/beacon", @@ -15263,16 +15263,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.40.2", + "version": "v3.41.1", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "4344562a516b76afe8f2d64b2e52214c30d64ed8" + "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/4344562a516b76afe8f2d64b2e52214c30d64ed8", - "reference": "4344562a516b76afe8f2d64b2e52214c30d64ed8", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/8b6ae8dcbaf23f09680643ab832a4a3a260265f6", + "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6", "shasum": "" }, "require": { @@ -15302,8 +15302,6 @@ "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", - "phpspec/prophecy": "^1.17", - "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.6", "symfony/phpunit-bridge": "^6.3.8 || ^7.0", "symfony/yaml": "^5.4 || ^6.0 || ^7.0" @@ -15344,7 +15342,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.40.2" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.41.1" }, "funding": [ { @@ -15352,7 +15350,7 @@ "type": "github" } ], - "time": "2023-12-03T09:21:33+00:00" + "time": "2023-12-10T19:59:27+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -15633,16 +15631,16 @@ }, { "name": "mockery/mockery", - "version": "1.6.6", + "version": "1.6.7", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e" + "reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/b8e0bb7d8c604046539c1115994632c74dcb361e", - "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e", + "url": "https://api.github.com/repos/mockery/mockery/zipball/0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06", + "reference": "0cc058854b3195ba21dc6b1f7b1f60f4ef3a9c06", "shasum": "" }, "require": { @@ -15655,9 +15653,7 @@ }, "require-dev": { "phpunit/phpunit": "^8.5 || ^9.6.10", - "psalm/plugin-phpunit": "^0.18.4", - "symplify/easy-coding-standard": "^11.5.0", - "vimeo/psalm": "^4.30" + "symplify/easy-coding-standard": "^12.0.8" }, "type": "library", "autoload": { @@ -15714,7 +15710,7 @@ "security": "https://github.com/mockery/mockery/security/advisories", "source": "https://github.com/mockery/mockery" }, - "time": "2023-08-09T00:03:52+00:00" + "time": "2023-12-10T02:24:34+00:00" }, { "name": "myclabs/deep-copy", @@ -16071,16 +16067,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.47", + "version": "1.10.48", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "84dbb33b520ea28b6cf5676a3941f4bae1c1ff39" + "reference": "087ed4b5f4a7a6e8f3bbdfbfe98ce5c181380bc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/84dbb33b520ea28b6cf5676a3941f4bae1c1ff39", - "reference": "84dbb33b520ea28b6cf5676a3941f4bae1c1ff39", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/087ed4b5f4a7a6e8f3bbdfbfe98ce5c181380bc6", + "reference": "087ed4b5f4a7a6e8f3bbdfbfe98ce5c181380bc6", "shasum": "" }, "require": { @@ -16129,7 +16125,7 @@ "type": "tidelift" } ], - "time": "2023-12-01T15:19:17+00:00" + "time": "2023-12-08T14:34:28+00:00" }, { "name": "phpunit/php-code-coverage", From b250ba613c3373d8988f34921346a325c9b123f5 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 11 Dec 2023 22:42:50 +1100 Subject: [PATCH 14/14] v5.7.60 --- VERSION.txt | 2 +- .../Requests/Credit/UpdateCreditRequest.php | 2 +- .../Requests/Invoice/UpdateInvoiceRequest.php | 3 +- .../UpdatePurchaseOrderRequest.php | 2 +- .../Requests/Quote/UpdateQuoteRequest.php | 5 +- app/Jobs/Company/CompanyExport.php | 10 +-- app/Jobs/Company/CompanyImport.php | 63 ++++++++++--------- app/Jobs/Mail/PaymentFailedMailer.php | 2 +- .../GoCardless/InstantBankPay.php | 51 ++++++++++++--- .../GoCardlessPaymentDriver.php | 2 +- config/ninja.php | 4 +- 11 files changed, 93 insertions(+), 53 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index bca730d00e5a..d24b80453203 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.7.59 \ No newline at end of file +5.7.60 \ No newline at end of file diff --git a/app/Http/Requests/Credit/UpdateCreditRequest.php b/app/Http/Requests/Credit/UpdateCreditRequest.php index 23ee7007b654..4d15796ac139 100644 --- a/app/Http/Requests/Credit/UpdateCreditRequest.php +++ b/app/Http/Requests/Credit/UpdateCreditRequest.php @@ -60,7 +60,7 @@ class UpdateCreditRequest extends Request $rules['file'] = $this->file_validation; } - $rules['number'] = ['bail', 'sometimes', Rule::unique('credits')->where('company_id', $user->company()->id)->ignore($this->credit->id)]; + $rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('credits')->where('company_id', $user->company()->id)->ignore($this->credit->id)]; $rules['client_id'] = ['bail', 'sometimes',Rule::in([$this->credit->client_id])]; diff --git a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php index 319f1d9aab91..1591b9912579 100644 --- a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php @@ -59,9 +59,8 @@ class UpdateInvoiceRequest extends Request $rules['id'] = new LockedInvoiceRule($this->invoice); - $rules['number'] = ['bail', 'sometimes', Rule::unique('invoices')->where('company_id', $user->company()->id)->ignore($this->invoice->id)]; + $rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('invoices')->where('company_id', $user->company()->id)->ignore($this->invoice->id)]; - $rules['is_amount_discount'] = ['boolean']; $rules['client_id'] = ['bail', 'sometimes', Rule::in([$this->invoice->client_id])]; $rules['line_items'] = 'array'; diff --git a/app/Http/Requests/PurchaseOrder/UpdatePurchaseOrderRequest.php b/app/Http/Requests/PurchaseOrder/UpdatePurchaseOrderRequest.php index d9549f881f98..800eaf8405ca 100644 --- a/app/Http/Requests/PurchaseOrder/UpdatePurchaseOrderRequest.php +++ b/app/Http/Requests/PurchaseOrder/UpdatePurchaseOrderRequest.php @@ -48,7 +48,7 @@ class UpdatePurchaseOrderRequest extends Request $rules = []; - $rules['number'] = ['bail', 'sometimes', Rule::unique('purchase_orders')->where('company_id', $user->company()->id)->ignore($this->purchase_order->id)]; + $rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('purchase_orders')->where('company_id', $user->company()->id)->ignore($this->purchase_order->id)]; $rules['vendor_id'] = ['bail', 'sometimes', Rule::in([$this->purchase_order->vendor_id])]; $rules['line_items'] = 'array'; diff --git a/app/Http/Requests/Quote/UpdateQuoteRequest.php b/app/Http/Requests/Quote/UpdateQuoteRequest.php index 4b473825c88a..4294385b15f2 100644 --- a/app/Http/Requests/Quote/UpdateQuoteRequest.php +++ b/app/Http/Requests/Quote/UpdateQuoteRequest.php @@ -55,7 +55,7 @@ class UpdateQuoteRequest extends Request } - $rules['number'] = ['bail', 'sometimes', Rule::unique('quotes')->where('company_id', $user->company()->id)->ignore($this->quote->id)]; + $rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('quotes')->where('company_id', $user->company()->id)->ignore($this->quote->id)]; $rules['client_id'] = ['bail', 'sometimes', Rule::in([$this->quote->client_id])]; @@ -73,6 +73,8 @@ class UpdateQuoteRequest extends Request $input = $this->decodePrimaryKeys($input); + $input['id'] = $this->quote->id; + if (isset($input['line_items'])) { $input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : []; } @@ -85,7 +87,6 @@ class UpdateQuoteRequest extends Request $input['exchange_rate'] = 1; } - $input['id'] = $this->quote->id; $this->replace($input); } diff --git a/app/Jobs/Company/CompanyExport.php b/app/Jobs/Company/CompanyExport.php index 23afdd37738f..0fc36b2500af 100644 --- a/app/Jobs/Company/CompanyExport.php +++ b/app/Jobs/Company/CompanyExport.php @@ -387,19 +387,19 @@ class CompanyExport implements ShouldQueue })->all(); - $this->export_data['bank_integrations'] = $this->company->bank_integrations()->orderBy('id', 'ASC')->cursor()->map(function ($bank_integration) { + $this->export_data['bank_integrations'] = $this->company->bank_integrations()->withTrashed()->orderBy('id', 'ASC')->cursor()->map(function ($bank_integration) { $bank_integration = $this->transformArrayOfKeys($bank_integration, ['account_id','company_id', 'user_id']); - return $bank_integration->makeVisible(['id','user_id','company_id','account_id']); + return $bank_integration->makeVisible(['id','user_id','company_id','account_id','hashed_id']); })->all(); - $this->export_data['bank_transactions'] = $this->company->bank_transactions()->orderBy('id', 'ASC')->cursor()->map(function ($bank_transaction) { - $bank_transaction = $this->transformArrayOfKeys($bank_transaction, ['company_id', 'user_id','bank_integration_id','expense_id','category_id','ninja_category_id','vendor_id']); + $this->export_data['bank_transactions'] = $this->company->bank_transactions()->withTrashed()->orderBy('id', 'ASC')->cursor()->map(function ($bank_transaction) { + $bank_transaction = $this->transformArrayOfKeys($bank_transaction, ['company_id', 'user_id','bank_integration_id','expense_id','ninja_category_id','vendor_id']); return $bank_transaction->makeVisible(['id','user_id','company_id']); })->all(); - $this->export_data['schedulers'] = $this->company->schedulers()->orderBy('id', 'ASC')->cursor()->map(function ($scheduler) { + $this->export_data['schedulers'] = $this->company->schedulers()->withTrashed()->orderBy('id', 'ASC')->cursor()->map(function ($scheduler) { $scheduler = $this->transformArrayOfKeys($scheduler, ['company_id', 'user_id']); return $scheduler->makeVisible(['id','user_id','company_id']); diff --git a/app/Jobs/Company/CompanyImport.php b/app/Jobs/Company/CompanyImport.php index 7c84d721b1e9..44abb45fdf3b 100644 --- a/app/Jobs/Company/CompanyImport.php +++ b/app/Jobs/Company/CompanyImport.php @@ -63,14 +63,12 @@ use App\Utils\Ninja; use App\Utils\TempFile; use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\MakesHash; -use function GuzzleHttp\json_encode; 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\Cache; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use JsonMachine\JsonDecoder\ExtJsonDecoder; @@ -142,7 +140,6 @@ class CompanyImport implements ShouldQueue 'recurring_expenses', 'expenses', 'tasks', - 'payments', 'company_ledger', 'designs', 'documents', @@ -569,7 +566,7 @@ class CompanyImport implements ShouldQueue ['expenses' => 'expense_id'], ['vendors' => 'vendor_id'], ['expense_categories' => 'ninja_category_id'], - ['expense_categories' => 'category_id'], + // ['expense_categories' => 'category_id'], ['bank_integrations' => 'bank_integration_id'] ], 'bank_transactions', @@ -1143,7 +1140,34 @@ class CompanyImport implements ShouldQueue continue; } + $storage_url = (object)$this->getObject('storage_url', true); + + if (!Storage::exists($document->url) && is_string($storage_url)) { + $url = $storage_url . $document->url; + + $file = @file_get_contents($url); + + + if ($file) { + try { + Storage::disk(config('filesystems.default'))->put($document->url, $file); + + + } catch(\Exception $e) { + nlog($e->getMessage()); + nlog("I could not upload {$document->url}"); + + } + } + else + continue; + + } + else + continue; + $new_document = new Document(); + $new_document->disk = config('filesystems.default'); $new_document->user_id = $this->transformId('users', $document->user_id); $new_document->assigned_user_id = $this->transformId('users', $document->assigned_user_id); $new_document->company_id = $this->company->id; @@ -1169,26 +1193,6 @@ class CompanyImport implements ShouldQueue $new_document->save(['timestamps' => false]); - $storage_url = (object)$this->getObject('storage_url', true); - - if (!Storage::exists($new_document->url) && is_string($storage_url)) { - $url = $storage_url . $new_document->url; - - $file = @file_get_contents($url); - - if ($file) { - try { - Storage::disk(config('filesystems.default'))->put($new_document->url, $file); - - $new_document->disk = config('filesystems.default'); - $new_document->save(); - } catch(\Exception $e) { - nlog($e->getMessage()); - nlog("I could not upload {$new_document->url}"); - $new_document->forceDelete(); - } - } - } } return $this; @@ -1727,7 +1731,9 @@ class CompanyImport implements ShouldQueue */ private function transformId(string $resource, ?string $old): ?int { - if (empty($old)) { + + // WjnegYbwZ1 == 0 return null; + if (empty($old) || $old == 'WjnegYbwZ1') { return null; } @@ -1736,6 +1742,7 @@ class CompanyImport implements ShouldQueue } if (! array_key_exists($resource, $this->ids)) { + $this->sendImportMail("The Import failed due to missing data in the import file. Resource {$resource} not available."); throw new \Exception("Resource {$resource} not available."); @@ -1744,16 +1751,12 @@ class CompanyImport implements ShouldQueue if (! array_key_exists("{$old}", $this->ids[$resource])) { // nlog($this->ids[$resource]); nlog("searching for {$old} in {$resource}"); - - nlog("If we are missing a user - default to the company owner"); if ($resource == 'users') { return $this->company_owner->id; } - $this->sendImportMail("The Import failed due to missing data in the import file. Resource {$resource} not available."); - - nlog($this->ids[$resource]); + $this->sendImportMail("The Import failed due to missing data in the import file. Key {$old} not found in {$resource}."); throw new \Exception("Missing {$resource} key: {$old}"); } diff --git a/app/Jobs/Mail/PaymentFailedMailer.php b/app/Jobs/Mail/PaymentFailedMailer.php index 461b1a01c695..15b9bdb61c8f 100644 --- a/app/Jobs/Mail/PaymentFailedMailer.php +++ b/app/Jobs/Mail/PaymentFailedMailer.php @@ -105,7 +105,7 @@ class PaymentFailedMailer implements ShouldQueue }); //add client payment failures here. - // + if ($this->client->contacts()->whereNotNull('email')->exists() && $this->payment_hash) { $contact = $this->client->contacts()->whereNotNull('email')->first(); diff --git a/app/PaymentDrivers/GoCardless/InstantBankPay.php b/app/PaymentDrivers/GoCardless/InstantBankPay.php index 3d5cf238272a..b6d8f31faea1 100644 --- a/app/PaymentDrivers/GoCardless/InstantBankPay.php +++ b/app/PaymentDrivers/GoCardless/InstantBankPay.php @@ -113,6 +113,10 @@ class InstantBankPay implements MethodInterface return $this->processSuccessfulPayment($payment); } + if ($billing_request->status === 'submitted') { + return $this->processPendingPayment($payment); + } + return $this->processUnsuccessfulPayment($payment); } catch (\Exception $exception) { throw new PaymentFailed( @@ -125,7 +129,40 @@ class InstantBankPay implements MethodInterface /** * Handle pending payments for Instant Bank Transfer. * - * @param ResourcesPayment $payment + * @param \GoCardlessPro\Resources\Payment $payment + * @param array $data + * @return RedirectResponse + */ + public function processPendingPayment(\GoCardlessPro\Resources\Payment $payment, array $data = []) + { + $data = [ + 'payment_method' => $payment->links->mandate, + 'payment_type' => PaymentType::INSTANT_BANK_PAY, + 'amount' => $this->go_cardless->payment_hash->data->amount_with_fee, + 'transaction_reference' => $payment->id, + 'gateway_type_id' => GatewayType::INSTANT_BANK_PAY, + ]; + + $payment = $this->go_cardless->createPayment($data, Payment::STATUS_PENDING); + + SystemLogger::dispatch( + ['response' => $payment, 'data' => $data], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_GOCARDLESS, + $this->go_cardless->client, + $this->go_cardless->client->company, + ); + + return redirect()->route('client.payments.show', ['payment' => $this->go_cardless->encodePrimaryKey($payment->id)]); + } + + + + /** + * Handle pending payments for Instant Bank Transfer. + * + * @param \GoCardlessPro\Resources\Payment $payment * @param array $data * @return RedirectResponse */ @@ -163,12 +200,12 @@ class InstantBankPay implements MethodInterface { PaymentFailureMailer::dispatch($this->go_cardless->client, $payment->status, $this->go_cardless->client->company, $this->go_cardless->payment_hash->data->amount_with_fee); - PaymentFailureMailer::dispatch( - $this->go_cardless->client, - $payment, - $this->go_cardless->client->company, - $payment->amount - ); + // PaymentFailureMailer::dispatch( + // $this->go_cardless->client, + // $payment, + // $this->go_cardless->client->company, + // $payment->amount + // ); $message = [ 'server_response' => $payment, diff --git a/app/PaymentDrivers/GoCardlessPaymentDriver.php b/app/PaymentDrivers/GoCardlessPaymentDriver.php index 00db105fa717..cca2f9ba8f98 100644 --- a/app/PaymentDrivers/GoCardlessPaymentDriver.php +++ b/app/PaymentDrivers/GoCardlessPaymentDriver.php @@ -165,7 +165,7 @@ class GoCardlessPaymentDriver extends BaseDriver ], ]); - if ($payment->status === 'pending_submission') { + if (in_array($payment->status, ['submitted', 'pending_submission'])) { $this->confirmGatewayFee(); $data = [ diff --git a/config/ninja.php b/config/ninja.php index 94d0a307fc6a..87c3a2fa2a94 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -17,8 +17,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.59'), - 'app_tag' => env('APP_TAG', '5.7.59'), + 'app_version' => env('APP_VERSION', '5.7.60'), + 'app_tag' => env('APP_TAG', '5.7.60'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false),