PHPStorm can order methods by alphabet, who knew.

This commit is contained in:
James Cole
2024-02-22 20:11:09 +01:00
parent f9d4a43e05
commit 68c9c4ec3c
221 changed files with 5840 additions and 5843 deletions

View File

@@ -83,12 +83,12 @@ class MoveTransactionsRequest extends FormRequest
$data = $validator->getData();
$repository = app(AccountRepositoryInterface::class);
$repository->setUser(auth()->user());
$original = $repository->find((int) $data['original_account']);
$destination = $repository->find((int) $data['destination_account']);
$original = $repository->find((int)$data['original_account']);
$destination = $repository->find((int)$data['destination_account']);
// not the same type:
if ($original->accountType->type !== $destination->accountType->type) {
$validator->errors()->add('title', (string) trans('validation.same_account_type'));
$validator->errors()->add('title', (string)trans('validation.same_account_type'));
return;
}
@@ -98,7 +98,7 @@ class MoveTransactionsRequest extends FormRequest
// check different scenario's.
if (null === $originalCurrency xor null === $destinationCurrency) {
$validator->errors()->add('title', (string) trans('validation.same_account_currency'));
$validator->errors()->add('title', (string)trans('validation.same_account_currency'));
return;
}
@@ -107,7 +107,7 @@ class MoveTransactionsRequest extends FormRequest
return;
}
if ($originalCurrency->code !== $destinationCurrency->code) {
$validator->errors()->add('title', (string) trans('validation.same_account_currency'));
$validator->errors()->add('title', (string)trans('validation.same_account_currency'));
}
}
}

View File

@@ -78,6 +78,25 @@ class GenericRequest extends FormRequest
return $return;
}
private function parseAccounts(): void
{
if (0 !== $this->accounts->count()) {
return;
}
$repository = app(AccountRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('accounts');
if (is_array($array)) {
foreach ($array as $accountId) {
$accountId = (int)$accountId;
$account = $repository->find($accountId);
if (null !== $account) {
$this->accounts->push($account);
}
}
}
}
public function getBills(): Collection
{
$this->parseBills();
@@ -85,6 +104,25 @@ class GenericRequest extends FormRequest
return $this->bills;
}
private function parseBills(): void
{
if (0 !== $this->bills->count()) {
return;
}
$repository = app(BillRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('bills');
if (is_array($array)) {
foreach ($array as $billId) {
$billId = (int)$billId;
$bill = $repository->find($billId);
if (null !== $bill) {
$this->bills->push($bill);
}
}
}
}
public function getBudgets(): Collection
{
$this->parseBudgets();
@@ -92,6 +130,25 @@ class GenericRequest extends FormRequest
return $this->budgets;
}
private function parseBudgets(): void
{
if (0 !== $this->budgets->count()) {
return;
}
$repository = app(BudgetRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('budgets');
if (is_array($array)) {
foreach ($array as $budgetId) {
$budgetId = (int)$budgetId;
$budget = $repository->find($budgetId);
if (null !== $budget) {
$this->budgets->push($budget);
}
}
}
}
public function getCategories(): Collection
{
$this->parseCategories();
@@ -99,6 +156,25 @@ class GenericRequest extends FormRequest
return $this->categories;
}
private function parseCategories(): void
{
if (0 !== $this->categories->count()) {
return;
}
$repository = app(CategoryRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('categories');
if (is_array($array)) {
foreach ($array as $categoryId) {
$categoryId = (int)$categoryId;
$category = $repository->find($categoryId);
if (null !== $category) {
$this->categories->push($category);
}
}
}
}
public function getEnd(): Carbon
{
$date = $this->getCarbonDate('end');
@@ -154,100 +230,6 @@ class GenericRequest extends FormRequest
return $this->tags;
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
// this is cheating, but it works to initialize the collections.
$this->accounts = new Collection();
$this->budgets = new Collection();
$this->categories = new Collection();
$this->bills = new Collection();
$this->tags = new Collection();
return [
'start' => 'required|date',
'end' => 'required|date|after_or_equal:start',
];
}
private function parseAccounts(): void
{
if (0 !== $this->accounts->count()) {
return;
}
$repository = app(AccountRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('accounts');
if (is_array($array)) {
foreach ($array as $accountId) {
$accountId = (int)$accountId;
$account = $repository->find($accountId);
if (null !== $account) {
$this->accounts->push($account);
}
}
}
}
private function parseBills(): void
{
if (0 !== $this->bills->count()) {
return;
}
$repository = app(BillRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('bills');
if (is_array($array)) {
foreach ($array as $billId) {
$billId = (int)$billId;
$bill = $repository->find($billId);
if (null !== $bill) {
$this->bills->push($bill);
}
}
}
}
private function parseBudgets(): void
{
if (0 !== $this->budgets->count()) {
return;
}
$repository = app(BudgetRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('budgets');
if (is_array($array)) {
foreach ($array as $budgetId) {
$budgetId = (int)$budgetId;
$budget = $repository->find($budgetId);
if (null !== $budget) {
$this->budgets->push($budget);
}
}
}
}
private function parseCategories(): void
{
if (0 !== $this->categories->count()) {
return;
}
$repository = app(CategoryRepositoryInterface::class);
$repository->setUser(auth()->user());
$array = $this->get('categories');
if (is_array($array)) {
foreach ($array as $categoryId) {
$categoryId = (int)$categoryId;
$category = $repository->find($categoryId);
if (null !== $category) {
$this->categories->push($category);
}
}
}
}
private function parseTags(): void
{
if (0 !== $this->tags->count()) {
@@ -266,4 +248,22 @@ class GenericRequest extends FormRequest
}
}
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
// this is cheating, but it works to initialize the collections.
$this->accounts = new Collection();
$this->budgets = new Collection();
$this->categories = new Collection();
$this->bills = new Collection();
$this->tags = new Collection();
return [
'start' => 'required|date',
'end' => 'required|date|after_or_equal:start',
];
}
}

View File

@@ -83,7 +83,7 @@ class UpdateRequest extends FormRequest
$start = new Carbon($data['start']);
$end = new Carbon($data['end']);
if ($end->isBefore($start)) {
$validator->errors()->add('end', (string) trans('validation.date_after'));
$validator->errors()->add('end', (string)trans('validation.date_after'));
}
}
}

View File

@@ -73,6 +73,65 @@ class StoreRequest extends FormRequest
];
}
/**
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
*/
private function getTransactionData(): array
{
$return = [];
// transaction data:
/** @var null|array $transactions */
$transactions = $this->get('transactions');
if (null === $transactions) {
return [];
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = $this->getSingleTransactionData($transaction);
}
return $return;
}
/**
* Returns the repetition data as it is found in the submitted data.
*/
private function getRepetitionData(): array
{
$return = [];
// repetition data:
/** @var null|array $repetitions */
$repetitions = $this->get('repetitions');
if (null === $repetitions) {
return [];
}
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$current = [];
if (array_key_exists('type', $repetition)) {
$current['type'] = $repetition['type'];
}
if (array_key_exists('moment', $repetition)) {
$current['moment'] = $repetition['moment'];
}
if (array_key_exists('skip', $repetition)) {
$current['skip'] = (int)$repetition['skip'];
}
if (array_key_exists('weekend', $repetition)) {
$current['weekend'] = (int)$repetition['weekend'];
}
$return[] = $current;
}
return $return;
}
/**
* The rules that the incoming request must be matched against.
*/
@@ -136,63 +195,4 @@ class StoreRequest extends FormRequest
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
}
}
/**
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
*/
private function getTransactionData(): array
{
$return = [];
// transaction data:
/** @var null|array $transactions */
$transactions = $this->get('transactions');
if (null === $transactions) {
return [];
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = $this->getSingleTransactionData($transaction);
}
return $return;
}
/**
* Returns the repetition data as it is found in the submitted data.
*/
private function getRepetitionData(): array
{
$return = [];
// repetition data:
/** @var null|array $repetitions */
$repetitions = $this->get('repetitions');
if (null === $repetitions) {
return [];
}
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$current = [];
if (array_key_exists('type', $repetition)) {
$current['type'] = $repetition['type'];
}
if (array_key_exists('moment', $repetition)) {
$current['moment'] = $repetition['moment'];
}
if (array_key_exists('skip', $repetition)) {
$current['skip'] = (int)$repetition['skip'];
}
if (array_key_exists('weekend', $repetition)) {
$current['weekend'] = (int)$repetition['weekend'];
}
$return[] = $current;
}
return $return;
}
}

View File

@@ -78,6 +78,70 @@ class UpdateRequest extends FormRequest
return $return;
}
/**
* Returns the repetition data as it is found in the submitted data.
*/
private function getRepetitionData(): ?array
{
$return = [];
// repetition data:
/** @var null|array $repetitions */
$repetitions = $this->get('repetitions');
if (null === $repetitions) {
return null;
}
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$current = [];
if (array_key_exists('type', $repetition)) {
$current['type'] = $repetition['type'];
}
if (array_key_exists('moment', $repetition)) {
$current['moment'] = (string)$repetition['moment'];
}
if (array_key_exists('skip', $repetition)) {
$current['skip'] = (int)$repetition['skip'];
}
if (array_key_exists('weekend', $repetition)) {
$current['weekend'] = (int)$repetition['weekend'];
}
$return[] = $current;
}
if (0 === count($return)) {
return null;
}
return $return;
}
/**
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
*/
private function getTransactionData(): array
{
$return = [];
// transaction data:
/** @var null|array $transactions */
$transactions = $this->get('transactions');
if (null === $transactions) {
return [];
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = $this->getSingleTransactionData($transaction);
}
return $return;
}
/**
* The rules that the incoming request must be matched against.
*/
@@ -146,68 +210,4 @@ class UpdateRequest extends FormRequest
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
}
}
/**
* Returns the repetition data as it is found in the submitted data.
*/
private function getRepetitionData(): ?array
{
$return = [];
// repetition data:
/** @var null|array $repetitions */
$repetitions = $this->get('repetitions');
if (null === $repetitions) {
return null;
}
/** @var array $repetition */
foreach ($repetitions as $repetition) {
$current = [];
if (array_key_exists('type', $repetition)) {
$current['type'] = $repetition['type'];
}
if (array_key_exists('moment', $repetition)) {
$current['moment'] = (string) $repetition['moment'];
}
if (array_key_exists('skip', $repetition)) {
$current['skip'] = (int) $repetition['skip'];
}
if (array_key_exists('weekend', $repetition)) {
$current['weekend'] = (int) $repetition['weekend'];
}
$return[] = $current;
}
if (0 === count($return)) {
return null;
}
return $return;
}
/**
* Returns the transaction data as it is found in the submitted data. It's a complex method according to code
* standards but it just has a lot of ??-statements because of the fields that may or may not exist.
*/
private function getTransactionData(): array
{
$return = [];
// transaction data:
/** @var null|array $transactions */
$transactions = $this->get('transactions');
if (null === $transactions) {
return [];
}
/** @var array $transaction */
foreach ($transactions as $transaction) {
$return[] = $this->getSingleTransactionData($transaction);
}
return $return;
}
}

View File

@@ -64,6 +64,42 @@ class StoreRequest extends FormRequest
return $data;
}
private function getRuleTriggers(): array
{
$triggers = $this->get('triggers');
$return = [];
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
private function getRuleActions(): array
{
$actions = $this->get('actions');
$return = [];
if (is_array($actions)) {
foreach ($actions as $action) {
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
/**
* The rules that the incoming request must be matched against.
*/
@@ -197,40 +233,4 @@ class StoreRequest extends FormRequest
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
}
}
private function getRuleTriggers(): array
{
$triggers = $this->get('triggers');
$return = [];
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
private function getRuleActions(): array
{
$actions = $this->get('actions');
$return = [];
if (is_array($actions)) {
foreach ($actions as $action) {
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
}

View File

@@ -47,16 +47,6 @@ class TestRequest extends FormRequest
];
}
public function rules(): array
{
return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
];
}
private function getPage(): int
{
return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page');
@@ -81,4 +71,14 @@ class TestRequest extends FormRequest
{
return $this->get('accounts');
}
public function rules(): array
{
return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
];
}
}

View File

@@ -46,16 +46,6 @@ class TriggerRequest extends FormRequest
];
}
public function rules(): array
{
return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
];
}
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
@@ -75,4 +65,14 @@ class TriggerRequest extends FormRequest
{
return $this->get('accounts') ?? [];
}
public function rules(): array
{
return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
];
}
}

View File

@@ -70,6 +70,50 @@ class UpdateRequest extends FormRequest
return $return;
}
private function getRuleTriggers(): ?array
{
if (!$this->has('triggers')) {
return null;
}
$triggers = $this->get('triggers');
$return = [];
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$active = array_key_exists('active', $trigger) ? $trigger['active'] : true;
$stopProcessing = array_key_exists('stop_processing', $trigger) ? $trigger['stop_processing'] : false;
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $active,
'stop_processing' => $stopProcessing,
];
}
}
return $return;
}
private function getRuleActions(): ?array
{
if (!$this->has('actions')) {
return null;
}
$actions = $this->get('actions');
$return = [];
if (is_array($actions)) {
foreach ($actions as $action) {
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
/**
* The rules that the incoming request must be matched against.
*/
@@ -204,48 +248,4 @@ class UpdateRequest extends FormRequest
$validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action'));
}
}
private function getRuleTriggers(): ?array
{
if (!$this->has('triggers')) {
return null;
}
$triggers = $this->get('triggers');
$return = [];
if (is_array($triggers)) {
foreach ($triggers as $trigger) {
$active = array_key_exists('active', $trigger) ? $trigger['active'] : true;
$stopProcessing = array_key_exists('stop_processing', $trigger) ? $trigger['stop_processing'] : false;
$return[] = [
'type' => $trigger['type'],
'value' => $trigger['value'],
'active' => $active,
'stop_processing' => $stopProcessing,
];
}
}
return $return;
}
private function getRuleActions(): ?array
{
if (!$this->has('actions')) {
return null;
}
$actions = $this->get('actions');
$return = [];
if (is_array($actions)) {
foreach ($actions as $action) {
$return[] = [
'type' => $action['type'],
'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
];
}
}
return $return;
}
}

View File

@@ -46,16 +46,6 @@ class TestRequest extends FormRequest
];
}
public function rules(): array
{
return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
];
}
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
@@ -75,4 +65,14 @@ class TestRequest extends FormRequest
{
return $this->get('accounts');
}
public function rules(): array
{
return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
'accounts' => '',
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
];
}
}

View File

@@ -46,14 +46,6 @@ class TriggerRequest extends FormRequest
];
}
public function rules(): array
{
return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
];
}
private function getDate(string $field): ?Carbon
{
$value = $this->query($field);
@@ -77,4 +69,12 @@ class TriggerRequest extends FormRequest
return $this->get('accounts');
}
public function rules(): array
{
return [
'start' => 'date',
'end' => 'date|after_or_equal:start',
];
}
}

View File

@@ -69,134 +69,6 @@ class StoreRequest extends FormRequest
// TODO include location and ability to process it.
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
app('log')->debug('Collect rules of TransactionStoreRequest');
$validProtocols = config('firefly.valid_url_protocols');
return [
// basic fields for group:
'group_title' => 'min:1|max:1000|nullable',
'error_if_duplicate_hash' => [new IsBoolean()],
'apply_rules' => [new IsBoolean()],
// transaction rules (in array for splits):
'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
'transactions.*.date' => ['required', new IsDateOrTime()],
'transactions.*.order' => 'numeric|min:0',
// currency info
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
// amount
'transactions.*.amount' => ['required', new IsValidPositiveAmount()],
'transactions.*.foreign_amount' => ['nullable', new IsValidZeroOrMoreAmount()],
// description
'transactions.*.description' => 'nullable|min:1|max:1000',
// source of transaction
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.source_name' => 'min:1|max:255|nullable',
'transactions.*.source_iban' => 'min:1|max:255|nullable|iban',
'transactions.*.source_number' => 'min:1|max:255|nullable',
'transactions.*.source_bic' => 'min:1|max:255|nullable|bic',
// destination of transaction
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.destination_name' => 'min:1|max:255|nullable',
'transactions.*.destination_iban' => 'min:1|max:255|nullable|iban',
'transactions.*.destination_number' => 'min:1|max:255|nullable',
'transactions.*.destination_bic' => 'min:1|max:255|nullable|bic',
// budget, category, bill and piggy
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser()],
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser(), 'nullable'],
'transactions.*.category_name' => 'min:1|max:255|nullable',
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()],
'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
'transactions.*.piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser()],
'transactions.*.piggy_bank_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
// other interesting fields
'transactions.*.reconciled' => [new IsBoolean()],
'transactions.*.notes' => 'min:1|max:32768|nullable',
'transactions.*.tags' => 'min:0|max:255',
'transactions.*.tags.*' => 'min:0|max:255',
// meta info fields
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => sprintf('min:1|max:255|nullable|url:%s', $validProtocols),
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_op' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_id' => 'min:1|max:255|nullable',
'transactions.*.sepa_db' => 'min:1|max:255|nullable',
'transactions.*.sepa_country' => 'min:1|max:255|nullable',
'transactions.*.sepa_ep' => 'min:1|max:255|nullable',
'transactions.*.sepa_ci' => 'min:1|max:255|nullable',
'transactions.*.sepa_batch_id' => 'min:1|max:255|nullable',
// dates
'transactions.*.interest_date' => 'date|nullable',
'transactions.*.book_date' => 'date|nullable',
'transactions.*.process_date' => 'date|nullable',
'transactions.*.due_date' => 'date|nullable',
'transactions.*.payment_date' => 'date|nullable',
'transactions.*.invoice_date' => 'date|nullable',
];
}
/**
* Configure the validator instance.
*/
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
// must be valid array.
$this->validateTransactionArray($validator);
// must submit at least one transaction.
app('log')->debug('Now going to validateOneTransaction');
$this->validateOneTransaction($validator);
app('log')->debug('Now done with validateOneTransaction');
// all journals must have a description
$this->validateDescriptions($validator);
// all transaction types must be equal:
$this->validateTransactionTypes($validator);
// validate foreign currency info
$this->validateForeignCurrencyInformation($validator);
// validate all account info
$this->validateAccountInformation($validator);
// validate source/destination is equal, depending on the transaction journal type.
$this->validateEqualAccounts($validator);
// the group must have a description if > 1 journal.
$this->validateGroupDescription($validator);
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
}
}
/**
* Get transaction data.
*/
@@ -291,4 +163,132 @@ class StoreRequest extends FormRequest
return $return;
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
app('log')->debug('Collect rules of TransactionStoreRequest');
$validProtocols = config('firefly.valid_url_protocols');
return [
// basic fields for group:
'group_title' => 'min:1|max:1000|nullable',
'error_if_duplicate_hash' => [new IsBoolean()],
'apply_rules' => [new IsBoolean()],
// transaction rules (in array for splits):
'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation',
'transactions.*.date' => ['required', new IsDateOrTime()],
'transactions.*.order' => 'numeric|min:0',
// currency info
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
// amount
'transactions.*.amount' => ['required', new IsValidPositiveAmount()],
'transactions.*.foreign_amount' => ['nullable', new IsValidZeroOrMoreAmount()],
// description
'transactions.*.description' => 'nullable|min:1|max:1000',
// source of transaction
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.source_name' => 'min:1|max:255|nullable',
'transactions.*.source_iban' => 'min:1|max:255|nullable|iban',
'transactions.*.source_number' => 'min:1|max:255|nullable',
'transactions.*.source_bic' => 'min:1|max:255|nullable|bic',
// destination of transaction
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.destination_name' => 'min:1|max:255|nullable',
'transactions.*.destination_iban' => 'min:1|max:255|nullable|iban',
'transactions.*.destination_number' => 'min:1|max:255|nullable',
'transactions.*.destination_bic' => 'min:1|max:255|nullable|bic',
// budget, category, bill and piggy
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser()],
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser(), 'nullable'],
'transactions.*.category_name' => 'min:1|max:255|nullable',
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()],
'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
'transactions.*.piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser()],
'transactions.*.piggy_bank_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
// other interesting fields
'transactions.*.reconciled' => [new IsBoolean()],
'transactions.*.notes' => 'min:1|max:32768|nullable',
'transactions.*.tags' => 'min:0|max:255',
'transactions.*.tags.*' => 'min:0|max:255',
// meta info fields
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => sprintf('min:1|max:255|nullable|url:%s', $validProtocols),
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_op' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_id' => 'min:1|max:255|nullable',
'transactions.*.sepa_db' => 'min:1|max:255|nullable',
'transactions.*.sepa_country' => 'min:1|max:255|nullable',
'transactions.*.sepa_ep' => 'min:1|max:255|nullable',
'transactions.*.sepa_ci' => 'min:1|max:255|nullable',
'transactions.*.sepa_batch_id' => 'min:1|max:255|nullable',
// dates
'transactions.*.interest_date' => 'date|nullable',
'transactions.*.book_date' => 'date|nullable',
'transactions.*.process_date' => 'date|nullable',
'transactions.*.due_date' => 'date|nullable',
'transactions.*.payment_date' => 'date|nullable',
'transactions.*.invoice_date' => 'date|nullable',
];
}
/**
* Configure the validator instance.
*/
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
// must be valid array.
$this->validateTransactionArray($validator);
// must submit at least one transaction.
app('log')->debug('Now going to validateOneTransaction');
$this->validateOneTransaction($validator);
app('log')->debug('Now done with validateOneTransaction');
// all journals must have a description
$this->validateDescriptions($validator);
// all transaction types must be equal:
$this->validateTransactionTypes($validator);
// validate foreign currency info
$this->validateForeignCurrencyInformation($validator);
// validate all account info
$this->validateAccountInformation($validator);
// validate source/destination is equal, depending on the transaction journal type.
$this->validateEqualAccounts($validator);
// the group must have a description if > 1 journal.
$this->validateGroupDescription($validator);
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
}
}
}

View File

@@ -90,127 +90,6 @@ class UpdateRequest extends FormRequest
return $data;
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$validProtocols = config('firefly.valid_url_protocols');
return [
// basic fields for group:
'group_title' => 'min:1|max:1000|nullable',
'apply_rules' => [new IsBoolean()],
// transaction rules (in array for splits):
'transactions.*.type' => 'in:withdrawal,deposit,transfer,opening-balance,reconciliation',
'transactions.*.date' => [new IsDateOrTime()],
'transactions.*.order' => 'numeric|min:0',
// group id:
'transactions.*.transaction_journal_id' => ['nullable', 'numeric', new BelongsUser()],
// currency info
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
// amount
'transactions.*.amount' => [new IsValidPositiveAmount()],
'transactions.*.foreign_amount' => ['nullable', new IsValidZeroOrMoreAmount()],
// description
'transactions.*.description' => 'nullable|min:1|max:1000',
// source of transaction
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.source_name' => 'min:1|max:255|nullable',
// destination of transaction
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.destination_name' => 'min:1|max:255|nullable',
// budget, category, bill and piggy
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser(), 'nullable'],
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser(), 'nullable'],
'transactions.*.category_name' => 'min:1|max:255|nullable',
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()],
'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
// other interesting fields
'transactions.*.reconciled' => [new IsBoolean()],
'transactions.*.notes' => 'min:1|max:32768|nullable',
'transactions.*.tags' => 'min:0|max:255|nullable',
'transactions.*.tags.*' => 'min:0|max:255',
// meta info fields
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => sprintf('min:1|max:255|nullable|url:%s', $validProtocols),
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_op' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_id' => 'min:1|max:255|nullable',
'transactions.*.sepa_db' => 'min:1|max:255|nullable',
'transactions.*.sepa_country' => 'min:1|max:255|nullable',
'transactions.*.sepa_ep' => 'min:1|max:255|nullable',
'transactions.*.sepa_ci' => 'min:1|max:255|nullable',
'transactions.*.sepa_batch_id' => 'min:1|max:255|nullable',
// dates
'transactions.*.interest_date' => 'date|nullable',
'transactions.*.book_date' => 'date|nullable',
'transactions.*.process_date' => 'date|nullable',
'transactions.*.due_date' => 'date|nullable',
'transactions.*.payment_date' => 'date|nullable',
'transactions.*.invoice_date' => 'date|nullable',
];
}
/**
* Configure the validator instance.
*/
public function withValidator(Validator $validator): void
{
app('log')->debug('Now in withValidator');
/** @var TransactionGroup $transactionGroup */
$transactionGroup = $this->route()->parameter('transactionGroup');
$validator->after(
function (Validator $validator) use ($transactionGroup): void {
// if more than one, verify that there are journal ID's present.
$this->validateJournalIds($validator, $transactionGroup);
// all transaction types must be equal:
$this->validateTransactionTypesForUpdate($validator);
// user wants to update a reconciled transaction.
// source, destination, amount + foreign_amount cannot be changed
// and must be omitted from the request.
$this->preventUpdateReconciled($validator, $transactionGroup);
// validate source/destination is equal, depending on the transaction journal type.
$this->validateEqualAccountsForUpdate($validator, $transactionGroup);
// see method:
// $this->preventNoAccountInfo($validator, );
// validate that the currency fits the source and/or destination account.
// validate all account info
$this->validateAccountInformationUpdate($validator, $transactionGroup);
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
}
}
/**
* Get transaction data.
*
@@ -258,7 +137,7 @@ class UpdateRequest extends FormRequest
{
foreach ($this->integerFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]);
$current[$fieldName] = $this->integerFromValue((string)$transaction[$fieldName]);
}
}
@@ -273,7 +152,7 @@ class UpdateRequest extends FormRequest
{
foreach ($this->stringFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->clearString((string) $transaction[$fieldName]);
$current[$fieldName] = $this->clearString((string)$transaction[$fieldName]);
}
}
@@ -288,7 +167,7 @@ class UpdateRequest extends FormRequest
{
foreach ($this->textareaFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->clearStringKeepNewlines((string) $transaction[$fieldName]); // keep newlines
$current[$fieldName] = $this->clearStringKeepNewlines((string)$transaction[$fieldName]); // keep newlines
}
}
@@ -304,8 +183,8 @@ class UpdateRequest extends FormRequest
foreach ($this->dateFields as $fieldName) {
app('log')->debug(sprintf('Now at date field %s', $fieldName));
if (array_key_exists($fieldName, $transaction)) {
app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName]));
$current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]);
app('log')->debug(sprintf('New value: "%s"', (string)$transaction[$fieldName]));
$current[$fieldName] = $this->dateFromValue((string)$transaction[$fieldName]);
}
}
@@ -320,7 +199,7 @@ class UpdateRequest extends FormRequest
{
foreach ($this->booleanFields as $fieldName) {
if (array_key_exists($fieldName, $transaction)) {
$current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]);
$current[$fieldName] = $this->convertBoolean((string)$transaction[$fieldName]);
}
}
@@ -355,11 +234,132 @@ class UpdateRequest extends FormRequest
$current[$fieldName] = sprintf('%.12f', $value);
}
if (!is_float($value)) {
$current[$fieldName] = (string) $value;
$current[$fieldName] = (string)$value;
}
}
}
return $current;
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$validProtocols = config('firefly.valid_url_protocols');
return [
// basic fields for group:
'group_title' => 'min:1|max:1000|nullable',
'apply_rules' => [new IsBoolean()],
// transaction rules (in array for splits):
'transactions.*.type' => 'in:withdrawal,deposit,transfer,opening-balance,reconciliation',
'transactions.*.date' => [new IsDateOrTime()],
'transactions.*.order' => 'numeric|min:0',
// group id:
'transactions.*.transaction_journal_id' => ['nullable', 'numeric', new BelongsUser()],
// currency info
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
// amount
'transactions.*.amount' => [new IsValidPositiveAmount()],
'transactions.*.foreign_amount' => ['nullable', new IsValidZeroOrMoreAmount()],
// description
'transactions.*.description' => 'nullable|min:1|max:1000',
// source of transaction
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.source_name' => 'min:1|max:255|nullable',
// destination of transaction
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.destination_name' => 'min:1|max:255|nullable',
// budget, category, bill and piggy
'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser(), 'nullable'],
'transactions.*.budget_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser(), 'nullable'],
'transactions.*.category_name' => 'min:1|max:255|nullable',
'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()],
'transactions.*.bill_name' => ['min:1', 'max:255', 'nullable', new BelongsUser()],
// other interesting fields
'transactions.*.reconciled' => [new IsBoolean()],
'transactions.*.notes' => 'min:1|max:32768|nullable',
'transactions.*.tags' => 'min:0|max:255|nullable',
'transactions.*.tags.*' => 'min:0|max:255',
// meta info fields
'transactions.*.internal_reference' => 'min:1|max:255|nullable',
'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => sprintf('min:1|max:255|nullable|url:%s', $validProtocols),
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_op' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_id' => 'min:1|max:255|nullable',
'transactions.*.sepa_db' => 'min:1|max:255|nullable',
'transactions.*.sepa_country' => 'min:1|max:255|nullable',
'transactions.*.sepa_ep' => 'min:1|max:255|nullable',
'transactions.*.sepa_ci' => 'min:1|max:255|nullable',
'transactions.*.sepa_batch_id' => 'min:1|max:255|nullable',
// dates
'transactions.*.interest_date' => 'date|nullable',
'transactions.*.book_date' => 'date|nullable',
'transactions.*.process_date' => 'date|nullable',
'transactions.*.due_date' => 'date|nullable',
'transactions.*.payment_date' => 'date|nullable',
'transactions.*.invoice_date' => 'date|nullable',
];
}
/**
* Configure the validator instance.
*/
public function withValidator(Validator $validator): void
{
app('log')->debug('Now in withValidator');
/** @var TransactionGroup $transactionGroup */
$transactionGroup = $this->route()->parameter('transactionGroup');
$validator->after(
function (Validator $validator) use ($transactionGroup): void {
// if more than one, verify that there are journal ID's present.
$this->validateJournalIds($validator, $transactionGroup);
// all transaction types must be equal:
$this->validateTransactionTypesForUpdate($validator);
// user wants to update a reconciled transaction.
// source, destination, amount + foreign_amount cannot be changed
// and must be omitted from the request.
$this->preventUpdateReconciled($validator, $transactionGroup);
// validate source/destination is equal, depending on the transaction journal type.
$this->validateEqualAccountsForUpdate($validator, $transactionGroup);
// see method:
// $this->preventNoAccountInfo($validator, );
// validate that the currency fits the source and/or destination account.
// validate all account info
$this->validateAccountInformationUpdate($validator, $transactionGroup);
}
);
if ($validator->fails()) {
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
}
}
}