237 lines
9.0 KiB
PHP
237 lines
9.0 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Activity;
|
|
use App\Models\Contract;
|
|
use App\Models\FieldJob;
|
|
use App\Models\FieldJobSetting;
|
|
use App\Models\User;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Inertia\Inertia;
|
|
|
|
class FieldJobController extends Controller
|
|
{
|
|
public function index(Request $request)
|
|
{
|
|
$setting = FieldJobSetting::query()->latest('id')->first();
|
|
// Only fetch contracts that are currently in either the primary segment
|
|
// or the optional queue segment defined on the latest FieldJobSetting.
|
|
$segmentIds = collect([
|
|
optional($setting)->queue_segment_id,
|
|
optional($setting)->segment_id,
|
|
])->filter()->unique()->values();
|
|
|
|
$contracts = Contract::query()
|
|
->with(['clientCase.person', 'clientCase.client.person', 'type', 'account'])
|
|
->when($segmentIds->isNotEmpty(), function ($q) use ($segmentIds) {
|
|
$q->whereHas('segments', function ($sq) use ($segmentIds) {
|
|
// Relation already filters on active pivots
|
|
$sq->whereIn('segments.id', $segmentIds);
|
|
});
|
|
}, function ($q) {
|
|
// No segments configured on FieldJobSetting -> return none
|
|
$q->whereRaw('1 = 0');
|
|
})
|
|
->latest('id')
|
|
->limit(50)
|
|
->get();
|
|
|
|
// Mirror client onto the contract for simpler frontend access: c.client.person.full_name
|
|
$contracts->each(function (Contract $contract): void {
|
|
if ($contract->relationLoaded('clientCase') && $contract->clientCase) {
|
|
$contract->setRelation('client', $contract->clientCase->client);
|
|
}
|
|
});
|
|
|
|
// Build active assignment map keyed by contract uuid for quicker UI checks
|
|
$assignments = collect();
|
|
if ($contracts->isNotEmpty()) {
|
|
$activeJobs = FieldJob::query()
|
|
->whereIn('contract_id', $contracts->pluck('id'))
|
|
->whereNull('completed_at')
|
|
->whereNull('cancelled_at')
|
|
->with(['assignedUser:id,name', 'user:id,name', 'contract:id,uuid'])
|
|
->get();
|
|
|
|
$assignments = $activeJobs->mapWithKeys(function (FieldJob $job) {
|
|
return [
|
|
optional($job->contract)->uuid => [
|
|
'assigned_to' => $job->assignedUser ? ['id' => $job->assignedUser->id, 'name' => $job->assignedUser->name] : null,
|
|
'assigned_by' => $job->user ? ['id' => $job->user->id, 'name' => $job->user->name] : null,
|
|
'assigned_at' => $job->assigned_at,
|
|
],
|
|
];
|
|
})->filter();
|
|
}
|
|
|
|
$users = User::query()->orderBy('name')->get(['id', 'name']);
|
|
|
|
return Inertia::render('FieldJob/Index', [
|
|
'setting' => $setting,
|
|
'contracts' => $contracts,
|
|
'users' => $users,
|
|
'assignments' => $assignments,
|
|
]);
|
|
}
|
|
|
|
public function assign(Request $request)
|
|
{
|
|
$data = $request->validate([
|
|
'contract_uuid' => 'required|string|exists:contracts,uuid',
|
|
'assigned_user_id' => 'required|integer|exists:users,id',
|
|
]);
|
|
|
|
$setting = FieldJobSetting::query()->latest('id')->first();
|
|
if (! $setting) {
|
|
return back()->withErrors(['setting' => 'No Field Job Setting found. Create one in Settings → Field Job Settings.']);
|
|
}
|
|
|
|
$contract = Contract::query()->where('uuid', $data['contract_uuid'])->firstOrFail();
|
|
|
|
$job = FieldJob::create([
|
|
'field_job_setting_id' => $setting->id,
|
|
'assigned_user_id' => $data['assigned_user_id'],
|
|
'contract_id' => $contract->id,
|
|
'assigned_at' => now(),
|
|
]);
|
|
|
|
// Create an activity for the assignment
|
|
// Find the first action linked to the assign decision via pivot; also prefer actions within the same segment as the setting
|
|
$decisionId = $setting->assign_decision_id;
|
|
$actionId = null;
|
|
if ($decisionId) {
|
|
// Strictly use the action_decision pivot: take the first action mapped to this decision
|
|
$actionId = DB::table('action_decision')
|
|
->where('decision_id', $decisionId)
|
|
->orderBy('id')
|
|
->value('action_id');
|
|
}
|
|
|
|
if ($actionId) {
|
|
$assigneeName = User::query()->where('id', $data['assigned_user_id'])->value('name');
|
|
// Localized note: "Terensko opravilo dodeljeno" + assignee when present
|
|
$note = 'Terensko opravilo dodeljeno'.($assigneeName ? ' uporabniku '.$assigneeName : '');
|
|
Activity::create([
|
|
'due_date' => null,
|
|
'amount' => null,
|
|
'note' => $note,
|
|
'action_id' => $actionId,
|
|
'decision_id' => $decisionId,
|
|
'client_case_id' => $contract->client_case_id,
|
|
'contract_id' => $contract->id,
|
|
]);
|
|
}
|
|
|
|
return back()->with('success', 'Field job assigned.');
|
|
}
|
|
|
|
public function cancel(Request $request)
|
|
{
|
|
$data = $request->validate([
|
|
'contract_uuid' => 'required|string|exists:contracts,uuid',
|
|
]);
|
|
|
|
$contract = Contract::query()->where('uuid', $data['contract_uuid'])->firstOrFail();
|
|
|
|
$job = FieldJob::query()
|
|
->where('contract_id', $contract->id)
|
|
->whereNull('completed_at')
|
|
->whereNull('cancelled_at')
|
|
->latest('id')
|
|
->first();
|
|
|
|
if ($job) {
|
|
$job->cancelled_at = now();
|
|
$job->save();
|
|
|
|
// Create an activity for the cancellation, mirroring the assign flow
|
|
// Prefer the job's setting for a consistent decision
|
|
$job->loadMissing('setting');
|
|
$decisionId = optional($job->setting)->cancel_decision_id;
|
|
if ($decisionId) {
|
|
$actionId = DB::table('action_decision')
|
|
->where('decision_id', $decisionId)
|
|
->orderBy('id')
|
|
->value('action_id');
|
|
|
|
if ($actionId) {
|
|
Activity::create([
|
|
'due_date' => null,
|
|
'amount' => null,
|
|
'note' => 'Terensko opravilo preklicano',
|
|
'action_id' => $actionId,
|
|
'decision_id' => $decisionId,
|
|
'client_case_id' => $contract->client_case_id,
|
|
'contract_id' => $contract->id,
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return back()->with('success', 'Field job cancelled.');
|
|
}
|
|
|
|
public function complete(Request $request, \App\Models\ClientCase $clientCase)
|
|
{
|
|
// Complete all active field jobs for contracts of this case assigned to current user
|
|
$userId = optional($request->user())->id;
|
|
$setting = FieldJobSetting::query()->latest('id')->first();
|
|
if (! $setting) {
|
|
return back()->withErrors(['setting' => 'No Field Job Setting found.']);
|
|
}
|
|
|
|
$decisionId = $setting->complete_decision_id;
|
|
$actionId = null;
|
|
if ($decisionId) {
|
|
$actionId = DB::table('action_decision')
|
|
->where('decision_id', $decisionId)
|
|
->orderBy('id')
|
|
->value('action_id');
|
|
}
|
|
|
|
// Find all active jobs for this case for the current user
|
|
$jobs = FieldJob::query()
|
|
->whereHas('contract', function ($q) use ($clientCase) {
|
|
$q->where('client_case_id', $clientCase->id);
|
|
})
|
|
->where(function ($q) use ($userId) {
|
|
if ($userId) {
|
|
$q->where('assigned_user_id', $userId);
|
|
}
|
|
})
|
|
->whereNull('completed_at')
|
|
->whereNull('cancelled_at')
|
|
->with(['contract:id,client_case_id', 'setting'])
|
|
->get();
|
|
|
|
DB::transaction(function () use ($jobs, $decisionId, $actionId) {
|
|
foreach ($jobs as $job) {
|
|
// Mark job complete
|
|
$job->completed_at = now();
|
|
$job->save();
|
|
|
|
// Log completion activity on the contract/case
|
|
if ($actionId && $decisionId) {
|
|
Activity::create([
|
|
'due_date' => null,
|
|
'amount' => null,
|
|
'note' => 'Terensko opravilo zaključeno',
|
|
'action_id' => $actionId,
|
|
'decision_id' => $decisionId,
|
|
'client_case_id' => $job->contract->client_case_id,
|
|
'contract_id' => $job->contract_id,
|
|
]);
|
|
}
|
|
|
|
// Move contract to configured return segment
|
|
$job->returnContractToConfiguredSegment();
|
|
}
|
|
});
|
|
|
|
// Redirect back to phone index
|
|
return to_route('phone.index');
|
|
}
|
|
}
|