diff --git a/.env.example b/.env.example index ced6bafaf041..7cfcb0b572ee 100644 --- a/.env.example +++ b/.env.example @@ -23,7 +23,7 @@ DB_USERNAME2=ninja DB_PASSWORD2=ninja DB_PORT2=3306 - +DEMO_MODE=false BROADCAST_DRIVER=log LOG_CHANNEL=stack diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 109ac3b8bcb2..8d71e9ba0015 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -80,7 +80,7 @@ class Handler extends ExceptionHandler } else if($exception instanceof FatalThrowableError) { - return response()->json(['message'=>'Fatal error', 500]); + return response()->json(['message'=>'Fatal error'], 500); } else if($exception instanceof AuthorizationException) { diff --git a/app/Http/Controllers/ClientPortal/InvitationController.php b/app/Http/Controllers/ClientPortal/InvitationController.php index 44557d94d179..5ab7783297e6 100644 --- a/app/Http/Controllers/ClientPortal/InvitationController.php +++ b/app/Http/Controllers/ClientPortal/InvitationController.php @@ -29,10 +29,12 @@ class InvitationController extends Controller use MakesHash; use MakesDates; - public function invoiceRouter(string $invitation_key) + public function router(string $entity, string $invitation_key) { + $key = $entity.'_id'; + $entity_obj = ucfirst($entity).'Invitation'; - $invitation = InvoiceInvitation::whereRaw("BINARY `invitation_key`= ?", [$invitation_key])->first(); + $invitation = $entity_obj::whereRaw("BINARY `key`= ?", [$invitation_key])->first(); if($invitation){ @@ -41,7 +43,7 @@ class InvitationController extends Controller $invitation->markViewed(); - return redirect()->route('client.invoice.show', ['invoice' => $this->encodePrimaryKey($invitation->invoice_id)]); + return redirect()->route('client.'.$entity.'.show', [$entity => $this->encodePrimaryKey($invitation->{$key})]); } else @@ -49,9 +51,9 @@ class InvitationController extends Controller } - // public function invoiceRouterForIframe(string $client_hash, string $invitation_key) - // { + public function routerForIframe(string $entity, string $client_hash, string $invitation_key) + { - // } + } } diff --git a/app/Http/Controllers/OpenAPI/CompanySchema.php b/app/Http/Controllers/OpenAPI/CompanySchema.php index c6f082dfd23f..0dcd2821d095 100644 --- a/app/Http/Controllers/OpenAPI/CompanySchema.php +++ b/app/Http/Controllers/OpenAPI/CompanySchema.php @@ -6,6 +6,8 @@ * @OA\Property(property="id", type="string", example="WJxbojagwO", description="The company hash id"), * @OA\Property(property="size_id", type="string", example="1", description="The company size ID"), * @OA\Property(property="industry_id", type="string", example="1", description="The company industry ID"), + * @OA\Property(property="portal_mode", type="string", example="subdomain", description="Determines the client facing urls ie: subdomain,domain,iframe"), + * @OA\Property(property="portal_domain", type="string", example="https://subdomain.invoicing.co", description="The fully qualified domain for client facing URLS"), * @OA\Property(property="enabled_tax_rates", type="integer", example="1", description="Number of taxes rates used per entity"), * @OA\Property(property="fill_products", type="boolean", example=true, description="Toggles filling a product description based on product key"), * @OA\Property(property="convert_products", type="boolean", example=true, description="___________"), diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 88fc878d85f3..defd99cf4e52 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -603,11 +603,11 @@ class PaymentController extends BaseController switch ($action) { case 'clone_to_invoice': - $payment = CloneInvoiceFactory::create($payment, auth()->user()->id); - return $this->itemResponse($payment); + //$payment = CloneInvoiceFactory::create($payment, auth()->user()->id); + //return $this->itemResponse($payment); break; case 'clone_to_quote': - $quote = CloneInvoiceToQuoteFactory::create($payment, auth()->user()->id); + //$quote = CloneInvoiceToQuoteFactory::create($payment, auth()->user()->id); // todo build the quote transformer and return response here break; case 'history': diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 9e89969cf25a..87dc5a09948b 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -106,6 +106,8 @@ class Kernel extends HttpKernel 'contact_token_auth' => \App\Http\Middleware\ContactTokenAuth::class, 'contact_db' => \App\Http\Middleware\ContactSetDb::class, 'domain_db' => \App\Http\Middleware\SetDomainNameDb::class, + 'email_db' => \App\Http\Middleware\SetEmailDb::class, + 'invite_db' => \App\Http\Middleware\SetInviteDb::class, 'password_protected' => \App\Http\Middleware\PasswordProtection::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'portal_enabled' => \App\Http\Middleware\ClientPortalEnabled::class, diff --git a/app/Http/Middleware/ApiSecretCheck.php b/app/Http/Middleware/ApiSecretCheck.php index d7f1448a9385..a76df2f54602 100644 --- a/app/Http/Middleware/ApiSecretCheck.php +++ b/app/Http/Middleware/ApiSecretCheck.php @@ -37,7 +37,7 @@ class ApiSecretCheck return response() ->json(json_encode($error, JSON_PRETTY_PRINT) ,403) ->header('X-App-Version', config('ninja.app_version')) - ->header('X-API-VERSION', config('ninja.api_version')); + ->header('X-Api-Version', config('ninja.api_version')); } diff --git a/app/Http/Middleware/SetEmailDb.php b/app/Http/Middleware/SetEmailDb.php new file mode 100644 index 000000000000..39d12ca0b997 --- /dev/null +++ b/app/Http/Middleware/SetEmailDb.php @@ -0,0 +1,58 @@ + 'Email not set or not found', + 'errors' => [] + ]; + + if( $request->input('email') && config('ninja.db.multi_db_enabled')) + { + + if(! MultiDB::userFindAndSetDb($request->input('email'))) + { + + return response()->json($error, 403); + + } + + } + else { + + + return response()->json($error, 403); + + } + + return $next($request); + } + + +} diff --git a/app/Http/Middleware/SetInviteDb.php b/app/Http/Middleware/SetInviteDb.php new file mode 100644 index 000000000000..ef2e7764ece3 --- /dev/null +++ b/app/Http/Middleware/SetInviteDb.php @@ -0,0 +1,49 @@ + 'Invalid URL', + 'errors' => [] + ]; + /* + * Use the host name to set the active DB + **/ + if( $request->getSchemeAndHttpHost() && config('ninja.db.multi_db_enabled') && ! MultiDB::findAndSetDbByInvitation($request->route('entity'),$request->route('invitation_key'))) + { + if(request()->json) + return response()->json(json_encode($error, JSON_PRETTY_PRINT) ,403); + else + abort(404); + } + + return $next($request); + } + + +} diff --git a/app/Http/Requests/Payment/StorePaymentRequest.php b/app/Http/Requests/Payment/StorePaymentRequest.php index 7263ec9fce07..dff715924dbb 100644 --- a/app/Http/Requests/Payment/StorePaymentRequest.php +++ b/app/Http/Requests/Payment/StorePaymentRequest.php @@ -13,9 +13,11 @@ namespace App\Http\Requests\Payment; use App\Http\Requests\Request; use App\Models\Payment; +use App\Utils\Traits\MakesHash; class StorePaymentRequest extends Request { + use MakesHash; /** * Determine if the user is authorized to make this request. * @@ -29,6 +31,8 @@ class StorePaymentRequest extends Request public function rules() { + $this->sanitize(); + return [ 'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx', 'client_id' => 'integer|nullable', @@ -41,7 +45,15 @@ class StorePaymentRequest extends Request public function sanitize() { - //do post processing of Payment request here, ie. Payment_items + + $input = $this->all(); + + if(isset($input['invoices'])) + $input['invoices'] = $this->transformKeys(array_column($input['invoices']), 'id'); + + $this->replace($input); + + return $this->all(); } public function messages() diff --git a/app/Http/Requests/Quote/UpdateQuoteRequest.php b/app/Http/Requests/Quote/UpdateQuoteRequest.php index f10ddb053cb1..288dbae40cbf 100644 --- a/app/Http/Requests/Quote/UpdateQuoteRequest.php +++ b/app/Http/Requests/Quote/UpdateQuoteRequest.php @@ -12,11 +12,16 @@ namespace App\Http\Requests\Quote; use App\Http\Requests\Request; +use App\Utils\Traits\CleanLineItems; +use App\Utils\Traits\MakesHash; use Illuminate\Support\Facades\Log; use Illuminate\Validation\Rule; class UpdateQuoteRequest extends Request { + use MakesHash; + use CleanLineItems; + /** * Determine if the user is authorized to make this request. * @@ -33,10 +38,26 @@ class UpdateQuoteRequest extends Request public function rules() { + $this->sanitize(); + return [ 'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx', - 'client_id' => 'required|integer', ]; } - + + public function sanitize() + { + $input = $this->all(); + + // if(isset($input['client_id'])) + // $input['client_id'] = $this->decodePrimaryKey($input['client_id']); + + if(isset($input['line_items'])) + $input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : []; + + $this->replace($input); + + return $this->all(); + } + } \ No newline at end of file diff --git a/app/Jobs/Invoice/CreateInvoiceInvitations.php b/app/Jobs/Invoice/CreateInvoiceInvitations.php new file mode 100644 index 000000000000..7361f80f8820 --- /dev/null +++ b/app/Jobs/Invoice/CreateInvoiceInvitations.php @@ -0,0 +1,67 @@ +invoice = $invoice; + + } + + public function handle() + { + + $contacts = $this->invoice->client->contacts; + + $contacts->each(function ($contact) { + + $invitation = InvoiceInvitation::whereCompanyId($this->invoice->company_id) + ->whereClientContactId($contact->id) + ->whereInvoiceId($this->invoice->id) + ->first(); + + if(!$invitation && $contact->send_invoice) { + $ii = InvoiceInvitationFactory::create($this->invoice->company_id, $this->invoice->user_id); + $ii->invoice_id = $this->invoice->id; + $ii->client_contact_id = $contact->id; + $ii->save(); + } + else if($invitation && !$contact->send_invoice) { + $invitation->delete(); + } + + }); + + } +} \ No newline at end of file diff --git a/app/Libraries/MultiDB.php b/app/Libraries/MultiDB.php index c68d49169ab1..9be708240961 100644 --- a/app/Libraries/MultiDB.php +++ b/app/Libraries/MultiDB.php @@ -123,6 +123,21 @@ class MultiDB } + public static function userFindAndSetDb($email) : bool + { + + + //multi-db active + foreach (self::$dbs as $db) + { + if(User::on($db)->where(['email' => $email])->get()->count() >=1) // if user already exists, validation will fail + return true; + } + + return false; + + } + public static function findAndSetDb($token) :bool { @@ -161,6 +176,21 @@ class MultiDB } + public static function findAndSetDbByInvitation($entity, $invitation_key) + { + $entity.'Invitation'; + + foreach (self::$dbs as $db) + { + if($invite = $entity::on($db)->whereKey($invitation_key)->first()) + { + self::setDb($db); + return true; + } + } + return false; + } + /** * @param $database */ diff --git a/app/Models/InvoiceInvitation.php b/app/Models/InvoiceInvitation.php index 8fd890ad423c..b3088ade4312 100644 --- a/app/Models/InvoiceInvitation.php +++ b/app/Models/InvoiceInvitation.php @@ -12,6 +12,7 @@ namespace App\Models; use App\Models\Invoice; +use App\Utils\Traits\Inviteable; use App\Utils\Traits\MakesDates; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; @@ -22,7 +23,8 @@ class InvoiceInvitation extends BaseModel use MakesDates; use SoftDeletes; - + use Inviteable; + protected $fillable = [ 'id', 'client_contact_id', @@ -79,11 +81,6 @@ class InvoiceInvitation extends BaseModel return $this->invitation_key; } - public function getLink() - { - - } - public function markViewed() { $this->viewed_date = Carbon::now(); diff --git a/app/Models/Quote.php b/app/Models/Quote.php index 3fa46c43950e..bb180dd2d8af 100644 --- a/app/Models/Quote.php +++ b/app/Models/Quote.php @@ -73,6 +73,12 @@ class Quote extends BaseModel return $this->belongsTo(User::class); } + public function client() + { + return $this->belongsTo(Client::class); + } + + public function assigned_user() { return $this->belongsTo(User::class ,'assigned_user_id', 'id'); diff --git a/app/Repositories/InvoiceRepository.php b/app/Repositories/InvoiceRepository.php index ae22f7a12075..6c91e86582a8 100644 --- a/app/Repositories/InvoiceRepository.php +++ b/app/Repositories/InvoiceRepository.php @@ -17,6 +17,7 @@ use App\Factory\InvoiceInvitationFactory; use App\Helpers\Invoice\InvoiceSum; use App\Jobs\Company\UpdateCompanyLedgerWithInvoice; use App\Jobs\Invoice\ApplyInvoiceNumber; +use App\Jobs\Invoice\CreateInvoiceInvitations; use App\Listeners\Invoice\CreateInvoiceInvitation; use App\Models\ClientContact; use App\Models\Invoice; @@ -58,6 +59,7 @@ class InvoiceRepository extends BaseRepository $starting_amount = $invoice->amount; $invoice->fill($data); + $invoice->save(); if(isset($data['client_contacts'])) @@ -105,7 +107,9 @@ class InvoiceRepository extends BaseRepository } - //event(new CreateInvoiceInvitation($invoice)); + /* If no invitations have been created, this is our fail safe to maintain state*/ + if($invoice->invitations->count() == 0) + CreateInvoiceInvitations::dispatchNow($invoice); $invoice = $invoice->calc()->getInvoice(); diff --git a/app/Repositories/PaymentRepository.php b/app/Repositories/PaymentRepository.php index cced9b9ba7c3..88a8c72b55cf 100644 --- a/app/Repositories/PaymentRepository.php +++ b/app/Repositories/PaymentRepository.php @@ -28,8 +28,19 @@ class PaymentRepository extends BaseRepository public function save(Request $request, Payment $payment) : ?Payment { + $payment->fill($request->input()); + if($request->input('invoices')) + { + + $invoices = Invoice::whereIn('id', $request->input('invoices'))->get(); + + } + + //parse invoices[] and attach to paymentables + //parse invoices[] and apply payments and subfunctions + $payment->save(); return $payment; diff --git a/app/Repositories/QuoteRepository.php b/app/Repositories/QuoteRepository.php index 4bbcfc642b22..47a341995eed 100644 --- a/app/Repositories/QuoteRepository.php +++ b/app/Repositories/QuoteRepository.php @@ -12,6 +12,7 @@ namespace App\Repositories; use App\Helpers\Invoice\InvoiceSum; +use App\Models\Client; use App\Models\Quote; use Illuminate\Http\Request; @@ -29,12 +30,12 @@ class QuoteRepository extends BaseRepository public function save(Request $request, Quote $quote) : ?Quote { + $quote->fill($request->input()); - + $quote->save(); - - $invoice_calc = new InvoiceSum($quote, $quote->settings); + $invoice_calc = new InvoiceSum($quote); $quote = $invoice_calc->build()->getInvoice(); diff --git a/app/Transformers/InvoiceInvitationTransformer.php b/app/Transformers/InvoiceInvitationTransformer.php index c7b450a67eb8..63bcdb94f707 100644 --- a/app/Transformers/InvoiceInvitationTransformer.php +++ b/app/Transformers/InvoiceInvitationTransformer.php @@ -28,7 +28,7 @@ class InvoiceInvitationTransformer extends EntityTransformer 'key' => $invitation->key, 'link' => $invitation->getLink() ?: '', 'sent_date' => $invitation->sent_date ?: '', - 'viewed_date' => $invitation->sent_date ?: '', + 'viewed_date' => $invitation->viewed_date ?: '', 'opened_date' => $invitation->opened_date ?: '', ]; } diff --git a/app/Utils/Traits/Inviteable.php b/app/Utils/Traits/Inviteable.php index 53e03063f48c..9c21dc5cb5c8 100644 --- a/app/Utils/Traits/Inviteable.php +++ b/app/Utils/Traits/Inviteable.php @@ -34,7 +34,6 @@ trait Inviteable if(isset($this->opened_date)) $status = ctrans('texts.invitation_status_opened'); - if(isset($this->viewed_date)) $status = ctrans('texts.invitation_status_viewed'); @@ -42,4 +41,30 @@ trait Inviteable return $status; } + public function getLink() : string + { + $entity_type = strtolower(class_basename($this->entityType())); + + //$this->with('company','contact',$this->entity_type); + $this->with('company'); + + $domain = isset($this->company->portal_domain) ?: $this->company->domain; + + switch ($this->company->portal_mode) { + case 'subdomain': + return $domain . $entity_type .'/'. $this->key; + break; + case 'iframe': + return $domain . $entity_type .'/'. $this->key; + //return $domain . $entity_type .'/'. $this->contact->client->client_hash .'/'. $this->key; + break; + case 'domain': + return $domain . $entity_type .'/'. $this->key; + break; + + } + + } + + } \ No newline at end of file diff --git a/database/migrations/2014_10_13_000000_create_users_table.php b/database/migrations/2014_10_13_000000_create_users_table.php index 281395a23551..9f977bfc050d 100644 --- a/database/migrations/2014_10_13_000000_create_users_table.php +++ b/database/migrations/2014_10_13_000000_create_users_table.php @@ -161,6 +161,9 @@ class CreateUsersTable extends Migration $table->unsignedInteger('size_id')->nullable(); $table->string('first_day_of_week')->nullable(); $table->string('first_month_of_year')->nullable(); + $table->string('portal_mode')->default('subdomain'); + $table->string('portal_domain')->nullable(); + $table->smallInteger('enable_modules')->default(0); $table->mediumText('custom_fields'); $table->mediumText('settings'); diff --git a/routes/api.php b/routes/api.php index 1c305e49567e..a172749c0774 100644 --- a/routes/api.php +++ b/routes/api.php @@ -25,7 +25,7 @@ Route::group(['middleware' => ['api_secret_check']], function () { }); -Route::group(['api_secret_check','domain_db'], function () { +Route::group(['api_secret_check','email_db'], function () { Route::post('api/v1/login', 'Auth\LoginController@apiLogin')->name('login.submit'); Route::post('api/v1/reset_password', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.reset'); diff --git a/routes/client.php b/routes/client.php index b3f67c4ef3f1..98e575027d8c 100644 --- a/routes/client.php +++ b/routes/client.php @@ -11,7 +11,6 @@ Route::get('client/password/reset/{token}', 'Auth\ContactResetPasswordController Route::post('client/password/reset', 'Auth\ContactResetPasswordController@reset')->name('client.password.update'); //todo implement domain DB -//Route::group(['middleware' => ['auth:contact', 'domain_db'], 'prefix' => 'client', 'as' => 'client.'], function () { Route::group(['middleware' => ['auth:contact'], 'prefix' => 'client', 'as' => 'client.'], function () { Route::get('dashboard', 'ClientPortal\DashboardController@index')->name('dashboard'); // name = (dashboard. index / create / show / update / destroy / edit @@ -45,11 +44,11 @@ Route::group(['middleware' => ['auth:contact'], 'prefix' => 'client', 'as' => 'c }); -Route::group(['middleware' => ['domain_db'], 'prefix' => 'client', 'as' => 'client.'], function () { +Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'client.'], function () { /*Invitation catches*/ - Route::get('invoice/{invitation_id}','ClientPortal\InvitationController@invoiceRouter'); - //Route::get('invoice/{client_hash}/{invitation_id}','ClientPortal\InvitationController@invoiceRouterForIframe'); we shouldn't need this if we force subdomain for the clients + Route::get('{entity}/{invitation_key}','ClientPortal\InvitationController@router'); + Route::get('{entity}/{client_hash}/{invitation_key}','ClientPortal\InvitationController@routerForIframe'); //should never need this Route::get('payment_hook/{company_gateway_id}/{gateway_type_id}','ClientPortal\PaymentHookController@process'); }); diff --git a/tests/Feature/ClientApiTest.php b/tests/Feature/ClientApiTest.php index 5370ba9e46a1..26519012f09d 100644 --- a/tests/Feature/ClientApiTest.php +++ b/tests/Feature/ClientApiTest.php @@ -22,6 +22,7 @@ use Tests\TestCase; /** * @test + * @covers App\Http\Controllers\ClientController */ class ClientApiTest extends TestCase { @@ -89,5 +90,68 @@ class ClientApiTest extends TestCase $response->assertStatus(200); } - + + public function testClientNotArchived() + { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->get('/api/v1/clients/'.$this->encodePrimaryKey($this->client->id)); + + $arr = $response->json(); + + $this->assertNull($arr['data']['deleted_at']); + } + + public function testClientArchived() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->client->id)], + ]; + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->post('/api/v1/clients/bulk?action=archive', $data); + + $arr = $response->json(); + + $this->assertNotNull($arr['data'][0]['deleted_at']); + } + + public function testClientRestored() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->client->id)], + ]; + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->post('/api/v1/clients/bulk?action=restore', $data); + + $arr = $response->json(); + + $this->assertNull($arr['data'][0]['deleted_at']); + } + + public function testClientDeleted() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->client->id)], + ]; + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->post('/api/v1/clients/bulk?action=delete', $data); + + $arr = $response->json(); + + $this->assertTrue($arr['data'][0]['is_deleted']); + } + } \ No newline at end of file diff --git a/tests/Feature/QuoteTest.php b/tests/Feature/QuoteTest.php index 670021b1cbca..d6fb142eecf7 100644 --- a/tests/Feature/QuoteTest.php +++ b/tests/Feature/QuoteTest.php @@ -178,17 +178,17 @@ class QuoteTest extends TestCase $quote_update = [ 'status_id' => Quote::STATUS_APPROVED, - 'client_id' => $quote->client_id, + // 'client_id' => $this->encodePrimaryKey($quote->client_id), ]; $this->assertNotNull($quote); - $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $token, - ])->put('/api/v1/quotes/'.$this->encodePrimaryKey($quote->id), $quote_update) - ->assertStatus(200); + ])->put('/api/v1/quotes/'.$this->encodePrimaryKey($quote->id), $quote_update); + + $response->assertStatus(200); $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), diff --git a/tests/Integration/MultiDBUserTest.php b/tests/Integration/MultiDBUserTest.php index e88d8da2b9a3..938eb790e505 100644 --- a/tests/Integration/MultiDBUserTest.php +++ b/tests/Integration/MultiDBUserTest.php @@ -112,10 +112,24 @@ class MultiDBUserTest extends TestCase $this->assertFalse(MultiDB::checkUserEmailExists('bademail@example.com')); } + public function test_check_that_set_db_by_email_works() + { + $this->assertTrue(MultiDB::userFindAndSetDb('db1@example.com')); + } + + public function test_check_that_set_db_by_email_works_db_2() + { + $this->assertTrue(MultiDB::userFindAndSetDb('db2@example.com')); + } + + public function test_check_that_set_db_by_email_works_db_3() + { + $this->assertFalse(MultiDB::userFindAndSetDb('bademail@example.com')); + } + /* * This is what you do when you demand 100% code coverage :/ */ - public function test_set_db_invokes() { $this->expectNotToPerformAssertions(MultiDB::setDB('db-ninja-01')); diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index be2ca8c9785a..853241e56fe4 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -18,6 +18,7 @@ use App\Factory\ClientFactory; use App\Factory\InvoiceFactory; use App\Factory\InvoiceItemFactory; use App\Factory\InvoiceToRecurringInvoiceFactory; +use App\Helpers\Invoice\InvoiceSum; use App\Jobs\Company\UpdateCompanyLedgerWithInvoice; use App\Models\Client; use App\Models\CompanyGateway; @@ -29,8 +30,9 @@ use App\Models\Quote; use App\Models\RecurringInvoice; use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\MakesHash; -use App\Helpers\Invoice\InvoiceSum; use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Schema; /** * Class MockAccountData @@ -54,6 +56,34 @@ trait MockAccountData public function makeTestData() { + + /* Warm up the cache !*/ + $cached_tables = config('ninja.cached_tables'); + + foreach ($cached_tables as $name => $class) { + if (! Cache::has($name)) { + // check that the table exists in case the migration is pending + if (! Schema::hasTable((new $class())->getTable())) { + continue; + } + if ($name == 'payment_terms') { + $orderBy = 'num_days'; + } elseif ($name == 'fonts') { + $orderBy = 'sort_order'; + } elseif (in_array($name, ['currencies', 'industries', 'languages', 'countries', 'banks'])) { + $orderBy = 'name'; + } else { + $orderBy = 'id'; + } + $tableData = $class::orderBy($orderBy)->get(); + if ($tableData->count()) { + Cache::forever($name, $tableData); + } + } + } + + + $this->account = factory(\App\Models\Account::class)->create(); $this->company = factory(\App\Models\Company::class)->create([ 'account_id' => $this->account->id,