Changes to import and notifications

This commit is contained in:
Simon Pocrnjič
2025-10-13 21:14:10 +02:00
parent 0bbed64542
commit 79b3e20b02
28 changed files with 2173 additions and 438 deletions
+114
View File
@@ -146,6 +146,7 @@ public function store(Request $request)
'size' => $file->getSize(),
'sheet_name' => $validated['sheet_name'] ?? null,
'status' => 'uploaded',
'show_missing' => false,
'meta' => [
'has_header' => $validated['has_header'] ?? true,
],
@@ -155,6 +156,7 @@ public function store(Request $request)
'id' => $import->id,
'uuid' => $import->uuid,
'status' => $import->status,
'show_missing' => (bool) ($import->show_missing ?? false),
]);
}
@@ -354,6 +356,116 @@ public function getMappings(Import $import)
return response()->json(['mappings' => $rows]);
}
/**
* List active, non-archived contracts for the import's client that are NOT present
* in the processed import file (based on mapped contract.reference values).
* Only available when contract.reference mapping apply_mode is 'keyref'.
*/
public function missingContracts(Import $import)
{
// Ensure client context is available
if (empty($import->client_id)) {
return response()->json(['error' => 'Import has no client bound.'], 422);
}
// Respect optional feature flag on import
if (! (bool) ($import->show_missing ?? false)) {
return response()->json(['error' => 'Missing contracts listing is disabled for this import.'], 422);
}
// Check that this import's mappings set contract.reference to keyref mode
$mappings = \DB::table('import_mappings')
->where('import_id', $import->id)
->get(['target_field', 'apply_mode']);
$isKeyref = false;
foreach ($mappings as $map) {
$tf = strtolower((string) ($map->target_field ?? ''));
$am = strtolower((string) ($map->apply_mode ?? ''));
if (in_array($tf, ['contract.reference', 'contracts.reference'], true) && $am === 'keyref') {
$isKeyref = true;
break;
}
}
if (! $isKeyref) {
return response()->json(['error' => 'Missing contracts are only available for keyref mapping on contract.reference.'], 422);
}
// Collect referenced contract references from processed rows
$present = [];
foreach (\App\Models\ImportRow::query()->where('import_id', $import->id)->get(['mapped_data']) as $row) {
$md = $row->mapped_data ?? [];
if (is_array($md) && isset($md['contract']['reference'])) {
$ref = (string) $md['contract']['reference'];
if ($ref !== '') {
$present[] = preg_replace('/\s+/', '', trim($ref));
}
}
}
$present = array_values(array_unique(array_filter($present)));
// Query active, non-archived contracts for this client that were not in import
// Include person full_name (owner of the client case) and aggregate active accounts' balance_amount
$contractsQ = \App\Models\Contract::query()
->join('client_cases', 'contracts.client_case_id', '=', 'client_cases.id')
->join('person', 'person.id', '=', 'client_cases.person_id')
->leftJoin('accounts', function ($join) {
$join->on('accounts.contract_id', '=', 'contracts.id')
->where('accounts.active', 1);
})
->where('client_cases.client_id', $import->client_id)
->where('contracts.active', 1)
->whereNull('contracts.deleted_at')
->when(count($present) > 0, function ($q) use ($present) {
$q->whereNotIn('contracts.reference', $present);
})
->groupBy('contracts.uuid', 'contracts.reference', 'client_cases.uuid', 'person.full_name')
->orderBy('contracts.reference')
->get([
'contracts.uuid as uuid',
'contracts.reference as reference',
'client_cases.uuid as case_uuid',
'person.full_name as full_name',
\DB::raw('COALESCE(SUM(accounts.balance_amount), 0) as balance_amount'),
]);
return response()->json([
'missing' => $contractsQ,
'count' => $contractsQ->count(),
]);
}
/**
* Update import options (e.g., booleans like show_missing, reactivate) from the UI.
*/
public function updateOptions(Request $request, Import $import)
{
$data = $request->validate([
'show_missing' => 'nullable|boolean',
'reactivate' => 'nullable|boolean',
]);
$payload = [];
if (array_key_exists('show_missing', $data)) {
$payload['show_missing'] = (bool) $data['show_missing'];
}
if (array_key_exists('reactivate', $data)) {
$payload['reactivate'] = (bool) $data['reactivate'];
}
if (! empty($payload)) {
$import->update($payload);
}
return response()->json([
'ok' => true,
'import' => [
'id' => $import->id,
'uuid' => $import->uuid,
'show_missing' => (bool) ($import->show_missing ?? false),
'reactivate' => (bool) ($import->reactivate ?? false),
],
]);
}
// Fetch recent import events (logs) for an import
public function getEvents(Import $import)
{
@@ -533,6 +645,8 @@ public function show(Import $import)
'client_id' => $import->client_id,
'client_uuid' => optional($client)->uuid,
'import_template_id' => $import->import_template_id,
'show_missing' => (bool) ($import->show_missing ?? false),
'reactivate' => (bool) ($import->reactivate ?? false),
'total_rows' => $import->total_rows,
'imported_rows' => $import->imported_rows,
'invalid_rows' => $import->invalid_rows,