1 | <?php |
||
2 | /** |
||
3 | * Steam.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\Support; |
||
24 | |||
25 | use Carbon\Carbon; |
||
26 | use Crypt; |
||
27 | use DB; |
||
28 | use FireflyIII\Models\Account; |
||
29 | use FireflyIII\Models\Transaction; |
||
30 | use Illuminate\Contracts\Encryption\DecryptException; |
||
31 | use Illuminate\Support\Collection; |
||
32 | |||
33 | /** |
||
34 | * Class Steam. |
||
35 | */ |
||
36 | class Steam |
||
37 | { |
||
38 | /** |
||
39 | * @param \FireflyIII\Models\Account $account |
||
40 | * @param \Carbon\Carbon $date |
||
41 | * |
||
42 | * @return string |
||
43 | */ |
||
44 | public function balance(Account $account, Carbon $date): string |
||
45 | { |
||
46 | // abuse chart properties: |
||
47 | $cache = new CacheProperties; |
||
48 | $cache->addProperty($account->id); |
||
49 | $cache->addProperty('balance'); |
||
50 | $cache->addProperty($date); |
||
51 | if ($cache->has()) { |
||
52 | return $cache->get(); // @codeCoverageIgnore |
||
53 | } |
||
54 | $currencyId = intval($account->getMeta('currency_id')); |
||
55 | // use system default currency: |
||
56 | if (0 === $currencyId) { |
||
57 | $currency = app('amount')->getDefaultCurrencyByUser($account->user); |
||
58 | $currencyId = $currency->id; |
||
59 | } |
||
60 | // first part: get all balances in own currency: |
||
61 | $nativeBalance = strval( |
||
62 | $account->transactions() |
||
63 | ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') |
||
64 | ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) |
||
65 | ->where('transactions.transaction_currency_id', $currencyId) |
||
66 | ->sum('transactions.amount') |
||
67 | ); |
||
68 | |||
69 | // get all balances in foreign currency: |
||
70 | $foreignBalance = strval( |
||
71 | $account->transactions() |
||
72 | ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') |
||
73 | ->where('transaction_journals.date', '<=', $date->format('Y-m-d')) |
||
74 | ->where('transactions.foreign_currency_id', $currencyId) |
||
75 | ->where('transactions.transaction_currency_id', '!=', $currencyId) |
||
76 | ->sum('transactions.foreign_amount') |
||
77 | ); |
||
78 | $balance = bcadd($nativeBalance, $foreignBalance); |
||
79 | $virtual = null === $account->virtual_balance ? '0' : strval($account->virtual_balance); |
||
80 | $balance = bcadd($balance, $virtual); |
||
81 | $cache->store($balance); |
||
82 | |||
83 | return $balance; |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * @param \FireflyIII\Models\Account $account |
||
88 | * @param \Carbon\Carbon $date |
||
89 | * |
||
90 | * @return string |
||
91 | */ |
||
92 | public function balanceIgnoreVirtual(Account $account, Carbon $date): string |
||
93 | { |
||
94 | // abuse chart properties: |
||
95 | $cache = new CacheProperties; |
||
96 | $cache->addProperty($account->id); |
||
97 | $cache->addProperty('balance-no-virtual'); |
||
98 | $cache->addProperty($date); |
||
99 | if ($cache->has()) { |
||
100 | return $cache->get(); // @codeCoverageIgnore |
||
101 | } |
||
102 | $currencyId = intval($account->getMeta('currency_id')); |
||
0 ignored issues
–
show
Deprecated Code
introduced
by
Loading history...
|
|||
103 | |||
104 | $nativeBalance = strval( |
||
105 | $account->transactions() |
||
106 | ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') |
||
107 | ->where('transaction_journals.date', '<=', $date->format('Y-m-d')) |
||
108 | ->where('transactions.transaction_currency_id', $currencyId) |
||
109 | ->sum('transactions.amount') |
||
110 | ); |
||
111 | |||
112 | // get all balances in foreign currency: |
||
113 | $foreignBalance = strval( |
||
114 | $account->transactions() |
||
115 | ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') |
||
116 | ->where('transaction_journals.date', '<=', $date->format('Y-m-d')) |
||
117 | ->where('transactions.foreign_currency_id', $currencyId) |
||
118 | ->where('transactions.transaction_currency_id', '!=', $currencyId) |
||
119 | ->sum('transactions.foreign_amount') |
||
120 | ); |
||
121 | $balance = bcadd($nativeBalance, $foreignBalance); |
||
122 | |||
123 | $cache->store($balance); |
||
124 | |||
125 | return $balance; |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * Gets the balance for the given account during the whole range, using this format:. |
||
130 | * |
||
131 | * [yyyy-mm-dd] => 123,2 |
||
132 | * |
||
133 | * @param \FireflyIII\Models\Account $account |
||
134 | * @param \Carbon\Carbon $start |
||
135 | * @param \Carbon\Carbon $end |
||
136 | * |
||
137 | * @return array |
||
138 | */ |
||
139 | public function balanceInRange(Account $account, Carbon $start, Carbon $end): array |
||
140 | { |
||
141 | // abuse chart properties: |
||
142 | $cache = new CacheProperties; |
||
143 | $cache->addProperty($account->id); |
||
144 | $cache->addProperty('balance-in-range'); |
||
145 | $cache->addProperty($start); |
||
146 | $cache->addProperty($end); |
||
147 | if ($cache->has()) { |
||
148 | return $cache->get(); // @codeCoverageIgnore |
||
149 | } |
||
150 | |||
151 | $start->subDay(); |
||
152 | $end->addDay(); |
||
153 | $balances = []; |
||
154 | $formatted = $start->format('Y-m-d'); |
||
155 | $startBalance = $this->balance($account, $start); |
||
156 | |||
157 | $balances[$formatted] = $startBalance; |
||
158 | $currencyId = intval($account->getMeta('currency_id')); |
||
159 | $start->addDay(); |
||
160 | |||
161 | // query! |
||
162 | $set = $account->transactions() |
||
163 | ->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') |
||
164 | ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00')) |
||
165 | ->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59')) |
||
166 | ->groupBy('transaction_journals.date') |
||
167 | ->groupBy('transactions.transaction_currency_id') |
||
168 | ->groupBy('transactions.foreign_currency_id') |
||
169 | ->orderBy('transaction_journals.date', 'ASC') |
||
170 | ->whereNull('transaction_journals.deleted_at') |
||
171 | ->get( |
||
172 | [ |
||
173 | 'transaction_journals.date', |
||
174 | 'transactions.transaction_currency_id', |
||
175 | DB::raw('SUM(transactions.amount) AS modified'), |
||
176 | 'transactions.foreign_currency_id', |
||
177 | DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'), |
||
178 | ] |
||
179 | ); |
||
180 | |||
181 | $currentBalance = $startBalance; |
||
182 | /** @var Transaction $entry */ |
||
183 | foreach ($set as $entry) { |
||
184 | // normal amount and foreign amount |
||
185 | $modified = null === $entry->modified ? '0' : strval($entry->modified); |
||
186 | $foreignModified = null === $entry->modified_foreign ? '0' : strval($entry->modified_foreign); |
||
187 | $amount = '0'; |
||
188 | if ($currencyId === intval($entry->transaction_currency_id) || 0 === $currencyId) { |
||
189 | // use normal amount: |
||
190 | $amount = $modified; |
||
191 | } |
||
192 | if ($currencyId === intval($entry->foreign_currency_id)) { |
||
193 | // use foreign amount: |
||
194 | $amount = $foreignModified; |
||
195 | } |
||
196 | |||
197 | $currentBalance = bcadd($currentBalance, $amount); |
||
198 | $carbon = new Carbon($entry->date); |
||
199 | $date = $carbon->format('Y-m-d'); |
||
200 | $balances[$date] = $currentBalance; |
||
201 | } |
||
202 | |||
203 | $cache->store($balances); |
||
204 | |||
205 | return $balances; |
||
206 | } |
||
207 | |||
208 | /** |
||
209 | * This method always ignores the virtual balance. |
||
210 | * |
||
211 | * @param \Illuminate\Support\Collection $accounts |
||
212 | * @param \Carbon\Carbon $date |
||
213 | * |
||
214 | * @return array |
||
215 | */ |
||
216 | public function balancesByAccounts(Collection $accounts, Carbon $date): array |
||
217 | { |
||
218 | $ids = $accounts->pluck('id')->toArray(); |
||
219 | // cache this property. |
||
220 | $cache = new CacheProperties; |
||
221 | $cache->addProperty($ids); |
||
222 | $cache->addProperty('balances'); |
||
223 | $cache->addProperty($date); |
||
224 | if ($cache->has()) { |
||
225 | return $cache->get(); // @codeCoverageIgnore |
||
226 | } |
||
227 | |||
228 | // need to do this per account. |
||
229 | $result = []; |
||
230 | /** @var Account $account */ |
||
231 | foreach ($accounts as $account) { |
||
232 | $result[$account->id] = $this->balance($account, $date); |
||
233 | } |
||
234 | |||
235 | $cache->store($result); |
||
236 | |||
237 | return $result; |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * @param int $isEncrypted |
||
242 | * @param $value |
||
243 | * |
||
244 | * @return string |
||
245 | * @throws \Illuminate\Contracts\Encryption\DecryptException |
||
246 | */ |
||
247 | public function decrypt(int $isEncrypted, string $value) |
||
248 | { |
||
249 | if (1 === $isEncrypted) { |
||
250 | return Crypt::decrypt($value); |
||
251 | } |
||
252 | |||
253 | return $value; |
||
254 | } |
||
255 | |||
256 | /** |
||
257 | * @param array $accounts |
||
258 | * |
||
259 | * @return array |
||
260 | */ |
||
261 | public function getLastActivities(array $accounts): array |
||
262 | { |
||
263 | $list = []; |
||
264 | |||
265 | $set = auth()->user()->transactions() |
||
266 | ->whereIn('transactions.account_id', $accounts) |
||
267 | ->groupBy(['transactions.account_id', 'transaction_journals.user_id']) |
||
268 | ->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) AS max_date')]); |
||
269 | |||
270 | foreach ($set as $entry) { |
||
271 | $list[intval($entry->account_id)] = new Carbon($entry->max_date); |
||
272 | } |
||
273 | |||
274 | return $list; |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * @param string $amount |
||
279 | * |
||
280 | * @return string |
||
281 | */ |
||
282 | public function negative(string $amount): string |
||
283 | { |
||
284 | if (1 === bccomp($amount, '0')) { |
||
285 | $amount = bcmul($amount, '-1'); |
||
286 | } |
||
287 | |||
288 | return $amount; |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * @param string $amount |
||
293 | * |
||
294 | * @return string|null |
||
295 | */ |
||
296 | public function opposite(string $amount = null): ?string |
||
297 | { |
||
298 | if (is_null($amount)) { |
||
299 | return null; |
||
300 | } |
||
301 | $amount = bcmul($amount, '-1'); |
||
302 | |||
303 | return $amount; |
||
304 | } |
||
305 | |||
306 | /** |
||
307 | * @param $string |
||
308 | * |
||
309 | * @return int |
||
310 | */ |
||
311 | public function phpBytes($string): int |
||
312 | { |
||
313 | $string = strtolower($string); |
||
314 | |||
315 | if (!(false === stripos($string, 'k'))) { |
||
316 | // has a K in it, remove the K and multiply by 1024. |
||
317 | $bytes = bcmul(rtrim($string, 'kK'), '1024'); |
||
318 | |||
319 | return intval($bytes); |
||
320 | } |
||
321 | |||
322 | if (!(false === stripos($string, 'm'))) { |
||
323 | // has a M in it, remove the M and multiply by 1048576. |
||
324 | $bytes = bcmul(rtrim($string, 'mM'), '1048576'); |
||
325 | |||
326 | return intval($bytes); |
||
327 | } |
||
328 | |||
329 | if (!(false === stripos($string, 'g'))) { |
||
330 | // has a G in it, remove the G and multiply by (1024)^3. |
||
331 | $bytes = bcmul(rtrim($string, 'gG'), '1073741824'); |
||
332 | |||
333 | return intval($bytes); |
||
334 | } |
||
335 | |||
336 | return intval($string); |
||
337 | } |
||
338 | |||
339 | /** |
||
340 | * @param string $amount |
||
341 | * |
||
342 | * @return string |
||
343 | */ |
||
344 | public function positive(string $amount): string |
||
345 | { |
||
346 | if (bccomp($amount, '0') === -1) { |
||
347 | $amount = bcmul($amount, '-1'); |
||
348 | } |
||
349 | |||
350 | return $amount; |
||
351 | } |
||
352 | |||
353 | /** |
||
354 | * @param $value |
||
355 | * |
||
356 | * @return mixed |
||
357 | */ |
||
358 | public function tryDecrypt($value) |
||
359 | { |
||
360 | try { |
||
361 | $value = Crypt::decrypt($value); |
||
362 | } catch (DecryptException $e) { |
||
363 | // do not care. |
||
364 | } |
||
365 | |||
366 | return $value; |
||
367 | } |
||
368 | } |
||
369 |