diff --git a/app/Api/V1/Controllers/AccountController.php b/app/Api/V1/Controllers/AccountController.php index 0108417d24..c650a89410 100644 --- a/app/Api/V1/Controllers/AccountController.php +++ b/app/Api/V1/Controllers/AccountController.php @@ -218,7 +218,7 @@ class AccountController extends Controller } /** - * Show all transactions. + * Show all transaction groups related to the account. * * @param Request $request * @param Account $account diff --git a/app/Api/V1/Controllers/ImportController.php b/app/Api/V1/Controllers/ImportController.php index cc3fc4f0f3..ea7ad487ea 100644 --- a/app/Api/V1/Controllers/ImportController.php +++ b/app/Api/V1/Controllers/ImportController.php @@ -29,7 +29,6 @@ use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\ImportJobTransformer; use FireflyIII\Transformers\TransactionGroupTransformer; -use FireflyIII\Transformers\TransactionTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; diff --git a/app/Api/V1/Controllers/SummaryController.php b/app/Api/V1/Controllers/SummaryController.php index 4c1770a432..7380d42596 100644 --- a/app/Api/V1/Controllers/SummaryController.php +++ b/app/Api/V1/Controllers/SummaryController.php @@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers; use Carbon\Carbon; +use Exception; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Report\NetWorthInterface; @@ -179,20 +180,15 @@ class SummaryController extends Controller // set types of transactions to return. ->setTypes([TransactionType::DEPOSIT]); - // TODO possible candidate for getExtractedGroups - $set = $collector->getGroups(); + $set = $collector->getExtractedJournals(); + /** @var array $transactionJournal */ + foreach ($set as $transactionJournal) { - /** @var array $group */ - foreach ($set as $group) { - /** @var array $transaction */ - foreach ($group['transactions'] as $transaction) { - - $currencyId = (int)$transaction['currency_id']; - $incomes[$currencyId] = $incomes[$currencyId] ?? '0'; - $incomes[$currencyId] = bcadd($incomes[$currencyId], bcmul($transaction['amount'], '-1')); - $sums[$currencyId] = $sums[$currencyId] ?? '0'; - $sums[$currencyId] = bcadd($sums[$currencyId], bcmul($transaction['amount'], '-1')); - } + $currencyId = (int)$transactionJournal['currency_id']; + $incomes[$currencyId] = $incomes[$currencyId] ?? '0'; + $incomes[$currencyId] = bcadd($incomes[$currencyId], bcmul($transactionJournal['amount'], '-1')); + $sums[$currencyId] = $sums[$currencyId] ?? '0'; + $sums[$currencyId] = bcadd($sums[$currencyId], bcmul($transactionJournal['amount'], '-1')); } // collect expenses of user using the new group collector. @@ -205,19 +201,16 @@ class SummaryController extends Controller // set types of transactions to return. ->setTypes([TransactionType::WITHDRAWAL]); - $set = $collector->getGroups(); - /** @var array $group */ - foreach ($set as $group) { - /** @var array $transaction */ - foreach ($group['transactions'] as $transaction) { + $set = $collector->getExtractedJournals(); - $currencyId = (int)$transaction['currency_id']; - $expenses[$currencyId] = $expenses[$currencyId] ?? '0'; - $expenses[$currencyId] = bcadd($expenses[$currencyId], $transaction['amount']); - $sums[$currencyId] = $sums[$currencyId] ?? '0'; - $sums[$currencyId] = bcadd($sums[$currencyId], $transaction['amount']); - } + /** @var array $transactionJournal */ + foreach ($set as $transactionJournal) { + $currencyId = (int)$transactionJournal['currency_id']; + $expenses[$currencyId] = $expenses[$currencyId] ?? '0'; + $expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']); + $sums[$currencyId] = $sums[$currencyId] ?? '0'; + $sums[$currencyId] = bcadd($sums[$currencyId], $transactionJournal['amount']); } // format amounts: @@ -333,6 +326,7 @@ class SummaryController extends Controller * @param Carbon $end * * @return array + * @throws Exception */ private function getLeftToSpendInfo(Carbon $start, Carbon $end): array { diff --git a/app/Api/V1/Controllers/TagController.php b/app/Api/V1/Controllers/TagController.php index 3b4f92db49..0d02227222 100644 --- a/app/Api/V1/Controllers/TagController.php +++ b/app/Api/V1/Controllers/TagController.php @@ -26,14 +26,12 @@ namespace FireflyIII\Api\V1\Controllers; use Carbon\Carbon; use FireflyIII\Api\V1\Requests\TagRequest; use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Helpers\Collector\TransactionCollectorInterface; -use FireflyIII\Helpers\Filter\InternalTransferFilter; +use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Models\Tag; -use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\TagTransformer; -use FireflyIII\Transformers\TransactionTransformer; +use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -242,28 +240,32 @@ class TagController extends Controller /** @var User $admin */ $admin = auth()->user(); - /** @var TransactionCollectorInterface $collector */ - $collector = app(TransactionCollectorInterface::class); - $collector->setUser($admin); - $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); - $collector->setAllAssetAccounts(); - $collector->setTag($tag); - if (\in_array(TransactionType::TRANSFER, $types, true)) { - $collector->removeFilter(InternalTransferFilter::class); - } + // use new group collector: + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector + ->setUser($admin) + // filter on tag. + ->setTag($tag) + // 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')); } - $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); - $collector->setTypes($types); - $paginator = $collector->getPaginatedTransactions(); + $paginator = $collector->getPaginatedGroups(); $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); $transactions = $paginator->getCollection(); - /** @var TransactionTransformer $transformer */ - $transformer = app(TransactionTransformer::class); + /** @var TransactionGroupTransformer $transformer */ + $transformer = app(TransactionGroupTransformer::class); $transformer->setParameters($this->parameters); $resource = new FractalCollection($transactions, $transformer, 'transactions'); diff --git a/app/Api/V1/Controllers/TransactionController.php b/app/Api/V1/Controllers/TransactionController.php index a00438536b..5a11a5e706 100644 --- a/app/Api/V1/Controllers/TransactionController.php +++ b/app/Api/V1/Controllers/TransactionController.php @@ -25,28 +25,28 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers; use FireflyIII\Api\V1\Requests\TransactionRequest; +use FireflyIII\Events\StoredTransactionGroup; use FireflyIII\Events\StoredTransactionJournal; +use FireflyIII\Events\UpdatedTransactionGroup; use FireflyIII\Events\UpdatedTransactionJournal; use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Helpers\Collector\TransactionCollectorInterface; -use FireflyIII\Helpers\Filter\InternalTransferFilter; -use FireflyIII\Helpers\Filter\NegativeAmountFilter; -use FireflyIII\Helpers\Filter\PositiveAmountFilter; -use FireflyIII\Models\Transaction; -use FireflyIII\Models\TransactionType; +use FireflyIII\Helpers\Collector\GroupCollectorInterface; +use FireflyIII\Models\TransactionGroup; +use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\AttachmentTransformer; use FireflyIII\Transformers\PiggyBankEventTransformer; -use FireflyIII\Transformers\TransactionTransformer; +use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use Illuminate\Support\Collection; use League\Fractal\Manager; use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class TransactionController @@ -80,18 +80,18 @@ class TransactionController extends Controller } /** - * @param Request $request - * @param Transaction $transaction + * @param Request $request + * @param TransactionJournal $transactionJournal * * @return JsonResponse */ - public function attachments(Request $request, Transaction $transaction): JsonResponse + public function attachments(Request $request, TransactionJournal $transactionJournal): JsonResponse { $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - $attachments = $this->repository->getAttachmentsByTr($transaction); + $attachments = $this->repository->getAttachments($transactionJournal); /** @var AttachmentTransformer $transformer */ $transformer = app(AttachmentTransformer::class); @@ -106,14 +106,27 @@ class TransactionController extends Controller /** * Remove the specified resource from storage. * - * @param \FireflyIII\Models\Transaction $transaction + * @param TransactionGroup $transactionGroup * * @return JsonResponse */ - public function delete(Transaction $transaction): JsonResponse + public function delete(TransactionGroup $transactionGroup): JsonResponse { - $journal = $transaction->transactionJournal; - $this->repository->destroy($journal); + $this->repository->destroyGroup($transactionGroup); + + return response()->json([], 204); + } + + /** + * Remove the specified resource from storage. + * + * @param TransactionJournal $transactionJournal + * + * @return JsonResponse + */ + public function deleteJournal(TransactionJournal $transactionJournal): JsonResponse + { + $this->repository->destroyJournal($transactionJournal); return response()->json([], 204); } @@ -138,27 +151,31 @@ class TransactionController extends Controller /** @var User $admin */ $admin = auth()->user(); - /** @var TransactionCollectorInterface $collector */ - $collector = app(TransactionCollectorInterface::class); - $collector->setUser($admin); - $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); - $collector->setAllAssetAccounts(); - if (\in_array(TransactionType::TRANSFER, $types, true)) { - $collector->removeFilter(InternalTransferFilter::class); - } + // use new group collector: + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector + ->setUser($admin) + // 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')); } - $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); - $collector->setTypes($types); - $paginator = $collector->getPaginatedTransactions(); + $paginator = $collector->getPaginatedGroups(); $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); $transactions = $paginator->getCollection(); - /** @var TransactionTransformer $transformer */ - $transformer = app(TransactionTransformer::class); + /** @var TransactionGroupTransformer $transformer */ + $transformer = app(TransactionGroupTransformer::class); $transformer->setParameters($this->parameters); $resource = new FractalCollection($transactions, $transformer, 'transactions'); @@ -168,18 +185,18 @@ class TransactionController extends Controller } /** - * @param Request $request - * @param Transaction $transaction + * @param Request $request + * @param TransactionJournal $transactionJournal * * @return JsonResponse */ - public function piggyBankEvents(Request $request, Transaction $transaction): JsonResponse + public function piggyBankEvents(Request $request, TransactionJournal $transactionJournal): JsonResponse { $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - $events = $this->repository->getPiggyBankEventsbyTr($transaction); + $events = $this->repository->getPiggyBankEvents($transactionJournal); /** @var PiggyBankEventTransformer $transformer */ $transformer = app(PiggyBankEventTransformer::class); @@ -194,38 +211,37 @@ class TransactionController extends Controller /** * Show a single transaction. * - * @param Request $request - * @param Transaction $transaction + * @param Request $request + * @param TransactionGroup $transactionGroup * * @return JsonResponse */ - public function show(Request $request, Transaction $transaction): JsonResponse + public function show(Request $request, TransactionGroup $transactionGroup): JsonResponse { $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - // collect transactions using the journal collector - $collector = app(TransactionCollectorInterface::class); - $collector->setUser(auth()->user()); - $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); - // filter on specific journals. - $collector->setJournals(new Collection([$transaction->transactionJournal])); + /** @var User $admin */ + $admin = auth()->user(); + // use new group collector: + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector + ->setUser($admin) + // filter on transaction group. + ->setTransactionGroup($transactionGroup) + // all info needed for the API: + ->withAPIInformation(); - // add filter to remove transactions: - $transactionType = $transaction->transactionJournal->transactionType->type; - if ($transactionType === TransactionType::WITHDRAWAL) { - $collector->addFilter(PositiveAmountFilter::class); + $selectedGroup = $collector->getGroups()->first(); + if (null === $selectedGroup) { + throw new NotFoundHttpException(); } - if (!($transactionType === TransactionType::WITHDRAWAL)) { - $collector->addFilter(NegativeAmountFilter::class); // @codeCoverageIgnore - } - - $transactions = $collector->getTransactions(); - /** @var TransactionTransformer $transformer */ - $transformer = app(TransactionTransformer::class); + /** @var TransactionGroupTransformer $transformer */ + $transformer = app(TransactionGroupTransformer::class); $transformer->setParameters($this->parameters); - $resource = new FractalCollection($transactions, $transformer, 'transactions'); + $resource = new Item($selectedGroup, $transformer, 'transactions'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); } @@ -236,45 +252,43 @@ class TransactionController extends Controller * @param TransactionRequest $request * * @param JournalRepositoryInterface $repository + * TODO refactor me. * * @throws FireflyException * @return JsonResponse */ public function store(TransactionRequest $request, JournalRepositoryInterface $repository): JsonResponse { - $data = $request->getAll(); - $data['user'] = auth()->user()->id; - $journal = $repository->store($data); + $data = $request->getAll(); + $data['user'] = auth()->user()->id; + $transactionGroup = $repository->store($data); - event(new StoredTransactionJournal($journal)); + event(new StoredTransactionGroup($transactionGroup)); $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - // collect transactions using the journal collector - $collector = app(TransactionCollectorInterface::class); - $collector->setUser(auth()->user()); - $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); - // filter on specific journals. - $collector->setJournals(new Collection([$journal])); + /** @var User $admin */ + $admin = auth()->user(); + // use new group collector: + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector + ->setUser($admin) + // filter on transaction group. + ->setTransactionGroup($transactionGroup) + // all info needed for the API: + ->withAPIInformation(); - // add filter to remove transactions: - $transactionType = $journal->transactionType->type; - if ($transactionType === TransactionType::WITHDRAWAL) { - $collector->addFilter(PositiveAmountFilter::class); + $selectedGroup = $collector->getGroups()->first(); + if (null === $selectedGroup) { + throw new NotFoundHttpException(); } - if (!($transactionType === TransactionType::WITHDRAWAL)) { - $collector->addFilter(NegativeAmountFilter::class); - } - - $transactions = $collector->getTransactions(); - - /** @var TransactionTransformer $transformer */ - $transformer = app(TransactionTransformer::class); + /** @var TransactionGroupTransformer $transformer */ + $transformer = app(TransactionGroupTransformer::class); $transformer->setParameters($this->parameters); - - $resource = new FractalCollection($transactions, $transformer, 'transactions'); + $resource = new Item($selectedGroup, $transformer, 'transactions'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); } @@ -283,47 +297,42 @@ class TransactionController extends Controller /** * Update a transaction. * - * @param TransactionRequest $request - * @param JournalRepositoryInterface $repository - * @param Transaction $transaction + * @param TransactionRequest $request + * @param TransactionGroup $transactionGroup * * @return JsonResponse */ - public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction): JsonResponse + public function update(TransactionRequest $request, TransactionGroup $transactionGroup): JsonResponse { - $data = $request->getAll(); - $data['user'] = auth()->user()->id; - $journal = $repository->update($transaction->transactionJournal, $data); - $manager = new Manager(); - $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $data = $request->getAll(); + $data['user'] = auth()->user()->id; + $transactionGroup = $this->repository->update($transactionGroup, $data); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - event(new UpdatedTransactionJournal($journal)); + event(new UpdatedTransactionGroup($transactionGroup)); - // needs a lot of extra data to match the journal collector. Or just expand that one. - // collect transactions using the journal collector - $collector = app(TransactionCollectorInterface::class); - $collector->setUser(auth()->user()); - $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); - // filter on specific journals. - $collector->setJournals(new Collection([$journal])); + /** @var User $admin */ + $admin = auth()->user(); + // use new group collector: + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector + ->setUser($admin) + // filter on transaction group. + ->setTransactionGroup($transactionGroup) + // all info needed for the API: + ->withAPIInformation(); - // add filter to remove transactions: - $transactionType = $journal->transactionType->type; - if ($transactionType === TransactionType::WITHDRAWAL) { - $collector->addFilter(PositiveAmountFilter::class); + $selectedGroup = $collector->getGroups()->first(); + if (null === $selectedGroup) { + throw new NotFoundHttpException(); } - if (!($transactionType === TransactionType::WITHDRAWAL)) { - $collector->addFilter(NegativeAmountFilter::class); - } - - $transactions = $collector->getTransactions(); - - /** @var TransactionTransformer $transformer */ - $transformer = app(TransactionTransformer::class); + /** @var TransactionGroupTransformer $transformer */ + $transformer = app(TransactionGroupTransformer::class); $transformer->setParameters($this->parameters); - - $resource = new FractalCollection($transactions, $transformer, 'transactions'); + $resource = new Item($selectedGroup, $transformer, 'transactions'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); diff --git a/app/Events/StoredTransactionGroup.php b/app/Events/StoredTransactionGroup.php new file mode 100644 index 0000000000..83c82b181b --- /dev/null +++ b/app/Events/StoredTransactionGroup.php @@ -0,0 +1,51 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Events; + +use FireflyIII\Models\TransactionGroup; +use Illuminate\Queue\SerializesModels; + +/** + * Class StoredTransactionGroup. + * + * @codeCoverageIgnore + */ +class StoredTransactionGroup extends Event +{ + use SerializesModels; + + /** @var TransactionGroup The group that was stored. */ + public $transactionGroup; + + /** + * Create a new event instance. + * + * @param TransactionGroup $transactionGroup + */ + public function __construct(TransactionGroup $transactionGroup) + { + $this->transactionGroup = $transactionGroup; + } +} diff --git a/app/Events/StoredTransactionJournal.php b/app/Events/StoredTransactionJournal.php index c631e7b148..ed3102c045 100644 --- a/app/Events/StoredTransactionJournal.php +++ b/app/Events/StoredTransactionJournal.php @@ -24,12 +24,13 @@ declare(strict_types=1); namespace FireflyIII\Events; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionJournal; use Illuminate\Queue\SerializesModels; /** * Class StoredTransactionJournal. - * + * @deprecated * @codeCoverageIgnore */ class StoredTransactionJournal extends Event @@ -46,6 +47,7 @@ class StoredTransactionJournal extends Event */ public function __construct(TransactionJournal $journal) { + throw new FireflyException('The StoredTransactionJournal event is deprecated.'); $this->journal = $journal; } } diff --git a/app/Events/UpdatedTransactionGroup.php b/app/Events/UpdatedTransactionGroup.php new file mode 100644 index 0000000000..8d1c3ff647 --- /dev/null +++ b/app/Events/UpdatedTransactionGroup.php @@ -0,0 +1,52 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Events; + +use FireflyIII\Models\TransactionGroup; +use FireflyIII\Models\TransactionJournal; +use Illuminate\Queue\SerializesModels; + +/** + * Class UpdatedTransactionGroup. + * @codeCoverageIgnore + * + */ +class UpdatedTransactionGroup extends Event +{ + use SerializesModels; + + /** @var TransactionGroup The group that was stored. */ + public $transactionGroup; + + /** + * Create a new event instance. + * + * @param TransactionGroup $transactionGroup + */ + public function __construct(TransactionGroup $transactionGroup) + { + $this->transactionGroup = $transactionGroup; + } +} diff --git a/app/Events/UpdatedTransactionJournal.php b/app/Events/UpdatedTransactionJournal.php index 3d3ef2fff6..dc120035d5 100644 --- a/app/Events/UpdatedTransactionJournal.php +++ b/app/Events/UpdatedTransactionJournal.php @@ -29,7 +29,7 @@ use Illuminate\Queue\SerializesModels; /** * Class UpdatedTransactionJournal. - * + * @deprecated * @codeCoverageIgnore * */ @@ -47,6 +47,7 @@ class UpdatedTransactionJournal extends Event */ public function __construct(TransactionJournal $journal) { + throw new FireflyException('The UpdatedTransactionJournal event is deprecated.'); $this->journal = $journal; } } diff --git a/app/Helpers/Collector/GroupCollector.php b/app/Helpers/Collector/GroupCollector.php index ccf79de342..e4a2dbe4ea 100644 --- a/app/Helpers/Collector/GroupCollector.php +++ b/app/Helpers/Collector/GroupCollector.php @@ -118,6 +118,25 @@ class GroupCollector implements GroupCollectorInterface ]; } + /** + * Return the transaction journals without group information. Is useful in some instances. + * + * @return array + */ + public function getExtractedJournals(): array + { + $selection = $this->getGroups(); + $return = new Collection; + /** @var array $group */ + foreach ($selection as $group) { + foreach ($group['transactions'] as $journalId => $journal) { + $return[$journalId] = $journal; + } + } + + return $return; + } + /** * Return the groups. * @@ -339,6 +358,18 @@ class GroupCollector implements GroupCollectorInterface return $this; } + /** + * Limit the search to one specific transaction group. + * + * @param TransactionGroup $transactionGroup + * + * @return GroupCollectorInterface + */ + public function setTransactionGroup(TransactionGroup $transactionGroup): GroupCollectorInterface + { + $this->query->where('transaction_groups.id', $transactionGroup->id); + } + /** * Limit the included transaction types. * diff --git a/app/Helpers/Collector/GroupCollectorInterface.php b/app/Helpers/Collector/GroupCollectorInterface.php index dca9c4a62a..09fb4acbf7 100644 --- a/app/Helpers/Collector/GroupCollectorInterface.php +++ b/app/Helpers/Collector/GroupCollectorInterface.php @@ -29,6 +29,7 @@ use FireflyIII\Models\Budget; use FireflyIII\Models\Category; use FireflyIII\Models\Tag; use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Models\TransactionGroup; use FireflyIII\User; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; @@ -38,6 +39,13 @@ use Illuminate\Support\Collection; */ interface GroupCollectorInterface { + /** + * Return the transaction journals without group information. Is useful in some instances. + * + * @return array + */ + public function getExtractedJournals(): array; + /** * Return the groups. * @@ -106,6 +114,15 @@ interface GroupCollectorInterface */ public function setCurrency(TransactionCurrency $currency): GroupCollectorInterface; + /** + * Limit the result to a set of specific journals. + * + * @param array $journalIds + * + * @return GroupCollectorInterface + */ + public function setJournalIds(array $journalIds): GroupCollectorInterface; + /** * Limit the number of returned entries. * @@ -124,15 +141,6 @@ interface GroupCollectorInterface */ public function setPage(int $page): GroupCollectorInterface; - /** - * Limit the result to a set of specific journals. - * - * @param array $journalIds - * - * @return GroupCollectorInterface - */ - public function setJournalIds(array $journalIds): GroupCollectorInterface; - /** * Set the start and end time of the results to return. * @@ -152,6 +160,15 @@ interface GroupCollectorInterface */ public function setTag(Tag $tag): GroupCollectorInterface; + /** + * Limit the search to one specific transaction group. + * + * @param TransactionGroup $transactionGroup + * + * @return GroupCollectorInterface + */ + public function setTransactionGroup(TransactionGroup $transactionGroup): GroupCollectorInterface; + /** * Limit the included transaction types. * diff --git a/app/Http/Controllers/Transaction/SingleController.php b/app/Http/Controllers/Transaction/SingleController.php index bbf82c8737..558a2be813 100644 --- a/app/Http/Controllers/Transaction/SingleController.php +++ b/app/Http/Controllers/Transaction/SingleController.php @@ -288,11 +288,6 @@ class SingleController extends Controller return redirect(route('accounts.reconcile.edit', [$journal->id])); } - // redirect to split edit: - if ($this->isSplitJournal($journal)) { - return redirect(route('transactions.split.edit', [$journal->id])); - } - $what = strtolower($transactionType); $budgetList = app('expandedform')->makeSelectListWithEmpty($this->budgets->getBudgets()); diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 5906f25503..4a854b5e49 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -27,7 +27,6 @@ use DB; use Exception; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\TransactionJournalFactory; -use FireflyIII\Factory\TransactionJournalMetaFactory; use FireflyIII\Helpers\Collector\TransactionCollectorInterface; use FireflyIII\Helpers\Filter\InternalTransferFilter; use FireflyIII\Models\Account; @@ -35,11 +34,13 @@ use FireflyIII\Models\AccountType; use FireflyIII\Models\Note; use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournalLink; use FireflyIII\Models\TransactionJournalMeta; use FireflyIII\Models\TransactionType; use FireflyIII\Services\Internal\Destroy\JournalDestroyService; +use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService; use FireflyIII\Services\Internal\Update\JournalUpdateService; use FireflyIII\Support\CacheProperties; use FireflyIII\User; @@ -136,29 +137,25 @@ class JournalRepository implements JournalRepositoryInterface } /** - * @param TransactionJournal $journal + * @param TransactionGroup $transactionGroup * - * @return int */ - public function countTransactions(TransactionJournal $journal): int + public function destroyGroup(TransactionGroup $transactionGroup): void { - return $journal->transactions()->count(); + /** @var TransactionGroupDestroyService $service */ + $service = app(TransactionGroupDestroyService::class); + $service->destroy($transactionGroup); } /** * @param TransactionJournal $journal * - * @return bool - * - */ - public function destroy(TransactionJournal $journal): bool + public function destroyJournal(TransactionJournal $journal): void { /** @var JournalDestroyService $service */ $service = app(JournalDestroyService::class); $service->destroy($journal); - - return true; } /** @@ -199,23 +196,6 @@ class JournalRepository implements JournalRepositoryInterface return $this->user->transactionJournals()->where('id', $journalId)->first(); } - /** - * @param Transaction $transaction - * - * @return Transaction|null - */ - public function findOpposingTransaction(Transaction $transaction): ?Transaction - { - $opposing = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->where('transaction_journals.user_id', $this->user->id) - ->where('transactions.transaction_journal_id', $transaction->transaction_journal_id) - ->where('transactions.identifier', $transaction->identifier) - ->where('amount', bcmul($transaction->amount, '-1')) - ->first(['transactions.*']); - - return $opposing; - } - /** * @param int $transactionid * @@ -278,13 +258,16 @@ class JournalRepository implements JournalRepositoryInterface } /** - * @param Transaction $transaction + * Get all attachments connected to the transaction group. + * + * @param TransactionJournal $transactionJournal * * @return Collection */ - public function getAttachmentsByTr(Transaction $transaction): Collection + public function getAttachmentsByJournal(TransactionJournal $transactionJournal): Collection { - return $transaction->transactionJournal->attachments()->get(); + // TODO: Implement getAttachmentsByJournal() method. + throw new NotImplementedException; } /** @@ -638,16 +621,6 @@ class JournalRepository implements JournalRepositoryInterface return $events; } - /** - * @param Transaction $transaction - * - * @return Collection - */ - public function getPiggyBankEventsbyTr(Transaction $transaction): Collection - { - return $transaction->transactionJournal->piggyBankEvents()->get(); - } - /** * Returns all journals with more than 2 transactions. Should only return empty collections * in Firefly III > v4.8.0. @@ -692,14 +665,6 @@ class JournalRepository implements JournalRepositoryInterface return $journal->transactionType->type; } - /** - * @return Collection - */ - public function getTransactionTypes(): Collection - { - return TransactionType::orderBy('type', 'ASC')->get(); - } - /** * @param array $transactionIds * @@ -786,29 +751,6 @@ class JournalRepository implements JournalRepositoryInterface return false; } - /** - * Set meta field for journal that contains a date. - * - * @param TransactionJournal $journal - * @param string $name - * @param Carbon $date - * - * @return void - */ - public function setMetaDate(TransactionJournal $journal, string $name, Carbon $date): void - { - /** @var TransactionJournalMetaFactory $factory */ - $factory = app(TransactionJournalMetaFactory::class); - $factory->updateOrCreate( - [ - 'data' => $date, - 'journal' => $journal, - 'name' => $name, - ] - ); - - } - /** * @param TransactionJournal $journal * @param int $order diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index 1819c16678..05eeabfd2f 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournalLink; use FireflyIII\Models\TransactionJournalMeta; @@ -36,6 +37,7 @@ use Illuminate\Support\MessageBag; /** * Interface JournalRepositoryInterface. + * TODO needs cleaning up. Remove unused methods. */ interface JournalRepositoryInterface { @@ -50,20 +52,18 @@ interface JournalRepositoryInterface public function convert(TransactionJournal $journal, TransactionType $type, Account $source, Account $destination): MessageBag; /** - * @param TransactionJournal $journal + * Deletes a transaction group. * - * @return int + * @param TransactionGroup $transactionGroup */ - public function countTransactions(TransactionJournal $journal): int; + public function destroyGroup(TransactionGroup $transactionGroup): void; /** * Deletes a journal. * * @param TransactionJournal $journal - * - * @return bool */ - public function destroy(TransactionJournal $journal): bool; + public function destroyJournal(TransactionJournal $journal): void; /** @noinspection MoreThanThreeArgumentsInspection */ @@ -86,13 +86,6 @@ interface JournalRepositoryInterface */ public function findNull(int $journalId): ?TransactionJournal; - /** - * @param Transaction $transaction - * - * @return Transaction|null - */ - public function findOpposingTransaction(Transaction $transaction): ?Transaction; - /** * @param int $transactionid * @@ -123,13 +116,6 @@ interface JournalRepositoryInterface */ public function getAttachments(TransactionJournal $journal): Collection; - /** - * @param Transaction $transaction - * - * @return Collection - */ - public function getAttachmentsByTr(Transaction $transaction): Collection; - /** * Returns the first positive transaction for the journal. Useful when editing journals. * @@ -264,13 +250,6 @@ interface JournalRepositoryInterface */ public function getPiggyBankEvents(TransactionJournal $journal): Collection; - /** - * @param Transaction $transaction - * - * @return Collection - */ - public function getPiggyBankEventsbyTr(Transaction $transaction): Collection; - /** * Returns all journals with more than 2 transactions. Should only return empty collections * in Firefly III > v4.8.0. @@ -297,11 +276,6 @@ interface JournalRepositoryInterface */ public function getTransactionType(TransactionJournal $journal): string; - /** - * @return Collection - */ - public function getTransactionTypes(): Collection; - /** * @param array $transactionIds * @@ -332,17 +306,6 @@ interface JournalRepositoryInterface */ public function reconcileById(int $transactionId): bool; - /** - * Set meta field for journal that contains a date. - * - * @param TransactionJournal $journal - * @param string $name - * @param Carbon $date - * - * @return void - */ - public function setMetaDate(TransactionJournal $journal, string $name, Carbon $date): void; - /** * @param TransactionJournal $journal * @param int $order @@ -362,15 +325,15 @@ interface JournalRepositoryInterface * @throws FireflyException * @return TransactionJournal */ - public function store(array $data): TransactionJournal; + public function store(array $data): TransactionGroup; /** - * @param TransactionJournal $journal - * @param array $data + * @param TransactionGroup $transactionGroup + * @param array $data * - * @return TransactionJournal + * @return TransactionGroup */ - public function update(TransactionJournal $journal, array $data): TransactionJournal; + public function update(TransactionGroup $transactionGroup, array $data): TransactionGroup; /** * Update budget for a journal. diff --git a/app/Services/Internal/Destroy/TransactionGroupDestroyService.php b/app/Services/Internal/Destroy/TransactionGroupDestroyService.php new file mode 100644 index 0000000000..3b732c2071 --- /dev/null +++ b/app/Services/Internal/Destroy/TransactionGroupDestroyService.php @@ -0,0 +1,52 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Destroy; + +use Exception; +use FireflyIII\Models\TransactionGroup; + +/** + * Class TransactionGroupDestroyService + */ +class TransactionGroupDestroyService +{ + + /** + * @param TransactionGroup $transactionGroup + */ + public function destroy(TransactionGroup $transactionGroup): void + { + /** @var JournalDestroyService $service */ + $service = app(JournalDestroyService::class); + foreach ($transactionGroup->transactionJournals as $journal) { + $service->destroy($journal); + } + try { + $transactionGroup->delete(); + } catch (Exception $e) { + app('log')->error(sprintf('Could not delete transaction group: %s', $e->getMessage())); // @codeCoverageIgnore + } + } + +} \ No newline at end of file diff --git a/app/Support/Http/Controllers/ModelInformation.php b/app/Support/Http/Controllers/ModelInformation.php index 658c2b8da7..60cecd60f9 100644 --- a/app/Support/Http/Controllers/ModelInformation.php +++ b/app/Support/Http/Controllers/ModelInformation.php @@ -249,22 +249,4 @@ trait ModelInformation { return TransactionType::OPENING_BALANCE === $journal->transactionType->type; } - - /** - * Checks if journal is split. - * - * @param TransactionJournal $journal - * - * @return bool - */ - protected function isSplitJournal(TransactionJournal $journal): bool // validate objects - { - /** @var JournalRepositoryInterface $repository */ - $repository = app(JournalRepositoryInterface::class); - $repository->setUser($journal->user); - $count = $repository->countTransactions($journal); - - return $count > 2; - } - } diff --git a/app/Transformers/TransactionGroupTransformer.php b/app/Transformers/TransactionGroupTransformer.php index 5428015428..abb1e3c5fb 100644 --- a/app/Transformers/TransactionGroupTransformer.php +++ b/app/Transformers/TransactionGroupTransformer.php @@ -114,6 +114,7 @@ class TransactionGroupTransformer extends AbstractTransformer $metaDateData = $this->groupRepos->getMetaDateFields((int)$row['transaction_journal_id'], $this->metaDateFields); $result[] = [ + 'transaction_journal_id' => $row['transaction_journal_id'], 'description' => $row['description'], 'date' => $row['date']->toAtomString(), 'type' => $type, diff --git a/routes/api.php b/routes/api.php index 7fd930b220..22f10efd8f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -396,11 +396,12 @@ Route::group( // Transaction API routes: Route::get('', ['uses' => 'TransactionController@index', 'as' => 'index']); Route::post('', ['uses' => 'TransactionController@store', 'as' => 'store']); - Route::get('{transaction}', ['uses' => 'TransactionController@show', 'as' => 'show']); - Route::get('{transaction}/attachments', ['uses' => 'TransactionController@attachments', 'as' => 'attachments']); - Route::get('{transaction}/piggy_bank_events', ['uses' => 'TransactionController@piggyBankEvents', 'as' => 'piggy_bank_events']); - Route::put('{transaction}', ['uses' => 'TransactionController@update', 'as' => 'update']); - Route::delete('{transaction}', ['uses' => 'TransactionController@delete', 'as' => 'delete']); + Route::get('{transactionGroup}', ['uses' => 'TransactionController@show', 'as' => 'show']); + Route::get('{transactionJournal}/attachments', ['uses' => 'TransactionController@attachments', 'as' => 'attachments']); + Route::get('{transactionJournal}/piggy_bank_events', ['uses' => 'TransactionController@piggyBankEvents', 'as' => 'piggy_bank_events']); + Route::put('{transactionGroup}', ['uses' => 'TransactionController@update', 'as' => 'update']); + Route::delete('{transactionGroup}/{transactionJournal}', ['uses' => 'TransactionController@deleteJournal', 'as' => 'delete-journal']); + Route::delete('{transactionGroup}', ['uses' => 'TransactionController@delete', 'as' => 'delete']); } );