From eac2d21d45b0c5d46d6e78c9e88a9a71311bbba3 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 17 Nov 2024 11:17:26 +1100 Subject: [PATCH] Updates for credit valid until date --- app/DataMapper/CompanySettings.php | 1 + app/Http/Controllers/DesignController.php | 90 ++++- .../Requests/Design/DefaultDesignRequest.php | 9 +- app/Services/Pdf/PdfBuilder.php | 5 + app/Services/Pdf/PdfMock.php | 2 + app/Services/PdfMaker/Design.php | 4 +- .../Designs/Utilities/DesignHelpers.php | 6 + app/Services/Template/TemplateService.php | 7 + app/Utils/HtmlEngine.php | 2 + composer.lock | 46 +-- tests/Feature/DesignApiTest.php | 351 +++++++++++++++++- 11 files changed, 483 insertions(+), 40 deletions(-) diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index 21bee38a8b..0778805016 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -999,6 +999,7 @@ class CompanySettings extends BaseSettings 'credit_details' => [ '$credit.number', '$credit.po_number', + '$credit.valid_until', '$credit.date', '$credit.balance', '$credit.total', diff --git a/app/Http/Controllers/DesignController.php b/app/Http/Controllers/DesignController.php index 4e2530bb14..82dfb06fdc 100644 --- a/app/Http/Controllers/DesignController.php +++ b/app/Http/Controllers/DesignController.php @@ -544,6 +544,9 @@ class DesignController extends BaseController { $design_id = $request->input('design_id'); $entity = $request->input('entity'); + $settings_level = $request->input('settings_level', 'company'); + $group_settings_id = $request->input('group_settings_id', false); + $client_id = $request->input('client_id', false); /** @var \App\Models\User $user */ $user = auth()->user(); @@ -561,19 +564,100 @@ class DesignController extends BaseController switch ($entity) { case 'invoice': - $company->invoices()->update(['design_id' => $design_id]); + + $company->invoices() + ->when($settings_level == 'company', function ($query){ + + $query->whereDoesntHave('client.group_settings') + ->orWhereHas('client.group_settings', function ($q){ + + $q->whereRaw("JSON_EXTRACT(settings, '$.invoice_design_id') IS NULL") + ->orWhereRaw("JSON_EXTRACT(settings, '$.invoice_design_id') = ''"); + + }); + }) + ->when($settings_level == 'group_settings' && $group_settings_id, function ($query) use($group_settings_id){ + + $query->whereHas('client', function ($q) use ($group_settings_id) { + $q->where('group_settings_id', $group_settings_id); + }); + + }) + ->when($settings_level == 'client' && $client_id, function ($query) use($client_id){ + + $query->where('client_id', $client_id); + + }) + ->update(['design_id' => $design_id]); + + + if($settings_level == 'company') + $company->recurring_invoices()->update(['design_id' => $design_id]); + break; case 'quote': - $company->quotes()->update(['design_id' => $design_id]); + + $company->quotes() + ->when($settings_level == 'company', function ($query){ + + $query->whereDoesntHave('client.group_settings') + ->orWhereHas('client.group_settings', function ($q){ + + $q->whereRaw("JSON_EXTRACT(settings, '$.invoice_design_id') IS NULL") + ->orWhereRaw("JSON_EXTRACT(settings, '$.invoice_design_id') = ''"); + + }); + }) + ->when($settings_level == 'group_settings' && $group_settings_id, function ($query) use($group_settings_id){ + + $query->whereHas('client', function ($q) use ($group_settings_id) { + $q->where('group_settings_id', $group_settings_id); + }); + + }) + ->when($settings_level == 'client' && $client_id, function ($query) use($client_id){ + + $query->where('client_id', $client_id); + + }) + ->update(['design_id' => $design_id]); + break; case 'credit': - $company->credits()->update(['design_id' => $design_id]); + + $company->credits() + ->when($settings_level == 'company', function ($query){ + + $query->whereDoesntHave('client.group_settings') + ->orWhereHas('client.group_settings', function ($q){ + + $q->whereRaw("JSON_EXTRACT(settings, '$.invoice_design_id') IS NULL") + ->orWhereRaw("JSON_EXTRACT(settings, '$.invoice_design_id') = ''"); + + }); + }) + ->when($settings_level == 'group_settings' && $group_settings_id, function ($query) use($group_settings_id){ + + $query->whereHas('client', function ($q) use ($group_settings_id) { + $q->where('group_settings_id', $group_settings_id); + }); + + }) + ->when($settings_level == 'client' && $client_id, function ($query) use($client_id){ + + $query->where('client_id', $client_id); + + }) + ->update(['design_id' => $design_id]); + break; + case 'purchase_order': $company->purchase_orders()->update(['design_id' => $design_id]); break; case 'recurring_invoice': $company->recurring_invoices()->update(['design_id' => $design_id]); + break; default: // code... diff --git a/app/Http/Requests/Design/DefaultDesignRequest.php b/app/Http/Requests/Design/DefaultDesignRequest.php index 367c4a4eae..4c324c65d3 100644 --- a/app/Http/Requests/Design/DefaultDesignRequest.php +++ b/app/Http/Requests/Design/DefaultDesignRequest.php @@ -27,9 +27,14 @@ class DefaultDesignRequest extends Request public function rules() { + $user = auth()->user(); + return [ - 'entity' => 'required', - 'design_id' => 'required', + 'entity' => 'bail|required', + 'design_id' => 'bail|required', + 'settings_level' => 'bail|sometimes|in:company,client,group_settings', + 'client_id' => 'bail|required_if:settings_level,client|exists:clients,id,company_id,'.$user->company()->id, + 'group_settings_id' => 'bail|required_if:settings_level,group_settings|exists:group_settings,id,company_id,'.$user->company()->id, ]; } diff --git a/app/Services/Pdf/PdfBuilder.php b/app/Services/Pdf/PdfBuilder.php index 76b88c3a60..8c19e23e2f 100644 --- a/app/Services/Pdf/PdfBuilder.php +++ b/app/Services/Pdf/PdfBuilder.php @@ -1138,6 +1138,11 @@ class PdfBuilder // Some variables don't map 1:1 to table columns. This gives us support for such cases. $aliases = [ '$quote.balance_due' => 'partial', + '$purchase_order.po_number' => 'number', + '$purchase_order.total' => 'amount', + '$purchase_order.due_date' => 'due_date', + '$purchase_order.balance_due' => 'balance_due', + '$credit.valid_until' => 'due_date', ]; try { diff --git a/app/Services/Pdf/PdfMock.php b/app/Services/Pdf/PdfMock.php index 91e3a82dfa..1bfc5f87f7 100644 --- a/app/Services/Pdf/PdfMock.php +++ b/app/Services/Pdf/PdfMock.php @@ -262,6 +262,7 @@ class PdfMock '$client.billing_city' => 'Aufderharchester', '$secondary_font_name' => isset($this->settings?->secondary_font) ? $this->settings->secondary_font : 'Roboto', '$secondary_font_url' => isset($this->settings?->secondary_font) ? \App\Utils\Helpers::resolveFont($this->settings->secondary_font)['url'] : 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', + '$credit.valid_until' => '2024-12-11', '$product.line_total' => '', '$product.tax_amount' => '', '$company.vat_number' => $this->settings->vat_number, @@ -596,6 +597,7 @@ class PdfMock '$invoice.invoice_no_label' => ctrans('texts.invoice_no'), '$contact.first_name_label' => ctrans('texts.first_name'), '$secondary_font_url_label' => ctrans('texts.secondary_font'), + '$credit.valid_until_label' => ctrans('texts.valid_until'), '$contact.signature_label' => ctrans('texts.signature'), '$product.tax_name1_label' => ctrans('texts.tax_name1'), '$product.tax_name2_label' => ctrans('texts.tax_name2'), diff --git a/app/Services/PdfMaker/Design.php b/app/Services/PdfMaker/Design.php index 308ce849d9..9db7fb81b4 100644 --- a/app/Services/PdfMaker/Design.php +++ b/app/Services/PdfMaker/Design.php @@ -383,7 +383,7 @@ class Design extends BaseDesign return !in_array($m, ['$invoice.balance_due', '$invoice.total']); }); } - + foreach ($variables as $variable) { $_variable = explode('.', $variable)[1]; $_customs = ['custom1', 'custom2', 'custom3', 'custom4']; @@ -403,7 +403,7 @@ class Design extends BaseDesign ]]; } } - + return $elements; } diff --git a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php index 7b811a968a..3683b1aef2 100644 --- a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php +++ b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php @@ -283,6 +283,7 @@ trait DesignHelpers '$purchase_order.total' => 'amount', '$purchase_order.due_date' => 'due_date', '$purchase_order.balance_due' => 'balance_due', + '$credit.valid_until' => 'due_date', ]; try { @@ -319,6 +320,11 @@ trait DesignHelpers // Some variables don't map 1:1 to table columns. This gives us support for such cases. $aliases = [ '$quote.balance_due' => 'partial', + '$purchase_order.po_number' => 'number', + '$purchase_order.total' => 'amount', + '$purchase_order.due_date' => 'due_date', + '$purchase_order.balance_due' => 'balance_due', + '$credit.valid_until' => 'due_date', ]; try { diff --git a/app/Services/Template/TemplateService.php b/app/Services/Template/TemplateService.php index 2ba7f55733..8732d6c75d 100644 --- a/app/Services/Template/TemplateService.php +++ b/app/Services/Template/TemplateService.php @@ -789,6 +789,7 @@ class TemplateService 'last_sent_date' => $this->translateDate($quote->last_sent_date, $quote->client->date_format(), $quote->client->locale()), 'next_send_date' => $this->translateDate($quote->next_send_date, $quote->client->date_format(), $quote->client->locale()), 'due_date' => $this->translateDate($quote->due_date, $quote->client->date_format(), $quote->client->locale()), + 'valid_until' => $this->translateDate($quote->due_date, $quote->client->date_format(), $quote->client->locale()), 'terms' => $quote->terms ?: '', 'public_notes' => $quote->public_notes ?: '', 'private_notes' => $quote->private_notes ?: '', @@ -864,6 +865,7 @@ class TemplateService 'last_sent_date' => $this->translateDate($credit->last_sent_date, $credit->client->date_format(), $credit->client->locale()), 'next_send_date' => $this->translateDate($credit->next_send_date, $credit->client->date_format(), $credit->client->locale()), 'due_date' => $this->translateDate($credit->due_date, $credit->client->date_format(), $credit->client->locale()), + 'valid_until' => $this->translateDate($credit->due_date, $credit->client->date_format(), $credit->client->locale()), 'terms' => $credit->terms ?: '', 'public_notes' => $credit->public_notes ?: '', 'private_notes' => $credit->private_notes ?: '', @@ -1495,6 +1497,11 @@ class TemplateService // Some variables don't map 1:1 to table columns. This gives us support for such cases. $aliases = [ '$quote.balance_due' => 'partial', + '$purchase_order.po_number' => 'number', + '$purchase_order.total' => 'amount', + '$purchase_order.due_date' => 'due_date', + '$purchase_order.balance_due' => 'balance_due', + '$credit.valid_until' => 'due_date', ]; try { diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php index 9a2afd90d0..8fd6ecf0de 100644 --- a/app/Utils/HtmlEngine.php +++ b/app/Utils/HtmlEngine.php @@ -394,6 +394,8 @@ class HtmlEngine $data['$credit.total'] = &$data['$credit.total']; $data['$credit.po_number'] = &$data['$invoice.po_number']; $data['$credit.date'] = ['value' => $this->translateDate($this->entity->date, $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.credit_date')]; + $data['$credit.valid_until'] = ['value' => $this->translateDate($this->entity->due_date, $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.valid_until')]; + $data['$balance'] = ['value' => Number::formatMoney($this->getBalance(), $this->client) ?: ' ', 'label' => ctrans('texts.balance')]; $data['$credit.balance'] = ['value' => Number::formatMoney($this->entity_calc->getBalance(), $this->client) ?: ' ', 'label' => ctrans('texts.credit_balance')]; $data['$client.credit_balance'] = &$data['$credit.balance']; diff --git a/composer.lock b/composer.lock index 387fa06c8a..5718c3d3da 100644 --- a/composer.lock +++ b/composer.lock @@ -535,16 +535,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.327.1", + "version": "3.328.0", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "3d52ec587989b136e486f94eff3dd316465aeb42" + "reference": "a99b58e166ae367f2b067937afb04e843e900745" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3d52ec587989b136e486f94eff3dd316465aeb42", - "reference": "3d52ec587989b136e486f94eff3dd316465aeb42", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a99b58e166ae367f2b067937afb04e843e900745", + "reference": "a99b58e166ae367f2b067937afb04e843e900745", "shasum": "" }, "require": { @@ -627,9 +627,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.327.1" + "source": "https://github.com/aws/aws-sdk-php/tree/3.328.0" }, - "time": "2024-11-15T01:53:30+00:00" + "time": "2024-11-15T19:06:57+00:00" }, { "name": "babenkoivan/elastic-adapter", @@ -3886,16 +3886,16 @@ }, { "name": "horstoeko/zugferd", - "version": "v1.0.78", + "version": "v1.0.79", "source": { "type": "git", "url": "https://github.com/horstoeko/zugferd.git", - "reference": "bacbe6707eacfc135254774f2ff164e4091168ea" + "reference": "6e5901e9ba1afb1097ddd315c18f1058af2a2cb5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/horstoeko/zugferd/zipball/bacbe6707eacfc135254774f2ff164e4091168ea", - "reference": "bacbe6707eacfc135254774f2ff164e4091168ea", + "url": "https://api.github.com/repos/horstoeko/zugferd/zipball/6e5901e9ba1afb1097ddd315c18f1058af2a2cb5", + "reference": "6e5901e9ba1afb1097ddd315c18f1058af2a2cb5", "shasum": "" }, "require": { @@ -3955,9 +3955,9 @@ ], "support": { "issues": "https://github.com/horstoeko/zugferd/issues", - "source": "https://github.com/horstoeko/zugferd/tree/v1.0.78" + "source": "https://github.com/horstoeko/zugferd/tree/v1.0.79" }, - "time": "2024-11-11T10:59:22+00:00" + "time": "2024-11-16T06:41:07+00:00" }, { "name": "horstoeko/zugferdvisualizer", @@ -4888,16 +4888,16 @@ }, { "name": "laravel/framework", - "version": "v11.31.0", + "version": "v11.32.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "365090ed2c68244e3141cdb5e247cdf3dfba2c40" + "reference": "bc2aad63f83ee5089be7b21cf29d645ccf31e927" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/365090ed2c68244e3141cdb5e247cdf3dfba2c40", - "reference": "365090ed2c68244e3141cdb5e247cdf3dfba2c40", + "url": "https://api.github.com/repos/laravel/framework/zipball/bc2aad63f83ee5089be7b21cf29d645ccf31e927", + "reference": "bc2aad63f83ee5089be7b21cf29d645ccf31e927", "shasum": "" }, "require": { @@ -5093,7 +5093,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-11-12T15:36:15+00:00" + "time": "2024-11-15T17:04:33+00:00" }, { "name": "laravel/prompts", @@ -7880,16 +7880,16 @@ }, { "name": "nwidart/laravel-modules", - "version": "v11.1.4", + "version": "v11.1.6", "source": { "type": "git", "url": "https://github.com/nWidart/laravel-modules.git", - "reference": "fb1f6bd7b168baaa6212dee678c18fc983d47ed4" + "reference": "bebe5b4676cf22d891c1863e9aa2688f34ddaa9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nWidart/laravel-modules/zipball/fb1f6bd7b168baaa6212dee678c18fc983d47ed4", - "reference": "fb1f6bd7b168baaa6212dee678c18fc983d47ed4", + "url": "https://api.github.com/repos/nWidart/laravel-modules/zipball/bebe5b4676cf22d891c1863e9aa2688f34ddaa9f", + "reference": "bebe5b4676cf22d891c1863e9aa2688f34ddaa9f", "shasum": "" }, "require": { @@ -7953,7 +7953,7 @@ ], "support": { "issues": "https://github.com/nWidart/laravel-modules/issues", - "source": "https://github.com/nWidart/laravel-modules/tree/v11.1.4" + "source": "https://github.com/nWidart/laravel-modules/tree/v11.1.6" }, "funding": [ { @@ -7965,7 +7965,7 @@ "type": "github" } ], - "time": "2024-09-22T20:04:49+00:00" + "time": "2024-11-16T20:27:06+00:00" }, { "name": "nyholm/psr7", diff --git a/tests/Feature/DesignApiTest.php b/tests/Feature/DesignApiTest.php index d5d7a4df46..bfcbaf431b 100644 --- a/tests/Feature/DesignApiTest.php +++ b/tests/Feature/DesignApiTest.php @@ -11,14 +11,20 @@ namespace Tests\Feature; -use App\Factory\DesignFactory; -use App\Models\Design; -use App\Utils\Traits\MakesHash; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Foundation\Testing\DatabaseTransactions; -use Illuminate\Support\Facades\Session; -use Tests\MockAccountData; use Tests\TestCase; +use App\Models\Quote; +use App\Models\Client; +use App\Models\Credit; +use App\Models\Design; +use App\Models\Invoice; +use Tests\MockAccountData; +use App\Factory\DesignFactory; +use App\Utils\Traits\MakesHash; +use App\DataMapper\ClientSettings; +use App\Factory\GroupSettingFactory; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Facades\Session; +use Illuminate\Foundation\Testing\DatabaseTransactions; /** * @@ -40,13 +46,338 @@ class DesignApiTest extends TestCase $this->makeTestData(); - Session::start(); - $this->faker = \Faker\Factory::create(); - Model::reguard(); } + public function testSelectiveDefaultDesignUpdatesInvoice() + { + $settings = ClientSettings::defaults(); + $hashed_design_id = $this->encodePrimaryKey(5); + $settings->invoice_design_id = $hashed_design_id; + + $c = Client::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'settings' => $settings + ]); + + $i = Invoice::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $c->id, + 'design_id' => 5 + ]); + + $this->assertEquals(5, $i->design_id); + $this->assertEquals($hashed_design_id, $c->settings->invoice_design_id); + + $new_design_hash = $this->encodePrimaryKey(7); + + $data = [ + 'entity' => 'invoice', + 'design_id' => $new_design_hash, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/designs/set/default', $data); + + $response->assertStatus(200); + + $new_design_truth_test = Invoice::where('company_id', $this->company->id)->orderBy('id','asc')->where('design_id', 7)->exists(); + + $this->assertTrue($new_design_truth_test); + + ///Test Client Level + + $data = [ + 'entity' => 'invoice', + 'design_id' => $new_design_hash, + 'settings_level' => 'client', + 'client_id' => $c->hashed_id + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/designs/set/default', $data); + + $response->assertStatus(200); + + $i = $i->fresh(); + + $this->assertEquals(7, $i->design_id); + + //////////////////////////////////////////// + + // Group Settings + + $gs = GroupSettingFactory::create($this->company->id, $this->user->id); + $settings = $gs->settings; + $settings->invoice_design_id = $this->encodePrimaryKey(4); + $gs->settings = $settings; + $gs->name = "GS Setter"; + $gs->save(); + + $c2 = Client::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'group_settings_id' => $gs->id, + ]); + + + $this->assertNotNull($c2->group_settings_id); + + $i2 = Invoice::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $c2->id, + 'design_id' => 4 + ]); + + $new_gs_design_hash = $this->encodePrimaryKey(1); + + $data = [ + 'entity' => 'invoice', + 'design_id' => $new_gs_design_hash, + 'settings_level' => 'group_settings', + 'group_settings_id' => $gs->hashed_id + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/designs/set/default', $data); + + $response->assertStatus(200); + + $i2 = $i2->fresh(); + + $this->assertEquals(1, $i2->design_id); + + } + + public function testSelectiveDefaultDesignUpdatesQuote() + { + $settings = ClientSettings::defaults(); + $hashed_design_id = $this->encodePrimaryKey(5); + $settings->quote_design_id = $hashed_design_id; + + $c = Client::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'settings' => $settings + ]); + + $i = \App\Models\Quote::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $c->id, + 'design_id' => 5 + ]); + + $this->assertEquals(5, $i->design_id); + $this->assertEquals($hashed_design_id, $c->settings->quote_design_id); + + $new_design_hash = $this->encodePrimaryKey(7); + + $data = [ + 'entity' => 'quote', + 'design_id' => $new_design_hash, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/designs/set/default', $data); + + $response->assertStatus(200); + + $new_design_truth_test = Quote::where('company_id', $this->company->id)->orderBy('id','asc')->where('design_id', 7)->exists(); + + $this->assertTrue($new_design_truth_test); + + ///Test Client Level + + $data = [ + 'entity' => 'quote', + 'design_id' => $new_design_hash, + 'settings_level' => 'client', + 'client_id' => $c->hashed_id + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/designs/set/default', $data); + + $response->assertStatus(200); + + $i = $i->fresh(); + + $this->assertEquals(7, $i->design_id); + + //////////////////////////////////////////// + + // Group Settings + + $gs = GroupSettingFactory::create($this->company->id, $this->user->id); + $settings = $gs->settings; + $settings->quote_design_id = $this->encodePrimaryKey(4); + $gs->settings = $settings; + $gs->name = "GS Setter"; + $gs->save(); + + $c2 = Client::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'group_settings_id' => $gs->id, + ]); + + + $this->assertNotNull($c2->group_settings_id); + + $i2 = Quote::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $c2->id, + 'design_id' => 4 + ]); + + $new_gs_design_hash = $this->encodePrimaryKey(1); + + $data = [ + 'entity' => 'quote', + 'design_id' => $new_gs_design_hash, + 'settings_level' => 'group_settings', + 'group_settings_id' => $gs->hashed_id + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/designs/set/default', $data); + + $response->assertStatus(200); + + $i2 = $i2->fresh(); + + $this->assertEquals(1, $i2->design_id); + + } + + public function testSelectiveDefaultDesignUpdatesCredit() + { + $settings = ClientSettings::defaults(); + $hashed_design_id = $this->encodePrimaryKey(5); + $settings->credit_design_id = $hashed_design_id; + + $c = Client::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'settings' => $settings + ]); + + $i = Credit::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $c->id, + 'design_id' => 5 + ]); + + $this->assertEquals(5, $i->design_id); + $this->assertEquals($hashed_design_id, $c->settings->credit_design_id); + + $new_design_hash = $this->encodePrimaryKey(7); + + $data = [ + 'entity' => 'credit', + 'design_id' => $new_design_hash, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/designs/set/default', $data); + + $response->assertStatus(200); + + $new_design_truth_test = Credit::where('company_id', $this->company->id)->orderBy('id','asc')->where('design_id', 7)->exists(); + + $this->assertTrue($new_design_truth_test); + + ///Test Client Level + + $data = [ + 'entity' => 'credit', + 'design_id' => $new_design_hash, + 'settings_level' => 'client', + 'client_id' => $c->hashed_id + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/designs/set/default', $data); + + $response->assertStatus(200); + + $i = $i->fresh(); + + $this->assertEquals(7, $i->design_id); + + //////////////////////////////////////////// + + // Group Settings + + $gs = GroupSettingFactory::create($this->company->id, $this->user->id); + $settings = $gs->settings; + $settings->credit_design_id = $this->encodePrimaryKey(4); + $gs->settings = $settings; + $gs->name = "GS Setter"; + $gs->save(); + + $c2 = Client::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'group_settings_id' => $gs->id, + ]); + + + $this->assertNotNull($c2->group_settings_id); + + $i2 = Credit::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $c2->id, + 'design_id' => 4 + ]); + + $new_gs_design_hash = $this->encodePrimaryKey(1); + + $data = [ + 'entity' => 'credit', + 'design_id' => $new_gs_design_hash, + 'settings_level' => 'group_settings', + 'group_settings_id' => $gs->hashed_id + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/designs/set/default', $data); + + $response->assertStatus(200); + + $i2 = $i2->fresh(); + + $this->assertEquals(1, $i2->design_id); + + } + + public function testFindInSetQueries() {