1 | <?php |
||||||
2 | /** |
||||||
3 | * JournalRepository.php |
||||||
4 | * Copyright (c) 2017 [email protected] |
||||||
5 | * |
||||||
6 | * This file is part of Firefly III. |
||||||
7 | * |
||||||
8 | * Firefly III is free software: you can redistribute it and/or modify |
||||||
9 | * it under the terms of the GNU General Public License as published by |
||||||
10 | * the Free Software Foundation, either version 3 of the License, or |
||||||
11 | * (at your option) any later version. |
||||||
12 | * |
||||||
13 | * Firefly III is distributed in the hope that it will be useful, |
||||||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
16 | * GNU General Public License for more details. |
||||||
17 | * |
||||||
18 | * You should have received a copy of the GNU General Public License |
||||||
19 | * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. |
||||||
20 | */ |
||||||
21 | declare(strict_types=1); |
||||||
22 | |||||||
23 | namespace FireflyIII\Repositories\Journal; |
||||||
24 | |||||||
25 | use Carbon\Carbon; |
||||||
26 | use DB; |
||||||
27 | use Exception; |
||||||
28 | use FireflyIII\Models\Account; |
||||||
29 | use FireflyIII\Models\AccountType; |
||||||
30 | use FireflyIII\Models\Note; |
||||||
31 | use FireflyIII\Models\PiggyBankEvent; |
||||||
32 | use FireflyIII\Models\Transaction; |
||||||
33 | use FireflyIII\Models\TransactionGroup; |
||||||
34 | use FireflyIII\Models\TransactionJournal; |
||||||
35 | use FireflyIII\Models\TransactionJournalLink; |
||||||
36 | use FireflyIII\Models\TransactionJournalMeta; |
||||||
37 | use FireflyIII\Models\TransactionType; |
||||||
38 | use FireflyIII\Services\Internal\Destroy\JournalDestroyService; |
||||||
39 | use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService; |
||||||
40 | use FireflyIII\Services\Internal\Update\JournalUpdateService; |
||||||
41 | use FireflyIII\Support\CacheProperties; |
||||||
42 | use FireflyIII\User; |
||||||
43 | use Illuminate\Support\Collection; |
||||||
44 | use Illuminate\Support\MessageBag; |
||||||
45 | use Log; |
||||||
46 | use stdClass; |
||||||
47 | |||||||
48 | /** |
||||||
49 | * Class JournalRepository. |
||||||
50 | * |
||||||
51 | * @SuppressWarnings(PHPMD.CouplingBetweenObjects) |
||||||
52 | * @SuppressWarnings(PHPMD.TooManyPublicMethods) |
||||||
53 | * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) |
||||||
54 | */ |
||||||
55 | class JournalRepository implements JournalRepositoryInterface |
||||||
56 | { |
||||||
57 | |||||||
58 | |||||||
59 | /** @var User */ |
||||||
60 | private $user; |
||||||
61 | |||||||
62 | /** |
||||||
63 | * Constructor. |
||||||
64 | */ |
||||||
65 | public function __construct() |
||||||
66 | { |
||||||
67 | if ('testing' === config('app.env')) { |
||||||
68 | Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this))); |
||||||
69 | } |
||||||
70 | } |
||||||
71 | |||||||
72 | /** |
||||||
73 | * Search in journal descriptions. |
||||||
74 | * |
||||||
75 | * @param string $search |
||||||
76 | * @return Collection |
||||||
77 | */ |
||||||
78 | public function searchJournalDescriptions(string $search): Collection |
||||||
79 | { |
||||||
80 | $query = $this->user->transactionJournals() |
||||||
81 | ->orderBy('date', 'DESC'); |
||||||
82 | if ('' !== $query) { |
||||||
83 | $query->where('description', 'LIKE', sprintf('%%%s%%', $search)); |
||||||
84 | } |
||||||
85 | |||||||
86 | return $query->get(); |
||||||
87 | } |
||||||
88 | |||||||
89 | /** @noinspection MoreThanThreeArgumentsInspection */ |
||||||
90 | |||||||
91 | /** |
||||||
92 | * @param TransactionJournal $journal |
||||||
93 | * @param TransactionType $type |
||||||
94 | * @param Account $source |
||||||
95 | * @param Account $destination |
||||||
96 | * |
||||||
97 | * @return MessageBag |
||||||
98 | * @SuppressWarnings(PHPMD.CyclomaticComplexity) |
||||||
99 | * @SuppressWarnings(PHPMD.ExcessiveMethodLength) |
||||||
100 | */ |
||||||
101 | public function convert(TransactionJournal $journal, TransactionType $type, Account $source, Account $destination): MessageBag |
||||||
102 | { |
||||||
103 | if ($source->id === $destination->id || null === $source->id || null === $destination->id) { |
||||||
104 | // default message bag that shows errors for everything. |
||||||
105 | $messages = new MessageBag; |
||||||
106 | $messages->add('source_account_revenue', (string)trans('firefly.invalid_convert_selection')); |
||||||
107 | $messages->add('destination_account_asset', (string)trans('firefly.invalid_convert_selection')); |
||||||
108 | $messages->add('destination_account_expense', (string)trans('firefly.invalid_convert_selection')); |
||||||
109 | $messages->add('source_account_asset', (string)trans('firefly.invalid_convert_selection')); |
||||||
110 | |||||||
111 | return $messages; |
||||||
112 | } |
||||||
113 | |||||||
114 | $srcTransaction = $journal->transactions()->where('amount', '<', 0)->first(); |
||||||
115 | $dstTransaction = $journal->transactions()->where('amount', '>', 0)->first(); |
||||||
116 | if (null === $srcTransaction || null === $dstTransaction) { |
||||||
117 | // default message bag that shows errors for everything. |
||||||
118 | |||||||
119 | $messages = new MessageBag; |
||||||
120 | $messages->add('source_account_revenue', (string)trans('firefly.source_or_dest_invalid')); |
||||||
121 | $messages->add('destination_account_asset', (string)trans('firefly.source_or_dest_invalid')); |
||||||
122 | $messages->add('destination_account_expense', (string)trans('firefly.source_or_dest_invalid')); |
||||||
123 | $messages->add('source_account_asset', (string)trans('firefly.source_or_dest_invalid')); |
||||||
124 | |||||||
125 | return $messages; |
||||||
126 | } |
||||||
127 | // update transactions, and update journal: |
||||||
128 | |||||||
129 | $srcTransaction->account_id = $source->id; |
||||||
130 | $dstTransaction->account_id = $destination->id; |
||||||
131 | $journal->transaction_type_id = $type->id; |
||||||
132 | $dstTransaction->save(); |
||||||
133 | $srcTransaction->save(); |
||||||
134 | $journal->save(); |
||||||
135 | |||||||
136 | // if journal is a transfer now, remove budget: |
||||||
137 | if (TransactionType::TRANSFER === $type->type) { |
||||||
138 | |||||||
139 | $journal->budgets()->detach(); |
||||||
140 | // also from transactions: |
||||||
141 | foreach ($journal->transactions as $transaction) { |
||||||
142 | $transaction->budgets()->detach(); |
||||||
143 | } |
||||||
144 | } |
||||||
145 | // if journal is not a withdrawal, remove the bill ID. |
||||||
146 | if (TransactionType::WITHDRAWAL !== $type->type) { |
||||||
147 | $journal->bill_id = null; |
||||||
148 | $journal->save(); |
||||||
149 | } |
||||||
150 | |||||||
151 | app('preferences')->mark(); |
||||||
152 | |||||||
153 | return new MessageBag; |
||||||
154 | } |
||||||
155 | |||||||
156 | /** |
||||||
157 | * @param TransactionGroup $transactionGroup |
||||||
158 | * |
||||||
159 | */ |
||||||
160 | public function destroyGroup(TransactionGroup $transactionGroup): void |
||||||
161 | { |
||||||
162 | /** @var TransactionGroupDestroyService $service */ |
||||||
163 | $service = app(TransactionGroupDestroyService::class); |
||||||
164 | $service->destroy($transactionGroup); |
||||||
165 | } |
||||||
166 | |||||||
167 | /** |
||||||
168 | * @param TransactionJournal $journal |
||||||
169 | * |
||||||
170 | */ |
||||||
171 | public function destroyJournal(TransactionJournal $journal): void |
||||||
172 | { |
||||||
173 | /** @var JournalDestroyService $service */ |
||||||
174 | $service = app(JournalDestroyService::class); |
||||||
175 | $service->destroy($journal); |
||||||
176 | } |
||||||
177 | |||||||
178 | /** |
||||||
179 | * Find a journal by its hash. |
||||||
180 | * |
||||||
181 | * @param string $hash |
||||||
182 | * |
||||||
183 | * @return TransactionJournalMeta|null |
||||||
184 | */ |
||||||
185 | public function findByHash(string $hash): ?TransactionJournalMeta |
||||||
186 | { |
||||||
187 | $jsonEncode = json_encode($hash); |
||||||
188 | $hashOfHash = hash('sha256', $jsonEncode); |
||||||
189 | Log::debug(sprintf('JSON encoded hash is: %s', $jsonEncode)); |
||||||
190 | Log::debug(sprintf('Hash of hash is: %s', $hashOfHash)); |
||||||
191 | |||||||
192 | $result = TransactionJournalMeta::withTrashed() |
||||||
193 | ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') |
||||||
194 | ->where('hash', $hashOfHash) |
||||||
195 | ->where('name', 'import_hash_v2') |
||||||
196 | ->first(['journal_meta.*']); |
||||||
197 | if (null === $result) { |
||||||
198 | Log::debug('Result is null'); |
||||||
199 | } |
||||||
200 | |||||||
201 | return $result; |
||||||
202 | } |
||||||
203 | |||||||
204 | /** |
||||||
205 | * Find a specific journal. |
||||||
206 | * |
||||||
207 | * @param int $journalId |
||||||
208 | * |
||||||
209 | * @return TransactionJournal|null |
||||||
210 | */ |
||||||
211 | public function findNull(int $journalId): ?TransactionJournal |
||||||
212 | { |
||||||
213 | return $this->user->transactionJournals()->where('id', $journalId)->first(); |
||||||
214 | } |
||||||
215 | |||||||
216 | /** |
||||||
217 | * @param int $transactionid |
||||||
218 | * |
||||||
219 | * @return Transaction|null |
||||||
220 | */ |
||||||
221 | public function findTransaction(int $transactionid): ?Transaction |
||||||
222 | { |
||||||
223 | $transaction = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') |
||||||
224 | ->where('transaction_journals.user_id', $this->user->id) |
||||||
225 | ->where('transactions.id', $transactionid) |
||||||
226 | ->first(['transactions.*']); |
||||||
227 | |||||||
228 | return $transaction; |
||||||
229 | } |
||||||
230 | |||||||
231 | /** |
||||||
232 | * Get users first transaction journal or NULL. |
||||||
233 | * |
||||||
234 | * @return TransactionJournal|null |
||||||
235 | */ |
||||||
236 | public function firstNull(): ?TransactionJournal |
||||||
237 | { |
||||||
238 | /** @var TransactionJournal $entry */ |
||||||
239 | $entry = $this->user->transactionJournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']); |
||||||
240 | $result = null; |
||||||
241 | if (null !== $entry) { |
||||||
242 | $result = $entry; |
||||||
243 | } |
||||||
244 | |||||||
245 | return $result; |
||||||
246 | } |
||||||
247 | |||||||
248 | /** |
||||||
249 | * @param TransactionJournal $journal |
||||||
250 | * |
||||||
251 | * @return Transaction|null |
||||||
252 | */ |
||||||
253 | public function getAssetTransaction(TransactionJournal $journal): ?Transaction |
||||||
254 | { |
||||||
255 | /** @var Transaction $transaction */ |
||||||
256 | foreach ($journal->transactions as $transaction) { |
||||||
257 | if (AccountType::ASSET === $transaction->account->accountType->type) { |
||||||
258 | return $transaction; |
||||||
259 | } |
||||||
260 | } |
||||||
261 | |||||||
262 | return null; |
||||||
263 | } |
||||||
264 | |||||||
265 | /** |
||||||
266 | * Return all attachments for journal. |
||||||
267 | * |
||||||
268 | * @param TransactionJournal $journal |
||||||
269 | * |
||||||
270 | * @return Collection |
||||||
271 | */ |
||||||
272 | public function getAttachments(TransactionJournal $journal): Collection |
||||||
273 | { |
||||||
274 | return $journal->attachments; |
||||||
275 | } |
||||||
276 | |||||||
277 | /** |
||||||
278 | * Get all attachments connected to the transaction group. |
||||||
279 | * |
||||||
280 | * @param TransactionJournal $transactionJournal |
||||||
281 | * |
||||||
282 | * @return Collection |
||||||
283 | */ |
||||||
284 | public function getAttachmentsByJournal(TransactionJournal $transactionJournal): Collection |
||||||
0 ignored issues
–
show
|
|||||||
285 | { |
||||||
286 | // TODO: Implement getAttachmentsByJournal() method. |
||||||
287 | throw new NotImplementedException; |
||||||
0 ignored issues
–
show
The type
FireflyIII\Repositories\...NotImplementedException was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths
Loading history...
|
|||||||
288 | } |
||||||
289 | |||||||
290 | /** |
||||||
291 | * Returns the first positive transaction for the journal. Useful when editing journals. |
||||||
292 | * |
||||||
293 | * @param TransactionJournal $journal |
||||||
294 | * |
||||||
295 | * @return Transaction |
||||||
296 | */ |
||||||
297 | public function getFirstPosTransaction(TransactionJournal $journal): Transaction |
||||||
298 | { |
||||||
299 | return $journal->transactions()->where('amount', '>', 0)->first(); |
||||||
300 | } |
||||||
301 | |||||||
302 | /** |
||||||
303 | * Return the ID of the budget linked to the journal (if any) or the transactions (if any). |
||||||
304 | * |
||||||
305 | * @param TransactionJournal $journal |
||||||
306 | * |
||||||
307 | * @return int |
||||||
308 | */ |
||||||
309 | public function getJournalBudgetId(TransactionJournal $journal): int |
||||||
310 | { |
||||||
311 | $budget = $journal->budgets()->first(); |
||||||
312 | if (null !== $budget) { |
||||||
313 | return $budget->id; |
||||||
314 | } |
||||||
315 | /** @noinspection NullPointerExceptionInspection */ |
||||||
316 | $budget = $journal->transactions()->first()->budgets()->first(); |
||||||
317 | if (null !== $budget) { |
||||||
318 | return $budget->id; |
||||||
319 | } |
||||||
320 | |||||||
321 | return 0; |
||||||
322 | } |
||||||
323 | |||||||
324 | /** |
||||||
325 | * Return the ID of the category linked to the journal (if any) or to the transactions (if any). |
||||||
326 | * |
||||||
327 | * @param TransactionJournal $journal |
||||||
328 | * |
||||||
329 | * @return int |
||||||
330 | */ |
||||||
331 | public function getJournalCategoryId(TransactionJournal $journal): int |
||||||
332 | { |
||||||
333 | $category = $journal->categories()->first(); |
||||||
334 | if (null !== $category) { |
||||||
335 | return $category->id; |
||||||
336 | } |
||||||
337 | /** @noinspection NullPointerExceptionInspection */ |
||||||
338 | $category = $journal->transactions()->first()->categories()->first(); |
||||||
339 | if (null !== $category) { |
||||||
340 | return $category->id; |
||||||
341 | } |
||||||
342 | |||||||
343 | return 0; |
||||||
344 | } |
||||||
345 | |||||||
346 | /** |
||||||
347 | * Return the name of the category linked to the journal (if any) or to the transactions (if any). |
||||||
348 | * |
||||||
349 | * @param TransactionJournal $journal |
||||||
350 | * |
||||||
351 | * @return string |
||||||
352 | */ |
||||||
353 | public function getJournalCategoryName(TransactionJournal $journal): string |
||||||
354 | { |
||||||
355 | $category = $journal->categories()->first(); |
||||||
356 | if (null !== $category) { |
||||||
357 | return $category->name; |
||||||
358 | } |
||||||
359 | /** @noinspection NullPointerExceptionInspection */ |
||||||
360 | $category = $journal->transactions()->first()->categories()->first(); |
||||||
361 | if (null !== $category) { |
||||||
362 | return $category->name; |
||||||
363 | } |
||||||
364 | |||||||
365 | return ''; |
||||||
366 | } |
||||||
367 | |||||||
368 | /** |
||||||
369 | * Return requested date as string. When it's a NULL return the date of journal, |
||||||
370 | * otherwise look for meta field and return that one. |
||||||
371 | * |
||||||
372 | * @param TransactionJournal $journal |
||||||
373 | * @param null|string $field |
||||||
374 | * |
||||||
375 | * @return string |
||||||
376 | * @SuppressWarnings(PHPMD.CyclomaticComplexity) |
||||||
377 | * @SuppressWarnings(PHPMD.ExcessiveMethodLength) |
||||||
378 | */ |
||||||
379 | public function getJournalDate(TransactionJournal $journal, ?string $field): string |
||||||
380 | { |
||||||
381 | if (null === $field) { |
||||||
382 | return $journal->date->format('Y-m-d'); |
||||||
383 | } |
||||||
384 | /** @noinspection NotOptimalIfConditionsInspection */ |
||||||
385 | if (null !== $journal->$field && $journal->$field instanceof Carbon) { |
||||||
386 | // make field NULL |
||||||
387 | $carbon = clone $journal->$field; |
||||||
388 | $journal->$field = null; |
||||||
389 | $journal->save(); |
||||||
390 | |||||||
391 | // create meta entry |
||||||
392 | $this->setMetaDate($journal, $field, $carbon); |
||||||
0 ignored issues
–
show
The method
setMetaDate() does not exist on FireflyIII\Repositories\Journal\JournalRepository .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed.
Loading history...
|
|||||||
393 | |||||||
394 | // return that one instead. |
||||||
395 | return $carbon->format('Y-m-d'); |
||||||
396 | } |
||||||
397 | $metaField = $this->getMetaDate($journal, $field); |
||||||
398 | if (null !== $metaField) { |
||||||
399 | return $metaField->format('Y-m-d'); |
||||||
400 | } |
||||||
401 | |||||||
402 | return ''; |
||||||
403 | } |
||||||
404 | |||||||
405 | /** |
||||||
406 | * Return Carbon value of a meta field (or NULL). |
||||||
407 | * |
||||||
408 | * @param TransactionJournal $journal |
||||||
409 | * @param string $field |
||||||
410 | * |
||||||
411 | * @return null|Carbon |
||||||
412 | */ |
||||||
413 | public function getMetaDate(TransactionJournal $journal, string $field): ?Carbon |
||||||
414 | { |
||||||
415 | $cache = new CacheProperties; |
||||||
416 | $cache->addProperty('journal-meta-updated'); |
||||||
417 | $cache->addProperty($journal->id); |
||||||
418 | $cache->addProperty($field); |
||||||
419 | |||||||
420 | if ($cache->has()) { |
||||||
421 | return new Carbon($cache->get()); // @codeCoverageIgnore |
||||||
422 | } |
||||||
423 | |||||||
424 | $entry = $journal->transactionJournalMeta()->where('name', $field)->first(); |
||||||
425 | if (null === $entry) { |
||||||
426 | return null; |
||||||
427 | } |
||||||
428 | $value = new Carbon($entry->data); |
||||||
429 | $cache->store($entry->data); |
||||||
430 | |||||||
431 | return $value; |
||||||
432 | } |
||||||
433 | |||||||
434 | /** |
||||||
435 | * Return a list of all destination accounts related to journal. |
||||||
436 | * |
||||||
437 | * @param TransactionJournal $journal |
||||||
438 | * @param bool $useCache |
||||||
439 | * |
||||||
440 | * @return Collection |
||||||
441 | */ |
||||||
442 | public function getJournalDestinationAccounts(TransactionJournal $journal, bool $useCache = true): Collection |
||||||
443 | { |
||||||
444 | $cache = new CacheProperties; |
||||||
445 | $cache->addProperty($journal->id); |
||||||
446 | $cache->addProperty('destination-account-list'); |
||||||
447 | if ($useCache && $cache->has()) { |
||||||
448 | return $cache->get(); // @codeCoverageIgnore |
||||||
449 | } |
||||||
450 | $transactions = $journal->transactions()->where('amount', '>', 0)->orderBy('transactions.account_id')->with('account')->get(); |
||||||
451 | $list = new Collection; |
||||||
452 | /** @var Transaction $t */ |
||||||
453 | foreach ($transactions as $t) { |
||||||
454 | $list->push($t->account); |
||||||
455 | } |
||||||
456 | $list = $list->unique('id'); |
||||||
457 | $cache->store($list); |
||||||
458 | |||||||
459 | return $list; |
||||||
460 | } |
||||||
461 | |||||||
462 | /** |
||||||
463 | * Return a list of all source accounts related to journal. |
||||||
464 | * |
||||||
465 | * @param TransactionJournal $journal |
||||||
466 | * @param bool $useCache |
||||||
467 | * |
||||||
468 | * @return Collection |
||||||
469 | */ |
||||||
470 | public function getJournalSourceAccounts(TransactionJournal $journal, bool $useCache = true): Collection |
||||||
471 | { |
||||||
472 | $cache = new CacheProperties; |
||||||
473 | $cache->addProperty($journal->id); |
||||||
474 | $cache->addProperty('source-account-list'); |
||||||
475 | if ($useCache && $cache->has()) { |
||||||
476 | return $cache->get(); // @codeCoverageIgnore |
||||||
477 | } |
||||||
478 | $transactions = $journal->transactions()->where('amount', '<', 0)->orderBy('transactions.account_id')->with('account')->get(); |
||||||
479 | $list = new Collection; |
||||||
480 | /** @var Transaction $t */ |
||||||
481 | foreach ($transactions as $t) { |
||||||
482 | $list->push($t->account); |
||||||
483 | } |
||||||
484 | $list = $list->unique('id'); |
||||||
485 | $cache->store($list); |
||||||
486 | |||||||
487 | return $list; |
||||||
488 | } |
||||||
489 | |||||||
490 | /** |
||||||
491 | * Return total amount of journal. Is always positive. |
||||||
492 | * |
||||||
493 | * @param TransactionJournal $journal |
||||||
494 | * |
||||||
495 | * @return string |
||||||
496 | */ |
||||||
497 | public function getJournalTotal(TransactionJournal $journal): string |
||||||
498 | { |
||||||
499 | $cache = new CacheProperties; |
||||||
500 | $cache->addProperty($journal->id); |
||||||
501 | $cache->addProperty('amount-positive'); |
||||||
502 | if ($cache->has()) { |
||||||
503 | return $cache->get(); // @codeCoverageIgnore |
||||||
504 | } |
||||||
505 | |||||||
506 | // saves on queries: |
||||||
507 | $amount = $journal->transactions()->where('amount', '>', 0)->get()->sum('amount'); |
||||||
508 | $amount = (string)$amount; |
||||||
509 | $cache->store($amount); |
||||||
510 | |||||||
511 | return $amount; |
||||||
512 | } |
||||||
513 | |||||||
514 | /** |
||||||
515 | * Return all journals without a group, used in an upgrade routine. |
||||||
516 | * |
||||||
517 | * @return array |
||||||
518 | */ |
||||||
519 | public function getJournalsWithoutGroup(): array |
||||||
520 | { |
||||||
521 | return TransactionJournal::whereNull('transaction_group_id')->get(['id', 'user_id'])->toArray(); |
||||||
522 | } |
||||||
523 | |||||||
524 | /** |
||||||
525 | * @param TransactionJournalLink $link |
||||||
526 | * |
||||||
527 | * @return string |
||||||
528 | */ |
||||||
529 | public function getLinkNoteText(TransactionJournalLink $link): string |
||||||
530 | { |
||||||
531 | $notes = null; |
||||||
532 | /** @var Note $note */ |
||||||
533 | $note = $link->notes()->first(); |
||||||
534 | if (null !== $note) { |
||||||
535 | return $note->text ?? ''; |
||||||
536 | } |
||||||
537 | |||||||
538 | return ''; |
||||||
539 | } |
||||||
540 | |||||||
541 | /** |
||||||
542 | * Return string value of a meta date (or NULL). |
||||||
543 | * |
||||||
544 | * @param TransactionJournal $journal |
||||||
545 | * @param string $field |
||||||
546 | * |
||||||
547 | * @return null|string |
||||||
548 | */ |
||||||
549 | public function getMetaDateString(TransactionJournal $journal, string $field): ?string |
||||||
550 | { |
||||||
551 | $date = $this->getMetaDate($journal, $field); |
||||||
552 | if (null === $date) { |
||||||
553 | return null; |
||||||
554 | } |
||||||
555 | |||||||
556 | return $date->format('Y-m-d'); |
||||||
557 | } |
||||||
558 | |||||||
559 | /** |
||||||
560 | * Return value of a meta field (or NULL) as a string. |
||||||
561 | * |
||||||
562 | * @param TransactionJournal $journal |
||||||
563 | * @param string $field |
||||||
564 | * |
||||||
565 | * @return null|string |
||||||
566 | * @SuppressWarnings(PHPMD.CyclomaticComplexity) |
||||||
567 | */ |
||||||
568 | public function getMetaField(TransactionJournal $journal, string $field): ?string |
||||||
569 | { |
||||||
570 | $cache = new CacheProperties; |
||||||
571 | $cache->addProperty('journal-meta-updated'); |
||||||
572 | $cache->addProperty($journal->id); |
||||||
573 | $cache->addProperty($field); |
||||||
574 | |||||||
575 | if ($cache->has()) { |
||||||
576 | return $cache->get(); // @codeCoverageIgnore |
||||||
577 | } |
||||||
578 | |||||||
579 | $entry = $journal->transactionJournalMeta()->where('name', $field)->first(); |
||||||
580 | if (null === $entry) { |
||||||
581 | return null; |
||||||
582 | } |
||||||
583 | |||||||
584 | $value = $entry->data; |
||||||
585 | |||||||
586 | if (is_array($value)) { |
||||||
587 | $return = implode(',', $value); |
||||||
588 | $cache->store($return); |
||||||
589 | |||||||
590 | return $return; |
||||||
591 | } |
||||||
592 | |||||||
593 | // return when something else: |
||||||
594 | try { |
||||||
595 | $return = (string)$value; |
||||||
596 | $cache->store($return); |
||||||
597 | } catch (Exception $e) { |
||||||
598 | Log::error($e->getMessage()); |
||||||
599 | |||||||
600 | return ''; |
||||||
601 | } |
||||||
602 | |||||||
603 | return $return; |
||||||
604 | } |
||||||
605 | |||||||
606 | /** |
||||||
607 | * Return text of a note attached to journal, or NULL |
||||||
608 | * |
||||||
609 | * @param TransactionJournal $journal |
||||||
610 | * |
||||||
611 | * @return string|null |
||||||
612 | */ |
||||||
613 | public function getNoteText(TransactionJournal $journal): ?string |
||||||
614 | { |
||||||
615 | $note = $journal->notes()->first(); |
||||||
616 | if (null === $note) { |
||||||
617 | return null; |
||||||
618 | } |
||||||
619 | |||||||
620 | return $note->text; |
||||||
621 | } |
||||||
622 | |||||||
623 | /** |
||||||
624 | * @param TransactionJournal $journal |
||||||
625 | * |
||||||
626 | * @return Collection |
||||||
627 | */ |
||||||
628 | public function getPiggyBankEvents(TransactionJournal $journal): Collection |
||||||
629 | { |
||||||
630 | /** @var Collection $set */ |
||||||
631 | $events = $journal->piggyBankEvents()->get(); |
||||||
632 | $events->each( |
||||||
633 | function (PiggyBankEvent $event) { |
||||||
634 | $event->piggyBank = $event->piggyBank()->withTrashed()->first(); |
||||||
635 | } |
||||||
636 | ); |
||||||
637 | |||||||
638 | return $events; |
||||||
639 | } |
||||||
640 | |||||||
641 | /** |
||||||
642 | * Returns all journals with more than 2 transactions. Should only return empty collections |
||||||
643 | * in Firefly III > v4.8.0. |
||||||
644 | * |
||||||
645 | * @return Collection |
||||||
646 | */ |
||||||
647 | public function getSplitJournals(): Collection |
||||||
648 | { |
||||||
649 | $query = TransactionJournal |
||||||
650 | ::leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') |
||||||
651 | ->groupBy('transaction_journals.id'); |
||||||
652 | $result = $query->get(['transaction_journals.id as id', DB::raw('count(transactions.id) as transaction_count')]); |
||||||
653 | $journalIds = []; |
||||||
654 | /** @var stdClass $row */ |
||||||
655 | foreach ($result as $row) { |
||||||
656 | if ((int)$row->transaction_count > 2) { |
||||||
657 | $journalIds[] = (int)$row->id; |
||||||
658 | } |
||||||
659 | } |
||||||
660 | $journalIds = array_unique($journalIds); |
||||||
661 | |||||||
662 | return TransactionJournal |
||||||
663 | ::with(['transactions']) |
||||||
664 | ->whereIn('id', $journalIds)->get(); |
||||||
665 | } |
||||||
666 | |||||||
667 | /** |
||||||
668 | * Return all tags as strings in an array. |
||||||
669 | * |
||||||
670 | * @param TransactionJournal $journal |
||||||
671 | * |
||||||
672 | * @return array |
||||||
673 | */ |
||||||
674 | public function getTags(TransactionJournal $journal): array |
||||||
675 | { |
||||||
676 | return $journal->tags()->get()->pluck('tag')->toArray(); |
||||||
677 | } |
||||||
678 | |||||||
679 | /** |
||||||
680 | * Return the transaction type of the journal. |
||||||
681 | * |
||||||
682 | * @param TransactionJournal $journal |
||||||
683 | * |
||||||
684 | * @return string |
||||||
685 | */ |
||||||
686 | public function getTransactionType(TransactionJournal $journal): string |
||||||
687 | { |
||||||
688 | return $journal->transactionType->type; |
||||||
689 | } |
||||||
690 | |||||||
691 | /** |
||||||
692 | * Will tell you if journal is reconciled or not. |
||||||
693 | * |
||||||
694 | * @param TransactionJournal $journal |
||||||
695 | * |
||||||
696 | * @return bool |
||||||
697 | */ |
||||||
698 | public function isJournalReconciled(TransactionJournal $journal): bool |
||||||
699 | { |
||||||
700 | foreach ($journal->transactions as $transaction) { |
||||||
701 | if ($transaction->reconciled) { |
||||||
702 | return true; |
||||||
703 | } |
||||||
704 | } |
||||||
705 | |||||||
706 | return false; |
||||||
707 | } |
||||||
708 | |||||||
709 | /** |
||||||
710 | * @param int $transactionId |
||||||
711 | */ |
||||||
712 | public function reconcileById(int $journalId): void |
||||||
713 | { |
||||||
714 | /** @var TransactionJournal $journal */ |
||||||
715 | $journal = $this->user->transactionJournals()->find($journalId); |
||||||
716 | if (null !== $journal) { |
||||||
717 | $journal->transactions()->update(['reconciled' => true]); |
||||||
718 | } |
||||||
719 | } |
||||||
720 | |||||||
721 | /** |
||||||
722 | * @param Transaction $transaction |
||||||
723 | * |
||||||
724 | * @return bool |
||||||
725 | */ |
||||||
726 | public function reconcile(Transaction $transaction): bool |
||||||
727 | { |
||||||
728 | Log::debug(sprintf('Going to reconcile transaction #%d', $transaction->id)); |
||||||
729 | $opposing = $this->findOpposingTransaction($transaction); |
||||||
0 ignored issues
–
show
The method
findOpposingTransaction() does not exist on FireflyIII\Repositories\Journal\JournalRepository .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed.
Loading history...
|
|||||||
730 | |||||||
731 | if (null === $opposing) { |
||||||
732 | Log::debug('Opposing transaction is NULL. Cannot reconcile.'); |
||||||
733 | |||||||
734 | return false; |
||||||
735 | } |
||||||
736 | Log::debug(sprintf('Opposing transaction ID is #%d', $opposing->id)); |
||||||
737 | |||||||
738 | $transaction->reconciled = true; |
||||||
739 | $opposing->reconciled = true; |
||||||
740 | $transaction->save(); |
||||||
741 | $opposing->save(); |
||||||
742 | |||||||
743 | return true; |
||||||
744 | } |
||||||
745 | |||||||
746 | /** |
||||||
747 | * @param TransactionJournal $journal |
||||||
748 | * @param int $order |
||||||
749 | * |
||||||
750 | * @return bool |
||||||
751 | */ |
||||||
752 | public function setOrder(TransactionJournal $journal, int $order): bool |
||||||
753 | { |
||||||
754 | $journal->order = $order; |
||||||
755 | $journal->save(); |
||||||
756 | |||||||
757 | return true; |
||||||
758 | } |
||||||
759 | |||||||
760 | /** |
||||||
761 | * @param User $user |
||||||
762 | */ |
||||||
763 | public function setUser(User $user): void |
||||||
764 | { |
||||||
765 | $this->user = $user; |
||||||
766 | } |
||||||
767 | |||||||
768 | /** |
||||||
769 | * Update budget for a journal. |
||||||
770 | * |
||||||
771 | * @param TransactionJournal $journal |
||||||
772 | * @param int $budgetId |
||||||
773 | * |
||||||
774 | * @return TransactionJournal |
||||||
775 | */ |
||||||
776 | public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal |
||||||
777 | { |
||||||
778 | /** @var JournalUpdateService $service */ |
||||||
779 | $service = app(JournalUpdateService::class); |
||||||
780 | |||||||
781 | $service->setTransactionJournal($journal); |
||||||
782 | $service->setData( |
||||||
783 | [ |
||||||
784 | 'budget_id' => $budgetId, |
||||||
785 | ] |
||||||
786 | ); |
||||||
787 | $service->update(); |
||||||
788 | $journal->refresh(); |
||||||
789 | |||||||
790 | return $journal; |
||||||
791 | } |
||||||
792 | |||||||
793 | /** |
||||||
794 | * Update category for a journal. |
||||||
795 | * |
||||||
796 | * @param TransactionJournal $journal |
||||||
797 | * @param string $category |
||||||
798 | * |
||||||
799 | * @return TransactionJournal |
||||||
800 | */ |
||||||
801 | public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal |
||||||
802 | { |
||||||
803 | /** @var JournalUpdateService $service */ |
||||||
804 | $service = app(JournalUpdateService::class); |
||||||
805 | $service->setTransactionJournal($journal); |
||||||
806 | $service->setData( |
||||||
807 | [ |
||||||
808 | 'category_name' => $category, |
||||||
809 | ] |
||||||
810 | ); |
||||||
811 | $service->update(); |
||||||
812 | $journal->refresh(); |
||||||
813 | |||||||
814 | return $journal; |
||||||
815 | } |
||||||
816 | |||||||
817 | /** |
||||||
818 | * Update tag(s) for a journal. |
||||||
819 | * |
||||||
820 | * @param TransactionJournal $journal |
||||||
821 | * @param array $tags |
||||||
822 | * |
||||||
823 | * @return TransactionJournal |
||||||
824 | */ |
||||||
825 | public function updateTags(TransactionJournal $journal, array $tags): TransactionJournal |
||||||
826 | { |
||||||
827 | /** @var JournalUpdateService $service */ |
||||||
828 | $service = app(JournalUpdateService::class); |
||||||
829 | $service->setTransactionJournal($journal); |
||||||
830 | $service->setData( |
||||||
831 | [ |
||||||
832 | 'tags' => $tags, |
||||||
833 | ] |
||||||
834 | ); |
||||||
835 | $service->update(); |
||||||
836 | $journal->refresh(); |
||||||
837 | |||||||
838 | return $journal; |
||||||
839 | } |
||||||
840 | |||||||
841 | /** |
||||||
842 | * Get all transaction journals with a specific type, regardless of user. |
||||||
843 | * |
||||||
844 | * @param array $types |
||||||
845 | * @return Collection |
||||||
846 | */ |
||||||
847 | public function getAllJournals(array $types): Collection |
||||||
848 | { |
||||||
849 | return TransactionJournal |
||||||
850 | ::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') |
||||||
851 | ->whereIn('transaction_types.type', $types) |
||||||
852 | ->with(['user', 'transactionType', 'transactionCurrency', 'transactions', 'transactions.account']) |
||||||
853 | ->get(['transaction_journals.*']); |
||||||
854 | } |
||||||
855 | |||||||
856 | /** |
||||||
857 | * Get all transaction journals with a specific type, for the logged in user. |
||||||
858 | * |
||||||
859 | * @param array $types |
||||||
860 | * @return Collection |
||||||
861 | */ |
||||||
862 | public function getJournals(array $types): Collection |
||||||
863 | { |
||||||
864 | return $this->user->transactionJournals() |
||||||
865 | ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') |
||||||
866 | ->whereIn('transaction_types.type', $types) |
||||||
867 | ->with(['user', 'transactionType', 'transactionCurrency', 'transactions', 'transactions.account']) |
||||||
868 | ->get(['transaction_journals.*']); |
||||||
869 | } |
||||||
870 | |||||||
871 | /** |
||||||
872 | * Return Carbon value of a meta field (or NULL). |
||||||
873 | * |
||||||
874 | * @param int $journalId |
||||||
875 | * @param string $field |
||||||
876 | * |
||||||
877 | * @return null|Carbon |
||||||
878 | */ |
||||||
879 | public function getMetaDateById(int $journalId, string $field): ?Carbon |
||||||
880 | { |
||||||
881 | $cache = new CacheProperties; |
||||||
882 | $cache->addProperty('journal-meta-updated'); |
||||||
883 | $cache->addProperty($journalId); |
||||||
884 | $cache->addProperty($field); |
||||||
885 | |||||||
886 | if ($cache->has()) { |
||||||
887 | return new Carbon($cache->get()); // @codeCoverageIgnore |
||||||
888 | } |
||||||
889 | $entry = TransactionJournalMeta::where('transaction_journal_id', $journalId) |
||||||
890 | ->where('name', $field)->first(); |
||||||
891 | if (null === $entry) { |
||||||
892 | return null; |
||||||
893 | } |
||||||
894 | $value = new Carbon($entry->data); |
||||||
895 | $cache->store($entry->data); |
||||||
896 | |||||||
897 | return $value; |
||||||
898 | } |
||||||
899 | } |
||||||
900 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.