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    = strval($piggyBank->currentRelevantRep()->currentamount);
88
        $leftToSave    = bcsub($piggyBank->targetamount, $savedSoFar);
89
        $maxAmount     = strval(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
     * @throws \Exception
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 strval($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(strval($piggyBank->targetamount), strval($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 intval($this->user->piggyBanks()->max('order'));
275
    }
276
277
    /**
278
     * @return Collection
279
     */
280
    public function getPiggyBanks(): Collection
281
    {
282
        /** @var Collection $set */
283
        $set = $this->user->piggyBanks()->orderBy('order', 'ASC')->get();
284
285
        return $set;
286
    }
287
288
    /**
289
     * Also add amount in name.
290
     *
291
     * @return Collection
292
     */
293
    public function getPiggyBanksWithAmount(): Collection
294
    {
295
        $currency = app('amount')->getDefaultCurrency();
296
        $set      = $this->getPiggyBanks();
297
        foreach ($set as $piggy) {
298
            $currentAmount = $piggy->currentRelevantRep()->currentamount ?? '0';
299
300
            $piggy->name = $piggy->name . ' (' . app('amount')->formatAnything($currency, $currentAmount, false) . ')';
301
        }
302
303
        return $set;
304
    }
305
306
    /**
307
     * @param PiggyBank $piggyBank
308
     * @param Carbon    $date
309
     *
310
     * @return PiggyBankRepetition
311
     */
312
    public function getRepetition(PiggyBank $piggyBank, Carbon $date): PiggyBankRepetition
313
    {
314
        $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($date)->first();
315
        if (null === $repetition) {
316
            return new PiggyBankRepetition;
317
        }
318
319
        return $repetition;
320
    }
321
322
    /**
323
     * @param PiggyBank $piggyBank
324
     * @param string    $amount
325
     *
326
     * @return bool
327
     */
328
    public function removeAmount(PiggyBank $piggyBank, string $amount): bool
329
    {
330
        $repetition                = $piggyBank->currentRelevantRep();
331
        $repetition->currentamount = bcsub($repetition->currentamount, $amount);
332
        $repetition->save();
333
334
        // create event
335
        $this->createEvent($piggyBank, bcmul($amount, '-1'));
336
337
        return true;
338
    }
339
340
    /**
341
     * Set all piggy banks to order 0.
342
     *
343
     * @return bool
344
     */
345
    public function reset(): bool
346
    {
347
        // split query to make it work in sqlite:
348
        $set = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.id')
349
                        ->where('accounts.user_id', $this->user->id)->get(['piggy_banks.*']);
350
        foreach ($set as $e) {
351
            $e->order = 0;
352
            $e->save();
353
        }
354
355
        return true;
356
    }
357
358
    /**
359
     * set id of piggy bank.
360
     *
361
     * @param int $piggyBankId
362
     * @param int $order
363
     *
364
     * @return bool
365
     */
366
    public function setOrder(int $piggyBankId, int $order): bool
367
    {
368
        $piggyBank = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')->where('accounts.user_id', $this->user->id)
369
                              ->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
370
        if ($piggyBank) {
371
            $piggyBank->order = $order;
372
            $piggyBank->save();
373
        }
374
375
        return true;
376
    }
377
378
    /**
379
     * @param User $user
380
     */
381
    public function setUser(User $user)
382
    {
383
        $this->user = $user;
384
    }
385
386
    /**
387
     * @param array $data
388
     *
389
     * @return PiggyBank
390
     */
391
    public function store(array $data): PiggyBank
392
    {
393
        $data['order'] = $this->getMaxOrder() + 1;
394
        /** @var PiggyBank $piggyBank */
395
        $piggyBank = PiggyBank::create($data);
396
397
        $this->updateNote($piggyBank, $data['note']);
398
399
        return $piggyBank;
400
    }
401
402
    /**
403
     * @param PiggyBank $piggyBank
404
     * @param array     $data
405
     *
406
     * @return PiggyBank
407
     */
408
    public function update(PiggyBank $piggyBank, array $data): PiggyBank
409
    {
410
        $piggyBank->name         = $data['name'];
411
        $piggyBank->account_id   = intval($data['account_id']);
412
        $piggyBank->targetamount = round($data['targetamount'], 2);
413
        $piggyBank->targetdate   = $data['targetdate'];
414
        $piggyBank->startdate    = $data['startdate'];
415
416
        $piggyBank->save();
417
418
        $this->updateNote($piggyBank, $data['note']);
419
420
        // if the piggy bank is now smaller than the current relevant rep,
421
        // remove money from the rep.
422
        $repetition = $piggyBank->currentRelevantRep();
423
        if ($repetition->currentamount > $piggyBank->targetamount) {
424
            $diff = bcsub($piggyBank->targetamount, $repetition->currentamount);
425
            $this->createEvent($piggyBank, $diff);
426
427
            $repetition->currentamount = $piggyBank->targetamount;
428
            $repetition->save();
429
        }
430
431
        return $piggyBank;
432
    }
433
434
    /**
435
     * @param PiggyBank $piggyBank
436
     * @param string    $note
437
     *
438
     * @return bool
439
     */
440
    private function updateNote(PiggyBank $piggyBank, string $note): bool
441
    {
442
        if (0 === strlen($note)) {
443
            $dbNote = $piggyBank->notes()->first();
444
            if (null !== $dbNote) {
445
                $dbNote->delete();
446
            }
447
448
            return true;
449
        }
450
        $dbNote = $piggyBank->notes()->first();
451
        if (null === $dbNote) {
452
            $dbNote = new Note();
453
            $dbNote->noteable()->associate($piggyBank);
454
        }
455
        $dbNote->text = trim($note);
456
        $dbNote->save();
457
458
        return true;
459
    }
460
}
461