Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 6 additions & 51 deletions app/Http/Controllers/API/v1/TransactionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
use App\Jobs\RecurrentTransactionJob;
use App\Models\RecurringTransactionRule;
use App\Models\Transaction;
use App\Rules\Iso8601DateTime;
use App\Rules\ValidateClientId;
use App\Services\FileService;
use App\Services\RecurringTransactionService;
use Illuminate\Http\JsonResponse;
Expand All @@ -17,6 +15,8 @@
use OpenApi\Attributes as OA;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Throwable;
use App\Http\Requests\StoreTransactionRequest;
use App\Http\Requests\UpdateTransactionRequest;

#[OA\Tag(name: 'Transactions', description: 'Endpoints for managing transactions')]
class TransactionController extends ApiController
Expand Down Expand Up @@ -291,33 +291,10 @@ enum: ['daily', 'weekly', 'monthly', 'yearly']
/**
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function store(Request $request): JsonResponse
public function store(StoreTransactionRequest $request): JsonResponse
{
$validationResult = $this->validateRequest($request, [
'client_id' => ['nullable', 'string', new ValidateClientId()],
'amount' => 'required|numeric|min:0.01',
'type' => 'required|string|in:income,expense',
'description' => 'nullable|string',
'datetime' => ['nullable', new Iso8601DateTime()],
'created_at' => ['nullable', new Iso8601DateTime()],
'group_id' => 'nullable|integer|exists:groups,id',
'party_id' => 'nullable|integer|exists:parties,id',
'wallet_id' => 'required|integer|exists:wallets,id',
'categories' => 'nullable|array',
'is_recurring' => 'nullable|boolean',
'recurrence_period' => 'nullable|string|in:daily,weekly,monthly,yearly',
'recurrence_interval' => 'nullable|integer|min:1',
'recurrence_ends_at' => ['nullable', 'date', 'after:today', new Iso8601DateTime()],
'categories.*' => 'integer|exists:categories,id',
'files' => 'nullable|array',
'files.*' => 'file|mimes:' . FileService::ALLOWED_EXTENSIONS . '|max:' . FileService::MAX_KILOBYTES,
]);

if (! $validationResult['isValidated']) {
return $this->failure($validationResult['message'], $validationResult['code'], $validationResult['errors']);
}

$data = $validationResult['data'];
$data = $request->validated();
$user = $request->user();

if (! empty($data['client_id'])) {
Expand Down Expand Up @@ -611,31 +588,9 @@ public function show($transactionId, Request $request): JsonResponse
/**
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function update(Request $request, $transactionId): JsonResponse
public function update(UpdateTransactionRequest $request, $transactionId): JsonResponse
{
$validationResult = $this->validateRequest($request, [
'client_id' => ['nullable', 'string', new ValidateClientId()],
'amount' => 'nullable|numeric|min:0.01',
'type' => 'nullable|string|in:income,expense',
'datetime' => ['nullable', new Iso8601DateTime()],
'description' => 'nullable|string',
'party_id' => 'nullable|integer|exists:parties,id',
'wallet_id' => 'sometimes|integer|exists:wallets,id',
'group_id' => 'nullable|integer|exists:groups,id',
'categories' => 'nullable|array',
'categories.*' => 'integer|exists:categories,id',
'is_recurring' => 'nullable|boolean',
'recurrence_period' => 'nullable|string|in:daily,weekly,monthly,yearly',
'recurrence_interval' => 'nullable|integer|min:1',
'recurrence_ends_at' => ['nullable', 'date', 'after:today', new Iso8601DateTime()],
'updated_at' => ['nullable', new Iso8601DateTime()],
]);

if (! $validationResult['isValidated']) {
return $this->failure($validationResult['message'], $validationResult['code'], $validationResult['errors']);
}

$validatedData = $validationResult['data'];
$validatedData = $request->validated();
$recurringTransactionData = [];

if (isset($validatedData['is_recurring']) && $validatedData['is_recurring']) {
Expand Down
30 changes: 30 additions & 0 deletions app/Http/Requests/ApiFormRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\Http\Requests;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;

abstract class ApiFormRequest extends FormRequest
{
/**
* Handle a failed validation attempt.
*
* @param \Illuminate\Contracts\Validation\Validator $validator
* @return void
*
* @throws \Illuminate\Http\Exceptions\HttpResponseException
*/
protected function failedValidation(Validator $validator)
{
// This exactly mirrors the ApiController's failure() structure
$response = response()->json([
'success' => false,
'message' => __('Server failed to validate request.'),
'errors' => $validator->errors()->toArray(),
], 422);

throw new HttpResponseException($response);
}
}
4 changes: 2 additions & 2 deletions app/Http/Requests/FileImportApiRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
// use Illuminate\Foundation\Http\FormRequest;

class FileImportApiRequest extends FormRequest
class FileImportApiRequest extends ApiFormRequest
{
/**
* Get the validation rules that apply to the request.
Expand Down
4 changes: 2 additions & 2 deletions app/Http/Requests/FixFailedImportsRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
// use Illuminate\Foundation\Http\FormRequest;

class FixFailedImportsRequest extends FormRequest
class FixFailedImportsRequest extends ApiFormRequest
{
/**
* Get the validation rules that apply to the request.
Expand Down
4 changes: 2 additions & 2 deletions app/Http/Requests/ImportAnalyzeRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
// use Illuminate\Foundation\Http\FormRequest;

class ImportAnalyzeRequest extends FormRequest
class ImportAnalyzeRequest extends ApiFormRequest
{
public function rules(): array
{
Expand Down
4 changes: 2 additions & 2 deletions app/Http/Requests/ImportConfirmRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
// use Illuminate\Foundation\Http\FormRequest;

class ImportConfirmRequest extends FormRequest
class ImportConfirmRequest extends ApiFormRequest
{
public function rules(): array
{
Expand Down
50 changes: 50 additions & 0 deletions app/Http/Requests/StoreTransactionRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace App\Http\Requests;

use App\Rules\Iso8601DateTime;
use App\Rules\ValidateClientId;
use App\Services\FileService;

// use Illuminate\Foundation\Http\FormRequest;

class StoreTransactionRequest extends ApiFormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'convert_myself_to_transfer' => 'sometimes|boolean',
'client_id' => ['nullable', 'string', new ValidateClientId()],
'amount' => 'required|numeric|min:0.01',
'type' => 'required|string|in:income,expense',
'description' => 'nullable|string',
'datetime' => ['nullable', new Iso8601DateTime()],
'created_at' => ['nullable', new Iso8601DateTime()],
'group_id' => 'nullable|integer|exists:groups,id',
'party_id' => 'nullable|integer|exists:parties,id',
'wallet_id' => 'required|integer|exists:wallets,id',
'categories' => 'nullable|array',
'categories.*' => 'integer|exists:categories,id',
'is_recurring' => 'nullable|boolean',
'recurrence_period' => 'nullable|string|in:daily,weekly,monthly,yearly',
'recurrence_interval' => 'nullable|integer|min:1',
'recurrence_ends_at' => ['nullable', 'date', 'after:today', new Iso8601DateTime()],
'files' => 'nullable|array',
'files.*' => 'file|mimes:' . FileService::ALLOWED_EXTENSIONS . '|max:' . FileService::MAX_KILOBYTES,
'from_wallet_id' => 'required_if:convert_myself_to_transfer,true|integer|exists:wallets,id',
];
}
}
45 changes: 45 additions & 0 deletions app/Http/Requests/UpdateTransactionRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace App\Http\Requests;

use App\Rules\Iso8601DateTime;
use App\Rules\ValidateClientId;

// use Illuminate\Foundation\Http\FormRequest;

class UpdateTransactionRequest extends ApiFormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true; //auth handled by middleware
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'client_id' => ['nullable', 'string', new ValidateClientId()],
'amount' => 'nullable|numeric|min:0.01',
'type' => 'nullable|string|in:income,expense',
'datetime' => ['nullable', new Iso8601DateTime()],
'description' => 'nullable|string',
'party_id' => 'nullable|integer|exists:parties,id',
'wallet_id' => 'sometimes|integer|exists:wallets,id',
'group_id' => 'nullable|integer|exists:groups,id',
'categories' => 'nullable|array',
'categories.*' => 'integer|exists:categories,id',
'is_recurring' => 'nullable|boolean',
'recurrence_period' => 'nullable|string|in:daily,weekly,monthly,yearly',
'recurrence_interval' => 'nullable|integer|min:1',
'recurrence_ends_at' => ['nullable', 'date', 'after:today', new Iso8601DateTime()],
'updated_at' => ['nullable', new Iso8601DateTime()],
];
}
}
Loading