mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-25 06:51:08 +00:00
Display for bills.
This commit is contained in:
@@ -109,8 +109,9 @@ class BillController extends Controller
|
|||||||
$cache = new CacheProperties();
|
$cache = new CacheProperties();
|
||||||
$cache->addProperty('chart.bill.single');
|
$cache->addProperty('chart.bill.single');
|
||||||
$cache->addProperty($bill->id);
|
$cache->addProperty($bill->id);
|
||||||
|
$cache->addProperty($this->convertToNative);
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return response()->json($cache->get());
|
// return response()->json($cache->get());
|
||||||
}
|
}
|
||||||
$locale = app('steam')->getLocale();
|
$locale = app('steam')->getLocale();
|
||||||
|
|
||||||
@@ -132,42 +133,55 @@ class BillController extends Controller
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
$currency = $bill->transactionCurrency;
|
||||||
|
if($this->convertToNative) {
|
||||||
|
$currency = $this->defaultCurrency;
|
||||||
|
}
|
||||||
|
|
||||||
$chartData = [
|
$chartData = [
|
||||||
[
|
[
|
||||||
'type' => 'line',
|
'type' => 'line',
|
||||||
'label' => (string) trans('firefly.min-amount'),
|
'label' => (string) trans('firefly.min-amount'),
|
||||||
'currency_symbol' => $bill->transactionCurrency->symbol,
|
'currency_symbol' => $currency->symbol,
|
||||||
'currency_code' => $bill->transactionCurrency->code,
|
'currency_code' => $currency->code,
|
||||||
'entries' => [],
|
'entries' => [],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'type' => 'line',
|
'type' => 'line',
|
||||||
'label' => (string) trans('firefly.max-amount'),
|
'label' => (string) trans('firefly.max-amount'),
|
||||||
'currency_symbol' => $bill->transactionCurrency->symbol,
|
'currency_symbol' => $currency->symbol,
|
||||||
'currency_code' => $bill->transactionCurrency->code,
|
'currency_code' => $currency->code,
|
||||||
'entries' => [],
|
'entries' => [],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'type' => 'bar',
|
'type' => 'bar',
|
||||||
'label' => (string) trans('firefly.journal-amount'),
|
'label' => (string) trans('firefly.journal-amount'),
|
||||||
'currency_symbol' => $bill->transactionCurrency->symbol,
|
'currency_symbol' => $currency->symbol,
|
||||||
'currency_code' => $bill->transactionCurrency->code,
|
'currency_code' => $currency->code,
|
||||||
'entries' => [],
|
'entries' => [],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
$currencyId = $bill->transaction_currency_id;
|
$currencyId = $bill->transaction_currency_id;
|
||||||
|
$amountMin = $bill->amount_min;
|
||||||
|
$amountMax = $bill->amount_max;
|
||||||
|
if($this->convertToNative) {
|
||||||
|
$amountMin = $bill->native_amount_min;
|
||||||
|
$amountMax = $bill->native_amount_max;
|
||||||
|
}
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
$date = $journal['date']->isoFormat((string) trans('config.month_and_day_js', [], $locale));
|
$date = $journal['date']->isoFormat((string) trans('config.month_and_day_js', [], $locale));
|
||||||
$chartData[0]['entries'][$date] = $bill->amount_min; // minimum amount of bill
|
$chartData[0]['entries'][$date] = $amountMin; // minimum amount of bill
|
||||||
$chartData[1]['entries'][$date] = $bill->amount_max; // maximum amount of bill
|
$chartData[1]['entries'][$date] = $amountMax; // maximum amount of bill
|
||||||
|
|
||||||
// append amount because there are more than one per moment:
|
// append amount because there are more than one per moment:
|
||||||
if (!array_key_exists($date, $chartData[2]['entries'])) {
|
if (!array_key_exists($date, $chartData[2]['entries'])) {
|
||||||
$chartData[2]['entries'][$date] = '0';
|
$chartData[2]['entries'][$date] = '0';
|
||||||
}
|
}
|
||||||
$amount = bcmul($journal['amount'], '-1');
|
$amount = bcmul($journal['amount'], '-1');
|
||||||
if ($currencyId === $journal['foreign_currency_id']) {
|
if($this->convertToNative) {
|
||||||
|
$amount = bcmul($journal['native_amount'], '-1');
|
||||||
|
}
|
||||||
|
if($this->convertToNative && $currencyId === $journal['foreign_currency_id']) {
|
||||||
$amount = bcmul($journal['foreign_amount'], '-1');
|
$amount = bcmul($journal['foreign_amount'], '-1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,6 +59,8 @@ class Transaction extends Model
|
|||||||
'date' => 'datetime',
|
'date' => 'datetime',
|
||||||
'amount' => 'string',
|
'amount' => 'string',
|
||||||
'foreign_amount' => 'string',
|
'foreign_amount' => 'string',
|
||||||
|
'native_amount' => 'string',
|
||||||
|
'native_foreign_amount' => 'string',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $fillable
|
protected $fillable
|
||||||
|
@@ -61,8 +61,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
$search->whereLike('name', sprintf('%%%s', $query));
|
$search->whereLike('name', sprintf('%%%s', $query));
|
||||||
}
|
}
|
||||||
$search->orderBy('name', 'ASC')
|
$search->orderBy('name', 'ASC')
|
||||||
->where('active', true)
|
->where('active', true);
|
||||||
;
|
|
||||||
|
|
||||||
return $search->take($limit)->get();
|
return $search->take($limit)->get();
|
||||||
}
|
}
|
||||||
@@ -74,8 +73,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
$search->whereLike('name', sprintf('%s%%', $query));
|
$search->whereLike('name', sprintf('%s%%', $query));
|
||||||
}
|
}
|
||||||
$search->orderBy('name', 'ASC')
|
$search->orderBy('name', 'ASC')
|
||||||
->where('active', true)
|
->where('active', true);
|
||||||
;
|
|
||||||
|
|
||||||
return $search->take($limit)->get();
|
return $search->take($limit)->get();
|
||||||
}
|
}
|
||||||
@@ -179,8 +177,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
return $this->user->bills()
|
return $this->user->bills()
|
||||||
->orderBy('order', 'ASC')
|
->orderBy('order', 'ASC')
|
||||||
->orderBy('active', 'DESC')
|
->orderBy('active', 'DESC')
|
||||||
->orderBy('name', 'ASC')->get()
|
->orderBy('name', 'ASC')->get();
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBillsForAccounts(Collection $accounts): Collection
|
public function getBillsForAccounts(Collection $accounts): Collection
|
||||||
@@ -221,8 +218,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
->orderBy('bills.active', 'DESC')
|
->orderBy('bills.active', 'DESC')
|
||||||
->orderBy('bills.name', 'ASC')
|
->orderBy('bills.name', 'ASC')
|
||||||
->groupBy($fields)
|
->groupBy($fields)
|
||||||
->get($fields)
|
->get($fields);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -262,14 +258,20 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
$currency = $journal->transactionCurrency;
|
$currency = $journal->transactionCurrency;
|
||||||
$result[$currencyId] ??= [
|
$result[$currencyId] ??= [
|
||||||
'sum' => '0',
|
'sum' => '0',
|
||||||
|
'native_sum' => '0',
|
||||||
'count' => 0,
|
'count' => 0,
|
||||||
'avg' => '0',
|
'avg' => '0',
|
||||||
|
'native_avg' => '0',
|
||||||
'currency_id' => $currency->id,
|
'currency_id' => $currency->id,
|
||||||
'currency_code' => $currency->code,
|
'currency_code' => $currency->code,
|
||||||
'currency_symbol' => $currency->symbol,
|
'currency_symbol' => $currency->symbol,
|
||||||
'currency_decimal_places' => $currency->decimal_places,
|
'currency_decimal_places' => $currency->decimal_places,
|
||||||
];
|
];
|
||||||
$result[$currencyId]['sum'] = bcadd($result[$currencyId]['sum'], $transaction->amount);
|
$result[$currencyId]['sum'] = bcadd($result[$currencyId]['sum'], $transaction->amount);
|
||||||
|
$result[$currencyId]['native_sum'] = bcadd($result[$currencyId]['native_sum'], $transaction->native_amount);
|
||||||
|
if ($journal->foreign_currency_id === Amount::getDefaultCurrency()->id) {
|
||||||
|
$result[$currencyId]['native_sum'] = bcadd($result[$currencyId]['native_sum'], $transaction->amount);
|
||||||
|
}
|
||||||
++$result[$currencyId]['count'];
|
++$result[$currencyId]['count'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,12 +282,13 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
foreach ($result as $currencyId => $arr) {
|
foreach ($result as $currencyId => $arr) {
|
||||||
$result[$currencyId]['avg'] = bcdiv($arr['sum'], (string) $arr['count']);
|
$result[$currencyId]['avg'] = bcdiv($arr['sum'], (string) $arr['count']);
|
||||||
|
$result[$currencyId]['native_avg'] = bcdiv($arr['native_sum'], (string) $arr['count']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUser(null|Authenticatable|User $user): void
|
public function setUser(null | Authenticatable | User $user): void
|
||||||
{
|
{
|
||||||
if ($user instanceof User) {
|
if ($user instanceof User) {
|
||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
@@ -296,8 +299,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
{
|
{
|
||||||
return $this->user->bills()
|
return $this->user->bills()
|
||||||
->orderBy('active', 'DESC')
|
->orderBy('active', 'DESC')
|
||||||
->orderBy('name', 'ASC')->paginate($size)
|
->orderBy('name', 'ASC')->paginate($size);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -316,8 +318,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
'transaction_journals.date',
|
'transaction_journals.date',
|
||||||
'transaction_journals.transaction_group_id',
|
'transaction_journals.transaction_group_id',
|
||||||
]
|
]
|
||||||
)
|
);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -329,8 +330,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id')
|
->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id')
|
||||||
->where('rule_actions.action_type', 'link_to_bill')
|
->where('rule_actions.action_type', 'link_to_bill')
|
||||||
->where('rule_actions.action_value', $bill->name)
|
->where('rule_actions.action_value', $bill->name)
|
||||||
->get(['rules.*'])
|
->get(['rules.*']);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -344,8 +344,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
$rules = $this->user->rules()
|
$rules = $this->user->rules()
|
||||||
->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id')
|
->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id')
|
||||||
->where('rule_actions.action_type', 'link_to_bill')
|
->where('rule_actions.action_type', 'link_to_bill')
|
||||||
->get(['rules.id', 'rules.title', 'rule_actions.action_value', 'rules.active'])
|
->get(['rules.id', 'rules.title', 'rule_actions.action_value', 'rules.active']);
|
||||||
;
|
|
||||||
$array = [];
|
$array = [];
|
||||||
|
|
||||||
/** @var Rule $rule */
|
/** @var Rule $rule */
|
||||||
@@ -371,10 +370,9 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
$result = [];
|
$result = [];
|
||||||
|
|
||||||
$journals = $bill->transactionJournals()
|
$journals = $bill->transactionJournals()
|
||||||
->where('date', '>=', $date->year.'-01-01 00:00:00')
|
->where('date', '>=', $date->year . '-01-01 00:00:00')
|
||||||
->where('date', '<=', $date->year.'-12-31 23:59:59')
|
->where('date', '<=', $date->year . '-12-31 23:59:59')
|
||||||
->get()
|
->get();
|
||||||
;
|
|
||||||
|
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
@@ -387,6 +385,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
$currency = $journal->transactionCurrency;
|
$currency = $journal->transactionCurrency;
|
||||||
$result[$currencyId] ??= [
|
$result[$currencyId] ??= [
|
||||||
'sum' => '0',
|
'sum' => '0',
|
||||||
|
'native_sum' => '0',
|
||||||
'count' => 0,
|
'count' => 0,
|
||||||
'avg' => '0',
|
'avg' => '0',
|
||||||
'currency_id' => $currency->id,
|
'currency_id' => $currency->id,
|
||||||
@@ -395,6 +394,10 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
'currency_decimal_places' => $currency->decimal_places,
|
'currency_decimal_places' => $currency->decimal_places,
|
||||||
];
|
];
|
||||||
$result[$currencyId]['sum'] = bcadd($result[$currencyId]['sum'], $transaction->amount);
|
$result[$currencyId]['sum'] = bcadd($result[$currencyId]['sum'], $transaction->amount);
|
||||||
|
$result[$currencyId]['native_sum'] = bcadd($result[$currencyId]['native_sum'], $transaction->native_amount);
|
||||||
|
if ($journal->foreign_currency_id === Amount::getDefaultCurrency()->id) {
|
||||||
|
$result[$currencyId]['native_sum'] = bcadd($result[$currencyId]['native_sum'], $transaction->amount);
|
||||||
|
}
|
||||||
++$result[$currencyId]['count'];
|
++$result[$currencyId]['count'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,6 +408,7 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
foreach ($result as $currencyId => $arr) {
|
foreach ($result as $currencyId => $arr) {
|
||||||
$result[$currencyId]['avg'] = bcdiv($arr['sum'], (string) $arr['count']);
|
$result[$currencyId]['avg'] = bcdiv($arr['sum'], (string) $arr['count']);
|
||||||
|
$result[$currencyId]['native_avg'] = bcdiv($arr['native_sum'], (string) $arr['count']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
@@ -439,12 +443,12 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
// find the most recent date for this bill NOT in the future. Cache this date:
|
// find the most recent date for this bill NOT in the future. Cache this date:
|
||||||
$start = clone $bill->date;
|
$start = clone $bill->date;
|
||||||
$start->startOfDay();
|
$start->startOfDay();
|
||||||
app('log')->debug('nextExpectedMatch: Start is '.$start->format('Y-m-d'));
|
app('log')->debug('nextExpectedMatch: Start is ' . $start->format('Y-m-d'));
|
||||||
|
|
||||||
while ($start < $date) {
|
while ($start < $date) {
|
||||||
app('log')->debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d H:i:s'), $date->format('Y-m-d H:i:s')));
|
app('log')->debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d H:i:s'), $date->format('Y-m-d H:i:s')));
|
||||||
$start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
|
$start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
|
||||||
app('log')->debug('Start is now '.$start->format('Y-m-d H:i:s'));
|
app('log')->debug('Start is now ' . $start->format('Y-m-d H:i:s'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
|
$end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
|
||||||
@@ -459,8 +463,8 @@ class BillRepository implements BillRepositoryInterface
|
|||||||
$start = clone $end;
|
$start = clone $end;
|
||||||
$end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
|
$end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
|
||||||
}
|
}
|
||||||
app('log')->debug('nextExpectedMatch: Final start is '.$start->format('Y-m-d'));
|
app('log')->debug('nextExpectedMatch: Final start is ' . $start->format('Y-m-d'));
|
||||||
app('log')->debug('nextExpectedMatch: Matching end is '.$end->format('Y-m-d'));
|
app('log')->debug('nextExpectedMatch: Matching end is ' . $end->format('Y-m-d'));
|
||||||
|
|
||||||
$cache->store($start);
|
$cache->store($start);
|
||||||
|
|
||||||
|
@@ -66,7 +66,13 @@
|
|||||||
<td>{{ trans('firefly.average_bill_amount_year', {year: year}) }}</td>
|
<td>{{ trans('firefly.average_bill_amount_year', {year: year}) }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% for avg in yearAverage %}
|
{% for avg in yearAverage %}
|
||||||
{{ formatAmountBySymbol(avg.avg, avg.currency_symbol, avg.currency_decimal_places, true) }}<br>
|
{{ formatAmountBySymbol(avg.avg, avg.currency_symbol, avg.currency_decimal_places, true) }}
|
||||||
|
{% if convertToNative %}
|
||||||
|
({{ formatAmountBySymbol(avg.native_avg,
|
||||||
|
defaultCurrency.symbol, defaultCurrency.decimal_places, true) }})
|
||||||
|
{% endif %}
|
||||||
|
<br>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -74,7 +80,12 @@
|
|||||||
<td>{{ 'average_bill_amount_overall'|_ }}</td>
|
<td>{{ 'average_bill_amount_overall'|_ }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% for avg in overallAverage %}
|
{% for avg in overallAverage %}
|
||||||
{{ formatAmountBySymbol(avg.avg, avg.currency_symbol, avg.currency_decimal_places, true) }}<br>
|
{{ formatAmountBySymbol(avg.avg, avg.currency_symbol, avg.currency_decimal_places, true) }}
|
||||||
|
{% if convertToNative %}
|
||||||
|
({{ formatAmountBySymbol(avg.native_avg,
|
||||||
|
defaultCurrency.symbol, defaultCurrency.decimal_places, true) }})
|
||||||
|
{% endif %}
|
||||||
|
<br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -174,7 +185,7 @@
|
|||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script type="text/javascript" nonce="{{ JS_NONCE }}">
|
<script type="text/javascript" nonce="{{ JS_NONCE }}">
|
||||||
var billCurrencySymbol = "{{ object.data.currency.symbol }}";
|
var billCurrencySymbol = "{{ convertToNative ? defaultCurrency.symbol : object.data.currency.symbol }}";
|
||||||
var billUrl = '{{ route('chart.bill.single', [object.data.id]) }}';
|
var billUrl = '{{ route('chart.bill.single', [object.data.id]) }}';
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
|
<script type="text/javascript" src="v1/js/lib/Chart.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
|
||||||
|
@@ -69,7 +69,7 @@
|
|||||||
~ {{ formatAmountBySymbol((entry.amount_max + entry.amount_min)/2, entry.currency_symbol, entry.currency_decimal_places) }}
|
~ {{ formatAmountBySymbol((entry.amount_max + entry.amount_min)/2, entry.currency_symbol, entry.currency_decimal_places) }}
|
||||||
|
|
||||||
{% if '0' != entry.native_amount_max %}
|
{% if '0' != entry.native_amount_max %}
|
||||||
({{ formatAmountBySymbol((entry.native_amount_max + entry.native_amount_min)/2, defaultCurrency.symbol, defaultCurrency.decimal_places) }})
|
(~ {{ formatAmountBySymbol((entry.native_amount_max + entry.native_amount_min)/2, defaultCurrency.symbol, defaultCurrency.decimal_places) }})
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
Reference in New Issue
Block a user