GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 37b02e...ebbbe1 )
by James
08:59
created

app/Repositories/PiggyBank/PiggyBankRepository.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * PiggyBankRepository.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\PiggyBank;
24
25
use Carbon\Carbon;
26
use FireflyIII\Models\Note;
27
use FireflyIII\Models\PiggyBank;
28
use FireflyIII\Models\PiggyBankEvent;
29
use FireflyIII\Models\PiggyBankRepetition;
30
use FireflyIII\Models\TransactionJournal;
31
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
32
use FireflyIII\User;
33
use Illuminate\Support\Collection;
34
use Log;
35
36
/**
37
 * Class PiggyBankRepository.
38
 */
39
class PiggyBankRepository implements PiggyBankRepositoryInterface
40
{
41
    /** @var User */
42
    private $user;
43
44
    /**
45
     * @param PiggyBank $piggyBank
46
     * @param string    $amount
47
     *
48
     * @return bool
49
     */
50
    public function addAmount(PiggyBank $piggyBank, string $amount): bool
51
    {
52
        $repetition                = $piggyBank->currentRelevantRep();
53
        $currentAmount             = $repetition->currentamount ?? '0';
54
        $repetition->currentamount = bcadd($currentAmount, $amount);
55
        $repetition->save();
56
57
        // create event
58
        $this->createEvent($piggyBank, $amount);
59
60
        return true;
61
    }
62
63
    /**
64
     * @param PiggyBankRepetition $repetition
65
     * @param string              $amount
66
     *
67
     * @return string
68
     */
69
    public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount): string
70
    {
71
        $newAmount                 = bcadd($repetition->currentamount, $amount);
72
        $repetition->currentamount = $newAmount;
73
        $repetition->save();
74
75
        return $newAmount;
76
    }
77
78
    /**
79
     * @param PiggyBank $piggyBank
80
     * @param string    $amount
81
     *
82
     * @return bool
83
     */
84
    public function canAddAmount(PiggyBank $piggyBank, string $amount): bool
85
    {
86
        $leftOnAccount = $piggyBank->leftOnAccount(new Carbon);
87
        $savedSoFar    = (string)$piggyBank->currentRelevantRep()->currentamount;
88
        $leftToSave    = bcsub($piggyBank->targetamount, $savedSoFar);
89
        $maxAmount     = (string)min(round($leftOnAccount, 12), round($leftToSave, 12));
90
91
        return bccomp($amount, $maxAmount) <= 0;
92
    }
93
94
    /**
95
     * @param PiggyBank $piggyBank
96
     * @param string    $amount
97
     *
98
     * @return bool
99
     */
100
    public function canRemoveAmount(PiggyBank $piggyBank, string $amount): bool
101
    {
102
        $savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
103
104
        return bccomp($amount, $savedSoFar) <= 0;
105
    }
106
107
    /**
108
     * @param PiggyBank $piggyBank
109
     * @param string    $amount
110
     *
111
     * @return PiggyBankEvent
112
     */
113
    public function createEvent(PiggyBank $piggyBank, string $amount): PiggyBankEvent
114
    {
115
        /** @var PiggyBankEvent $event */
116
        $event = PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount, 'piggy_bank_id' => $piggyBank->id]);
117
118
        return $event;
119
    }
120
121
    /**
122
     * @param PiggyBank          $piggyBank
123
     * @param string             $amount
124
     * @param TransactionJournal $journal
125
     *
126
     * @return PiggyBankEvent
127
     */
128
    public function createEventWithJournal(PiggyBank $piggyBank, string $amount, TransactionJournal $journal): PiggyBankEvent
129
    {
130
        /** @var PiggyBankEvent $event */
131
        $event = PiggyBankEvent::create(
132
            [
133
                'piggy_bank_id'          => $piggyBank->id,
134
                'transaction_journal_id' => $journal->id,
135
                'date'                   => $journal->date->format('Y-m-d'),
136
                'amount'                 => $amount]
137
        );
138
139
        return $event;
140
    }
141
142
    /**
143
     * @param PiggyBank $piggyBank
144
     *
145
     * @return bool
146
     *
147
148
     */
149
    public function destroy(PiggyBank $piggyBank): bool
150
    {
151
        $piggyBank->delete();
152
153
        return true;
154
    }
155
156
    /**
157
     * @param int $piggyBankid
158
     *
159
     * @return PiggyBank
160
     */
161
    public function find(int $piggyBankid): PiggyBank
162
    {
163
        $piggyBank = $this->user->piggyBanks()->where('piggy_banks.id', $piggyBankid)->first(['piggy_banks.*']);
164
        if (null !== $piggyBank) {
165
            return $piggyBank;
166
        }
167
168
        return new PiggyBank();
169
    }
170
171
    /**
172
     * Find by name or return NULL.
173
     *
174
     * @param string $name
175
     *
176
     * @return PiggyBank|null
177
     */
178
    public function findByName(string $name): ?PiggyBank
179
    {
180
        $set = $this->user->piggyBanks()->get(['piggy_banks.*']);
181
        /** @var PiggyBank $piggy */
182
        foreach ($set as $piggy) {
183
            if ($piggy->name === $name) {
184
                return $piggy;
185
            }
186
        }
187
188
        return null;
189
    }
190
191
    /**
192
     * Get current amount saved in piggy bank.
193
     *
194
     * @param PiggyBank $piggyBank
195
     *
196
     * @return string
197
     */
198
    public function getCurrentAmount(PiggyBank $piggyBank): string
199
    {
200
        /** @var PiggyBankRepetition $rep */
201
        $rep = $piggyBank->piggyBankRepetitions()->first(['piggy_bank_repetitions.*']);
202
        if (null === $rep) {
203
            return '0';
204
        }
205
206
        return (string)$rep->currentamount;
0 ignored issues
show
The property currentamount does not seem to exist on FireflyIII\Models\PiggyBankRepetition. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
207
    }
208
209
    /**
210
     * @param PiggyBank $piggyBank
211
     *
212
     * @return Collection
213
     */
214
    public function getEvents(PiggyBank $piggyBank): Collection
215
    {
216
        return $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
217
    }
218
219
    /**
220
     * Used for connecting to a piggy bank.
221
     *
222
     * @param PiggyBank           $piggyBank
223
     * @param PiggyBankRepetition $repetition
224
     * @param TransactionJournal  $journal
225
     *
226
     * @return string
227
     */
228
    public function getExactAmount(PiggyBank $piggyBank, PiggyBankRepetition $repetition, TransactionJournal $journal): string
229
    {
230
        /** @var JournalRepositoryInterface $repos */
231
        $repos = app(JournalRepositoryInterface::class);
232
        $repos->setUser($this->user);
233
234
        $amount  = $repos->getJournalTotal($journal);
235
        $sources = $repos->getJournalSourceAccounts($journal)->pluck('id')->toArray();
236
        $room    = bcsub((string)$piggyBank->targetamount, (string)$repetition->currentamount);
237
        $compare = bcmul($repetition->currentamount, '-1');
238
239
        Log::debug(sprintf('Will add/remove %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
240
241
        // if piggy account matches source account, the amount is positive
242
        if (in_array($piggyBank->account_id, $sources)) {
243
            $amount = bcmul($amount, '-1');
244
            Log::debug(sprintf('Account #%d is the source, so will remove amount from piggy bank.', $piggyBank->account_id));
245
        }
246
247
        // if the amount is positive, make sure it fits in piggy bank:
248
        if (1 === bccomp($amount, '0') && bccomp($room, $amount) === -1) {
249
            // amount is positive and $room is smaller than $amount
250
            Log::debug(sprintf('Room in piggy bank for extra money is %f', $room));
251
            Log::debug(sprintf('There is NO room to add %f to piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
252
            Log::debug(sprintf('New amount is %f', $room));
253
254
            return $room;
255
        }
256
257
        // amount is negative and $currentamount is smaller than $amount
258
        if (bccomp($amount, '0') === -1 && 1 === bccomp($compare, $amount)) {
259
            Log::debug(sprintf('Max amount to remove is %f', $repetition->currentamount));
260
            Log::debug(sprintf('Cannot remove %f from piggy bank #%d ("%s")', $amount, $piggyBank->id, $piggyBank->name));
261
            Log::debug(sprintf('New amount is %f', $compare));
262
263
            return $compare;
264
        }
265
266
        return $amount;
267
    }
268
269
    /**
270
     * @return int
271
     */
272
    public function getMaxOrder(): int
273
    {
274
        return (int)$this->user->piggyBanks()->max('order');
275
    }
276
277
    /**
278
     * @return Collection
279
     */
280
    public function getPiggyBanks(): Collection
281
    {
282
        return $this->user->piggyBanks()->orderBy('order', 'ASC')->get();
283
    }
284
285
    /**
286
     * Also add amount in name.
287
     *
288
     * @return Collection
289
     */
290
    public function getPiggyBanksWithAmount(): Collection
291
    {
292
        $currency = app('amount')->getDefaultCurrency();
293
        $set      = $this->getPiggyBanks();
294
        foreach ($set as $piggy) {
295
            $currentAmount = $piggy->currentRelevantRep()->currentamount ?? '0';
296
297
            $piggy->name = $piggy->name . ' (' . app('amount')->formatAnything($currency, $currentAmount, false) . ')';
298
        }
299
300
        return $set;
301
    }
302
303
    /**
304
     * @param PiggyBank $piggyBank
305
     * @param Carbon    $date
306
     *
307
     * @return PiggyBankRepetition
308
     */
309
    public function getRepetition(PiggyBank $piggyBank, Carbon $date): PiggyBankRepetition
310
    {
311
        $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($date)->first();
312
        if (null === $repetition) {
313
            return new PiggyBankRepetition;
314
        }
315
316
        return $repetition;
317
    }
318
319
    /**
320
     * @param PiggyBank $piggyBank
321
     * @param string    $amount
322
     *
323
     * @return bool
324
     */
325
    public function removeAmount(PiggyBank $piggyBank, string $amount): bool
326
    {
327
        $repetition                = $piggyBank->currentRelevantRep();
328
        $repetition->currentamount = bcsub($repetition->currentamount, $amount);
329
        $repetition->save();
330
331
        // create event
332
        $this->createEvent($piggyBank, bcmul($amount, '-1'));
333
334
        return true;
335
    }
336
337
    /**
338
     * Set all piggy banks to order 0.
339
     *
340
     * @return bool
341
     */
342
    public function reset(): bool
343
    {
344
        // split query to make it work in sqlite:
345
        $set = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.id')
346
                        ->where('accounts.user_id', $this->user->id)->get(['piggy_banks.*']);
347
        foreach ($set as $e) {
348
            $e->order = 0;
349
            $e->save();
350
        }
351
352
        return true;
353
    }
354
355
    /**
356
     * set id of piggy bank.
357
     *
358
     * @param int $piggyBankId
359
     * @param int $order
360
     *
361
     * @return bool
362
     */
363
    public function setOrder(int $piggyBankId, int $order): bool
364
    {
365
        $piggyBank = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')->where('accounts.user_id', $this->user->id)
366
                              ->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
367
        if ($piggyBank) {
368
            $piggyBank->order = $order;
369
            $piggyBank->save();
370
        }
371
372
        return true;
373
    }
374
375
    /**
376
     * @param User $user
377
     */
378
    public function setUser(User $user)
379
    {
380
        $this->user = $user;
381
    }
382
383
    /**
384
     * @param array $data
385
     *
386
     * @return PiggyBank
387
     */
388
    public function store(array $data): PiggyBank
389
    {
390
        $data['order'] = $this->getMaxOrder() + 1;
391
        /** @var PiggyBank $piggyBank */
392
        $piggyBank = PiggyBank::create($data);
393
394
        $this->updateNote($piggyBank, $data['note']);
395
396
        return $piggyBank;
397
    }
398
399
    /**
400
     * @param PiggyBank $piggyBank
401
     * @param array     $data
402
     *
403
     * @return PiggyBank
404
     */
405
    public function update(PiggyBank $piggyBank, array $data): PiggyBank
406
    {
407
        $piggyBank->name         = $data['name'];
408
        $piggyBank->account_id   = (int)$data['account_id'];
409
        $piggyBank->targetamount = round($data['targetamount'], 2);
410
        $piggyBank->targetdate   = $data['targetdate'];
411
        $piggyBank->startdate    = $data['startdate'];
412
413
        $piggyBank->save();
414
415
        $this->updateNote($piggyBank, $data['note']);
416
417
        // if the piggy bank is now smaller than the current relevant rep,
418
        // remove money from the rep.
419
        $repetition = $piggyBank->currentRelevantRep();
420
        if ($repetition->currentamount > $piggyBank->targetamount) {
421
            $diff = bcsub($piggyBank->targetamount, $repetition->currentamount);
422
            $this->createEvent($piggyBank, $diff);
423
424
            $repetition->currentamount = $piggyBank->targetamount;
425
            $repetition->save();
426
        }
427
428
        return $piggyBank;
429
    }
430
431
    /**
432
     * @param PiggyBank $piggyBank
433
     * @param string    $note
434
     *
435
     * @return bool
436
     */
437
    private function updateNote(PiggyBank $piggyBank, string $note): bool
438
    {
439
        if (0 === strlen($note)) {
440
            $dbNote = $piggyBank->notes()->first();
441
            if (null !== $dbNote) {
442
                $dbNote->delete();
443
            }
444
445
            return true;
446
        }
447
        $dbNote = $piggyBank->notes()->first();
448
        if (null === $dbNote) {
449
            $dbNote = new Note();
450
            $dbNote->noteable()->associate($piggyBank);
451
        }
452
        $dbNote->text = trim($note);
453
        $dbNote->save();
454
455
        return true;
456
    }
457
}
458