From d56da2d321264b19b0980586a849c8c2b062fb88 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 20 Apr 2022 08:26:44 +1000 Subject: [PATCH 1/6] Add required fields for Paytrace --- app/PaymentDrivers/PaytracePaymentDriver.php | 46 ++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/app/PaymentDrivers/PaytracePaymentDriver.php b/app/PaymentDrivers/PaytracePaymentDriver.php index f834791c4311..882ce3f79fbc 100644 --- a/app/PaymentDrivers/PaytracePaymentDriver.php +++ b/app/PaymentDrivers/PaytracePaymentDriver.php @@ -173,6 +173,52 @@ class PaytracePaymentDriver extends BaseDriver $this->processUnsuccessfulTransaction($data, false); } + public function getClientRequiredFields(): array + { + $fields = []; + + if ($this->company_gateway->require_client_name) { + $fields[] = ['name' => 'client_name', 'label' => ctrans('texts.client_name'), 'type' => 'text', 'validation' => 'required']; + } + + if ($this->company_gateway->require_contact_name) { + $fields[] = ['name' => 'contact_first_name', 'label' => ctrans('texts.first_name'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'contact_last_name', 'label' => ctrans('texts.last_name'), 'type' => 'text', 'validation' => 'required']; + } + + if ($this->company_gateway->require_contact_email) { + $fields[] = ['name' => 'contact_email', 'label' => ctrans('texts.email'), 'type' => 'text', 'validation' => 'required,email:rfc']; + } + + if ($this->company_gateway->require_client_phone) { + $fields[] = ['name' => 'client_phone', 'label' => ctrans('texts.client_phone'), 'type' => 'tel', 'validation' => 'required']; + } + + if ($this->company_gateway->require_billing_address) { + $fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required']; + } + + if($this->company_gateway->require_postal_code) { + $fields[] = ['name' => 'client_postal_code', 'label' => ctrans('texts.postal_code'), 'type' => 'text', 'validation' => 'required']; + } + + if ($this->company_gateway->require_shipping_address) { + $fields[] = ['name' => 'client_shipping_address_line_1', 'label' => ctrans('texts.shipping_address1'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_shipping_city', 'label' => ctrans('texts.shipping_city'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_shipping_state', 'label' => ctrans('texts.shipping_state'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_shipping_postal_code', 'label' => ctrans('texts.shipping_postal_code'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_shipping_country_id', 'label' => ctrans('texts.shipping_country'), 'type' => 'text', 'validation' => 'required']; + } + + + return $fields; + } + + + public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null) { } From 98012e0ef3cd7235b777275d595e6a073be1cd17 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 20 Apr 2022 08:28:25 +1000 Subject: [PATCH 2/6] Fixes for purge API docs --- app/Http/Controllers/ClientController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index b4c35f59d866..ce6ed40da855 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -596,7 +596,7 @@ class ClientController extends BaseController * * * - * @OA\Put( + * @OA\Post( * path="/api/v1/clients/{id}/purge", * operationId="purgeClient", * tags={"clients"}, From 394d3b327dbb0f57bac992c9a9c8688e5ae5d1a7 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 20 Apr 2022 08:51:27 +1000 Subject: [PATCH 3/6] Improve error handling within PayTrace --- app/PaymentDrivers/PayTrace/CreditCard.php | 24 +++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/app/PaymentDrivers/PayTrace/CreditCard.php b/app/PaymentDrivers/PayTrace/CreditCard.php index 3e00f657e881..a1d00b31a166 100644 --- a/app/PaymentDrivers/PayTrace/CreditCard.php +++ b/app/PaymentDrivers/PayTrace/CreditCard.php @@ -99,6 +99,29 @@ class CreditCard $response = $this->paytrace->gatewayRequest('/v1/customer/pt_protect_create', $post_data); + if(!$response->success) + { + + $error = 'Error creating customer in gateway'; + $error_code = isset($response->response_code) ? $response->response_code : 'PT_ERR'; + + if(isset($response->errors)) + { + foreach($response->errors as $err) + { + $error = end($err); + } + } + + $data = [ + 'response' => $response, + 'error' => $error, + 'error_code' => $error_code, + ]; + + return $this->paytrace->processUnsuccessfulTransaction($data); + } + $cgt = []; $cgt['token'] = $response->customer_id; $cgt['payment_method_id'] = GatewayType::CREDIT_CARD; @@ -124,7 +147,6 @@ class CreditCard $profile = $this->paytrace->gatewayRequest('/v1/customer/export', [ 'integrator_id' => $this->paytrace->company_gateway->getConfigField('integratorId'), 'customer_id' => $customer_id, - // 'include_bin' => true, ]); return $profile->customers[0]; From a7b8845edb5d2401a1b5e606413c9a82d00271d0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 20 Apr 2022 10:22:19 +1000 Subject: [PATCH 4/6] Minor fixes --- app/Http/Controllers/SelfUpdateController.php | 3 --- app/PaymentDrivers/WePayPaymentDriver.php | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/app/Http/Controllers/SelfUpdateController.php b/app/Http/Controllers/SelfUpdateController.php index 325aa29c5b73..0f28dc8aaa1c 100644 --- a/app/Http/Controllers/SelfUpdateController.php +++ b/app/Http/Controllers/SelfUpdateController.php @@ -111,9 +111,6 @@ class SelfUpdateController extends BaseController copy($this->getDownloadUrl(), storage_path('app/invoiceninja.zip')); - // $contents = file_get_contents($this->getDownloadUrl()); - // Storage::disk('local')->put('invoiceninja.zip', $contents); - $file = Storage::disk('local')->path('invoiceninja.zip'); $zipFile = new \PhpZip\ZipFile(); diff --git a/app/PaymentDrivers/WePayPaymentDriver.php b/app/PaymentDrivers/WePayPaymentDriver.php index 748299e49e16..afd78b16ab79 100644 --- a/app/PaymentDrivers/WePayPaymentDriver.php +++ b/app/PaymentDrivers/WePayPaymentDriver.php @@ -191,7 +191,7 @@ class WePayPaymentDriver extends BaseDriver if ($objectType == 'credit_card') { $payment_method = ClientGatewayToken::where('token', $objectId)->first(); - if (! $paymentMethod) + if (! $payment_method) throw new \Exception('Unknown payment method'); $source = $this->wepay->request('credit_card', array( From fde59d0cd8fabfcee3c090ff6132f21e74122b72 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 20 Apr 2022 11:38:01 +1000 Subject: [PATCH 5/6] Fixes for reminders --- VERSION.txt | 2 +- app/Jobs/Util/ReminderJob.php | 13 +++++++++++-- config/ninja.php | 4 ++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 9f7319154f05..a7e0a988addf 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.3.80 \ No newline at end of file +5.3.81 \ No newline at end of file diff --git a/app/Jobs/Util/ReminderJob.php b/app/Jobs/Util/ReminderJob.php index edb96ff59f0e..4b4bdb159b7e 100644 --- a/app/Jobs/Util/ReminderJob.php +++ b/app/Jobs/Util/ReminderJob.php @@ -81,10 +81,19 @@ class ReminderJob implements ShouldQueue $invoice = $this->calcLateFee($invoice, $reminder_template); $invoice->service()->touchPdf(); - + + //20-04-2022 fixes for endless reminders - generic template naming was wrong + $enabled_reminder = "enable_".$reminder_template; + + if($reminder_template == 'endless_reminder') + $enabled_reminder = 'enable_reminder_endless'; + //check if this reminder needs to be emailed //15-01-2022 - insert addition if block if send_reminders is definitely set - if(in_array($reminder_template, ['reminder1','reminder2','reminder3','reminder_endless']) && $invoice->client->getSetting("enable_".$reminder_template) && $invoice->client->getSetting("send_reminders") && $invoice->company->account->isPaidHostedClient()) + if(in_array($reminder_template, ['reminder1','reminder2','reminder3','reminder_endless','endless_reminder']) && + $invoice->client->getSetting($enabled_reminder) && + $invoice->client->getSetting("send_reminders") && + (Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) { $invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) { EmailEntity::dispatch($invitation, $invitation->company, $reminder_template); diff --git a/config/ninja.php b/config/ninja.php index e9e48c3786d8..5cd221c4039e 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -14,8 +14,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => '5.3.80', - 'app_tag' => '5.3.80', + 'app_version' => '5.3.81', + 'app_tag' => '5.3.81', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''), From 127683ee290b156b1e0ccb0bedbfca0774b290dd Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 20 Apr 2022 11:55:33 +1000 Subject: [PATCH 6/6] Fixes for eager loading --- app/Http/Middleware/QueryLogging.php | 17 +++++++++-------- .../Transformer/Wave/InvoiceTransformer.php | 8 +++++++- app/Listeners/Invoice/CreateInvoicePdf.php | 6 +++--- app/Models/Invoice.php | 1 + app/Providers/AppServiceProvider.php | 1 - app/Repositories/ActivityRepository.php | 14 +++++++++++--- app/Services/Invoice/InvoiceService.php | 2 +- app/Services/Quote/QuoteService.php | 2 +- app/Utils/HtmlEngine.php | 2 +- 9 files changed, 34 insertions(+), 19 deletions(-) diff --git a/app/Http/Middleware/QueryLogging.php b/app/Http/Middleware/QueryLogging.php index 94ba71086a22..caa5d0949197 100644 --- a/app/Http/Middleware/QueryLogging.php +++ b/app/Http/Middleware/QueryLogging.php @@ -35,9 +35,9 @@ class QueryLogging { // Enable query logging for development - if (!Ninja::isHosted() || !config('beacon.enabled')) { - return $next($request); - } + // if (!Ninja::isHosted() || !config('beacon.enabled')) { + // return $next($request); + // } $timeStart = microtime(true); DB::enableQueryLog(); @@ -52,11 +52,12 @@ class QueryLogging $time = $timeEnd - $timeStart; // info("Query count = {$count}"); - - if($count > 175){ - nlog("Query count = {$count}"); - nlog($queries); - } + $url = urldecode($request->url()); + $method = $request->method(); + // if($count > 175){ + nlog("Query count = {$count} - {$method} - {$url} "); + // nlog($queries); + // } $ip = ''; diff --git a/app/Import/Transformer/Wave/InvoiceTransformer.php b/app/Import/Transformer/Wave/InvoiceTransformer.php index 68e40115b354..60921ddee0fd 100644 --- a/app/Import/Transformer/Wave/InvoiceTransformer.php +++ b/app/Import/Transformer/Wave/InvoiceTransformer.php @@ -83,11 +83,17 @@ class InvoiceTransformer extends BaseTransformer { } else { //could be a generate invoices.csv file + + $calculated_tax_rate = 0; + + if($this->getFloat( $record, 'Invoice Tax Total' ) != 0 && $this->getFloat( $record, 'Invoice Total' ) != 0) + $calculated_tax_rate = round($this->getFloat( $record, 'Invoice Tax Total' ) / $this->getFloat( $record, 'Invoice Total' ) * 100,2); + $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), + 'tax_rate1' => $calculated_tax_rate, 'quantity' => 1, ]; diff --git a/app/Listeners/Invoice/CreateInvoicePdf.php b/app/Listeners/Invoice/CreateInvoicePdf.php index ab9b23333c74..eb10aaf2a4bb 100644 --- a/app/Listeners/Invoice/CreateInvoicePdf.php +++ b/app/Listeners/Invoice/CreateInvoicePdf.php @@ -39,21 +39,21 @@ class CreateInvoicePdf implements ShouldQueue if(isset($event->invoice)) { $event->invoice->invitations->each(function ($invitation) { - CreateEntityPdf::dispatch($invitation); + CreateEntityPdf::dispatch($invitation->load("invoice", "contact.client.company")); }); } if(isset($event->quote)) { $event->quote->invitations->each(function ($invitation) { - CreateEntityPdf::dispatch($invitation); + CreateEntityPdf::dispatch($invitation->load("quote", "contact.client.company")); }); } if(isset($event->credit)) { $event->credit->invitations->each(function ($invitation) { - CreateEntityPdf::dispatch($invitation); + CreateEntityPdf::dispatch($invitation->load("credit", "contact.client.company")); }); } diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 5a028981c5f7..928051e6428f 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -466,6 +466,7 @@ class Invoice extends BaseModel { $this->invitations->each(function ($invitation) { if (! isset($invitation->sent_date)) { + $invitation->load('invoice'); $invitation->sent_date = Carbon::now(); $invitation->save(); } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 7374fe18ad27..f2d5f13296cc 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -70,7 +70,6 @@ class AppServiceProvider extends ServiceProvider app()->instance(TruthSource::class, new TruthSource()); - // Model::preventLazyLoading( // !$this->app->isProduction() // ); diff --git a/app/Repositories/ActivityRepository.php b/app/Repositories/ActivityRepository.php index a4a771991813..6c9e361a226e 100644 --- a/app/Repositories/ActivityRepository.php +++ b/app/Repositories/ActivityRepository.php @@ -110,12 +110,20 @@ class ActivityRepository extends BaseRepository private function generateHtml($entity) { $entity_design_id = ''; + $entity_type = ''; - if ($entity instanceof Invoice || $entity instanceof RecurringInvoice) { + if ($entity instanceof Invoice ) { + $entity_type = 'invoice'; $entity_design_id = 'invoice_design_id'; - } elseif ($entity instanceof Quote) { + } elseif ($entity instanceof RecurringInvoice){ + $entity_type = 'recurring_invoice'; + $entity_design_id = 'invoice_design_id'; + } + elseif ($entity instanceof Quote) { + $entity_type = 'quote'; $entity_design_id = 'quote_design_id'; } elseif ($entity instanceof Credit) { + $entity_type = 'credit'; $entity_design_id = 'credit_design_id'; } @@ -132,7 +140,7 @@ class ActivityRepository extends BaseRepository $entity->load('client.company', 'invitations'); - $html = new HtmlEngine($entity->invitations->first()); + $html = new HtmlEngine($entity->invitations->first()->load($entity_type, "contact")); if ($design->is_custom) { $options = [ diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index 8ecc39274f44..e91ae43aa5b5 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -242,7 +242,7 @@ class InvoiceService public function triggeredActions($request) { - $this->invoice = (new TriggeredActions($this->invoice, $request))->run(); + $this->invoice = (new TriggeredActions($this->invoice->load('invitations'), $request))->run(); return $this; } diff --git a/app/Services/Quote/QuoteService.php b/app/Services/Quote/QuoteService.php index 05816b5945ed..e340f9e8ae62 100644 --- a/app/Services/Quote/QuoteService.php +++ b/app/Services/Quote/QuoteService.php @@ -221,7 +221,7 @@ class QuoteService public function triggeredActions($request) { - $this->quote = (new TriggeredActions($this->quote, $request))->run(); + $this->quote = (new TriggeredActions($this->quote->load('invitations'), $request))->run(); return $this; } diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php index 34585a2efb06..6f1a17a54ee3 100644 --- a/app/Utils/HtmlEngine.php +++ b/app/Utils/HtmlEngine.php @@ -58,7 +58,7 @@ class HtmlEngine $this->company = $invitation->company; - $this->contact = $invitation->contact; + $this->contact = $invitation->contact->load('client'); $this->client = $this->contact->client->load('company','country');