nhance/app/Views/docs/correction.php
2026-05-22 15:01:14 +05:30

266 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Correction (employee Excel upload) — content only
* app/Views/docs/correction.php
*
* Based on:
* - app/Views/employee_upload.php
* - app/Controllers/EmployeeServiceController.php
* (excelFileFormatValidation, excelFileDataValidation, employeesCorrectionProcess)
* - app/Controllers/EmployeeController.php (employeesUplodWithEvents)
* - app/Controllers/JobWorker.php
*/
?>
<p>
<strong>Correction</strong> updates existing member data on an active policy via Excel upload
(<code>files.action = correction</code>). The final step creates <strong>pending correction endorsements</strong>
on the <code>employees</code> table — data is not updated until those endorsements are applied downstream.
</p>
<p>
Processing is in <code>EmployeeServiceController::employeesCorrectionProcess</code>, queued after the same
format and data validation steps used for inception and deletion.
</p>
<h2 id="overview">Overview</h2>
<div class="mermaid-wrapper">
<div class="mermaid">
flowchart LR
A["Upload Excel action correction"] --> B["excelFileFormatValidation"]
B --> C["excelFileDataValidation"]
C --> D["employeesCorrectionProcess job"]
D --> E["emp_endorsement pending on employees"]
B -->|errors| F["files.status failed"]
C -->|errors| F
D -->|loop done| G["files.status success"]
</div>
</div>
<p><strong>In short:</strong></p>
<ul>
<li><strong>Step 1 — Format:</strong> 8 columns (AH); field must be one of four allowed names; dates <code>d-M-Y</code>.</li>
<li><strong>Step 2 — Data:</strong> Member must exist (emp code + name + active policy); code <strong>10</strong> if not found.</li>
<li><strong>Step 3 — Correction:</strong> One pending endorsement per row per field (skips duplicate pending corrections).</li>
<li>Each Excel row = one field change for one member (not a full-family operation).</li>
</ul>
<h2 id="key-files-routes">Key files and routes</h2>
<table>
<thead>
<tr><th>Area</th><th>Location</th></tr>
</thead>
<tbody>
<tr>
<td>UI</td>
<td><code>app/Views/employee_upload.php</code> — action <strong>Correction</strong></td>
</tr>
<tr>
<td>Upload</td>
<td><code>EmployeeController::employeesUplodWithEvents</code></td>
</tr>
<tr>
<td>Validation</td>
<td><code>excelFileFormatValidation</code>, <code>excelFileDataValidation</code></td>
</tr>
<tr>
<td>Correction process</td>
<td><code>EmployeeServiceController::employeesCorrectionProcess</code></td>
</tr>
<tr>
<td>Column config API</td>
<td><code>getCorrectionExcelColumns()</code> — used when building correction Excel programmatically</td>
</tr>
<tr>
<td>Job</td>
<td><code>employeesCorrectionProcess</code> in <code>JobWorker.php</code></td>
</tr>
<tr>
<td>Endorsements</td>
<td><code>EmpEndorsementModel</code> — <code>actions = c</code>, <code>table_name = employees</code>, <code>status = pending</code></td>
</tr>
</tbody>
</table>
<p><strong>Routes</strong> (group <code>/employee</code>, <code>authMVC</code>):</p>
<ul>
<li><code>GET /employee/upload</code> — upload screen</li>
<li><code>POST /employee/upload</code> — <code>upload-action-type=correction</code></li>
<li><code>GET /employee/excel_error/{file_id}</code> — validation errors</li>
</ul>
<div class="callout info">
<span>i</span>
<div>
<strong><code>files.policy_id</code></strong> is the client policy id. Lookup requires active
<code>employees</code> + <code>employee_polices</code> on that policy and branch.
</div>
</div>
<h2 id="sync-vs-jobs">Sync vs background jobs</h2>
<table>
<thead>
<tr><th>Step</th><th>&lt; 1 MB</th><th>≥ 1 MB</th></tr>
</thead>
<tbody>
<tr><td>Format validation</td><td>Inline on upload</td><td>Job <code>excelFileFormatValidation</code></td></tr>
<tr><td>Data validation</td><td>Job <code>excelFileDataValidation</code></td><td>Same</td></tr>
<tr><td>Correction process</td><td>Job <code>employeesCorrectionProcess</code></td><td>Same</td></tr>
</tbody>
</table>
<h2 id="format-validation">Step 1: excelFileFormatValidation</h2>
<ul>
<li>Uses <code>$correction_excel_columns</code> — <strong>8 columns (AH)</strong>.</li>
<li>Action code <code>C</code> for mandatory rules on correction-specific columns.</li>
<li><strong>Field</strong> (column D): only <code>name</code>, <code>dob</code>, <code>relationship</code>, <code>email_corporate</code>.</li>
<li><strong>Date of Correction</strong> (F): <code>d-M-Y</code>.</li>
<li><strong>Change event</strong> (G) and <strong>Value</strong> (E) are mandatory.</li>
</ul>
<h3 id="format-errors">Format error codes</h3>
<table>
<thead>
<tr><th>Code</th><th>Meaning</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>Mandatory missing</td></tr>
<tr><td>2</td><td>Wrong format</td></tr>
<tr><td>3</td><td>Not in allowed list (e.g. invalid Field value)</td></tr>
<tr><td>4</td><td>Custom validation failed</td></tr>
<tr><td>5</td><td>File / policy problem</td></tr>
<tr><td>6</td><td>Column headers wrong</td></tr>
</tbody>
</table>
<h2 id="data-validation">Step 2: excelFileDataValidation</h2>
<p>Rows grouped by EMP ID; for correction the critical check is <code>name_and_empid_check_in_db</code>:</p>
<ul>
<li>Each row must match an active employee on the uploaded policy (emp code + name).</li>
<li>Not found → error code <strong>10</strong> (“Record Not found”).</li>
</ul>
<p>On success → queues <code>employeesCorrectionProcess</code> (with optional <code>batch_file_id</code> for TPA multi-file flows).</p>
<h2 id="correction-process">Step 3: employeesCorrectionProcess</h2>
<div class="mermaid-wrapper">
<div class="mermaid">
flowchart TD
A["Read each Excel row"] --> B["Match emp_code plus name on active policy"]
B --> C{"Pending correction for same field?"}
C -->|Yes| D["Skip row"]
C -->|No| E["Insert emp_endorsement actions c"]
E --> F["old_value from DB new_value from Excel"]
</div>
</div>
<p><strong>Per row:</strong></p>
<ul>
<li><code>field_name</code> ← column D (<code>name</code>, <code>dob</code>, <code>relationship</code>, <code>email_corporate</code>)</li>
<li><code>new_value</code> ← column E; if field is <code>dob</code>, converted from <code>d-M-Y</code> to <code>Y-m-d</code></li>
<li><code>date_of_correction</code> ← column F (converted to <code>Y-m-d</code>)</li>
<li><code>remarks</code> ← column H (optional)</li>
<li><code>old_value</code> ← current value from <code>employees.{field_name}</code></li>
</ul>
<p>
Skips insert when a pending correction endorsement already exists for the same
<code>emp_code</code>, <code>name</code>, and <code>field_name</code>
(<code>actions = c</code>, <code>endorsement_id IS NULL</code>, <code>status != truncated</code>).
</p>
<p>
Sets <code>files.status = success</code> when the loop completes and sends a success pull notification.
Rows with no DB match are not endorsed (no row-level failure on the file record).
</p>
<p>
<strong>TPA batch:</strong> If <code>batch_file_id</code> is set, also queues
<code>updateEmployeeDataFromTpa</code>, <code>reconTpaApiDataWithEmployeepolicies</code>, and
<code>initializeDeletionProcessForTpaApiData</code>.
</p>
<h2 id="excel-columns">Correction Excel columns</h2>
<table>
<thead>
<tr><th>Col</th><th>Header</th><th>Required</th><th>Notes</th></tr>
</thead>
<tbody>
<tr><td>A</td><td>S.No</td><td>Yes</td><td></td></tr>
<tr><td>B</td><td>EMP ID</td><td>Yes</td><td></td></tr>
<tr><td>C</td><td>NAME OF EMP/DEP</td><td>Yes</td><td>Must match DB before correction</td></tr>
<tr><td>D</td><td>Field</td><td>Yes</td><td><code>name</code>, <code>dob</code>, <code>relationship</code>, <code>email_corporate</code></td></tr>
<tr><td>E</td><td>Value</td><td>Yes</td><td>New value; DOB as <code>d-M-Y</code></td></tr>
<tr><td>F</td><td>Date of Correction</td><td>Yes</td><td><code>d-M-Y</code></td></tr>
<tr><td>G</td><td>Change event</td><td>Yes</td><td>e.g. <code>correction</code></td></tr>
<tr><td>H</td><td>Remarks</td><td>No</td><td>Stored on endorsement</td></tr>
</tbody>
</table>
<h2 id="row-example">Row layout examples</h2>
<p><strong>Fix DOB</strong> — one row, one field:</p>
<table>
<thead>
<tr><th>EMP ID</th><th>NAME</th><th>Field</th><th>Value</th><th>Date of Correction</th><th>Change event</th><th>Remarks</th></tr>
</thead>
<tbody>
<tr>
<td>EMP001</td>
<td>Raj Kumar</td>
<td>dob</td>
<td>15-Jan-1985</td>
<td>19-May-2026</td>
<td>correction</td>
<td>Typo in upload</td>
</tr>
</tbody>
</table>
<p><strong>Multiple fixes</strong> — use separate rows (same or different members):</p>
<table>
<thead>
<tr><th>EMP ID</th><th>NAME</th><th>Field</th><th>Value</th></tr>
</thead>
<tbody>
<tr><td>EMP001</td><td>Raj Kumar</td><td>email_corporate</td><td>raj.kumar@company.com</td></tr>
<tr><td>EMP001</td><td>Priya Kumar</td><td>relationship</td><td>Spouse</td></tr>
</tbody>
</table>
<h2 id="developer-steps">Developer steps</h2>
<ol>
<li>Upload with <code>upload-action-type=correction</code>; note <code>file_id</code>.</li>
<li>On validation failure, check <code>/employee/excel_error/{file_id}</code> for code <strong>10</strong>.</li>
<li>After success, query <code>emp_endorsement</code> where <code>file_id</code> = upload id, <code>actions = 'c'</code>, <code>status = 'pending'</code>.</li>
<li>Compare <code>field_name</code>, <code>old_value</code>, <code>new_value</code> per row to the Excel.</li>
<li>To generate correction Excel in code, use <code>getCorrectionExcelColumns()</code> for header layout.</li>
</ol>
<h2 id="pitfalls">Common pitfalls</h2>
<ul>
<li><strong>Name must match DB</strong> — correction identifies the member by current <code>emp_code</code> + <code>name</code>; rename via a <code>name</code> field row uses the old name in column C.</li>
<li><strong>Only four fields</strong> — mobile, SI, band, etc. are not supported in this upload path.</li>
<li><strong>Duplicate pending correction</strong> — second upload for the same field is skipped until the first endorsement is processed or truncated.</li>
<li><strong>File success vs rows</strong> — <code>files.status = success</code> does not mean every row created an endorsement.</li>
<li><strong>Not live update</strong> — <code>employees</code> columns change only after endorsement approval/application.</li>
</ul>
<p>
Related:
<a href="<?= base_url('docs/inception') ?>">Inception</a>,
<a href="<?= base_url('docs/deletion') ?>">Deletion</a>.
</p>