This commit is contained in:
James Cole
2024-11-30 06:19:21 +01:00
parent f5c56e02da
commit 9ad005e31f
9 changed files with 154 additions and 37 deletions

View File

@@ -63,7 +63,7 @@ class BudgetLimitController extends Controller
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.budgets'));
app('view')->share('title', (string) trans('firefly.budgets'));
app('view')->share('mainTitleIcon', 'fa-pie-chart');
$this->repository = app(BudgetRepositoryInterface::class);
$this->opsRepository = app(OperationsRepositoryInterface::class);
@@ -101,6 +101,24 @@ class BudgetLimitController extends Controller
return view('budgets.budget-limits.create', compact('start', 'end', 'currencies', 'budget'));
}
/**
* @return Factory|View
*/
public function show(BudgetLimit $budgetLimit)
{
$notes = $this->blRepository->getNoteText($budgetLimit);
return view('budgets.budget-limits.show', compact('budgetLimit', 'notes'));
}
/**
* @return Factory|View
*/
public function edit(BudgetLimit $budgetLimit)
{
$notes = $this->blRepository->getNoteText($budgetLimit);
return view('budgets.budget-limits.edit', compact('budgetLimit', 'notes'));
}
/**
* @return Redirector|RedirectResponse
*/
@@ -117,12 +135,12 @@ class BudgetLimitController extends Controller
*
* @throws FireflyException
*/
public function store(Request $request): JsonResponse|RedirectResponse
public function store(Request $request): JsonResponse | RedirectResponse
{
app('log')->debug('Going to store new budget-limit.', $request->all());
// first search for existing one and update it if necessary.
$currency = $this->currencyRepos->find((int)$request->get('transaction_currency_id'));
$budget = $this->repository->find((int)$request->get('budget_id'));
$currency = $this->currencyRepos->find((int) $request->get('transaction_currency_id'));
$budget = $this->repository->find((int) $request->get('budget_id'));
if (null === $currency || null === $budget) {
throw new FireflyException('No valid currency or budget.');
}
@@ -133,7 +151,7 @@ class BudgetLimitController extends Controller
return response()->json([]);
}
$amount = (string)$request->get('amount');
$amount = (string) $request->get('amount');
$start->startOfDay();
$end->startOfDay();
@@ -154,7 +172,7 @@ class BudgetLimitController extends Controller
// return empty=ish array:
return response()->json([]);
}
if ((int)$amount > 268435456) { // intentional cast to integer
if ((int) $amount > 268435456) { // intentional cast to integer
$amount = '268435456';
}
if (-1 === bccomp($amount, '0')) {
@@ -169,13 +187,16 @@ class BudgetLimitController extends Controller
$limit = $this->blRepository->store(
[
'budget_id' => $request->get('budget_id'),
'currency_id' => (int)$request->get('transaction_currency_id'),
'currency_id' => (int) $request->get('transaction_currency_id'),
'start_date' => $start,
'end_date' => $end,
'amount' => $amount,
]
);
}
// parse notes, if any.
$notes = (string) $request->get('notes');
$this->blRepository->setNoteText($limit, $notes);
if ($request->expectsJson()) {
$array = $limit->toArray();
@@ -184,26 +205,29 @@ class BudgetLimitController extends Controller
$array['spent'] = $spentArr[$currency->id]['sum'] ?? '0';
$array['left_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, bcadd($array['spent'], $array['amount']));
$array['amount_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $limit['amount']);
$array['days_left'] = (string)$this->activeDaysLeft($start, $end);
$array['days_left'] = (string) $this->activeDaysLeft($start, $end);
// left per day:
$array['left_per_day'] = 0 === bccomp('0', $array['days_left']) ? bcadd($array['spent'], $array['amount']) : bcdiv(bcadd($array['spent'], $array['amount']), $array['days_left']);
// left per day formatted.
$array['left_per_day_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $array['left_per_day']);
// notes:
$array['notes'] = $this->blRepository->getNoteText($limit);
return response()->json($array);
}
return redirect(route('budgets.index'));
}
public function update(Request $request, BudgetLimit $budgetLimit): JsonResponse
public function update(Request $request, BudgetLimit $budgetLimit): JsonResponse|RedirectResponse
{
$amount = (string)$request->get('amount');
$amount = (string) $request->get('amount');
if ('' === $amount) {
$amount = '0';
}
if ((int)$amount > 268435456) { // 268 million, intentional integer
if ((int) $amount > 268435456) { // 268 million, intentional integer
$amount = '268435456';
}
// sanity check on amount:
@@ -224,8 +248,13 @@ class BudgetLimitController extends Controller
if (-1 === bccomp($amount, '0')) {
$amount = bcmul($amount, '-1');
}
$notes = (string)$request->get('notes');
if(strlen($notes) > 32768) {
$notes = substr($notes, 0, 32768);
}
$limit = $this->blRepository->update($budgetLimit, ['amount' => $amount]);
$limit = $this->blRepository->update($budgetLimit, ['amount' => $amount,'notes' => $notes]);
app('preferences')->mark();
$array = $limit->toArray();
@@ -240,13 +269,15 @@ class BudgetLimitController extends Controller
$array['spent'] = $spentArr[$budgetLimit->transactionCurrency->id]['sum'] ?? '0';
$array['left_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, bcadd($array['spent'], $array['amount']));
$array['amount_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $limit['amount']);
$array['days_left'] = (string)$daysLeft;
$array['days_left'] = (string) $daysLeft;
$array['left_per_day'] = 0 === $daysLeft ? bcadd($array['spent'], $array['amount']) : bcdiv(bcadd($array['spent'], $array['amount']), $array['days_left']);
// left per day formatted.
$array['amount'] = app('steam')->bcround($limit['amount'], $limit->transactionCurrency->decimal_places);
$array['left_per_day_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $array['left_per_day']);
if ('true' === $request->get('redirect')) {
return redirect(route('budgets.index'));
}
return response()->json($array);
}
}

View File

@@ -213,6 +213,7 @@ class IndexController extends Controller
$array['budgeted'][] = [
'id' => $limit->id,
'amount' => $amount,
'notes' => $this->blRepository->getNoteText($limit),
'start_date' => $limit->start_date->isoFormat($this->monthAndDayFormat),
'end_date' => $limit->end_date->isoFormat($this->monthAndDayFormat),
'in_range' => $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end),

View File

@@ -35,6 +35,8 @@ $(function () {
$('.budget_amount').on('change', updateBudgetedAmount);
$('.create_bl').on('click', createBudgetLimit);
$('.edit_bl').on('click', editBudgetLimit);
$('.show_bl').on('click', showBudgetLimit);
$('.delete_bl').on('click', deleteBudgetLimit);
@@ -216,6 +218,24 @@ function createBudgetLimit(e) {
return false;
}
function editBudgetLimit(e) {
var button = $(e.currentTarget);
var budgetLimitId = button.data('id');
$('#defaultModal').empty().load(editBudgetLimitUrl.replace('REPLACEME', budgetLimitId.toString()), function () {
$('#defaultModal').modal('show');
});
return false;
}
function showBudgetLimit(e) {
var button = $(e.currentTarget);
var budgetLimitId = button.data('id');
$('#defaultModal').empty().load(showBudgetLimitUrl.replace('REPLACEME', budgetLimitId.toString()), function () {
$('#defaultModal').modal('show');
});
return false;
}
function deleteBudgetLimit(e) {
e.preventDefault();
var button = $(e.currentTarget);

View File

@@ -2068,6 +2068,10 @@ return [
'opt_group_l_Mortgage' => 'Liability: Mortgage',
'opt_group_l_Credit card' => 'Liability: Credit card',
'notes' => 'Notes',
'view_notes' => 'View notes',
'set_budget_limit_notes' => 'View the notes for this budgeted amount',
'edit_bl_notes' => 'Edit notes',
'update_bl_notes' => 'Update notes',
'unknown_journal_error' => 'Could not store the transaction. Please check the log files.',
'attachment_not_found' => 'This attachment could not be found.',
'journal_link_bill' => 'This transaction is linked to bill <a href=":route">:name</a>. To remove the connection, uncheck the checkbox. Use rules to connect it to another bill.',

View File

@@ -25,6 +25,10 @@
<div class="form-group">
<input step="any" class="form-control" id="amount" value="" autocomplete="off" name="amount" type="number"/>
</div>
<div class="form-group">
<textarea name="notes" class="form-control" rows="3" placeholder="{{ 'notes'|_ }}"></textarea>
<span class="help-block">{{ trans('firefly.field_supports_markdown')|raw }}</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'close'|_ }}</button>

View File

@@ -0,0 +1,28 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span>&times;</span><span class="sr-only">{{ 'close'|_ }}</span>
</button>
<h4 class="modal-title">
{{ trans('firefly.edit_bl_notes') }}
</h4>
</div>
<form style="display: inline;" action="{{ route('budget-limits.update', [budgetLimit.id]) }}" method="POST">
<div class="modal-body">
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
<input type="hidden" name="redirect" value="true"/>
<input type="hidden" name="amount" value="{{ budgetLimit.amount }}"/>
<div class="form-group">
<textarea name="notes" class="form-control" rows="3" placeholder="{{ 'notes'|_ }}">{{ notes }}</textarea>
<span class="help-block">{{ trans('firefly.field_supports_markdown')|raw }}</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'close'|_ }}</button>
<button type="submit" class="btn btn-primary">{{ 'update_bl_notes'|_ }}</button>
</div>
</form>
</div>
</div>

View File

@@ -0,0 +1,20 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span>&times;</span><span class="sr-only">{{ 'close'|_ }}</span>
</button>
<h4 class="modal-title">
{{ trans('firefly.set_budget_limit_notes') }}
</h4>
</div>
<div class="modal-body">
<div>
{{ notes|markdown }}
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'close'|_ }}</button>
</div>
</div>
</div>

View File

@@ -212,6 +212,7 @@
</tr>
</thead>
<tbody>
{# START OF BUDGET ROW #}
{% for budget in budgets %}
<tr data-id="{{ budget.id }}">
<td class="hidden-sm hidden-xs">
@@ -269,7 +270,6 @@
{% if not budgetLimit.in_range %}
<small class="text-muted">
{{ trans('firefly.budget_limit_not_in_range', {start: budgetLimit.start_date, end: budgetLimit.end_date}) }}
</small><br>
{% endif %}
<div class="input-group bl_entry" data-budget-limit-id="{{ budgetLimit.id }}">
@@ -285,7 +285,13 @@
<li>
<a class="delete_bl" href="#" data-budget-limit-id="{{ budgetLimit.id }}">{{ trans('firefly.remove_budgeted_amount', {currency: budgetLimit.currency_name }) }}</a>
</li>
<li>
<a class="edit_bl" href="#" data-id="{{ budgetLimit.id }}">{{ trans('firefly.edit_bl_notes') }}</a>
</li>
</ul>
{% if '' != budgetLimit.notes %}
<a href="#" class="btn btn-default show_bl" data-id="{{ budgetLimit.id }}"><em title="{{ 'view_notes'|_ }}" class="fa fa-commenting-o" aria-hidden="true"></em></a>
{% endif %}
</div>
</div>
<span class="text-danger budget_warning" data-id="{{ budget.id }}" data-budgetLimit="{{ budgetLimit.id }}"
@@ -368,6 +374,7 @@
</td>
</tr>
{% endfor %}
{# END OF BUDGET ROW #}
</tbody>
</table>
</div>
@@ -444,6 +451,8 @@
var createBudgetLimitUrl = "{{ route('budget-limits.create', ['REPLACEME', start.format('Y-m-d'), end.format('Y-m-d')]) }}";
var storeBudgetLimitUrl = "{{ route('budget-limits.store') }}";
var updateBudgetLimitUrl = "{{ route('budget-limits.update', ['REPLACEME']) }}";
var showBudgetLimitUrl = "{{ route('budget-limits.show', ['REPLACEME']) }}";
var editBudgetLimitUrl = "{{ route('budget-limits.edit', ['REPLACEME']) }}";
var deleteBudgetLimitUrl = "{{ route('budget-limits.delete', ['REPLACEME']) }}";
var totalBudgetedUrl = "{{ route('json.budget.total-budgeted', ['REPLACEME', start.format('Y-m-d'), end.format('Y-m-d')]) }}";

View File

@@ -304,10 +304,10 @@ Route::group(
Route::group(
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers', 'prefix' => 'budget-limits', 'as' => 'budget-limits.'],
static function (): void {
Route::get('create/{budget}/{start_date}/{end_date}', ['uses' => 'Budget\BudgetLimitController@create', 'as' => 'create'])
->where(['start_date' => DATEFORMAT])
->where(['end_date' => DATEFORMAT])
;
Route::get('create/{budget}/{start_date}/{end_date}', ['uses' => 'Budget\BudgetLimitController@create', 'as' => 'create'])->where(['start_date' => DATEFORMAT])->where(['end_date' => DATEFORMAT]);
Route::get('edit/{budgetLimit}', ['uses' => 'Budget\BudgetLimitController@edit', 'as' => 'edit']);
Route::get('show/{budgetLimit}', ['uses' => 'Budget\BudgetLimitController@show', 'as' => 'show']);
Route::post('store', ['uses' => 'Budget\BudgetLimitController@store', 'as' => 'store']);
Route::post('delete/{budgetLimit}', ['uses' => 'Budget\BudgetLimitController@delete', 'as' => 'delete']);