diff --git a/app/Http/Controllers/ImportTemplateController.php b/app/Http/Controllers/ImportTemplateController.php index e48f741..ca390db 100644 --- a/app/Http/Controllers/ImportTemplateController.php +++ b/app/Http/Controllers/ImportTemplateController.php @@ -294,6 +294,12 @@ public function update(Request $request, ImportTemplate $template) if (! empty($raw['client_uuid'] ?? null)) { $raw['client_id'] = Client::where('uuid', $raw['client_uuid'])->value('id'); } + // If template already has mappings, lock client assignment on backend as well + // to prevent accidental clearing when client_uuid/client_id not sent. + $hasMappings = $template->mappings()->exists(); + if ($hasMappings) { + unset($raw['client_id'], $raw['client_uuid']); + } $data = validator($raw, [ 'name' => 'required|string|max:100', 'description' => 'nullable|string|max:255', @@ -338,26 +344,28 @@ public function update(Request $request, ImportTemplate $template) } } - $template->update([ + // Finalize meta (ensure payments entities forced if enabled) + $finalMeta = $newMeta; + if (! empty($finalMeta['payments_import'])) { + $finalMeta['entities'] = ['contracts', 'accounts', 'payments']; + } + + $update = [ 'name' => $data['name'], 'description' => $data['description'] ?? null, 'source_type' => $data['source_type'], 'default_record_type' => $data['default_record_type'] ?? null, - 'client_id' => $data['client_id'] ?? null, + // Only set client_id if explicitly present and not locked, otherwise keep existing 'is_active' => $data['is_active'] ?? $template->is_active, 'reactivate' => $data['reactivate'] ?? $template->reactivate, 'sample_headers' => $data['sample_headers'] ?? $template->sample_headers, - 'meta' => (function () use ($newMeta) { - // If payments import mode is enabled, force entities sequence in meta - $meta = $newMeta; - $payments = (bool) ($meta['payments_import'] ?? false); - if ($payments) { - $meta['entities'] = ['contracts', 'accounts', 'payments']; - } - - return $meta; - })(), - ]); + 'meta' => $finalMeta, + ]; + if (! $hasMappings && array_key_exists('client_id', $data)) { + $update['client_id'] = $data['client_id']; + } + // When locked, do not touch client_id (prevents clearing to null) + $template->update($update); return redirect()->route('importTemplates.edit', ['template' => $template->uuid]) ->with('success', 'Template updated'); diff --git a/resources/js/Layouts/Partials/GlobalSearch.vue b/resources/js/Layouts/Partials/GlobalSearch.vue index f225be0..0a60dab 100644 --- a/resources/js/Layouts/Partials/GlobalSearch.vue +++ b/resources/js/Layouts/Partials/GlobalSearch.vue @@ -1,91 +1,257 @@ - \ No newline at end of file +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.15s; +} +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + diff --git a/resources/js/Pages/Testing/Index.vue b/resources/js/Pages/Testing/Index.vue new file mode 100644 index 0000000..93d5c3a --- /dev/null +++ b/resources/js/Pages/Testing/Index.vue @@ -0,0 +1,22 @@ + + + diff --git a/routes/web.php b/routes/web.php index 03be493..fbd0f78 100644 --- a/routes/web.php +++ b/routes/web.php @@ -61,8 +61,10 @@ })->name('dashboard'); Route::get('testing', function () { - return Inertia::render('Testing', []); - }); + return Inertia::render('Testing/Index', [ + 'example' => 'Hello World', + ]); + })->name('testing.index'); // Phone page Route::get('phone', [PhoneViewController::class, 'index'])->name('phone.index'); @@ -88,7 +90,7 @@ $builder->join('client_cases', 'person.id', '=', 'client_cases.person_id') ->leftJoin('person_addresses', 'person.id', '=', 'person_addresses.person_id') ->leftJoin('person_phones', 'person.id', '=', 'person_phones.person_id') - ->select('person.*', 'client_cases.uuid as case_uuid') + ->select('person.*', 'client_cases.uuid as case_uuid', 'client_cases.id as case_id') ->limit($request->input('limit')); }) ->get(); @@ -100,9 +102,21 @@ $contractCases = \App\Models\Contract::query() ->join('client_cases', 'contracts.client_case_id', '=', 'client_cases.id') ->join('person', 'client_cases.person_id', '=', 'person.id') - // portable case-insensitive match across drivers + ->leftJoin('contract_segment', function ($j) { + $j->on('contract_segment.contract_id', '=', 'contracts.id') + ->where('contract_segment.active', true); + }) + ->leftJoin('segments', 'segments.id', '=', 'contract_segment.segment_id') + // case-insensitive reference match ->whereRaw('LOWER(contracts.reference) LIKE ?', ['%'.mb_strtolower($query).'%']) - ->select('person.*', 'client_cases.uuid as case_uuid') + ->select( + 'person.*', + 'client_cases.uuid as case_uuid', + 'client_cases.id as case_id', + 'contracts.reference as contract_reference', + \DB::raw("COALESCE(json_agg(DISTINCT jsonb_build_object('id', segments.id, 'name', segments.name)) FILTER (WHERE segments.id IS NOT NULL), '[]') as contract_segments") + ) + ->groupBy('person.id', 'client_cases.uuid', 'client_cases.id', 'contracts.reference') ->limit($limit) ->get(); @@ -110,8 +124,46 @@ $clientCases = $clientCases ->concat($contractCases) ->unique('case_uuid') - ->values() - ->take($limit); + ->values(); + + // Collect all case ids for segment lookup (for non-contract matches) + $caseIds = $clientCases->pluck('case_id')->filter()->unique()->values(); + if ($caseIds->isNotEmpty()) { + $caseSegments = \DB::table('client_cases') + ->join('contracts', 'contracts.client_case_id', '=', 'client_cases.id') + ->join('contract_segment', function ($j) { + $j->on('contract_segment.contract_id', '=', 'contracts.id') + ->where('contract_segment.active', true); + }) + ->join('segments', 'segments.id', '=', 'contract_segment.segment_id') + ->whereIn('client_cases.id', $caseIds) + ->select( + 'client_cases.id as case_id', + \DB::raw("COALESCE(json_agg(DISTINCT jsonb_build_object('id', segments.id, 'name', segments.name)) FILTER (WHERE segments.id IS NOT NULL), '[]') as segments_json") + ) + ->groupBy('client_cases.id') + ->get() + ->keyBy('case_id'); + + $clientCases = $clientCases->map(function ($row) use ($contractCases, $caseSegments) { + $contractHit = $contractCases->firstWhere('case_uuid', $row->case_uuid); + if ($contractHit) { + $row->contract_reference = $contractHit->contract_reference; + $segmentsJson = $contractHit->contract_segments ?? '[]'; + $row->contract_segments = is_string($segmentsJson) ? json_decode($segmentsJson, true) : (array) $segmentsJson; + } else { + $segRow = $caseSegments->get($row->case_id); + if ($segRow) { + $row->case_segments = json_decode($segRow->segments_json, true) ?? []; + } else { + $row->case_segments = []; + } + } + return $row; + })->take($limit); + } else { + $clientCases = $clientCases->take($limit); + } } return [