mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 10:47:00 +00:00 
			
		
		
		
	Various code reshuffelling.
This commit is contained in:
		| @@ -277,6 +277,27 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|         return $query->get(['accounts.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttachments(Account $account): Collection | ||||
|     { | ||||
|         $set = $account->attachments()->get(); | ||||
|  | ||||
|         /** @var Storage $disk */ | ||||
|         $disk = Storage::disk('upload'); | ||||
|  | ||||
|         return $set->each( | ||||
|             static function (Attachment $attachment) use ($disk) { | ||||
|                 $notes                   = $attachment->notes()->first(); | ||||
|                 $attachment->file_exists = $disk->exists($attachment->fileName()); | ||||
|                 $attachment->notes       = $notes ? $notes->text : ''; | ||||
|  | ||||
|                 return $attachment; | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account | ||||
|      * | ||||
| @@ -293,6 +314,38 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|         return $factory->findOrCreate('Cash account', $type->type); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $types | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getInactiveAccountsByType(array $types): Collection | ||||
|     { | ||||
|         /** @var Collection $result */ | ||||
|         $query = $this->user->accounts()->with( | ||||
|             ['accountmeta' => function (HasMany $query) { | ||||
|                 $query->where('name', 'account_role'); | ||||
|             }] | ||||
|         ); | ||||
|         if (!empty($types)) { | ||||
|             $query->accountTypeIn($types); | ||||
|         } | ||||
|         $query->where('active', 0); | ||||
|         $query->orderBy('accounts.account_type_id', 'ASC'); | ||||
|         $query->orderBy('accounts.order', 'ASC'); | ||||
|         $query->orderBy('accounts.name', 'ASC'); | ||||
|  | ||||
|         return $query->get(['accounts.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getLocation(Account $account): ?Location | ||||
|     { | ||||
|         return $account->locations()->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Return meta value for account. Null if not found. | ||||
|      * | ||||
| @@ -463,6 +516,22 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|         return $factory->create($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getUsedCurrencies(Account $account): Collection | ||||
|     { | ||||
|         $info        = $account->transactions()->get(['transaction_currency_id', 'foreign_currency_id'])->toArray(); | ||||
|         $currencyIds = []; | ||||
|         foreach ($info as $entry) { | ||||
|             $currencyIds[] = (int)$entry['transaction_currency_id']; | ||||
|             $currencyIds[] = (int)$entry['foreign_currency_id']; | ||||
|         } | ||||
|         $currencyIds = array_unique($currencyIds); | ||||
|  | ||||
|         return TransactionCurrency::whereIn('id', $currencyIds)->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
| @@ -514,6 +583,22 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function resetAccountOrder(array $types): void | ||||
|     { | ||||
|         $list = $this->getAccountsByType($types); | ||||
|         /** | ||||
|          * @var int     $index | ||||
|          * @var Account $account | ||||
|          */ | ||||
|         foreach ($list as $index => $account) { | ||||
|             $account->order = $index + 1; | ||||
|             $account->save(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param array  $types | ||||
| @@ -546,129 +631,6 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|         return $dbQuery->take($limit)->get(['accounts.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function setUser(User $user): void | ||||
|     { | ||||
|         $this->user = $user; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Account | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(array $data): Account | ||||
|     { | ||||
|         /** @var AccountFactory $factory */ | ||||
|         $factory = app(AccountFactory::class); | ||||
|         $factory->setUser($this->user); | ||||
|  | ||||
|         return $factory->create($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param array   $data | ||||
|      * | ||||
|      * @return Account | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(Account $account, array $data): Account | ||||
|     { | ||||
|         /** @var AccountUpdateService $service */ | ||||
|         $service = app(AccountUpdateService::class); | ||||
|  | ||||
|         return $service->update($account, $data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $types | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getInactiveAccountsByType(array $types): Collection | ||||
|     { | ||||
|         /** @var Collection $result */ | ||||
|         $query = $this->user->accounts()->with( | ||||
|             ['accountmeta' => function (HasMany $query) { | ||||
|                 $query->where('name', 'account_role'); | ||||
|             }] | ||||
|         ); | ||||
|         if (!empty($types)) { | ||||
|             $query->accountTypeIn($types); | ||||
|         } | ||||
|         $query->where('active', 0); | ||||
|         $query->orderBy('accounts.account_type_id', 'ASC'); | ||||
|         $query->orderBy('accounts.order', 'ASC'); | ||||
|         $query->orderBy('accounts.name', 'ASC'); | ||||
|  | ||||
|         return $query->get(['accounts.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getLocation(Account $account): ?Location | ||||
|     { | ||||
|         return $account->locations()->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttachments(Account $account): Collection | ||||
|     { | ||||
|         $set = $account->attachments()->get(); | ||||
|  | ||||
|         /** @var Storage $disk */ | ||||
|         $disk = Storage::disk('upload'); | ||||
|  | ||||
|         return $set->each( | ||||
|             static function (Attachment $attachment) use ($disk) { | ||||
|                 $notes                   = $attachment->notes()->first(); | ||||
|                 $attachment->file_exists = $disk->exists($attachment->fileName()); | ||||
|                 $attachment->notes       = $notes ? $notes->text : ''; | ||||
|  | ||||
|                 return $attachment; | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getUsedCurrencies(Account $account): Collection | ||||
|     { | ||||
|         $info        = $account->transactions()->get(['transaction_currency_id', 'foreign_currency_id'])->toArray(); | ||||
|         $currencyIds = []; | ||||
|         foreach ($info as $entry) { | ||||
|             $currencyIds[] = (int)$entry['transaction_currency_id']; | ||||
|             $currencyIds[] = (int)$entry['foreign_currency_id']; | ||||
|         } | ||||
|         $currencyIds = array_unique($currencyIds); | ||||
|  | ||||
|         return TransactionCurrency::whereIn('id', $currencyIds)->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function resetAccountOrder(array $types): void | ||||
|     { | ||||
|         $list = $this->getAccountsByType($types); | ||||
|         /** | ||||
|          * @var int     $index | ||||
|          * @var Account $account | ||||
|          */ | ||||
|         foreach ($list as $index => $account) { | ||||
|             $account->order = $index + 1; | ||||
|             $account->save(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
| @@ -707,6 +669,14 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|         return $dbQuery->take($limit)->get(['accounts.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function setUser(User $user): void | ||||
|     { | ||||
|         $this->user = $user; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
| @@ -748,9 +718,39 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|  | ||||
|         // set the rest to zero: | ||||
|         $this->user->accounts() | ||||
|             ->leftJoin('account_types', 'accounts.account_type_id', 'account_types.id') | ||||
|             ->whereNotIn('account_types.type', [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]) | ||||
|             ->update(['order' => '0']); | ||||
|                    ->leftJoin('account_types', 'accounts.account_type_id', 'account_types.id') | ||||
|                    ->whereNotIn('account_types.type', [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]) | ||||
|                    ->update(['order' => '0']); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Account | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(array $data): Account | ||||
|     { | ||||
|         /** @var AccountFactory $factory */ | ||||
|         $factory = app(AccountFactory::class); | ||||
|         $factory->setUser($this->user); | ||||
|  | ||||
|         return $factory->create($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param array   $data | ||||
|      * | ||||
|      * @return Account | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(Account $account, array $data): Account | ||||
|     { | ||||
|         /** @var AccountUpdateService $service */ | ||||
|         $service = app(AccountUpdateService::class); | ||||
|  | ||||
|         return $service->update($account, $data); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -47,41 +47,6 @@ interface AccountRepositoryInterface | ||||
|      */ | ||||
|     public function count(array $types): int; | ||||
|  | ||||
|     /** | ||||
|      * Reset order types of the mentioned accounts. | ||||
|      * | ||||
|      * @param array $types | ||||
|      */ | ||||
|     public function resetAccountOrder(array $types): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getUsedCurrencies(Account $account): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Sort accounts (and fix the sort if necessary). | ||||
|      */ | ||||
|     public function sortAccounts(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttachments(Account $account): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Get account location, if any. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return Location|null | ||||
|      */ | ||||
|     public function getLocation(Account $account): ?Location; | ||||
|  | ||||
|     /** | ||||
|      * Moved here from account CRUD. | ||||
|      * | ||||
| @@ -161,6 +126,18 @@ interface AccountRepositoryInterface | ||||
|      */ | ||||
|     public function getActiveAccountsByType(array $types): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttachments(Account $account): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function getCashAccount(): Account; | ||||
|  | ||||
|     /** | ||||
|      * @param array $types | ||||
|      * | ||||
| @@ -169,9 +146,13 @@ interface AccountRepositoryInterface | ||||
|     public function getInactiveAccountsByType(array $types): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @return Account | ||||
|      * Get account location, if any. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return Location|null | ||||
|      */ | ||||
|     public function getCashAccount(): Account; | ||||
|     public function getLocation(Account $account): ?Location; | ||||
|  | ||||
|     /** | ||||
|      * Return meta value for account. Null if not found. | ||||
| @@ -241,6 +222,12 @@ interface AccountRepositoryInterface | ||||
|      */ | ||||
|     public function getReconciliation(Account $account): ?Account; | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getUsedCurrencies(Account $account): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
| @@ -249,7 +236,6 @@ interface AccountRepositoryInterface | ||||
|      */ | ||||
|     public function isLiability(Account $account): bool; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Returns the date of the very first transaction in this account. | ||||
|      * | ||||
| @@ -268,6 +254,13 @@ interface AccountRepositoryInterface | ||||
|      */ | ||||
|     public function oldestJournalDate(Account $account): ?Carbon; | ||||
|  | ||||
|     /** | ||||
|      * Reset order types of the mentioned accounts. | ||||
|      * | ||||
|      * @param array $types | ||||
|      */ | ||||
|     public function resetAccountOrder(array $types): void; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param array  $types | ||||
| @@ -291,6 +284,11 @@ interface AccountRepositoryInterface | ||||
|      */ | ||||
|     public function setUser(User $user); | ||||
|  | ||||
|     /** | ||||
|      * Sort accounts (and fix the sort if necessary). | ||||
|      */ | ||||
|     public function sortAccounts(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|   | ||||
| @@ -33,16 +33,16 @@ interface AccountTaskerInterface | ||||
| { | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAccountReport(Collection $accounts, Carbon $start, Carbon $end): array; | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return array | ||||
| @@ -50,8 +50,8 @@ interface AccountTaskerInterface | ||||
|     public function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): array; | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return array | ||||
|   | ||||
| @@ -24,13 +24,11 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Repositories\Account; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * | ||||
| @@ -163,8 +161,8 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null): array | ||||
|     { | ||||
|     public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null | ||||
|     ): array { | ||||
|         $start->startOfDay(); | ||||
|         $end->endOfDay(); | ||||
|  | ||||
| @@ -178,7 +176,7 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|         if (null !== $accounts) { | ||||
|             $collector->setSourceAccounts($accounts); | ||||
|         } | ||||
|         if(null !== $expense) { | ||||
|         if (null !== $expense) { | ||||
|             $collector->setDestinationAccounts($expense); | ||||
|         } | ||||
|         if (null !== $currency) { | ||||
| @@ -233,15 +231,17 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|                 $array[$foreignId]['sum'] = bcadd($array[$foreignId]['sum'], app('steam')->negative($journal['foreign_amount'])); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $array; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * // TODO same as income but copied. | ||||
|      * | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null): array | ||||
|     { | ||||
|     public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null | ||||
|     ): array { | ||||
|         $start->startOfDay(); | ||||
|         $end->endOfDay(); | ||||
|  | ||||
| @@ -255,7 +255,7 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|         if (null !== $accounts) { | ||||
|             $collector->setDestinationAccounts($accounts); | ||||
|         } | ||||
|         if(null !== $revenue) { | ||||
|         if (null !== $revenue) { | ||||
|             $collector->setSourceAccounts($revenue); | ||||
|         } | ||||
|         if (null !== $currency) { | ||||
| @@ -273,7 +273,7 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|             if (null !== $accounts) { | ||||
|                 $collector->setDestinationAccounts($accounts); | ||||
|             } | ||||
|             if(null !== $revenue) { | ||||
|             if (null !== $revenue) { | ||||
|                 $collector->setSourceAccounts($revenue); | ||||
|             } | ||||
|             $result = $collector->getExtractedJournals(); | ||||
| @@ -309,6 +309,7 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|                 $array[$foreignId]['sum'] = bcadd($array[$foreignId]['sum'], app('steam')->positive($journal['foreign_amount'])); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $array; | ||||
|     } | ||||
|  | ||||
| @@ -375,6 +376,7 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|                 $array[$foreignId]['sum'] = bcadd($array[$foreignId]['sum'], app('steam')->positive($journal['foreign_amount'])); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $array; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -38,8 +38,8 @@ interface OperationsRepositoryInterface | ||||
|      * which have the specified accounts. It's grouped per currency, with as few details in the array | ||||
|      * as possible. Amounts are always negative. | ||||
|      * | ||||
|      * @param Carbon          $start | ||||
|      * @param Carbon          $end | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return array | ||||
| @@ -75,7 +75,8 @@ interface OperationsRepositoryInterface | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null): array; | ||||
|     public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null | ||||
|     ): array; | ||||
|  | ||||
|     /** | ||||
|      * Sum of income journals in period for a set of accounts, grouped per currency. Amounts are always positive. | ||||
| @@ -88,7 +89,8 @@ interface OperationsRepositoryInterface | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null): array; | ||||
|     public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null | ||||
|     ): array; | ||||
|  | ||||
|     /** | ||||
|      * Sum of transfers in period for a set of accounts, grouped per currency. Amounts are always positive. | ||||
|   | ||||
| @@ -49,7 +49,7 @@ class AttachmentRepository implements AttachmentRepositoryInterface | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return bool | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function destroy(Attachment $attachment): bool | ||||
|     { | ||||
| @@ -111,7 +111,7 @@ class AttachmentRepository implements AttachmentRepositoryInterface | ||||
|             try { | ||||
|                 $unencryptedContent = Crypt::decrypt($encryptedContent); // verified | ||||
|             } catch (DecryptException $e) { | ||||
|                     $unencryptedContent = $encryptedContent; | ||||
|                 $unencryptedContent = $encryptedContent; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -53,6 +53,22 @@ class BillRepository implements BillRepositoryInterface | ||||
|  | ||||
|     private User $user; | ||||
|  | ||||
|     /** | ||||
|      * Correct order of piggies in case of issues. | ||||
|      */ | ||||
|     public function correctOrder(): void | ||||
|     { | ||||
|         $set     = $this->user->bills()->orderBy('order', 'ASC')->get(); | ||||
|         $current = 1; | ||||
|         foreach ($set as $bill) { | ||||
|             if ((int)$bill->order !== $current) { | ||||
|                 $bill->order = $current; | ||||
|                 $bill->save(); | ||||
|             } | ||||
|             $current++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
| @@ -69,6 +85,14 @@ class BillRepository implements BillRepositoryInterface | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $this->user->bills()->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Find a bill by ID. | ||||
|      * | ||||
| @@ -486,6 +510,7 @@ class BillRepository implements BillRepositoryInterface | ||||
|                 return $date->format('Y-m-d'); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         //Log::debug(sprintf('Found dates between %s and %s:', $start->format('Y-m-d'), $end->format('Y-m-d')), $simple->toArray()); | ||||
|  | ||||
|         return $set; | ||||
| @@ -614,7 +639,7 @@ class BillRepository implements BillRepositoryInterface | ||||
|      * @param Bill   $bill | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return \Carbon\Carbon | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function nextDateMatch(Bill $bill, Carbon $date): Carbon | ||||
|     { | ||||
| @@ -688,6 +713,16 @@ class BillRepository implements BillRepositoryInterface | ||||
|         return $start; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function removeObjectGroup(Bill $bill): Bill | ||||
|     { | ||||
|         $bill->objectGroups()->sync([]); | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
| @@ -701,6 +736,28 @@ class BillRepository implements BillRepositoryInterface | ||||
|         return $this->user->bills()->where('name', 'LIKE', $query)->take($limit)->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function setObjectGroup(Bill $bill, string $objectGroupTitle): Bill | ||||
|     { | ||||
|         $objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle); | ||||
|         if (null !== $objectGroup) { | ||||
|             $bill->objectGroups()->sync([$objectGroup->id]); | ||||
|         } | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function setOrder(Bill $bill, int $order): void | ||||
|     { | ||||
|         $bill->order = $order; | ||||
|         $bill->save(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
| @@ -724,6 +781,14 @@ class BillRepository implements BillRepositoryInterface | ||||
|         return $factory->create($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      */ | ||||
|     public function unlinkAll(Bill $bill): void | ||||
|     { | ||||
|         $this->user->transactionJournals()->where('bill_id', $bill->id)->update(['bill_id' => null]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill  $bill | ||||
|      * @param array $data | ||||
| @@ -737,68 +802,4 @@ class BillRepository implements BillRepositoryInterface | ||||
|  | ||||
|         return $service->update($bill, $data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      */ | ||||
|     public function unlinkAll(Bill $bill): void | ||||
|     { | ||||
|         $this->user->transactionJournals()->where('bill_id', $bill->id)->update(['bill_id' => null]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Correct order of piggies in case of issues. | ||||
|      */ | ||||
|     public function correctOrder(): void | ||||
|     { | ||||
|         $set     = $this->user->bills()->orderBy('order', 'ASC')->get(); | ||||
|         $current = 1; | ||||
|         foreach ($set as $bill) { | ||||
|             if ((int)$bill->order !== $current) { | ||||
|                 $bill->order = $current; | ||||
|                 $bill->save(); | ||||
|             } | ||||
|             $current++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function setObjectGroup(Bill $bill, string $objectGroupTitle): Bill | ||||
|     { | ||||
|         $objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle); | ||||
|         if (null !== $objectGroup) { | ||||
|             $bill->objectGroups()->sync([$objectGroup->id]); | ||||
|         } | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function removeObjectGroup(Bill $bill): Bill | ||||
|     { | ||||
|         $bill->objectGroups()->sync([]); | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function setOrder(Bill $bill, int $order): void | ||||
|     { | ||||
|         $bill->order = $order; | ||||
|         $bill->save(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $this->user->bills()->delete(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -35,44 +35,11 @@ use Illuminate\Support\Collection; | ||||
| interface BillRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Bill   $bill | ||||
|      * @param string $objectGroupTitle | ||||
|      * | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function setObjectGroup(Bill $bill, string $objectGroupTitle): Bill; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function removeObjectGroup(Bill $bill): Bill; | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      */ | ||||
|     public function unlinkAll(Bill $bill): void; | ||||
|  | ||||
|     /** | ||||
|      * Add correct order to bills. | ||||
|      */ | ||||
|     public function correctOrder(): void; | ||||
|  | ||||
|     /** | ||||
|      * Set specific piggy bank to specific order. | ||||
|      * | ||||
|      * @param Bill $bill | ||||
|      * @param int  $order | ||||
|      */ | ||||
|     public function setOrder(Bill $bill, int $order): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
| @@ -80,6 +47,11 @@ interface BillRepositoryInterface | ||||
|      */ | ||||
|     public function destroy(Bill $bill): bool; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * Find a bill by ID. | ||||
|      * | ||||
| @@ -273,7 +245,7 @@ interface BillRepositoryInterface | ||||
|      * @param Bill   $bill | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return \Carbon\Carbon | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function nextDateMatch(Bill $bill, Carbon $date): Carbon; | ||||
|  | ||||
| @@ -281,10 +253,17 @@ interface BillRepositoryInterface | ||||
|      * @param Bill   $bill | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return \Carbon\Carbon | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function nextExpectedMatch(Bill $bill, Carbon $date): Carbon; | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function removeObjectGroup(Bill $bill): Bill; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
| @@ -293,6 +272,22 @@ interface BillRepositoryInterface | ||||
|      */ | ||||
|     public function searchBill(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Bill   $bill | ||||
|      * @param string $objectGroupTitle | ||||
|      * | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function setObjectGroup(Bill $bill, string $objectGroupTitle): Bill; | ||||
|  | ||||
|     /** | ||||
|      * Set specific piggy bank to specific order. | ||||
|      * | ||||
|      * @param Bill $bill | ||||
|      * @param int  $order | ||||
|      */ | ||||
|     public function setOrder(Bill $bill, int $order): void; | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
| @@ -306,6 +301,11 @@ interface BillRepositoryInterface | ||||
|      */ | ||||
|     public function store(array $data): Bill; | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      */ | ||||
|     public function unlinkAll(Bill $bill): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Bill  $bill | ||||
|      * @param array $data | ||||
|   | ||||
| @@ -41,6 +41,14 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface | ||||
| { | ||||
|     private User $user; | ||||
|  | ||||
|     /** | ||||
|      * Delete all available budgets. | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $this->user->availableBudgets()->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AvailableBudget $availableBudget | ||||
|      */ | ||||
| @@ -171,6 +179,18 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface | ||||
|         return $query->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget | ||||
|     { | ||||
|         return $this->user | ||||
|             ->availableBudgets() | ||||
|             ->where('transaction_currency_id', $currency->id) | ||||
|             ->where('start_date', $start->format('Y-m-d')) | ||||
|             ->where('end_date', $end->format('Y-m-d'))->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * @param Carbon              $start | ||||
| @@ -215,13 +235,14 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface | ||||
|     public function store(array $data): ?AvailableBudget | ||||
|     { | ||||
|         $start = $data['start']; | ||||
|         if($start instanceof Carbon) { | ||||
|         if ($start instanceof Carbon) { | ||||
|             $start = $data['start']->startOfDay(); | ||||
|         } | ||||
|         $end = $data['end']; | ||||
|         if($end instanceof Carbon) { | ||||
|         if ($end instanceof Carbon) { | ||||
|             $end = $data['end']->endOfDay(); | ||||
|         } | ||||
|  | ||||
|         return AvailableBudget::create( | ||||
|             [ | ||||
|                 'user_id'                 => $this->user->id, | ||||
| @@ -271,11 +292,11 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface | ||||
|         } | ||||
|  | ||||
|         $start = $data['start']; | ||||
|         if($start instanceof Carbon) { | ||||
|         if ($start instanceof Carbon) { | ||||
|             $start = $data['start']->startOfDay(); | ||||
|         } | ||||
|         $end = $data['end']; | ||||
|         if($end instanceof Carbon) { | ||||
|         if ($end instanceof Carbon) { | ||||
|             $end = $data['end']->endOfDay(); | ||||
|         } | ||||
|  | ||||
| @@ -288,24 +309,4 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface | ||||
|         return $availableBudget; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete all available budgets. | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $this->user->availableBudgets()->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget | ||||
|     { | ||||
|         return $this->user | ||||
|             ->availableBudgets() | ||||
|             ->where('transaction_currency_id', $currency->id) | ||||
|             ->where('start_date', $start->format('Y-m-d')) | ||||
|             ->where('end_date', $end->format('Y-m-d'))->first(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -66,17 +66,6 @@ interface AvailableBudgetRepositoryInterface | ||||
|      */ | ||||
|     public function get(?Carbon $start = null, ?Carbon $end = null): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Get by transaction currency and date. Should always result in one entry or NULL. | ||||
|      * | ||||
|      * @param Carbon              $start | ||||
|      * @param Carbon              $end | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return null|AvailableBudget | ||||
|      */ | ||||
|     public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget; | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * @param Carbon              $start | ||||
| @@ -115,6 +104,17 @@ interface AvailableBudgetRepositoryInterface | ||||
|      */ | ||||
|     public function getAvailableBudgetsByDate(?Carbon $start, ?Carbon $end): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Get by transaction currency and date. Should always result in one entry or NULL. | ||||
|      * | ||||
|      * @param Carbon              $start | ||||
|      * @param Carbon              $end | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return null|AvailableBudget | ||||
|      */ | ||||
|     public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget; | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * @param Carbon              $start | ||||
|   | ||||
| @@ -88,8 +88,6 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface | ||||
|                        ); | ||||
|                 } | ||||
|             ) | ||||
|  | ||||
|  | ||||
|             ->where('budget_limits.transaction_currency_id', $currency->id) | ||||
|             ->whereNull('budgets.deleted_at') | ||||
|             ->where('budgets.user_id', $this->user->id); | ||||
| @@ -107,6 +105,18 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Destroy all budget limits. | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $budgets = $this->user->budgets()->get(); | ||||
|         /** @var Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             $budget->budgetlimits()->delete(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Destroy a budget limit. | ||||
|      * | ||||
| @@ -168,8 +178,10 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface | ||||
|                 // start date must be after $start. | ||||
|                 $query->where('start_date', '>=', $start->format('Y-m-d 00:00:00')); | ||||
|             } | ||||
|  | ||||
|             return $query->get(['budget_limits.*']); | ||||
|         } | ||||
|  | ||||
|         // neither are NULL: | ||||
|         return BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id') | ||||
|                           ->with(['budget']) | ||||
| @@ -244,6 +256,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface | ||||
|                 // start date must be after $start. | ||||
|                 $query->where('start_date', '>=', $start->format('Y-m-d 00:00:00')); | ||||
|             } | ||||
|  | ||||
|             return $query->get(['budget_limits.*']); | ||||
|         } | ||||
|  | ||||
| @@ -307,7 +320,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface | ||||
|         $currency->save(); | ||||
|  | ||||
|         // find the budget: | ||||
|         $budget = $this->user->budgets()->find((int) $data['budget_id']); | ||||
|         $budget = $this->user->budgets()->find((int)$data['budget_id']); | ||||
|         if (null === $budget) { | ||||
|             throw new FireflyException('200004: Budget does not exist.'); // @codeCoverageIgnore | ||||
|         } | ||||
| @@ -344,7 +357,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface | ||||
|      */ | ||||
|     public function update(BudgetLimit $budgetLimit, array $data): BudgetLimit | ||||
|     { | ||||
|         $budgetLimit->amount     = array_key_exists('amount',$data) ? $data['amount'] : $budgetLimit->amount; | ||||
|         $budgetLimit->amount     = array_key_exists('amount', $data) ? $data['amount'] : $budgetLimit->amount; | ||||
|         $budgetLimit->budget_id  = array_key_exists('budget_id', $data) ? $data['budget_id'] : $budgetLimit->budget_id; | ||||
|         $budgetLimit->start_date = array_key_exists('start_date', $data) ? $data['start_date']->format('Y-m-d 00:00:00') : $budgetLimit->start_date; | ||||
|         $budgetLimit->end_date   = array_key_exists('end_date', $data) ? $data['end_date']->format('Y-m-d 23:59:59') : $budgetLimit->end_date; | ||||
| @@ -353,13 +366,13 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface | ||||
|         $currency = null; | ||||
|  | ||||
|         // update if relevant: | ||||
|         if(array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { | ||||
|         if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { | ||||
|             /** @var TransactionCurrencyFactory $factory */ | ||||
|             $factory  = app(TransactionCurrencyFactory::class); | ||||
|             $currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null); | ||||
|         } | ||||
|         // catch unexpected null: | ||||
|         if(null === $currency) { | ||||
|         if (null === $currency) { | ||||
|             $currency = $budgetLimit->transactionCurrency ?? app('amount')->getDefaultCurrencyByUser($this->user); | ||||
|         } | ||||
|         $currency->enabled = true; | ||||
| @@ -441,16 +454,4 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface | ||||
|  | ||||
|         return $limit; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Destroy all budget limits. | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $budgets = $this->user->budgets()->get(); | ||||
|         /** @var Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             $budget->budgetlimits()->delete(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -36,11 +36,6 @@ use Illuminate\Support\Collection; | ||||
| interface BudgetLimitRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Destroy all budget limits. | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * Tells you which amount has been budgeted (for the given budgets) | ||||
|      * in the selected query. Returns a positive amount as a string. | ||||
| @@ -54,6 +49,11 @@ interface BudgetLimitRepositoryInterface | ||||
|      */ | ||||
|     public function budgeted(Carbon $start, Carbon $end, TransactionCurrency $currency, ?Collection $budgets = null): string; | ||||
|  | ||||
|     /** | ||||
|      * Destroy all budget limits. | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * Destroy a budget limit. | ||||
|      * | ||||
|   | ||||
| @@ -90,6 +90,33 @@ class BudgetRepository implements BudgetRepositoryInterface | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Destroy all budgets. | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $budgets = $this->getBudgets(); | ||||
|         /** @var Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             DB::table('budget_transaction')->where('budget_id', $budget->id)->delete(); | ||||
|             DB::table('budget_transaction_journal')->where('budget_id', $budget->id)->delete(); | ||||
|             RecurrenceTransactionMeta::where('name', 'budget_id')->where('value', $budget->id)->delete(); | ||||
|             RuleAction::where('action_type', 'set_budget')->where('action_value', $budget->id)->delete(); | ||||
|             $budget->delete(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAutoBudget(Budget $budget): void | ||||
|     { | ||||
|         /** @var AutoBudget $autoBudget */ | ||||
|         foreach ($budget->autoBudgets()->get() as $autoBudget) { | ||||
|             $autoBudget->delete(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int|null    $budgetId | ||||
|      * @param string|null $budgetName | ||||
| @@ -176,6 +203,35 @@ class BudgetRepository implements BudgetRepositoryInterface | ||||
|                           ->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttachments(Budget $budget): Collection | ||||
|     { | ||||
|         $set = $budget->attachments()->get(); | ||||
|  | ||||
|         /** @var Storage $disk */ | ||||
|         $disk = Storage::disk('upload'); | ||||
|  | ||||
|         return $set->each( | ||||
|             static function (Attachment $attachment) use ($disk) { | ||||
|                 $notes                   = $attachment->notes()->first(); | ||||
|                 $attachment->file_exists = $disk->exists($attachment->fileName()); | ||||
|                 $attachment->notes       = $notes ? $notes->text : ''; | ||||
|  | ||||
|                 return $attachment; | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAutoBudget(Budget $budget): ?AutoBudget | ||||
|     { | ||||
|         return $budget->autoBudgets()->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -207,6 +263,11 @@ class BudgetRepository implements BudgetRepositoryInterface | ||||
|                           ->orderBy('name', 'ASC')->where('active', 0)->get(); | ||||
|     } | ||||
|  | ||||
|     public function getMaxOrder(): int | ||||
|     { | ||||
|         return (int)$this->user->budgets()->max('order'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
| @@ -380,27 +441,6 @@ class BudgetRepository implements BudgetRepositoryInterface | ||||
|         return $budget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $oldName | ||||
|      * @param string $newName | ||||
|      */ | ||||
|     private function updateRuleActions(string $oldName, string $newName): void | ||||
|     { | ||||
|         $types   = ['set_budget',]; | ||||
|         $actions = RuleAction::leftJoin('rules', 'rules.id', '=', 'rule_actions.rule_id') | ||||
|                              ->where('rules.user_id', $this->user->id) | ||||
|                              ->whereIn('rule_actions.action_type', $types) | ||||
|                              ->where('rule_actions.action_value', $oldName) | ||||
|                              ->get(['rule_actions.*']); | ||||
|         Log::debug(sprintf('Found %d actions to update.', $actions->count())); | ||||
|         /** @var RuleAction $action */ | ||||
|         foreach ($actions as $action) { | ||||
|             $action->action_value = $newName; | ||||
|             $action->save(); | ||||
|             Log::debug(sprintf('Updated action %d: %s', $action->id, $action->action_value)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $oldName | ||||
|      * @param string $newName | ||||
| @@ -423,63 +463,23 @@ class BudgetRepository implements BudgetRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Destroy all budgets. | ||||
|      * @param string $oldName | ||||
|      * @param string $newName | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     private function updateRuleActions(string $oldName, string $newName): void | ||||
|     { | ||||
|         $budgets = $this->getBudgets(); | ||||
|         /** @var Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             DB::table('budget_transaction')->where('budget_id', $budget->id)->delete(); | ||||
|             DB::table('budget_transaction_journal')->where('budget_id', $budget->id)->delete(); | ||||
|             RecurrenceTransactionMeta::where('name', 'budget_id')->where('value', $budget->id)->delete(); | ||||
|             RuleAction::where('action_type', 'set_budget')->where('action_value', $budget->id)->delete(); | ||||
|             $budget->delete(); | ||||
|         $types   = ['set_budget',]; | ||||
|         $actions = RuleAction::leftJoin('rules', 'rules.id', '=', 'rule_actions.rule_id') | ||||
|                              ->where('rules.user_id', $this->user->id) | ||||
|                              ->whereIn('rule_actions.action_type', $types) | ||||
|                              ->where('rule_actions.action_value', $oldName) | ||||
|                              ->get(['rule_actions.*']); | ||||
|         Log::debug(sprintf('Found %d actions to update.', $actions->count())); | ||||
|         /** @var RuleAction $action */ | ||||
|         foreach ($actions as $action) { | ||||
|             $action->action_value = $newName; | ||||
|             $action->save(); | ||||
|             Log::debug(sprintf('Updated action %d: %s', $action->id, $action->action_value)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAutoBudget(Budget $budget): ?AutoBudget | ||||
|     { | ||||
|         return $budget->autoBudgets()->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAutoBudget(Budget $budget): void | ||||
|     { | ||||
|         /** @var AutoBudget $autoBudget */ | ||||
|         foreach ($budget->autoBudgets()->get() as $autoBudget) { | ||||
|             $autoBudget->delete(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttachments(Budget $budget): Collection | ||||
|     { | ||||
|         $set = $budget->attachments()->get(); | ||||
|  | ||||
|         /** @var Storage $disk */ | ||||
|         $disk = Storage::disk('upload'); | ||||
|  | ||||
|         return $set->each( | ||||
|             static function (Attachment $attachment) use ($disk) { | ||||
|                 $notes                   = $attachment->notes()->first(); | ||||
|                 $attachment->file_exists = $disk->exists($attachment->fileName()); | ||||
|                 $attachment->notes       = $notes ? $notes->text : ''; | ||||
|  | ||||
|                 return $attachment; | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function getMaxOrder(): int | ||||
|     { | ||||
|         return (int)$this->user->budgets()->max('order'); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -23,8 +23,8 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Repositories\Budget; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\AutoBudget; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\AutoBudget; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Support\Collection; | ||||
| @@ -34,36 +34,6 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| interface BudgetRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * Destroy all budgets. | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttachments(Budget $budget): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return AutoBudget|null | ||||
|      */ | ||||
|     public function getAutoBudget(Budget $budget): ?AutoBudget; | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      */ | ||||
|     public function destroyAutoBudget(Budget $budget): void; | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getMaxOrder(): int; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
| @@ -76,6 +46,16 @@ interface BudgetRepositoryInterface | ||||
|      */ | ||||
|     public function destroy(Budget $budget): bool; | ||||
|  | ||||
|     /** | ||||
|      * Destroy all budgets. | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      */ | ||||
|     public function destroyAutoBudget(Budget $budget): void; | ||||
|  | ||||
|     /** | ||||
|      * @param int|null    $budgetId | ||||
|      * @param string|null $budgetName | ||||
| @@ -117,6 +97,20 @@ interface BudgetRepositoryInterface | ||||
|      */ | ||||
|     public function getActiveBudgets(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttachments(Budget $budget): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return AutoBudget|null | ||||
|      */ | ||||
|     public function getAutoBudget(Budget $budget): ?AutoBudget; | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -136,9 +130,15 @@ interface BudgetRepositoryInterface | ||||
|      */ | ||||
|     public function getInactiveBudgets(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getMaxOrder(): int; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int $limit | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchBudget(string $query, int $limit): Collection; | ||||
|   | ||||
| @@ -30,7 +30,6 @@ use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * | ||||
| @@ -135,12 +134,12 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface | ||||
|             /** @var TransactionCurrency $currency */ | ||||
|             $currency = $currencies[$code]; | ||||
|             $return[] = [ | ||||
|                 'currency_id'             => (string) $currency['id'], | ||||
|                 'currency_id'             => (string)$currency['id'], | ||||
|                 'currency_code'           => $code, | ||||
|                 'currency_name'           => $currency['name'], | ||||
|                 'currency_symbol'         => $currency['symbol'], | ||||
|                 'currency_decimal_places' => $currency['decimal_places'], | ||||
|                 'amount'                  => number_format((float)$spent,$currency['decimal_places'], '.',''), | ||||
|                 'amount'                  => number_format((float)$spent, $currency['decimal_places'], '.', ''), | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -25,12 +25,9 @@ namespace FireflyIII\Repositories\Budget; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| @@ -59,15 +56,15 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|         foreach ($budget->budgetlimits as $limit) { | ||||
|             $diff   = $limit->start_date->diffInDays($limit->end_date); | ||||
|             $diff   = 0 === $diff ? 1 : $diff; | ||||
|             $amount = (string) $limit->amount; | ||||
|             $perDay = bcdiv($amount, (string) $diff); | ||||
|             $amount = (string)$limit->amount; | ||||
|             $perDay = bcdiv($amount, (string)$diff); | ||||
|             $total  = bcadd($total, $perDay); | ||||
|             $count++; | ||||
|             Log::debug(sprintf('Found %d budget limits. Per day is %s, total is %s', $count, $perDay, $total)); | ||||
|         } | ||||
|         $avg = $total; | ||||
|         if ($count > 0) { | ||||
|             $avg = bcdiv($total, (string) $count); | ||||
|             $avg = bcdiv($total, (string)$count); | ||||
|         } | ||||
|         Log::debug(sprintf('%s / %d = %s = average.', $total, $count, $avg)); | ||||
|  | ||||
| @@ -103,9 +100,9 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|         /** @var array $journal */ | ||||
|         foreach ($journals as $journal) { | ||||
|             // prep data array for currency: | ||||
|             $budgetId   = (int) $journal['budget_id']; | ||||
|             $budgetId   = (int)$journal['budget_id']; | ||||
|             $budgetName = $journal['budget_name']; | ||||
|             $currencyId = (int) $journal['currency_id']; | ||||
|             $currencyId = (int)$journal['currency_id']; | ||||
|             $key        = sprintf('%d-%d', $budgetId, $currencyId); | ||||
|  | ||||
|             $data[$key]                   = $data[$key] ?? [ | ||||
| @@ -157,9 +154,9 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|         $array    = []; | ||||
|  | ||||
|         foreach ($journals as $journal) { | ||||
|             $currencyId = (int) $journal['currency_id']; | ||||
|             $budgetId   = (int) $journal['budget_id']; | ||||
|             $budgetName = (string) $journal['budget_name']; | ||||
|             $currencyId = (int)$journal['currency_id']; | ||||
|             $budgetId   = (int)$journal['budget_id']; | ||||
|             $budgetName = (string)$journal['budget_name']; | ||||
|  | ||||
|             // catch "no category" entries. | ||||
|             if (0 === $budgetId) { | ||||
| @@ -185,7 +182,7 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|  | ||||
|             // add journal to array: | ||||
|             // only a subset of the fields. | ||||
|             $journalId = (int) $journal['transaction_journal_id']; | ||||
|             $journalId = (int)$journal['transaction_journal_id']; | ||||
|  | ||||
|  | ||||
|             $array[$currencyId]['budgets'][$budgetId]['transaction_journals'][$journalId] = [ | ||||
| @@ -269,7 +266,7 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|                 'currency_name'           => $currency['name'], | ||||
|                 'currency_symbol'         => $currency['symbol'], | ||||
|                 'currency_decimal_places' => $currency['decimal_places'], | ||||
|                 'amount'                  => number_format((float) $spent, $currency['decimal_places'], '.', ''), | ||||
|                 'amount'                  => number_format((float)$spent, $currency['decimal_places'], '.', ''), | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
| @@ -286,8 +283,7 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|      * @return array | ||||
|      */ | ||||
|     public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null | ||||
|     ): array | ||||
|     { | ||||
|     ): array { | ||||
|         Log::debug(sprintf('Now in %s', __METHOD__)); | ||||
|         $start->startOfDay(); | ||||
|         $end->endOfDay(); | ||||
| @@ -326,7 +322,7 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|         $array = []; | ||||
|  | ||||
|         foreach ($journals as $journal) { | ||||
|             $currencyId                = (int) $journal['currency_id']; | ||||
|             $currencyId                = (int)$journal['currency_id']; | ||||
|             $array[$currencyId]        = $array[$currencyId] ?? [ | ||||
|                     'sum'                     => '0', | ||||
|                     'currency_id'             => $currencyId, | ||||
| @@ -338,8 +334,8 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|             $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal['amount'])); | ||||
|  | ||||
|             // also do foreign amount: | ||||
|             $foreignId                = (int) $journal['foreign_currency_id']; | ||||
|             if(0 !== $foreignId) { | ||||
|             $foreignId = (int)$journal['foreign_currency_id']; | ||||
|             if (0 !== $foreignId) { | ||||
|                 $array[$foreignId]        = $array[$foreignId] ?? [ | ||||
|                         'sum'                     => '0', | ||||
|                         'currency_id'             => $foreignId, | ||||
| @@ -356,6 +352,17 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|         return $array; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     private function getBudgets(): Collection | ||||
|     { | ||||
|         /** @var BudgetRepositoryInterface $repos */ | ||||
|         $repos = app(BudgetRepositoryInterface::class); | ||||
|  | ||||
|         return $repos->getActiveBudgets(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * For now, simply refer to whichever repository holds this function. | ||||
|      * TODO might be done better in the future. | ||||
| @@ -373,15 +380,4 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|  | ||||
|         return $blRepository->getBudgetLimits($budget, $start, $end); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     private function getBudgets(): Collection | ||||
|     { | ||||
|         /** @var BudgetRepositoryInterface $repos */ | ||||
|         $repos = app(BudgetRepositoryInterface::class); | ||||
|  | ||||
|         return $repos->getActiveBudgets(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -56,11 +56,27 @@ interface OperationsRepositoryInterface | ||||
|      */ | ||||
|     public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array; | ||||
|  | ||||
|     /** | ||||
|      * This method returns a list of all the withdrawal transaction journals (as arrays) set in that period | ||||
|      * which have the specified budget set to them. It's grouped per currency, with as few details in the array | ||||
|      * as possible. Amounts are always negative. | ||||
|      * | ||||
|      * @param Carbon          $start | ||||
|      * @param Carbon          $end | ||||
|      * @param Collection|null $accounts | ||||
|      * @param Collection|null $budgets | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null): array; | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function setUser(User $user): void; | ||||
|  | ||||
|     /** @noinspection MoreThanThreeArgumentsInspection */ | ||||
|  | ||||
|     /** | ||||
|      * Return multi-currency spent information. | ||||
|      * | ||||
| @@ -74,7 +90,6 @@ interface OperationsRepositoryInterface | ||||
|      */ | ||||
|     public function spentInPeriodMc(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array; | ||||
|  | ||||
|     /** @noinspection MoreThanThreeArgumentsInspection */ | ||||
|     /** | ||||
|      * @param Carbon                   $start | ||||
|      * @param Carbon                   $end | ||||
| @@ -87,18 +102,4 @@ interface OperationsRepositoryInterface | ||||
|     public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null | ||||
|     ): array; | ||||
|  | ||||
|     /** | ||||
|      * This method returns a list of all the withdrawal transaction journals (as arrays) set in that period | ||||
|      * which have the specified budget set to them. It's grouped per currency, with as few details in the array | ||||
|      * as possible. Amounts are always negative. | ||||
|      * | ||||
|      * @param Carbon          $start | ||||
|      * @param Carbon          $end | ||||
|      * @param Collection|null $accounts | ||||
|      * @param Collection|null $budgets | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null): array; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -24,6 +24,7 @@ namespace FireflyIII\Repositories\Category; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use DB; | ||||
| use Exception; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Factory\CategoryFactory; | ||||
| use FireflyIII\Models\Attachment; | ||||
| @@ -61,6 +62,22 @@ class CategoryRepository implements CategoryRepositoryInterface | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete all categories. | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $categories = $this->getCategories(); | ||||
|         /** @var Category $category */ | ||||
|         foreach ($categories as $category) { | ||||
|             DB::table('category_transaction')->where('category_id', $category->id)->delete(); | ||||
|             DB::table('category_transaction_journal')->where('category_id', $category->id)->delete(); | ||||
|             RecurrenceTransactionMeta::where('name', 'category_id')->where('value', $category->id)->delete(); | ||||
|             RuleAction::where('action_type', 'set_category')->where('action_value', $category->name)->delete(); | ||||
|             $category->delete(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Find a category. | ||||
|      * | ||||
| @@ -150,6 +167,27 @@ class CategoryRepository implements CategoryRepositoryInterface | ||||
|         return $firstJournalDate; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttachments(Category $category): Collection | ||||
|     { | ||||
|         $set = $category->attachments()->get(); | ||||
|  | ||||
|         /** @var Storage $disk */ | ||||
|         $disk = Storage::disk('upload'); | ||||
|  | ||||
|         return $set->each( | ||||
|             static function (Attachment $attachment) use ($disk) { | ||||
|                 $notes                   = $attachment->notes()->first(); | ||||
|                 $attachment->file_exists = $disk->exists($attachment->fileName()); | ||||
|                 $attachment->notes       = $notes ? $notes->text : ''; | ||||
|  | ||||
|                 return $attachment; | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all categories with ID's. | ||||
|      * | ||||
| @@ -172,6 +210,19 @@ class CategoryRepository implements CategoryRepositoryInterface | ||||
|         return $this->user->categories()->with(['attachments'])->orderBy('name', 'ASC')->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getNoteText(Category $category): ?string | ||||
|     { | ||||
|         $dbNote = $category->notes()->first(); | ||||
|         if (null === $dbNote) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return $dbNote->text; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category   $category | ||||
|      * @param Collection $accounts | ||||
| @@ -201,6 +252,14 @@ class CategoryRepository implements CategoryRepositoryInterface | ||||
|         return $lastJournalDate; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      */ | ||||
|     public function removeNotes(Category $category): void | ||||
|     { | ||||
|         $category->notes()->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
| @@ -254,16 +313,6 @@ class CategoryRepository implements CategoryRepositoryInterface | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      */ | ||||
|     public function removeNotes(Category $category): void | ||||
|     { | ||||
|         $category->notes()->delete(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param array    $data | ||||
| @@ -279,6 +328,20 @@ class CategoryRepository implements CategoryRepositoryInterface | ||||
|         return $service->update($category, $data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function updateNotes(Category $category, string $notes): void | ||||
|     { | ||||
|         $dbNote = $category->notes()->first(); | ||||
|         if (null === $dbNote) { | ||||
|             $dbNote = new Note; | ||||
|             $dbNote->noteable()->associate($category); | ||||
|         } | ||||
|         $dbNote->text = trim($notes); | ||||
|         $dbNote->save(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
| @@ -345,7 +408,7 @@ class CategoryRepository implements CategoryRepositoryInterface | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return Carbon|null | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     private function getLastTransactionDate(Category $category, Collection $accounts): ?Carbon | ||||
|     { | ||||
| @@ -365,68 +428,4 @@ class CategoryRepository implements CategoryRepositoryInterface | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete all categories. | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $categories = $this->getCategories(); | ||||
|         /** @var Category $category */ | ||||
|         foreach ($categories as $category) { | ||||
|             DB::table('category_transaction')->where('category_id', $category->id)->delete(); | ||||
|             DB::table('category_transaction_journal')->where('category_id', $category->id)->delete(); | ||||
|             RecurrenceTransactionMeta::where('name', 'category_id')->where('value', $category->id)->delete(); | ||||
|             RuleAction::where('action_type', 'set_category')->where('action_value', $category->name)->delete(); | ||||
|             $category->delete(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttachments(Category $category): Collection | ||||
|     { | ||||
|         $set = $category->attachments()->get(); | ||||
|  | ||||
|         /** @var Storage $disk */ | ||||
|         $disk = Storage::disk('upload'); | ||||
|  | ||||
|         return $set->each( | ||||
|             static function (Attachment $attachment) use ($disk) { | ||||
|                 $notes                   = $attachment->notes()->first(); | ||||
|                 $attachment->file_exists = $disk->exists($attachment->fileName()); | ||||
|                 $attachment->notes       = $notes ? $notes->text : ''; | ||||
|  | ||||
|                 return $attachment; | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function updateNotes(Category $category, string $notes): void | ||||
|     { | ||||
|         $dbNote = $category->notes()->first(); | ||||
|         if (null === $dbNote) { | ||||
|             $dbNote = new Note; | ||||
|             $dbNote->noteable()->associate($category); | ||||
|         } | ||||
|         $dbNote->text = trim($notes); | ||||
|         $dbNote->save(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getNoteText(Category $category): ?string | ||||
|     { | ||||
|         $dbNote = $category->notes()->first(); | ||||
|         if (null === $dbNote) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return $dbNote->text; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -34,38 +34,6 @@ use Illuminate\Support\Collection; | ||||
| interface CategoryRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Remove notes. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      */ | ||||
|     public function removeNotes(Category $category): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param string   $notes | ||||
|      */ | ||||
|     public function updateNotes(Category $category, string $notes): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getNoteText(Category $category): ?string; | ||||
|  | ||||
|     /** | ||||
|      * Delete all categories. | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttachments(Category $category): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
| @@ -73,6 +41,11 @@ interface CategoryRepositoryInterface | ||||
|      */ | ||||
|     public function destroy(Category $category): bool; | ||||
|  | ||||
|     /** | ||||
|      * Delete all categories. | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * Find a category. | ||||
|      * | ||||
| @@ -106,6 +79,13 @@ interface CategoryRepositoryInterface | ||||
|      */ | ||||
|     public function firstUseDate(Category $category): ?Carbon; | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttachments(Category $category): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Get all categories with ID's. | ||||
|      * | ||||
| @@ -122,6 +102,13 @@ interface CategoryRepositoryInterface | ||||
|      */ | ||||
|     public function getCategories(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getNoteText(Category $category): ?string; | ||||
|  | ||||
|     /** | ||||
|      * Return most recent transaction(journal) date or null when never used before. | ||||
|      * | ||||
| @@ -132,9 +119,16 @@ interface CategoryRepositoryInterface | ||||
|      */ | ||||
|     public function lastUseDate(Category $category, Collection $accounts): ?Carbon; | ||||
|  | ||||
|     /** | ||||
|      * Remove notes. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      */ | ||||
|     public function removeNotes(Category $category): void; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int $limit | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -147,8 +141,9 @@ interface CategoryRepositoryInterface | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * @throws FireflyException | ||||
|      * | ||||
|      * @return Category | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(array $data): Category; | ||||
|  | ||||
| @@ -159,4 +154,10 @@ interface CategoryRepositoryInterface | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function update(Category $category, array $data): Category; | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param string   $notes | ||||
|      */ | ||||
|     public function updateNotes(Category $category, string $notes): void; | ||||
| } | ||||
|   | ||||
| @@ -29,7 +29,6 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * | ||||
| @@ -110,7 +109,7 @@ class OperationsRepository implements OperationsRepositoryInterface | ||||
|                 'source_account_id'        => $journal['source_account_id'], | ||||
|                 'budget_name'              => $journal['budget_name'], | ||||
|                 'source_account_name'      => $journal['source_account_name'], | ||||
|                 'destination_account_id' => $journal['destination_account_id'], | ||||
|                 'destination_account_id'   => $journal['destination_account_id'], | ||||
|                 'destination_account_name' => $journal['destination_account_name'], | ||||
|                 'description'              => $journal['description'], | ||||
|                 'transaction_group_id'     => $journal['transaction_group_id'], | ||||
|   | ||||
| @@ -57,6 +57,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface | ||||
|     public function countJournals(TransactionCurrency $currency): int | ||||
|     { | ||||
|         $count = $currency->transactions()->whereNull('deleted_at')->count() + $currency->transactionJournals()->whereNull('deleted_at')->count(); | ||||
|  | ||||
|         // also count foreign: | ||||
|         return $count + Transaction::where('foreign_currency_id', $currency->id)->count(); | ||||
|     } | ||||
| @@ -452,9 +453,17 @@ class CurrencyRepository implements CurrencyRepositoryInterface | ||||
|                           )->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function isFallbackCurrency(TransactionCurrency $currency): bool | ||||
|     { | ||||
|         return $currency->code === config('firefly.default_currency', 'EUR'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $search | ||||
|      * @param int $limit | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -508,12 +517,4 @@ class CurrencyRepository implements CurrencyRepositoryInterface | ||||
|  | ||||
|         return $service->update($currency, $data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function isFallbackCurrency(TransactionCurrency $currency): bool | ||||
|     { | ||||
|         return $currency->code === config('firefly.default_currency', 'EUR'); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -36,13 +36,6 @@ use Illuminate\Support\Collection; | ||||
| interface CurrencyRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isFallbackCurrency(TransactionCurrency $currency): bool; | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
| @@ -223,6 +216,13 @@ interface CurrencyRepositoryInterface | ||||
|      */ | ||||
|     public function getExchangeRates(TransactionCurrency $currency): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isFallbackCurrency(TransactionCurrency $currency): bool; | ||||
|  | ||||
|     /** | ||||
|      * @param string $search | ||||
|      * @param int    $limit | ||||
| @@ -238,8 +238,9 @@ interface CurrencyRepositoryInterface | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * @throws FireflyException | ||||
|      * | ||||
|      * @return TransactionCurrency | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(array $data): TransactionCurrency; | ||||
|  | ||||
|   | ||||
| @@ -48,9 +48,9 @@ class JournalAPIRepository implements JournalAPIRepositoryInterface | ||||
|     public function findTransaction(int $transactionId): ?Transaction | ||||
|     { | ||||
|         return Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|                                   ->where('transaction_journals.user_id', $this->user->id) | ||||
|                                   ->where('transactions.id', $transactionId) | ||||
|                                   ->first(['transactions.*']); | ||||
|                           ->where('transaction_journals.user_id', $this->user->id) | ||||
|                           ->where('transactions.id', $transactionId) | ||||
|                           ->first(['transactions.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -78,6 +78,16 @@ class JournalAPIRepository implements JournalAPIRepositoryInterface | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getJournalLinks(TransactionJournal $journal): Collection | ||||
|     { | ||||
|         $collection = $journal->destJournalLinks()->get(); | ||||
|  | ||||
|         return $journal->sourceJournalLinks()->get()->merge($collection); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all piggy bank events for a journal. | ||||
|      * | ||||
| @@ -105,14 +115,4 @@ class JournalAPIRepository implements JournalAPIRepositoryInterface | ||||
|     { | ||||
|         $this->user = $user; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getJournalLinks(TransactionJournal $journal): Collection | ||||
|     { | ||||
|         $collection = $journal->destJournalLinks()->get(); | ||||
|  | ||||
|         return $journal->sourceJournalLinks()->get()->merge($collection); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -33,64 +33,6 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| interface JournalCLIRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function setUser(User $user); | ||||
|  | ||||
|     /** | ||||
|      * Return all tags as strings in an array. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getTags(TransactionJournal $journal): array; | ||||
|  | ||||
|     /** | ||||
|      * Returns all journals with more than 2 transactions. Should only return empty collections | ||||
|      * in Firefly III > v4.8,0. | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getSplitJournals(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Return text of a note attached to journal, or NULL | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getNoteText(TransactionJournal $journal): ?string; | ||||
|  | ||||
|     /** | ||||
|      * Return value of a meta field (or NULL). | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param string             $field | ||||
|      * | ||||
|      * @return null|string | ||||
|      */ | ||||
|     public function getMetaField(TransactionJournal $journal, string $field): ?string; | ||||
|  | ||||
|     /** | ||||
|      * Return Carbon value of a meta field (or NULL). | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param string             $field | ||||
|      * | ||||
|      * @return null|Carbon | ||||
|      */ | ||||
|     public function getMetaDate(TransactionJournal $journal, string $field): ?Carbon; | ||||
|  | ||||
|     /** | ||||
|      * Return all journals without a group, used in an upgrade routine. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getJournalsWithoutGroup(): array; | ||||
|  | ||||
|     /** | ||||
|      * Get all transaction journals with a specific type, regardless of user. | ||||
|      * | ||||
| @@ -118,4 +60,62 @@ interface JournalCLIRepositoryInterface | ||||
|      */ | ||||
|     public function getJournalCategoryId(TransactionJournal $journal): int; | ||||
|  | ||||
|     /** | ||||
|      * Return all journals without a group, used in an upgrade routine. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getJournalsWithoutGroup(): array; | ||||
|  | ||||
|     /** | ||||
|      * Return Carbon value of a meta field (or NULL). | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param string             $field | ||||
|      * | ||||
|      * @return null|Carbon | ||||
|      */ | ||||
|     public function getMetaDate(TransactionJournal $journal, string $field): ?Carbon; | ||||
|  | ||||
|     /** | ||||
|      * Return value of a meta field (or NULL). | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param string             $field | ||||
|      * | ||||
|      * @return null|string | ||||
|      */ | ||||
|     public function getMetaField(TransactionJournal $journal, string $field): ?string; | ||||
|  | ||||
|     /** | ||||
|      * Return text of a note attached to journal, or NULL | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getNoteText(TransactionJournal $journal): ?string; | ||||
|  | ||||
|     /** | ||||
|      * Returns all journals with more than 2 transactions. Should only return empty collections | ||||
|      * in Firefly III > v4.8,0. | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getSplitJournals(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Return all tags as strings in an array. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getTags(TransactionJournal $journal): array; | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function setUser(User $user); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -37,7 +37,6 @@ use FireflyIII\Services\Internal\Update\JournalUpdateService; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class JournalRepository. | ||||
| @@ -49,24 +48,6 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|     /** @var User */ | ||||
|     private $user; | ||||
|  | ||||
|     /** | ||||
|      * Search in journal descriptions. | ||||
|      * | ||||
|      * @param string $search | ||||
|      * @param int $limit | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchJournalDescriptions(string $search, int $limit): Collection | ||||
|     { | ||||
|         $query = $this->user->transactionJournals() | ||||
|                             ->orderBy('date', 'DESC'); | ||||
|         if ('' !== $query) { | ||||
|             $query->where('description', 'LIKE', sprintf('%%%s%%', $search)); | ||||
|         } | ||||
|  | ||||
|         return $query->take($limit)->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionGroup $transactionGroup | ||||
|      * | ||||
| @@ -89,6 +70,18 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|         $service->destroy($journal); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function findByType(array $types): Collection | ||||
|     { | ||||
|         return $this->user | ||||
|             ->transactionJournals() | ||||
|             ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|             ->whereIn('transaction_types.type', $types) | ||||
|             ->get(['transaction_journals.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Find a specific journal. | ||||
|      * | ||||
| @@ -118,11 +111,25 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getDestinationAccount(TransactionJournal $journal): Account | ||||
|     { | ||||
|         /** @var Transaction $transaction */ | ||||
|         $transaction = $journal->transactions()->with('account')->where('amount', '>', 0)->first(); | ||||
|         if (null === $transaction) { | ||||
|             throw new FireflyException(sprintf('Your administration is broken. Transaction journal #%d has no destination transaction.', $journal->id)); | ||||
|         } | ||||
|  | ||||
|         return $transaction->account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Return a list of all destination accounts related to journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param bool $useCache | ||||
|      * @param bool               $useCache | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -150,7 +157,7 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|      * Return a list of all source accounts related to journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param bool $useCache | ||||
|      * @param bool               $useCache | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -198,6 +205,21 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|         return $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return TransactionJournal|null | ||||
|      */ | ||||
|     public function getLast(): ?TransactionJournal | ||||
|     { | ||||
|         /** @var TransactionJournal $entry */ | ||||
|         $entry  = $this->user->transactionJournals()->orderBy('date', 'DESC')->first(['transaction_journals.*']); | ||||
|         $result = null; | ||||
|         if (null !== $entry) { | ||||
|             $result = $entry; | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournalLink $link | ||||
|      * | ||||
| @@ -214,107 +236,6 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param int $transactionId | ||||
|      */ | ||||
|     public function reconcileById(int $journalId): void | ||||
|     { | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         $journal = $this->user->transactionJournals()->find($journalId); | ||||
|         if (null !== $journal) { | ||||
|             $journal->transactions()->update(['reconciled' => true]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function setUser(User $user): void | ||||
|     { | ||||
|         $this->user = $user; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update budget for a journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param int $budgetId | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
|     public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal | ||||
|     { | ||||
|         /** @var JournalUpdateService $service */ | ||||
|         $service = app(JournalUpdateService::class); | ||||
|  | ||||
|         $service->setTransactionJournal($journal); | ||||
|         $service->setData( | ||||
|             [ | ||||
|                 'budget_id' => $budgetId, | ||||
|             ] | ||||
|         ); | ||||
|         $service->update(); | ||||
|         $journal->refresh(); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update category for a journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param string $category | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
|     public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal | ||||
|     { | ||||
|         /** @var JournalUpdateService $service */ | ||||
|         $service = app(JournalUpdateService::class); | ||||
|         $service->setTransactionJournal($journal); | ||||
|         $service->setData( | ||||
|             [ | ||||
|                 'category_name' => $category, | ||||
|             ] | ||||
|         ); | ||||
|         $service->update(); | ||||
|         $journal->refresh(); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update tag(s) for a journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param array $tags | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
|     public function updateTags(TransactionJournal $journal, array $tags): TransactionJournal | ||||
|     { | ||||
|         /** @var JournalUpdateService $service */ | ||||
|         $service = app(JournalUpdateService::class); | ||||
|         $service->setTransactionJournal($journal); | ||||
|         $service->setData( | ||||
|             [ | ||||
|                 'tags' => $tags, | ||||
|             ] | ||||
|         ); | ||||
|         $service->update(); | ||||
|         $journal->refresh(); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Return Carbon value of a meta field (or NULL). | ||||
|      * | ||||
| @@ -359,43 +280,114 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      * @param int $transactionId | ||||
|      */ | ||||
|     public function getDestinationAccount(TransactionJournal $journal): Account | ||||
|     public function reconcileById(int $journalId): void | ||||
|     { | ||||
|         /** @var Transaction $transaction */ | ||||
|         $transaction = $journal->transactions()->with('account')->where('amount', '>', 0)->first(); | ||||
|         if (null === $transaction) { | ||||
|             throw new FireflyException(sprintf('Your administration is broken. Transaction journal #%d has no destination transaction.', $journal->id)); | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         $journal = $this->user->transactionJournals()->find($journalId); | ||||
|         if (null !== $journal) { | ||||
|             $journal->transactions()->update(['reconciled' => true]); | ||||
|         } | ||||
|  | ||||
|         return $transaction->account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return TransactionJournal|null | ||||
|      * Search in journal descriptions. | ||||
|      * | ||||
|      * @param string $search | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getLast(): ?TransactionJournal | ||||
|     public function searchJournalDescriptions(string $search, int $limit): Collection | ||||
|     { | ||||
|         /** @var TransactionJournal $entry */ | ||||
|         $entry  = $this->user->transactionJournals()->orderBy('date', 'DESC')->first(['transaction_journals.*']); | ||||
|         $result = null; | ||||
|         if (null !== $entry) { | ||||
|             $result = $entry; | ||||
|         $query = $this->user->transactionJournals() | ||||
|                             ->orderBy('date', 'DESC'); | ||||
|         if ('' !== $query) { | ||||
|             $query->where('description', 'LIKE', sprintf('%%%s%%', $search)); | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|         return $query->take($limit)->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function findByType(array $types): Collection | ||||
|     public function setUser(User $user): void | ||||
|     { | ||||
|         return $this->user | ||||
|             ->transactionJournals() | ||||
|             ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|             ->whereIn('transaction_types.type', $types) | ||||
|             ->get(['transaction_journals.*']); | ||||
|         $this->user = $user; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update budget for a journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param int                $budgetId | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
|     public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal | ||||
|     { | ||||
|         /** @var JournalUpdateService $service */ | ||||
|         $service = app(JournalUpdateService::class); | ||||
|  | ||||
|         $service->setTransactionJournal($journal); | ||||
|         $service->setData( | ||||
|             [ | ||||
|                 'budget_id' => $budgetId, | ||||
|             ] | ||||
|         ); | ||||
|         $service->update(); | ||||
|         $journal->refresh(); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update category for a journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param string             $category | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
|     public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal | ||||
|     { | ||||
|         /** @var JournalUpdateService $service */ | ||||
|         $service = app(JournalUpdateService::class); | ||||
|         $service->setTransactionJournal($journal); | ||||
|         $service->setData( | ||||
|             [ | ||||
|                 'category_name' => $category, | ||||
|             ] | ||||
|         ); | ||||
|         $service->update(); | ||||
|         $journal->refresh(); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update tag(s) for a journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param array              $tags | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
|     public function updateTags(TransactionJournal $journal, array $tags): TransactionJournal | ||||
|     { | ||||
|         /** @var JournalUpdateService $service */ | ||||
|         $service = app(JournalUpdateService::class); | ||||
|         $service->setTransactionJournal($journal); | ||||
|         $service->setData( | ||||
|             [ | ||||
|                 'tags' => $tags, | ||||
|             ] | ||||
|         ); | ||||
|         $service->update(); | ||||
|         $journal->refresh(); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -36,28 +36,6 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| interface JournalRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * @return TransactionJournal|null | ||||
|      */ | ||||
|     public function getLast(): ?TransactionJournal; | ||||
|  | ||||
|     /** | ||||
|      * @param array $types | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function findByType(array $types): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Search in journal descriptions. | ||||
|      * | ||||
|      * @param string $search | ||||
|      * @param int $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchJournalDescriptions(string $search, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Deletes a transaction group. | ||||
|      * | ||||
| @@ -72,6 +50,13 @@ interface JournalRepositoryInterface | ||||
|      */ | ||||
|     public function destroyJournal(TransactionJournal $journal): void; | ||||
|  | ||||
|     /** | ||||
|      * @param array $types | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function findByType(array $types): Collection; | ||||
|  | ||||
|     /** | ||||
|      * TODO Refactor to "find". | ||||
|      * Find a specific journal. | ||||
| @@ -89,13 +74,24 @@ interface JournalRepositoryInterface | ||||
|      */ | ||||
|     public function firstNull(): ?TransactionJournal; | ||||
|  | ||||
|     /** | ||||
|      * Returns the destination account of the journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return Account | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function getDestinationAccount(TransactionJournal $journal): Account; | ||||
|  | ||||
|     /** | ||||
|      * TODO this method is no longer well-fitted in 4.8,0. Should be refactored and/or removed. | ||||
|      * Return a list of all destination accounts related to journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @deprecated | ||||
|      * | ||||
|      * @return Collection | ||||
|      * @deprecated | ||||
|      */ | ||||
|     public function getJournalDestinationAccounts(TransactionJournal $journal): Collection; | ||||
|  | ||||
| @@ -104,11 +100,45 @@ interface JournalRepositoryInterface | ||||
|      * Return a list of all source accounts related to journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @deprecated | ||||
|      * | ||||
|      * @return Collection | ||||
|      * @deprecated | ||||
|      */ | ||||
|     public function getJournalSourceAccounts(TransactionJournal $journal): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Return total amount of journal. Is always positive. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getJournalTotal(TransactionJournal $journal): string; | ||||
|  | ||||
|     /** | ||||
|      * @return TransactionJournal|null | ||||
|      */ | ||||
|     public function getLast(): ?TransactionJournal; | ||||
|  | ||||
|     /** | ||||
|      * TODO used only in transformer, so only for API use. | ||||
|      * | ||||
|      * @param TransactionJournalLink $link | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getLinkNoteText(TransactionJournalLink $link): string; | ||||
|  | ||||
|     /** | ||||
|      * Return Carbon value of a meta field (or NULL). | ||||
|      * | ||||
|      * @param int    $journalId | ||||
|      * @param string $field | ||||
|      * | ||||
|      * @return null|Carbon | ||||
|      */ | ||||
|     public function getMetaDateById(int $journalId, string $field): ?Carbon; | ||||
|  | ||||
|     /** | ||||
|      * Returns the source account of the journal. | ||||
|      * | ||||
| @@ -119,47 +149,6 @@ interface JournalRepositoryInterface | ||||
|      */ | ||||
|     public function getSourceAccount(TransactionJournal $journal): Account; | ||||
|  | ||||
|     /** | ||||
|      * Returns the destination account of the journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @return Account | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function getDestinationAccount(TransactionJournal $journal): Account; | ||||
|  | ||||
|     /** | ||||
|      * Return total amount of journal. Is always positive. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getJournalTotal(TransactionJournal $journal): string; | ||||
|  | ||||
|     /** | ||||
|      * TODO used only in transformer, so only for API use. | ||||
|      * @param TransactionJournalLink $link | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getLinkNoteText(TransactionJournalLink $link): string; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Return Carbon value of a meta field (or NULL). | ||||
|      * | ||||
|      * @param int $journalId | ||||
|      * @param string             $field | ||||
|      * | ||||
|      * @return null|Carbon | ||||
|      */ | ||||
|     public function getMetaDateById(int $journalId, string $field): ?Carbon; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * TODO maybe move to account repository? | ||||
|      * | ||||
| @@ -167,6 +156,16 @@ interface JournalRepositoryInterface | ||||
|      */ | ||||
|     public function reconcileById(int $journalId): void; | ||||
|  | ||||
|     /** | ||||
|      * Search in journal descriptions. | ||||
|      * | ||||
|      * @param string $search | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchJournalDescriptions(string $search, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
| @@ -176,7 +175,7 @@ interface JournalRepositoryInterface | ||||
|      * Update budget for a journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param int $budgetId | ||||
|      * @param int                $budgetId | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
| @@ -186,7 +185,7 @@ interface JournalRepositoryInterface | ||||
|      * Update category for a journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param string $category | ||||
|      * @param string             $category | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
| @@ -196,7 +195,7 @@ interface JournalRepositoryInterface | ||||
|      * Update tag(s) for a journal. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param array $tags | ||||
|      * @param array              $tags | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
|   | ||||
| @@ -57,7 +57,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface | ||||
|      * @param LinkType $moveTo | ||||
|      * | ||||
|      * @return bool | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function destroy(LinkType $linkType, LinkType $moveTo = null): bool | ||||
|     { | ||||
| @@ -73,7 +73,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface | ||||
|      * @param TransactionJournalLink $link | ||||
|      * | ||||
|      * @return bool | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function destroyLink(TransactionJournalLink $link): bool | ||||
|     { | ||||
| @@ -309,14 +309,14 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface | ||||
|      */ | ||||
|     public function update(LinkType $linkType, array $data): LinkType | ||||
|     { | ||||
|         if(array_key_exists('name', $data) && '' !== (string)$data['name']) { | ||||
|             $linkType->name    = $data['name']; | ||||
|         if (array_key_exists('name', $data) && '' !== (string)$data['name']) { | ||||
|             $linkType->name = $data['name']; | ||||
|         } | ||||
|         if(array_key_exists('inward', $data) && '' !== (string)$data['inward']) { | ||||
|             $linkType->inward    = $data['inward']; | ||||
|         if (array_key_exists('inward', $data) && '' !== (string)$data['inward']) { | ||||
|             $linkType->inward = $data['inward']; | ||||
|         } | ||||
|         if(array_key_exists('outward', $data) && '' !== (string)$data['outward']) { | ||||
|             $linkType->outward    = $data['outward']; | ||||
|         if (array_key_exists('outward', $data) && '' !== (string)$data['outward']) { | ||||
|             $linkType->outward = $data['outward']; | ||||
|         } | ||||
|         $linkType->save(); | ||||
|  | ||||
| @@ -338,7 +338,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface | ||||
|         $journalLink->save(); | ||||
|         if (array_key_exists('link_type_name', $data)) { | ||||
|             $linkType = LinkType::whereName($data['link_type_name'])->first(); | ||||
|             if(null !== $linkType) { | ||||
|             if (null !== $linkType) { | ||||
|                 $journalLink->link_type_id = $linkType->id; | ||||
|                 $journalLink->save(); | ||||
|             } | ||||
| @@ -362,7 +362,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface | ||||
|      * @param TransactionJournalLink $link | ||||
|      * @param string                 $text | ||||
|      * | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     private function setNoteText(TransactionJournalLink $link, string $text): void | ||||
|     { | ||||
|   | ||||
| @@ -32,16 +32,6 @@ use FireflyIII\User; | ||||
|  */ | ||||
| trait CreatesObjectGroups | ||||
| { | ||||
|     /** | ||||
|      * @param string $title | ||||
|      * | ||||
|      * @return null|ObjectGroup | ||||
|      */ | ||||
|     protected function findObjectGroup(string $title): ?ObjectGroup | ||||
|     { | ||||
|         return $this->user->objectGroups()->where('title', $title)->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $groupId | ||||
|      * | ||||
| @@ -79,7 +69,7 @@ trait CreatesObjectGroups | ||||
|      */ | ||||
|     protected function getObjectGroupMaxOrder(): int | ||||
|     { | ||||
|         return (int) $this->user->objectGroups()->max('order'); | ||||
|         return (int)$this->user->objectGroups()->max('order'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -91,4 +81,14 @@ trait CreatesObjectGroups | ||||
|     { | ||||
|         return 1 === $this->user->objectGroups()->where('title', $title)->count(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $title | ||||
|      * | ||||
|      * @return null|ObjectGroup | ||||
|      */ | ||||
|     protected function findObjectGroup(string $title): ?ObjectGroup | ||||
|     { | ||||
|         return $this->user->objectGroups()->where('title', $title)->first(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,6 +39,49 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface | ||||
|     /** @var User */ | ||||
|     private $user; | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function deleteAll(): void | ||||
|     { | ||||
|         $all = $this->get(); | ||||
|         /** @var ObjectGroup $group */ | ||||
|         foreach ($all as $group) { | ||||
|             $group->piggyBanks()->sync([]); | ||||
|             $group->bills()->sync([]); | ||||
|             $group->delete(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function deleteEmpty(): void | ||||
|     { | ||||
|         $all = $this->get(); | ||||
|         /** @var ObjectGroup $group */ | ||||
|         foreach ($all as $group) { | ||||
|             $count = DB::table('object_groupables')->where('object_groupables.object_group_id', $group->id)->count(); | ||||
|             if (0 === $count) { | ||||
|                 $group->delete(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroy(ObjectGroup $objectGroup): void | ||||
|     { | ||||
|         $list = $objectGroup->piggyBanks; | ||||
|         /** @var PiggyBank $piggy */ | ||||
|         foreach ($list as $piggy) { | ||||
|             $piggy->objectGroups()->sync([]); | ||||
|             $piggy->save(); | ||||
|         } | ||||
|         $objectGroup->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
| @@ -49,9 +92,25 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface | ||||
|                           ->orderBy('order', 'ASC')->orderBy('title', 'ASC')->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getBills(ObjectGroup $objectGroup): Collection | ||||
|     { | ||||
|         return $objectGroup->bills; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getPiggyBanks(ObjectGroup $objectGroup): Collection | ||||
|     { | ||||
|         return $objectGroup->piggyBanks; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int $limit | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -74,16 +133,15 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function deleteEmpty(): void | ||||
|     public function setOrder(ObjectGroup $objectGroup, int $order): ObjectGroup | ||||
|     { | ||||
|         $all = $this->get(); | ||||
|         /** @var ObjectGroup $group */ | ||||
|         foreach ($all as $group) { | ||||
|             $count = DB::table('object_groupables')->where('object_groupables.object_group_id', $group->id)->count(); | ||||
|             if (0 === $count) { | ||||
|                 $group->delete(); | ||||
|             } | ||||
|         } | ||||
|         $order              = 0 === $order ? 1 : $order; | ||||
|         $objectGroup->order = $order; | ||||
|         $objectGroup->save(); | ||||
|  | ||||
|         Log::debug(sprintf('Objectgroup #%d order is now %d', $objectGroup->id, $order)); | ||||
|  | ||||
|         return $objectGroup; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -102,20 +160,6 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function setOrder(ObjectGroup $objectGroup, int $order): ObjectGroup | ||||
|     { | ||||
|         $order              = 0 === $order ? 1 : $order; | ||||
|         $objectGroup->order = $order; | ||||
|         $objectGroup->save(); | ||||
|  | ||||
|         Log::debug(sprintf('Objectgroup #%d order is now %d', $objectGroup->id, $order)); | ||||
|  | ||||
|         return $objectGroup; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
| @@ -133,20 +177,6 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface | ||||
|         return $objectGroup; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroy(ObjectGroup $objectGroup): void | ||||
|     { | ||||
|         $list = $objectGroup->piggyBanks; | ||||
|         /** @var PiggyBank $piggy */ | ||||
|         foreach($list as $piggy) { | ||||
|             $piggy->objectGroups()->sync([]); | ||||
|             $piggy->save(); | ||||
|         } | ||||
|         $objectGroup->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
| @@ -154,34 +184,4 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface | ||||
|     { | ||||
|         $this->user = $user; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getPiggyBanks(ObjectGroup $objectGroup): Collection | ||||
|     { | ||||
|         return $objectGroup->piggyBanks; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getBills(ObjectGroup $objectGroup): Collection | ||||
|     { | ||||
|         return $objectGroup->bills; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function deleteAll(): void | ||||
|     { | ||||
|         $all = $this->get(); | ||||
|         /** @var ObjectGroup $group */ | ||||
|         foreach ($all as $group) { | ||||
|             $group->piggyBanks()->sync([]); | ||||
|             $group->bills()->sync([]); | ||||
|             $group->delete(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -32,34 +32,25 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| interface ObjectGroupRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function get(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function search(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Delete empty ones. | ||||
|      */ | ||||
|     public function deleteEmpty(): void; | ||||
|     /** | ||||
|      * Delete all. | ||||
|      */ | ||||
|     public function deleteAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * Delete empty ones. | ||||
|      */ | ||||
|     public function deleteEmpty(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param ObjectGroup $objectGroup | ||||
|      * | ||||
|      */ | ||||
|     public function destroy(ObjectGroup $objectGroup): void; | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getPiggyBanks(ObjectGroup $objectGroup): Collection; | ||||
|     public function get(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param ObjectGroup $objectGroup | ||||
| @@ -69,9 +60,19 @@ interface ObjectGroupRepositoryInterface | ||||
|     public function getBills(ObjectGroup $objectGroup): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Sort | ||||
|      * @param ObjectGroup $objectGroup | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function sort(): void; | ||||
|     public function getPiggyBanks(ObjectGroup $objectGroup): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function search(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param ObjectGroup $objectGroup | ||||
| @@ -81,6 +82,11 @@ interface ObjectGroupRepositoryInterface | ||||
|      */ | ||||
|     public function setOrder(ObjectGroup $objectGroup, int $index): ObjectGroup; | ||||
|  | ||||
|     /** | ||||
|      * Sort | ||||
|      */ | ||||
|     public function sort(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param ObjectGroup $objectGroup | ||||
|      * @param array       $data | ||||
| @@ -89,9 +95,4 @@ interface ObjectGroupRepositoryInterface | ||||
|      */ | ||||
|     public function update(ObjectGroup $objectGroup, array $data): ObjectGroup; | ||||
|  | ||||
|     /** | ||||
|      * @param ObjectGroup $objectGroup | ||||
|      */ | ||||
|     public function destroy(ObjectGroup $objectGroup): void; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -68,17 +68,6 @@ trait ModifiesPiggyBanks | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function removeObjectGroup(PiggyBank $piggyBank): PiggyBank | ||||
|     { | ||||
|         $piggyBank->objectGroups()->sync([]); | ||||
|  | ||||
|         return $piggyBank; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBankRepetition $repetition | ||||
|      * @param string              $amount | ||||
| @@ -188,7 +177,7 @@ trait ModifiesPiggyBanks | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return bool | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function destroy(PiggyBank $piggyBank): bool | ||||
|     { | ||||
| @@ -219,6 +208,16 @@ trait ModifiesPiggyBanks | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function removeObjectGroup(PiggyBank $piggyBank): PiggyBank | ||||
|     { | ||||
|         $piggyBank->objectGroups()->sync([]); | ||||
|  | ||||
|         return $piggyBank; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param string    $amount | ||||
| @@ -245,6 +244,20 @@ trait ModifiesPiggyBanks | ||||
|         return $piggyBank; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function setObjectGroup(PiggyBank $piggyBank, string $objectGroupTitle): PiggyBank | ||||
|     { | ||||
|         $objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle); | ||||
|         if (null !== $objectGroup) { | ||||
|             $piggyBank->objectGroups()->sync([$objectGroup->id]); | ||||
|         } | ||||
|  | ||||
|         return $piggyBank; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * set id of piggy bank. | ||||
|      * | ||||
| @@ -261,22 +274,6 @@ trait ModifiesPiggyBanks | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function setObjectGroup(PiggyBank $piggyBank, string $objectGroupTitle): PiggyBank | ||||
|     { | ||||
|         $objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle); | ||||
|         if (null !== $objectGroup) { | ||||
|             $piggyBank->objectGroups()->sync([$objectGroup->id]); | ||||
|         } | ||||
|  | ||||
|         return $piggyBank; | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
| @@ -328,32 +325,6 @@ trait ModifiesPiggyBanks | ||||
|         return $piggyBank; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param array     $data | ||||
|      * | ||||
|      * @return PiggyBank | ||||
|      */ | ||||
|     private function updateProperties(PiggyBank $piggyBank, array $data): PiggyBank | ||||
|     { | ||||
|         if (array_key_exists('name', $data) && '' !== $data['name']) { | ||||
|             $piggyBank->name = $data['name']; | ||||
|         } | ||||
|         if (array_key_exists('account_id', $data) && 0 !== $data['account_id']) { | ||||
|             $piggyBank->account_id = (int)$data['account_id']; | ||||
|         } | ||||
|         if (array_key_exists('targetamount', $data) && '' !== $data['targetamount']) { | ||||
|             $piggyBank->targetamount = $data['targetamount']; | ||||
|         } | ||||
|         if (array_key_exists('targetdate', $data) && '' !== $data['targetdate']) { | ||||
|             $piggyBank->targetdate = $data['targetdate']; | ||||
|         } | ||||
|         $piggyBank->startdate = $data['startdate'] ?? $piggyBank->startdate; | ||||
|         $piggyBank->save(); | ||||
|  | ||||
|         return $piggyBank; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param array     $data | ||||
| @@ -450,6 +421,32 @@ trait ModifiesPiggyBanks | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param array     $data | ||||
|      * | ||||
|      * @return PiggyBank | ||||
|      */ | ||||
|     private function updateProperties(PiggyBank $piggyBank, array $data): PiggyBank | ||||
|     { | ||||
|         if (array_key_exists('name', $data) && '' !== $data['name']) { | ||||
|             $piggyBank->name = $data['name']; | ||||
|         } | ||||
|         if (array_key_exists('account_id', $data) && 0 !== $data['account_id']) { | ||||
|             $piggyBank->account_id = (int)$data['account_id']; | ||||
|         } | ||||
|         if (array_key_exists('targetamount', $data) && '' !== $data['targetamount']) { | ||||
|             $piggyBank->targetamount = $data['targetamount']; | ||||
|         } | ||||
|         if (array_key_exists('targetdate', $data) && '' !== $data['targetdate']) { | ||||
|             $piggyBank->targetdate = $data['targetdate']; | ||||
|         } | ||||
|         $piggyBank->startdate = $data['startdate'] ?? $piggyBank->startdate; | ||||
|         $piggyBank->save(); | ||||
|  | ||||
|         return $piggyBank; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param int       $oldOrder | ||||
|   | ||||
| @@ -46,6 +46,14 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|  | ||||
|     private User $user; | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $this->user->piggyBanks()->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Find by name or return NULL. | ||||
|      * | ||||
| @@ -74,7 +82,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int|null $piggyBankId | ||||
|      * @param int|null    $piggyBankId | ||||
|      * @param string|null $piggyBankName | ||||
|      * | ||||
|      * @return PiggyBank|null | ||||
| @@ -104,6 +112,27 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttachments(PiggyBank $piggyBank): Collection | ||||
|     { | ||||
|         $set = $piggyBank->attachments()->get(); | ||||
|  | ||||
|         /** @var Storage $disk */ | ||||
|         $disk = Storage::disk('upload'); | ||||
|  | ||||
|         return $set->each( | ||||
|             static function (Attachment $attachment) use ($disk) { | ||||
|                 $notes                   = $attachment->notes()->first(); | ||||
|                 $attachment->file_exists = $disk->exists($attachment->fileName()); | ||||
|                 $attachment->notes       = $notes ? $notes->text : ''; | ||||
|  | ||||
|                 return $attachment; | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get current amount saved in piggy bank. | ||||
|      * | ||||
| @@ -134,9 +163,9 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|     /** | ||||
|      * Used for connecting to a piggy bank. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param PiggyBank           $piggyBank | ||||
|      * @param PiggyBankRepetition $repetition | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param TransactionJournal  $journal | ||||
|      * | ||||
|      * @return string | ||||
|      * | ||||
| @@ -155,7 +184,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|         $accountRepos = app(AccountRepositoryInterface::class); | ||||
|         $accountRepos->setUser($this->user); | ||||
|  | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user); | ||||
|         $defaultCurrency   = app('amount')->getDefaultCurrencyByUser($this->user); | ||||
|         $piggyBankCurrency = $accountRepos->getAccountCurrency($piggyBank->account) ?? $defaultCurrency; | ||||
|  | ||||
|         Log::debug(sprintf('Piggy bank #%d currency is %s', $piggyBank->id, $piggyBankCurrency->code)); | ||||
| @@ -180,6 +209,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|         } | ||||
|         if (null === $operator || null === $currency) { | ||||
|             Log::debug('Currency is NULL and operator is NULL, return "0".'); | ||||
|  | ||||
|             return '0'; | ||||
|         } | ||||
|         // currency of the account + the piggy bank currency are almost the same. | ||||
| @@ -195,13 +225,14 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|         } | ||||
|         if (null === $amount) { | ||||
|             Log::debug('No match on currency, so amount remains null, return "0".'); | ||||
|  | ||||
|             return '0'; | ||||
|         } | ||||
|  | ||||
|         Log::debug(sprintf('The currency is %s and the amount is %s', $currency->code, $amount)); | ||||
|  | ||||
|  | ||||
|         $room = bcsub((string)$piggyBank->targetamount, (string)$repetition->currentamount); | ||||
|         $room    = bcsub((string)$piggyBank->targetamount, (string)$repetition->currentamount); | ||||
|         $compare = bcmul($repetition->currentamount, '-1'); | ||||
|         Log::debug(sprintf('Will add/remove %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name)); | ||||
|  | ||||
| @@ -211,6 +242,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|             Log::debug(sprintf('Room in piggy bank for extra money is %f', $room)); | ||||
|             Log::debug(sprintf('There is NO room to add %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name)); | ||||
|             Log::debug(sprintf('New amount is %f', $room)); | ||||
|  | ||||
|             return $room; | ||||
|         } | ||||
|  | ||||
| @@ -219,6 +251,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|             Log::debug(sprintf('Max amount to remove is %f', $repetition->currentamount)); | ||||
|             Log::debug(sprintf('Cannot remove %f from piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name)); | ||||
|             Log::debug(sprintf('New amount is %f', $compare)); | ||||
|  | ||||
|             return $compare; | ||||
|         } | ||||
|  | ||||
| @@ -259,7 +292,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|         return $this->user->piggyBanks()->with(['account', 'objectGroups'])->orderBy('order', 'ASC')->get(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Also add amount in name. | ||||
|      * | ||||
| @@ -275,7 +307,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|         /** @var PiggyBank $piggy */ | ||||
|         foreach ($set as $piggy) { | ||||
|             $currentAmount = $this->getRepetition($piggy)->currentamount ?? '0'; | ||||
|             $piggy->name = $piggy->name . ' (' . app('amount')->formatAnything($currency, $currentAmount, false) . ')'; | ||||
|             $piggy->name   = $piggy->name . ' (' . app('amount')->formatAnything($currency, $currentAmount, false) . ')'; | ||||
|         } | ||||
|  | ||||
|  | ||||
| @@ -303,13 +335,13 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|     public function getSuggestedMonthlyAmount(PiggyBank $piggyBank): string | ||||
|     { | ||||
|         $savePerMonth = '0'; | ||||
|         $repetition = $this->getRepetition($piggyBank); | ||||
|         $repetition   = $this->getRepetition($piggyBank); | ||||
|         if (null === $repetition) { | ||||
|             return $savePerMonth; | ||||
|         } | ||||
|         if (null !== $piggyBank->targetdate && $repetition->currentamount < $piggyBank->targetamount) { | ||||
|             $now = Carbon::now(); | ||||
|             $diffInMonths = $now->diffInMonths($piggyBank->targetdate, false); | ||||
|             $now             = Carbon::now(); | ||||
|             $diffInMonths    = $now->diffInMonths($piggyBank->targetdate, false); | ||||
|             $remainingAmount = bcsub($piggyBank->targetamount, $repetition->currentamount); | ||||
|  | ||||
|             // more than 1 month to go and still need money to save: | ||||
| @@ -330,7 +362,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|      * Get for piggy account what is left to put in piggies. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param Carbon $date | ||||
|      * @param Carbon    $date | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
| @@ -353,45 +385,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|         return $balance; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function setUser(User $user): void | ||||
|     { | ||||
|         $this->user = $user; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttachments(PiggyBank $piggyBank): Collection | ||||
|     { | ||||
|         $set = $piggyBank->attachments()->get(); | ||||
|  | ||||
|         /** @var Storage $disk */ | ||||
|         $disk = Storage::disk('upload'); | ||||
|  | ||||
|         return $set->each( | ||||
|             static function (Attachment $attachment) use ($disk) { | ||||
|                 $notes = $attachment->notes()->first(); | ||||
|                 $attachment->file_exists = $disk->exists($attachment->fileName()); | ||||
|                 $attachment->notes = $notes ? $notes->text : ''; | ||||
|  | ||||
|                 return $attachment; | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $this->user->piggyBanks()->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
| @@ -402,8 +395,16 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|             $search->where('piggy_banks.name', 'LIKE', sprintf('%%%s%%', $query)); | ||||
|         } | ||||
|         $search->orderBy('piggy_banks.order', 'ASC') | ||||
|             ->orderBy('piggy_banks.name', 'ASC'); | ||||
|                ->orderBy('piggy_banks.name', 'ASC'); | ||||
|  | ||||
|         return $search->take($limit)->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function setUser(User $user): void | ||||
|     { | ||||
|         $this->user = $user; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -36,41 +36,6 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| interface PiggyBankRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param string    $objectGroupTitle | ||||
|      * | ||||
|      * @return PiggyBank | ||||
|      */ | ||||
|     public function setObjectGroup(PiggyBank $piggyBank, string $objectGroupTitle): PiggyBank; | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return PiggyBank | ||||
|      */ | ||||
|     public function removeObjectGroup(PiggyBank $piggyBank): PiggyBank; | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param string    $amount | ||||
|      * | ||||
|      * @return PiggyBank | ||||
|      */ | ||||
|     public function setCurrentAmount(PiggyBank $piggyBank, string $amount): PiggyBank; | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttachments(PiggyBank $piggyBank): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param string    $amount | ||||
| @@ -136,6 +101,11 @@ interface PiggyBankRepositoryInterface | ||||
|      */ | ||||
|     public function destroy(PiggyBank $piggyBank): bool; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * Find by name or return NULL. | ||||
|      * | ||||
| @@ -145,16 +115,6 @@ interface PiggyBankRepositoryInterface | ||||
|      */ | ||||
|     public function findByName(string $name): ?PiggyBank; | ||||
|  | ||||
|     /** | ||||
|      * Search for piggy banks. | ||||
|      * | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchPiggyBank(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param int $piggyBankId | ||||
|      * | ||||
| @@ -163,13 +123,20 @@ interface PiggyBankRepositoryInterface | ||||
|     public function findNull(int $piggyBankId): ?PiggyBank; | ||||
|  | ||||
|     /** | ||||
|      * @param int|null       $piggyBankId | ||||
|      * @param string|null    $piggyBankName | ||||
|      * @param int|null    $piggyBankId | ||||
|      * @param string|null $piggyBankName | ||||
|      * | ||||
|      * @return PiggyBank|null | ||||
|      */ | ||||
|     public function findPiggyBank(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank; | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttachments(PiggyBank $piggyBank): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Get current amount saved in piggy bank. | ||||
|      * | ||||
| @@ -263,6 +230,39 @@ interface PiggyBankRepositoryInterface | ||||
|      */ | ||||
|     public function removeAmount(PiggyBank $piggyBank, string $amount): bool; | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return PiggyBank | ||||
|      */ | ||||
|     public function removeObjectGroup(PiggyBank $piggyBank): PiggyBank; | ||||
|  | ||||
|     /** | ||||
|      * Search for piggy banks. | ||||
|      * | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchPiggyBank(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param string    $amount | ||||
|      * | ||||
|      * @return PiggyBank | ||||
|      */ | ||||
|     public function setCurrentAmount(PiggyBank $piggyBank, string $amount): PiggyBank; | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param string    $objectGroupTitle | ||||
|      * | ||||
|      * @return PiggyBank | ||||
|      */ | ||||
|     public function setObjectGroup(PiggyBank $piggyBank, string $objectGroupTitle): PiggyBank; | ||||
|  | ||||
|     /** | ||||
|      * Set specific piggy bank to specific order. | ||||
|      * | ||||
|   | ||||
| @@ -69,6 +69,14 @@ class RecurringRepository implements RecurringRepositoryInterface | ||||
|         $service->destroy($recurrence); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $this->user->recurrences()->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns all of the user's recurring transactions. | ||||
|      * | ||||
| @@ -378,6 +386,50 @@ class RecurringRepository implements RecurringRepositoryInterface | ||||
|         return $this->filterWeekends($repetition, $occurrences); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Calculate the next X iterations starting on the date given in $date. | ||||
|      * Returns an array of Carbon objects. | ||||
|      * | ||||
|      * Only returns them of they are after $afterDate | ||||
|      * | ||||
|      * @param RecurrenceRepetition $repetition | ||||
|      * @param Carbon               $date | ||||
|      * @param Carbon               $afterDate | ||||
|      * @param int                  $count | ||||
|      * | ||||
|      * @return array | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function getXOccurrencesSince(RecurrenceRepetition $repetition, Carbon $date, Carbon $afterDate, int $count): array | ||||
|     { | ||||
|         Log::debug('Now in getXOccurrencesSince()'); | ||||
|         $skipMod     = $repetition->repetition_skip + 1; | ||||
|         $occurrences = []; | ||||
|         if ('daily' === $repetition->repetition_type) { | ||||
|             $occurrences = $this->getXDailyOccurrencesSince($date, $afterDate, $count, $skipMod); | ||||
|         } | ||||
|         if ('weekly' === $repetition->repetition_type) { | ||||
|             $occurrences = $this->getXWeeklyOccurrencesSince($date, $afterDate, $count, $skipMod, $repetition->repetition_moment); | ||||
|         } | ||||
|         if ('monthly' === $repetition->repetition_type) { | ||||
|             $occurrences = $this->getXMonthlyOccurrencesSince($date, $afterDate, $count, $skipMod, $repetition->repetition_moment); | ||||
|         } | ||||
|         if ('ndom' === $repetition->repetition_type) { | ||||
|             $occurrences = $this->getXNDomOccurrencesSince($date, $afterDate, $count, $skipMod, $repetition->repetition_moment); | ||||
|         } | ||||
|         if ('yearly' === $repetition->repetition_type) { | ||||
|             $occurrences = $this->getXYearlyOccurrencesSince($date, $afterDate, $count, $skipMod, $repetition->repetition_moment); | ||||
|         } | ||||
|  | ||||
|         // filter out all the weekend days: | ||||
|         $occurrences = $this->filterWeekends($repetition, $occurrences); | ||||
|  | ||||
|         // filter out everything if "repeat_until" is set. | ||||
|         $repeatUntil = $repetition->recurrence->repeat_until; | ||||
|  | ||||
|         return $this->filterMaxDate($repeatUntil, $occurrences); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parse the repetition in a string that is user readable. | ||||
|      * | ||||
| @@ -437,6 +489,21 @@ class RecurringRepository implements RecurringRepositoryInterface | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function searchRecurrence(string $query, int $limit): Collection | ||||
|     { | ||||
|         $search = $this->user->recurrences(); | ||||
|         if ('' !== $query) { | ||||
|             $search->where('recurrences.title', 'LIKE', sprintf('%%%s%%', $query)); | ||||
|         } | ||||
|         $search | ||||
|             ->orderBy('recurrences.title', 'ASC'); | ||||
|  | ||||
|         return $search->take($limit)->get(['id', 'title', 'description']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set user for in repository. | ||||
|      * | ||||
| @@ -466,96 +533,6 @@ class RecurringRepository implements RecurringRepositoryInterface | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a recurring transaction. | ||||
|      * | ||||
|      * @param Recurrence $recurrence | ||||
|      * @param array      $data | ||||
|      * | ||||
|      * @return Recurrence | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(Recurrence $recurrence, array $data): Recurrence | ||||
|     { | ||||
|         /** @var RecurrenceUpdateService $service */ | ||||
|         $service = app(RecurrenceUpdateService::class); | ||||
|  | ||||
|         return $service->update($recurrence, $data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Calculate the next X iterations starting on the date given in $date. | ||||
|      * Returns an array of Carbon objects. | ||||
|      * | ||||
|      * Only returns them of they are after $afterDate | ||||
|      * | ||||
|      * @param RecurrenceRepetition $repetition | ||||
|      * @param Carbon               $date | ||||
|      * @param Carbon               $afterDate | ||||
|      * @param int                  $count | ||||
|      * | ||||
|      * @return array | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function getXOccurrencesSince(RecurrenceRepetition $repetition, Carbon $date, Carbon $afterDate, int $count): array | ||||
|     { | ||||
|         Log::debug('Now in getXOccurrencesSince()'); | ||||
|         $skipMod     = $repetition->repetition_skip + 1; | ||||
|         $occurrences = []; | ||||
|         if ('daily' === $repetition->repetition_type) { | ||||
|             $occurrences = $this->getXDailyOccurrencesSince($date, $afterDate, $count, $skipMod); | ||||
|         } | ||||
|         if ('weekly' === $repetition->repetition_type) { | ||||
|             $occurrences = $this->getXWeeklyOccurrencesSince($date, $afterDate, $count, $skipMod, $repetition->repetition_moment); | ||||
|         } | ||||
|         if ('monthly' === $repetition->repetition_type) { | ||||
|             $occurrences = $this->getXMonthlyOccurrencesSince($date, $afterDate, $count, $skipMod, $repetition->repetition_moment); | ||||
|         } | ||||
|         if ('ndom' === $repetition->repetition_type) { | ||||
|             $occurrences = $this->getXNDomOccurrencesSince($date, $afterDate, $count, $skipMod, $repetition->repetition_moment); | ||||
|         } | ||||
|         if ('yearly' === $repetition->repetition_type) { | ||||
|             $occurrences = $this->getXYearlyOccurrencesSince($date, $afterDate, $count, $skipMod, $repetition->repetition_moment); | ||||
|         } | ||||
|  | ||||
|         // filter out all the weekend days: | ||||
|         $occurrences = $this->filterWeekends($repetition, $occurrences); | ||||
|  | ||||
|         // filter out everything if "repeat_until" is set. | ||||
|         $repeatUntil = $repetition->recurrence->repeat_until; | ||||
|  | ||||
|         return $this->filterMaxDate($repeatUntil, $occurrences); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon|null $max | ||||
|      * @param array       $occurrences | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function filterMaxDate(?Carbon $max, array $occurrences): array | ||||
|     { | ||||
|         if (null === $max) { | ||||
|             return $occurrences; | ||||
|         } | ||||
|         $filtered = []; | ||||
|         foreach ($occurrences as $date) { | ||||
|             if ($date->lte($max)) { | ||||
|                 $filtered[] = $date; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $filtered; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $this->user->recurrences()->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
| @@ -581,17 +558,40 @@ class RecurringRepository implements RecurringRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      * Update a recurring transaction. | ||||
|      * | ||||
|      * @param Recurrence $recurrence | ||||
|      * @param array      $data | ||||
|      * | ||||
|      * @return Recurrence | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function searchRecurrence(string $query, int $limit): Collection | ||||
|     public function update(Recurrence $recurrence, array $data): Recurrence | ||||
|     { | ||||
|         $search = $this->user->recurrences(); | ||||
|         if ('' !== $query) { | ||||
|             $search->where('recurrences.title', 'LIKE', sprintf('%%%s%%', $query)); | ||||
|         } | ||||
|         $search | ||||
|             ->orderBy('recurrences.title', 'ASC'); | ||||
|         /** @var RecurrenceUpdateService $service */ | ||||
|         $service = app(RecurrenceUpdateService::class); | ||||
|  | ||||
|         return $search->take($limit)->get(['id', 'title', 'description']); | ||||
|         return $service->update($recurrence, $data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon|null $max | ||||
|      * @param array       $occurrences | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function filterMaxDate(?Carbon $max, array $occurrences): array | ||||
|     { | ||||
|         if (null === $max) { | ||||
|             return $occurrences; | ||||
|         } | ||||
|         $filtered = []; | ||||
|         foreach ($occurrences as $date) { | ||||
|             if ($date->lte($max)) { | ||||
|                 $filtered[] = $date; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $filtered; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,28 +39,6 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| interface RecurringRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * Destroy all recurring transactions. | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchRecurrence(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Calculate how many transactions are to be expected from this recurrence. | ||||
|      * | ||||
|      * @param Recurrence $recurrence | ||||
|      * @param RecurrenceRepetition $repetition | ||||
|      * @return int | ||||
|      */ | ||||
|     public function totalTransactions(Recurrence $recurrence, RecurrenceRepetition $repetition): int; | ||||
|  | ||||
|     /** | ||||
|      * Destroy a recurring transaction. | ||||
|      * | ||||
| @@ -68,6 +46,11 @@ interface RecurringRepositoryInterface | ||||
|      */ | ||||
|     public function destroy(Recurrence $recurrence): void; | ||||
|  | ||||
|     /** | ||||
|      * Destroy all recurring transactions. | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * Returns all of the user's recurring transactions. | ||||
|      * | ||||
| @@ -142,6 +125,7 @@ interface RecurringRepositoryInterface | ||||
|  | ||||
|     /** | ||||
|      * @param RecurrenceTransaction $transaction | ||||
|      * | ||||
|      * @return int|null | ||||
|      */ | ||||
|     public function getPiggyBank(RecurrenceTransaction $transaction): ?int; | ||||
| @@ -179,8 +163,8 @@ interface RecurringRepositoryInterface | ||||
|      * @param Carbon               $date | ||||
|      * @param int                  $count | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return array | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function getXOccurrences(RecurrenceRepetition $repetition, Carbon $date, int $count): array; | ||||
|  | ||||
| @@ -192,13 +176,13 @@ interface RecurringRepositoryInterface | ||||
|      * | ||||
|      * @param RecurrenceRepetition $repetition | ||||
|      * @param Carbon               $date | ||||
|      * @param Carbon $afterDate | ||||
|      * @param Carbon               $afterDate | ||||
|      * @param int                  $count | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return array | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function getXOccurrencesSince(RecurrenceRepetition $repetition, Carbon $date,Carbon $afterDate, int $count): array; | ||||
|     public function getXOccurrencesSince(RecurrenceRepetition $repetition, Carbon $date, Carbon $afterDate, int $count): array; | ||||
|  | ||||
|     /** | ||||
|      * Parse the repetition in a string that is user readable. | ||||
| @@ -209,6 +193,14 @@ interface RecurringRepositoryInterface | ||||
|      */ | ||||
|     public function repetitionDescription(RecurrenceRepetition $repetition): string; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchRecurrence(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Set user for in repository. | ||||
|      * | ||||
| @@ -220,11 +212,22 @@ interface RecurringRepositoryInterface | ||||
|      * Store a new recurring transaction. | ||||
|      * | ||||
|      * @param array $data | ||||
|      * @throws FireflyException | ||||
|      * | ||||
|      * @return Recurrence | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(array $data): Recurrence; | ||||
|  | ||||
|     /** | ||||
|      * Calculate how many transactions are to be expected from this recurrence. | ||||
|      * | ||||
|      * @param Recurrence           $recurrence | ||||
|      * @param RecurrenceRepetition $repetition | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function totalTransactions(Recurrence $recurrence, RecurrenceRepetition $repetition): int; | ||||
|  | ||||
|     /** | ||||
|      * Update a recurring transaction. | ||||
|      * | ||||
|   | ||||
| @@ -22,6 +22,7 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Repositories\Rule; | ||||
|  | ||||
| use Exception; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Models\RuleAction; | ||||
| @@ -52,7 +53,7 @@ class RuleRepository implements RuleRepositoryInterface | ||||
|      * @param Rule $rule | ||||
|      * | ||||
|      * @return bool | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function destroy(Rule $rule): bool | ||||
|     { | ||||
| @@ -67,6 +68,34 @@ class RuleRepository implements RuleRepositoryInterface | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function duplicate(Rule $rule): Rule | ||||
|     { | ||||
|         $newRule        = $rule->replicate(); | ||||
|         $newRule->title = (string)trans('firefly.rule_copy_of', ['title' => $rule->title]); | ||||
|         $newRule->save(); | ||||
|  | ||||
|         // replicate all triggers | ||||
|         /** @var RuleTrigger $trigger */ | ||||
|         foreach ($rule->ruleTriggers as $trigger) { | ||||
|             $newTrigger          = $trigger->replicate(); | ||||
|             $newTrigger->rule_id = $newRule->id; | ||||
|             $newTrigger->save(); | ||||
|         } | ||||
|  | ||||
|         // replicate all actions | ||||
|         /** @var RuleAction $action */ | ||||
|         foreach ($rule->ruleActions as $action) { | ||||
|             $newAction          = $action->replicate(); | ||||
|             $newAction->rule_id = $newRule->id; | ||||
|             $newAction->save(); | ||||
|         } | ||||
|  | ||||
|         return $newRule; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $ruleId | ||||
|      * | ||||
| @@ -149,6 +178,84 @@ class RuleRepository implements RuleRepositoryInterface | ||||
|         return $rule->ruleTriggers()->orderBy('order', 'ASC')->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getSearchQuery(Rule $rule): string | ||||
|     { | ||||
|         $params = []; | ||||
|         /** @var RuleTrigger $trigger */ | ||||
|         foreach ($rule->ruleTriggers as $trigger) { | ||||
|             if ('user_action' === $trigger->trigger_type) { | ||||
|                 continue; | ||||
|             } | ||||
|             $needsContext = config(sprintf('firefly.search.operators.%s.needs_context', $trigger->trigger_type)) ?? true; | ||||
|             if (false === $needsContext) { | ||||
|                 $params[] = sprintf('%s:true', OperatorQuerySearch::getRootOperator($trigger->trigger_type)); | ||||
|             } | ||||
|             if (true === $needsContext) { | ||||
|                 $params[] = sprintf('%s:"%s"', OperatorQuerySearch::getRootOperator($trigger->trigger_type), $trigger->trigger_value); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return implode(' ', $params); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getStoreRules(): Collection | ||||
|     { | ||||
|         $collection = $this->user->rules() | ||||
|                                  ->leftJoin('rule_groups', 'rule_groups.id', '=', 'rules.rule_group_id') | ||||
|                                  ->where('rules.active', 1) | ||||
|                                  ->where('rule_groups.active', 1) | ||||
|                                  ->orderBy('rule_groups.order', 'ASC') | ||||
|                                  ->orderBy('rules.order', 'ASC') | ||||
|                                  ->orderBy('rules.id', 'ASC') | ||||
|                                  ->with(['ruleGroup', 'ruleTriggers'])->get(['rules.*']); | ||||
|         $filtered   = new Collection; | ||||
|         /** @var Rule $rule */ | ||||
|         foreach ($collection as $rule) { | ||||
|             /** @var RuleTrigger $ruleTrigger */ | ||||
|             foreach ($rule->ruleTriggers as $ruleTrigger) { | ||||
|                 if ('user_action' === $ruleTrigger->trigger_type && 'store-journal' === $ruleTrigger->trigger_value) { | ||||
|                     $filtered->push($rule); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $filtered; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getUpdateRules(): Collection | ||||
|     { | ||||
|         $collection = $this->user->rules() | ||||
|                                  ->leftJoin('rule_groups', 'rule_groups.id', '=', 'rules.rule_group_id') | ||||
|                                  ->where('rules.active', 1) | ||||
|                                  ->where('rule_groups.active', 1) | ||||
|                                  ->orderBy('rule_groups.order', 'ASC') | ||||
|                                  ->orderBy('rules.order', 'ASC') | ||||
|                                  ->orderBy('rules.id', 'ASC') | ||||
|                                  ->with(['ruleGroup', 'ruleTriggers'])->get(); | ||||
|         $filtered   = new Collection; | ||||
|         /** @var Rule $rule */ | ||||
|         foreach ($collection as $rule) { | ||||
|             /** @var RuleTrigger $ruleTrigger */ | ||||
|             foreach ($rule->ruleTriggers as $ruleTrigger) { | ||||
|                 if ('user_action' === $ruleTrigger->trigger_type && 'update-journal' === $ruleTrigger->trigger_value) { | ||||
|                     $filtered->push($rule); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $filtered; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Rule $rule | ||||
|      * | ||||
| @@ -172,6 +279,20 @@ class RuleRepository implements RuleRepositoryInterface | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function moveRule(Rule $rule, RuleGroup $ruleGroup, int $order): Rule | ||||
|     { | ||||
|         $rule->order = $order; | ||||
|         if ($rule->rule_group_id !== $ruleGroup->id) { | ||||
|             $rule->rule_group_id = $ruleGroup->id; | ||||
|         } | ||||
|         $rule->save(); | ||||
|  | ||||
|         return $rule; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Rule $rule | ||||
|      * | ||||
| @@ -263,6 +384,21 @@ class RuleRepository implements RuleRepositoryInterface | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function searchRule(string $query, int $limit): Collection | ||||
|     { | ||||
|         $search = $this->user->rules(); | ||||
|         if ('' !== $query) { | ||||
|             $search->where('rules.title', 'LIKE', sprintf('%%%s%%', $query)); | ||||
|         } | ||||
|         $search->orderBy('rules.order', 'ASC') | ||||
|                ->orderBy('rules.title', 'ASC'); | ||||
|  | ||||
|         return $search->take($limit)->get(['id', 'title', 'description']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
| @@ -397,27 +533,33 @@ class RuleRepository implements RuleRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $moment | ||||
|      * @param Rule   $rule | ||||
|      * @param Rule  $rule | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     private function setRuleTrigger(string $moment, Rule $rule): void | ||||
|     private function storeTriggers(Rule $rule, array $data): bool | ||||
|     { | ||||
|         /** @var RuleTrigger $trigger */ | ||||
|         $trigger = $rule->ruleTriggers()->where('trigger_type', 'user_action')->first(); | ||||
|         if (null !== $trigger) { | ||||
|             $trigger->trigger_value = $moment; | ||||
|             $trigger->save(); | ||||
|         $order = 1; | ||||
|         foreach ($data['triggers'] as $trigger) { | ||||
|             $value          = $trigger['value'] ?? ''; | ||||
|             $stopProcessing = $trigger['stop_processing'] ?? false; | ||||
|             $active         = $trigger['active'] ?? true; | ||||
|  | ||||
|             return; | ||||
|             $triggerValues = [ | ||||
|                 'action'          => $trigger['type'], | ||||
|                 'value'           => $value, | ||||
|                 'stop_processing' => $stopProcessing, | ||||
|                 'order'           => $order, | ||||
|                 'active'          => $active, | ||||
|             ]; | ||||
|             app('telemetry')->feature('rules.triggers.uses_trigger', $trigger['type']); | ||||
|  | ||||
|             $this->storeTrigger($rule, $triggerValues); | ||||
|             ++$order; | ||||
|         } | ||||
|         $trigger                  = new RuleTrigger; | ||||
|         $trigger->order           = 0; | ||||
|         $trigger->trigger_type    = 'user_action'; | ||||
|         $trigger->trigger_value   = $moment; | ||||
|         $trigger->rule_id         = $rule->id; | ||||
|         $trigger->active          = true; | ||||
|         $trigger->stop_processing = false; | ||||
|         $trigger->save(); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -450,167 +592,26 @@ class RuleRepository implements RuleRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Rule  $rule | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return bool | ||||
|      * @param string $moment | ||||
|      * @param Rule   $rule | ||||
|      */ | ||||
|     private function storeTriggers(Rule $rule, array $data): bool | ||||
|     private function setRuleTrigger(string $moment, Rule $rule): void | ||||
|     { | ||||
|         $order = 1; | ||||
|         foreach ($data['triggers'] as $trigger) { | ||||
|             $value          = $trigger['value'] ?? ''; | ||||
|             $stopProcessing = $trigger['stop_processing'] ?? false; | ||||
|             $active         = $trigger['active'] ?? true; | ||||
|  | ||||
|             $triggerValues = [ | ||||
|                 'action'          => $trigger['type'], | ||||
|                 'value'           => $value, | ||||
|                 'stop_processing' => $stopProcessing, | ||||
|                 'order'           => $order, | ||||
|                 'active'          => $active, | ||||
|             ]; | ||||
|             app('telemetry')->feature('rules.triggers.uses_trigger', $trigger['type']); | ||||
|  | ||||
|             $this->storeTrigger($rule, $triggerValues); | ||||
|             ++$order; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function duplicate(Rule $rule): Rule | ||||
|     { | ||||
|         $newRule        = $rule->replicate(); | ||||
|         $newRule->title = (string)trans('firefly.rule_copy_of', ['title' => $rule->title]); | ||||
|         $newRule->save(); | ||||
|  | ||||
|         // replicate all triggers | ||||
|         /** @var RuleTrigger $trigger */ | ||||
|         foreach ($rule->ruleTriggers as $trigger) { | ||||
|             $newTrigger          = $trigger->replicate(); | ||||
|             $newTrigger->rule_id = $newRule->id; | ||||
|             $newTrigger->save(); | ||||
|         $trigger = $rule->ruleTriggers()->where('trigger_type', 'user_action')->first(); | ||||
|         if (null !== $trigger) { | ||||
|             $trigger->trigger_value = $moment; | ||||
|             $trigger->save(); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // replicate all actions | ||||
|         /** @var RuleAction $action */ | ||||
|         foreach ($rule->ruleActions as $action) { | ||||
|             $newAction          = $action->replicate(); | ||||
|             $newAction->rule_id = $newRule->id; | ||||
|             $newAction->save(); | ||||
|         } | ||||
|  | ||||
|         return $newRule; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function moveRule(Rule $rule, RuleGroup $ruleGroup, int $order): Rule | ||||
|     { | ||||
|         $rule->order = $order; | ||||
|         if ($rule->rule_group_id !== $ruleGroup->id) { | ||||
|             $rule->rule_group_id = $ruleGroup->id; | ||||
|         } | ||||
|         $rule->save(); | ||||
|  | ||||
|         return $rule; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getStoreRules(): Collection | ||||
|     { | ||||
|         $collection = $this->user->rules() | ||||
|                                  ->leftJoin('rule_groups', 'rule_groups.id', '=', 'rules.rule_group_id') | ||||
|                                  ->where('rules.active', 1) | ||||
|                                  ->where('rule_groups.active', 1) | ||||
|                                  ->orderBy('rule_groups.order', 'ASC') | ||||
|                                  ->orderBy('rules.order', 'ASC') | ||||
|                                  ->orderBy('rules.id', 'ASC') | ||||
|                                  ->with(['ruleGroup', 'ruleTriggers'])->get(['rules.*']); | ||||
|         $filtered   = new Collection; | ||||
|         /** @var Rule $rule */ | ||||
|         foreach ($collection as $rule) { | ||||
|             /** @var RuleTrigger $ruleTrigger */ | ||||
|             foreach ($rule->ruleTriggers as $ruleTrigger) { | ||||
|                 if ('user_action' === $ruleTrigger->trigger_type && 'store-journal' === $ruleTrigger->trigger_value) { | ||||
|                     $filtered->push($rule); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $filtered; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getUpdateRules(): Collection | ||||
|     { | ||||
|         $collection = $this->user->rules() | ||||
|                                  ->leftJoin('rule_groups', 'rule_groups.id', '=', 'rules.rule_group_id') | ||||
|                                  ->where('rules.active', 1) | ||||
|                                  ->where('rule_groups.active', 1) | ||||
|                                  ->orderBy('rule_groups.order', 'ASC') | ||||
|                                  ->orderBy('rules.order', 'ASC') | ||||
|                                  ->orderBy('rules.id', 'ASC') | ||||
|                                  ->with(['ruleGroup', 'ruleTriggers'])->get(); | ||||
|         $filtered   = new Collection; | ||||
|         /** @var Rule $rule */ | ||||
|         foreach ($collection as $rule) { | ||||
|             /** @var RuleTrigger $ruleTrigger */ | ||||
|             foreach ($rule->ruleTriggers as $ruleTrigger) { | ||||
|                 if ('user_action' === $ruleTrigger->trigger_type && 'update-journal' === $ruleTrigger->trigger_value) { | ||||
|                     $filtered->push($rule); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $filtered; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getSearchQuery(Rule $rule): string | ||||
|     { | ||||
|         $params = []; | ||||
|         /** @var RuleTrigger $trigger */ | ||||
|         foreach ($rule->ruleTriggers as $trigger) { | ||||
|             if ('user_action' === $trigger->trigger_type) { | ||||
|                 continue; | ||||
|             } | ||||
|             $needsContext = config(sprintf('firefly.search.operators.%s.needs_context', $trigger->trigger_type)) ?? true; | ||||
|             if (false === $needsContext) { | ||||
|                 $params[] = sprintf('%s:true', OperatorQuerySearch::getRootOperator($trigger->trigger_type)); | ||||
|             } | ||||
|             if (true === $needsContext) { | ||||
|                 $params[] = sprintf('%s:"%s"', OperatorQuerySearch::getRootOperator($trigger->trigger_type), $trigger->trigger_value); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return implode(' ', $params); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function searchRule(string $query, int $limit): Collection | ||||
|     { | ||||
|         $search = $this->user->rules(); | ||||
|         if ('' !== $query) { | ||||
|             $search->where('rules.title', 'LIKE', sprintf('%%%s%%', $query)); | ||||
|         } | ||||
|         $search->orderBy('rules.order', 'ASC') | ||||
|                ->orderBy('rules.title', 'ASC'); | ||||
|  | ||||
|         return $search->take($limit)->get(['id', 'title', 'description']); | ||||
|         $trigger                  = new RuleTrigger; | ||||
|         $trigger->order           = 0; | ||||
|         $trigger->trigger_type    = 'user_action'; | ||||
|         $trigger->trigger_value   = $moment; | ||||
|         $trigger->rule_id         = $rule->id; | ||||
|         $trigger->active          = true; | ||||
|         $trigger->stop_processing = false; | ||||
|         $trigger->save(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,31 +39,6 @@ interface RuleRepositoryInterface | ||||
|      */ | ||||
|     public function count(): int; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchRule(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Return search query for rule. | ||||
|      * | ||||
|      * @param Rule $rule | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getSearchQuery(Rule $rule): string; | ||||
|  | ||||
|     /** | ||||
|      * @param Rule      $rule | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * @param int       $order | ||||
|      * | ||||
|      * @return Rule | ||||
|      */ | ||||
|     public function moveRule(Rule $rule, RuleGroup $ruleGroup, int $order): Rule; | ||||
|  | ||||
|     /** | ||||
|      * @param Rule $rule | ||||
|      * | ||||
| @@ -92,20 +67,6 @@ interface RuleRepositoryInterface | ||||
|      */ | ||||
|     public function getAll(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Get all the users rules that trigger on storage. | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getStoreRules(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Get all the users rules that trigger on update. | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getUpdateRules(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @return RuleGroup | ||||
|      */ | ||||
| @@ -139,6 +100,29 @@ interface RuleRepositoryInterface | ||||
|      */ | ||||
|     public function getRuleTriggers(Rule $rule): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Return search query for rule. | ||||
|      * | ||||
|      * @param Rule $rule | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getSearchQuery(Rule $rule): string; | ||||
|  | ||||
|     /** | ||||
|      * Get all the users rules that trigger on storage. | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getStoreRules(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Get all the users rules that trigger on update. | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getUpdateRules(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Rule $rule | ||||
|      * | ||||
| @@ -146,6 +130,15 @@ interface RuleRepositoryInterface | ||||
|      */ | ||||
|     public function moveDown(Rule $rule): bool; | ||||
|  | ||||
|     /** | ||||
|      * @param Rule      $rule | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * @param int       $order | ||||
|      * | ||||
|      * @return Rule | ||||
|      */ | ||||
|     public function moveRule(Rule $rule, RuleGroup $ruleGroup, int $order): Rule; | ||||
|  | ||||
|     /** | ||||
|      * @param Rule $rule | ||||
|      * | ||||
| @@ -176,6 +169,14 @@ interface RuleRepositoryInterface | ||||
|      */ | ||||
|     public function resetRulesInGroupOrder(RuleGroup $ruleGroup): bool; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchRule(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|   | ||||
| @@ -22,13 +22,14 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Repositories\RuleGroup; | ||||
|  | ||||
| use DB; | ||||
| use Exception; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Relations\HasMany; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use DB; | ||||
|  | ||||
| /** | ||||
|  * Class RuleGroupRepository. | ||||
| @@ -37,6 +38,28 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
| { | ||||
|     private User $user; | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function correctRuleGroupOrder(): void | ||||
|     { | ||||
|         $set   = $this->user | ||||
|             ->ruleGroups() | ||||
|             ->orderBy('order', 'ASC') | ||||
|             ->orderBy('active', 'DESC') | ||||
|             ->orderBy('title', 'ASC') | ||||
|             ->get(['rule_groups.id']); | ||||
|         $index = 1; | ||||
|         /** @var RuleGroup $ruleGroup */ | ||||
|         foreach ($set as $ruleGroup) { | ||||
|             if ($ruleGroup->order !== $index) { | ||||
|                 $ruleGroup->order = $index; | ||||
|                 $ruleGroup->save(); | ||||
|             } | ||||
|             $index++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
| @@ -50,7 +73,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
|      * @param RuleGroup|null $moveTo | ||||
|      * | ||||
|      * @return bool | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function destroy(RuleGroup $ruleGroup, ?RuleGroup $moveTo): bool | ||||
|     { | ||||
| @@ -76,52 +99,16 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function resetRuleGroupOrder(): bool | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $this->user->ruleGroups()->whereNotNull('deleted_at')->update(['order' => 0]); | ||||
|  | ||||
|         $set   = $this->user | ||||
|             ->ruleGroups() | ||||
|             ->orderBy('order', 'ASC')->get(); | ||||
|         $count = 1; | ||||
|         /** @var RuleGroup $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             $entry->order = $count; | ||||
|             $entry->save(); | ||||
|  | ||||
|             // also update rules in group. | ||||
|             $this->resetRulesInGroupOrder($entry); | ||||
|  | ||||
|             ++$count; | ||||
|         $groups = $this->get(); | ||||
|         /** @var RuleGroup $group */ | ||||
|         foreach ($groups as $group) { | ||||
|             $group->rules()->delete(); | ||||
|             $group->delete(); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function resetRulesInGroupOrder(RuleGroup $ruleGroup): bool | ||||
|     { | ||||
|         $ruleGroup->rules()->whereNotNull('deleted_at')->update(['order' => 0]); | ||||
|  | ||||
|         $set   = $ruleGroup->rules() | ||||
|                            ->orderBy('order', 'ASC') | ||||
|                            ->orderBy('updated_at', 'DESC') | ||||
|                            ->get(); | ||||
|         $count = 1; | ||||
|         /** @var Rule $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             $entry->order = $count; | ||||
|             $entry->save(); | ||||
|             ++$count; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -139,6 +126,16 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
|         return $group; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $title | ||||
|      * | ||||
|      * @return RuleGroup|null | ||||
|      */ | ||||
|     public function findByTitle(string $title): ?RuleGroup | ||||
|     { | ||||
|         return $this->user->ruleGroups()->where('title', $title)->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -197,6 +194,16 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
|                      ->get(['rules.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getHighestOrderRuleGroup(): int | ||||
|     { | ||||
|         $entry = $this->user->ruleGroups()->max('order'); | ||||
|  | ||||
|         return (int)$entry; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string|null $filter | ||||
|      * | ||||
| @@ -261,6 +268,14 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
|                      ->get(['rules.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function maxOrder(): int | ||||
|     { | ||||
|         return (int)$this->user->ruleGroups()->max('order'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * | ||||
| @@ -307,6 +322,70 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function resetRuleGroupOrder(): bool | ||||
|     { | ||||
|         $this->user->ruleGroups()->whereNotNull('deleted_at')->update(['order' => 0]); | ||||
|  | ||||
|         $set   = $this->user | ||||
|             ->ruleGroups() | ||||
|             ->orderBy('order', 'ASC')->get(); | ||||
|         $count = 1; | ||||
|         /** @var RuleGroup $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             $entry->order = $count; | ||||
|             $entry->save(); | ||||
|  | ||||
|             // also update rules in group. | ||||
|             $this->resetRulesInGroupOrder($entry); | ||||
|  | ||||
|             ++$count; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function resetRulesInGroupOrder(RuleGroup $ruleGroup): bool | ||||
|     { | ||||
|         $ruleGroup->rules()->whereNotNull('deleted_at')->update(['order' => 0]); | ||||
|  | ||||
|         $set   = $ruleGroup->rules() | ||||
|                            ->orderBy('order', 'ASC') | ||||
|                            ->orderBy('updated_at', 'DESC') | ||||
|                            ->get(); | ||||
|         $count = 1; | ||||
|         /** @var Rule $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             $entry->order = $count; | ||||
|             $entry->save(); | ||||
|             ++$count; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function searchRuleGroup(string $query, int $limit): Collection | ||||
|     { | ||||
|         $search = $this->user->ruleGroups(); | ||||
|         if ('' !== $query) { | ||||
|             $search->where('rule_groups.title', 'LIKE', sprintf('%%%s%%', $query)); | ||||
|         } | ||||
|         $search->orderBy('rule_groups.order', 'ASC') | ||||
|                ->orderBy('rule_groups.title', 'ASC'); | ||||
|  | ||||
|         return $search->take($limit)->get(['id', 'title', 'description']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
| @@ -339,16 +418,6 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
|         return $newRuleGroup; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getHighestOrderRuleGroup(): int | ||||
|     { | ||||
|         $entry = $this->user->ruleGroups()->max('order'); | ||||
|  | ||||
|         return (int)$entry; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * @param array     $data | ||||
| @@ -373,7 +442,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
|             $max = $this->maxOrder(); | ||||
|             // TODO also for bills and accounts: | ||||
|             $data['order'] = $data['order'] > $max ? $max : $data['order']; | ||||
|             $ruleGroup = $this->updateOrder($ruleGroup, $ruleGroup->order, $data['order']); | ||||
|             $ruleGroup     = $this->updateOrder($ruleGroup, $ruleGroup->order, $data['order']); | ||||
|         } | ||||
|  | ||||
|         $ruleGroup->save(); | ||||
| @@ -381,66 +450,6 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
|         return $ruleGroup; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $title | ||||
|      * | ||||
|      * @return RuleGroup|null | ||||
|      */ | ||||
|     public function findByTitle(string $title): ?RuleGroup | ||||
|     { | ||||
|         return $this->user->ruleGroups()->where('title', $title)->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAll(): void | ||||
|     { | ||||
|         $groups = $this->get(); | ||||
|         /** @var RuleGroup $group */ | ||||
|         foreach ($groups as $group) { | ||||
|             $group->rules()->delete(); | ||||
|             $group->delete(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function searchRuleGroup(string $query, int $limit): Collection | ||||
|     { | ||||
|         $search = $this->user->ruleGroups(); | ||||
|         if ('' !== $query) { | ||||
|             $search->where('rule_groups.title', 'LIKE', sprintf('%%%s%%', $query)); | ||||
|         } | ||||
|         $search->orderBy('rule_groups.order', 'ASC') | ||||
|                ->orderBy('rule_groups.title', 'ASC'); | ||||
|  | ||||
|         return $search->take($limit)->get(['id', 'title', 'description']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function correctRuleGroupOrder(): void | ||||
|     { | ||||
|         $set   = $this->user | ||||
|             ->ruleGroups() | ||||
|             ->orderBy('order', 'ASC') | ||||
|             ->orderBy('active', 'DESC') | ||||
|             ->orderBy('title', 'ASC') | ||||
|             ->get(['rule_groups.id']); | ||||
|         $index = 1; | ||||
|         /** @var RuleGroup $ruleGroup */ | ||||
|         foreach ($set as $ruleGroup) { | ||||
|             if ($ruleGroup->order !== $index) { | ||||
|                 $ruleGroup->order = $index; | ||||
|                 $ruleGroup->save(); | ||||
|             } | ||||
|             $index++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
| @@ -463,12 +472,4 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface | ||||
|  | ||||
|         return $ruleGroup; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function maxOrder(): int | ||||
|     { | ||||
|         return (int)$this->user->ruleGroups()->max('order'); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -37,36 +37,6 @@ interface RuleGroupRepositoryInterface | ||||
|      */ | ||||
|     public function correctRuleGroupOrder(): void; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * @param int       $oldOrder | ||||
|      * @param int       $newOrder | ||||
|      * | ||||
|      * @return RuleGroup | ||||
|      */ | ||||
|     public function updateOrder(RuleGroup $ruleGroup, int $oldOrder, int $newOrder): RuleGroup; | ||||
|  | ||||
|     /** | ||||
|      * Get highest possible order for a rule group. | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function maxOrder(): int; | ||||
|  | ||||
|     /** | ||||
|      * Delete everything. | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchRuleGroup(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
| @@ -80,6 +50,11 @@ interface RuleGroupRepositoryInterface | ||||
|      */ | ||||
|     public function destroy(RuleGroup $ruleGroup, ?RuleGroup $moveTo): bool; | ||||
|  | ||||
|     /** | ||||
|      * Delete everything. | ||||
|      */ | ||||
|     public function destroyAll(): void; | ||||
|  | ||||
|     /** | ||||
|      * @param int $ruleGroupId | ||||
|      * | ||||
| @@ -146,6 +121,13 @@ interface RuleGroupRepositoryInterface | ||||
|      */ | ||||
|     public function getRules(RuleGroup $group): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Get highest possible order for a rule group. | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function maxOrder(): int; | ||||
|  | ||||
|     /** | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * | ||||
| @@ -172,6 +154,14 @@ interface RuleGroupRepositoryInterface | ||||
|      */ | ||||
|     public function resetRulesInGroupOrder(RuleGroup $ruleGroup): bool; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchRuleGroup(string $query, int $limit): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
| @@ -191,4 +181,14 @@ interface RuleGroupRepositoryInterface | ||||
|      * @return RuleGroup | ||||
|      */ | ||||
|     public function update(RuleGroup $ruleGroup, array $data): RuleGroup; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * @param int       $oldOrder | ||||
|      * @param int       $newOrder | ||||
|      * | ||||
|      * @return RuleGroup | ||||
|      */ | ||||
|     public function updateOrder(RuleGroup $ruleGroup, int $oldOrder, int $newOrder): RuleGroup; | ||||
| } | ||||
|   | ||||
| @@ -24,7 +24,6 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Repositories\Tag; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Log; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\TransactionType; | ||||
|   | ||||
| @@ -24,6 +24,7 @@ namespace FireflyIII\Repositories\Tag; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use DB; | ||||
| use Exception; | ||||
| use FireflyIII\Factory\TagFactory; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\Attachment; | ||||
| @@ -55,7 +56,7 @@ class TagRepository implements TagRepositoryInterface | ||||
|      * @param Tag $tag | ||||
|      * | ||||
|      * @return bool | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function destroy(Tag $tag): bool | ||||
|     { | ||||
| @@ -139,6 +140,26 @@ class TagRepository implements TagRepositoryInterface | ||||
|         return $this->user->tags()->orderBy('tag', 'ASC')->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttachments(Tag $tag): Collection | ||||
|     { | ||||
|         $set = $tag->attachments()->get(); | ||||
|         /** @var Storage $disk */ | ||||
|         $disk = Storage::disk('upload'); | ||||
|  | ||||
|         return $set->each( | ||||
|             static function (Attachment $attachment) use ($disk) { | ||||
|                 $notes                   = $attachment->notes()->first(); | ||||
|                 $attachment->file_exists = $disk->exists($attachment->fileName()); | ||||
|                 $attachment->notes       = $notes ? $notes->text : ''; | ||||
|  | ||||
|                 return $attachment; | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
| @@ -479,7 +500,7 @@ class TagRepository implements TagRepositoryInterface | ||||
|                 $location->save(); | ||||
|             } | ||||
|         } | ||||
|         if(true === $deleteLocation) { | ||||
|         if (true === $deleteLocation) { | ||||
|             $tag->locations()->delete(); | ||||
|         } | ||||
|  | ||||
| @@ -535,24 +556,4 @@ class TagRepository implements TagRepositoryInterface | ||||
|  | ||||
|         return $min; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttachments(Tag $tag): Collection | ||||
|     { | ||||
|         $set = $tag->attachments()->get(); | ||||
|         /** @var Storage $disk */ | ||||
|         $disk = Storage::disk('upload'); | ||||
|  | ||||
|         return $set->each( | ||||
|             static function (Attachment $attachment) use ($disk) { | ||||
|                 $notes                   = $attachment->notes()->first(); | ||||
|                 $attachment->file_exists = $disk->exists($attachment->fileName()); | ||||
|                 $attachment->notes       = $notes ? $notes->text : ''; | ||||
|  | ||||
|                 return $attachment; | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,13 +39,6 @@ interface TagRepositoryInterface | ||||
|      */ | ||||
|     public function count(): int; | ||||
|  | ||||
|     /** | ||||
|      * @param Tag $tag | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttachments(Tag $tag): Collection; | ||||
|  | ||||
|     /** | ||||
|      * This method destroys a tag. | ||||
|      * | ||||
| @@ -97,6 +90,13 @@ interface TagRepositoryInterface | ||||
|      */ | ||||
|     public function get(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Tag $tag | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttachments(Tag $tag): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Return location, or NULL. | ||||
|      * | ||||
| @@ -156,7 +156,7 @@ interface TagRepositoryInterface | ||||
|      * Search the users tags. | ||||
|      * | ||||
|      * @param string $query | ||||
|      * @param int $limit | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -189,11 +189,12 @@ interface TagRepositoryInterface | ||||
|  | ||||
|     /** | ||||
|      * Generates a tag cloud. | ||||
|      * @deprecated | ||||
|      * | ||||
|      * @param int|null $year | ||||
|      * | ||||
|      * @return array | ||||
|      * @deprecated | ||||
|      * | ||||
|      */ | ||||
|     public function tagCloud(?int $year): array; | ||||
|  | ||||
|   | ||||
| @@ -50,14 +50,6 @@ class TelemetryRepository implements TelemetryRepositoryInterface | ||||
|         Telemetry::whereNotNull('created_at')->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function paginated(int $pageSize): LengthAwarePaginator | ||||
|     { | ||||
|         return Telemetry::orderBy('created_at', 'DESC')->paginate($pageSize); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
| @@ -66,4 +58,12 @@ class TelemetryRepository implements TelemetryRepositoryInterface | ||||
|         // created_at is never NULL. | ||||
|         Telemetry::whereNotNull('submitted')->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function paginated(int $pageSize): LengthAwarePaginator | ||||
|     { | ||||
|         return Telemetry::orderBy('created_at', 'DESC')->paginate($pageSize); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,15 +39,6 @@ interface TelemetryRepositoryInterface | ||||
|      */ | ||||
|     public function count(): int; | ||||
|  | ||||
|     /** | ||||
|      * Return paginated result of telemetry records. | ||||
|      * | ||||
|      * @param int $pageSize | ||||
|      * | ||||
|      * @return LengthAwarePaginator | ||||
|      */ | ||||
|     public function paginated( int $pageSize): LengthAwarePaginator; | ||||
|  | ||||
|     /** | ||||
|      * Delete all records. | ||||
|      */ | ||||
| @@ -58,4 +49,13 @@ interface TelemetryRepositoryInterface | ||||
|      */ | ||||
|     public function deleteSubmitted(): void; | ||||
|  | ||||
|     /** | ||||
|      * Return paginated result of telemetry records. | ||||
|      * | ||||
|      * @param int $pageSize | ||||
|      * | ||||
|      * @return LengthAwarePaginator | ||||
|      */ | ||||
|     public function paginated(int $pageSize): LengthAwarePaginator; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -177,6 +177,17 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getLocation(int $journalId): ?Location | ||||
|     { | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         $journal = $this->user->transactionJournals()->find($journalId); | ||||
|  | ||||
|         return $journal->locations()->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Return object with all found meta field things as Carbon objects. | ||||
|      * | ||||
| @@ -266,7 +277,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface | ||||
|             ->get(['piggy_bank_events.*']); | ||||
|         /** @var PiggyBankEvent $row */ | ||||
|         foreach ($data as $row) { | ||||
|             if(null === $row->piggyBank) { | ||||
|             if (null === $row->piggyBank) { | ||||
|                 continue; | ||||
|             } | ||||
|             // get currency preference. | ||||
| @@ -294,6 +305,17 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getTagObjects(int $journalId): Collection | ||||
|     { | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         $journal = $this->user->transactionJournals()->find($journalId); | ||||
|  | ||||
|         return $journal->tags()->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the tags for a journal (by ID). | ||||
|      * | ||||
| @@ -337,7 +359,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface | ||||
|         } catch (DuplicateTransactionException $e) { | ||||
|             Log::warning('Group repository caught group factory with a duplicate exception!'); | ||||
|             throw new DuplicateTransactionException($e->getMessage()); | ||||
|         } catch(FireflyException $e) { | ||||
|         } catch (FireflyException $e) { | ||||
|             Log::warning('Group repository caught group factory with an exception!'); | ||||
|             Log::error($e->getMessage()); | ||||
|             Log::error($e->getTraceAsString()); | ||||
| @@ -397,9 +419,9 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface | ||||
|      */ | ||||
|     private function expandTransaction(Transaction $transaction): array | ||||
|     { | ||||
|         $array = $transaction->toArray(); | ||||
|         $array['account'] = $transaction->account->toArray(); | ||||
|         $array['budgets'] = []; | ||||
|         $array               = $transaction->toArray(); | ||||
|         $array['account']    = $transaction->account->toArray(); | ||||
|         $array['budgets']    = []; | ||||
|         $array['categories'] = []; | ||||
|  | ||||
|         foreach ($transaction->categories as $category) { | ||||
| @@ -462,26 +484,4 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getTagObjects(int $journalId): Collection | ||||
|     { | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         $journal = $this->user->transactionJournals()->find($journalId); | ||||
|  | ||||
|         return $journal->tags()->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getLocation(int $journalId): ?Location | ||||
|     { | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         $journal = $this->user->transactionJournals()->find($journalId); | ||||
|  | ||||
|         return $journal->locations()->first(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -77,6 +77,15 @@ interface TransactionGroupRepositoryInterface | ||||
|      */ | ||||
|     public function getLinks(TransactionGroup $group): array; | ||||
|  | ||||
|     /** | ||||
|      * Get the location of a journal or NULL. | ||||
|      * | ||||
|      * @param int $journalId | ||||
|      * | ||||
|      * @return Location|null | ||||
|      */ | ||||
|     public function getLocation(int $journalId): ?Location; | ||||
|  | ||||
|     /** | ||||
|      * Return object with all found meta field things as Carbon objects. | ||||
|      * | ||||
| @@ -97,16 +106,6 @@ interface TransactionGroupRepositoryInterface | ||||
|      */ | ||||
|     public function getMetaFields(int $journalId, array $fields): NullArrayObject; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Get the location of a journal or NULL. | ||||
|      * | ||||
|      * @param int $journalId | ||||
|      * | ||||
|      * @return Location|null | ||||
|      */ | ||||
|     public function getLocation(int $journalId): ?Location; | ||||
|  | ||||
|     /** | ||||
|      * Get the note text for a journal (by ID). | ||||
|      * | ||||
| @@ -125,15 +124,6 @@ interface TransactionGroupRepositoryInterface | ||||
|      */ | ||||
|     public function getPiggyEvents(TransactionGroup $group): array; | ||||
|  | ||||
|     /** | ||||
|      * Get the tags for a journal (by ID). | ||||
|      * | ||||
|      * @param int $journalId | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getTags(int $journalId): array; | ||||
|  | ||||
|     /** | ||||
|      * Get the tags for a journal (by ID) as Tag objects. | ||||
|      * | ||||
| @@ -143,6 +133,15 @@ interface TransactionGroupRepositoryInterface | ||||
|      */ | ||||
|     public function getTagObjects(int $journalId): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Get the tags for a journal (by ID). | ||||
|      * | ||||
|      * @param int $journalId | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getTags(int $journalId): array; | ||||
|  | ||||
|     /** | ||||
|      * Set the user. | ||||
|      * | ||||
|   | ||||
| @@ -47,7 +47,7 @@ class TransactionTypeRepository implements TransactionTypeRepositoryInterface | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionType|null $type | ||||
|      * @param string|null $typeString | ||||
|      * @param string|null          $typeString | ||||
|      * | ||||
|      * @return TransactionType | ||||
|      */ | ||||
| @@ -71,7 +71,8 @@ class TransactionTypeRepository implements TransactionTypeRepositoryInterface | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int $limit | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchTypes(string $query, int $limit): Collection | ||||
|   | ||||
| @@ -31,6 +31,13 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| interface TransactionTypeRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * @param string $type | ||||
|      * | ||||
|      * @return TransactionType|null | ||||
|      */ | ||||
|     public function findByType(string $type): ?TransactionType; | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionType|null $type | ||||
|      * @param string|null          $typeString | ||||
| @@ -39,16 +46,10 @@ interface TransactionTypeRepositoryInterface | ||||
|      */ | ||||
|     public function findTransactionType(?TransactionType $type, ?string $typeString): TransactionType; | ||||
|  | ||||
|     /** | ||||
|      * @param string $type | ||||
|      * | ||||
|      * @return TransactionType|null | ||||
|      */ | ||||
|     public function findByType(string $type): ?TransactionType; | ||||
|  | ||||
|     /** | ||||
|      * @param string $query | ||||
|      * @param int $limit | ||||
|      * @param int    $limit | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function searchTypes(string $query, int $limit): Collection; | ||||
|   | ||||
| @@ -22,6 +22,7 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Repositories\User; | ||||
|  | ||||
| use Exception; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Models\Role; | ||||
| use FireflyIII\User; | ||||
| @@ -77,7 +78,7 @@ class UserRepository implements UserRepositoryInterface | ||||
|      * @param string $newEmail | ||||
|      * | ||||
|      * @return bool | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      * @see updateEmail | ||||
|      * | ||||
|      */ | ||||
| @@ -157,7 +158,7 @@ class UserRepository implements UserRepositoryInterface | ||||
|      * @param User $user | ||||
|      * | ||||
|      * @return bool | ||||
|      * @throws \Exception | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function destroy(User $user): bool | ||||
|     { | ||||
|   | ||||
| @@ -65,6 +65,64 @@ class WebhookRepository implements WebhookRepositoryInterface | ||||
|         return $this->user->webhooks()->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroy(Webhook $webhook): void | ||||
|     { | ||||
|         $webhook->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAttempt(WebhookAttempt $attempt): void | ||||
|     { | ||||
|         $attempt->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyMessage(WebhookMessage $message): void | ||||
|     { | ||||
|         $message->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttempts(WebhookMessage $webhookMessage): Collection | ||||
|     { | ||||
|         return $webhookMessage->webhookAttempts()->orderBy('created_at', 'DESC')->get(['webhook_attempts.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getMessages(Webhook $webhook): Collection | ||||
|     { | ||||
|         return $webhook->webhookMessages() | ||||
|                        ->orderBy('created_at', 'DESC') | ||||
|                        ->get(['webhook_messages.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getReadyMessages(Webhook $webhook): Collection | ||||
|     { | ||||
|         return $webhook->webhookMessages() | ||||
|                        ->where('webhook_messages.sent', 0) | ||||
|                        ->where('webhook_messages.errored', 0) | ||||
|                        ->get(['webhook_messages.*']) | ||||
|                        ->filter( | ||||
|                            function (WebhookMessage $message) { | ||||
|                                return $message->webhookAttempts()->count() <= 2; | ||||
|                            } | ||||
|                        )->splice(0, 3); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
| @@ -114,62 +172,4 @@ class WebhookRepository implements WebhookRepositoryInterface | ||||
|  | ||||
|         return $webhook; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroy(Webhook $webhook): void | ||||
|     { | ||||
|         $webhook->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyMessage(WebhookMessage $message): void | ||||
|     { | ||||
|         $message->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function destroyAttempt(WebhookAttempt $attempt): void | ||||
|     { | ||||
|         $attempt->delete(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getReadyMessages(Webhook $webhook): Collection | ||||
|     { | ||||
|         return $webhook->webhookMessages() | ||||
|                        ->where('webhook_messages.sent', 0) | ||||
|                        ->where('webhook_messages.errored', 0) | ||||
|                        ->get(['webhook_messages.*']) | ||||
|                        ->filter( | ||||
|                            function (WebhookMessage $message) { | ||||
|                                return $message->webhookAttempts()->count() <= 2; | ||||
|                            } | ||||
|                        )->splice(0, 3); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getMessages(Webhook $webhook): Collection | ||||
|     { | ||||
|         return $webhook->webhookMessages() | ||||
|                        ->orderBy('created_at', 'DESC') | ||||
|                        ->get(['webhook_messages.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getAttempts(WebhookMessage $webhookMessage): Collection | ||||
|     { | ||||
|         return $webhookMessage->webhookAttempts()->orderBy('created_at', 'DESC')->get(['webhook_attempts.*']); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -61,6 +61,42 @@ interface WebhookRepositoryInterface | ||||
|      */ | ||||
|     public function all(): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Webhook $webhook | ||||
|      */ | ||||
|     public function destroy(Webhook $webhook): void; | ||||
|  | ||||
|     /** | ||||
|      * @param WebhookAttempt $attempt | ||||
|      */ | ||||
|     public function destroyAttempt(WebhookAttempt $attempt): void; | ||||
|  | ||||
|     /** | ||||
|      * @param WebhookMessage $message | ||||
|      */ | ||||
|     public function destroyMessage(WebhookMessage $message): void; | ||||
|  | ||||
|     /** | ||||
|      * @param WebhookMessage $webhookMessage | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttempts(WebhookMessage $webhookMessage): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Webhook $webhook | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getMessages(Webhook $webhook): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Webhook $webhook | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getReadyMessages(Webhook $webhook): Collection; | ||||
|  | ||||
|     /** | ||||
|      * Set user. | ||||
|      * | ||||
| @@ -83,40 +119,4 @@ interface WebhookRepositoryInterface | ||||
|      */ | ||||
|     public function update(Webhook $webhook, array $data): Webhook; | ||||
|  | ||||
|     /** | ||||
|      * @param Webhook $webhook | ||||
|      */ | ||||
|     public function destroy(Webhook $webhook): void; | ||||
|  | ||||
|     /** | ||||
|      * @param WebhookMessage $message | ||||
|      */ | ||||
|     public function destroyMessage(WebhookMessage $message): void; | ||||
|  | ||||
|     /** | ||||
|      * @param WebhookAttempt $attempt | ||||
|      */ | ||||
|     public function destroyAttempt(WebhookAttempt $attempt): void; | ||||
|  | ||||
|     /** | ||||
|      * @param Webhook $webhook | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getReadyMessages(Webhook $webhook): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param Webhook $webhook | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getMessages(Webhook $webhook): Collection; | ||||
|  | ||||
|     /** | ||||
|      * @param WebhookMessage $webhookMessage | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAttempts(WebhookMessage $webhookMessage): Collection; | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user