diff --git a/app/Http/Controllers/ClientCaseContoller.php b/app/Http/Controllers/ClientCaseContoller.php index 9847f23..8b599eb 100644 --- a/app/Http/Controllers/ClientCaseContoller.php +++ b/app/Http/Controllers/ClientCaseContoller.php @@ -223,7 +223,11 @@ public function updateContract(ClientCase $clientCase, string $uuid, UpdateContr return back()->with('warning', __('contracts.edit_not_allowed_archived')); } - \DB::transaction(function () use ($request, $contract) { + $balanceChanged = false; + $oldBalance = null; + $newBalance = null; + + \DB::transaction(function () use ($request, $contract, &$balanceChanged, &$oldBalance, &$newBalance) { $contract->update([ 'reference' => $request->input('reference'), 'type_id' => $request->input('type_id'), @@ -254,6 +258,7 @@ public function updateContract(ClientCase $clientCase, string $uuid, UpdateContr $accountData['type_id'] = $request->input('account_type_id'); } if ($currentAccount) { + $oldBalance = (float) $currentAccount->balance_amount; $currentAccount->update($accountData); if (array_key_exists('balance_amount', $accountData)) { $currentAccount->forceFill(['balance_amount' => $accountData['balance_amount']])->save(); @@ -264,6 +269,10 @@ public function updateContract(ClientCase $clientCase, string $uuid, UpdateContr ->update(['balance_amount' => $accountData['balance_amount'], 'updated_at' => now()]); $freshBal = (float) optional($currentAccount->fresh())->balance_amount; } + $newBalance = $freshBal; + if ($oldBalance !== $freshBal) { + $balanceChanged = true; + } } else { $freshBal = (float) optional($currentAccount->fresh())->balance_amount; } @@ -276,6 +285,27 @@ public function updateContract(ClientCase $clientCase, string $uuid, UpdateContr }); + // Fire activity if balance changed and settings require it + if ($balanceChanged) { + $contractSetting = \App\Models\ContractSetting::query()->first(); + if ($contractSetting && $contractSetting->create_activity_on_balance_change) { + $note = str_replace( + ['{old_balance}', '{new_balance}', '{currency}'], + [number_format($oldBalance, 2, '.', ''), number_format($newBalance, 2, '.', ''), 'EUR'], + $contractSetting->activity_note_template ?? '' + ); + \App\Models\Activity::query()->create([ + 'due_date' => null, + 'amount' => $newBalance, + 'note' => $note, + 'action_id' => $contractSetting->default_action_id, + 'decision_id' => $contractSetting->default_decision_id, + 'client_case_id' => $contract->client_case_id, + 'contract_id' => $contract->id, + ]); + } + } + // Preserve segment filter if present $segment = request('segment'); diff --git a/app/Http/Controllers/ContractSettingController.php b/app/Http/Controllers/ContractSettingController.php new file mode 100644 index 0000000..d920033 --- /dev/null +++ b/app/Http/Controllers/ContractSettingController.php @@ -0,0 +1,56 @@ +first(); + if (! $setting) { + $setting = \App\Models\ContractSetting::query()->create([ + 'create_activity_on_balance_change' => false, + 'default_action_id' => null, + 'default_decision_id' => null, + 'activity_note_template' => 'Sprememba stanja pogodbe: {old_balance} → {new_balance} {currency}', + ]); + } + + $decisions = \App\Models\Decision::query()->orderBy('name')->get(['id', 'name']); + $actions = \App\Models\Action::query() + ->with(['decisions:id']) + ->orderBy('name') + ->get() + ->map(function (\App\Models\Action $a) { + return [ + 'id' => $a->id, + 'name' => $a->name, + 'decision_ids' => $a->decisions->pluck('id')->values(), + ]; + }); + + return \Inertia\Inertia::render('Settings/Contracts/Index', [ + 'setting' => [ + 'id' => $setting->id, + 'create_activity_on_balance_change' => (bool) $setting->create_activity_on_balance_change, + 'default_action_id' => $setting->default_action_id, + 'default_decision_id' => $setting->default_decision_id, + 'activity_note_template' => $setting->activity_note_template, + ], + 'decisions' => $decisions, + 'actions' => $actions, + ]); + } + + public function update(\App\Http\Requests\UpdateContractSettingRequest $request): \Illuminate\Http\RedirectResponse + { + $data = $request->validated(); + $setting = \App\Models\ContractSetting::query()->firstOrFail(); + + $data['create_activity_on_balance_change'] = (bool) ($data['create_activity_on_balance_change'] ?? false); + + $setting->update($data); + + return back()->with('success', 'Nastavitve shranjene.'); + } +} diff --git a/app/Http/Requests/UpdateContractSettingRequest.php b/app/Http/Requests/UpdateContractSettingRequest.php new file mode 100644 index 0000000..5b2e17a --- /dev/null +++ b/app/Http/Requests/UpdateContractSettingRequest.php @@ -0,0 +1,23 @@ + ['sometimes', 'boolean'], + 'default_action_id' => ['nullable', 'integer', 'exists:actions,id'], + 'default_decision_id' => ['nullable', 'integer', 'exists:decisions,id'], + 'activity_note_template' => ['nullable', 'string', 'max:255'], + ]; + } +} diff --git a/app/Models/ContractSetting.php b/app/Models/ContractSetting.php new file mode 100644 index 0000000..e201e6a --- /dev/null +++ b/app/Models/ContractSetting.php @@ -0,0 +1,15 @@ +id(); + $table->boolean('create_activity_on_balance_change')->default(false); + $table->foreignId('default_action_id')->nullable()->constrained('actions')->nullOnDelete(); + $table->foreignId('default_decision_id')->nullable()->constrained('decisions')->nullOnDelete(); + $table->string('activity_note_template', 255)->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('contract_settings'); + } +}; diff --git a/resources/js/Pages/Settings/Contracts/Index.vue b/resources/js/Pages/Settings/Contracts/Index.vue new file mode 100644 index 0000000..a710b3c --- /dev/null +++ b/resources/js/Pages/Settings/Contracts/Index.vue @@ -0,0 +1,159 @@ + + + + + + + + + + + Nastavitve pogodb + + + + + + + Ustvari aktivnost ob spremembi odprtega zneska pogodbe + + + + + + Privzeto dejanje + + + + + + — Brez — + {{ + a.name + }} + + + + {{ form.errors.default_action_id }} + + + + + Privzeta odločitev + + + + + + — Najprej izberite dejanje — + {{ + d.name + }} + + + + {{ form.errors.default_decision_id }} + + + + + + Predloga opombe aktivnosti + + + Podprti žetoni: {old_balance}, {new_balance}, {currency} + + + {{ form.errors.activity_note_template }} + + + + + Ponastavi + Shrani + + + + + + diff --git a/resources/js/Pages/Settings/Index.vue b/resources/js/Pages/Settings/Index.vue index 449fde8..80ad3d1 100644 --- a/resources/js/Pages/Settings/Index.vue +++ b/resources/js/Pages/Settings/Index.vue @@ -52,6 +52,12 @@ const settingsCards = [ route: "settings.contractConfigs.index", icon: FileText, }, + { + title: "Contract Settings", + description: "Auto-activity triggers on contract balance changes.", + route: "settings.contract.edit", + icon: FileText, + }, { title: "Archive Settings", description: "Define rules for archiving or soft-deleting aged data.", diff --git a/routes/web.php b/routes/web.php index 43cbe07..deeeec6 100644 --- a/routes/web.php +++ b/routes/web.php @@ -9,6 +9,7 @@ use App\Http\Controllers\ClientCaseContoller; use App\Http\Controllers\ClientController; use App\Http\Controllers\ContractConfigController; +use App\Http\Controllers\ContractSettingController; use App\Http\Controllers\FieldJobController; use App\Http\Controllers\FieldJobSettingController; use App\Http\Controllers\ImportController; @@ -518,6 +519,10 @@ Route::get('settings/installment', [InstallmentSettingController::class, 'edit'])->name('settings.installment.edit'); Route::put('settings/installment', [InstallmentSettingController::class, 'update'])->name('settings.installment.update'); + // settings - contract settings + Route::get('settings/contract', [ContractSettingController::class, 'edit'])->name('settings.contract.edit'); + Route::put('settings/contract', [ContractSettingController::class, 'update'])->name('settings.contract.update'); + Route::get('types/address', function (Request $request) { $types = App\Models\Person\AddressType::all();
+ Podprti žetoni: {old_balance}, {new_balance}, {currency} +