FIX_CLAIM_STATUS_MISS_MATCH

This commit is contained in:
VENKATESHWARAN 2026-05-26 14:28:37 +05:30
parent 5dc49f7108
commit 998a74906d
2 changed files with 190 additions and 3 deletions

View File

@ -968,6 +968,58 @@ class TicketController extends BaseController
return $extra_fields;
}
/**
* Overlay conditional `required` rules onto a base validation rule-set based on the
* submitted `claim_status_id`. For example, when claim_status_id is a "Settled" status
* (11/24/34/44), fields like `utr_details` and `settled_date` are promoted from
* `permit_empty` to `required` so the request is rejected when they are blank.
*
* Letter URL fields (`approved_letter`, `settle_letter`) accept an alternative PDF
* upload, so they are intentionally not promoted here; that pairing is enforced by
* the upload validation flow. `approved_description` stays optional to match the
* existing UI contract.
*/
private function applyClaimStatusConditionalRules(array $rules): array
{
$claimStatusId = (int) $this->request->getPost('claim_status_id');
if ($claimStatusId <= 0) {
return $rules;
}
if (!isset($this->extraFields[$claimStatusId]) || !is_array($this->extraFields[$claimStatusId])) {
return $rules;
}
$requiredFields = $this->extraFields[$claimStatusId];
$skipFields = ['approved_letter', 'settle_letter', 'approved_description'];
foreach ($requiredFields as $field) {
if (in_array($field, $skipFields, true) || !isset($rules[$field])) {
continue;
}
$existingRules = $rules[$field]['rules'] ?? '';
$parts = $existingRules === ''
? []
: array_values(array_filter(array_map('trim', explode('|', $existingRules)), function ($part) {
return $part !== '' && $part !== 'permit_empty';
}));
if (!in_array('required', $parts, true)) {
array_unshift($parts, 'required');
}
$rules[$field]['rules'] = implode('|', array_unique($parts));
if (!isset($rules[$field]['errors']) || !is_array($rules[$field]['errors'])) {
$rules[$field]['errors'] = [];
}
$label = $rules[$field]['label'] ?? ucwords(str_replace('_', ' ', $field));
$rules[$field]['errors']['required'] = $label . ' is required for the selected claim status.';
}
return $rules;
}
public function view_ticket($ticket_id)
{
// $ticket_data = $this->ticketMasterModel->where('id', $ticket_id)->where('is_active', 1)->first();
@ -1456,6 +1508,8 @@ class TicketController extends BaseController
];
}
$rules = $this->applyClaimStatusConditionalRules($rules);
if (!$this->validate($rules)) {
return $this->response->setStatusCode(400)->setJSON([
'status' => false,
@ -1944,6 +1998,9 @@ class TicketController extends BaseController
'return_remark' => ['label' => 'Return Remark','rules' => 'permit_empty','errors' => []],
];
}
$rules = $this->applyClaimStatusConditionalRules($rules);
if (!$this->validate($rules)) {
return $this->response->setStatusCode(400)->setJSON([
'status' => false,
@ -3053,7 +3110,7 @@ class TicketController extends BaseController
}
}
public function getLastMatchedStatus($incoming_form_values, $old_ticket_data)
public function getLastMatchedStatusOld($incoming_form_values, $old_ticket_data)
{
if (empty($incoming_form_values) || !isset($incoming_form_values['claim_status_id']) || !isset($incoming_form_values['extra_fields_array_for_validate'])) {
return null;
@ -3122,6 +3179,71 @@ class TicketController extends BaseController
return $lastMatchedStatus;
}
public function getLastMatchedStatus($incoming_form_values, $old_ticket_data)
{
// Preserve the incoming claim_status_id (if any) as the safe fallback so callers
// never accidentally nullify the status when validation inputs are missing.
$incomingStatus = $incoming_form_values['claim_status_id'] ?? null;
if (empty($incoming_form_values) || !isset($incoming_form_values['extra_fields_array_for_validate'])) {
return $incomingStatus;
}
$lastMatchedStatus = $incomingStatus;
$statusMapping = json_decode($incoming_form_values['extra_fields_array_for_validate'], true);
if (!is_array($statusMapping) || empty($statusMapping)) {
return $incomingStatus;
}
// Drop transitional / aggregate statuses that should never be auto-selected.
$removeKeys = is_array($this->removeArrayKey) ? $this->removeArrayKey : [];
$statusMapping = array_diff_key($statusMapping, $removeKeys);
$oldStatusId = is_array($old_ticket_data) ? ($old_ticket_data['claim_status_id'] ?? null) : null;
$skipFields = ['approved_description'];
foreach ($statusMapping as $status => $requiredFields) {
if (empty($requiredFields)) {
continue;
}
// Skip the current/old status — we only advance forward to a newer status.
if ($oldStatusId !== null && (int) $status === (int) $oldStatusId) {
continue;
}
if (!is_array($requiredFields)) {
$requiredFields = [$requiredFields];
}
$allFieldsMatched = true;
foreach ($requiredFields as $field) {
if (in_array($field, $skipFields, true)) {
continue;
}
if (!isset($incoming_form_values[$field]) || $incoming_form_values[$field] === '' || $incoming_form_values[$field] === null) {
$allFieldsMatched = false;
break;
}
}
if ($allFieldsMatched) {
$lastMatchedStatus = $status;
}
}
// When a TPA number is present, promote the base "registered" statuses
// (1 -> 2 for standard, 67 -> 68 for the alternate flow).
if (!empty($incoming_form_values['tpa_no']) && in_array((int) $lastMatchedStatus, [1, 67], true)) {
$lastMatchedStatus = ((int) $lastMatchedStatus === 1) ? 2 : 68;
}
return $lastMatchedStatus;
}
public function getPolicyStartDate()
{

View File

@ -579,6 +579,42 @@
var doa;
var STATUS_SECTION_CLASSES = ['cda_ir', 'settled', 'approved', 'rejected', 'up_qdr', 'up_cnu', 'canceled', 'returned', 'payment', 'non_id'];
var statusSectionInitialValues = {};
// Cached full mapping of claim_status_id -> required fields.
// The hidden input gets destructively reduced when the status dropdown changes,
// so we capture the full map once at load time for use by frontend required-logic.
var STATUS_REQUIRED_FIELDS_MAP = {};
function initStatusRequiredFieldsMap() {
var raw = $('#extra_fields_array_for_validate').val();
if (!raw) {
STATUS_REQUIRED_FIELDS_MAP = {};
return;
}
try {
var parsed = JSON.parse(raw);
STATUS_REQUIRED_FIELDS_MAP = (parsed && typeof parsed === 'object') ? parsed : {};
} catch (e) {
STATUS_REQUIRED_FIELDS_MAP = {};
}
}
function getRequiredFieldsForSelectedStatus() {
if (!STATUS_REQUIRED_FIELDS_MAP) {
return [];
}
var selected = $('#claim_status_id').val();
if (selected === undefined || selected === null || selected === '') {
return [];
}
var fields = STATUS_REQUIRED_FIELDS_MAP[selected];
if (Array.isArray(fields)) {
return fields;
}
if (fields) {
return [fields];
}
return [];
}
function captureSectionInitialValues(sectionClass) {
if (!sectionClass) {
@ -656,12 +692,40 @@
return;
}
if (sectionClass === 'approved' || sectionClass === 'settled') {
// The URL-or-File letter pair has its own validity rules (see enforceLetterPairRules).
// We still need to enforce required on the other status-mandated fields
// (e.g. utr_details, settled_date, approved_amount, approved_date), which the
// previous early-return was skipping.
enforceLetterPairRules();
updateSectionRequiredLabels(sectionClass, hasSectionChanged(sectionClass));
var letterPairIds = sectionClass === 'approved'
? ['approved_letter', 'approved_letter_file', 'approved_description']
: ['settle_letter', 'settle_letter_file'];
var statusRequiredFields = getRequiredFieldsForSelectedStatus();
var sectionChanged = hasSectionChanged(sectionClass);
$('.' + sectionClass).find('input, textarea, select').each(function () {
var id = this.id;
if (!id || letterPairIds.indexOf(id) !== -1) {
return;
}
var statusRequires = statusRequiredFields.indexOf(id) !== -1;
$(this).prop('required', statusRequires || sectionChanged);
});
var statusMandatesSection = false;
for (var i = 0; i < statusRequiredFields.length; i++) {
if ($('.' + sectionClass + ' #' + statusRequiredFields[i]).length > 0) {
statusMandatesSection = true;
break;
}
}
updateSectionRequiredLabels(sectionClass, sectionChanged || statusMandatesSection);
return;
}
var changed = hasSectionChanged(sectionClass);
$('.' + sectionClass).find('input, textarea, select').each(function() {
$('.' + sectionClass).find('input, textarea, select').each(function () {
if (this.id === 'approved_description') {
return;
}
@ -738,6 +802,7 @@
allowInput: false
});
initStatusRequiredFieldsMap();
updateClaimStatusDisplay("<?= isset($ticket_data['claim_status_id']) ? $ticket_data['claim_status_id'] : 0 ?>")
var extraFields = <?= json_encode(isset($extra_fields) ? $extra_fields : []); ?>;
GlobelExtraFields = extraFields;