From 2012e0dd5e64f2cddc75f9a2b60ee698b8aec016 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 11 Sep 2023 11:05:05 +1000 Subject: [PATCH] Add classifications for clients/vendors and company --- app/DataMapper/CompanySettings.php | 3 + app/Factory/ClientFactory.php | 3 +- app/Factory/VendorFactory.php | 1 + .../Requests/Client/StoreClientRequest.php | 3 +- .../Requests/Client/UpdateClientRequest.php | 1 + .../Requests/Vendor/StoreVendorRequest.php | 1 + .../Requests/Vendor/UpdateVendorRequest.php | 1 + app/Models/Client.php | 1 + app/Models/Vendor.php | 1 + app/Transformers/ClientTransformer.php | 1 + app/Transformers/VendorTransformer.php | 1 + ...add_client_and_company_classifications.php | 31 +++ lang/en/texts.php | 6 + tests/Feature/ClassificationTest.php | 220 ++++++++++++++++++ tests/MockUnitData.php | 20 +- 15 files changed, 286 insertions(+), 8 deletions(-) create mode 100644 database/migrations/2023_09_11_003230_add_client_and_company_classifications.php create mode 100644 tests/Feature/ClassificationTest.php diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index 99638a0fa981..e4e8ff3085c5 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -481,8 +481,11 @@ class CompanySettings extends BaseSettings public $enable_e_invoice = false; + public $classification = ''; // individual, company, partnership, trust, charity, government, other + public static $casts = [ 'enable_e_invoice' => 'bool', + 'classification' => 'string', 'default_expense_payment_type_id' => 'string', 'e_invoice_type' => 'string', 'mailgun_endpoint' => 'string', diff --git a/app/Factory/ClientFactory.php b/app/Factory/ClientFactory.php index 37d23311add5..fbb6f36ab528 100644 --- a/app/Factory/ClientFactory.php +++ b/app/Factory/ClientFactory.php @@ -32,7 +32,8 @@ class ClientFactory $client->is_deleted = 0; $client->client_hash = Str::random(40); $client->settings = ClientSettings::defaults(); - + $client->classification = ''; + return $client; } } diff --git a/app/Factory/VendorFactory.php b/app/Factory/VendorFactory.php index 021d91053c6e..04c009267b21 100644 --- a/app/Factory/VendorFactory.php +++ b/app/Factory/VendorFactory.php @@ -28,6 +28,7 @@ class VendorFactory $vendor->country_id = 4; $vendor->is_deleted = 0; $vendor->vendor_hash = Str::random(40); + $vendor->classification = ''; return $vendor; } diff --git a/app/Http/Requests/Client/StoreClientRequest.php b/app/Http/Requests/Client/StoreClientRequest.php index c06305dd8e77..3a1d3841bfc4 100644 --- a/app/Http/Requests/Client/StoreClientRequest.php +++ b/app/Http/Requests/Client/StoreClientRequest.php @@ -93,7 +93,8 @@ class StoreClientRequest extends Request $rules['number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)]; $rules['id_number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)]; - + $rules['classification'] = 'bail|sometimes|nullable|in:individual,company,partnership,trust,charity,government,other'; + return $rules; } diff --git a/app/Http/Requests/Client/UpdateClientRequest.php b/app/Http/Requests/Client/UpdateClientRequest.php index 0344d7aaf205..0c2f3628874f 100644 --- a/app/Http/Requests/Client/UpdateClientRequest.php +++ b/app/Http/Requests/Client/UpdateClientRequest.php @@ -60,6 +60,7 @@ class UpdateClientRequest extends Request $rules['size_id'] = 'integer|nullable'; $rules['country_id'] = 'integer|nullable'; $rules['shipping_country_id'] = 'integer|nullable'; + $rules['classification'] = 'bail|sometimes|nullable|in:individual,company,partnership,trust,charity,government,other'; if ($this->id_number) { $rules['id_number'] = Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id); diff --git a/app/Http/Requests/Vendor/StoreVendorRequest.php b/app/Http/Requests/Vendor/StoreVendorRequest.php index 2de5edeca00c..3ce8ba472198 100644 --- a/app/Http/Requests/Vendor/StoreVendorRequest.php +++ b/app/Http/Requests/Vendor/StoreVendorRequest.php @@ -60,6 +60,7 @@ class StoreVendorRequest extends Request } $rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id'; + $rules['classification'] = 'bail|sometimes|nullable|in:individual,company,partnership,trust,charity,government,other'; return $rules; } diff --git a/app/Http/Requests/Vendor/UpdateVendorRequest.php b/app/Http/Requests/Vendor/UpdateVendorRequest.php index 867b4541c0bf..b50e8cf79229 100644 --- a/app/Http/Requests/Vendor/UpdateVendorRequest.php +++ b/app/Http/Requests/Vendor/UpdateVendorRequest.php @@ -61,6 +61,7 @@ class UpdateVendorRequest extends Request } $rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id'; + $rules['classification'] = 'bail|sometimes|nullable|in:individual,company,partnership,trust,charity,government,other'; return $rules; } diff --git a/app/Models/Client.php b/app/Models/Client.php index 2087a27186da..5abb007ad357 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -169,6 +169,7 @@ class Client extends BaseModel implements HasLocalePreference 'routing_id', 'is_tax_exempt', 'has_valid_vat_number', + 'classification', ]; protected $with = [ diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index 25ebbc4d9e29..243a38691370 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -113,6 +113,7 @@ class Vendor extends BaseModel 'custom_value4', 'number', 'language_id', + 'classification', ]; protected $casts = [ diff --git a/app/Transformers/ClientTransformer.php b/app/Transformers/ClientTransformer.php index f34b805ff581..711c9cfec5ba 100644 --- a/app/Transformers/ClientTransformer.php +++ b/app/Transformers/ClientTransformer.php @@ -151,6 +151,7 @@ class ClientTransformer extends EntityTransformer 'is_tax_exempt' => (bool) $client->is_tax_exempt, 'routing_id' => (string) $client->routing_id, 'tax_info' => $client->tax_data ?: new \stdClass, + 'classification' => $client->classification ?: '', ]; } } diff --git a/app/Transformers/VendorTransformer.php b/app/Transformers/VendorTransformer.php index 051e8fb2f497..29aeafa703cd 100644 --- a/app/Transformers/VendorTransformer.php +++ b/app/Transformers/VendorTransformer.php @@ -104,6 +104,7 @@ class VendorTransformer extends EntityTransformer 'created_at' => (int) $vendor->created_at, 'number' => (string) $vendor->number ?: '', 'language_id' => (string) $vendor->language_id ?: '', + 'classification' => (string) $vendor->classification ?: '', ]; } } diff --git a/database/migrations/2023_09_11_003230_add_client_and_company_classifications.php b/database/migrations/2023_09_11_003230_add_client_and_company_classifications.php new file mode 100644 index 000000000000..ba41f214219f --- /dev/null +++ b/database/migrations/2023_09_11_003230_add_client_and_company_classifications.php @@ -0,0 +1,31 @@ +string('classification')->nullable(); + }); + + Schema::table('vendors', function (Blueprint $table) { + $table->string('classification')->nullable(); + }); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // + } +}; diff --git a/lang/en/texts.php b/lang/en/texts.php index 8be95187c7be..c17129c75120 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -5158,6 +5158,12 @@ $LANG = array( 'click_or_drop_files_here' => 'Click or drop files here', 'set_public' => 'Set public', 'set_private' => 'Set private', + 'individual' => 'Individual', + 'business' => 'Business', + 'partnership' => 'partnership', + 'trust' => 'Trust', + 'charity' => 'Charity', + 'government' => 'Government', ); return $LANG; diff --git a/tests/Feature/ClassificationTest.php b/tests/Feature/ClassificationTest.php new file mode 100644 index 000000000000..fe9df9600756 --- /dev/null +++ b/tests/Feature/ClassificationTest.php @@ -0,0 +1,220 @@ +faker = \Faker\Factory::create(); + + $this->makeTestData(); + + + } + + public function testClientClassification() + { + $data = [ + 'name' => 'Personal Company', + 'classification' => 'individual' + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/clients', $data); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals('individual', $arr['data']['classification']); + } + + public function testValidationClassification() + { + $data = [ + 'name' => 'Personal Company', + 'classification' => 'this_is_not_validated' + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/clients', $data); + + $response->assertStatus(422); + + } + + public function testValidation2Classification() + { + $this->client->classification = 'company'; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->putJson('/api/v1/clients/'.$this->client->hashed_id, $this->client->toArray()); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals('company', $arr['data']['classification']); + } + + public function testValidation3Classification() + { + $this->client->classification = 'this_is_not_validated'; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->putJson('/api/v1/clients/'.$this->client->hashed_id, $this->client->toArray()); + + $response->assertStatus(422); + + } + + public function testVendorClassification() + { + $data = [ + 'name' => 'Personal Company', + 'classification' => 'individual' + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/vendors', $data); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals('individual', $arr['data']['classification']); + } + + public function testVendorValidationClassification() + { + $data = [ + 'name' => 'Personal Company', + 'classification' => 'this_is_not_validated' + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson('/api/v1/vendors', $data); + + $response->assertStatus(422); + + } + + public function testVendorValidation2Classification() + { + $this->vendor->classification = 'company'; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->putJson('/api/v1/vendors/'.$this->vendor->hashed_id, $this->vendor->toArray()); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals('company', $arr['data']['classification']); + } + + public function testVendorValidation3Classification() + { + $this->vendor->classification = 'this_is_not_validated'; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->putJson('/api/v1/vendors/'.$this->vendor->hashed_id, $this->vendor->toArray()); + + $response->assertStatus(422); + + } + + public function testCompanyClassification() + { + $settings = $this->company->settings; + $settings->classification = 'company'; + + $this->company->settings = $settings; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->putJson('/api/v1/companies/'.$this->company->hashed_id, $this->company->toArray()); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals('company', $arr['data']['settings']['classification']); + } + + public function testCompanyValidationClassification() + { + $settings = $this->company->settings; + $settings->classification = 545454; + + $this->company->settings = $settings; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->putJson('/api/v1/companies/'.$this->company->hashed_id, $this->company->toArray()); + + $response->assertStatus(422); + + } + + public function testCompanyValidation2Classification() + { + $settings = $this->company->settings; + $settings->classification = null; + + $this->company->settings = $settings; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->putJson('/api/v1/companies/'.$this->company->hashed_id, $this->company->toArray()); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals('', $arr['data']['settings']['classification']); + } +} \ No newline at end of file diff --git a/tests/MockUnitData.php b/tests/MockUnitData.php index 4ca402d23a6c..fcf7c3e1841f 100644 --- a/tests/MockUnitData.php +++ b/tests/MockUnitData.php @@ -11,15 +11,16 @@ namespace Tests; +use App\Models\User; +use App\Models\Client; +use App\Models\Vendor; +use App\Models\Account; +use App\Models\Company; +use App\Models\CompanyToken; +use App\Models\ClientContact; use App\DataMapper\CompanySettings; use App\DataMapper\DefaultSettings; use App\Factory\InvoiceItemFactory; -use App\Models\Account; -use App\Models\Client; -use App\Models\ClientContact; -use App\Models\Company; -use App\Models\CompanyToken; -use App\Models\User; /** * Class MockUnitData. @@ -34,6 +35,8 @@ trait MockUnitData public $client; + public $vendor; + public $faker; public $primary_contact; @@ -92,6 +95,11 @@ trait MockUnitData 'company_id' => $this->company->id, ]); + $this->vendor = Vendor::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + ]); + $this->primary_contact = ClientContact::factory()->create([ 'user_id' => $this->user->id, 'client_id' => $this->client->id,