FIX_DIAGONSIS_COMMENTS
This commit is contained in:
parent
e30c17ae37
commit
bf2908723a
@ -81,7 +81,11 @@ class HrLoginDiagnoseController extends AdminController
|
||||
'HR_NOT_FOUND',
|
||||
'high',
|
||||
'No active HR found in post level_contacts for the given email/mobile (contact_type=client).',
|
||||
'Create/activate the HR contact under the correct client branch, or verify the email/mobile.'
|
||||
[
|
||||
'Option A: Verify email/mobile spelling and that level_contacts.contact_type = client and is_active = 1.',
|
||||
'Option B: Create/activate the HR contact under the correct client_branch (ref_id = branch id).',
|
||||
'Option C: If HR exists only in pre DB, create the matching post level_contacts row first.',
|
||||
]
|
||||
);
|
||||
|
||||
return [
|
||||
@ -89,6 +93,7 @@ class HrLoginDiagnoseController extends AdminController
|
||||
'overall_status' => 'FAIL',
|
||||
'summary' => 'HR not found in post DB.',
|
||||
'issues' => $issues,
|
||||
'problems' => $issues,
|
||||
'post' => ['contacts' => []],
|
||||
'hr_access_control'=> [],
|
||||
'pre' => ['reachable' => null, 'mappings' => []],
|
||||
@ -102,6 +107,7 @@ class HrLoginDiagnoseController extends AdminController
|
||||
$accessRows = [];
|
||||
$preMaps = [];
|
||||
$loginCards = [];
|
||||
$pairRows = [];
|
||||
$preReachable = null;
|
||||
|
||||
try {
|
||||
@ -115,7 +121,11 @@ class HrLoginDiagnoseController extends AdminController
|
||||
'PRE_DB_UNREACHABLE',
|
||||
'high',
|
||||
'Could not connect to preDB: ' . $e->getMessage(),
|
||||
'Check preDB credentials in Database config / .env.'
|
||||
[
|
||||
'Option A: Check preDB hostname/database/username/password in app/Config/Database.php or .env.',
|
||||
'Option B: Confirm pre DB server is reachable from this host (network/firewall).',
|
||||
'Option C: Re-run diagnose after connectivity is restored to validate PRE mapping.',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@ -130,16 +140,24 @@ class HrLoginDiagnoseController extends AdminController
|
||||
$issues[] = $this->issue(
|
||||
'BRANCH_INACTIVE',
|
||||
'high',
|
||||
"Branch inactive for post_hr_id={$contact['post_hr_id']} (branch #{$contact['post_branch_id']}).",
|
||||
'Activate client_branch.is_active=1 for this branch.'
|
||||
"Branch inactive for post_hr_id={$contact['post_hr_id']} (branch #{$contact['post_branch_id']}, {$contact['branch_name']}).",
|
||||
[
|
||||
"Option A: UPDATE client_branch SET is_active=1 WHERE id={$contact['post_branch_id']};",
|
||||
'Option B: In Client Onboarding, activate this branch and re-check login.',
|
||||
'Note: Login join requires client_branch.is_active=1.',
|
||||
]
|
||||
);
|
||||
}
|
||||
if (!$flags['CLIENT_ACTIVE']) {
|
||||
$issues[] = $this->issue(
|
||||
'CLIENT_INACTIVE',
|
||||
'high',
|
||||
"Client inactive for post_hr_id={$contact['post_hr_id']} (client #{$contact['post_client_id']}).",
|
||||
'Activate clients.is_active=1 for this client.'
|
||||
"Client inactive for post_hr_id={$contact['post_hr_id']} (client #{$contact['post_client_id']}, {$contact['client_name']}).",
|
||||
[
|
||||
"Option A: UPDATE clients SET is_active=1 WHERE id={$contact['post_client_id']};",
|
||||
'Option B: Activate the client in admin and re-run diagnose.',
|
||||
'Note: Login join requires clients.is_active=1.',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@ -160,8 +178,12 @@ class HrLoginDiagnoseController extends AdminController
|
||||
$issues[] = $this->issue(
|
||||
'NO_HR_ACCESS_CONTROL_ROW',
|
||||
'high',
|
||||
"No hr_access_control row for post_hr_id={$contact['post_hr_id']}, post_branch_id={$contact['post_branch_id']}, post_client_id={$contact['post_client_id']}.",
|
||||
'Open Client Onboarding → HR Access and save at least one module for this HR/branch.'
|
||||
"No hr_access_control row for post_hr_id={$contact['post_hr_id']}, post_branch_id={$contact['post_branch_id']}, post_client_id={$contact['post_client_id']} ({$contact['client_name']} / {$contact['branch_name']}).",
|
||||
[
|
||||
'Option A: Open Client Onboarding → HR Access for this client, select at least one module for this HR/branch, then Save.',
|
||||
"Option B: Insert hr_access_control with post_hr_id={$contact['post_hr_id']}, post_branch_id={$contact['post_branch_id']}, post_client_id={$contact['post_client_id']} and allowed_modules JSON.",
|
||||
'Note: Without this row, getVerifiedHrData returns empty token for this card.',
|
||||
]
|
||||
);
|
||||
} else {
|
||||
$modules = json_decode($access['allowed_modules'] ?? '[]', true);
|
||||
@ -176,8 +198,12 @@ class HrLoginDiagnoseController extends AdminController
|
||||
$issues[] = $this->issue(
|
||||
'EMPTY_ALLOWED_MODULES',
|
||||
'high',
|
||||
"hr_access_control id={$access['id']} exists but allowed_modules is empty.",
|
||||
'Assign pre/post modules in HR Access Control and save.'
|
||||
"hr_access_control id={$access['id']} exists but allowed_modules is empty for post_hr_id={$contact['post_hr_id']}.",
|
||||
[
|
||||
'Option A: Open HR Access Control, tick PRE/POST modules for this HR, Save.',
|
||||
"Option B: UPDATE hr_access_control SET allowed_modules='{\"pre\":[1],\"post\":[2,3,4]}' WHERE id={$access['id']}; (adjust module ids as needed).",
|
||||
'Note: Empty modules → token is treated as not ready.',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -206,25 +232,52 @@ class HrLoginDiagnoseController extends AdminController
|
||||
|
||||
if ($preReachable === true) {
|
||||
if (empty($preMap['PRE_BRANCH_LINKED'])) {
|
||||
$postBranchId = (int) ($contact['post_branch_id'] ?? 0);
|
||||
$issues[] = $this->issue(
|
||||
'PRE_BRANCH_NOT_LINKED',
|
||||
'medium',
|
||||
"Post branch #{$contact['post_branch_id']} has no valid pre_branch_id link.",
|
||||
'Set client_branch.pre_branch_id to the matching pre branch id.'
|
||||
"Post branch #{$postBranchId} ({$contact['branch_name']}) has no valid pre_branch_id link (current pre_branch_id=" . ($contact['pre_branch_id'] ?? 'null') . ").",
|
||||
[
|
||||
"Option A: Set client_branch.pre_branch_id on post branch #{$postBranchId} to the matching pre client_branch.id.",
|
||||
'Option B: Use Testing/mapping tools to sync post↔pre branch ids, then re-run diagnose.',
|
||||
'Option C: Confirm the pre branch exists and is_active=1 before linking.',
|
||||
'Note: Without this link, PRE HR/client mapping cannot be resolved.',
|
||||
]
|
||||
);
|
||||
} elseif (empty($preMap['PRE_HR_MATCHED'])) {
|
||||
$issues[] = $this->issue(
|
||||
'PRE_HR_NOT_MATCHED',
|
||||
'medium',
|
||||
"No pre level_contacts match for email+mobile under pre client #{$preMap['pre_client_id']}.",
|
||||
'Align email and mobile between pre and post HR contacts.'
|
||||
"No pre level_contacts match for email/mobile under pre client #{$preMap['pre_client_id']} "
|
||||
. "(post_hr_id={$contact['post_hr_id']}, email={$contact['hr_mail']}, mobile={$contact['hr_mobile']}).",
|
||||
[
|
||||
'Option A: Align email AND mobile between pre and post level_contacts for this HR.',
|
||||
"Option B: Create/activate pre HR contact under pre client #{$preMap['pre_client_id']} with the same email/mobile.",
|
||||
'Option C: Check pre contact_type=client and is_active=1 on the matching branch.',
|
||||
]
|
||||
);
|
||||
} elseif (empty($preMap['PRE_IDS_CONSISTENT']) && !empty($access)) {
|
||||
$storedHr = (int) ($access['pre_hr_id'] ?? 0);
|
||||
$storedClient = (int) ($access['pre_client_id'] ?? 0);
|
||||
$storedBranch = (int) ($access['pre_branch_id'] ?? 0);
|
||||
$liveHr = (int) ($preMap['pre_hr_id'] ?? 0);
|
||||
$liveClient = (int) ($preMap['pre_client_id'] ?? 0);
|
||||
$liveBranch = (int) ($preMap['pre_branch_id'] ?? 0);
|
||||
$accessId = (int) ($access['id'] ?? 0);
|
||||
|
||||
$issues[] = $this->issue(
|
||||
'PRE_IDS_INCONSISTENT',
|
||||
'medium',
|
||||
"hr_access_control pre ids do not match live pre data for post_hr_id={$contact['post_hr_id']}.",
|
||||
'Re-save HR Access Control so pre_hr_id / pre_client_id / pre_branch_id are refreshed.'
|
||||
"hr_access_control pre ids do not match live pre data for post_hr_id={$contact['post_hr_id']} "
|
||||
. "(client #{$contact['post_client_id']}, branch #{$contact['post_branch_id']}). "
|
||||
. "Stored (hr_access_control id={$accessId}): pre_hr_id={$storedHr}, pre_client_id={$storedClient}, pre_branch_id={$storedBranch}. "
|
||||
. "Live pre: pre_hr_id={$liveHr}, pre_client_id={$liveClient}, pre_branch_id={$liveBranch}.",
|
||||
[
|
||||
'Option A: Open Client Onboarding → HR Access for this client, select modules for this HR, Save (form must send live pre ids).',
|
||||
"Option B (recommended): UPDATE hr_access_control SET pre_hr_id={$liveHr}, pre_client_id={$liveClient}, pre_branch_id={$liveBranch} WHERE id={$accessId};",
|
||||
'Option C: If UI re-save keeps old ids, auto-refresh in saveHrAccessData is commented out — enable it or use Option B.',
|
||||
'Note: POST login can still work; this mainly affects PRE modules/JWT pre mapping.',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -244,6 +297,29 @@ class HrLoginDiagnoseController extends AdminController
|
||||
: (!$flags['CLIENT_ACTIVE'] ? 'CLIENT_INACTIVE' : 'UNKNOWN'))),
|
||||
];
|
||||
|
||||
$pairRows[] = [
|
||||
'post' => [
|
||||
'post_hr_id' => (int) $contact['post_hr_id'],
|
||||
'hr_name' => $contact['hr_name'] ?? '',
|
||||
'hr_mail' => $contact['hr_mail'] ?? '',
|
||||
'hr_mobile' => $contact['hr_mobile'] ?? '',
|
||||
'is_active' => (int) ($contact['is_active'] ?? 0),
|
||||
'post_branch_id' => (int) ($contact['post_branch_id'] ?? 0),
|
||||
'branch_name' => $contact['branch_name'] ?? '',
|
||||
'branch_active' => (int) ($contact['branch_active'] ?? 0),
|
||||
'pre_branch_id' => $contact['pre_branch_id'] ?? null,
|
||||
'post_client_id' => (int) ($contact['post_client_id'] ?? 0),
|
||||
'client_name' => $contact['client_name'] ?? '',
|
||||
'client_active' => (int) ($contact['client_active'] ?? 0),
|
||||
'has_access' => ! empty($access),
|
||||
'token_ready' => $tokenReady,
|
||||
'hr_active' => (int) ($contact['is_active'] ?? 0) === 1,
|
||||
],
|
||||
'pre' => $preMap,
|
||||
'access_id' => isset($access['id']) ? (int) $access['id'] : null,
|
||||
'has_token' => $canLoginCard,
|
||||
];
|
||||
|
||||
$contact['hr_found'] = true;
|
||||
$contact['flags'] = $flags;
|
||||
}
|
||||
@ -307,6 +383,26 @@ class HrLoginDiagnoseController extends AdminController
|
||||
$tokenCards = array_filter($loginCards, static fn ($c) => ! empty($c['has_token']));
|
||||
$preMatched = array_filter($preMaps, static fn ($m) => ! empty($m['PRE_HR_MATCHED']));
|
||||
|
||||
// Group PRE/POST pairs by post client for client-wise display.
|
||||
$byClientMap = [];
|
||||
foreach ($pairRows as $pair) {
|
||||
$cid = (int) ($pair['post']['post_client_id'] ?? 0);
|
||||
$key = (string) $cid;
|
||||
if (! isset($byClientMap[$key])) {
|
||||
$byClientMap[$key] = [
|
||||
'post_client_id' => $cid,
|
||||
'client_name' => $pair['post']['client_name'] ?? '',
|
||||
'client_active' => (int) ($pair['post']['client_active'] ?? 0),
|
||||
'rows' => [],
|
||||
];
|
||||
}
|
||||
$byClientMap[$key]['rows'][] = $pair;
|
||||
}
|
||||
$byClient = array_values($byClientMap);
|
||||
usort($byClient, static function ($a, $b) {
|
||||
return strcasecmp((string) ($a['client_name'] ?? ''), (string) ($b['client_name'] ?? ''));
|
||||
});
|
||||
|
||||
return [
|
||||
'input' => ['email' => $email, 'mobile' => $mobile],
|
||||
'overall_status' => $overall,
|
||||
@ -315,6 +411,7 @@ class HrLoginDiagnoseController extends AdminController
|
||||
'summary' => $summary,
|
||||
'issues' => $deduped,
|
||||
'problems' => $deduped,
|
||||
'by_client' => $byClient,
|
||||
'post' => [
|
||||
'contacts' => $postContacts,
|
||||
'raw_found' => count($postContacts) > 0,
|
||||
@ -355,6 +452,7 @@ class HrLoginDiagnoseController extends AdminController
|
||||
'pre_matched' => count($preMatched),
|
||||
'token_cards' => count($tokenCards),
|
||||
'access_rows' => count(array_filter($accessRows, static fn ($a) => ! empty($a['id']))),
|
||||
'client_count' => count($byClient),
|
||||
'would_return_both' => $anyToken && count($preMatched) > 0,
|
||||
'winner' => ($anyToken && count($preMatched) > 0) ? 'both' : ($anyToken ? 'post' : (count($preMatched) > 0 ? 'pre' : 'none')),
|
||||
'reason' => $summary,
|
||||
@ -514,13 +612,25 @@ class HrLoginDiagnoseController extends AdminController
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function issue(string $code, string $severity, string $message, string $fix = ''): array
|
||||
/**
|
||||
* @param string|array<int, string> $fix
|
||||
* @return array{code:string,severity:string,message:string,fix:string,fixes:array<int,string>}
|
||||
*/
|
||||
private function issue(string $code, string $severity, string $message, $fix = ''): array
|
||||
{
|
||||
if (is_array($fix)) {
|
||||
$fixes = array_values(array_filter(array_map('strval', $fix)));
|
||||
} else {
|
||||
$fixes = preg_split("/\r\n|\n|\r/", (string) $fix) ?: [];
|
||||
$fixes = array_values(array_filter(array_map('trim', $fixes)));
|
||||
}
|
||||
|
||||
return [
|
||||
'code' => $code,
|
||||
'severity' => $severity,
|
||||
'message' => $message,
|
||||
'fix' => $fix,
|
||||
'fix' => implode("\n", $fixes),
|
||||
'fixes' => $fixes,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,8 +132,46 @@
|
||||
.badge-high{background:var(--high-badge-bg);color:var(--high-badge-text);}
|
||||
.code{font-family:var(--mono);font-size:12.5px;color:var(--danger-code);font-weight:600;}
|
||||
.fix-text{color:var(--text-secondary);}
|
||||
.fix-list{margin:0;padding-left:18px;}
|
||||
.fix-list li{margin-bottom:6px;line-height:1.35;}
|
||||
.fix-list li:last-child{margin-bottom:0;}
|
||||
.problems-table td.fix-cell{min-width:320px;max-width:480px;}
|
||||
.problems-table td.msg-cell{min-width:260px;}
|
||||
|
||||
.compare-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:20px;}
|
||||
.compare-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px;}
|
||||
.client-block{margin-bottom:0;}
|
||||
.client-block-head{
|
||||
display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
|
||||
padding:12px 16px;background:#F8F9FA;border-bottom:1px solid var(--border);
|
||||
font-size:13.5px;font-weight:700;
|
||||
}
|
||||
.client-block-head .meta{font-weight:400;color:var(--text-muted);font-size:12.5px;}
|
||||
.client-block .compare-grid{margin:0;padding:12px;background:#fff;border-radius:0;}
|
||||
.client-block .compare-grid + .compare-grid{border-top:1px dashed var(--border);}
|
||||
.branch-label{font-size:12px;color:var(--text-secondary);font-weight:600;margin:0 0 8px;padding:0 4px;}
|
||||
|
||||
.client-tabs-wrap{margin-bottom:20px;}
|
||||
.client-tabs{
|
||||
display:flex;gap:4px;border-bottom:1px solid var(--border);margin-bottom:0;padding:0 4px;
|
||||
flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;
|
||||
}
|
||||
.client-tab{
|
||||
padding:10px 14px;font-size:12.5px;font-weight:600;color:var(--text-secondary);
|
||||
cursor:pointer;border-bottom:2px solid transparent;background:none;border-top:none;border-left:none;border-right:none;
|
||||
font-family:var(--sans);white-space:nowrap;flex:0 0 auto;max-width:260px;overflow:hidden;text-overflow:ellipsis;
|
||||
}
|
||||
.client-tab.active{color:var(--teal-dark);border-bottom-color:var(--teal);}
|
||||
.client-tab:hover:not(.active){color:var(--text-primary);}
|
||||
.client-tab .badge-count{
|
||||
display:inline-block;margin-left:6px;font-size:10px;font-weight:700;padding:1px 6px;border-radius:999px;
|
||||
background:var(--low-badge-bg);color:var(--low-badge-text);
|
||||
}
|
||||
.client-tab.active .badge-count{background:var(--teal-tint);color:var(--teal-dark);}
|
||||
.client-panel{
|
||||
display:none;border:1px solid var(--border);border-top:none;
|
||||
border-radius:0 0 var(--radius-md) var(--radius-md);background:#fff;overflow:hidden;
|
||||
}
|
||||
.client-panel.active{display:block;}
|
||||
.compare-card{border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden;background:#fff;}
|
||||
.compare-head{
|
||||
padding:14px 20px;background:#F8F9FA;border-bottom:1px solid var(--border);
|
||||
@ -246,6 +284,7 @@
|
||||
$problems = $result['problems'] ?? ($result['issues'] ?? []);
|
||||
$accessRows = $result['hr_access_control'] ?? [];
|
||||
$loginSim = $result['login_simulation'] ?? [];
|
||||
$byClient = $result['by_client'] ?? [];
|
||||
$postPrimary = $post['primary'] ?? [];
|
||||
$prePrimary = $pre['primary'] ?? [];
|
||||
$postFs = $post['filters_summary'] ?? [];
|
||||
@ -265,87 +304,156 @@
|
||||
<table class="problems-table">
|
||||
<tr>
|
||||
<th style="width:80px;">Severity</th>
|
||||
<th style="width:220px;">Code</th>
|
||||
<th style="width:200px;">Code</th>
|
||||
<th>Message</th>
|
||||
<th style="width:340px;">Fix</th>
|
||||
<th style="width:420px;">Fix</th>
|
||||
</tr>
|
||||
<?php if (empty($problems)): ?>
|
||||
<tr><td class="empty" colspan="4">No problems detected.</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($problems as $p): ?>
|
||||
<?php $sev = strtolower((string) ($p['severity'] ?? 'low')); ?>
|
||||
<?php
|
||||
$sev = strtolower((string) ($p['severity'] ?? 'low'));
|
||||
$fixLines = $p['fixes'] ?? null;
|
||||
if (! is_array($fixLines) || $fixLines === []) {
|
||||
$fixLines = preg_split("/\r\n|\n|\r/", (string) ($p['fix'] ?? '')) ?: [];
|
||||
$fixLines = array_values(array_filter(array_map('trim', $fixLines)));
|
||||
}
|
||||
?>
|
||||
<tr class="sev-<?= esc($sev) ?>">
|
||||
<td><span class="badge badge-<?= esc($sev) ?>"><?= esc(strtoupper($sev)) ?></span></td>
|
||||
<td><span class="code"><?= esc($p['code'] ?? '') ?></span></td>
|
||||
<td><?= esc($p['message'] ?? '') ?></td>
|
||||
<td class="fix-text"><?= esc($p['fix'] ?? '') ?></td>
|
||||
<td class="msg-cell"><?= esc($p['message'] ?? '') ?></td>
|
||||
<td class="fix-text fix-cell">
|
||||
<?php if (count($fixLines) <= 1): ?>
|
||||
<?= esc($fixLines[0] ?? '') ?>
|
||||
<?php else: ?>
|
||||
<ol class="fix-list">
|
||||
<?php foreach ($fixLines as $line): ?>
|
||||
<li><?= esc($line) ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ol>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</table>
|
||||
|
||||
<div class="compare-grid">
|
||||
<div class="compare-card">
|
||||
<div class="compare-head">PRE <span>(enrollment)</span></div>
|
||||
<?php if (! empty($pre['error'])): ?>
|
||||
<div class="alert-inline"><?= esc($pre['error']) ?></div>
|
||||
<?php endif; ?>
|
||||
<table class="kv-table">
|
||||
<tr>
|
||||
<td class="kv-key">Raw found</td>
|
||||
<td class="kv-val"><?= ! empty($pre['raw_found']) ? $mark(true) . ' Yes' : $mark(false) . ' No' ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="kv-key">Eligible (matched)</td>
|
||||
<td class="kv-val"><?= ! empty($pre['eligible']) ? $mark(true) . ' Yes' : $mark(false) . ' No' ?></td>
|
||||
</tr>
|
||||
<tr><td class="kv-key">preDB reachable</td><td class="kv-val"><?= isset($preFs['db_reachable']) ? $mark((bool) $preFs['db_reachable']) : '—' ?></td></tr>
|
||||
<tr><td class="kv-key">PRE_BRANCH_LINKED</td><td class="kv-val"><?= isset($preFs['PRE_BRANCH_LINKED']) ? $mark((bool) $preFs['PRE_BRANCH_LINKED']) : '—' ?></td></tr>
|
||||
<tr><td class="kv-key">PRE_HR_MATCHED</td><td class="kv-val"><?= isset($preFs['PRE_HR_MATCHED']) ? $mark((bool) $preFs['PRE_HR_MATCHED']) : '—' ?></td></tr>
|
||||
<tr><td class="kv-key">PRE_IDS_CONSISTENT</td><td class="kv-val"><?= isset($preFs['PRE_IDS_CONSISTENT']) ? $mark((bool) $preFs['PRE_IDS_CONSISTENT']) : '—' ?></td></tr>
|
||||
<tr><td class="kv-key">PRE_CLIENT_MAPPED</td><td class="kv-val"><?= isset($preFs['PRE_CLIENT_MAPPED']) ? $mark((bool) $preFs['PRE_CLIENT_MAPPED']) : '—' ?></td></tr>
|
||||
<tr><td class="kv-key">pre_hr_id</td><td class="kv-val"><?= esc((string) ($prePrimary['pre_hr_id'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">name</td><td class="kv-val"><?= esc((string) ($prePrimary['hr_name'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">email</td><td class="kv-val"><?= esc((string) ($prePrimary['hr_mail'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">mobile</td><td class="kv-val"><?= esc((string) ($prePrimary['hr_mobile'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">client</td><td class="kv-val"><?= esc((string) (($prePrimary['pre_client_name'] ?? '') . ' #' . ($prePrimary['pre_client_id'] ?? ''))) ?></td></tr>
|
||||
<tr><td class="kv-key">branch</td><td class="kv-val"><?= esc((string) (($prePrimary['pre_branch_name'] ?? '') . ' #' . ($prePrimary['pre_branch_id'] ?? ''))) ?></td></tr>
|
||||
<tr><td class="kv-key">pre_client_id</td><td class="kv-val"><?= esc((string) ($prePrimary['pre_client_id'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">pre_branch_id</td><td class="kv-val"><?= esc((string) ($prePrimary['pre_branch_id'] ?? '—')) ?></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section-title">Client-wise PRE / POST <span>(<?= count($byClient) ?> client<?= count($byClient) === 1 ? '' : 's' ?>)</span></div>
|
||||
<?php if (! empty($pre['error'])): ?>
|
||||
<div class="alert-inline" style="margin:0 0 12px;"><?= esc($pre['error']) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="compare-card">
|
||||
<div class="compare-head">POST <span>(live)</span></div>
|
||||
<table class="kv-table">
|
||||
<tr>
|
||||
<td class="kv-key">Raw found</td>
|
||||
<td class="kv-val">
|
||||
<?= ! empty($post['raw_found'])
|
||||
? $mark(true) . ' Yes (' . count($post['contacts'] ?? []) . ')'
|
||||
: $mark(false) . ' No' ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="kv-key">Eligible for login</td>
|
||||
<td class="kv-val"><?= ! empty($post['eligible']) ? $mark(true) . ' Yes' : $mark(false) . ' No' ?></td>
|
||||
</tr>
|
||||
<tr><td class="kv-key">hr active</td><td class="kv-val"><?= isset($postFs['hr_active']) ? $mark((bool) $postFs['hr_active']) : '—' ?></td></tr>
|
||||
<tr><td class="kv-key">branch active</td><td class="kv-val"><?= isset($postFs['branch_active']) ? $mark((bool) $postFs['branch_active']) : '—' ?></td></tr>
|
||||
<tr><td class="kv-key">client active</td><td class="kv-val"><?= isset($postFs['client_active']) ? $mark((bool) $postFs['client_active']) : '—' ?></td></tr>
|
||||
<tr><td class="kv-key">has access row</td><td class="kv-val"><?= isset($postFs['has_access']) ? $mark((bool) $postFs['has_access']) : '—' ?></td></tr>
|
||||
<tr><td class="kv-key">token ready</td><td class="kv-val"><?= isset($postFs['token_ready']) ? $mark((bool) $postFs['token_ready']) : '—' ?></td></tr>
|
||||
<tr><td class="kv-key">post_hr_id</td><td class="kv-val"><?= esc((string) ($postPrimary['post_hr_id'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">name</td><td class="kv-val"><?= esc((string) ($postPrimary['hr_name'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">email</td><td class="kv-val"><?= esc((string) ($postPrimary['hr_mail'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">mobile</td><td class="kv-val"><?= esc((string) ($postPrimary['hr_mobile'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">client</td><td class="kv-val"><?= esc((string) (($postPrimary['client_name'] ?? '') . ' #' . ($postPrimary['post_client_id'] ?? ''))) ?></td></tr>
|
||||
<tr><td class="kv-key">branch</td><td class="kv-val"><?= esc((string) (($postPrimary['branch_name'] ?? '') . ' #' . ($postPrimary['post_branch_id'] ?? ''))) ?></td></tr>
|
||||
</table>
|
||||
<?php if (empty($byClient)): ?>
|
||||
<div class="card" style="padding:16px 20px;margin-bottom:20px;">
|
||||
<p class="muted" style="padding:0;margin:0;">No client mappings to display.</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="client-tabs-wrap">
|
||||
<div class="client-tabs" role="tablist" aria-label="Clients">
|
||||
<?php foreach ($byClient as $ci => $clientBlock): ?>
|
||||
<?php
|
||||
$clientRows = $clientBlock['rows'] ?? [];
|
||||
$tokenReadyCount = 0;
|
||||
foreach ($clientRows as $cr) {
|
||||
if (! empty($cr['has_token'])) {
|
||||
$tokenReadyCount++;
|
||||
}
|
||||
}
|
||||
$tabLabel = (string) ($clientBlock['client_name'] ?? 'Unknown client');
|
||||
$tabId = 'client-' . (int) ($clientBlock['post_client_id'] ?? $ci);
|
||||
?>
|
||||
<button
|
||||
type="button"
|
||||
class="client-tab<?= $ci === 0 ? ' active' : '' ?>"
|
||||
data-client-panel="<?= esc($tabId) ?>"
|
||||
title="<?= esc($tabLabel . ' #' . ($clientBlock['post_client_id'] ?? '')) ?>"
|
||||
>
|
||||
<?= esc($tabLabel) ?>
|
||||
<span class="badge-count"><?= (int) $tokenReadyCount ?>/<?= count($clientRows) ?></span>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="tabs" role="tablist">
|
||||
<?php foreach ($byClient as $ci => $clientBlock): ?>
|
||||
<?php
|
||||
$clientRows = $clientBlock['rows'] ?? [];
|
||||
$tokenReadyCount = 0;
|
||||
foreach ($clientRows as $cr) {
|
||||
if (! empty($cr['has_token'])) {
|
||||
$tokenReadyCount++;
|
||||
}
|
||||
}
|
||||
$tabId = 'client-' . (int) ($clientBlock['post_client_id'] ?? $ci);
|
||||
?>
|
||||
<div class="client-panel<?= $ci === 0 ? ' active' : '' ?>" id="<?= esc($tabId) ?>">
|
||||
<div class="client-block">
|
||||
<div class="client-block-head">
|
||||
<div>
|
||||
<?= esc((string) ($clientBlock['client_name'] ?? 'Unknown client')) ?>
|
||||
<span class="meta">#<?= esc((string) ($clientBlock['post_client_id'] ?? '')) ?></span>
|
||||
</div>
|
||||
<div class="meta">
|
||||
<?= count($clientRows) ?> branch/HR row<?= count($clientRows) === 1 ? '' : 's' ?>
|
||||
· token ready <?= (int) $tokenReadyCount ?>/<?= count($clientRows) ?>
|
||||
· client <?= ((int) ($clientBlock['client_active'] ?? 0) === 1) ? 'active' : 'inactive' ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php foreach ($clientRows as $row): ?>
|
||||
<?php
|
||||
$rowPost = $row['post'] ?? [];
|
||||
$rowPre = $row['pre'] ?? [];
|
||||
?>
|
||||
<div class="compare-grid">
|
||||
<div class="compare-card" style="border:none;border-radius:0;">
|
||||
<div class="compare-head">PRE <span>(enrollment)</span></div>
|
||||
<p class="branch-label">Branch: <?= esc((string) (($rowPre['pre_branch_name'] ?? '—') . ' #' . ($rowPre['pre_branch_id'] ?? ''))) ?></p>
|
||||
<table class="kv-table">
|
||||
<tr><td class="kv-key">PRE_BRANCH_LINKED</td><td class="kv-val"><?= $mark(! empty($rowPre['PRE_BRANCH_LINKED'])) ?></td></tr>
|
||||
<tr><td class="kv-key">PRE_HR_MATCHED</td><td class="kv-val"><?= $mark(! empty($rowPre['PRE_HR_MATCHED'])) ?></td></tr>
|
||||
<tr><td class="kv-key">PRE_IDS_CONSISTENT</td><td class="kv-val"><?= $mark(! empty($rowPre['PRE_IDS_CONSISTENT'])) ?></td></tr>
|
||||
<tr><td class="kv-key">PRE_CLIENT_MAPPED</td><td class="kv-val"><?= $mark(! empty($rowPre['PRE_CLIENT_MAPPED'])) ?></td></tr>
|
||||
<tr><td class="kv-key">pre_hr_id</td><td class="kv-val"><?= esc((string) ($rowPre['pre_hr_id'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">name</td><td class="kv-val"><?= esc((string) ($rowPre['hr_name'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">email</td><td class="kv-val"><?= esc((string) ($rowPre['hr_mail'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">mobile</td><td class="kv-val"><?= esc((string) ($rowPre['hr_mobile'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">client</td><td class="kv-val"><?= esc((string) (($rowPre['pre_client_name'] ?? '') . ' #' . ($rowPre['pre_client_id'] ?? ''))) ?></td></tr>
|
||||
<tr><td class="kv-key">branch</td><td class="kv-val"><?= esc((string) (($rowPre['pre_branch_name'] ?? '') . ' #' . ($rowPre['pre_branch_id'] ?? ''))) ?></td></tr>
|
||||
<tr><td class="kv-key">pre_client_id</td><td class="kv-val"><?= esc((string) ($rowPre['pre_client_id'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">pre_branch_id</td><td class="kv-val"><?= esc((string) ($rowPre['pre_branch_id'] ?? '—')) ?></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="compare-card" style="border:none;border-radius:0;">
|
||||
<div class="compare-head">POST <span>(live)</span></div>
|
||||
<p class="branch-label">Branch: <?= esc((string) (($rowPost['branch_name'] ?? '—') . ' #' . ($rowPost['post_branch_id'] ?? ''))) ?></p>
|
||||
<table class="kv-table">
|
||||
<tr><td class="kv-key">Eligible for login</td><td class="kv-val"><?= ! empty($row['has_token']) ? $mark(true) . ' Yes' : $mark(false) . ' No' ?></td></tr>
|
||||
<tr><td class="kv-key">hr active</td><td class="kv-val"><?= $mark(! empty($rowPost['hr_active'])) ?></td></tr>
|
||||
<tr><td class="kv-key">branch active</td><td class="kv-val"><?= $mark((int) ($rowPost['branch_active'] ?? 0) === 1) ?></td></tr>
|
||||
<tr><td class="kv-key">client active</td><td class="kv-val"><?= $mark((int) ($rowPost['client_active'] ?? 0) === 1) ?></td></tr>
|
||||
<tr><td class="kv-key">has access row</td><td class="kv-val"><?= $mark(! empty($rowPost['has_access'])) ?></td></tr>
|
||||
<tr><td class="kv-key">token ready</td><td class="kv-val"><?= $mark(! empty($rowPost['token_ready'])) ?></td></tr>
|
||||
<tr><td class="kv-key">post_hr_id</td><td class="kv-val"><?= esc((string) ($rowPost['post_hr_id'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">name</td><td class="kv-val"><?= esc((string) ($rowPost['hr_name'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">email</td><td class="kv-val"><?= esc((string) ($rowPost['hr_mail'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">mobile</td><td class="kv-val"><?= esc((string) ($rowPost['hr_mobile'] ?? '—')) ?></td></tr>
|
||||
<tr><td class="kv-key">client</td><td class="kv-val"><?= esc((string) (($rowPost['client_name'] ?? '') . ' #' . ($rowPost['post_client_id'] ?? ''))) ?></td></tr>
|
||||
<tr><td class="kv-key">branch</td><td class="kv-val"><?= esc((string) (($rowPost['branch_name'] ?? '') . ' #' . ($rowPost['post_branch_id'] ?? ''))) ?></td></tr>
|
||||
<tr><td class="kv-key">access id</td><td class="kv-val"><?= esc((string) ($row['access_id'] ?? '—')) ?></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="tabs detail-tabs" role="tablist">
|
||||
<button type="button" class="tab active" data-tab="merge">Summary</button>
|
||||
<button type="button" class="tab" data-tab="access">Access</button>
|
||||
<button type="button" class="tab" data-tab="login">Login sim</button>
|
||||
@ -359,6 +467,7 @@
|
||||
<tr><td class="cred-key">POST eligible</td><td><?= ! empty($merge['post_eligible']) ? 'Yes' : 'No' ?></td></tr>
|
||||
<tr><td class="cred-key">PRE eligible</td><td><?= ! empty($merge['pre_eligible']) ? 'Yes' : 'No' ?></td></tr>
|
||||
<tr><td class="cred-key">POST contacts</td><td class="val-raw"><?= esc((string) ($merge['post_contacts'] ?? 0)) ?></td></tr>
|
||||
<tr><td class="cred-key">Clients mapped</td><td class="val-raw"><?= esc((string) ($merge['client_count'] ?? count($byClient))) ?></td></tr>
|
||||
<tr><td class="cred-key">PRE matched</td><td class="val-raw"><?= esc((string) ($merge['pre_matched'] ?? 0)) ?></td></tr>
|
||||
<tr><td class="cred-key">Access rows with id</td><td class="val-raw"><?= esc((string) ($merge['access_rows'] ?? 0)) ?></td></tr>
|
||||
<tr><td class="cred-key">Token-ready cards</td><td class="val-raw"><?= esc((string) ($merge['token_cards'] ?? 0)) ?></td></tr>
|
||||
@ -537,7 +646,20 @@
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var tabs = document.querySelectorAll('.tab');
|
||||
var clientTabs = document.querySelectorAll('.client-tab');
|
||||
var clientPanels = document.querySelectorAll('.client-panel');
|
||||
clientTabs.forEach(function (tab) {
|
||||
tab.addEventListener('click', function () {
|
||||
var target = tab.getAttribute('data-client-panel');
|
||||
clientTabs.forEach(function (t) { t.classList.remove('active'); });
|
||||
clientPanels.forEach(function (p) { p.classList.remove('active'); });
|
||||
tab.classList.add('active');
|
||||
var panel = document.getElementById(target);
|
||||
if (panel) panel.classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
var tabs = document.querySelectorAll('.detail-tabs .tab');
|
||||
var panels = {
|
||||
merge: document.getElementById('panel-merge'),
|
||||
access: document.getElementById('panel-access'),
|
||||
@ -566,6 +688,16 @@
|
||||
lines.push('Winner: <?= esc($merge['winner'] ?? '', 'js') ?>');
|
||||
<?php foreach ($problems as $p): ?>
|
||||
lines.push('[<?= esc(strtoupper((string) ($p['severity'] ?? '')), 'js') ?>] <?= esc($p['code'] ?? '', 'js') ?>: <?= esc($p['message'] ?? '', 'js') ?>');
|
||||
<?php
|
||||
$copyFixes = $p['fixes'] ?? [];
|
||||
if (! is_array($copyFixes) || $copyFixes === []) {
|
||||
$copyFixes = preg_split("/\r\n|\n|\r/", (string) ($p['fix'] ?? '')) ?: [];
|
||||
$copyFixes = array_values(array_filter(array_map('trim', $copyFixes)));
|
||||
}
|
||||
foreach ($copyFixes as $fixLine):
|
||||
?>
|
||||
lines.push(' - <?= esc($fixLine, 'js') ?>');
|
||||
<?php endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
navigator.clipboard.writeText(lines.join('\n')).then(function () {
|
||||
btn.textContent = 'Copied';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user