GWM : Manual merge option
This commit is contained in:
parent
413180a565
commit
a2865f1096
@ -818,6 +818,7 @@ $routes->group("/ticket", ["filter" => "authMVC"], function ($routes) {
|
|||||||
$routes->get("getMoreInfo","TicketController::getMoreInfo");
|
$routes->get("getMoreInfo","TicketController::getMoreInfo");
|
||||||
$routes->post('upload_url',"TicketController::upload_url");
|
$routes->post('upload_url',"TicketController::upload_url");
|
||||||
$routes->post('getUrlDataByTicketId',"TicketController::getUrlDataByTicketId");
|
$routes->post('getUrlDataByTicketId',"TicketController::getUrlDataByTicketId");
|
||||||
|
$routes->post('manualMergeClaimFiles', 'TicketController::manualMergeClaimFiles');
|
||||||
$routes->post('uploadClaimFilesToTPA', 'TicketController::uploadClaimFilesToTPA');
|
$routes->post('uploadClaimFilesToTPA', 'TicketController::uploadClaimFilesToTPA');
|
||||||
$routes->get('remove_url',"TicketController::remove_url");
|
$routes->get('remove_url',"TicketController::remove_url");
|
||||||
$routes->get('fetchVehiclePolicy/(:any)','TicketController::fetchVehiclePolicy/$1');
|
$routes->get('fetchVehiclePolicy/(:any)','TicketController::fetchVehiclePolicy/$1');
|
||||||
|
|||||||
@ -3721,9 +3721,78 @@ class TicketController extends BaseController
|
|||||||
->where('is_active', 1)
|
->where('is_active', 1)
|
||||||
->findAll();
|
->findAll();
|
||||||
|
|
||||||
|
helper('merge_pdf');
|
||||||
|
$mergeUi = merge_ticket_manual_merge_status((int) $ticket_id);
|
||||||
|
|
||||||
return $this->response->setJSON([
|
return $this->response->setJSON([
|
||||||
'status' => true,
|
'status' => true,
|
||||||
'data' => $urlData
|
'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,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -86,13 +86,8 @@ if (! function_exists('merge_ticket_pdfs')) {
|
|||||||
|
|
||||||
$sourceFiles = [];
|
$sourceFiles = [];
|
||||||
foreach ($rows as $row) {
|
foreach ($rows as $row) {
|
||||||
$name = ! empty($row['url']) ? $row['url'] : ($row['file_name'] ?? '');
|
$full = merge_ticket_pdf_resolve_disk_path($row, $uploadDir);
|
||||||
if (empty($name)) {
|
if ($full !== null) {
|
||||||
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)) {
|
|
||||||
$mime = merge_ticket_pdf_resolve_mime($full, (string) ($row['mime_type'] ?? ''));
|
$mime = merge_ticket_pdf_resolve_mime($full, (string) ($row['mime_type'] ?? ''));
|
||||||
if (! in_array($mime, $opts['include_mime_types'], true)) {
|
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}");
|
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,
|
'id' => $row['id'] ?? null,
|
||||||
];
|
];
|
||||||
} else {
|
} 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';
|
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');
|
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')) {
|
if (! function_exists('merge_ticket_pdf_add_image_page')) {
|
||||||
/**
|
/**
|
||||||
* Add an uploaded image as a single PDF page, preserving portrait/landscape
|
* 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;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -103,6 +103,11 @@
|
|||||||
<h4 class="mb-0" style="position: relative;">File List</h4>
|
<h4 class="mb-0" style="position: relative;">File List</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 text-md-right mt-2 mt-md-0">
|
<div class="col-md-6 text-md-right mt-2 mt-md-0">
|
||||||
|
<button type="button" class="btn btn-warning waves-effect waves-light mr-2 d-none"
|
||||||
|
id="btn_manual_merge_claim_files"
|
||||||
|
title="Combine uploaded PDFs and images into one file">
|
||||||
|
Merge documents
|
||||||
|
</button>
|
||||||
<button type="button" class="btn btn-primary waves-effect waves-light"
|
<button type="button" class="btn btn-primary waves-effect waves-light"
|
||||||
id="btn_upload_claim_files_to_tpa">
|
id="btn_upload_claim_files_to_tpa">
|
||||||
Upload files to TPA
|
Upload files to TPA
|
||||||
@ -170,9 +175,18 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
let ticket_id = $('#ticket_master_id').val();
|
let ticket_id = getClaimFileListTicketId();
|
||||||
$('#ticket_id_url').val(ticket_id);
|
$('#ticket_id_url').val(ticket_id);
|
||||||
let urlData = getUrlDataByTicketId(ticket_id);
|
if (ticket_id) {
|
||||||
|
getUrlDataByTicketId(ticket_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('shown.bs.tab', 'a[href="#uploads-tab"], #uploads_tab', function () {
|
||||||
|
var ticket_id = getClaimFileListTicketId();
|
||||||
|
if (ticket_id) {
|
||||||
|
getUrlDataByTicketId(ticket_id);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function getClaimFileListTicketId() {
|
function getClaimFileListTicketId() {
|
||||||
@ -183,6 +197,88 @@
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveManualMergeUi(serverMergeUi, fileListData) {
|
||||||
|
if (serverMergeUi && serverMergeUi.show_manual_merge) {
|
||||||
|
return serverMergeUi;
|
||||||
|
}
|
||||||
|
if (!fileListData || !fileListData.length) {
|
||||||
|
return serverMergeUi || { show_manual_merge: false };
|
||||||
|
}
|
||||||
|
var hasMerged = fileListData.some(function (item) {
|
||||||
|
return item.file_type == 4 || item.file_type === '4';
|
||||||
|
});
|
||||||
|
var sourceCount = fileListData.filter(function (item) {
|
||||||
|
return item.file_type == 1 || item.file_type === '1'
|
||||||
|
|| item.file_type == 2 || item.file_type === '2';
|
||||||
|
}).length;
|
||||||
|
if (!hasMerged && sourceCount >= 1) {
|
||||||
|
return {
|
||||||
|
show_manual_merge: true,
|
||||||
|
button_label: 'Merge documents',
|
||||||
|
mergeable_count: sourceCount
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return serverMergeUi || { show_manual_merge: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateManualMergeButton(mergeUi, fileListData) {
|
||||||
|
var $btn = $('#btn_manual_merge_claim_files');
|
||||||
|
if (!$btn.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var resolved = resolveManualMergeUi(mergeUi, fileListData);
|
||||||
|
if (resolved && resolved.show_manual_merge) {
|
||||||
|
$btn.removeClass('d-none').css('display', 'inline-block');
|
||||||
|
$btn.text(resolved.button_label || 'Merge documents');
|
||||||
|
$btn.prop('disabled', false);
|
||||||
|
} else {
|
||||||
|
$btn.addClass('d-none').css('display', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).on('click', '#btn_manual_merge_claim_files', function () {
|
||||||
|
var ticket_id = getClaimFileListTicketId();
|
||||||
|
if (!ticket_id) {
|
||||||
|
toastr.warning('Ticket ID is missing. Please reload the page.', 'Validation');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var $btn = $(this);
|
||||||
|
$.ajax({
|
||||||
|
url: "<?= base_url('ticket/manualMergeClaimFiles') ?>",
|
||||||
|
type: "POST",
|
||||||
|
data: { ticket_id: ticket_id },
|
||||||
|
dataType: "json",
|
||||||
|
beforeSend: function () {
|
||||||
|
$btn.prop('disabled', true);
|
||||||
|
$('.loader').fadeIn();
|
||||||
|
$('.loader-mask').fadeIn();
|
||||||
|
},
|
||||||
|
success: function (res) {
|
||||||
|
if (res && res.status === true) {
|
||||||
|
toastr.success(res.message || 'Documents merged successfully', 'Success');
|
||||||
|
getUrlDataByTicketId(ticket_id);
|
||||||
|
} else {
|
||||||
|
toastr.error((res && res.message) ? res.message : 'Failed to merge documents', 'Error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (xhr) {
|
||||||
|
var msg = 'Failed to merge documents';
|
||||||
|
try {
|
||||||
|
var r = JSON.parse(xhr.responseText);
|
||||||
|
if (r.message) {
|
||||||
|
msg = r.message;
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
toastr.error(msg, 'Error');
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
$btn.prop('disabled', false);
|
||||||
|
$('.loader').fadeOut();
|
||||||
|
$('.loader-mask').delay(350).fadeOut('slow');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$(document).on('click', '#btn_upload_claim_files_to_tpa', function () {
|
$(document).on('click', '#btn_upload_claim_files_to_tpa', function () {
|
||||||
var ticket_id = getClaimFileListTicketId();
|
var ticket_id = getClaimFileListTicketId();
|
||||||
if (!ticket_id) {
|
if (!ticket_id) {
|
||||||
@ -395,10 +491,13 @@
|
|||||||
console.log('Form submitted response:', response);
|
console.log('Form submitted response:', response);
|
||||||
|
|
||||||
if (response.status === true) {
|
if (response.status === true) {
|
||||||
|
window._claimFilesMergeUi = response.merge_ui || null;
|
||||||
create_url_list(response.data);
|
create_url_list(response.data);
|
||||||
|
updateManualMergeButton(response.merge_ui, response.data);
|
||||||
addHTMLInput();
|
addHTMLInput();
|
||||||
return ;
|
return ;
|
||||||
} else {
|
} else {
|
||||||
|
updateManualMergeButton(null, []);
|
||||||
addHTMLInput();
|
addHTMLInput();
|
||||||
console.warn("No Data");
|
console.warn("No Data");
|
||||||
}
|
}
|
||||||
@ -555,6 +654,7 @@
|
|||||||
} else {
|
} else {
|
||||||
$('#table_bd').html('<tr><td colspan="5">No Data Found</td></tr>');
|
$('#table_bd').html('<tr><td colspan="5">No Data Found</td></tr>');
|
||||||
}
|
}
|
||||||
|
updateManualMergeButton(window._claimFilesMergeUi || null, data || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).on('click', '.delete-url', function (e) {
|
$(document).on('click', '.delete-url', function (e) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user