From ac19a4bb122a69d95a192597bcfc19313e4cb6d0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 11 Sep 2019 15:32:47 +1000 Subject: [PATCH] Working on cascading settings --- app/Http/Controllers/Auth/LoginController.php | 10 +- app/Http/Controllers/BaseController.php | 6 +- .../ClientPortal/InvoiceController.php | 2 +- app/Http/Middleware/ApiSecretCheck.php | 5 +- app/Models/Client.php | 26 +++-- app/Models/CompanyGateway.php | 2 +- app/Models/GroupSetting.php | 11 +- app/Models/Invoice.php | 4 +- app/Utils/Traits/CompanyGatewaySettings.php | 47 -------- .../2014_10_13_000000_create_users_table.php | 2 - database/seeds/RandomDataSeeder.php | 1 - tests/Feature/ClientTest.php | 2 +- tests/Feature/UserTest.php | 4 +- tests/MockAccountData.php | 13 +++ tests/Unit/GroupSettingsTest.php | 107 ++++++++++++++++++ 15 files changed, 170 insertions(+), 72 deletions(-) delete mode 100644 app/Utils/Traits/CompanyGatewaySettings.php create mode 100644 tests/Unit/GroupSettingsTest.php diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index c498825d296c..f38fc1533092 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -93,7 +93,10 @@ class LoginController extends BaseController if ($this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); - return response()->json(['message' => 'Too many login attempts, you are being throttled'], 401)->header('X-API-VERSION', config('ninja.api_version')); + return response() + ->json(['message' => 'Too many login attempts, you are being throttled'], 401) + ->header('X-App-Version', config('ninja.app_version')) + ->header('X-Api-Version', config('ninja.api_version')); } if ($this->attemptLogin($request)) { @@ -108,7 +111,10 @@ class LoginController extends BaseController $this->incrementLoginAttempts($request); - return response()->json(['message' => ctrans('texts.invalid_credentials')], 401)->header('X-API-VERSION', config('ninja.api_version')); + return response() + ->json(['message' => ctrans('texts.invalid_credentials')], 401) + ->header('X-App-Version', config('ninja.app_version')) + ->header('X-Api-Version', config('ninja.api_version')); } } diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index 775b1aa057b5..eaa53d22b936 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -110,7 +110,8 @@ class BaseController extends Controller { return response()->json(['message' => '404 | Nothing to see here!'], 404) - ->header('X-API-VERSION', config('ninja.api_version')); + ->header('X-Api-Version', config('ninja.api_version')) + ->header('X-App-Version', config('ninja.app_version')); } @@ -239,7 +240,8 @@ class BaseController extends Controller //'Access-Control-Allow-Headers' => 'Origin, Content-Type, Accept, Authorization, X-Requested-With', //'Access-Control-Allow-Credentials' => 'true', //'X-Total-Count' => $count, - 'X-API-VERSION' => config('ninja.api_version'), + 'X-Api-Version' => config('ninja.api_version'), + 'X-App-Version' => config('ninja.app_version'), //'X-Rate-Limit-Limit' - The number of allowed requests in the current period //'X-Rate-Limit-Remaining' - The number of remaining requests in the current period //'X-Rate-Limit-Reset' - The number of seconds left in the current period, diff --git a/app/Http/Controllers/ClientPortal/InvoiceController.php b/app/Http/Controllers/ClientPortal/InvoiceController.php index 7860925c8f1c..537503ff0e58 100644 --- a/app/Http/Controllers/ClientPortal/InvoiceController.php +++ b/app/Http/Controllers/ClientPortal/InvoiceController.php @@ -132,7 +132,7 @@ class InvoiceController extends Controller }); - $formatted_total = Number::formatMoney($total, auth()->user()->client->currency, auth()->user()->client->country, auth()->user()->client->getMergedSettings()); + $formatted_total = Number::formatMoney($total, auth()->user()->client); $payment_methods = auth()->user()->client->getPaymentMethods($total); diff --git a/app/Http/Middleware/ApiSecretCheck.php b/app/Http/Middleware/ApiSecretCheck.php index 9f47e251756f..38e195981e93 100644 --- a/app/Http/Middleware/ApiSecretCheck.php +++ b/app/Http/Middleware/ApiSecretCheck.php @@ -32,7 +32,10 @@ class ApiSecretCheck $error['error'] = ['message' => 'Invalid secret']; - return response()->json(json_encode($error, JSON_PRETTY_PRINT) ,403)->header('X-API-VERSION', config('ninja.api_version')); + 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')); } diff --git a/app/Models/Client.php b/app/Models/Client.php index f48e53e560b4..e8439359308c 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -38,7 +38,6 @@ class Client extends BaseModel use SoftDeletes; use Filterable; use GeneratesCounter; - use CompanyGatewaySettings; protected $presenter = 'App\Models\Presenters\ClientPresenter'; @@ -128,27 +127,36 @@ class Client extends BaseModel public function timezone() { - return Timezone::find($this->getMergedSettings()->timezone_id); + return Timezone::find($this->getSetting('timezone_id')); } public function date_format() { - return $this->getMergedSettings()->date_format; + return $this->getSetting('date_format'); } public function datetime_format() { - return $this->getMergedSettings()->datetime_format; + return $this->getSetting('datetime_format'); } public function currency() { return $this->belongsTo(Currency::class); - //return Currency::find($this->getMergedSettings()->currency_id); } public function getMergedSettings() { + + if($this->group_settings !== null) + { + + $group_settings = ClientSettings::buildClientSettings(new ClientSettings($this->group_settings()), new ClientSettings($this->settings)); + + return ClientSettings::buildClientSettings(new CompanySettings($this->company->settings), $group_settings); + + } + return ClientSettings::buildClientSettings(new CompanySettings($this->company->settings), new ClientSettings($this->settings)); } @@ -170,7 +178,7 @@ class Client extends BaseModel return $this->settings->{$setting}; //check group level (if a group is assigned) - if($this->group_settings && isset($this->group_settings->{$setting}) && property_exists($this->group_settings, $setting)) + if($this->group_settings && isset($this->group_settings->settings->{$setting}) && property_exists($this->group_settings->settings, $setting)) return $this->group_settings->{$setting}; //check company level @@ -206,11 +214,11 @@ class Client extends BaseModel */ public function getPaymentMethods($amount) :array { - $settings = $this->getMergedSettings(); + $payment_gateways = $this->getSetting('payment_gateways'); /* If we have a custom gateway list pass this back first */ - if($settings->payment_gateways) - $gateways = $this->company->company_gateways->whereIn('id', $settings->payment_gateways); + if($settings) + $gateways = $this->company->company_gateways->whereIn('id', $payment_gateways); else $gateways = $this->company->company_gateways; diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index f02dd36c8fb4..4f20484f9d80 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -151,7 +151,7 @@ class CompanyGateway extends BaseModel $fee = $this->calcGatewayFee($amount); if($fee > 0 ){ - $fee = Number::formatMoney(round($fee, 2), $client->currency, $client->country(), $client->getMergedSettings()); + $fee = Number::formatMoney(round($fee, 2), $client); $label = ' - ' . $fee . ' ' . ctrans('texts.fee'); } diff --git a/app/Models/GroupSetting.php b/app/Models/GroupSetting.php index 0f3e7bdc97f2..3c86df78a215 100644 --- a/app/Models/GroupSetting.php +++ b/app/Models/GroupSetting.php @@ -13,14 +13,18 @@ namespace App\Models; use App\DataMapper\ClientSettings; use App\DataMapper\CompanySettings; +use App\Models\Client; use App\Models\Company; use App\Models\User; use App\Utils\Traits\MakesHash; use Hashids\Hashids; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Model; -class GroupSetting extends BaseModel +class GroupSetting extends Model { + public $timestamps = false; + protected $casts = [ 'settings' => 'object' ]; @@ -35,5 +39,10 @@ class GroupSetting extends BaseModel return $this->belongsTo(User::class); } + public function clients() + { + return $this->hasMany(Client::class, 'id', 'group_settings_id'); + } + } \ No newline at end of file diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index b5fda91ac916..6d067217c7e8 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -169,7 +169,7 @@ class Invoice extends BaseModel */ public function isLocked() : bool { - return $this->client->getMergedSettings()->lock_sent_invoices; + return $this->client->getSetting('lock_sent_invoices'); } /** @@ -252,7 +252,7 @@ class Invoice extends BaseModel public function calc() { - $invoice_calc = new InvoiceCalc($this, $this->client->getMergedSettings()); + $invoice_calc = new InvoiceCalc($this, $this->settings); return $invoice_calc->build(); diff --git a/app/Utils/Traits/CompanyGatewaySettings.php b/app/Utils/Traits/CompanyGatewaySettings.php deleted file mode 100644 index 964c9b8254ef..000000000000 --- a/app/Utils/Traits/CompanyGatewaySettings.php +++ /dev/null @@ -1,47 +0,0 @@ -getMergedSettings(); - - /* Group Level */ - if(isset($settings->groups->company_gateways)){ - $gateways = $this->company->company_gateways->whereIn('id', $settings->group_selectors->{$settings->group->company_gateways}); - } - /* Client Level - Company Level*/ - else if(isset($settings->company_gateways)) { - $gateways = $this->company->company_gateways->whereIn('id', $settings->company_gateways); - } - /* DB raw*/ - else - return $this->company->company_gateways; - - } - -} \ 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 6aba055557e7..abd6a957a60b 100644 --- a/database/migrations/2014_10_13_000000_create_users_table.php +++ b/database/migrations/2014_10_13_000000_create_users_table.php @@ -920,8 +920,6 @@ class CreateUsersTable extends Migration $table->unsignedInteger('user_id')->nullable(); $table->string('name'); $table->text('settings'); - $table->boolean('is_default')->default(false); - $table->timestamps(6); $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); }); diff --git a/database/seeds/RandomDataSeeder.php b/database/seeds/RandomDataSeeder.php index 602c7722bd8e..835c07d9cdd6 100644 --- a/database/seeds/RandomDataSeeder.php +++ b/database/seeds/RandomDataSeeder.php @@ -123,7 +123,6 @@ class RandomDataSeeder extends Seeder GroupSetting::create([ 'company_id' => $company->id, 'user_id' => $user->id, - 'is_default' =>true, 'settings' => ClientSettings::buildClientSettings(new CompanySettings(CompanySettings::defaults()), new ClientSettings(ClientSettings::defaults())), 'name' => 'Default Client Settings', ]); diff --git a/tests/Feature/ClientTest.php b/tests/Feature/ClientTest.php index 7050092be0da..a1f617f4f307 100644 --- a/tests/Feature/ClientTest.php +++ b/tests/Feature/ClientTest.php @@ -245,7 +245,7 @@ class ClientTest extends TestCase $this->assertNotNull($client); /* Make sure we have a valid settings object*/ - $this->assertEquals($client->getMergedSettings()->timezone_id, 15); + $this->assertEquals($client->getSetting('timezone_id'), 15); /* Make sure we are harvesting valid data */ $this->assertEquals($client->timezone()->name, 'US/Eastern'); diff --git a/tests/Feature/UserTest.php b/tests/Feature/UserTest.php index 3893c75c768c..db69e58a2028 100644 --- a/tests/Feature/UserTest.php +++ b/tests/Feature/UserTest.php @@ -45,8 +45,8 @@ class UserTest extends TestCase $data = [ 'first_name' => $this->faker->firstName, 'last_name' => $this->faker->lastName, - 'name' => $this->faker->company, - 'email' => $this->faker->unique()->safeEmail, + 'name' => $this->faker->company, + 'email' => $this->faker->unique()->safeEmail, 'password' => 'ALongAndBrilliantPassword123', '_token' => csrf_token(), 'privacy_policy' => 1, diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index fac0dcafcbdf..2debab47ac03 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -11,6 +11,7 @@ namespace Tests; +use App\DataMapper\ClientSettings; use App\Factory\ClientFactory; use App\Factory\InvoiceFactory; use App\Factory\InvoiceItemFactory; @@ -19,6 +20,7 @@ use App\Helpers\Invoice\InvoiceCalc; use App\Jobs\Company\UpdateCompanyLedgerWithInvoice; use App\Models\Client; use App\Models\Credit; +use App\Models\GroupSetting; use App\Models\Invoice; use App\Models\Quote; use App\Models\RecurringInvoice; @@ -66,6 +68,17 @@ trait MockAccountData $this->client = ClientFactory::create($this->company->id, $this->user->id); $this->client->save(); + $gs = new GroupSetting; + $gs->name = 'Test'; + $gs->company_id = $this->client->company_id; + $gs->settings = new ClientSettings(ClientSettings::defaults()); + $gs->save(); + + $this->client->group_settings_id = $gs->id; + $this->client->save(); + + + $this->invoice = InvoiceFactory::create($this->company->id,$this->user->id);//stub the company and user_id $this->invoice->client_id = $this->client->id; diff --git a/tests/Unit/GroupSettingsTest.php b/tests/Unit/GroupSettingsTest.php new file mode 100644 index 000000000000..ec5653aac726 --- /dev/null +++ b/tests/Unit/GroupSettingsTest.php @@ -0,0 +1,107 @@ +makeTestData(); + + $this->company_settings = CompanySettings::defaults(); + $this->client->settings = new ClientSettings(ClientSettings::defaults()); + + + } + + + public function testCompanyDefaults() + { + + $this->company_settings->timezone_id = 'fluffy'; + $this->client->company->settings = $this->company_settings; + + $this->assertEquals($this->client->company->settings->timezone_id, 'fluffy'); + $this->assertEquals($this->client->getSetting('timezone_id'), 'fluffy'); + $this->assertEquals($this->client->getMergedSettings()->timezone_id, 'fluffy'); + + } + + + public function testGroupDefaults() + { + + $cs = $this->client->company->settings; + $cs->timezone_id = NULL; + + $this->client->company->settings = $cs; + + $gs = $this->client->group_settings->settings; + $gs->timezone_id = 'SPOCK'; + + $this->client->group_settings->settings = $gs; + + $cls = $this->client->settings; + $cls->timezone_id = NULL; + $cls->date_format = 'sharleen'; + + $this->client->settings = $cls; + + $this->client->group_settings->save(); + $this->client->company->save(); + $this->client->save(); + + $this->client->fresh(); + +// \Log::error(print_r($this->client,1)); + \Log::error(print_r($this->client->settings,1)); + \Log::error(print_r($this->client->settings->timezone_id,1)); + \Log::error(print_r($this->client->settings->date_format,1)); + \Log::error(print_r($this->client->group_settings->settings->timezone_id,1)); + \Log::error(print_r($this->client->group_settings->settings,1)); + \Log::error(print_r($this->client->company->settings->timezone_id,1)); + + $this->assertEquals($this->client->group_settings->settings->timezone_id, 'SPOCK'); + $this->assertEquals($this->client->getSetting('timezone_id'), 'SPOCK'); + $this->assertEquals($this->client->getMergedSettings()->timezone_id, 'SPOCK'); + + } + + + + public function testClientDefaults() + { + + $this->company_settings->timezone_id = NULL; + $this->client->group_settings->settings->timezone_id = NULL; + $this->client->settings->timezone_id = 'SCOTTY'; + $this->client->company->settings = $this->company_settings; + + $this->client->save(); + $this->client->company->save(); + $this->client->group_settings->save(); + + $this->assertEquals($this->client->settings->timezone_id, 'SCOTTY'); + $this->assertEquals($this->client->getSetting('timezone_id'), 'SCOTTY'); + $this->assertEquals($this->client->getMergedSettings()->timezone_id, 'SCOTTY'); + + } + +} \ No newline at end of file