Some refactoring.

This commit is contained in:
James Cole 2016-05-14 13:51:33 +02:00
parent 5a6967cefd
commit 863227c55c
12 changed files with 240 additions and 260 deletions

View File

@ -2,7 +2,6 @@
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;
use Crypt;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
use stdClass;
@ -33,25 +32,32 @@ class Expense
*/
public function addOrCreateExpense(TransactionJournal $entry)
{
$accountId = $entry->account_id;
$amount = strval(round($entry->journalAmount, 2));
if (bccomp('0', $amount) === -1) {
$amount = bcmul($amount, '-1');
// add each account individually:
$destinations = TransactionJournal::destinationTransactionList($entry);
foreach ($destinations as $transaction) {
$amount = strval($transaction->amount);
$account = $transaction->account;
if (bccomp('0', $amount) === -1) {
$amount = bcmul($amount, '-1');
}
$object = new stdClass;
$object->amount = $amount;
$object->name = $account->name;
$object->count = 1;
$object->id = $account->id;
// overrule some properties:
if ($this->expenses->has($account->id)) {
$object = $this->expenses->get($account->id);
$object->amount = bcadd($object->amount, $amount);
$object->count++;
}
$this->expenses->put($account->id, $object);
}
$object = new stdClass;
$object->amount = $amount;
$object->name = Crypt::decrypt($entry->account_name);
$object->count = 1;
$object->id = $accountId;
// overrule some properties:
if ($this->expenses->has($accountId)) {
$object = $this->expenses->get($accountId);
$object->amount = bcadd($object->amount, $amount);
$object->count++;
}
$this->expenses->put($accountId, $object);
}
/**

View File

@ -2,7 +2,6 @@
declare(strict_types = 1);
namespace FireflyIII\Helpers\Collection;
use Crypt;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
use stdClass;
@ -34,21 +33,29 @@ class Income
*/
public function addOrCreateIncome(TransactionJournal $entry)
{
$accountId = $entry->account_id;
// add each account individually:
$sources = TransactionJournal::sourceTransactionList($entry);
$object = new stdClass;
$object->amount = strval(round($entry->journalAmount, 2));
$object->name = Crypt::decrypt($entry->account_name);
$object->count = 1;
$object->id = $accountId;
foreach ($sources as $transaction) {
$amount = strval($transaction->amount);
$account = $transaction->account;
$amount = bcmul($amount, '-1');
// overrule some properties:
if ($this->incomes->has($accountId)) {
$object = $this->incomes->get($accountId);
$object->amount = bcadd($object->amount, $entry->journalAmount);
$object->count++;
$object = new stdClass;
$object->amount = $amount;
$object->name = $account->name;
$object->count = 1;
$object->id = $account->id;
// overrule some properties:
if ($this->incomes->has($account->id)) {
$object = $this->incomes->get($account->id);
$object->amount = bcadd($object->amount, $amount);
$object->count++;
}
$this->incomes->put($account->id, $object);
}
$this->incomes->put($accountId, $object);
}
/**

View File

@ -14,6 +14,8 @@ use FireflyIII\Models\Bill;
use FireflyIII\Models\Category;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
@ -171,10 +173,15 @@ class ReportHelper implements ReportHelperInterface
public function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): Expense
{
$object = new Expense;
$set = $this->query->expense($accounts, $start, $end);
/** @var AccountRepositoryInterface $repos */
$repos = app(AccountRepositoryInterface::class);
$types = [TransactionType::WITHDRAWAL, TransactionType::TRANSFER];
$journals = $repos->journalsInPeriod($accounts, $types, $start, $end);
foreach ($set as $entry) {
$object->addToTotal($entry->journalAmount); // can be positive, if it's a transfer
/** @var TransactionJournal $entry */
foreach ($journals as $entry) {
$amount = TransactionJournal::amount($entry);
$object->addToTotal($amount);
$object->addOrCreateExpense($entry);
}
@ -193,10 +200,14 @@ class ReportHelper implements ReportHelperInterface
public function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts): Income
{
$object = new Income;
$set = $this->query->income($accounts, $start, $end);
/** @var AccountRepositoryInterface $repos */
$repos = app(AccountRepositoryInterface::class);
$types = [TransactionType::DEPOSIT, TransactionType::TRANSFER];
$journals = $repos->journalsInPeriod($accounts, $types, $start, $end);
foreach ($set as $entry) {
$object->addToTotal($entry->journalAmount);
foreach ($journals as $entry) {
$amount = TransactionJournal::amount($entry);
$object->addToTotal($amount);
$object->addOrCreateIncome($entry);
}

View File

@ -62,76 +62,6 @@ class ReportQuery implements ReportQueryInterface
return $array;
}
/**
* This method returns all the "out" transaction journals for the given account and given period. The amount
* is stored in "journalAmount".
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function expense(Collection $accounts, Carbon $start, Carbon $end): Collection
{
$ids = $accounts->pluck('id')->toArray();
$set = Auth::user()->transactionjournals()
->leftJoin(
'transactions as t_from', function (JoinClause $join) {
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
}
)
->leftJoin(
'transactions as t_to', function (JoinClause $join) {
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('accounts', 't_to.account_id', '=', 'accounts.id')
->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
->before($end)
->after($start)
->whereIn('t_from.account_id', $ids)
->whereNotIn('t_to.account_id', $ids)
->get(['transaction_journals.*', 't_from.amount as journalAmount', 'accounts.id as account_id', 'accounts.name as account_name']);
return $set;
}
/**
* This method returns all the "in" transaction journals for the given account and given period. The amount
* is stored in "journalAmount".
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function income(Collection $accounts, Carbon $start, Carbon $end): Collection
{
$ids = $accounts->pluck('id')->toArray();
$set = Auth::user()->transactionjournals()
->leftJoin(
'transactions as t_from', function (JoinClause $join) {
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
}
)
->leftJoin(
'transactions as t_to', function (JoinClause $join) {
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
}
)
->leftJoin('accounts', 't_from.account_id', '=', 'accounts.id')
->transactionTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
->before($end)
->after($start)
->whereIn('t_to.account_id', $ids)
->whereNotIn('t_from.account_id', $ids)
->get(['transaction_journals.*', 't_to.amount as journalAmount', 'accounts.id as account_id', 'accounts.name as account_name']);
return $set;
}
/**
* Returns an array of the amount of money spent in the given accounts (on withdrawals, opening balances and transfers)
* grouped by month like so: "2015-01" => '123.45'

View File

@ -26,30 +26,6 @@ interface ReportQueryInterface
*/
public function earnedPerMonth(Collection $accounts, Carbon $start, Carbon $end): array;
/**
* This method returns all the "out" transaction journals for the given account and given period. The amount
* is stored in "journalAmount".
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function expense(Collection $accounts, Carbon $start, Carbon $end): Collection;
/**
* This method returns all the "in" transaction journals for the given account and given period. The amount
* is stored in "journalAmount".
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function income(Collection $accounts, Carbon $start, Carbon $end): Collection;
/**
* Returns an array of the amount of money spent in the given accounts (on withdrawals, opening balances and transfers)
* grouped by month like so: "2015-01" => '123.45'

View File

@ -3,7 +3,6 @@
use Amount;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI;
@ -84,13 +83,11 @@ class JsonController extends Controller
}
/**
* @param ReportQueryInterface $reportQuery
*
* @param ARI $accountRepository
* @param ARI $accountRepository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function boxIn(ReportQueryInterface $reportQuery, ARI $accountRepository)
public function boxIn(ARI $accountRepository)
{
$start = session('start', Carbon::now()->startOfMonth());
$end = session('end', Carbon::now()->endOfMonth());
@ -104,28 +101,23 @@ class JsonController extends Controller
return Response::json($cache->get());
}
$accounts = $accountRepository->getAccountsByType(['Default account', 'Asset account', 'Cash account']);
$amount = $reportQuery->income($accounts, $start, $end)->sum('journalAmount');
$data = ['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
$amount = $accountRepository->earnedInPeriod($accounts, $start, $end);
$data = ['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
$cache->store($data);
return Response::json($data);
}
/**
* @param ReportQueryInterface $reportQuery
*
* @param ARI $accountRepository
* @param ARI $accountRepository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function boxOut(ReportQueryInterface $reportQuery, ARI $accountRepository)
public function boxOut(ARI $accountRepository)
{
$start = session('start', Carbon::now()->startOfMonth());
$end = session('end', Carbon::now()->endOfMonth());
$accounts = $accountRepository->getAccountsByType(['Default account', 'Asset account', 'Cash account']);
// works for json too!
$cache = new CacheProperties;
$cache->addProperty($start);
@ -135,7 +127,8 @@ class JsonController extends Controller
return Response::json($cache->get());
}
$amount = $reportQuery->expense($accounts, $start, $end)->sum('journalAmount');
$accounts = $accountRepository->getAccountsByType(['Default account', 'Asset account', 'Cash account']);
$amount = $accountRepository->spentInPeriod($accounts, $start, $end);
$data = ['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount];
$cache->store($data);

View File

@ -16,6 +16,7 @@ use DB;
use ExpandedForm;
use FireflyIII\Events\TransactionJournalStored;
use FireflyIII\Events\TransactionJournalUpdated;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Requests\JournalFormRequest;
use FireflyIII\Http\Requests\MassDeleteJournalRequest;
@ -420,11 +421,46 @@ class TransactionController extends Controller
}
);
// TODO different for each transaction type!
/** @var Collection $transactions */
$transactions = $journal->transactions()->groupBy('transactions.account_id')->orderBy('amount', 'ASC')->get(
['transactions.*', DB::raw('SUM(`transactions`.`amount`) as `sum`')]
);
switch ($journal->transactionType->type) {
case TransactionType::DEPOSIT:
/** @var Collection $transactions */
$transactions = $journal->transactions()
->groupBy('transactions.account_id')
->where('amount', '<', 0)
->orderBy('amount', 'ASC')->get(
['transactions.*', DB::raw('SUM(`transactions`.`amount`) as `sum`')]
);
$final = $journal->transactions()
->groupBy('transactions.account_id')
->where('amount', '>', 0)
->orderBy('amount', 'ASC')->first(
['transactions.*', DB::raw('SUM(`transactions`.`amount`) as `sum`')]
);
$final->description = '';
$transactions->push($final);
break;
case TransactionType::WITHDRAWAL:
/** @var Collection $transactions */
$transactions = $journal->transactions()
->groupBy('transactions.account_id')
->where('amount', '>', 0)
->orderBy('amount', 'ASC')->get(
['transactions.*', DB::raw('SUM(`transactions`.`amount`) as `sum`')]
);
$final = $journal->transactions()
->groupBy('transactions.account_id')
->where('amount', '<', 0)
->orderBy('amount', 'ASC')->first(
['transactions.*', DB::raw('SUM(`transactions`.`amount`) as `sum`')]
);
$final->description = '';
$transactions->push($final);
break;
default:
throw new FireflyException('Cannot handle ' . $journal->transactionType->type);
break;
}
// foreach do balance thing
$transactions->each(

View File

@ -316,6 +316,8 @@ class TestData
{
Category::firstOrCreateEncrypted(['name' => 'Groceries', 'user_id' => $user->id]);
Category::firstOrCreateEncrypted(['name' => 'Car', 'user_id' => $user->id]);
Category::firstOrCreateEncrypted(['name' => 'Reimbursements', 'user_id' => $user->id]);
Category::firstOrCreateEncrypted(['name' => 'Salary', 'user_id' => $user->id]);
return true;
}
@ -690,7 +692,7 @@ class TestData
*/
public static function createRevenueAccounts(User $user): bool
{
$revenues = ['Job', 'Belastingdienst', 'Bank', 'KPN', 'Google'];
$revenues = ['Job', 'Belastingdienst', 'Bank', 'KPN', 'Google', 'Work SixtyFive', 'Work EightyFour','Work Fiftyone'];
foreach ($revenues as $name) {
// create account:
Account::create(

View File

@ -279,7 +279,6 @@ class TransactionJournalSupport extends Model
return $account;
}
/**
* @param TransactionJournal $journal
*
@ -327,6 +326,46 @@ class TransactionJournalSupport extends Model
return $type;
}
/**
* @param TransactionJournal $journal
*
* @return Collection
*/
public static function sourceTransactionList(TransactionJournal $journal): Collection
{
$cache = new CacheProperties;
$cache->addProperty($journal->id);
$cache->addProperty('transaction-journal');
$cache->addProperty('source-transaction-list');
if ($cache->has()) {
return $cache->get();
}
$list = $journal->transactions()->where('amount', '<', 0)->with('account')->get();
$cache->store($list);
return $list;
}
/**
* @param TransactionJournal $journal
*
* @return Collection
*/
public static function destinationTransactionList(TransactionJournal $journal): Collection
{
$cache = new CacheProperties;
$cache->addProperty($journal->id);
$cache->addProperty('transaction-journal');
$cache->addProperty('destination-transaction-list');
if ($cache->has()) {
return $cache->get();
}
$list = $journal->transactions()->where('amount', '>', 0)->with('account')->get();
$cache->store($list);
return $list;
}
/**
* @param TransactionJournal $journal
*

View File

@ -43,7 +43,7 @@ class SplitDataSeeder extends Seeder
public function run()
{
$skipWithdrawal = false;
$skipDeposit = true;
$skipDeposit = false;
$skipTransfer = true;
// start by creating all users:
// method will return the first user.
@ -80,7 +80,7 @@ class SplitDataSeeder extends Seeder
$today->addDay();
if (!$skipDeposit) {
$this->generateDeposits();
$this->generateDeposits($user);
}
// create a splitted transfer of 57,- (19)
// $today->addDay();
@ -90,51 +90,66 @@ class SplitDataSeeder extends Seeder
}
}
private function generateDeposits()
/**
* @param User $user
*/
private function generateDeposits(User $user)
{
$journal = TransactionJournal::create(
[
'user_id' => $user->id,
'transaction_type_id' => 2, // expense
'transaction_currency_id' => 1,
'description' => 'Split Income (journal)',
'completed' => 1,
'date' => $today->format('Y-m-d'),
]
/*
* DEPOSIT ONE
*/
$sources = ['Work SixtyFive', 'Work EightyFour'];
$categories = ['Salary', 'Reimbursements'];
$amounts = [50, 50];
$destination = TestData::findAccount($user, 'Alternate Checking Account');
$date = new Carbon('2012-03-15');
$journal = TransactionJournal::create(
['user_id' => $user->id, 'transaction_type_id' => 2, 'transaction_currency_id' => 1, 'description' => 'Split Even Income (journal (50/50))',
'completed' => 1, 'date' => $date->format('Y-m-d'),]
);
// split in 6 transactions (multiple destinations). 22,- each
// source is TestData Checking Account.
// also attach some budgets and stuff.
$destinations = ['Checking Account', 'Savings Account', 'Shared Checking Account'];
$source = TestData::findAccount($user, 'Belastingdienst');
$budgets = ['Groceries', 'Groceries', 'Car'];
$categories = ['Bills', 'Bills', 'Car'];
foreach ($destinations as $index => $dest) {
$bud = $budgets[$index];
$cat = $categories[$index];
$destination = TestData::findAccount($user, $dest);
$one = Transaction::create(
[
'account_id' => $source->id,
'transaction_journal_id' => $journal->id,
'amount' => '-33',
]
foreach ($sources as $index => $source) {
$cat = $categories[$index];
$source = TestData::findAccount($user, $source);
$one = Transaction::create(
['account_id' => $source->id, 'transaction_journal_id' => $journal->id, 'amount' => $amounts[$index] * -1,
'description' => 'Split Even Income #' . $index,]
);
$two = Transaction::create(
['account_id' => $destination->id, 'transaction_journal_id' => $journal->id, 'amount' => $amounts[$index],
'description' => 'Split Even Income #' . $index,]
);
$two = Transaction::create(
[
'account_id' => $destination->id,
'transaction_journal_id' => $journal->id,
'amount' => '33',
$one->categories()->save(TestData::findCategory($user, $cat));
$two->categories()->save(TestData::findCategory($user, $cat));
}
]
/*
* DEPOSIT TWO.
*/
$sources = ['Work SixtyFive', 'Work EightyFour', 'Work Fiftyone'];
$categories = ['Salary', 'Bills', 'Reimbursements'];
$amounts = [15, 34, 51];
$destination = TestData::findAccount($user, 'Checking Account');
$date = new Carbon;
$journal = TransactionJournal::create(
['user_id' => $user->id, 'transaction_type_id' => 2, 'transaction_currency_id' => 1,
'description' => 'Split Uneven Income (journal (15/34/51=100))', 'completed' => 1, 'date' => $date->format('Y-m-d'),]
);
foreach ($sources as $index => $source) {
$cat = $categories[$index];
$source = TestData::findAccount($user, $source);
$one = Transaction::create(
['account_id' => $source->id, 'transaction_journal_id' => $journal->id, 'amount' => $amounts[$index] * -1,
'description' => 'Split Uneven Income #' . $index,]
);
$two = Transaction::create(
['account_id' => $destination->id, 'transaction_journal_id' => $journal->id, 'amount' => $amounts[$index],
'description' => 'Split Uneven Income #' . $index,]
);
$one->budgets()->save(TestData::findBudget($user, $bud));
$two->budgets()->save(TestData::findBudget($user, $bud));
$one->categories()->save(TestData::findCategory($user, $cat));
$two->categories()->save(TestData::findCategory($user, $cat));
@ -190,114 +205,75 @@ class SplitDataSeeder extends Seeder
}
}
/**
* @param User $user
*/
private function generateWithdrawals(User $user)
{
/*
* TRANSACTION ONE
*/
$date = new Carbon('2012-03-15');
$journal = TransactionJournal::create(
[
'user_id' => $user->id,
'transaction_type_id' => 1, // withdrawal
'transaction_currency_id' => 1,
'description' => 'Split Even Expense (journal (50/50))',
'completed' => 1,
'date' => $date->format('Y-m-d'),
]
);
// split in 6 transactions (multiple destinations). 22,- each
// source is TestData Checking Account.
// also attach some budgets and stuff.
$destinations = ['SixtyFive', 'EightyFour'];
$budgets = ['Groceries', 'Car'];
$categories = ['Bills', 'Bills'];
$amounts = [50, 50];
$source = TestData::findAccount($user, 'Alternate Checking Account');
$date = new Carbon('2012-03-15');
$journal = TransactionJournal::create(
['user_id' => $user->id, 'transaction_type_id' => 1, 'transaction_currency_id' => 1, 'description' => 'Split Even Expense (journal (50/50))',
'completed' => 1, 'date' => $date->format('Y-m-d'),]
);
foreach ($destinations as $index => $dest) {
$bud = $budgets[$index];
$cat = $categories[$index];
$destination = TestData::findAccount($user, $dest);
$one = Transaction::create(
[
'account_id' => $source->id,
'transaction_journal_id' => $journal->id,
'amount' => $amounts[$index] * -1,
'description' => 'Split Even Expense #' . $index,
]
$one = Transaction::create(
['account_id' => $source->id, 'transaction_journal_id' => $journal->id, 'amount' => $amounts[$index] * -1,
'description' => 'Split Even Expense #' . $index,]
);
$two = Transaction::create(
[
'account_id' => $destination->id,
'transaction_journal_id' => $journal->id,
'amount' => $amounts[$index],
'description' => 'Split Even Expense #' . $index,
]
$two = Transaction::create(
['account_id' => $destination->id, 'transaction_journal_id' => $journal->id, 'amount' => $amounts[$index],
'description' => 'Split Even Expense #' . $index,]
);
$one->budgets()->save(TestData::findBudget($user, $bud));
$two->budgets()->save(TestData::findBudget($user, $bud));
$one->categories()->save(TestData::findCategory($user, $cat));
$two->categories()->save(TestData::findCategory($user, $cat));
}
/*
* GENERATE TRANSACTION TWO.
* TRANSACTION TWO.
*/
$date = new Carbon;
$journal = TransactionJournal::create(
[
'user_id' => $user->id,
'transaction_type_id' => 1, // withdrawal
'transaction_currency_id' => 1,
'description' => 'Split Uneven Expense (journal (15/34/51=100))',
'completed' => 1,
'date' => $date->format('Y-m-d'),
]
);
// split in 6 transactions (multiple destinations). 22,- each
// source is TestData Checking Account.
// also attach some budgets and stuff.
$destinations = ['SixtyFive', 'EightyFour', 'Fiftyone'];
$budgets = ['Groceries', 'Groceries', 'Car'];
$categories = ['Bills', 'Bills', 'Car'];
$amounts = [15, 34, 51];
$source = TestData::findAccount($user, 'Checking Account');
$date = new Carbon;
$journal = TransactionJournal::create(
['user_id' => $user->id, 'transaction_type_id' => 1, 'transaction_currency_id' => 1,
'description' => 'Split Uneven Expense (journal (15/34/51=100))', 'completed' => 1, 'date' => $date->format('Y-m-d'),]
);
foreach ($destinations as $index => $dest) {
$bud = $budgets[$index];
$cat = $categories[$index];
$destination = TestData::findAccount($user, $dest);
$one = Transaction::create(
[
'account_id' => $source->id,
'transaction_journal_id' => $journal->id,
'amount' => $amounts[$index] * -1,
'description' => 'Split Uneven Expense #' . $index,
]
$one = Transaction::create(
['account_id' => $source->id, 'transaction_journal_id' => $journal->id, 'amount' => $amounts[$index] * -1,
'description' => 'Split Uneven Expense #' . $index,]
);
$two = Transaction::create(
[
'account_id' => $destination->id,
'transaction_journal_id' => $journal->id,
'amount' => $amounts[$index],
'description' => 'Split Uneven Expense #' . $index,
]
$two = Transaction::create(
['account_id' => $destination->id, 'transaction_journal_id' => $journal->id, 'amount' => $amounts[$index],
'description' => 'Split Uneven Expense #' . $index,]
);
$one->budgets()->save(TestData::findBudget($user, $bud));
$two->budgets()->save(TestData::findBudget($user, $bud));
$one->categories()->save(TestData::findCategory($user, $cat));
$two->categories()->save(TestData::findCategory($user, $cat));
}

View File

@ -21,7 +21,9 @@
</small>
{% endif %}
</td>
<td>{{ (expense.amount)|formatAmount }}</td>
<td>
{{ (expense.amount)|formatAmount }}
</td>
</tr>
{% endfor %}
</tbody>

View File

@ -1,2 +1,4 @@
*
!.gitignore
!seed.local.json
!seed.split.json