Display for bills.

This commit is contained in:
James Cole
2024-12-26 11:28:31 +01:00
parent 71cf6c6a5e
commit 286a29ca3e
5 changed files with 127 additions and 96 deletions

View File

@@ -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');
} }

View File

@@ -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

View File

@@ -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,6 +282,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;
@@ -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 */
@@ -373,8 +372,7 @@ class BillRepository implements BillRepositoryInterface
$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;

View File

@@ -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>

View File

@@ -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>