Importer update add support for meta data and multiple inserts for some entities like addresses and phones, updated other things

This commit is contained in:
Simon Pocrnjič
2025-10-09 22:28:48 +02:00
parent c8029c9eb0
commit 0598261cdc
27 changed files with 2517 additions and 375 deletions
+1 -1
View File
@@ -1059,7 +1059,7 @@ public function show(ClientCase $clientCase)
// Only apply active/inactive filtering IF a segment filter is provided.
$contractsQuery = $case->contracts()
// Only select lean columns to avoid oversize JSON / headers (include description for UI display)
->select(['id', 'uuid', 'reference', 'start_date', 'end_date', 'description', 'active', 'type_id', 'client_case_id', 'created_at'])
->select(['id', 'uuid', 'reference', 'start_date', 'end_date', 'description', 'meta', 'active', 'type_id', 'client_case_id', 'created_at'])
->with([
'type:id,name',
// Use closure for account to avoid ambiguous column names with latestOfMany join
+54 -2
View File
@@ -78,8 +78,7 @@ public function show(Client $client, Request $request)
->when($request->input('search'), fn ($que, $search) => $que->whereHas(
'person',
fn ($q) => $q->where('full_name', 'ilike', '%'.$search.'%')
)
)
))
->addSelect([
'active_contracts_count' => \DB::query()
->from('contracts')
@@ -112,6 +111,59 @@ public function show(Client $client, Request $request)
]);
}
public function contracts(Client $client, Request $request)
{
$data = $client->load(['person' => fn ($q) => $q->with(['addresses', 'phones', 'bankAccounts', 'emails'])]);
$from = $request->input('from');
$to = $request->input('to');
$search = $request->input('search');
$contractsQuery = \App\Models\Contract::query()
->whereHas('clientCase', function ($q) use ($client) {
$q->where('client_id', $client->id);
})
->with([
'clientCase:id,uuid,person_id',
'clientCase.person:id,full_name',
'segments' => function ($q) {
$q->wherePivot('active', true)->select('segments.id', 'segments.name');
},
'account:id,accounts.contract_id,balance_amount',
])
->select(['id', 'uuid', 'reference', 'start_date', 'client_case_id'])
->whereNull('deleted_at')
->when($from || $to, function ($q) use ($from, $to) {
if (! empty($from)) {
$q->whereDate('start_date', '>=', $from);
}
if (! empty($to)) {
$q->whereDate('start_date', '<=', $to);
}
})
->when($search, function ($q) use ($search) {
$q->where(function ($inner) use ($search) {
$inner->where('reference', 'ilike', '%'.$search.'%')
->orWhereHas('clientCase.person', function ($p) use ($search) {
$p->where('full_name', 'ilike', '%'.$search.'%');
});
});
})
->orderByDesc('start_date');
$types = [
'address_types' => \App\Models\Person\AddressType::all(),
'phone_types' => \App\Models\Person\PhoneType::all(),
];
return Inertia::render('Client/Contracts', [
'client' => $data,
'contracts' => $contractsQuery->paginate(20)->withQueryString(),
'filters' => $request->only(['from', 'to', 'search']),
'types' => $types,
]);
}
public function store(Request $request)
{
@@ -385,6 +385,8 @@ public function bulkAddMappings(Request $request, ImportTemplate $template)
'default_field' => 'nullable|string', // if provided, used as the field name for all entries
'apply_mode' => 'nullable|string|in:insert,update,both,keyref',
'transform' => 'nullable|string|in:trim,upper,lower',
'options' => 'nullable|array',
'group' => 'nullable|string|max:50', // convenience: will be wrapped into options.group
])->validate();
// Accept commas, semicolons, and newlines; strip surrounding quotes/apostrophes and whitespace
@@ -408,9 +410,18 @@ public function bulkAddMappings(Request $request, ImportTemplate $template)
$entity = $data['entity'] ?? null;
$defaultField = $data['default_field'] ?? null; // allows forcing a specific field for all
// Build options payload once
$opts = [];
if (isset($data['options']) && is_array($data['options'])) {
$opts = $data['options'];
}
if (! empty($data['group'])) {
$opts['group'] = (string) $data['group'];
}
$created = 0;
$updated = 0;
DB::transaction(function () use ($template, $list, $apply, $transform, $entity, $defaultField, $basePosition, &$created, &$updated) {
DB::transaction(function () use ($template, $list, $apply, $transform, $entity, $defaultField, $basePosition, $opts, &$created, &$updated) {
foreach ($list as $idx => $source) {
$targetField = null;
if ($defaultField) {
@@ -429,7 +440,7 @@ public function bulkAddMappings(Request $request, ImportTemplate $template)
'entity' => $entity ?? $existing->entity,
'transform' => $transform ?? $existing->transform,
'apply_mode' => $apply ?? $existing->apply_mode ?? 'both',
'options' => $existing->options,
'options' => empty($opts) ? $existing->options : $opts,
// keep existing position
]);
$updated++;
@@ -441,7 +452,7 @@ public function bulkAddMappings(Request $request, ImportTemplate $template)
'target_field' => $targetField,
'transform' => $transform,
'apply_mode' => $apply,
'options' => null,
'options' => empty($opts) ? null : $opts,
'position' => $basePosition + $idx + 1,
]);
$created++;
@@ -546,6 +557,10 @@ public function applyToImport(Request $request, ImportTemplate $template, Import
$rows = $template->mappings()->orderBy('position')->get();
foreach ($rows as $row) {
$options = $row->options;
if (is_array($options) || $options instanceof \JsonSerializable || $options instanceof \stdClass) {
$options = json_encode($options);
}
\DB::table('import_mappings')->insert([
'import_id' => $import->id,
'entity' => $row->entity,
@@ -553,7 +568,7 @@ public function applyToImport(Request $request, ImportTemplate $template, Import
'target_field' => $row->target_field,
'transform' => $row->transform,
'apply_mode' => $row->apply_mode ?? 'both',
'options' => $row->options,
'options' => $options,
'position' => $row->position ?? null,
'created_at' => now(),
'updated_at' => now(),
+45 -3
View File
@@ -18,9 +18,15 @@ public function index(Request $request)
->whereNull('cancelled_at')
->with([
'contract' => function ($q) {
$q->with(['type:id,name', 'account', 'clientCase.person' => function ($pq) {
$pq->with(['addresses', 'phones']);
}]);
$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')
@@ -29,6 +35,41 @@ public function index(Request $request)
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',
]);
}
@@ -136,6 +177,7 @@ public function showCase(\App\Models\ClientCase $clientCase, Request $request)
'account_types' => \App\Models\AccountType::all(),
'actions' => \App\Models\Action::with('decisions')->get(),
'activities' => $activities,
'completed_mode' => (bool) $request->boolean('completed'),
]);
}
}