From 41b19c20c181f80b1334c1c4f730214f429b3dbd Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 27 May 2020 14:54:47 +1000 Subject: [PATCH 1/6] Place checks on quote 'isConvertable()' --- app/Http/Controllers/QuoteController.php | 2 +- app/Services/Quote/QuoteService.php | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index 9ecc45ddc1..59e43a4700 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -534,7 +534,7 @@ class QuoteController extends BaseController $this->entity_transformer = InvoiceTransformer::class; $invoices = $quotes->map(function ($quote, $key) use ($action) { - if (auth()->user()->can('edit', $quote)) { + if (auth()->user()->can('edit', $quote) && $quote->service()->isConvertable()) { $invoice = $quote->service()->convertToInvoice(); return $invoice->id; } diff --git a/app/Services/Quote/QuoteService.php b/app/Services/Quote/QuoteService.php index b9d9b0ebdc..71424e31c6 100644 --- a/app/Services/Quote/QuoteService.php +++ b/app/Services/Quote/QuoteService.php @@ -55,6 +55,7 @@ class QuoteService return $this; $convert_quote = new ConvertQuote($this->quote->client); + $this->invoice = $convert_quote->run($this->quote); $this->quote->fresh(); @@ -125,7 +126,7 @@ class QuoteService return $this; } - public function convertToInvoice() :Invoice + public function convertToInvoice() { //to prevent circular references we need to explicit call this here. @@ -137,6 +138,17 @@ class QuoteService return $this->invoice; } + public function isConvertable() :bool + { + if($this->quote->invoice_id) + return false; + + if($this->quote->status_id == Quote::STATUS_EXPIRED) + return false; + + return true; + } + /** * Saves the quote * @return Quote|null From 2d2be07944fd113040a5eb6cad095004443bf1b1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 28 May 2020 10:04:26 +1000 Subject: [PATCH 2/6] Improvements to quality of test data --- app/Console/Commands/CreateTestData.php | 84 +++++++++++++++--------- app/Http/Controllers/QuoteController.php | 7 +- database/factories/ClientFactory.php | 10 +-- 3 files changed, 62 insertions(+), 39 deletions(-) diff --git a/app/Console/Commands/CreateTestData.php b/app/Console/Commands/CreateTestData.php index df22a2a24b..7b79178e2b 100644 --- a/app/Console/Commands/CreateTestData.php +++ b/app/Console/Commands/CreateTestData.php @@ -135,28 +135,44 @@ class CreateTestData extends Command $this->createClient($company, $user); } - foreach ($company->clients as $client) { + for($x=0; $x<$this->count; $x++) + { + $client = $company->clients->random(); + $this->info('creating invoice for client #'.$client->id); $this->createInvoice($client); + $client = $company->clients->random(); + $this->info('creating credit for client #'.$client->id); $this->createCredit($client); + $client = $company->clients->random(); + $this->info('creating quote for client #'.$client->id); $this->createQuote($client); + $client = $company->clients->random(); + $this->info('creating expense for client #'.$client->id); $this->createExpense($client); + $client = $company->clients->random(); + $this->info('creating vendor for client #'.$client->id); $this->createVendor($client); + $client = $company->clients->random(); + $this->info('creating task for client #'.$client->id); $this->createTask($client); + $client = $company->clients->random(); + $this->info('creating project for client #'.$client->id); $this->createProject($client); } + } private function createMediumAccount() @@ -217,49 +233,42 @@ class CreateTestData extends Command $this->createClient($company, $user); } - foreach ($company->clients as $client) { - $this->info('creating invoice for client #'.$client->id); + for($x=0; $x<$this->count; $x++) + { + $client = $company->clients->random(); - for ($i=0; $i<$this->count; $i++) { - $this->createInvoice($client); - } + $this->info('creating invoice for client #'.$client->id); + $this->createInvoice($client); + + $client = $company->clients->random(); $this->info('creating credit for client #'.$client->id); + $this->createCredit($client); - for ($i=0; $i<$this->count; $i++) { - $this->createCredit($client); - } - + $client = $company->clients->random(); $this->info('creating quote for client #'.$client->id); + $this->createQuote($client); - for ($i=0; $i<$this->count; $i++) { - $this->createQuote($client); - } + $client = $company->clients->random(); $this->info('creating expense for client #'.$client->id); - - for ($i=0; $i<$this->count; $i++) { - $this->createExpense($client); - } + $this->createExpense($client); + + $client = $company->clients->random(); $this->info('creating vendor for client #'.$client->id); - - for ($i=0; $i<$this->count; $i++) { - $this->createVendor($client); - } + $this->createVendor($client); + + $client = $company->clients->random(); $this->info('creating task for client #'.$client->id); - - for ($i=0; $i<$this->count; $i++) { - $this->createTask($client); - } + $this->createTask($client); + + $client = $company->clients->random(); $this->info('creating project for client #'.$client->id); - - for ($i=0; $i<$this->count; $i++) { - $this->createProject($client); - } + $this->createProject($client); } } @@ -322,25 +331,40 @@ class CreateTestData extends Command $this->createClient($company, $user); } - foreach ($company->clients as $client) { + for($x=0; $x<$this->count; $x++) + { + $client = $company->clients->random(); + $this->info('creating invoice for client #'.$client->id); $this->createInvoice($client); + $client = $company->clients->random(); + $this->info('creating credit for client #'.$client->id); $this->createCredit($client); + $client = $company->clients->random(); + $this->info('creating quote for client #'.$client->id); $this->createQuote($client); + $client = $company->clients->random(); + $this->info('creating expense for client #'.$client->id); $this->createExpense($client); + $client = $company->clients->random(); + $this->info('creating vendor for client #'.$client->id); $this->createVendor($client); + $client = $company->clients->random(); + $this->info('creating task for client #'.$client->id); $this->createTask($client); + $client = $company->clients->random(); + $this->info('creating project for client #'.$client->id); $this->createProject($client); } diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index 59e43a4700..cfcb8cdac6 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -533,14 +533,13 @@ class QuoteController extends BaseController $this->entity_type = Invoice::class; $this->entity_transformer = InvoiceTransformer::class; - $invoices = $quotes->map(function ($quote, $key) use ($action) { + $quotes->each(function ($quote, $key) use ($action) { if (auth()->user()->can('edit', $quote) && $quote->service()->isConvertable()) { - $invoice = $quote->service()->convertToInvoice(); - return $invoice->id; + $quote->service()->convertToInvoice(); } }); - return $this->listResponse(Invoice::withTrashed()->whereIn('id', $invoices)->company()); + return $this->listResponse(Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()); } /* diff --git a/database/factories/ClientFactory.php b/database/factories/ClientFactory.php index 270b23dbdc..e00726d139 100644 --- a/database/factories/ClientFactory.php +++ b/database/factories/ClientFactory.php @@ -12,11 +12,11 @@ $factory->define(App\Models\Client::class, function (Faker $faker) { 'balance' => 0, 'paid_to_date' => 0, 'vat_number' => $faker->text(25), - 'id_number' => $faker->text(20), - 'custom_value1' => $faker->text(20), - 'custom_value2' => $faker->text(20), - 'custom_value3' => $faker->text(20), - 'custom_value4' => $faker->text(20), + 'id_number' => '', + 'custom_value1' => 'date|'.$faker->date('Y-m-d'), + 'custom_value2' => '', + 'custom_value3' => '', + 'custom_value4' => '', 'address1' => $faker->buildingNumber, 'address2' => $faker->streetAddress, 'city' => $faker->city, From 0485ffe912c4db3a5f3f4f5aa8a2607629d205dd Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 28 May 2020 10:59:33 +1000 Subject: [PATCH 3/6] fixes for invoices not generating invoice numbers on payment --- app/Services/Invoice/ApplyPayment.php | 2 ++ app/Services/Invoice/MarkPaid.php | 1 + database/factories/ClientFactory.php | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/Services/Invoice/ApplyPayment.php b/app/Services/Invoice/ApplyPayment.php index 9177e7ebd7..b606002084 100644 --- a/app/Services/Invoice/ApplyPayment.php +++ b/app/Services/Invoice/ApplyPayment.php @@ -62,6 +62,8 @@ class ApplyPayment extends AbstractService $this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($this->payment_amount*-1); } + $this->invoice->service()->applyNumber->save(); + return $this->invoice; } } diff --git a/app/Services/Invoice/MarkPaid.php b/app/Services/Invoice/MarkPaid.php index 6660c1a7df..8778a4ebd3 100644 --- a/app/Services/Invoice/MarkPaid.php +++ b/app/Services/Invoice/MarkPaid.php @@ -61,6 +61,7 @@ class MarkPaid extends AbstractService $this->invoice->service() ->updateBalance($payment->amount*-1) ->setStatus(Invoice::STATUS_PAID) + ->applyNumber() ->save(); /* Update Invoice balance */ diff --git a/database/factories/ClientFactory.php b/database/factories/ClientFactory.php index e00726d139..62b30fe154 100644 --- a/database/factories/ClientFactory.php +++ b/database/factories/ClientFactory.php @@ -13,7 +13,7 @@ $factory->define(App\Models\Client::class, function (Faker $faker) { 'paid_to_date' => 0, 'vat_number' => $faker->text(25), 'id_number' => '', - 'custom_value1' => 'date|'.$faker->date('Y-m-d'), + 'custom_value1' => $faker->date('Y-m-d'), 'custom_value2' => '', 'custom_value3' => '', 'custom_value4' => '', From b28cdd488bee00fafc747004836ed8f09e7813e3 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 28 May 2020 14:18:34 +1000 Subject: [PATCH 4/6] Set due date when invoice is marked as sent --- app/Services/Invoice/ApplyPayment.php | 4 ++-- app/Services/Invoice/InvoiceService.php | 7 ++++++- app/Services/Invoice/MarkSent.php | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/Services/Invoice/ApplyPayment.php b/app/Services/Invoice/ApplyPayment.php index b606002084..dda5d1fcce 100644 --- a/app/Services/Invoice/ApplyPayment.php +++ b/app/Services/Invoice/ApplyPayment.php @@ -62,8 +62,8 @@ class ApplyPayment extends AbstractService $this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($this->payment_amount*-1); } - $this->invoice->service()->applyNumber->save(); - + $this->invoice->service()->applyNumber()->save(); + return $this->invoice; } } diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index ad5567fc0a..589f6a3e24 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -139,8 +139,13 @@ class InvoiceService /* One liners */ public function setDueDate() { - $this->invoice->due_date = Carbon::now()->addDays($this->invoice->client->getSetting('payment_terms')); + if($this->invoice->due_date != '') + return $this; + //$this->invoice->due_date = Carbon::now()->addDays($this->invoice->client->getSetting('payment_terms')); + + $this->invoice->due_date = Carbon::parse($this->invoice->date)->addDays($this->invoice->client->getSetting('payment_terms')); + return $this; } diff --git a/app/Services/Invoice/MarkSent.php b/app/Services/Invoice/MarkSent.php index 994344bcb4..f31175598b 100644 --- a/app/Services/Invoice/MarkSent.php +++ b/app/Services/Invoice/MarkSent.php @@ -45,6 +45,7 @@ class MarkSent extends AbstractService ->service() ->setStatus(Invoice::STATUS_SENT) ->applyNumber() + ->setDueDate() ->save(); $this->client->service()->updateBalance($this->invoice->balance)->save(); From fe3242a0958673d5923e4cbe95adaa5207251486 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 28 May 2020 18:54:13 +1000 Subject: [PATCH 5/6] Adjustments for setup page --- app/Http/Controllers/BaseController.php | 4 ++-- resources/views/setup/_database.blade.php | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index 0b2293328e..fe6e3f777c 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -319,10 +319,10 @@ class BaseController extends Controller // return redirect()->secure(request()->path()); // } - if ((bool)$this->checkAppSetup() !== false) { + if ((bool)$this->checkAppSetup() !== false && $account = Account::all()->first()) { $data = []; - if (Ninja::isSelfHost() && $account = Account::all()->first()) { + if (Ninja::isSelfHost()) { $data['report_errors'] = $account->report_errors; } else { $data['report_errors'] = true; diff --git a/resources/views/setup/_database.blade.php b/resources/views/setup/_database.blade.php index 159bd92957..52c2e1f487 100644 --- a/resources/views/setup/_database.blade.php +++ b/resources/views/setup/_database.blade.php @@ -17,7 +17,7 @@ Show code
 -- Commands to create a MySQL database and user
-CREATE SCHEMA `ninja` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
+CREATE SCHEMA `db-ninja-01` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
 CREATE USER 'ninja'@'localhost' IDENTIFIED BY 'ninja';
 GRANT ALL PRIVILEGES ON `ninja`.* TO 'ninja'@'localhost';
 FLUSH PRIVILEGES;
@@ -38,7 +38,7 @@ FLUSH PRIVILEGES;
                     {{ ctrans('texts.host') }}*
                 
                 
- +
@@ -46,7 +46,7 @@ FLUSH PRIVILEGES; {{ ctrans('texts.database') }}*
- +
@@ -54,7 +54,7 @@ FLUSH PRIVILEGES; {{ ctrans('texts.username') }}*
- +
@@ -62,7 +62,7 @@ FLUSH PRIVILEGES; {{ ctrans('texts.password') }}
- +
From dea5543c06cdced342f6f42d7ec78ff10a807dec Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 28 May 2020 19:40:35 +1000 Subject: [PATCH 6/6] Fixes for setup page flow --- app/Exceptions/Handler.php | 10 +++++++--- app/Http/Controllers/BaseController.php | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 5d40fb8b87..2049d9c59c 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -15,15 +15,16 @@ use Exception; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Auth\AuthenticationException; use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException; +use Illuminate\Database\Eloquent\RelationNotFoundException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Http\Exceptions\ThrottleRequestsException; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Schema; use Illuminate\Validation\ValidationException; +use Sentry\State\Scope; use Symfony\Component\Debug\Exception\FatalThrowableError; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Illuminate\Database\Eloquent\RelationNotFoundException; -use Sentry\State\Scope; use function Sentry\configureScope; class Handler extends ExceptionHandler @@ -55,9 +56,12 @@ class Handler extends ExceptionHandler */ public function report(Exception $exception) { + if(!Schema::hasTable('accounts')) + return; + if (app()->bound('sentry') && $this->shouldReport($exception)) { app('sentry')->configureScope(function (Scope $scope): void { - if (auth()->guard('contact')->user() && auth()->guard('contact')->user()->company->account->report_errors) { + if (auth()->guard('contact') && auth()->guard('contact')->user() && auth()->guard('contact')->user()->company->account->report_errors) { $scope->setUser([ 'id' => auth()->guard('contact')->user()->company->account->key, 'email' => "anonymous@example.com", diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index fe6e3f777c..3444d6983e 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -23,6 +23,7 @@ use App\Utils\Traits\AppSetup; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Request as Input; +use Illuminate\Support\Facades\Schema; use League\Fractal\Manager; use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Resource\Collection; @@ -319,7 +320,7 @@ class BaseController extends Controller // return redirect()->secure(request()->path()); // } - if ((bool)$this->checkAppSetup() !== false && $account = Account::all()->first()) { + if ((bool)$this->checkAppSetup() !== false && Schema::hasTable('accounts') && $account = Account::all()->first()) { $data = []; if (Ninja::isSelfHost()) {