248 lines
9.4 KiB
PHP
248 lines
9.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\FieldJob;
|
|
use App\Services\ReferenceDataCache;
|
|
use Illuminate\Http\Request;
|
|
use Inertia\Inertia;
|
|
|
|
class PhoneViewController extends Controller
|
|
{
|
|
public function __construct(protected ReferenceDataCache $referenceCache) {}
|
|
public function index(Request $request)
|
|
{
|
|
$userId = $request->user()->id;
|
|
|
|
$jobs = FieldJob::query()
|
|
->where('assigned_user_id', $userId)
|
|
->whereNull('completed_at')
|
|
->whereNull('cancelled_at')
|
|
->with([
|
|
'contract' => function ($q) {
|
|
$q->with([
|
|
'type:id,name',
|
|
'account',
|
|
'clientCase.person' => function ($pq) {
|
|
$pq->with(['addresses', 'phones']);
|
|
},
|
|
'clientCase.client:id,uuid,person_id',
|
|
'clientCase.client.person:id,full_name',
|
|
]);
|
|
},
|
|
])
|
|
->orderByDesc('assigned_at')
|
|
->limit(100)
|
|
->get();
|
|
|
|
return Inertia::render('Phone/Index', [
|
|
'jobs' => $jobs,
|
|
'view_mode' => 'assigned',
|
|
]);
|
|
}
|
|
|
|
public function completedToday(Request $request)
|
|
{
|
|
$userId = $request->user()->id;
|
|
|
|
$start = now()->startOfDay();
|
|
$end = now()->endOfDay();
|
|
|
|
$jobs = FieldJob::query()
|
|
->where('assigned_user_id', $userId)
|
|
->whereNull('cancelled_at')
|
|
->whereBetween('completed_at', [$start, $end])
|
|
->with([
|
|
'contract' => function ($q) {
|
|
$q->with([
|
|
'type:id,name',
|
|
'account',
|
|
'clientCase.person' => function ($pq) {
|
|
$pq->with(['addresses', 'phones']);
|
|
},
|
|
'clientCase.client:id,uuid,person_id',
|
|
'clientCase.client.person:id,full_name',
|
|
]);
|
|
},
|
|
])
|
|
->orderByDesc('completed_at')
|
|
->limit(100)
|
|
->get();
|
|
|
|
return Inertia::render('Phone/Index', [
|
|
'jobs' => $jobs,
|
|
'view_mode' => 'completed-today',
|
|
]);
|
|
}
|
|
|
|
public function showCase(\App\Models\ClientCase $clientCase, Request $request)
|
|
{
|
|
$userId = $request->user()->id;
|
|
$completedMode = (bool) $request->boolean('completed');
|
|
|
|
// Eager load client case with person details
|
|
$case = \App\Models\ClientCase::query()
|
|
->with(['person' => fn ($q) => $q->with(['addresses', 'phones', 'emails', 'bankAccounts'])])
|
|
->findOrFail($clientCase->id);
|
|
|
|
// Determine contracts of this case relevant to the current user
|
|
// - Normal mode: contracts assigned to me and still active (not completed/cancelled)
|
|
// - Completed mode (?completed=1): contracts where my field job was completed today
|
|
if ($completedMode) {
|
|
$start = now()->startOfDay();
|
|
$end = now()->endOfDay();
|
|
$contractIds = FieldJob::query()
|
|
->where('assigned_user_id', $userId)
|
|
->whereNull('cancelled_at')
|
|
->whereBetween('completed_at', [$start, $end])
|
|
->whereHas('contract', fn ($q) => $q->where('client_case_id', $case->id))
|
|
->pluck('contract_id')
|
|
->unique()
|
|
->values();
|
|
} else {
|
|
$contractIds = FieldJob::query()
|
|
->where('assigned_user_id', $userId)
|
|
->whereNull('completed_at')
|
|
->whereNull('cancelled_at')
|
|
->whereHas('contract', fn ($q) => $q->where('client_case_id', $case->id))
|
|
->pluck('contract_id')
|
|
->unique()
|
|
->values();
|
|
}
|
|
|
|
$contracts = \App\Models\Contract::query()
|
|
->where('client_case_id', $case->id)
|
|
->whereIn('id', $contractIds)
|
|
->with(['type:id,name', 'account'])
|
|
->orderByDesc('created_at')
|
|
->get();
|
|
|
|
// Attach latest object (if any) to each contract as last_object for display
|
|
if ($contracts->isNotEmpty()) {
|
|
$byId = $contracts->keyBy('id');
|
|
$latestObjects = \App\Models\CaseObject::query()
|
|
->whereIn('contract_id', $byId->keys())
|
|
->whereNull('deleted_at')
|
|
->select('id', 'reference', 'name', 'description', 'type', 'contract_id', 'created_at')
|
|
->orderByDesc('created_at')
|
|
->get()
|
|
->groupBy('contract_id')
|
|
->map(function ($group) {
|
|
return $group->first();
|
|
});
|
|
|
|
foreach ($latestObjects as $cid => $obj) {
|
|
if (isset($byId[$cid])) {
|
|
$byId[$cid]->setAttribute('last_object', $obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Build merged documents: case documents + documents of assigned contracts
|
|
$contractRefMap = [];
|
|
foreach ($contracts as $c) {
|
|
$contractRefMap[$c->id] = $c->reference;
|
|
}
|
|
|
|
$contractDocs = \App\Models\Document::query()
|
|
->where('documentable_type', \App\Models\Contract::class)
|
|
->whereIn('documentable_id', $contractIds)
|
|
->orderByDesc('created_at')
|
|
->get()
|
|
->map(function ($d) use ($contractRefMap) {
|
|
$arr = $d->toArray();
|
|
$arr['contract_reference'] = $contractRefMap[$d->documentable_id] ?? null;
|
|
$arr['documentable_type'] = \App\Models\Contract::class;
|
|
$arr['contract_uuid'] = optional(\App\Models\Contract::withTrashed()->find($d->documentable_id))->uuid;
|
|
|
|
return $arr;
|
|
});
|
|
|
|
$caseDocs = $case->documents()->orderByDesc('created_at')->get()->map(function ($d) use ($case) {
|
|
$arr = $d->toArray();
|
|
$arr['documentable_type'] = \App\Models\ClientCase::class;
|
|
$arr['client_case_uuid'] = $case->uuid;
|
|
|
|
return $arr;
|
|
});
|
|
|
|
$documents = $caseDocs->concat($contractDocs)->sortByDesc('created_at')->values();
|
|
|
|
// Provide minimal types for PersonInfoGrid
|
|
$types = [
|
|
'address_types' => $this->referenceCache->getAddressTypes(),
|
|
'phone_types' => $this->referenceCache->getPhoneTypes(),
|
|
];
|
|
|
|
// Case activities (compact for phone): latest 20 with relations
|
|
$activities = $case->activities()
|
|
->with(['action', 'decision', 'contract:id,uuid,reference', 'user:id,name'])
|
|
->orderByDesc('created_at')
|
|
->limit(20)
|
|
->get()
|
|
->map(function ($a) {
|
|
$a->setAttribute('user_name', optional($a->user)->name);
|
|
|
|
return $a;
|
|
});
|
|
|
|
// Determine segment filters from FieldJobSettings for this case/user context
|
|
$settingIds = FieldJob::query()
|
|
->where('assigned_user_id', $userId)
|
|
->whereHas('contract', fn ($q) => $q->where('client_case_id', $case->id))
|
|
->when(
|
|
$completedMode,
|
|
function ($q) {
|
|
$q->whereNull('cancelled_at')
|
|
->whereBetween('completed_at', [now()->startOfDay(), now()->endOfDay()]);
|
|
},
|
|
function ($q) {
|
|
$q->whereNull('completed_at')->whereNull('cancelled_at');
|
|
}
|
|
)
|
|
->pluck('field_job_setting_id')
|
|
->filter()
|
|
->unique()
|
|
->values();
|
|
|
|
$segmentIds = collect();
|
|
if ($settingIds->isNotEmpty()) {
|
|
$segmentIds = \App\Models\FieldJobSetting::query()
|
|
->whereIn('id', $settingIds)
|
|
->pluck('segment_id')
|
|
->filter()
|
|
->unique()
|
|
->values();
|
|
}
|
|
|
|
// Filter actions and their decisions by the derived segment ids (decisions.segment_id)
|
|
$actions = \App\Models\Action::query()
|
|
->when($segmentIds->isNotEmpty(), function ($q) use ($segmentIds) {
|
|
// Filter actions by their segment_id matching the FieldJobSetting segment(s)
|
|
$q->whereIn('segment_id', $segmentIds);
|
|
})
|
|
->with([
|
|
'decisions' => function ($q) {
|
|
$q->select('decisions.id', 'decisions.name', 'decisions.color_tag', 'decisions.auto_mail', 'decisions.email_template_id');
|
|
},
|
|
'decisions.emailTemplate' => function ($q) {
|
|
$q->select('id', 'name', 'entity_types', 'allow_attachments');
|
|
},
|
|
])
|
|
->get(['id', 'name', 'color_tag', 'segment_id']);
|
|
|
|
return Inertia::render('Phone/Case/Index', [
|
|
'client' => $case->client()->with('person', fn ($q) => $q->with(['addresses', 'phones', 'emails', 'bankAccounts']))->firstOrFail(),
|
|
'client_case' => $case,
|
|
'contracts' => $contracts,
|
|
'documents' => $documents,
|
|
'types' => $types,
|
|
'account_types' => $this->referenceCache->getAccountTypes(),
|
|
// Provide decisions (filtered by segment) with linked email template metadata (entity_types, allow_attachments)
|
|
'actions' => $actions,
|
|
'activities' => $activities,
|
|
'completed_mode' => $completedMode,
|
|
]);
|
|
}
|
|
}
|