Improved validation for recurring ivnoice numbers
This commit is contained in:
parent
7304f01de6
commit
9a7478e175
|
|
@ -13,7 +13,6 @@ namespace App\Http\Requests\RecurringInvoice;
|
||||||
|
|
||||||
use App\Http\Requests\Request;
|
use App\Http\Requests\Request;
|
||||||
use App\Http\ValidationRules\Project\ValidProjectForClient;
|
use App\Http\ValidationRules\Project\ValidProjectForClient;
|
||||||
use App\Http\ValidationRules\Recurring\UniqueRecurringInvoiceNumberRule;
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\RecurringInvoice;
|
use App\Models\RecurringInvoice;
|
||||||
use App\Utils\Traits\CleanLineItems;
|
use App\Utils\Traits\CleanLineItems;
|
||||||
|
|
@ -68,7 +67,7 @@ class StoreRecurringInvoiceRequest extends Request
|
||||||
|
|
||||||
$rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())];
|
$rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())];
|
||||||
|
|
||||||
$rules['number'] = new UniqueRecurringInvoiceNumberRule($this->all());
|
$rules['number'] = ['bail', 'nullable', \Illuminate\Validation\Rule::unique('recurring_invoices')->where('company_id', $user->company()->id)];
|
||||||
|
|
||||||
$rules['tax_rate1'] = 'bail|sometimes|numeric';
|
$rules['tax_rate1'] = 'bail|sometimes|numeric';
|
||||||
$rules['tax_rate2'] = 'bail|sometimes|numeric';
|
$rules['tax_rate2'] = 'bail|sometimes|numeric';
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
namespace App\Http\Requests\RecurringQuote;
|
namespace App\Http\Requests\RecurringQuote;
|
||||||
|
|
||||||
use App\Http\Requests\Request;
|
use App\Http\Requests\Request;
|
||||||
use App\Http\ValidationRules\Recurring\UniqueRecurringQuoteNumberRule;
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\RecurringQuote;
|
use App\Models\RecurringQuote;
|
||||||
use App\Utils\Traits\CleanLineItems;
|
use App\Utils\Traits\CleanLineItems;
|
||||||
|
|
@ -63,7 +62,7 @@ class StoreRecurringQuoteRequest extends Request
|
||||||
|
|
||||||
$rules['frequency_id'] = 'required|integer|digits_between:1,12';
|
$rules['frequency_id'] = 'required|integer|digits_between:1,12';
|
||||||
|
|
||||||
$rules['number'] = new UniqueRecurringQuoteNumberRule($this->all());
|
$rules['number'] = ['bail', 'nullable', \Illuminate\Validation\Rule::unique('recurring_quotes')->where('company_id', $user->company()->id)];
|
||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Invoice Ninja (https://invoiceninja.com).
|
|
||||||
*
|
|
||||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @license https://www.elastic.co/licensing/elastic-license
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Http\ValidationRules\Recurring;
|
|
||||||
|
|
||||||
use App\Models\RecurringInvoice;
|
|
||||||
use Illuminate\Contracts\Validation\Rule;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class UniqueRecurringInvoiceNumberRule.
|
|
||||||
*/
|
|
||||||
class UniqueRecurringInvoiceNumberRule implements Rule
|
|
||||||
{
|
|
||||||
public $input;
|
|
||||||
|
|
||||||
public function __construct($input)
|
|
||||||
{
|
|
||||||
$this->input = $input;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $attribute
|
|
||||||
* @param mixed $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function passes($attribute, $value)
|
|
||||||
{
|
|
||||||
return $this->checkIfInvoiceNumberUnique(); //if it exists, return false!
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function message()
|
|
||||||
{
|
|
||||||
return ctrans('texts.recurring_invoice_number_taken', ['number' => $this->input['number']]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function checkIfInvoiceNumberUnique(): bool
|
|
||||||
{
|
|
||||||
if (empty($this->input['number'])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$invoice = RecurringInvoice::query()->where('client_id', $this->input['client_id'])
|
|
||||||
->where('number', $this->input['number'])
|
|
||||||
->withTrashed()
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
if ($invoice) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Quote Ninja (https://invoiceninja.com).
|
|
||||||
*
|
|
||||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022. Quote Ninja LLC (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @license https://www.elastic.co/licensing/elastic-license
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Http\ValidationRules\Recurring;
|
|
||||||
|
|
||||||
use App\Models\RecurringQuote;
|
|
||||||
use Illuminate\Contracts\Validation\Rule;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class UniqueRecurringQuoteNumberRule.
|
|
||||||
*/
|
|
||||||
class UniqueRecurringQuoteNumberRule implements Rule
|
|
||||||
{
|
|
||||||
public $input;
|
|
||||||
|
|
||||||
public function __construct($input)
|
|
||||||
{
|
|
||||||
$this->input = $input;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $attribute
|
|
||||||
* @param mixed $value
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function passes($attribute, $value)
|
|
||||||
{
|
|
||||||
return $this->checkIfQuoteNumberUnique(); //if it exists, return false!
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function message()
|
|
||||||
{
|
|
||||||
return ctrans('texts.recurring_quote_number_taken', ['number' => $this->input['number']]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function checkIfQuoteNumberUnique(): bool
|
|
||||||
{
|
|
||||||
if (empty($this->input['number'])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$invoice = RecurringQuote::query()->where('client_id', $this->input['client_id'])
|
|
||||||
->where('number', $this->input['number'])
|
|
||||||
->withTrashed()
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
if ($invoice) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -61,6 +61,36 @@ class RecurringInvoiceTest extends TestCase
|
||||||
$this->makeTestData();
|
$this->makeTestData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testUniqueNumber()
|
||||||
|
{
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'client_id' => $this->client->hashed_id,
|
||||||
|
'frequency_id' => 5,
|
||||||
|
'next_send_date' => now()->addMonth()->format('Y-m-d'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->postJson('/api/v1/recurring_invoices', $data);
|
||||||
|
|
||||||
|
$response->assertStatus(200);
|
||||||
|
|
||||||
|
$arr = $response->json();
|
||||||
|
|
||||||
|
$this->assertNotNull($arr['data']['number']);
|
||||||
|
|
||||||
|
$data['number'] = $arr['data']['number'];
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->postJson('/api/v1/recurring_invoices', $data)
|
||||||
|
->assertStatus(422);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function testBulkUpdatesTaxes()
|
public function testBulkUpdatesTaxes()
|
||||||
{
|
{
|
||||||
RecurringInvoice::factory(5)->create([
|
RecurringInvoice::factory(5)->create([
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue