Changes to address added fulltext (address,post_code,city), added imployer column to person fix / updated PersonInfoGrid vue component
This commit is contained in:
parent
7fc4520dbf
commit
8fdc0d6359
|
|
@ -46,6 +46,7 @@ class Person extends Model
|
|||
'group_id',
|
||||
'type_id',
|
||||
'user_id',
|
||||
'employer'
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
|
|
|
|||
|
|
@ -2974,7 +2974,7 @@ private function findOrCreatePersonId(array $p): ?int
|
|||
// Create person if any fields present; ensure required foreign keys
|
||||
if (! empty($p)) {
|
||||
$data = [];
|
||||
foreach (['first_name', 'last_name', 'full_name', 'tax_number', 'social_security_number', 'birthday', 'gender', 'description', 'group_id', 'type_id'] as $k) {
|
||||
foreach (['first_name', 'last_name', 'full_name', 'tax_number', 'social_security_number', 'birthday', 'gender', 'description', 'group_id', 'type_id', 'employer'] as $k) {
|
||||
if (array_key_exists($k, $p)) {
|
||||
$data[$k] = $p[$k];
|
||||
}
|
||||
|
|
@ -3163,10 +3163,38 @@ private function upsertAddress(int $personId, array $addrData, $mappings): array
|
|||
if (! isset($addrData['country']) || $addrData['country'] === null || $addrData['country'] === '') {
|
||||
$addrData['country'] = 'SLO';
|
||||
}
|
||||
|
||||
if (!empty($addrData['city']) && empty($addrData['post_code'])) {
|
||||
if (preg_match('/^\d{3,}\s+/',trim($addrData['city']))) {
|
||||
$cleanStrCity = str($addrData['city'])->squish()->value();
|
||||
$splitCity = preg_split('/\s/', $cleanStrCity, 2);
|
||||
if (count($splitCity) >= 2) {
|
||||
$addrData['post_code'] = $splitCity[0];
|
||||
$addrData['city'] = $splitCity[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compare addresses with all spaces removed to handle whitespace variations
|
||||
$addressLineNoSpaces = preg_replace('/\s+/', '', $addressLine);
|
||||
/*$addressLineNoSpaces = preg_replace('/\s+/', '', $addressLine);
|
||||
|
||||
|
||||
$existing = PersonAddress::where('person_id', $personId)
|
||||
->whereRaw("REPLACE(address, ' ', '') = ?", [$addressLineNoSpaces])
|
||||
->first();*/
|
||||
|
||||
// Build search query combining address, post_code and city
|
||||
$searchParts = [$addrData['post_code']];
|
||||
if (!empty($addrData['post_code'])) {
|
||||
$searchParts[] = $addrData['post_code'];
|
||||
}
|
||||
if (!empty($addrData['city'])) {
|
||||
$searchParts[] = $addrData['city'];
|
||||
}
|
||||
|
||||
$searchQuery = implode(' ', $searchParts);
|
||||
// Use fulltext search (GIN index optimized)
|
||||
$existing = PersonAddress::where('person_id', $personId)
|
||||
->whereRaw("search_vector @@ plainto_tsquery('simple', ?)", [$searchQuery])
|
||||
->first();
|
||||
|
||||
$applyInsert = [];
|
||||
|
|
@ -3211,6 +3239,11 @@ private function upsertAddress(int $personId, array $addrData, $mappings): array
|
|||
$data['person_id'] = $personId;
|
||||
$data['country'] = $data['country'] ?? 'SLO';
|
||||
$data['type_id'] = $data['type_id'] ?? $this->getDefaultAddressTypeId();
|
||||
|
||||
if (!empty($addrData['post_code']) && $addrData['post_code'] !== '0' && !isset($applyUpdate['post_code'])) {
|
||||
$data['post_code'] = $addrData['post_code'];
|
||||
}
|
||||
|
||||
try {
|
||||
$created = PersonAddress::create($data);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('person', function (Blueprint $table){
|
||||
$table->string('employer', 125)->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('person', function (Blueprint $table){
|
||||
$table->dropColumn('employer');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// Add a generated tsvector column for fulltext search
|
||||
DB::statement("
|
||||
ALTER TABLE person_addresses
|
||||
ADD COLUMN search_vector tsvector
|
||||
GENERATED ALWAYS AS (
|
||||
to_tsvector('simple',
|
||||
coalesce(address, '') || ' ' ||
|
||||
coalesce(post_code, '') || ' ' ||
|
||||
coalesce(city, '')
|
||||
)
|
||||
) STORED
|
||||
");
|
||||
|
||||
// Create GIN index on the tsvector column for fast fulltext search
|
||||
DB::statement('CREATE INDEX person_addresses_search_vector_idx ON person_addresses USING GIN(search_vector)');
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('person_addresses', function (Blueprint $table) {
|
||||
$table->dropIndex('person_addresses_search_vector_idx');
|
||||
$table->dropColumn('search_vector');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -14,7 +14,7 @@ public function run(): void
|
|||
'key' => 'person',
|
||||
'canonical_root' => 'person',
|
||||
'label' => 'Person',
|
||||
'fields' => ['first_name', 'last_name', 'full_name', 'gender', 'birthday', 'tax_number', 'social_security_number', 'description'],
|
||||
'fields' => ['first_name', 'last_name', 'full_name', 'gender', 'birthday', 'tax_number', 'social_security_number', 'description', 'employer'],
|
||||
'field_aliases' => [
|
||||
'dob' => 'birthday',
|
||||
'date_of_birth' => 'birthday',
|
||||
|
|
@ -30,6 +30,7 @@ public function run(): void
|
|||
['pattern' => '/^(spol|gender)\b/i', 'field' => 'gender'],
|
||||
['pattern' => '/^(rojstvo|datum\s*rojstva|dob|birth|birthday|date\s*of\s*birth)\b/i', 'field' => 'birthday'],
|
||||
['pattern' => '/^(komentar|opis|opomba|comment|description|note)\b/i', 'field' => 'description'],
|
||||
['pattern' => '/^(delodajalec|služba)\b/i', 'field' => 'employer']
|
||||
],
|
||||
'ui' => ['order' => 1],
|
||||
],
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@ const buildVarsFromSelectedContract = () => {
|
|||
if (!uuid) return {};
|
||||
const c = (contractsForCase.value || []).find((x) => x.uuid === uuid);
|
||||
if (!c) return {};
|
||||
|
||||
|
||||
const vars = {
|
||||
contract: {
|
||||
uuid: c.uuid,
|
||||
|
|
@ -407,7 +407,7 @@ const buildVarsFromSelectedContract = () => {
|
|||
);
|
||||
vars.contract.meta = hasStructuredMeta ? flattenMeta(c.meta) : c.meta;
|
||||
}
|
||||
|
||||
|
||||
if (c.account) {
|
||||
vars.account = {
|
||||
reference: c.account.reference,
|
||||
|
|
@ -580,6 +580,19 @@ const openSmsDialog = (phone) => {
|
|||
// Load contracts for this case (for contract/account placeholders)
|
||||
loadContractsForCase();
|
||||
};
|
||||
// Format YYYY-MM-DD (or ISO date) to dd.mm.yyyy
|
||||
function formatDate(value) {
|
||||
if (!value) return "-";
|
||||
try {
|
||||
const iso = String(value).split("T")[0];
|
||||
const parts = iso.split("-");
|
||||
if (parts.length !== 3) return value;
|
||||
const [y, m, d] = parts;
|
||||
return `${d.padStart(2, "0")}.${m.padStart(2, "0")}.${y}`;
|
||||
} catch (e) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
const loadContractsForCase = async () => {
|
||||
try {
|
||||
const url = route("clientCase.contracts.list", { client_case: props.clientCaseUuid });
|
||||
|
|
@ -640,43 +653,86 @@ const submitSms = () => {
|
|||
</div>
|
||||
<div class="grid grid-rows-* grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-2">
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-xs leading-5 md:text-sm text-gray-500">Nu.</p>
|
||||
<p class="text-xs leading-5 md:text-sm text-gray-500">Primer ref.</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">{{ person.nu }}</p>
|
||||
</div>
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Name.</p>
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Naziv</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ person.full_name }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Tax NU.</p>
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Davčna</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ person.tax_number }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Social security NU.</p>
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Emšo</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ person.social_security_number }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-rows-* grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 mt-1">
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Address</p>
|
||||
<div
|
||||
v-if="clientCaseUuid"
|
||||
class="grid grid-rows-* grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2 mt-1"
|
||||
>
|
||||
<div class="col-span-full lg:col-span-1 rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Naslov</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ getMainAddress(person.addresses) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Phone</p>
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Telefon</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ getMainPhone(person.phones) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="md:col-span-full lg:col-span-1 rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Description</p>
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Datum rojstva</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ formatDate(person.birthday) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="grid grid-rows-* grid-cols-1 md:grid-cols-2 gap-2 mt-1">
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Naslov</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ getMainAddress(person.addresses) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Telefon</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ getMainPhone(person.phones) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="clientCaseUuid"
|
||||
class="grid grid-rows-* grid-cols-1 lg:grid-cols-2 gap-2 mt-1"
|
||||
>
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Delodajalec</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ person.employer }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Opis</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ person.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="grid grid-rows-* grid-cols-1 md:grid-cols-2 gap-2 mt-1">
|
||||
<div class="col-span-full rounded p-2 shadow">
|
||||
<p class="text-sm leading-5 md:text-sm text-gray-500">Opis</p>
|
||||
<p class="text-sm md:text-base leading-7 text-gray-900">
|
||||
{{ person.description }}
|
||||
</p>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user