diff --git a/app/Http/Requests/Client/StoreClientRequest.php b/app/Http/Requests/Client/StoreClientRequest.php index b9cb4f1a15d6..313ee11eb6ae 100644 --- a/app/Http/Requests/Client/StoreClientRequest.php +++ b/app/Http/Requests/Client/StoreClientRequest.php @@ -19,6 +19,7 @@ use App\Models\Client; use App\Models\GroupSetting; use App\Utils\Traits\MakesHash; use Illuminate\Support\Facades\Cache; +use Illuminate\Validation\Rule; class StoreClientRequest extends Request { @@ -48,7 +49,6 @@ class StoreClientRequest extends Request /* Ensure we have a client name, and that all emails are unique*/ //$rules['name'] = 'required|min:1'; - $rules['id_number'] = 'unique:clients,id_number,'.$this->id.',id,company_id,'.$this->company_id; $rules['settings'] = new ValidClientGroupSettingsRule(); $rules['contacts.*.email'] = 'bail|nullable|distinct|sometimes|email'; $rules['contacts.*.password'] = [ @@ -66,6 +66,10 @@ class StoreClientRequest extends Request $rules['hosted_clients'] = new CanStoreClientsRule($this->company_id); } + $rules['number'] = ['nullable',Rule::unique('clients')->where('company_id', auth()->user()->company()->id)]; + $rules['id_number'] = ['nullable',Rule::unique('clients')->where('company_id', auth()->user()->company()->id)]; + + return $rules; } @@ -122,7 +126,7 @@ class StoreClientRequest extends Request public function messages() { return [ - 'unique' => ctrans('validation.unique', ['attribute' => 'email']), + // 'unique' => ctrans('validation.unique', ['attribute' => ['email','number']), //'required' => trans('validation.required', ['attribute' => 'email']), 'contacts.*.email.required' => ctrans('validation.email', ['attribute' => 'email']), ]; diff --git a/app/Http/Requests/Expense/StoreExpenseRequest.php b/app/Http/Requests/Expense/StoreExpenseRequest.php index 828217b4ee63..3a4726867d97 100644 --- a/app/Http/Requests/Expense/StoreExpenseRequest.php +++ b/app/Http/Requests/Expense/StoreExpenseRequest.php @@ -35,10 +35,9 @@ class StoreExpenseRequest extends Request { $rules = []; - if (isset($this->number)) { + if ($this->number) $rules['number'] = Rule::unique('expenses')->where('company_id', auth()->user()->company()->id); - } - + if(!empty($this->client_id)) $rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id; diff --git a/tests/Feature/ClientApiTest.php b/tests/Feature/ClientApiTest.php index 3c87a5e07633..affd7461d3c6 100644 --- a/tests/Feature/ClientApiTest.php +++ b/tests/Feature/ClientApiTest.php @@ -54,6 +54,28 @@ class ClientApiTest extends TestCase $response->assertStatus(200); } + public function testDuplicateNumberCatch() + { + $data = [ + 'name' => $this->faker->firstName, + 'number' => 'iamaduplicate', + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/clients', $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/clients', $data); + + $response->assertStatus(302); + } + public function testClientPut() { $data = [ @@ -67,6 +89,20 @@ class ClientApiTest extends TestCase ])->put('/api/v1/clients/'.$this->encodePrimaryKey($this->client->id), $data); $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/clients/'.$this->encodePrimaryKey($this->client->id), $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/clients/', $data); + + $response->assertStatus(302); } public function testClientGet() diff --git a/tests/Feature/CreditTest.php b/tests/Feature/CreditTest.php index 936a10b6978d..0562f2fd16a7 100644 --- a/tests/Feature/CreditTest.php +++ b/tests/Feature/CreditTest.php @@ -131,4 +131,80 @@ class CreditTest extends TestCase $response->assertStatus(200); } + + public function testDuplicateNumberCatch() + { + $data = [ + 'status_id' => 1, + 'number' => 'dfdfd', + 'discount' => 0, + 'is_amount_discount' => 1, + 'number' => '3434343', + 'public_notes' => 'notes', + 'is_deleted' => 0, + 'custom_value1' => 0, + 'custom_value2' => 0, + 'custom_value3' => 0, + 'custom_value4' => 0, + 'status' => 1, + 'client_id' => $this->encodePrimaryKey($this->client->id), + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/credits', $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/credits', $data); + + $response->assertStatus(302); + } + + public function testCreditPut() + { + $data = [ + 'status_id' => 1, + 'number' => 'dfdfd', + 'discount' => 0, + 'is_amount_discount' => 1, + 'number' => '3434343', + 'public_notes' => 'notes', + 'is_deleted' => 0, + 'custom_value1' => 0, + 'custom_value2' => 0, + 'custom_value3' => 0, + 'custom_value4' => 0, + 'status' => 1, + 'client_id' => $this->encodePrimaryKey($this->client->id), + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/credits/'.$this->encodePrimaryKey($this->credit->id), $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/credits/'.$this->encodePrimaryKey($this->credit->id), $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/credits/', $data); + + $response->assertStatus(302); + } + + + } diff --git a/tests/Feature/ExpenseApiTest.php b/tests/Feature/ExpenseApiTest.php index f17aeb5362b7..70254f13b67a 100644 --- a/tests/Feature/ExpenseApiTest.php +++ b/tests/Feature/ExpenseApiTest.php @@ -57,11 +57,34 @@ class ExpenseApiTest extends TestCase $this->assertNotEmpty($arr['data']['number']); } + public function testDuplicateNumberCatch() + { + $data = [ + 'public_notes' => $this->faker->firstName, + 'number' => 'iamaduplicate', + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/expenses', $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/expenses', $data); + + $response->assertStatus(302); + } + + public function testExpensePut() { $data = [ 'public_notes' => $this->faker->firstName, - 'id_number' => 'Coolio', + 'number' => 'Coolio', ]; $response = $this->withHeaders([ @@ -70,6 +93,22 @@ class ExpenseApiTest extends TestCase ])->put('/api/v1/expenses/'.$this->encodePrimaryKey($this->expense->id), $data); $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/expenses/'.$this->encodePrimaryKey($this->expense->id), $data); + + $response->assertStatus(200); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/expenses/', $data); + + $response->assertStatus(302); + + } public function testExpenseGet() diff --git a/tests/Feature/InvoiceTest.php b/tests/Feature/InvoiceTest.php index 8ad15adfc832..68341e10b631 100644 --- a/tests/Feature/InvoiceTest.php +++ b/tests/Feature/InvoiceTest.php @@ -125,8 +125,15 @@ class InvoiceTest extends TestCase ])->post('/api/v1/invoices/', $invoice) ->assertStatus(200); - //test that the same request should produce a validation error due - //to duplicate number being used. + + $arr = $response->json(); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/invoices/'.$arr['data']['id'], $invoice) + ->assertStatus(200); + $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token,