From a2865f1096523c92598952df9276a0d15e4eafad Mon Sep 17 00:00:00 2001 From: Gowtham M Date: Mon, 18 May 2026 16:40:05 +0530 Subject: [PATCH] GWM : Manual merge option --- app/Config/Routes.php | 1 + app/Controllers/TicketController.php | 73 ++++++++++++++- app/Helpers/merge_pdf_helper.php | 135 +++++++++++++++++++++++++-- app/Views/claim_files_upload.php | 104 ++++++++++++++++++++- 4 files changed, 301 insertions(+), 12 deletions(-) diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 74dddbef..55fa525f 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -818,6 +818,7 @@ $routes->group("/ticket", ["filter" => "authMVC"], function ($routes) { $routes->get("getMoreInfo","TicketController::getMoreInfo"); $routes->post('upload_url',"TicketController::upload_url"); $routes->post('getUrlDataByTicketId',"TicketController::getUrlDataByTicketId"); + $routes->post('manualMergeClaimFiles', 'TicketController::manualMergeClaimFiles'); $routes->post('uploadClaimFilesToTPA', 'TicketController::uploadClaimFilesToTPA'); $routes->get('remove_url',"TicketController::remove_url"); $routes->get('fetchVehiclePolicy/(:any)','TicketController::fetchVehiclePolicy/$1'); diff --git a/app/Controllers/TicketController.php b/app/Controllers/TicketController.php index bcfb183a..6addab9a 100644 --- a/app/Controllers/TicketController.php +++ b/app/Controllers/TicketController.php @@ -3721,9 +3721,78 @@ class TicketController extends BaseController ->where('is_active', 1) ->findAll(); + helper('merge_pdf'); + $mergeUi = merge_ticket_manual_merge_status((int) $ticket_id); + return $this->response->setJSON([ - 'status' => true, - 'data' => $urlData + 'status' => true, + 'data' => $urlData, + 'merge_ui' => $mergeUi, + ]); + } + + /** + * Manually merge claim PDF/image files for a ticket (Claim Files tab). + */ + public function manualMergeClaimFiles() + { + $ticket_id = (int) $this->request->getPost('ticket_id'); + + if ($ticket_id <= 0) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'Ticket ID is required', + ]); + } + + helper('merge_pdf'); + + $mergeUi = merge_ticket_manual_merge_status($ticket_id); + if (! $mergeUi['show_manual_merge'] && $mergeUi['mergeable_count'] < 1) { + return $this->response->setStatusCode(400)->setJSON([ + 'status' => false, + 'message' => 'No PDF or image files available on disk to merge.', + ]); + } + + $ticket = $this->ticketMasterModel + ->select('id, ticket_type_id') + ->where('id', $ticket_id) + ->where('is_active', 1) + ->first(); + + if (! $ticket) { + return $this->response->setStatusCode(404)->setJSON([ + 'status' => false, + 'message' => 'Claim not found.', + ]); + } + + try { + $result = merge_ticket_pdfs($ticket_id, [ + 'ticket_type' => (int) ($ticket['ticket_type_id'] ?? 1), + 'created_by' => function_exists('get_session_userid') ? get_session_userid() : null, + ]); + } catch (\Throwable $e) { + log_message('error', 'TicketController::manualMergeClaimFiles | ticket_id=' . $ticket_id . ' | ' . $e->getMessage()); + return $this->response->setStatusCode(500)->setJSON([ + 'status' => false, + 'message' => 'Merge failed: ' . $e->getMessage(), + ]); + } + + if (! ($result['status'] ?? false)) { + return $this->response->setJSON([ + 'status' => false, + 'message' => $result['message'] ?? 'Merge failed. Check logs for details.', + 'data' => $result, + ]); + } + + return $this->response->setJSON([ + 'status' => true, + 'message' => $result['message'] ?? 'Documents merged successfully.', + 'data' => $result, ]); } diff --git a/app/Helpers/merge_pdf_helper.php b/app/Helpers/merge_pdf_helper.php index 1751661f..c222289c 100644 --- a/app/Helpers/merge_pdf_helper.php +++ b/app/Helpers/merge_pdf_helper.php @@ -86,13 +86,8 @@ if (! function_exists('merge_ticket_pdfs')) { $sourceFiles = []; foreach ($rows as $row) { - $name = ! empty($row['url']) ? $row['url'] : ($row['file_name'] ?? ''); - if (empty($name)) { - continue; - } - // url column may sometimes hold a full URL; we only care about the file basename on disk. - $full = $uploadDir . basename($name); - if (is_file($full) && is_readable($full)) { + $full = merge_ticket_pdf_resolve_disk_path($row, $uploadDir); + if ($full !== null) { $mime = merge_ticket_pdf_resolve_mime($full, (string) ($row['mime_type'] ?? '')); if (! in_array($mime, $opts['include_mime_types'], true)) { log_message('error', "merge_ticket_pdfs | unsupported source mime {$mime} | claim_file_id={$row['id']} | path={$full}"); @@ -105,7 +100,8 @@ if (! function_exists('merge_ticket_pdfs')) { 'id' => $row['id'] ?? null, ]; } else { - log_message('error', "merge_ticket_pdfs | missing file on disk | claim_file_id={$row['id']} | path={$full}"); + $name = ! empty($row['url']) ? $row['url'] : ($row['file_name'] ?? ''); + log_message('error', "merge_ticket_pdfs | missing file on disk | claim_file_id={$row['id']} | path=" . $uploadDir . basename((string) $name)); } } @@ -340,10 +336,50 @@ if (! function_exists('merge_ticket_pdf_resolve_mime')) { return 'image/png'; } + if (in_array($detectedMime, ['application/octet-stream', 'binary/octet-stream'], true)) { + if ($ext === 'pdf') { + return 'application/pdf'; + } + if (in_array($ext, ['jpg', 'jpeg'], true)) { + return 'image/jpeg'; + } + if ($ext === 'png') { + return 'image/png'; + } + } + return $detectedMime ?: ($storedMime ?: 'application/octet-stream'); } } +if (! function_exists('merge_ticket_pdf_resolve_disk_path')) { + /** + * Resolve on-disk path for a claim_files row (url and/or file_name). + */ + function merge_ticket_pdf_resolve_disk_path(array $row, string $uploadDir): ?string + { + $candidates = []; + if (! empty($row['url'])) { + $candidates[] = basename((string) $row['url']); + } + if (! empty($row['file_name'])) { + $candidates[] = basename((string) $row['file_name']); + } + + foreach (array_unique($candidates) as $name) { + if ($name === '' || preg_match('#^https?://#i', $name)) { + continue; + } + $full = $uploadDir . $name; + if (is_file($full) && is_readable($full)) { + return $full; + } + } + + return null; + } +} + if (! function_exists('merge_ticket_pdf_add_image_page')) { /** * Add an uploaded image as a single PDF page, preserving portrait/landscape @@ -397,3 +433,86 @@ if (! function_exists('merge_ticket_pdf_add_image_page')) { return true; } } + +if (! function_exists('merge_ticket_manual_merge_status')) { + /** + * UI/status helper: whether manual merge should be offered on Claim Files tab. + * + * @return array{ + * has_merged_file: bool, + * mergeable_count: int, + * show_manual_merge: bool, + * button_label: string + * } + */ + function merge_ticket_manual_merge_status(int $ticket_master_id, array $opts = []): array + { + $opts += [ + 'include_file_types' => [1, 2], + 'include_mime_types' => ['application/pdf', 'image/jpeg', 'image/png'], + ]; + + $status = [ + 'has_merged_file' => false, + 'mergeable_count' => 0, + 'show_manual_merge' => false, + 'button_label' => 'Merge documents', + ]; + + if ($ticket_master_id <= 0) { + return $status; + } + + $claimFiles = new ClaimFilesModel(); + $rows = $claimFiles + ->where('ticket_id', $ticket_master_id) + ->where('is_active', 1) + ->whereIn('file_type', array_merge($opts['include_file_types'], [MERGED_CLAIM_FILE_TYPE])) + ->orderBy('id', 'ASC') + ->findAll(); + + $uploadDir = rtrim(WRITEPATH, '/\\') . DIRECTORY_SEPARATOR + . 'uploads' . DIRECTORY_SEPARATOR + . 'claim_files' . DIRECTORY_SEPARATOR; + + $mergeableCount = 0; + $sourceRowCount = 0; + foreach ($rows as $row) { + if ((int) ($row['file_type'] ?? 0) === MERGED_CLAIM_FILE_TYPE) { + $status['has_merged_file'] = true; + continue; + } + + if (! in_array((int) ($row['file_type'] ?? 0), $opts['include_file_types'], true)) { + continue; + } + + $sourceRowCount++; + + $full = merge_ticket_pdf_resolve_disk_path($row, $uploadDir); + if ($full === null) { + continue; + } + + $mime = merge_ticket_pdf_resolve_mime($full, (string) ($row['mime_type'] ?? '')); + if (in_array($mime, $opts['include_mime_types'], true)) { + $mergeableCount++; + } + } + + $status['mergeable_count'] = $mergeableCount; + + // Show manual merge when there is no merged file but user has uploaded docs in the list. + if (! $status['has_merged_file']) { + if ($mergeableCount >= 1 || $sourceRowCount >= 2) { + $status['show_manual_merge'] = true; + $status['button_label'] = 'Merge documents'; + } + } elseif ($mergeableCount >= 2) { + $status['show_manual_merge'] = true; + $status['button_label'] = 'Re-merge documents'; + } + + return $status; + } +} diff --git a/app/Views/claim_files_upload.php b/app/Views/claim_files_upload.php index 6ea03e37..c444773d 100644 --- a/app/Views/claim_files_upload.php +++ b/app/Views/claim_files_upload.php @@ -103,6 +103,11 @@

File List

+