« Back to History
developer_modules.php
|
20260722_120325.php
Initial Domain Snapshot
Copy Code
<?php require_once __DIR__ . '/developer_bootstrap.php'; $pdo = developer_get_pdo(); $erpUser = developer_get_erp_user(); if (developer_handle_company_switch($pdo, $erpUser)) { header('Location: developer_modules.php'); exit; } function verification_label(array $module): array { $failedChecks = (int)($module['failed_checks'] ?? 0); $totalChecks = (int)($module['total_checks'] ?? 0); if ($failedChecks > 0) { return ['Failed', 'badge-danger']; } if ($totalChecks > 0) { return ['Verified', 'badge-success']; } return ['Pending', 'badge-secondary']; } function gv(string $key, $default = null) { return isset($_GET[$key]) ? trim((string)$_GET[$key]) : $default; } function pv(string $key, $default = null) { return isset($_POST[$key]) ? trim((string)$_POST[$key]) : $default; } $canSwitchCompanies = is_array($erpUser) && strtolower((string)($erpUser['role'] ?? '')) === 'developer'; $effectiveCompany = developer_get_effective_company($pdo, $erpUser); $effectiveCompanyId = (int)($effectiveCompany['id'] ?? 0); $companyOptions = $canSwitchCompanies ? developer_get_company_options($pdo) : []; $message = gv('msg', ''); $editId = (int)gv('edit', 0); $errors = []; $form = [ 'id' => 0, 'module_name' => '', 'module_slug' => '', 'module_type' => 'ERP', 'version' => '1.0', 'status' => 'active', 'description' => '', ]; $modules = []; $pageError = ''; if ($effectiveCompanyId > 0) { try { if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_module'])) { $form['id'] = (int)pv('id', 0); $form['module_name'] = pv('module_name', ''); $form['module_slug'] = strtolower(trim((string)pv('module_slug', ''))); $form['module_type'] = pv('module_type', 'ERP'); $form['version'] = pv('version', '1.0'); $form['status'] = pv('status', 'active'); $form['description'] = pv('description', ''); if ($form['module_name'] === '') { $errors[] = 'Module name required hai.'; } if ($form['module_slug'] === '') { $errors[] = 'Module slug required hai.'; } elseif (!preg_match('/^[a-z0-9_\-]+$/', $form['module_slug'])) { $errors[] = 'Module slug me sirf lowercase letters, numbers, underscore aur hyphen use karo.'; } if (!in_array($form['status'], ['active', 'inactive', 'draft'], true)) { $errors[] = 'Status invalid hai.'; } if (!$errors) { $duplicateStmt = $pdo->prepare( 'SELECT id FROM developer_modules WHERE company_id = :company_id AND module_slug = :module_slug AND id <> :id LIMIT 1' ); $duplicateStmt->execute([ ':company_id' => $effectiveCompanyId, ':module_slug' => $form['module_slug'], ':id' => $form['id'], ]); if ($duplicateStmt->fetchColumn()) { $errors[] = 'Ye module slug is company me already use ho raha hai.'; } } if (!$errors) { if ($form['id'] > 0) { $stmt = $pdo->prepare( 'UPDATE developer_modules SET module_name = :module_name, module_slug = :module_slug, module_type = :module_type, version = :version, status = :status, description = :description WHERE company_id = :company_id AND id = :id' ); $stmt->execute([ ':module_name' => $form['module_name'], ':module_slug' => $form['module_slug'], ':module_type' => $form['module_type'], ':version' => $form['version'] !== '' ? $form['version'] : '1.0', ':status' => $form['status'], ':description' => $form['description'] !== '' ? $form['description'] : null, ':company_id' => $effectiveCompanyId, ':id' => $form['id'], ]); developer_log_activity($pdo, 'Updated verification module: ' . $form['module_slug']); header('Location: developer_modules.php?msg=' . urlencode('Module updated successfully.')); exit; } $stmt = $pdo->prepare( 'INSERT INTO developer_modules (company_id, module_name, module_slug, module_type, version, status, description) VALUES (:company_id, :module_name, :module_slug, :module_type, :version, :status, :description)' ); $stmt->execute([ ':company_id' => $effectiveCompanyId, ':module_name' => $form['module_name'], ':module_slug' => $form['module_slug'], ':module_type' => $form['module_type'], ':version' => $form['version'] !== '' ? $form['version'] : '1.0', ':status' => $form['status'], ':description' => $form['description'] !== '' ? $form['description'] : null, ]); developer_log_activity($pdo, 'Created verification module: ' . $form['module_slug']); header('Location: developer_modules.php?msg=' . urlencode('Module created successfully.')); exit; } } if ($editId > 0 && $_SERVER['REQUEST_METHOD'] !== 'POST') { $editStmt = $pdo->prepare('SELECT * FROM developer_modules WHERE company_id = :company_id AND id = :id LIMIT 1'); $editStmt->execute([ ':company_id' => $effectiveCompanyId, ':id' => $editId, ]); $editRow = $editStmt->fetch(PDO::FETCH_ASSOC); if ($editRow) { $form['id'] = (int)$editRow['id']; $form['module_name'] = (string)$editRow['module_name']; $form['module_slug'] = (string)$editRow['module_slug']; $form['module_type'] = (string)($editRow['module_type'] ?: 'ERP'); $form['version'] = (string)($editRow['version'] ?: '1.0'); $form['status'] = (string)($editRow['status'] ?: 'active'); $form['description'] = (string)($editRow['description'] ?? ''); } } $sql = " SELECT m.id, m.module_name, m.module_slug, m.module_type, m.version, m.status, m.description, m.created_at, d.updated_at AS logic_updated_at, COALESCE(v.total_checks, 0) AS total_checks, COALESCE(v.failed_checks, 0) AS failed_checks, COALESCE(v.critical_issues, 0) AS critical_issues, v.last_verified_at FROM developer_modules m LEFT JOIN module_logic_docs d ON d.company_id = m.company_id AND d.module_id = m.id LEFT JOIN ( SELECT company_id, module_id, COUNT(*) AS total_checks, SUM(CASE WHEN LOWER(COALESCE(verification_status, '')) IN ('failed', 'fail', 'error', 'critical') THEN 1 ELSE 0 END) AS failed_checks, SUM(CASE WHEN LOWER(COALESCE(severity, '')) = 'critical' AND LOWER(COALESCE(verification_status, '')) NOT IN ('passed', 'pass', 'success') THEN 1 ELSE 0 END) AS critical_issues, MAX(verified_at) AS last_verified_at FROM module_verifications GROUP BY company_id, module_id ) v ON v.company_id = m.company_id AND v.module_id = m.id WHERE m.company_id = :company_id ORDER BY m.module_name ASC, m.id ASC "; $stmt = $pdo->prepare($sql); $stmt->execute([':company_id' => $effectiveCompanyId]); $modules = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (Throwable $e) { $pageError = $e->getMessage(); } } $totalModules = count($modules); $verifiedModules = 0; $failedModules = 0; $criticalModules = 0; foreach ($modules as $module) { if ((int)($module['failed_checks'] ?? 0) > 0) { $failedModules++; } elseif ((int)($module['total_checks'] ?? 0) > 0) { $verifiedModules++; } if ((int)($module['critical_issues'] ?? 0) > 0) { $criticalModules++; } } ?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>ERP Module Verification Hub</title> <style> :root { --bg: #f4f7fb; --surface: #ffffff; --surface-alt: #eef4ff; --text: #152033; --muted: #627086; --line: #d9e2f0; --primary: #0d6efd; --danger: #cf2e2e; --success: #1f9d55; --warning: #d98e04; --shadow: 0 18px 40px rgba(24, 39, 75, 0.08); } * { box-sizing: border-box; } body { margin: 0; font-family: "Segoe UI", Tahoma, sans-serif; background: linear-gradient(180deg, #ebf3ff 0%, var(--bg) 180px); color: var(--text); } a { color: inherit; text-decoration: none; } .page-shell { max-width: 1380px; margin: 0 auto; padding: 24px; } .topbar, .summary-row, .toolbar, .row { display: flex; gap: 18px; flex-wrap: wrap; } .topbar { justify-content: space-between; align-items: flex-start; margin-bottom: 24px; } .brand h1, .section-title { margin: 0; } .brand p { margin: 8px 0 0; color: var(--muted); } .top-actions, .toolbar { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; } .card, .summary-card { background: var(--surface); border: 1px solid var(--line); border-radius: 18px; box-shadow: var(--shadow); } .card { margin-bottom: 18px; } .card-header, .card-body, .summary-card { padding: 20px; } .card-header { border-bottom: 1px solid var(--line); } .summary-card { min-width: 220px; flex: 1 1 220px; } .summary-card .count { font-size: 34px; font-weight: 700; margin-top: 8px; } .muted, .small { color: var(--muted); } .btn { display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 12px; padding: 11px 16px; cursor: pointer; font-weight: 600; } .btn-dark { background: #162033; color: #fff; } .btn-primary { background: var(--primary); color: #fff; } .btn-secondary { background: var(--surface-alt); color: var(--text); } .btn-sm { padding: 8px 12px; border-radius: 10px; font-size: 13px; } .form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; } .field { display: flex; flex-direction: column; gap: 8px; } .field input, .field select, .field textarea { width: 100%; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--line); background: #fbfdff; font: inherit; } .field textarea { min-height: 96px; resize: vertical; } .company-switcher form { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin: 0; } .company-switcher select { min-width: 240px; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--line); background: #fff; } .table-responsive { overflow-x: auto; } .table { width: 100%; border-collapse: collapse; } .table th, .table td { padding: 14px 16px; border-top: 1px solid var(--line); text-align: left; vertical-align: top; } .table thead th { background: #f8fbff; color: var(--muted); font-size: 13px; text-transform: uppercase; letter-spacing: 0.04em; } .badge { display: inline-flex; align-items: center; padding: 6px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; } .badge-success { background: #dcfce7; color: #166534; } .badge-danger { background: #ffe1e1; color: #991b1b; } .badge-secondary { background: #e8f0ff; color: #1849a9; } .notice, .error-box { padding: 14px 16px; border-radius: 14px; margin-bottom: 18px; } .notice { background: #fef7dd; border: 1px solid #f0dea0; color: #6d5800; } .error-box { background: #fff0f0; border: 1px solid #ffcaca; color: #991b1b; } .context-badge { display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 999px; background: #e8f0ff; color: #17305c; font-size: 13px; font-weight: 700; margin-top: 8px; } @media (max-width: 900px) { .topbar { flex-direction: column; } } </style> </head> <body> <div class="page-shell"> <div class="topbar"> <div class="brand"> <h1>ERP Module Verification Hub</h1> <p>Centralized module documentation, verification status, audit tracking and AI-ready review flow.</p> <?php if ($effectiveCompanyId > 0): ?> <div class="context-badge">Active Company: <?= h($effectiveCompany['name'] ?? 'Unknown') ?></div> <?php endif; ?> </div> <div class="top-actions"> <a href="dashboard.php" class="btn btn-dark">Back to Dashboard</a> <a href="module_verification_entry.php" class="btn btn-primary">Add Verification Check</a> <a href="module_verification.php" class="btn btn-secondary">Verification Status</a> <a href="module_verification_history.php" class="btn btn-secondary">Verification History</a> <?php if ($canSwitchCompanies): ?> <div class="company-switcher"> <form method="post"> <label class="small" for="developer_switch_company_id">Switch Company</label> <select id="developer_switch_company_id" name="developer_switch_company_id"> <?php foreach ($companyOptions as $company): ?> <option value="<?= (int)$company['id'] ?>" <?= (int)($effectiveCompany['id'] ?? 0) === (int)$company['id'] ? 'selected' : '' ?>> <?= h($company['name']) ?> </option> <?php endforeach; ?> </select> <button type="submit" class="btn btn-secondary">Apply</button> </form> </div> <?php endif; ?> </div> </div> <?php if ($effectiveCompanyId <= 0): ?> <div class="notice">Company context selected nahi hai. Dashboard se company switch karke phir verification hub open karo.</div> <?php endif; ?> <?php if ($pageError !== ''): ?> <div class="error-box">Verification tables query nahi hui: <?= h($pageError) ?></div> <?php endif; ?> <?php if ($message !== ''): ?> <div class="notice" style="background:#e8fff1;border-color:#b7f2cb;color:#166534;"><?= h($message) ?></div> <?php endif; ?> <?php if ($errors): ?> <div class="error-box"> <?php foreach ($errors as $error): ?> <div><?= h($error) ?></div> <?php endforeach; ?> </div> <?php endif; ?> <div class="summary-row"> <div class="summary-card"> <div class="small">Total Modules</div> <div class="count"><?= (int)$totalModules ?></div> </div> <div class="summary-card"> <div class="small">Verified Modules</div> <div class="count"><?= (int)$verifiedModules ?></div> </div> <div class="summary-card"> <div class="small">Failed Modules</div> <div class="count"><?= (int)$failedModules ?></div> </div> <div class="summary-card"> <div class="small">Critical Issues</div> <div class="count"><?= (int)$criticalModules ?></div> </div> </div> <div class="card"> <div class="card-header"> <div class="section-title"><?= $form['id'] > 0 ? 'Edit Module Specs' : 'Create Module Specs' ?></div> <div class="small">Module metadata yahin se maintain hoga. Iske baad logic docs aur verification checks add karo.</div> </div> <div class="card-body"> <form method="post"> <input type="hidden" name="id" value="<?= (int)$form['id'] ?>"> <div class="form-grid"> <label class="field"> <span>Module Name</span> <input type="text" name="module_name" value="<?= h($form['module_name']) ?>" required> </label> <label class="field"> <span>Module Slug</span> <input type="text" name="module_slug" value="<?= h($form['module_slug']) ?>" placeholder="semi_monthly_salary_report" required> </label> <label class="field"> <span>Module Type</span> <input type="text" name="module_type" value="<?= h($form['module_type']) ?>"> </label> <label class="field"> <span>Version</span> <input type="text" name="version" value="<?= h($form['version']) ?>"> </label> <label class="field"> <span>Status</span> <select name="status"> <?php foreach (['active', 'inactive', 'draft'] as $statusOption): ?> <option value="<?= h($statusOption) ?>" <?= $form['status'] === $statusOption ? 'selected' : '' ?>><?= h($statusOption) ?></option> <?php endforeach; ?> </select> </label> </div> <label class="field" style="margin-top:14px;"> <span>Description</span> <textarea name="description"><?= h($form['description']) ?></textarea> </label> <div class="toolbar" style="margin-top:14px;"> <button type="submit" name="save_module" value="1" class="btn btn-primary"><?= $form['id'] > 0 ? 'Update Module' : 'Create Module' ?></button> <?php if ($form['id'] > 0): ?> <a href="developer_modules.php" class="btn btn-secondary">Cancel Edit</a> <?php endif; ?> </div> </form> </div> </div> <div class="card"> <div class="card-header"> <div class="section-title">Module List</div> <div class="small">Expected behavior docs aur verification result dono yahin se open honge.</div> </div> <div class="card-body"> <?php if ($effectiveCompanyId > 0 && !$pageError && !$modules): ?> <div class="notice"> Abhi is company ke liye koi module record nahi mila. Start with <strong>semi_monthly_salary_report</strong> in <code>developer_modules</code>, phir logic docs aur verification checks add karo. </div> <?php endif; ?> <div class="table-responsive"> <table class="table"> <thead> <tr> <th>Module</th> <th>Type</th> <th>Status</th> <th>Version</th> <th>Logic Doc</th> <th>Last Verify</th> <th>Failed Checks</th> <th>Critical</th> <th>Actions</th> </tr> </thead> <tbody> <?php if (!$modules): ?> <tr> <td colspan="9" class="small muted">No module rows to display.</td> </tr> <?php endif; ?> <?php foreach ($modules as $module): ?> <?php [$statusLabel, $statusClass] = verification_label($module); ?> <tr> <td> <div style="font-weight:700;"><?= h($module['module_name']) ?></div> <div class="small"><?= h($module['module_slug']) ?></div> <?php if (!empty($module['description'])): ?> <div class="small" style="margin-top:6px;"><?= h($module['description']) ?></div> <?php endif; ?> </td> <td><?= h($module['module_type'] ?: 'ERP') ?></td> <td> <span class="badge <?= h($statusClass) ?>"><?= h($statusLabel) ?></span> <div class="small" style="margin-top:6px;"><?= h($module['status']) ?></div> </td> <td><?= h($module['version'] ?: '1.0') ?></td> <td><?= h($module['logic_updated_at'] ?: 'Pending') ?></td> <td><?= h($module['last_verified_at'] ?: 'Pending') ?></td> <td><?= (int)($module['failed_checks'] ?? 0) ?></td> <td><?= (int)($module['critical_issues'] ?? 0) ?></td> <td> <div class="toolbar"> <a href="developer_modules.php?edit=<?= (int)$module['id'] ?>" class="btn btn-sm btn-primary">Edit Specs</a> <a href="module_logic_view.php?module_id=<?= (int)$module['id'] ?>" class="btn btn-sm btn-dark">View Logic</a> <a href="module_verification_entry.php?module_id=<?= (int)$module['id'] ?>" class="btn btn-sm btn-secondary">Verify</a> <a href="module_verification_history.php?module_id=<?= (int)$module['id'] ?>" class="btn btn-sm btn-secondary">History</a> </div> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> </div> </div> <div class="card"> <div class="card-header"> <div class="section-title">Permanent ERP Rules</div> <div class="small">Ye base rules har module review me manually ya automatically verify hone chahiye.</div> </div> <div class="card-body"> <div class="toolbar"> <span class="badge badge-secondary">company_id mandatory</span> <span class="badge badge-secondary">auth required</span> <span class="badge badge-secondary">header/footer mandatory</span> <span class="badge badge-secondary">bootstrap friendly</span> <span class="badge badge-secondary">main.css usage</span> <span class="badge badge-secondary">no inline CSS</span> <span class="badge badge-secondary">no global behavior modification</span> </div> </div> </div> </div> </body> </html>