266 lines
10 KiB
PHP
266 lines
10 KiB
PHP
<?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 (A–H); 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>< 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 (A–H)</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>
|