diff --git a/app/Api/V1/Controllers/Models/Recurrence/DestroyController.php b/app/Api/V1/Controllers/Models/Recurrence/DestroyController.php new file mode 100644 index 0000000000..573c996762 --- /dev/null +++ b/app/Api/V1/Controllers/Models/Recurrence/DestroyController.php @@ -0,0 +1,75 @@ +. + */ + +namespace FireflyIII\Api\V1\Controllers\Models\Recurrence; + + +use FireflyIII\Api\V1\Controllers\Controller; +use FireflyIII\Models\Recurrence; +use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; +use FireflyIII\User; +use Illuminate\Http\JsonResponse; + +/** + * Class DestroyController + */ +class DestroyController extends Controller +{ + private RecurringRepositoryInterface $repository; + + /** + * RecurrenceController constructor. + * + * @codeCoverageIgnore + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var User $user */ + $user = auth()->user(); + + /** @var RecurringRepositoryInterface repository */ + $this->repository = app(RecurringRepositoryInterface::class); + $this->repository->setUser($user); + + return $next($request); + } + ); + } + + + /** + * Delete the resource. + * + * @param Recurrence $recurrence + * + * @return JsonResponse + * @codeCoverageIgnore + */ + public function destroy(Recurrence $recurrence): JsonResponse + { + $this->repository->destroy($recurrence); + + return response()->json([], 204); + } +} \ No newline at end of file diff --git a/app/Api/V1/Controllers/Models/Recurrence/ListController.php b/app/Api/V1/Controllers/Models/Recurrence/ListController.php new file mode 100644 index 0000000000..b84b2ae63e --- /dev/null +++ b/app/Api/V1/Controllers/Models/Recurrence/ListController.php @@ -0,0 +1,123 @@ +. + */ + +namespace FireflyIII\Api\V1\Controllers\Models\Recurrence; + + +use FireflyIII\Api\V1\Controllers\Controller; +use FireflyIII\Helpers\Collector\GroupCollectorInterface; +use FireflyIII\Models\Recurrence; +use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; +use FireflyIII\Support\Http\Api\TransactionFilter; +use FireflyIII\Transformers\TransactionGroupTransformer; +use FireflyIII\User; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; +use League\Fractal\Pagination\IlluminatePaginatorAdapter; +use League\Fractal\Resource\Collection as FractalCollection; + +/** + * Class ListController + */ +class ListController extends Controller +{ + use TransactionFilter; + + private RecurringRepositoryInterface $repository; + + /** + * RecurrenceController constructor. + * + * @codeCoverageIgnore + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var User $user */ + $user = auth()->user(); + + /** @var RecurringRepositoryInterface repository */ + $this->repository = app(RecurringRepositoryInterface::class); + $this->repository->setUser($user); + + return $next($request); + } + ); + } + + /** + * Show transactions for this recurrence. + * + * @param Request $request + * @param Recurrence $recurrence + * + * @return JsonResponse + * @codeCoverageIgnore + */ + public function transactions(Request $request, Recurrence $recurrence): JsonResponse + { + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $type = $request->get('type') ?? 'default'; + $this->parameters->set('type', $type); + + $types = $this->mapTransactionTypes($this->parameters->get('type')); + $manager = $this->getManager(); + // whatever is returned by the query, it must be part of these journals: + $journalIds = $this->repository->getJournalIds($recurrence); + + /** @var User $admin */ + $admin = auth()->user(); + + // use new group collector: + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector + ->setUser($admin) + // filter on journal IDs. + ->setJournalIds($journalIds) + // all info needed for the API: + ->withAPIInformation() + // set page size: + ->setLimit($pageSize) + // set page to retrieve + ->setPage($this->parameters->get('page')) + // set types of transactions to return. + ->setTypes($types); + + if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { + $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + } + $paginator = $collector->getPaginatedGroups(); + $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); + $transactions = $paginator->getCollection(); + + /** @var TransactionGroupTransformer $transformer */ + $transformer = app(TransactionGroupTransformer::class); + $transformer->setParameters($this->parameters); + + $resource = new FractalCollection($transactions, $transformer, 'transactions'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); + } +} \ No newline at end of file diff --git a/app/Api/V1/Controllers/Models/Recurrence/ShowController.php b/app/Api/V1/Controllers/Models/Recurrence/ShowController.php new file mode 100644 index 0000000000..f776df6626 --- /dev/null +++ b/app/Api/V1/Controllers/Models/Recurrence/ShowController.php @@ -0,0 +1,120 @@ +. + */ + +namespace FireflyIII\Api\V1\Controllers\Models\Recurrence; + + +use FireflyIII\Api\V1\Controllers\Controller; +use FireflyIII\Models\Recurrence; +use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; +use FireflyIII\Transformers\RecurrenceTransformer; +use FireflyIII\User; +use Illuminate\Http\JsonResponse; +use Illuminate\Pagination\LengthAwarePaginator; +use League\Fractal\Pagination\IlluminatePaginatorAdapter; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; + +/** + * Class ShowController + */ +class ShowController extends Controller +{ + private RecurringRepositoryInterface $repository; + + /** + * RecurrenceController constructor. + * + * @codeCoverageIgnore + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var User $user */ + $user = auth()->user(); + + /** @var RecurringRepositoryInterface repository */ + $this->repository = app(RecurringRepositoryInterface::class); + $this->repository->setUser($user); + + return $next($request); + } + ); + } + + /** + * List all of them. + * + * @return JsonResponse + * @codeCoverageIgnore + */ + public function index(): JsonResponse + { + $manager = $this->getManager(); + + // types to get, page size: + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + + // get list of budgets. Count it and split it. + $collection = $this->repository->getAll(); + $count = $collection->count(); + $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + // make paginator: + $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.recurrences.index') . $this->buildParams()); + + /** @var RecurrenceTransformer $transformer */ + $transformer = app(RecurrenceTransformer::class); + $transformer->setParameters($this->parameters); + + $resource = new FractalCollection($piggyBanks, $transformer, 'recurrences'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); + + } + + /** + * List single resource. + * + * @param Recurrence $recurrence + * + * @return JsonResponse + * @codeCoverageIgnore + */ + public function show(Recurrence $recurrence): JsonResponse + { + $manager = $this->getManager(); + + /** @var RecurrenceTransformer $transformer */ + $transformer = app(RecurrenceTransformer::class); + $transformer->setParameters($this->parameters); + + $resource = new Item($recurrence, $transformer, 'recurrences'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); + + + } +} \ No newline at end of file diff --git a/app/Api/V1/Controllers/Models/Recurrence/StoreController.php b/app/Api/V1/Controllers/Models/Recurrence/StoreController.php new file mode 100644 index 0000000000..af84688bf8 --- /dev/null +++ b/app/Api/V1/Controllers/Models/Recurrence/StoreController.php @@ -0,0 +1,85 @@ +. + */ + +namespace FireflyIII\Api\V1\Controllers\Models\Recurrence; + + +use FireflyIII\Api\V1\Controllers\Controller; +use FireflyIII\Api\V1\Requests\Models\Recurrence\StoreRequest; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; +use FireflyIII\Transformers\RecurrenceTransformer; +use FireflyIII\User; +use Illuminate\Http\JsonResponse; +use League\Fractal\Resource\Item; + +/** + * Class StoreController + */ +class StoreController extends Controller +{ + private RecurringRepositoryInterface $repository; + + /** + * RecurrenceController constructor. + * + * @codeCoverageIgnore + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var User $user */ + $user = auth()->user(); + + /** @var RecurringRepositoryInterface repository */ + $this->repository = app(RecurringRepositoryInterface::class); + $this->repository->setUser($user); + + return $next($request); + } + ); + } + + /** + * Store new object. + * + * @param StoreRequest $request + * + * @return JsonResponse + * @throws FireflyException + */ + public function store(StoreRequest $request): JsonResponse + { + $data = $request->getAll(); + $recurrence = $this->repository->store($data); + $manager = $this->getManager(); + + /** @var RecurrenceTransformer $transformer */ + $transformer = app(RecurrenceTransformer::class); + $transformer->setParameters($this->parameters); + + $resource = new Item($recurrence, $transformer, 'recurrences'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); + } +} \ No newline at end of file diff --git a/app/Api/V1/Controllers/Models/Recurrence/TriggerController.php b/app/Api/V1/Controllers/Models/Recurrence/TriggerController.php new file mode 100644 index 0000000000..7735076232 --- /dev/null +++ b/app/Api/V1/Controllers/Models/Recurrence/TriggerController.php @@ -0,0 +1,86 @@ +. + */ + +namespace FireflyIII\Api\V1\Controllers\Models\Recurrence; + + +use FireflyIII\Api\V1\Controllers\Controller; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; +use FireflyIII\Support\Cronjobs\RecurringCronjob; +use FireflyIII\User; +use Illuminate\Http\JsonResponse; +use Log; + +/** + * Class TriggerController + */ +class TriggerController extends Controller +{ + private RecurringRepositoryInterface $repository; + + /** + * RecurrenceController constructor. + * + * @codeCoverageIgnore + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var User $user */ + $user = auth()->user(); + + /** @var RecurringRepositoryInterface repository */ + $this->repository = app(RecurringRepositoryInterface::class); + $this->repository->setUser($user); + + return $next($request); + } + ); + } + + + /** + * @return JsonResponse + * @throws FireflyException + * @codeCoverageIgnore + * + * TODO currently unused + unreachable. + */ + public function trigger(): JsonResponse + { + /** @var RecurringCronjob $recurring */ + $recurring = app(RecurringCronjob::class); + try { + $result = $recurring->fire(); + } catch (FireflyException $e) { + Log::error($e->getMessage()); + throw new FireflyException('200022: Error in cron job.', 0, $e); + } + if (false === $result) { + return response()->json([], 204); + } + + return response()->json(); + } +} \ No newline at end of file diff --git a/app/Api/V1/Controllers/Models/Recurrence/UpdateController.php b/app/Api/V1/Controllers/Models/Recurrence/UpdateController.php new file mode 100644 index 0000000000..9f2181e785 --- /dev/null +++ b/app/Api/V1/Controllers/Models/Recurrence/UpdateController.php @@ -0,0 +1,88 @@ +. + */ + +namespace FireflyIII\Api\V1\Controllers\Models\Recurrence; + + +use FireflyIII\Api\V1\Controllers\Controller; +use FireflyIII\Api\V1\Requests\RecurrenceUpdateRequest; +use FireflyIII\Models\Recurrence; +use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; +use FireflyIII\Transformers\RecurrenceTransformer; +use FireflyIII\User; +use Illuminate\Http\JsonResponse; +use League\Fractal\Resource\Item; + +/** + * Class UpdateController + */ +class UpdateController extends Controller +{ + private RecurringRepositoryInterface $repository; + + /** + * RecurrenceController constructor. + * + * @codeCoverageIgnore + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var User $user */ + $user = auth()->user(); + + /** @var RecurringRepositoryInterface repository */ + $this->repository = app(RecurringRepositoryInterface::class); + $this->repository->setUser($user); + + return $next($request); + } + ); + } + + + + /** + * Update single recurrence. + * + * @param RecurrenceUpdateRequest $request + * @param Recurrence $recurrence + * + * @return JsonResponse + */ + public function update(RecurrenceUpdateRequest $request, Recurrence $recurrence): JsonResponse + { + $data = $request->getAll(); + $category = $this->repository->update($recurrence, $data); + $manager = $this->getManager(); + + /** @var RecurrenceTransformer $transformer */ + $transformer = app(RecurrenceTransformer::class); + $transformer->setParameters($this->parameters); + + $resource = new Item($category, $transformer, 'recurrences'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); + + } +} \ No newline at end of file diff --git a/app/Api/V1/Controllers/todo/RecurrenceController.php b/app/Api/V1/Controllers/todo/RecurrenceController.php deleted file mode 100644 index eea9ca4f56..0000000000 --- a/app/Api/V1/Controllers/todo/RecurrenceController.php +++ /dev/null @@ -1,273 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V1\Controllers; - -use FireflyIII\Api\V1\Requests\RecurrenceStoreRequest; -use FireflyIII\Api\V1\Requests\RecurrenceUpdateRequest; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Helpers\Collector\GroupCollectorInterface; -use FireflyIII\Models\Recurrence; -use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; -use FireflyIII\Support\Cronjobs\RecurringCronjob; -use FireflyIII\Support\Http\Api\TransactionFilter; -use FireflyIII\Transformers\RecurrenceTransformer; -use FireflyIII\Transformers\TransactionGroupTransformer; -use FireflyIII\User; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; -use Illuminate\Pagination\LengthAwarePaginator; -use League\Fractal\Pagination\IlluminatePaginatorAdapter; -use League\Fractal\Resource\Collection as FractalCollection; -use League\Fractal\Resource\Item; -use Log; - -/** - * Class RecurrenceController - */ -class RecurrenceController extends Controller -{ - use TransactionFilter; - - /** @var RecurringRepositoryInterface The recurring transaction repository */ - private $repository; - - - /** - * RecurrenceController constructor. - * - * @codeCoverageIgnore - */ - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - /** @var User $user */ - $user = auth()->user(); - - /** @var RecurringRepositoryInterface repository */ - $this->repository = app(RecurringRepositoryInterface::class); - $this->repository->setUser($user); - - return $next($request); - } - ); - } - - /** - * Delete the resource. - * - * @param Recurrence $recurrence - * - * @return JsonResponse - * @codeCoverageIgnore - */ - public function delete(Recurrence $recurrence): JsonResponse - { - $this->repository->destroy($recurrence); - - return response()->json([], 204); - } - - /** - * List all of them. - * - * @return JsonResponse - * @codeCoverageIgnore - */ - public function index(): JsonResponse - { - $manager = $this->getManager(); - - // types to get, page size: - $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; - - // get list of budgets. Count it and split it. - $collection = $this->repository->getAll(); - $count = $collection->count(); - $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); - - // make paginator: - $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.recurrences.index') . $this->buildParams()); - - /** @var RecurrenceTransformer $transformer */ - $transformer = app(RecurrenceTransformer::class); - $transformer->setParameters($this->parameters); - - $resource = new FractalCollection($piggyBanks, $transformer, 'recurrences'); - $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); - - return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - - } - - /** - * List single resource. - * - * @param Recurrence $recurrence - * - * @return JsonResponse - * @codeCoverageIgnore - */ - public function show(Recurrence $recurrence): JsonResponse - { - $manager = $this->getManager(); - - /** @var RecurrenceTransformer $transformer */ - $transformer = app(RecurrenceTransformer::class); - $transformer->setParameters($this->parameters); - - $resource = new Item($recurrence, $transformer, 'recurrences'); - - return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - - - } - - /** - * Store new object. - * - * @param RecurrenceStoreRequest $request - * - * @return JsonResponse - * @throws FireflyException - */ - public function store(RecurrenceStoreRequest $request): JsonResponse - { - $data = $request->getAll(); - $recurrence = $this->repository->store($data); - $manager = $this->getManager(); - - /** @var RecurrenceTransformer $transformer */ - $transformer = app(RecurrenceTransformer::class); - $transformer->setParameters($this->parameters); - - $resource = new Item($recurrence, $transformer, 'recurrences'); - - return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } - - /** - * Show transactions for this recurrence. - * - * @param Request $request - * @param Recurrence $recurrence - * - * @return JsonResponse - * @codeCoverageIgnore - */ - public function transactions(Request $request, Recurrence $recurrence): JsonResponse - { - $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; - $type = $request->get('type') ?? 'default'; - $this->parameters->set('type', $type); - - $types = $this->mapTransactionTypes($this->parameters->get('type')); - $manager = $this->getManager(); - // whatever is returned by the query, it must be part of these journals: - $journalIds = $this->repository->getJournalIds($recurrence); - - /** @var User $admin */ - $admin = auth()->user(); - - // use new group collector: - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector - ->setUser($admin) - // filter on journal IDs. - ->setJournalIds($journalIds) - // all info needed for the API: - ->withAPIInformation() - // set page size: - ->setLimit($pageSize) - // set page to retrieve - ->setPage($this->parameters->get('page')) - // set types of transactions to return. - ->setTypes($types); - - if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { - $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); - } - $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); - $transactions = $paginator->getCollection(); - - /** @var TransactionGroupTransformer $transformer */ - $transformer = app(TransactionGroupTransformer::class); - $transformer->setParameters($this->parameters); - - $resource = new FractalCollection($transactions, $transformer, 'transactions'); - $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); - - return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } - - /** - * @return JsonResponse - * @throws FireflyException - * @codeCoverageIgnore - */ - public function trigger(): JsonResponse - { - /** @var RecurringCronjob $recurring */ - $recurring = app(RecurringCronjob::class); - try { - $result = $recurring->fire(); - } catch (FireflyException $e) { - Log::error($e->getMessage()); - throw new FireflyException('200022: Error in cron job.', 0, $e); - } - if (false === $result) { - return response()->json([], 204); - } - - return response()->json(); - } - - /** - * Update single recurrence. - * - * @param RecurrenceUpdateRequest $request - * @param Recurrence $recurrence - * - * @return JsonResponse - */ - public function update(RecurrenceUpdateRequest $request, Recurrence $recurrence): JsonResponse - { - $data = $request->getAll(); - $category = $this->repository->update($recurrence, $data); - $manager = $this->getManager(); - - /** @var RecurrenceTransformer $transformer */ - $transformer = app(RecurrenceTransformer::class); - $transformer->setParameters($this->parameters); - - $resource = new Item($category, $transformer, 'recurrences'); - - return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - - } -} diff --git a/app/Api/V1/Requests/todo/RecurrenceStoreRequest.php b/app/Api/V1/Requests/Models/Recurrence/StoreRequest.php similarity index 97% rename from app/Api/V1/Requests/todo/RecurrenceStoreRequest.php rename to app/Api/V1/Requests/Models/Recurrence/StoreRequest.php index f9c880bac1..2fd320eaed 100644 --- a/app/Api/V1/Requests/todo/RecurrenceStoreRequest.php +++ b/app/Api/V1/Requests/Models/Recurrence/StoreRequest.php @@ -1,7 +1,7 @@ (int) $piggyBank->order, 'active' => true, 'notes' => $notes, - 'object_group_id' => (string) $objectGroupId, + 'object_group_id' => $objectGroupId ? (string)$objectGroupId : null, 'object_group_order' => $objectGroupOrder, 'object_group_title' => $objectGroupTitle, 'links' => [ diff --git a/app/Transformers/RecurrenceTransformer.php b/app/Transformers/RecurrenceTransformer.php index 7ac33c0847..6f794758e9 100644 --- a/app/Transformers/RecurrenceTransformer.php +++ b/app/Transformers/RecurrenceTransformer.php @@ -42,14 +42,10 @@ use Log; */ class RecurrenceTransformer extends AbstractTransformer { - /** @var BudgetRepositoryInterface */ - private $budgetRepos; - /** @var CategoryFactory */ - private $factory; - /** @var PiggyBankRepositoryInterface */ - private $piggyRepos; - /** @var RecurringRepositoryInterface */ - private $repository; + private BudgetRepositoryInterface $budgetRepos; + private CategoryFactory $factory; + private PiggyBankRepositoryInterface $piggyRepos; + private RecurringRepositoryInterface $repository; /** * RecurrenceTransformer constructor. @@ -86,9 +82,10 @@ class RecurrenceTransformer extends AbstractTransformer $notes = $this->repository->getNoteText($recurrence); $reps = 0 === (int)$recurrence->repetitions ? null : (int)$recurrence->repetitions; Log::debug('Get basic data.'); + // basic data. return [ - 'id' => (int)$recurrence->id, + 'id' => (string)$recurrence->id, 'created_at' => $recurrence->created_at->toAtomString(), 'updated_at' => $recurrence->updated_at->toAtomString(), 'type' => $shortType, @@ -127,13 +124,13 @@ class RecurrenceTransformer extends AbstractTransformer /** @var RecurrenceRepetition $repetition */ foreach ($recurrence->recurrenceRepetitions as $repetition) { $repetitionArray = [ - 'id' => (int) $repetition->id, + 'id' => (string)$repetition->id, 'created_at' => $repetition->created_at->toAtomString(), 'updated_at' => $repetition->updated_at->toAtomString(), 'type' => $repetition->repetition_type, 'moment' => $repetition->repetition_moment, - 'skip' => (int) $repetition->repetition_skip, - 'weekend' => (int) $repetition->weekend, + 'skip' => (int)$repetition->repetition_skip, + 'weekend' => (int)$repetition->weekend, 'description' => $this->repository->repetitionDescription($repetition), 'occurrences' => [], ]; @@ -182,21 +179,21 @@ class RecurrenceTransformer extends AbstractTransformer case 'piggy_bank_id': $piggy = $this->piggyRepos->findNull((int)$transactionMeta->value); if (null !== $piggy) { - $array['piggy_bank_id'] = (int) $piggy->id; + $array['piggy_bank_id'] = (string)$piggy->id; $array['piggy_bank_name'] = $piggy->name; } break; case 'category_name': $category = $this->factory->findOrCreate(null, $transactionMeta->value); if (null !== $category) { - $array['category_id'] = (int) $category->id; + $array['category_id'] = (string)$category->id; $array['category_name'] = $category->name; } break; case 'budget_id': $budget = $this->budgetRepos->findNull((int)$transactionMeta->value); if (null !== $budget) { - $array['budget_id'] = (int) $budget->id; + $array['budget_id'] = (string)$budget->id; $array['budget_name'] = $budget->name; } break; @@ -227,10 +224,10 @@ class RecurrenceTransformer extends AbstractTransformer $foreignCurrencyDp = null; $foreignCurrencyId = null; if (null !== $transaction->foreign_currency_id) { - $foreignCurrencyId = (int) $transaction->foreign_currency_id; + $foreignCurrencyId = (int)$transaction->foreign_currency_id; $foreignCurrencyCode = $transaction->foreignCurrency->code; $foreignCurrencySymbol = $transaction->foreignCurrency->symbol; - $foreignCurrencyDp = (int) $transaction->foreignCurrency->decimal_places; + $foreignCurrencyDp = (int)$transaction->foreignCurrency->decimal_places; } // source info: @@ -240,7 +237,7 @@ class RecurrenceTransformer extends AbstractTransformer $sourceIban = null; if (null !== $sourceAccount) { $sourceName = $sourceAccount->name; - $sourceId = (int) $sourceAccount->id; + $sourceId = (int)$sourceAccount->id; $sourceType = $sourceAccount->accountType->type; $sourceIban = $sourceAccount->iban; } @@ -250,31 +247,31 @@ class RecurrenceTransformer extends AbstractTransformer $destinationIban = null; if (null !== $destinationAccount) { $destinationName = $destinationAccount->name; - $destinationId = (int) $destinationAccount->id; + $destinationId = (int)$destinationAccount->id; $destinationType = $destinationAccount->accountType->type; $destinationIban = $destinationAccount->iban; } - $amount = number_format((float) $transaction->amount, $transaction->transactionCurrency->decimal_places, '.', ''); + $amount = number_format((float)$transaction->amount, $transaction->transactionCurrency->decimal_places, '.', ''); $foreignAmount = null; if (null !== $transaction->foreign_currency_id && null !== $transaction->foreign_amount) { - $foreignAmount = number_format((float) $transaction->foreign_amount, $foreignCurrencyDp, '.', ''); + $foreignAmount = number_format((float)$transaction->foreign_amount, $foreignCurrencyDp, '.', ''); } $transactionArray = [ - 'currency_id' => (int) $transaction->transaction_currency_id, + 'currency_id' => (string)$transaction->transaction_currency_id, 'currency_code' => $transaction->transactionCurrency->code, 'currency_symbol' => $transaction->transactionCurrency->symbol, - 'currency_decimal_places' => (int) $transaction->transactionCurrency->decimal_places, - 'foreign_currency_id' => $foreignCurrencyId, + 'currency_decimal_places' => (int)$transaction->transactionCurrency->decimal_places, + 'foreign_currency_id' => null === $foreignCurrencyId ? null : (string)$foreignCurrencyId, 'foreign_currency_code' => $foreignCurrencyCode, 'foreign_currency_symbol' => $foreignCurrencySymbol, 'foreign_currency_decimal_places' => $foreignCurrencyDp, - 'source_id' => $sourceId, + 'source_id' => (string)$sourceId, 'source_name' => $sourceName, 'source_iban' => $sourceIban, 'source_type' => $sourceType, - 'destination_id' => $destinationId, + 'destination_id' => (string)$destinationId, 'destination_name' => $destinationName, 'destination_iban' => $destinationIban, 'destination_type' => $destinationType, diff --git a/app/Validation/RecurrenceValidation.php b/app/Validation/RecurrenceValidation.php index 83d6b8fd79..6a067d26e4 100644 --- a/app/Validation/RecurrenceValidation.php +++ b/app/Validation/RecurrenceValidation.php @@ -96,7 +96,7 @@ trait RecurrenceValidation $data = $validator->getData(); $repetitions = $data['repetitions'] ?? []; // need at least one transaction - if (0 === count($repetitions)) { + if (!is_countable($repetitions) || 0 === count($repetitions)) { $validator->errors()->add('repetitions', (string)trans('validation.at_least_one_repetition')); } } @@ -144,11 +144,20 @@ trait RecurrenceValidation { $data = $validator->getData(); $repetitions = $data['repetitions'] ?? []; + if (!is_array($repetitions)) { + $validator->errors()->add(sprintf('repetitions.%d.type', 0), (string)trans('validation.valid_recurrence_rep_type')); + + return; + } /** * @var int $index * @var array $repetition */ foreach ($repetitions as $index => $repetition) { + if(null === $repetition['moment']) { + $repetition['moment'] = ''; + } + $repetition['moment'] = $repetition['moment'] ?? 'invalid'; switch ($repetition['type'] ?? 'empty') { default: $validator->errors()->add(sprintf('repetitions.%d.type', $index), (string)trans('validation.valid_recurrence_rep_type')); diff --git a/routes/api.php b/routes/api.php index e705fc8580..f0aaa1dd65 100644 --- a/routes/api.php +++ b/routes/api.php @@ -287,31 +287,6 @@ Route::group( } ); - - - - - - - - - - - - - - - - - - - - - - - - - // Piggy Bank API routes: Route::group( ['namespace' => 'FireflyIII\Api\V1\Controllers\Models\PiggyBank', 'prefix' => 'piggy_banks', @@ -329,6 +304,23 @@ Route::group( } ); +// Recurrence API routes: +Route::group( + ['namespace' => 'FireflyIII\Api\V1\Controllers\Models\Recurrence', 'prefix' => 'recurrences', + 'as' => 'api.v1.recurrences.',], + static function () { + + Route::get('', ['uses' => 'ShowController@index', 'as' => 'index']); + Route::post('', ['uses' => 'StoreController@store', 'as' => 'store']); + Route::get('{recurrence}', ['uses' => 'ShowController@show', 'as' => 'show']); + Route::put('{recurrence}', ['uses' => 'UpdateController@update', 'as' => 'update']); + Route::delete('{recurrence}', ['uses' => 'DestroyController@destroy', 'as' => 'delete']); + + Route::get('{recurrence}/transactions', ['uses' => 'ListController@transactions', 'as' => 'transactions']); + // TODO + Route::post('trigger', ['uses' => 'RecurrenceController@trigger', 'as' => 'trigger']); + } +); @@ -467,55 +459,40 @@ Route::group( // Route::get('{linkType}/transactions', ['uses' => 'LinkTypeController@transactions', 'as' => 'transactions']); // } //); +// +//// TODO VERIFY API DOCS +//Route::group( +// ['namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'transaction_links', +// 'as' => 'api.v1.transaction_links.',], +// static function () { +// +// // Transaction Links API routes: +// Route::get('', ['uses' => 'TransactionLinkController@index', 'as' => 'index']); +// Route::post('', ['uses' => 'TransactionLinkController@store', 'as' => 'store']); +// Route::get('{journalLink}', ['uses' => 'TransactionLinkController@show', 'as' => 'show']); +// Route::put('{journalLink}', ['uses' => 'TransactionLinkController@update', 'as' => 'update']); +// Route::delete('{journalLink}', ['uses' => 'TransactionLinkController@delete', 'as' => 'delete']); +// } +//); -// TODO VERIFY API DOCS -Route::group( - ['namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'transaction_links', - 'as' => 'api.v1.transaction_links.',], - static function () { - - // Transaction Links API routes: - Route::get('', ['uses' => 'TransactionLinkController@index', 'as' => 'index']); - Route::post('', ['uses' => 'TransactionLinkController@store', 'as' => 'store']); - Route::get('{journalLink}', ['uses' => 'TransactionLinkController@show', 'as' => 'show']); - Route::put('{journalLink}', ['uses' => 'TransactionLinkController@update', 'as' => 'update']); - Route::delete('{journalLink}', ['uses' => 'TransactionLinkController@delete', 'as' => 'delete']); - } -); +// +// +//// TODO VERIFY API DOCS +//Route::group( +// ['namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'preferences', +// 'as' => 'api.v1.preferences.',], +// static function () { +// +// // Preference API routes: +// Route::get('', ['uses' => 'PreferenceController@index', 'as' => 'index']); +// Route::get('date-ranges', ['uses' => 'Preferences\IndexController@dateRanges', 'as' => 'date-ranges']); +// Route::get('{preference}', ['uses' => 'PreferenceController@show', 'as' => 'show']); +// Route::put('{preference}', ['uses' => 'PreferenceController@update', 'as' => 'update']); +// } +//); -// TODO VERIFY API DOCS -Route::group( - ['namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'preferences', - 'as' => 'api.v1.preferences.',], - static function () { - - // Preference API routes: - Route::get('', ['uses' => 'PreferenceController@index', 'as' => 'index']); - Route::get('date-ranges', ['uses' => 'Preferences\IndexController@dateRanges', 'as' => 'date-ranges']); - Route::get('{preference}', ['uses' => 'PreferenceController@show', 'as' => 'show']); - Route::put('{preference}', ['uses' => 'PreferenceController@update', 'as' => 'update']); - } -); - -// TODO VERIFY API DOCS -Route::group( - ['namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'recurrences', - 'as' => 'api.v1.recurrences.',], - static function () { - - // Recurrence API routes: - Route::get('', ['uses' => 'RecurrenceController@index', 'as' => 'index']); - Route::post('', ['uses' => 'RecurrenceController@store', 'as' => 'store']); - Route::post('trigger', ['uses' => 'RecurrenceController@trigger', 'as' => 'trigger']); - Route::get('{recurrence}', ['uses' => 'RecurrenceController@show', 'as' => 'show']); - Route::put('{recurrence}', ['uses' => 'RecurrenceController@update', 'as' => 'update']); - Route::delete('{recurrence}', ['uses' => 'RecurrenceController@delete', 'as' => 'delete']); - Route::get('{recurrence}/transactions', ['uses' => 'RecurrenceController@transactions', 'as' => 'transactions']); - } -); - // TODO VERIFY API DOCS Route::group( ['namespace' => 'FireflyIII\Api\V1\Controllers', 'prefix' => 'rules',