133 lines
5.2 KiB
PHP
133 lines
5.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Http\Requests\StoreInstallmentRequest;
|
|
use App\Models\Account;
|
|
use App\Models\Activity;
|
|
use App\Models\Booking;
|
|
use App\Models\Installment;
|
|
use App\Models\InstallmentSetting;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\RedirectResponse;
|
|
|
|
class AccountInstallmentController extends Controller
|
|
{
|
|
public function list(Account $account): JsonResponse
|
|
{
|
|
$installments = Installment::query()
|
|
->where('account_id', $account->id)
|
|
->orderByDesc('installment_at')
|
|
->get(['id', 'amount', 'balance_before', 'currency', 'reference', 'installment_at', 'created_at'])
|
|
->map(function (Installment $i) {
|
|
return [
|
|
'id' => $i->id,
|
|
'amount' => (float) $i->amount,
|
|
'balance_before' => (float) ($i->balance_before ?? 0),
|
|
'currency' => $i->currency,
|
|
'reference' => $i->reference,
|
|
'installment_at' => optional($i->installment_at)?->toDateString(),
|
|
'created_at' => optional($i->created_at)?->toDateTimeString(),
|
|
];
|
|
});
|
|
|
|
return response()->json([
|
|
'account' => [
|
|
'id' => $account->id,
|
|
'balance_amount' => $account->balance_amount,
|
|
],
|
|
'installments' => $installments,
|
|
]);
|
|
}
|
|
|
|
public function store(StoreInstallmentRequest $request, Account $account): RedirectResponse
|
|
{
|
|
$validated = $request->validated();
|
|
|
|
$amountCents = (int) round(((float) $validated['amount']) * 100);
|
|
|
|
$settings = InstallmentSetting::query()->first();
|
|
$defaultCurrency = strtoupper($settings->default_currency ?? 'EUR');
|
|
|
|
$installment = Installment::query()->create([
|
|
'account_id' => $account->id,
|
|
'balance_before' => (float) ($account->balance_amount ?? 0),
|
|
'amount' => (float) $validated['amount'],
|
|
'currency' => strtoupper($validated['currency'] ?? $defaultCurrency),
|
|
'reference' => $validated['reference'] ?? null,
|
|
'installment_at' => $validated['installment_at'] ?? now(),
|
|
'meta' => $validated['meta'] ?? null,
|
|
'created_by' => $request->user()?->id,
|
|
]);
|
|
|
|
// Debit booking — increases the account balance
|
|
Booking::query()->create([
|
|
'account_id' => $account->id,
|
|
'payment_id' => null,
|
|
'amount_cents' => $amountCents,
|
|
'type' => 'debit',
|
|
'description' => $installment->reference ? ('Obremenitev '.$installment->reference) : 'Obremenitev',
|
|
'booked_at' => $installment->installment_at ?? now(),
|
|
]);
|
|
|
|
if ($settings && ($settings->create_activity_on_installment ?? false)) {
|
|
$note = $settings->activity_note_template ?? 'Dodan obrok';
|
|
$note = str_replace(['{amount}', '{currency}'], [number_format($amountCents / 100, 2, ',', '.'), $installment->currency], $note);
|
|
|
|
$account->refresh();
|
|
$beforeStr = number_format((float) ($installment->balance_before ?? 0), 2, ',', '.').' '.$installment->currency;
|
|
$afterStr = number_format((float) ($account->balance_amount ?? 0), 2, ',', '.').' '.$installment->currency;
|
|
$note .= " (Stanje pred: {$beforeStr}, Stanje po: {$afterStr}; Izvor: obrok)";
|
|
|
|
$account->loadMissing('contract');
|
|
$clientCaseId = $account->contract?->client_case_id;
|
|
if ($clientCaseId) {
|
|
$activity = Activity::query()->create([
|
|
'due_date' => null,
|
|
'amount' => $amountCents / 100,
|
|
'note' => $note,
|
|
'action_id' => $settings->default_action_id,
|
|
'decision_id' => $settings->default_decision_id,
|
|
'client_case_id' => $clientCaseId,
|
|
'contract_id' => $account->contract_id,
|
|
]);
|
|
$installment->update(['activity_id' => $activity->id]);
|
|
}
|
|
}
|
|
|
|
return back()->with('success', 'Installment created.');
|
|
}
|
|
|
|
public function destroy(Account $account, Installment $installment): RedirectResponse|JsonResponse
|
|
{
|
|
if ($installment->account_id !== $account->id) {
|
|
abort(404);
|
|
}
|
|
|
|
// Delete related debit booking(s) to revert balance via model events
|
|
Booking::query()
|
|
->where('account_id', $account->id)
|
|
->where('type', 'debit')
|
|
->whereDate('booked_at', optional($installment->installment_at)?->toDateString())
|
|
->where('amount_cents', (int) round(((float) $installment->amount) * 100))
|
|
->whereNull('payment_id')
|
|
->get()
|
|
->each->delete();
|
|
|
|
if ($installment->activity_id) {
|
|
$activity = Activity::query()->find($installment->activity_id);
|
|
if ($activity) {
|
|
$activity->delete();
|
|
}
|
|
}
|
|
|
|
$installment->delete();
|
|
|
|
if (request()->wantsJson()) {
|
|
return response()->json(['success' => true]);
|
|
}
|
|
|
|
return back()->with('success', 'Installment deleted.');
|
|
}
|
|
}
|