mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-12-23 15:40:32 -06:00
More code for the split journal support.
This commit is contained in:
parent
e113736887
commit
495b80f5ef
@ -9,6 +9,7 @@
|
||||
|
||||
namespace FireflyIII\Crud\Split;
|
||||
|
||||
use FireflyIII\Events\TransactionStored;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
@ -132,6 +133,13 @@ class Journal implements JournalInterface
|
||||
$two->budgets()->save($budget);
|
||||
}
|
||||
|
||||
if ($transaction['piggy_bank_id'] > 0) {
|
||||
// add some extra meta information to the transaction data
|
||||
$transaction['transaction_journal_id'] = $journal->id;
|
||||
$transaction['date'] = $journal->date->format('Y-m-d');
|
||||
event(new TransactionStored($transaction));
|
||||
}
|
||||
|
||||
return new Collection([$one, $two]);
|
||||
|
||||
}
|
||||
|
46
app/Events/TransactionStored.php
Normal file
46
app/Events/TransactionStored.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* TransactionStored.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
/**
|
||||
* TransactionStored.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class TransactionJournalStored
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class TransactionStored extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public $transaction = [];
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param array $transaction
|
||||
*/
|
||||
public function __construct(array $transaction)
|
||||
{
|
||||
//
|
||||
$this->transaction = $transaction;
|
||||
}
|
||||
|
||||
}
|
@ -11,6 +11,7 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Export\Entry;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* To extend the exported object, in case of new features in Firefly III for example,
|
||||
@ -45,8 +46,21 @@ class Entry
|
||||
public $description;
|
||||
/** @var EntryAccount */
|
||||
public $destinationAccount;
|
||||
/** @var Collection */
|
||||
public $destinationAccounts;
|
||||
/** @var EntryAccount */
|
||||
public $sourceAccount;
|
||||
/** @var Collection */
|
||||
public $sourceAccounts;
|
||||
|
||||
/**
|
||||
* Entry constructor.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
$this->sourceAccounts = new Collection;
|
||||
$this->destinationAccounts = new Collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
@ -66,10 +80,18 @@ class Entry
|
||||
$entry->bill = new EntryBill($journal->bill);
|
||||
|
||||
$sources = TransactionJournal::sourceAccountList($journal);
|
||||
$entry->sourceAccount = new EntryAccount($sources->first());
|
||||
$destinations = TransactionJournal::destinationAccountList($journal);
|
||||
$entry->sourceAccount = new EntryAccount($sources->first());
|
||||
$entry->destinationAccount = new EntryAccount($destinations->first());
|
||||
|
||||
foreach ($sources as $source) {
|
||||
$entry->sourceAccounts->push(new EntryAccount($source));
|
||||
}
|
||||
|
||||
foreach ($destinations as $destination) {
|
||||
$entry->destinationAccounts->push(new EntryAccount($destination));
|
||||
}
|
||||
|
||||
return $entry;
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Export\Exporter;
|
||||
|
||||
use FireflyIII\Export\Entry\Entry;
|
||||
use FireflyIII\Export\Entry\EntryAccount;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use League\Csv\Writer;
|
||||
use SplFileObject;
|
||||
@ -61,19 +62,84 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
// all rows:
|
||||
$rows = [];
|
||||
|
||||
/*
|
||||
* Count the maximum number of sources and destinations
|
||||
* each entry has. May need to expand the number of export fields:
|
||||
*/
|
||||
$maxSourceAccounts = 1;
|
||||
$maxDestinationAccounts = 1;
|
||||
/** @var Entry $entry */
|
||||
foreach ($this->getEntries() as $entry) {
|
||||
$sources = $entry->sourceAccounts->count();
|
||||
$destinations = $entry->destinationAccounts->count();
|
||||
$maxSourceAccounts = max($maxSourceAccounts, $sources);
|
||||
$maxDestinationAccounts = max($maxDestinationAccounts, $destinations);
|
||||
}
|
||||
|
||||
// add header:
|
||||
$rows[] = array_keys(Entry::getFieldsAndTypes());
|
||||
$rows[] = array_keys($this->getFieldsAndTypes($maxSourceAccounts, $maxDestinationAccounts));
|
||||
|
||||
// then the rest:
|
||||
/** @var Entry $entry */
|
||||
foreach ($this->getEntries() as $entry) {
|
||||
// order is defined in Entry::getFieldsAndTypes.
|
||||
$rows[] = [
|
||||
$entry->description, $entry->amount, $entry->date, $entry->sourceAccount->accountId, $entry->sourceAccount->name, $entry->sourceAccount->iban,
|
||||
$entry->sourceAccount->type, $entry->sourceAccount->number, $entry->destinationAccount->accountId, $entry->destinationAccount->name,
|
||||
$entry->destinationAccount->iban, $entry->destinationAccount->type, $entry->destinationAccount->number, $entry->budget->budgetId,
|
||||
$entry->budget->name, $entry->category->categoryId, $entry->category->name, $entry->bill->billId, $entry->bill->name,
|
||||
];
|
||||
$current = [
|
||||
$entry->description,
|
||||
$entry->amount,
|
||||
$entry->date];
|
||||
for ($i = 0; $i < $maxSourceAccounts; $i++) {
|
||||
/** @var EntryAccount $source */
|
||||
$source = $entry->sourceAccounts->get($i);
|
||||
$currentId = '';
|
||||
$currentName = '';
|
||||
$currentIban = '';
|
||||
$currentType = '';
|
||||
$currentNumber = '';
|
||||
if ($source) {
|
||||
$currentId = $source->accountId;
|
||||
$currentName = $source->name;
|
||||
$currentIban = $source->iban;
|
||||
$currentType = $source->type;
|
||||
$currentNumber = $source->number;
|
||||
}
|
||||
$current[] = $currentId;
|
||||
$current[] = $currentName;
|
||||
$current[] = $currentIban;
|
||||
$current[] = $currentType;
|
||||
$current[] = $currentNumber;
|
||||
}
|
||||
unset($source);
|
||||
for ($i = 0; $i < $maxDestinationAccounts; $i++) {
|
||||
/** @var EntryAccount $destination */
|
||||
$destination = $entry->destinationAccounts->get($i);
|
||||
$currentId = '';
|
||||
$currentName = '';
|
||||
$currentIban = '';
|
||||
$currentType = '';
|
||||
$currentNumber = '';
|
||||
if ($destination) {
|
||||
$currentId = $destination->accountId;
|
||||
$currentName = $destination->name;
|
||||
$currentIban = $destination->iban;
|
||||
$currentType = $destination->type;
|
||||
$currentNumber = $destination->number;
|
||||
}
|
||||
$current[] = $currentId;
|
||||
$current[] = $currentName;
|
||||
$current[] = $currentIban;
|
||||
$current[] = $currentType;
|
||||
$current[] = $currentNumber;
|
||||
}
|
||||
unset($destination);
|
||||
|
||||
|
||||
$current[] = $entry->budget->budgetId;
|
||||
$current[] = $entry->budget->name;
|
||||
$current[] = $entry->category->categoryId;
|
||||
$current[] = $entry->category->name;
|
||||
$current[] = $entry->bill->billId;
|
||||
$current[] = $entry->bill->name;
|
||||
$rows[] = $current;
|
||||
|
||||
}
|
||||
$writer->insertAll($rows);
|
||||
@ -81,6 +147,43 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getFieldsAndTypes(int $sources, int $destinations): array
|
||||
{
|
||||
// key = field name (see top of class)
|
||||
// value = field type (see csv.php under 'roles')
|
||||
$array = [
|
||||
'description' => 'description',
|
||||
'amount' => 'amount',
|
||||
'date' => 'date-transaction',
|
||||
];
|
||||
for ($i = 0; $i < $sources; $i++) {
|
||||
$array['source_account_' . $i . '_id'] = 'account-id';
|
||||
$array['source_account_' . $i . '_name'] = 'account-name';
|
||||
$array['source_account_' . $i . '_iban'] = 'account-iban';
|
||||
$array['source_account_' . $i . '_type'] = '_ignore';
|
||||
$array['source_account_' . $i . '_number'] = 'account-number';
|
||||
}
|
||||
for ($i = 0; $i < $destinations; $i++) {
|
||||
$array['destination_account_' . $i . '_id'] = 'account-id';
|
||||
$array['destination_account_' . $i . '_name'] = 'account-name';
|
||||
$array['destination_account_' . $i . '_iban'] = 'account-iban';
|
||||
$array['destination_account_' . $i . '_type'] = '_ignore';
|
||||
$array['destination_account_' . $i . '_number'] = 'account-number';
|
||||
}
|
||||
|
||||
$array['budget_id'] = 'budget-id';
|
||||
$array['budget_name'] = 'budget-name';
|
||||
$array['category_id'] = 'category-id';
|
||||
$array['category_name'] = 'category-name';
|
||||
$array['bill_id'] = 'bill-id';
|
||||
$array['bill_name'] = 'bill-name';
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
private function tempFile()
|
||||
{
|
||||
$this->fileName = $this->job->key . '-records.csv';
|
||||
|
68
app/Handlers/Events/ConnectTransactionToPiggyBank.php
Normal file
68
app/Handlers/Events/ConnectTransactionToPiggyBank.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* ConnectTransactionToPiggyBank.php
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\TransactionJournalStored;
|
||||
use FireflyIII\Events\TransactionStored;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Class ConnectTransactionToPiggyBank
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class ConnectTransactionToPiggyBank
|
||||
{
|
||||
|
||||
/**
|
||||
* Connect a new transaction journal to any related piggy banks.
|
||||
*
|
||||
* @param TransactionStored $event
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle(TransactionStored $event): bool
|
||||
{
|
||||
echo '<pre>';
|
||||
/** @var PiggyBankRepositoryInterface $repository */
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$transaction = $event->transaction;
|
||||
$piggyBank = $repository->find($transaction['piggy_bank_id']);
|
||||
|
||||
// valid piggy:
|
||||
if (is_null($piggyBank->id)) {
|
||||
return true;
|
||||
}
|
||||
$amount = strval($transaction['amount']);
|
||||
// piggy bank account something with amount:
|
||||
if ($transaction['source_account_id'] == $piggyBank->account_id) {
|
||||
// if the source of this transaction is the same as the piggy bank,
|
||||
// the money is being removed from the piggy bank. So the
|
||||
// amount must be negative:
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
||||
$repetition = $piggyBank->currentRelevantRep();
|
||||
// add or remove the money from the piggy bank:
|
||||
$newAmount = bcadd(strval($repetition->currentamount), $amount);
|
||||
$repetition->currentamount = $newAmount;
|
||||
$repetition->save();
|
||||
|
||||
// now generate a piggy bank event:
|
||||
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'date' => $transaction['date'], 'amount' => $newAmount]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -53,11 +53,13 @@ class SplitController extends Controller
|
||||
$accountRepository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface');
|
||||
$currencyRepository = app('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface');
|
||||
$budgetRepository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
|
||||
$piggyRepository = app('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface');
|
||||
$assetAccounts = ExpandedForm::makeSelectList($accountRepository->getAccountsByType(['Default account', 'Asset account']));
|
||||
$sessionData = session('journal-data', []);
|
||||
$uploadSize = min(Steam::phpBytes(ini_get('upload_max_filesize')), Steam::phpBytes(ini_get('post_max_size')));
|
||||
$currencies = ExpandedForm::makeSelectList($currencyRepository->get());
|
||||
$budgets = ExpandedForm::makeSelectListWithEmpty($budgetRepository->getActiveBudgets());
|
||||
$piggyBanks = ExpandedForm::makeSelectListWithEmpty($piggyRepository->getPiggyBanksWithAmount());
|
||||
$subTitle = trans('form.add_new_' . $sessionData['what']);
|
||||
$subTitleIcon = 'fa-plus';
|
||||
$preFilled = [
|
||||
@ -74,7 +76,8 @@ class SplitController extends Controller
|
||||
];
|
||||
|
||||
return view(
|
||||
'split.journals.create', compact('journal', 'subTitle', 'subTitleIcon', 'preFilled', 'assetAccounts', 'currencies', 'budgets', 'uploadSize')
|
||||
'split.journals.create',
|
||||
compact('journal', 'piggyBanks', 'subTitle', 'subTitleIcon', 'preFilled', 'assetAccounts', 'currencies', 'budgets', 'uploadSize')
|
||||
);
|
||||
}
|
||||
|
||||
@ -125,7 +128,6 @@ class SplitController extends Controller
|
||||
public function store(JournalInterface $repository, SplitJournalFormRequest $request, TransactionJournal $journal)
|
||||
{
|
||||
$data = $request->getSplitData();
|
||||
|
||||
foreach ($data['transactions'] as $transaction) {
|
||||
$repository->storeTransaction($journal, $transaction);
|
||||
}
|
||||
@ -245,7 +247,7 @@ class SplitController extends Controller
|
||||
$destinationName = $request->old('destination_account_name')[$index] ?? $transaction->account->name;
|
||||
|
||||
// any transfer not from the source:
|
||||
if (($journal->isWithdrawal() || $journal->isDeposit()) && $transaction->account_id !== $sourceAccounts->first()->id) {
|
||||
if ($transaction->account_id !== $sourceAccounts->first()->id) {
|
||||
$array['description'][] = $description;
|
||||
$array['destination_account_id'][] = $transaction->account_id;
|
||||
$array['destination_account_name'][] = $destinationName;
|
||||
|
@ -59,6 +59,9 @@ class SplitJournalFormRequest extends Request
|
||||
'category' => $this->get('category')[$index] ?? '',
|
||||
'source_account_id' => intval($this->get('journal_source_account_id')),
|
||||
'source_account_name' => $this->get('journal_source_account_name'),
|
||||
'piggy_bank_id' => isset($this->get('piggy_bank_id')[$index])
|
||||
? intval($this->get('piggy_bank_id')[$index])
|
||||
: 0,
|
||||
'destination_account_id' => isset($this->get('destination_account_id')[$index])
|
||||
? intval($this->get('destination_account_id')[$index])
|
||||
: intval($this->get('journal_destination_account_id')),
|
||||
|
@ -30,12 +30,16 @@ class EventServiceProvider extends ServiceProvider
|
||||
'FireflyIII\Handlers\Events\FireRulesForUpdate',
|
||||
|
||||
],
|
||||
|
||||
'FireflyIII\Events\BudgetLimitStored' => [
|
||||
'FireflyIII\Handlers\Events\BudgetLimitEventHandler@store',
|
||||
],
|
||||
'FireflyIII\Events\BudgetLimitUpdated' => [
|
||||
'FireflyIII\Handlers\Events\BudgetLimitEventHandler@update',
|
||||
],
|
||||
'FireflyIII\Events\TransactionStored' => [
|
||||
'FireflyIII\Handlers\Events\ConnectTransactionToPiggyBank',
|
||||
],
|
||||
'FireflyIII\Events\TransactionJournalStored' => [
|
||||
'FireflyIII\Handlers\Events\ScanForBillsAfterStore',
|
||||
'FireflyIII\Handlers\Events\ConnectJournalToPiggyBank',
|
||||
|
@ -18,6 +18,7 @@ use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
@ -167,6 +168,18 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
|
||||
if ($accounts->count() > 0) {
|
||||
$ids = $accounts->pluck('id')->toArray();
|
||||
// join source and destination:
|
||||
$query->leftJoin(
|
||||
'transactions as source', function (JoinClause $join) {
|
||||
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')->where('source.amount', '<', 0);
|
||||
}
|
||||
);
|
||||
$query->leftJoin(
|
||||
'transactions as destination', function (JoinClause $join) {
|
||||
$join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')->where('destination.amount', '>', 0);
|
||||
}
|
||||
);
|
||||
|
||||
$query->where(
|
||||
function (Builder $q) use ($ids) {
|
||||
$q->whereIn('destination.account_id', $ids);
|
||||
|
@ -57,6 +57,21 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $piggyBankid
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public function find(int $piggyBankid): PiggyBank
|
||||
{
|
||||
$piggyBank = $this->user->piggyBanks()->where('piggy_banks.id', $piggyBankid)->first(['piggy_banks.*']);
|
||||
if (!is_null($piggyBank)) {
|
||||
return $piggyBank;
|
||||
}
|
||||
|
||||
return new PiggyBank();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
|
@ -34,6 +34,13 @@ interface PiggyBankRepositoryInterface
|
||||
*/
|
||||
public function destroy(PiggyBank $piggyBank): bool;
|
||||
|
||||
/**
|
||||
* @param int $piggyBankid
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public function find(int $piggyBankid): PiggyBank;
|
||||
|
||||
/**
|
||||
* Get all events.
|
||||
*
|
||||
|
@ -93,6 +93,9 @@
|
||||
<th>{{ trans('list.budget') }}</th>
|
||||
{% endif %}
|
||||
<th>{{ trans('list.category') }}</th>
|
||||
{% if preFilled.what == 'transfer' %}
|
||||
<th>{{ trans('list.piggy_bank') }}</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -139,6 +142,12 @@
|
||||
<td>
|
||||
<input type="text" name="category[]" value="{{ preFilled.category[index] }}" class="form-control"/>
|
||||
</td>
|
||||
{% if preFilled.what == 'transfer' %}
|
||||
<td>
|
||||
<!-- RELATE THIS TRANSFER TO A PIGGY BANK -->
|
||||
{{ Form.select('piggy_bank_id[]',piggyBanks, preFilled.piggy_bank_id[index], {class: 'form-control'}) }}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
301
storage/database/seed.split.json
Normal file
301
storage/database/seed.split.json
Normal file
@ -0,0 +1,301 @@
|
||||
{
|
||||
"users": [
|
||||
{
|
||||
"email": "thegrumpydictator@gmail.com",
|
||||
"password": "james"
|
||||
}
|
||||
],
|
||||
"roles": [
|
||||
{
|
||||
"user_id": 1,
|
||||
"role": 1
|
||||
}
|
||||
],
|
||||
"accounts": [
|
||||
{
|
||||
"user_id": 1,
|
||||
"account_type_id": 3,
|
||||
"name": "Checking Account",
|
||||
"iban": "NL11XOLA6707795988"
|
||||
},
|
||||
{
|
||||
"user_id": 1,
|
||||
"account_type_id": 3,
|
||||
"name": "Alternate",
|
||||
"iban": "NL40UKBK3619908726"
|
||||
},
|
||||
{
|
||||
"user_id": 1,
|
||||
"account_type_id": 4,
|
||||
"name": "SixtyFive"
|
||||
},
|
||||
{
|
||||
"user_id": 1,
|
||||
"account_type_id": 4,
|
||||
"name": "EightyFour"
|
||||
},
|
||||
{
|
||||
"user_id": 1,
|
||||
"account_type_id": 4,
|
||||
"name": "Fiftyone"
|
||||
},
|
||||
{
|
||||
"user_id": 1,
|
||||
"account_type_id": 5,
|
||||
"name": "Work SixtyFive"
|
||||
},
|
||||
{
|
||||
"user_id": 1,
|
||||
"account_type_id": 5,
|
||||
"name": "Work EightyFour"
|
||||
},
|
||||
{
|
||||
"user_id": 1,
|
||||
"account_type_id": 5,
|
||||
"name": "Work Fiftyone"
|
||||
}
|
||||
],
|
||||
"account-meta": [
|
||||
{
|
||||
"account_id": 1,
|
||||
"name": "accountRole",
|
||||
"data": "\"defaultAsset\""
|
||||
},
|
||||
{
|
||||
"account_id": 2,
|
||||
"name": "accountRole",
|
||||
"data": "\"defaultAsset\""
|
||||
}
|
||||
],
|
||||
"bills": [],
|
||||
"budgets": [
|
||||
{
|
||||
"name": "Groceries",
|
||||
"user_id": 1
|
||||
},
|
||||
{
|
||||
"name": "Bills",
|
||||
"user_id": 1
|
||||
},
|
||||
{
|
||||
"name": "Car",
|
||||
"user_id": 1
|
||||
}
|
||||
],
|
||||
"budget-limits": [],
|
||||
"monthly-limits": [
|
||||
{
|
||||
"budget_id": 1,
|
||||
"amount_min": 200,
|
||||
"amount_max": 200
|
||||
},
|
||||
{
|
||||
"budget_id": 2,
|
||||
"amount_min": 1000,
|
||||
"amount_max": 1000
|
||||
},
|
||||
{
|
||||
"budget_id": 3,
|
||||
"amount_min": 200,
|
||||
"amount_max": 200
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"name": "Daily groceries",
|
||||
"user_id": 1
|
||||
},
|
||||
{
|
||||
"name": "Car",
|
||||
"user_id": 1
|
||||
},
|
||||
{
|
||||
"name": "Reimbursements",
|
||||
"user_id": 1
|
||||
}
|
||||
],
|
||||
"piggy-banks": [
|
||||
{
|
||||
"account_id": 2,
|
||||
"name": "New camera",
|
||||
"targetamount": 1000,
|
||||
"startdate": "2015-04-01",
|
||||
"reminder_skip": 0,
|
||||
"remind_me": 0,
|
||||
"order": 1,
|
||||
"currentamount": 0
|
||||
},
|
||||
{
|
||||
"account_id": 2,
|
||||
"name": "New phone",
|
||||
"targetamount": 600,
|
||||
"startdate": "2015-04-01",
|
||||
"reminder_skip": 0,
|
||||
"remind_me": 0,
|
||||
"order": 2,
|
||||
"currentamount": 0
|
||||
},
|
||||
{
|
||||
"account_id": 2,
|
||||
"name": "New couch",
|
||||
"targetamount": 500,
|
||||
"startdate": "2015-04-01",
|
||||
"reminder_skip": 0,
|
||||
"remind_me": 0,
|
||||
"order": 3,
|
||||
"currentamount": 0
|
||||
}
|
||||
],
|
||||
"piggy-events": [],
|
||||
"rule-groups": [],
|
||||
"rules": [],
|
||||
"rule-triggers": [],
|
||||
"rule-actions": [],
|
||||
"tags": [],
|
||||
"monthly-deposits": [],
|
||||
"monthly-transfers": [],
|
||||
"monthly-withdrawals": [],
|
||||
"attachments": [],
|
||||
"multi-withdrawals": [
|
||||
{
|
||||
"user_id": 1,
|
||||
"date": "2016-03-12",
|
||||
"description": "Even multi-withdrawal (50, 50)",
|
||||
"destination_ids": [
|
||||
3,
|
||||
4
|
||||
],
|
||||
"source_id": 1,
|
||||
"amounts": [
|
||||
50,
|
||||
50
|
||||
],
|
||||
"category_ids": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"budget_ids": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"user_id": 1,
|
||||
"date": "2016-05-12",
|
||||
"description": "Uneven multi-withdrawal (15,34,51)",
|
||||
"destination_ids": [
|
||||
3,
|
||||
4,
|
||||
5
|
||||
],
|
||||
"source_id": 1,
|
||||
"amounts": [
|
||||
14,
|
||||
35,
|
||||
51
|
||||
],
|
||||
"category_ids": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"budget_ids": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
}
|
||||
],
|
||||
"multi-deposits": [
|
||||
{
|
||||
"user_id": 1,
|
||||
"date": "2016-03-02",
|
||||
"description": "Even multi-deposit (50, 50)",
|
||||
"source_ids": [
|
||||
6,
|
||||
7
|
||||
],
|
||||
"destination_id": 1,
|
||||
"amounts": [
|
||||
50,
|
||||
50
|
||||
],
|
||||
"category_ids": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"user_id": 1,
|
||||
"date": "2016-05-02",
|
||||
"description": "Uneven multi-deposit (15,34,51)",
|
||||
"source_ids": [
|
||||
6,
|
||||
7,
|
||||
8
|
||||
],
|
||||
"destination_id": 1,
|
||||
"amounts": [
|
||||
14,
|
||||
35,
|
||||
51
|
||||
],
|
||||
"category_ids": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
}
|
||||
],
|
||||
"multi-transfers": [
|
||||
{
|
||||
"user_id": 1,
|
||||
"date": "2016-01-18",
|
||||
"description": "Even multi-transfer (50, 50)",
|
||||
"source_ids": [
|
||||
1,
|
||||
1
|
||||
],
|
||||
"destination_ids": [
|
||||
2,
|
||||
2
|
||||
],
|
||||
"amounts": [
|
||||
50,
|
||||
50
|
||||
],
|
||||
"category_ids": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"user_id": 1,
|
||||
"date": "2016-03-28",
|
||||
"description": "Uneven multi-transfer (15,34,51)",
|
||||
"source_ids": [
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"destination_ids": [
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
"amounts": [
|
||||
14,
|
||||
35,
|
||||
51
|
||||
],
|
||||
"category_ids": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user