2015-02-09 00:23:39 -06:00
|
|
|
<?php
|
2016-02-05 05:08:25 -06:00
|
|
|
declare(strict_types = 1);
|
2015-02-09 00:23:39 -06:00
|
|
|
|
|
|
|
namespace FireflyIII\Repositories\Account;
|
|
|
|
|
2015-02-21 05:16:41 -06:00
|
|
|
use Auth;
|
|
|
|
use Carbon\Carbon;
|
2015-02-09 00:56:24 -06:00
|
|
|
use Config;
|
2015-04-13 13:43:58 -05:00
|
|
|
use DB;
|
2016-02-17 08:52:46 -06:00
|
|
|
use FireflyIII\Exceptions\FireflyException;
|
2015-02-09 00:23:39 -06:00
|
|
|
use FireflyIII\Models\Account;
|
2015-02-14 07:25:29 -06:00
|
|
|
use FireflyIII\Models\AccountMeta;
|
2015-02-09 00:23:39 -06:00
|
|
|
use FireflyIII\Models\AccountType;
|
2015-02-24 14:10:25 -06:00
|
|
|
use FireflyIII\Models\PiggyBank;
|
2015-03-13 02:44:07 -05:00
|
|
|
use FireflyIII\Models\Preference;
|
2015-02-09 00:56:24 -06:00
|
|
|
use FireflyIII\Models\Transaction;
|
|
|
|
use FireflyIII\Models\TransactionJournal;
|
|
|
|
use FireflyIII\Models\TransactionType;
|
2015-04-04 14:23:37 -05:00
|
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
2015-02-21 05:16:41 -06:00
|
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
2015-03-13 02:44:07 -05:00
|
|
|
use Illuminate\Support\Collection;
|
2015-02-14 07:25:29 -06:00
|
|
|
use Log;
|
2015-03-21 02:51:34 -05:00
|
|
|
use Steam;
|
2015-02-09 00:23:39 -06:00
|
|
|
|
2015-05-05 13:46:13 -05:00
|
|
|
|
2015-02-09 00:23:39 -06:00
|
|
|
/**
|
2015-05-26 01:17:58 -05:00
|
|
|
*
|
2015-02-09 00:23:39 -06:00
|
|
|
* Class AccountRepository
|
|
|
|
*
|
|
|
|
* @package FireflyIII\Repositories\Account
|
|
|
|
*/
|
|
|
|
class AccountRepository implements AccountRepositoryInterface
|
|
|
|
{
|
|
|
|
|
2016-02-10 23:30:37 -06:00
|
|
|
/** @var array Valid field names of account_meta */
|
2016-02-10 15:09:24 -06:00
|
|
|
private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber'];
|
|
|
|
|
2015-03-13 02:44:07 -05:00
|
|
|
/**
|
2015-04-04 14:23:37 -05:00
|
|
|
* @param array $types
|
|
|
|
*
|
2015-03-13 02:44:07 -05:00
|
|
|
* @return int
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function countAccounts(array $types): int
|
2015-03-13 02:44:07 -05:00
|
|
|
{
|
2015-12-25 10:11:55 -06:00
|
|
|
$count = Auth::user()->accounts()->accountTypeIn($types)->count();
|
|
|
|
|
|
|
|
return $count;
|
2015-03-13 02:44:07 -05:00
|
|
|
}
|
|
|
|
|
2015-02-14 07:25:29 -06:00
|
|
|
/**
|
|
|
|
* @param Account $account
|
2015-07-10 13:48:45 -05:00
|
|
|
* @param Account $moveTo
|
2015-02-14 07:25:29 -06:00
|
|
|
*
|
2016-02-06 09:22:12 -06:00
|
|
|
* @return bool
|
2015-02-14 07:25:29 -06:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function destroy(Account $account, Account $moveTo = null): bool
|
2015-02-14 07:25:29 -06:00
|
|
|
{
|
2015-07-10 13:48:45 -05:00
|
|
|
if (!is_null($moveTo)) {
|
|
|
|
// update all transactions:
|
|
|
|
DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
|
|
|
|
}
|
|
|
|
|
2015-02-14 07:25:29 -06:00
|
|
|
$account->delete();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-01-19 06:59:54 -06:00
|
|
|
/**
|
|
|
|
* @deprecated
|
|
|
|
*
|
2016-02-05 02:25:15 -06:00
|
|
|
* @param int $accountId
|
2016-01-19 06:59:54 -06:00
|
|
|
*
|
|
|
|
* @return Account
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function find(int $accountId): Account
|
2016-01-19 06:59:54 -06:00
|
|
|
{
|
|
|
|
return Auth::user()->accounts()->findOrNew($accountId);
|
|
|
|
}
|
|
|
|
|
2016-02-04 01:53:15 -06:00
|
|
|
/**
|
|
|
|
* Gets all the accounts by ID, for a given set.
|
|
|
|
*
|
|
|
|
* @param array $ids
|
|
|
|
*
|
|
|
|
* @return Collection
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function get(array $ids): Collection
|
2016-02-04 01:53:15 -06:00
|
|
|
{
|
|
|
|
return Auth::user()->accounts()->whereIn('id', $ids)->get(['accounts.*']);
|
|
|
|
}
|
|
|
|
|
2015-04-04 14:23:37 -05:00
|
|
|
/**
|
|
|
|
* @param array $types
|
|
|
|
*
|
|
|
|
* @return Collection
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function getAccounts(array $types): Collection
|
2015-04-04 14:23:37 -05:00
|
|
|
{
|
2015-07-08 06:05:33 -05:00
|
|
|
/** @var Collection $result */
|
2015-04-11 08:01:42 -05:00
|
|
|
$result = Auth::user()->accounts()->with(
|
2015-06-05 05:18:20 -05:00
|
|
|
['accountmeta' => function (HasMany $query) {
|
2015-04-04 14:23:37 -05:00
|
|
|
$query->where('name', 'accountRole');
|
|
|
|
}]
|
2015-07-10 00:39:59 -05:00
|
|
|
)->accountTypeIn($types)->get(['accounts.*']);
|
2015-04-07 03:14:10 -05:00
|
|
|
|
2015-07-08 06:05:33 -05:00
|
|
|
$result = $result->sortBy(
|
|
|
|
function (Account $account) {
|
|
|
|
return strtolower($account->name);
|
|
|
|
}
|
|
|
|
);
|
2016-01-15 06:13:33 -06:00
|
|
|
|
2015-04-07 03:14:10 -05:00
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-12-27 00:59:00 -06:00
|
|
|
* This method returns the users credit cards, along with some basic information about the
|
|
|
|
* balance they have on their CC. To be used in the JSON boxes on the front page that say
|
|
|
|
* how many bills there are still left to pay. The balance will be saved in field "balance".
|
|
|
|
*
|
|
|
|
* To get the balance, the field "date" is necessary.
|
|
|
|
*
|
|
|
|
* @param Carbon $date
|
|
|
|
*
|
2015-04-07 03:14:10 -05:00
|
|
|
* @return Collection
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function getCreditCards(Carbon $date): Collection
|
2015-04-07 03:14:10 -05:00
|
|
|
{
|
2015-12-27 12:51:20 -06:00
|
|
|
$set = Auth::user()->accounts()
|
2015-06-05 05:18:20 -05:00
|
|
|
->hasMetaValue('accountRole', 'ccAsset')
|
|
|
|
->hasMetaValue('ccType', 'monthlyFull')
|
2015-12-27 00:59:00 -06:00
|
|
|
->leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
|
|
|
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
|
|
|
->whereNull('transactions.deleted_at')
|
|
|
|
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))
|
|
|
|
->groupBy('accounts.id')
|
2015-06-05 05:18:20 -05:00
|
|
|
->get(
|
|
|
|
[
|
|
|
|
'accounts.*',
|
|
|
|
'ccType.data as ccType',
|
2015-12-27 00:59:00 -06:00
|
|
|
'accountRole.data as accountRole',
|
2016-02-07 00:56:58 -06:00
|
|
|
DB::raw('SUM(`transactions`.`amount`) AS `balance`'),
|
2015-06-05 05:18:20 -05:00
|
|
|
]
|
|
|
|
);
|
2016-01-15 06:13:33 -06:00
|
|
|
|
2015-12-27 12:51:20 -06:00
|
|
|
return $set;
|
2015-04-04 14:23:37 -05:00
|
|
|
}
|
|
|
|
|
2015-04-03 02:30:44 -05:00
|
|
|
/**
|
|
|
|
* @param TransactionJournal $journal
|
|
|
|
* @param Account $account
|
|
|
|
*
|
|
|
|
* @return Transaction
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function getFirstTransaction(TransactionJournal $journal, Account $account): Transaction
|
2015-04-03 02:30:44 -05:00
|
|
|
{
|
2015-12-26 01:44:34 -06:00
|
|
|
$transaction = $journal->transactions()->where('account_id', $account->id)->first();
|
2015-04-03 02:30:44 -05:00
|
|
|
|
2015-12-26 01:44:34 -06:00
|
|
|
return $transaction;
|
2015-04-03 02:30:44 -05:00
|
|
|
}
|
|
|
|
|
2015-03-13 02:44:07 -05:00
|
|
|
/**
|
|
|
|
* @param Preference $preference
|
|
|
|
*
|
|
|
|
* @return Collection
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function getFrontpageAccounts(Preference $preference): Collection
|
2015-03-13 02:44:07 -05:00
|
|
|
{
|
2015-07-26 12:07:02 -05:00
|
|
|
$query = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account']);
|
2015-06-03 11:22:47 -05:00
|
|
|
|
2015-07-26 12:07:02 -05:00
|
|
|
if (count($preference->data) > 0) {
|
2015-07-26 12:10:31 -05:00
|
|
|
$query->whereIn('accounts.id', $preference->data);
|
2015-03-13 02:44:07 -05:00
|
|
|
}
|
|
|
|
|
2015-07-26 12:07:02 -05:00
|
|
|
$result = $query->get(['accounts.*']);
|
2016-01-15 06:13:33 -06:00
|
|
|
|
2015-07-26 12:07:02 -05:00
|
|
|
return $result;
|
2015-03-13 02:44:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2015-03-20 16:39:07 -05:00
|
|
|
* This method is used on the front page where (in turn) its viewed journals-tiny.php which (in turn)
|
|
|
|
* is almost the only place where formatJournal is used. Aka, we can use some custom querying to get some specific.
|
|
|
|
* fields using left joins.
|
|
|
|
*
|
2015-03-13 02:44:07 -05:00
|
|
|
* @param Account $account
|
|
|
|
* @param Carbon $start
|
|
|
|
* @param Carbon $end
|
|
|
|
*
|
2016-02-06 09:22:12 -06:00
|
|
|
* @return Collection
|
2015-03-13 02:44:07 -05:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end): Collection
|
2015-03-13 02:44:07 -05:00
|
|
|
{
|
2015-06-03 11:22:47 -05:00
|
|
|
$set = Auth::user()
|
2015-06-05 05:18:20 -05:00
|
|
|
->transactionjournals()
|
|
|
|
->with(['transactions'])
|
|
|
|
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
|
|
|
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $account->id)
|
|
|
|
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transaction_journals.transaction_currency_id')
|
|
|
|
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
|
|
|
->before($end)
|
|
|
|
->after($start)
|
|
|
|
->orderBy('transaction_journals.date', 'DESC')
|
2015-12-21 04:30:58 -06:00
|
|
|
->orderBy('transaction_journals.order', 'ASC')
|
2015-06-05 05:18:20 -05:00
|
|
|
->orderBy('transaction_journals.id', 'DESC')
|
|
|
|
->take(10)
|
|
|
|
->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']);
|
2016-01-15 06:13:33 -06:00
|
|
|
|
2015-06-03 11:22:47 -05:00
|
|
|
return $set;
|
2015-03-13 02:44:07 -05:00
|
|
|
}
|
|
|
|
|
2015-02-21 05:16:41 -06:00
|
|
|
/**
|
|
|
|
* @param Account $account
|
|
|
|
* @param int $page
|
|
|
|
*
|
2015-04-07 11:48:34 -05:00
|
|
|
* @return LengthAwarePaginator
|
2015-02-21 05:16:41 -06:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function getJournals(Account $account, $page): LengthAwarePaginator
|
2015-02-21 05:16:41 -06:00
|
|
|
{
|
2015-03-02 04:42:27 -06:00
|
|
|
$offset = ($page - 1) * 50;
|
2015-02-21 05:16:41 -06:00
|
|
|
$query = Auth::user()
|
2015-06-05 05:18:20 -05:00
|
|
|
->transactionJournals()
|
|
|
|
->withRelevantData()
|
|
|
|
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
|
|
|
->where('transactions.account_id', $account->id)
|
|
|
|
->orderBy('transaction_journals.date', 'DESC')
|
|
|
|
->orderBy('transaction_journals.order', 'ASC')
|
|
|
|
->orderBy('transaction_journals.id', 'DESC');
|
2015-02-21 05:16:41 -06:00
|
|
|
|
2015-02-23 14:55:52 -06:00
|
|
|
$count = $query->count();
|
|
|
|
$set = $query->take(50)->offset($offset)->get(['transaction_journals.*']);
|
|
|
|
$paginator = new LengthAwarePaginator($set, $count, 50, $page);
|
2015-02-22 01:38:46 -06:00
|
|
|
|
2015-02-21 05:16:41 -06:00
|
|
|
return $paginator;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-04-13 13:43:58 -05:00
|
|
|
/**
|
|
|
|
* Get the accounts of a user that have piggy banks connected to them.
|
|
|
|
*
|
|
|
|
* @return Collection
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function getPiggyBankAccounts(): Collection
|
2015-04-13 13:43:58 -05:00
|
|
|
{
|
2016-02-04 00:27:03 -06:00
|
|
|
$start = clone session('start', new Carbon);
|
|
|
|
$end = clone session('end', new Carbon);
|
2015-12-30 02:30:06 -06:00
|
|
|
$collection = new Collection(DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id']));
|
|
|
|
$ids = $collection->pluck('account_id')->toArray();
|
2016-01-01 05:41:00 -06:00
|
|
|
$accounts = new Collection;
|
2015-04-13 13:43:58 -05:00
|
|
|
|
|
|
|
$ids = array_unique($ids);
|
|
|
|
if (count($ids) > 0) {
|
2015-12-02 01:25:38 -06:00
|
|
|
$accounts = Auth::user()->accounts()->whereIn('id', $ids)->where('accounts.active', 1)->get();
|
2015-04-13 13:43:58 -05:00
|
|
|
}
|
2015-07-26 12:42:28 -05:00
|
|
|
bcscale(2);
|
2015-04-13 13:43:58 -05:00
|
|
|
|
|
|
|
$accounts->each(
|
2015-06-05 05:18:20 -05:00
|
|
|
function (Account $account) use ($start, $end) {
|
2015-04-13 14:13:05 -05:00
|
|
|
$account->startBalance = Steam::balance($account, $start, true);
|
|
|
|
$account->endBalance = Steam::balance($account, $end, true);
|
2016-02-05 05:28:05 -06:00
|
|
|
$account->piggyBalance = '0';
|
2015-04-13 13:43:58 -05:00
|
|
|
/** @var PiggyBank $piggyBank */
|
|
|
|
foreach ($account->piggyBanks as $piggyBank) {
|
2016-02-05 05:28:05 -06:00
|
|
|
$account->piggyBalance = bcadd($piggyBank->currentRelevantRep()->currentamount, $account->piggyBalance);
|
2015-04-13 13:43:58 -05:00
|
|
|
}
|
|
|
|
// sum of piggy bank amounts on this account:
|
|
|
|
// diff between endBalance and piggyBalance.
|
|
|
|
// then, percentage.
|
2015-07-26 12:42:28 -05:00
|
|
|
$difference = bcsub($account->endBalance, $account->piggyBalance);
|
2015-04-13 13:43:58 -05:00
|
|
|
$account->difference = $difference;
|
2015-05-06 11:09:45 -05:00
|
|
|
$account->percentage = $difference != 0 && $account->endBalance != 0 ? round((($difference / $account->endBalance) * 100)) : 100;
|
2015-04-13 13:43:58 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
return $accounts;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-03-21 02:51:34 -05:00
|
|
|
/**
|
|
|
|
* Get savings accounts and the balance difference in the period.
|
|
|
|
*
|
|
|
|
* @return Collection
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function getSavingsAccounts(): Collection
|
2015-03-21 02:51:34 -05:00
|
|
|
{
|
|
|
|
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')
|
|
|
|
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
|
|
|
|
->where('account_meta.name', 'accountRole')
|
2015-12-02 01:22:25 -06:00
|
|
|
->where('accounts.active', 1)
|
2015-03-21 02:51:34 -05:00
|
|
|
->where('account_meta.data', '"savingAsset"')
|
|
|
|
->get(['accounts.*']);
|
2016-02-04 00:27:03 -06:00
|
|
|
$start = clone session('start', new Carbon);
|
|
|
|
$end = clone session('end', new Carbon);
|
2015-03-21 02:51:34 -05:00
|
|
|
|
2015-07-26 12:42:28 -05:00
|
|
|
bcscale(2);
|
|
|
|
|
2015-03-21 02:51:34 -05:00
|
|
|
$accounts->each(
|
2015-06-05 05:18:20 -05:00
|
|
|
function (Account $account) use ($start, $end) {
|
2015-03-21 02:51:34 -05:00
|
|
|
$account->startBalance = Steam::balance($account, $start);
|
|
|
|
$account->endBalance = Steam::balance($account, $end);
|
|
|
|
|
|
|
|
// diff (negative when lost, positive when gained)
|
2015-07-26 12:42:28 -05:00
|
|
|
$diff = bcsub($account->endBalance, $account->startBalance);
|
2015-03-21 02:51:34 -05:00
|
|
|
|
2015-03-21 02:55:55 -05:00
|
|
|
if ($diff < 0 && $account->startBalance > 0) {
|
2015-03-21 02:51:34 -05:00
|
|
|
// percentage lost compared to start.
|
|
|
|
$pct = (($diff * -1) / $account->startBalance) * 100;
|
|
|
|
} else {
|
2015-03-21 02:55:55 -05:00
|
|
|
if ($diff >= 0 && $account->startBalance > 0) {
|
|
|
|
$pct = ($diff / $account->startBalance) * 100;
|
|
|
|
} else {
|
2015-03-21 02:56:24 -05:00
|
|
|
$pct = 100;
|
2015-03-21 02:55:55 -05:00
|
|
|
}
|
2015-03-21 02:51:34 -05:00
|
|
|
}
|
2015-03-21 02:55:55 -05:00
|
|
|
$pct = $pct > 100 ? 100 : $pct;
|
2015-03-21 02:51:34 -05:00
|
|
|
$account->difference = $diff;
|
|
|
|
$account->percentage = round($pct);
|
2015-05-07 13:56:27 -05:00
|
|
|
|
2015-03-21 02:51:34 -05:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
return $accounts;
|
|
|
|
}
|
|
|
|
|
2015-03-02 04:42:27 -06:00
|
|
|
/**
|
|
|
|
* @param Account $account
|
2015-05-20 12:55:53 -05:00
|
|
|
* @param Carbon $date
|
2015-03-02 04:42:27 -06:00
|
|
|
*
|
2016-02-06 09:22:12 -06:00
|
|
|
* @return string
|
2015-03-02 04:42:27 -06:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function leftOnAccount(Account $account, Carbon $date): string
|
2015-03-02 04:42:27 -06:00
|
|
|
{
|
2015-05-17 02:35:49 -05:00
|
|
|
|
|
|
|
$balance = Steam::balance($account, $date, true);
|
2015-03-02 04:42:27 -06:00
|
|
|
/** @var PiggyBank $p */
|
2016-02-07 00:56:58 -06:00
|
|
|
foreach ($account->piggyBanks()->get() as $p) {
|
2016-02-12 08:01:32 -06:00
|
|
|
$balance = bcsub($balance, $p->currentRelevantRep()->currentamount);
|
2015-03-02 04:42:27 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return $balance;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-02-14 07:25:29 -06:00
|
|
|
/**
|
|
|
|
* @param Account $account
|
|
|
|
*
|
|
|
|
* @return TransactionJournal|null
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function openingBalanceTransaction(Account $account): TransactionJournal
|
2015-02-14 07:25:29 -06:00
|
|
|
{
|
2015-12-26 01:44:34 -06:00
|
|
|
$journal = TransactionJournal
|
2015-06-05 05:18:20 -05:00
|
|
|
::orderBy('transaction_journals.date', 'ASC')
|
2016-01-15 15:41:26 -06:00
|
|
|
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
|
|
|
->where('transactions.account_id', $account->id)
|
2015-12-09 18:39:50 -06:00
|
|
|
->transactionTypes([TransactionType::OPENING_BALANCE])
|
2015-06-05 05:18:20 -05:00
|
|
|
->orderBy('created_at', 'ASC')
|
|
|
|
->first(['transaction_journals.*']);
|
2016-02-07 00:56:58 -06:00
|
|
|
if (is_null($journal)) {
|
2016-02-06 09:22:12 -06:00
|
|
|
return new TransactionJournal;
|
|
|
|
}
|
2015-12-26 01:44:34 -06:00
|
|
|
|
|
|
|
return $journal;
|
2015-02-14 07:25:29 -06:00
|
|
|
}
|
|
|
|
|
2015-02-09 00:23:39 -06:00
|
|
|
/**
|
|
|
|
* @param array $data
|
|
|
|
*
|
2015-05-27 01:36:26 -05:00
|
|
|
* @return Account
|
2015-02-09 00:23:39 -06:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function store(array $data): Account
|
2015-02-09 00:23:39 -06:00
|
|
|
{
|
2015-03-29 01:24:56 -05:00
|
|
|
$newAccount = $this->storeAccount($data);
|
2015-07-06 11:48:17 -05:00
|
|
|
if (!is_null($newAccount)) {
|
|
|
|
$this->storeMetadata($newAccount, $data);
|
|
|
|
}
|
2015-02-09 00:23:39 -06:00
|
|
|
|
|
|
|
|
|
|
|
// continue with the opposing account:
|
|
|
|
if ($data['openingBalance'] != 0) {
|
2015-02-09 00:56:24 -06:00
|
|
|
$opposingData = [
|
2015-06-02 10:58:30 -05:00
|
|
|
'user' => $data['user'],
|
2015-08-15 14:45:29 -05:00
|
|
|
'accountType' => 'initial',
|
2015-06-01 11:13:54 -05:00
|
|
|
'virtualBalance' => 0,
|
2015-06-02 10:58:30 -05:00
|
|
|
'name' => $data['name'] . ' initial balance',
|
|
|
|
'active' => false,
|
2015-07-03 05:51:14 -05:00
|
|
|
'iban' => '',
|
2015-02-09 00:23:39 -06:00
|
|
|
];
|
2015-06-05 05:18:20 -05:00
|
|
|
$opposing = $this->storeAccount($opposingData);
|
2015-07-06 11:57:15 -05:00
|
|
|
if (!is_null($opposing) && !is_null($newAccount)) {
|
2015-07-06 11:13:57 -05:00
|
|
|
$this->storeInitialBalance($newAccount, $opposing, $data);
|
|
|
|
}
|
2015-02-09 00:56:24 -06:00
|
|
|
|
2015-02-09 00:23:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return $newAccount;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-04-13 13:43:58 -05:00
|
|
|
/**
|
2015-07-26 12:07:02 -05:00
|
|
|
* @return string
|
2015-04-13 13:43:58 -05:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function sumOfEverything(): string
|
2015-04-13 13:43:58 -05:00
|
|
|
{
|
2016-02-11 04:21:50 -06:00
|
|
|
return strval(Auth::user()->transactions()->sum('amount'));
|
2015-04-13 13:43:58 -05:00
|
|
|
}
|
|
|
|
|
2015-02-14 07:25:29 -06:00
|
|
|
/**
|
|
|
|
* @param Account $account
|
|
|
|
* @param array $data
|
2015-05-05 03:23:01 -05:00
|
|
|
*
|
2016-01-15 12:37:09 -06:00
|
|
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // need the complexity.
|
|
|
|
*
|
2015-05-05 03:23:01 -05:00
|
|
|
* @return Account
|
2015-02-14 07:25:29 -06:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
public function update(Account $account, array $data): Account
|
2015-02-14 07:25:29 -06:00
|
|
|
{
|
|
|
|
// update the account:
|
2015-04-01 12:42:14 -05:00
|
|
|
$account->name = $data['name'];
|
|
|
|
$account->active = $data['active'] == '1' ? true : false;
|
|
|
|
$account->virtual_balance = $data['virtualBalance'];
|
2015-07-03 05:51:14 -05:00
|
|
|
$account->iban = $data['iban'];
|
2015-02-14 07:25:29 -06:00
|
|
|
$account->save();
|
|
|
|
|
2015-03-29 01:24:56 -05:00
|
|
|
$this->updateMetadata($account, $data);
|
2015-02-14 07:25:29 -06:00
|
|
|
$openingBalance = $this->openingBalanceTransaction($account);
|
|
|
|
if ($data['openingBalance'] != 0) {
|
|
|
|
if ($openingBalance) {
|
2015-03-29 01:24:56 -05:00
|
|
|
$this->updateInitialBalance($account, $openingBalance, $data);
|
2015-02-14 07:25:29 -06:00
|
|
|
} else {
|
|
|
|
$type = $data['openingBalance'] < 0 ? 'expense' : 'revenue';
|
|
|
|
$opposingData = [
|
2015-06-02 10:58:30 -05:00
|
|
|
'user' => $data['user'],
|
|
|
|
'accountType' => $type,
|
|
|
|
'name' => $data['name'] . ' initial balance',
|
|
|
|
'active' => false,
|
2015-07-09 07:04:01 -05:00
|
|
|
'iban' => '',
|
2015-06-02 10:58:30 -05:00
|
|
|
'virtualBalance' => 0,
|
2015-02-14 07:25:29 -06:00
|
|
|
];
|
2015-06-05 05:18:20 -05:00
|
|
|
$opposing = $this->storeAccount($opposingData);
|
2015-07-06 11:48:17 -05:00
|
|
|
if (!is_null($opposing)) {
|
|
|
|
$this->storeInitialBalance($account, $opposing, $data);
|
|
|
|
}
|
2015-02-14 07:25:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2015-05-26 01:17:58 -05:00
|
|
|
if ($openingBalance) { // opening balance is zero, should we delete it?
|
2015-05-26 13:57:31 -05:00
|
|
|
$openingBalance->delete(); // delete existing opening balance.
|
2015-02-14 07:25:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $account;
|
|
|
|
}
|
|
|
|
|
2015-02-09 00:23:39 -06:00
|
|
|
/**
|
|
|
|
* @param array $data
|
2015-02-09 00:56:24 -06:00
|
|
|
*
|
|
|
|
* @return Account
|
2016-02-17 14:14:32 -06:00
|
|
|
* @throws FireflyException
|
2015-02-09 00:23:39 -06:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
private function storeAccount(array $data): Account
|
2015-02-09 00:23:39 -06:00
|
|
|
{
|
2015-02-09 00:56:24 -06:00
|
|
|
$type = Config::get('firefly.accountTypeByIdentifier.' . $data['accountType']);
|
|
|
|
$accountType = AccountType::whereType($type)->first();
|
2015-02-09 00:23:39 -06:00
|
|
|
$newAccount = new Account(
|
|
|
|
[
|
|
|
|
'user_id' => $data['user'],
|
|
|
|
'account_type_id' => $accountType->id,
|
|
|
|
'name' => $data['name'],
|
2015-06-01 11:13:54 -05:00
|
|
|
'virtual_balance' => $data['virtualBalance'],
|
2015-02-09 00:23:39 -06:00
|
|
|
'active' => $data['active'] === true ? true : false,
|
2015-07-03 05:51:14 -05:00
|
|
|
'iban' => $data['iban'],
|
2015-02-09 00:23:39 -06:00
|
|
|
]
|
|
|
|
);
|
2015-03-26 12:05:23 -05:00
|
|
|
|
2015-02-09 00:23:39 -06:00
|
|
|
if (!$newAccount->isValid()) {
|
2015-02-14 07:25:29 -06:00
|
|
|
// does the account already exist?
|
2015-06-05 05:18:20 -05:00
|
|
|
$searchData = [
|
2015-05-08 00:27:29 -05:00
|
|
|
'user_id' => $data['user'],
|
|
|
|
'account_type_id' => $accountType->id,
|
2015-06-01 11:13:54 -05:00
|
|
|
'virtual_balance' => $data['virtualBalance'],
|
2015-07-03 05:51:14 -05:00
|
|
|
'name' => $data['name'],
|
|
|
|
'iban' => $data['iban'],
|
2015-05-08 00:27:29 -05:00
|
|
|
];
|
|
|
|
$existingAccount = Account::firstOrNullEncrypted($searchData);
|
2015-02-14 07:25:29 -06:00
|
|
|
if (!$existingAccount) {
|
|
|
|
Log::error('Account create error: ' . $newAccount->getErrors()->toJson());
|
2016-02-17 08:52:46 -06:00
|
|
|
throw new FireflyException(
|
|
|
|
'Cannot create a new account. See also the log files. First error is: ' . e($newAccount->getErrors()->first()) . '.'
|
|
|
|
);
|
2015-02-14 07:25:29 -06:00
|
|
|
}
|
|
|
|
$newAccount = $existingAccount;
|
2015-05-08 00:39:05 -05:00
|
|
|
|
2015-02-09 00:23:39 -06:00
|
|
|
}
|
|
|
|
$newAccount->save();
|
2015-02-09 00:56:24 -06:00
|
|
|
|
|
|
|
return $newAccount;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Account $account
|
|
|
|
* @param Account $opposing
|
|
|
|
* @param array $data
|
2015-02-11 00:35:10 -06:00
|
|
|
*
|
|
|
|
* @return TransactionJournal
|
2015-02-09 00:56:24 -06:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
private function storeInitialBalance(Account $account, Account $opposing, array $data): TransactionJournal
|
2015-02-09 00:56:24 -06:00
|
|
|
{
|
2015-12-09 18:39:50 -06:00
|
|
|
$transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first();
|
2015-07-26 10:03:05 -05:00
|
|
|
$journal = TransactionJournal::create(
|
2015-02-09 00:56:24 -06:00
|
|
|
[
|
|
|
|
'user_id' => $data['user'],
|
|
|
|
'transaction_type_id' => $transactionType->id,
|
|
|
|
'bill_id' => null,
|
|
|
|
'transaction_currency_id' => $data['openingBalanceCurrency'],
|
|
|
|
'description' => 'Initial balance for "' . $account->name . '"',
|
|
|
|
'completed' => true,
|
|
|
|
'date' => $data['openingBalanceDate'],
|
2016-01-15 12:37:09 -06:00
|
|
|
'encrypted' => true,
|
2015-02-09 00:56:24 -06:00
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($data['openingBalance'] < 0) {
|
|
|
|
$firstAccount = $opposing;
|
|
|
|
$secondAccount = $account;
|
|
|
|
$firstAmount = $data['openingBalance'] * -1;
|
|
|
|
$secondAmount = $data['openingBalance'];
|
|
|
|
} else {
|
|
|
|
$firstAccount = $account;
|
|
|
|
$secondAccount = $opposing;
|
|
|
|
$firstAmount = $data['openingBalance'];
|
|
|
|
$secondAmount = $data['openingBalance'] * -1;
|
|
|
|
}
|
2015-07-26 10:03:05 -05:00
|
|
|
|
2015-07-06 15:23:34 -05:00
|
|
|
$one = new Transaction(['account_id' => $firstAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $firstAmount]);
|
|
|
|
$one->save();// first transaction: from
|
2015-02-09 00:56:24 -06:00
|
|
|
|
2015-07-06 15:23:34 -05:00
|
|
|
$two = new Transaction(['account_id' => $secondAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $secondAmount]);
|
|
|
|
$two->save(); // second transaction: to
|
2015-02-09 00:56:24 -06:00
|
|
|
|
|
|
|
return $journal;
|
|
|
|
|
2015-02-09 00:23:39 -06:00
|
|
|
}
|
|
|
|
|
2015-02-24 14:10:25 -06:00
|
|
|
/**
|
|
|
|
* @param Account $account
|
2015-03-02 04:42:27 -06:00
|
|
|
* @param array $data
|
2016-02-06 09:22:12 -06:00
|
|
|
*
|
|
|
|
* @return bool
|
2015-02-24 14:10:25 -06:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
private function storeMetadata(Account $account, array $data): bool
|
2016-02-12 08:01:32 -06:00
|
|
|
{
|
2016-02-10 15:09:24 -06:00
|
|
|
foreach ($this->validFields as $field) {
|
2016-01-15 12:37:09 -06:00
|
|
|
if (isset($data[$field])) {
|
2016-01-19 06:59:54 -06:00
|
|
|
$metaData = new AccountMeta(
|
|
|
|
[
|
|
|
|
'account_id' => $account->id,
|
|
|
|
'name' => $field,
|
|
|
|
'data' => $data[$field],
|
|
|
|
]
|
|
|
|
);
|
|
|
|
$metaData->save();
|
2015-03-02 04:42:27 -06:00
|
|
|
}
|
2016-01-19 06:59:54 -06:00
|
|
|
}
|
2016-02-06 09:22:12 -06:00
|
|
|
|
|
|
|
return true;
|
2015-02-24 14:10:25 -06:00
|
|
|
}
|
2015-03-02 13:05:28 -06:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Account $account
|
|
|
|
* @param TransactionJournal $journal
|
|
|
|
* @param array $data
|
|
|
|
*
|
|
|
|
* @return TransactionJournal
|
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
private function updateInitialBalance(Account $account, TransactionJournal $journal, array $data): TransactionJournal
|
2015-03-02 13:05:28 -06:00
|
|
|
{
|
|
|
|
$journal->date = $data['openingBalanceDate'];
|
2016-01-22 08:44:23 -06:00
|
|
|
$journal->save();
|
2016-02-04 01:53:15 -06:00
|
|
|
|
2015-03-02 13:05:28 -06:00
|
|
|
/** @var Transaction $transaction */
|
|
|
|
foreach ($journal->transactions()->get() as $transaction) {
|
|
|
|
if ($account->id == $transaction->account_id) {
|
|
|
|
$transaction->amount = $data['openingBalance'];
|
|
|
|
$transaction->save();
|
|
|
|
}
|
|
|
|
if ($account->id != $transaction->account_id) {
|
|
|
|
$transaction->amount = $data['openingBalance'] * -1;
|
|
|
|
$transaction->save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $journal;
|
|
|
|
}
|
2015-12-03 23:56:45 -06:00
|
|
|
|
|
|
|
/**
|
2016-01-19 06:59:54 -06:00
|
|
|
* @param Account $account
|
|
|
|
* @param array $data
|
2015-12-03 23:56:45 -06:00
|
|
|
*
|
2016-02-06 09:22:12 -06:00
|
|
|
* @return bool
|
2015-12-03 23:56:45 -06:00
|
|
|
*/
|
2016-02-06 09:22:12 -06:00
|
|
|
private function updateMetadata(Account $account, array $data): bool
|
2015-12-03 23:56:45 -06:00
|
|
|
{
|
2016-02-10 15:09:24 -06:00
|
|
|
foreach ($this->validFields as $field) {
|
2016-01-19 06:59:54 -06:00
|
|
|
$entry = $account->accountMeta()->where('name', $field)->first();
|
|
|
|
|
|
|
|
if (isset($data[$field])) {
|
|
|
|
// update if new data is present:
|
|
|
|
if (!is_null($entry)) {
|
|
|
|
$entry->data = $data[$field];
|
|
|
|
$entry->save();
|
|
|
|
} else {
|
|
|
|
$metaData = new AccountMeta(
|
|
|
|
[
|
|
|
|
'account_id' => $account->id,
|
|
|
|
'name' => $field,
|
|
|
|
'data' => $data[$field],
|
|
|
|
]
|
|
|
|
);
|
|
|
|
$metaData->save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-06 09:22:12 -06:00
|
|
|
return true;
|
|
|
|
|
2015-12-03 23:56:45 -06:00
|
|
|
}
|
2015-03-29 01:14:32 -05:00
|
|
|
}
|