mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-31 10:14:36 -04:00
Add classifications for clients/vendors and company
This commit is contained in:
parent
3650d2527f
commit
2012e0dd5e
@ -481,8 +481,11 @@ class CompanySettings extends BaseSettings
|
|||||||
|
|
||||||
public $enable_e_invoice = false;
|
public $enable_e_invoice = false;
|
||||||
|
|
||||||
|
public $classification = ''; // individual, company, partnership, trust, charity, government, other
|
||||||
|
|
||||||
public static $casts = [
|
public static $casts = [
|
||||||
'enable_e_invoice' => 'bool',
|
'enable_e_invoice' => 'bool',
|
||||||
|
'classification' => 'string',
|
||||||
'default_expense_payment_type_id' => 'string',
|
'default_expense_payment_type_id' => 'string',
|
||||||
'e_invoice_type' => 'string',
|
'e_invoice_type' => 'string',
|
||||||
'mailgun_endpoint' => 'string',
|
'mailgun_endpoint' => 'string',
|
||||||
|
@ -32,7 +32,8 @@ class ClientFactory
|
|||||||
$client->is_deleted = 0;
|
$client->is_deleted = 0;
|
||||||
$client->client_hash = Str::random(40);
|
$client->client_hash = Str::random(40);
|
||||||
$client->settings = ClientSettings::defaults();
|
$client->settings = ClientSettings::defaults();
|
||||||
|
$client->classification = '';
|
||||||
|
|
||||||
return $client;
|
return $client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ class VendorFactory
|
|||||||
$vendor->country_id = 4;
|
$vendor->country_id = 4;
|
||||||
$vendor->is_deleted = 0;
|
$vendor->is_deleted = 0;
|
||||||
$vendor->vendor_hash = Str::random(40);
|
$vendor->vendor_hash = Str::random(40);
|
||||||
|
$vendor->classification = '';
|
||||||
|
|
||||||
return $vendor;
|
return $vendor;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,8 @@ class StoreClientRequest extends Request
|
|||||||
|
|
||||||
$rules['number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)];
|
$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['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;
|
return $rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ class UpdateClientRequest extends Request
|
|||||||
$rules['size_id'] = 'integer|nullable';
|
$rules['size_id'] = 'integer|nullable';
|
||||||
$rules['country_id'] = 'integer|nullable';
|
$rules['country_id'] = 'integer|nullable';
|
||||||
$rules['shipping_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) {
|
if ($this->id_number) {
|
||||||
$rules['id_number'] = Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id);
|
$rules['id_number'] = Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id);
|
||||||
|
@ -60,6 +60,7 @@ class StoreVendorRequest extends Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
$rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id';
|
$rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id';
|
||||||
|
$rules['classification'] = 'bail|sometimes|nullable|in:individual,company,partnership,trust,charity,government,other';
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ class UpdateVendorRequest extends Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
$rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id';
|
$rules['language_id'] = 'bail|nullable|sometimes|exists:languages,id';
|
||||||
|
$rules['classification'] = 'bail|sometimes|nullable|in:individual,company,partnership,trust,charity,government,other';
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
}
|
}
|
||||||
|
@ -169,6 +169,7 @@ class Client extends BaseModel implements HasLocalePreference
|
|||||||
'routing_id',
|
'routing_id',
|
||||||
'is_tax_exempt',
|
'is_tax_exempt',
|
||||||
'has_valid_vat_number',
|
'has_valid_vat_number',
|
||||||
|
'classification',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $with = [
|
protected $with = [
|
||||||
|
@ -113,6 +113,7 @@ class Vendor extends BaseModel
|
|||||||
'custom_value4',
|
'custom_value4',
|
||||||
'number',
|
'number',
|
||||||
'language_id',
|
'language_id',
|
||||||
|
'classification',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
@ -151,6 +151,7 @@ class ClientTransformer extends EntityTransformer
|
|||||||
'is_tax_exempt' => (bool) $client->is_tax_exempt,
|
'is_tax_exempt' => (bool) $client->is_tax_exempt,
|
||||||
'routing_id' => (string) $client->routing_id,
|
'routing_id' => (string) $client->routing_id,
|
||||||
'tax_info' => $client->tax_data ?: new \stdClass,
|
'tax_info' => $client->tax_data ?: new \stdClass,
|
||||||
|
'classification' => $client->classification ?: '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,7 @@ class VendorTransformer extends EntityTransformer
|
|||||||
'created_at' => (int) $vendor->created_at,
|
'created_at' => (int) $vendor->created_at,
|
||||||
'number' => (string) $vendor->number ?: '',
|
'number' => (string) $vendor->number ?: '',
|
||||||
'language_id' => (string) $vendor->language_id ?: '',
|
'language_id' => (string) $vendor->language_id ?: '',
|
||||||
|
'classification' => (string) $vendor->classification ?: '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('clients', function (Blueprint $table) {
|
||||||
|
$table->string('classification')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('vendors', function (Blueprint $table) {
|
||||||
|
$table->string('classification')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
};
|
@ -5158,6 +5158,12 @@ $LANG = array(
|
|||||||
'click_or_drop_files_here' => 'Click or drop files here',
|
'click_or_drop_files_here' => 'Click or drop files here',
|
||||||
'set_public' => 'Set public',
|
'set_public' => 'Set public',
|
||||||
'set_private' => 'Set private',
|
'set_private' => 'Set private',
|
||||||
|
'individual' => 'Individual',
|
||||||
|
'business' => 'Business',
|
||||||
|
'partnership' => 'partnership',
|
||||||
|
'trust' => 'Trust',
|
||||||
|
'charity' => 'Charity',
|
||||||
|
'government' => 'Government',
|
||||||
);
|
);
|
||||||
|
|
||||||
return $LANG;
|
return $LANG;
|
||||||
|
220
tests/Feature/ClassificationTest.php
Normal file
220
tests/Feature/ClassificationTest.php
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use Tests\TestCase;
|
||||||
|
use Tests\MockUnitData;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
class ClassificationTest extends TestCase
|
||||||
|
{
|
||||||
|
use MakesHash;
|
||||||
|
use DatabaseTransactions;
|
||||||
|
use MockUnitData;
|
||||||
|
|
||||||
|
protected function setUp() :void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->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']);
|
||||||
|
}
|
||||||
|
}
|
@ -11,15 +11,16 @@
|
|||||||
|
|
||||||
namespace Tests;
|
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\CompanySettings;
|
||||||
use App\DataMapper\DefaultSettings;
|
use App\DataMapper\DefaultSettings;
|
||||||
use App\Factory\InvoiceItemFactory;
|
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.
|
* Class MockUnitData.
|
||||||
@ -34,6 +35,8 @@ trait MockUnitData
|
|||||||
|
|
||||||
public $client;
|
public $client;
|
||||||
|
|
||||||
|
public $vendor;
|
||||||
|
|
||||||
public $faker;
|
public $faker;
|
||||||
|
|
||||||
public $primary_contact;
|
public $primary_contact;
|
||||||
@ -92,6 +95,11 @@ trait MockUnitData
|
|||||||
'company_id' => $this->company->id,
|
'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([
|
$this->primary_contact = ClientContact::factory()->create([
|
||||||
'user_id' => $this->user->id,
|
'user_id' => $this->user->id,
|
||||||
'client_id' => $this->client->id,
|
'client_id' => $this->client->id,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user