« Back to History
module_logic_view.php
|
20260723_000646.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)) { $moduleId = isset($_GET['module_id']) ? (int)$_GET['module_id'] : 0; header('Location: module_logic_view.php' . ($moduleId > 0 ? '?module_id=' . $moduleId : '')); exit; } function render_block($value, $fallback = 'Not documented yet.') { $value = trim((string)($value ?? '')); if ($value === '') { return '<div class="empty-state">' . h($fallback) . '</div>'; } return '<div class="prelike">' . nl2br(h($value)) . '</div>'; } function parse_related_files($value): array { $raw = preg_split('/[\r\n,]+/', (string)($value ?? '')) ?: []; $items = []; foreach ($raw as $entry) { $entry = trim($entry); if ($entry !== '') { $items[] = $entry; } } return array_values(array_unique($items)); } function developer_module_candidate_files(array $module, array $relatedFiles): array { $candidates = []; foreach ($relatedFiles as $file) { $normalized = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, trim((string)$file)); if ($normalized === '') { continue; } $fullPath = dirname(__DIR__) . DIRECTORY_SEPARATOR . ltrim($normalized, DIRECTORY_SEPARATOR); $candidates[] = $fullPath; } $slug = trim((string)($module['module_slug'] ?? '')); if ($slug !== '') { $guesses = [ dirname(__DIR__) . DIRECTORY_SEPARATOR . 'erp' . DIRECTORY_SEPARATOR . $slug . '.php', dirname(__DIR__) . DIRECTORY_SEPARATOR . 'developer' . DIRECTORY_SEPARATOR . $slug . '.php', dirname(__DIR__) . DIRECTORY_SEPARATOR . 'mserp' . DIRECTORY_SEPARATOR . $slug . '.php', ]; foreach ($guesses as $guess) { $candidates[] = $guess; } } return array_values(array_unique($candidates)); } function developer_pick_existing_file(array $candidates): ?string { foreach ($candidates as $candidate) { if (is_string($candidate) && $candidate !== '' && is_file($candidate) && is_readable($candidate)) { return $candidate; } } return null; } function developer_clean_table_name(string $table): string { return trim($table, "` \t\n\r\0\x0B"); } function developer_extract_sql_tables(string $code): array { $tables = []; if (preg_match_all('/\b(?:from|join|update|into)\s+`?([a-zA-Z0-9_]+)`?/i', $code, $matches)) { foreach ($matches[1] as $table) { $table = developer_clean_table_name((string)$table); if ($table !== '') { $tables[] = $table; } } } return array_values(array_unique($tables)); } function developer_build_code_read_summary(array $module, string $filePath): array { $code = @file_get_contents($filePath); if (!is_string($code) || $code === '') { return [ 'file_path' => $filePath, 'file_label' => str_replace(dirname(__DIR__) . DIRECTORY_SEPARATOR, '', $filePath), 'purpose' => 'Code file read nahi ho paya.', 'flow' => [], 'data_sources' => [], 'validations' => [], 'signals' => [], 'risks' => ['File readable nahi hai, isliye automatic explanation incomplete hai.'], ]; } $lineCount = substr_count($code, "\n") + 1; $fileLabel = str_replace(dirname(__DIR__) . DIRECTORY_SEPARATOR, '', $filePath); $purpose = []; $flow = []; $validations = []; $signals = []; $risks = []; $slug = trim((string)($module['module_slug'] ?? '')); if ($slug !== '') { $purpose[] = 'Module slug `' . $slug . '` ke basis par yeh page isi module ka primary implementation lag raha hai.'; } if (preg_match('/require_login\s*\(/i', $code)) { $signals[] = 'Auth check mila: require_login() present hai.'; } else { $risks[] = 'Auth check detect nahi hua.'; } if (preg_match('/company_id/i', $code)) { $signals[] = 'company_id usage detect hua.'; } else { $risks[] = 'company_id usage detect nahi hua.'; } if (preg_match('/\$pdo->prepare\s*\(/i', $code)) { $signals[] = 'Prepared statements use ho rahe hain.'; } elseif (preg_match('/->query\s*\(/i', $code)) { $risks[] = 'Direct query usage mila, query-by-query review zaroori hai.'; } else { $risks[] = 'Prepared statement detect nahi hua.'; } if (preg_match('/php:\/\/input|json_decode\s*\(file_get_contents\(/i', $code)) { $flow[] = 'Page AJAX या JSON request handle karta hai.'; } if (preg_match('/\$_POST|\$_GET/i', $code)) { $flow[] = 'Page request parameters ke basis par behavior change karta hai.'; } if (preg_match('/INSERT\s+INTO|UPDATE\s+|DELETE\s+FROM/i', $code)) { $flow[] = 'Page data write/update/delete operations karta hai.'; } if (preg_match('/SELECT\s+/i', $code)) { $flow[] = 'Page existing data fetch karke UI ya response build karta hai.'; } if (preg_match('/header\.php|footer\.php/i', $code)) { $signals[] = 'Header/footer include reference mila.'; } else { $risks[] = 'Header/footer include explicitly detect nahi hua.'; } if (preg_match('/<style|style\s*=\s*["\"]/i', $code)) { $risks[] = 'Inline CSS ya embedded style block mila.'; } if (preg_match('/if\s*\([^\)]*<=\s*0|empty\s*\(|isset\s*\(/i', $code)) { $validations[] = 'Input presence / basic validation checks maujood hain.'; } if (preg_match('/rollBack\s*\(|beginTransaction\s*\(/i', $code)) { $signals[] = 'Transactional flow detect hua.'; } if (preg_match('/json_encode\s*\(/i', $code)) { $flow[] = 'Page JSON response return kar sakta hai.'; } $tables = developer_extract_sql_tables($code); if (!$purpose) { $purpose[] = 'File structure ke basis par yeh module-specific business page lagta hai jisme UI aur backend logic dono mix hain.'; } if (!$flow) { $flow[] = 'Automatic flow detection limited rahi; file ko manual review bhi chahiye.'; } if (!$validations) { $validations[] = 'Validation pattern clearly infer nahi hua; manual review recommended.'; } return [ 'file_path' => $filePath, 'file_label' => str_replace(DIRECTORY_SEPARATOR, '/', $fileLabel), 'purpose' => implode(' ', $purpose), 'flow' => array_values(array_unique($flow)), 'data_sources' => $tables, 'validations' => array_values(array_unique($validations)), 'signals' => array_values(array_unique($signals)), 'risks' => array_values(array_unique($risks)), 'line_count' => $lineCount, ]; } 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) : []; $moduleId = isset($_GET['module_id']) ? (int)$_GET['module_id'] : 0; $module = null; $logicDoc = null; $moduleOptions = []; $message = isset($_GET['msg']) ? trim((string)$_GET['msg']) : ''; $errors = []; $pageError = ''; if ($effectiveCompanyId > 0) { try { $moduleOptionsStmt = $pdo->prepare('SELECT id, module_name, module_slug FROM developer_modules WHERE company_id = :company_id ORDER BY module_name, id'); $moduleOptionsStmt->execute([':company_id' => $effectiveCompanyId]); $moduleOptions = $moduleOptionsStmt->fetchAll(PDO::FETCH_ASSOC); if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_logic_doc'])) { $moduleId = (int)pv('module_id', 0); if ($moduleId <= 0) { $errors[] = 'Module select karna required hai.'; } else { $existsStmt = $pdo->prepare('SELECT id FROM developer_modules WHERE company_id = :company_id AND id = :id LIMIT 1'); $existsStmt->execute([ ':company_id' => $effectiveCompanyId, ':id' => $moduleId, ]); if (!$existsStmt->fetchColumn()) { $errors[] = 'Selected module available nahi hai.'; } } if (!$errors) { $payload = [ ':company_id' => $effectiveCompanyId, ':module_id' => $moduleId, ':purpose' => pv('purpose', ''), ':data_sources' => pv('data_sources', ''), ':calculation_flow' => pv('calculation_flow', ''), ':formulas' => pv('formulas', ''), ':validations' => pv('validations', ''), ':expected_output' => pv('expected_output', ''), ':risk_areas' => pv('risk_areas', ''), ':related_files' => pv('related_files', ''), ]; $checkStmt = $pdo->prepare('SELECT id FROM module_logic_docs WHERE company_id = :company_id AND module_id = :module_id LIMIT 1'); $checkStmt->execute([ ':company_id' => $effectiveCompanyId, ':module_id' => $moduleId, ]); $logicId = (int)$checkStmt->fetchColumn(); if ($logicId > 0) { $stmt = $pdo->prepare( 'UPDATE module_logic_docs SET purpose = :purpose, data_sources = :data_sources, calculation_flow = :calculation_flow, formulas = :formulas, validations = :validations, expected_output = :expected_output, risk_areas = :risk_areas, related_files = :related_files WHERE company_id = :company_id AND module_id = :module_id' ); $stmt->execute($payload); developer_log_activity($pdo, 'Updated logic doc for module #' . $moduleId); header('Location: module_logic_view.php?module_id=' . $moduleId . '&msg=' . urlencode('Logic documentation updated.')); exit; } $stmt = $pdo->prepare( 'INSERT INTO module_logic_docs (company_id, module_id, purpose, data_sources, calculation_flow, formulas, validations, expected_output, risk_areas, related_files) VALUES (:company_id, :module_id, :purpose, :data_sources, :calculation_flow, :formulas, :validations, :expected_output, :risk_areas, :related_files)' ); $stmt->execute($payload); developer_log_activity($pdo, 'Created logic doc for module #' . $moduleId); header('Location: module_logic_view.php?module_id=' . $moduleId . '&msg=' . urlencode('Logic documentation saved.')); exit; } } if ($moduleId > 0) { $moduleStmt = $pdo->prepare('SELECT * FROM developer_modules WHERE company_id = :company_id AND id = :id LIMIT 1'); $moduleStmt->execute([ ':company_id' => $effectiveCompanyId, ':id' => $moduleId, ]); $module = $moduleStmt->fetch(PDO::FETCH_ASSOC) ?: null; if ($module) { $logicStmt = $pdo->prepare('SELECT * FROM module_logic_docs WHERE company_id = :company_id AND module_id = :module_id LIMIT 1'); $logicStmt->execute([ ':company_id' => $effectiveCompanyId, ':module_id' => $moduleId, ]); $logicDoc = $logicStmt->fetch(PDO::FETCH_ASSOC) ?: null; } } } catch (Throwable $e) { $pageError = $e->getMessage(); } } $relatedFiles = parse_related_files($logicDoc['related_files'] ?? ''); $codeRead = null; if ($module) { $candidateFiles = developer_module_candidate_files($module, $relatedFiles); $resolvedFile = developer_pick_existing_file($candidateFiles); if ($resolvedFile) { $codeRead = developer_build_code_read_summary($module, $resolvedFile); } } ?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Module Logic View</title> <style> :root { --bg: #f4f7fb; --surface: #ffffff; --surface-alt: #eef4ff; --text: #152033; --muted: #627086; --line: #d9e2f0; --primary: #0d6efd; --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, .toolbar, .grid { display: flex; gap: 18px; flex-wrap: wrap; } .topbar { justify-content: space-between; align-items: flex-start; margin-bottom: 24px; } .card { background: var(--surface); border: 1px solid var(--line); border-radius: 18px; box-shadow: var(--shadow); margin-bottom: 18px; } .card-header, .card-body { padding: 20px; } .card-header { border-bottom: 1px solid var(--line); } .col-main { flex: 1 1 780px; } .col-side { flex: 0 1 300px; } .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); } .small { color: var(--muted); } .field { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; } .field textarea, .field select { width: 100%; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--line); background: #fbfdff; font: inherit; } .field textarea { min-height: 110px; resize: vertical; } .company-switcher form, .module-picker form { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin: 0; } select { min-width: 240px; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--line); background: #fff; } .empty-state, .notice, .error-box { padding: 14px 16px; border-radius: 14px; } .empty-state, .notice { background: #f8fbff; border: 1px solid var(--line); color: var(--muted); } .error-box { background: #fff0f0; border: 1px solid #ffcaca; color: #991b1b; margin-bottom: 18px; } .prelike { white-space: normal; line-height: 1.65; } .meta-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; } .meta-box { border: 1px solid var(--line); border-radius: 14px; padding: 14px; background: #fbfdff; } .list { margin: 0; padding-left: 18px; } .pill-row { display: flex; flex-wrap: wrap; gap: 8px; } .pill { display: inline-flex; align-items: center; padding: 7px 10px; border-radius: 999px; background: #eef4ff; color: #17305c; font-size: 12px; font-weight: 700; } </style> </head> <body> <div class="page-shell"> <div class="topbar"> <div> <h1 style="margin:0;">Module Logic Documentation</h1> <p class="small" style="margin:8px 0 0;">Purpose, formula, validation, expected output and risk areas in readable format.</p> </div> <div class="toolbar"> <a href="developer_modules.php" class="btn btn-dark">Back to Module List</a> <a href="module_verification.php<?= $moduleId > 0 ? '?module_id=' . $moduleId : '' ?>" class="btn btn-secondary">Open Verification</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 ($pageError !== ''): ?> <div class="error-box">Module logic query fail 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="grid"> <div class="col-side"> <div class="card"> <div class="card-header">Select Module</div> <div class="card-body"> <div class="module-picker"> <form method="get"> <select name="module_id" onchange="this.form.submit()"> <option value="0">Choose module</option> <?php foreach ($moduleOptions as $option): ?> <option value="<?= (int)$option['id'] ?>" <?= (int)$option['id'] === $moduleId ? 'selected' : '' ?>> <?= h($option['module_name']) ?> </option> <?php endforeach; ?> </select> <button type="submit" class="btn btn-primary">Open</button> </form> </div> <div class="small" style="margin-top:12px;">Start recommended: <strong>semi_monthly_salary_report</strong></div> </div> </div> <div class="card"> <div class="card-header">Logic Sections</div> <div class="card-body"> <ul class="list"> <li>Purpose</li> <li>Data Sources</li> <li>Calculation Flow</li> <li>Formulas</li> <li>Validations</li> <li>Expected Output</li> <li>Risk Areas</li> <li>Related Files</li> </ul> </div> </div> </div> <div class="col-main"> <?php if (!$module): ?> <div class="notice">Module select karo to logic documentation view open ho jayega.</div> <?php else: ?> <div class="card"> <div class="card-header"> <h2 style="margin:0;"><?= h($module['module_name']) ?></h2> <div class="small" style="margin-top:6px;"><?= h($module['module_slug']) ?> | <?= h($module['module_type'] ?: 'ERP') ?> | Version <?= h($module['version'] ?: '1.0') ?></div> </div> <div class="card-body"> <div class="meta-grid"> <div class="meta-box"> <div class="small">Current Status</div> <div style="font-weight:700;margin-top:6px;"><?= h($module['status'] ?: 'active') ?></div> </div> <div class="meta-box"> <div class="small">Company Context</div> <div style="font-weight:700;margin-top:6px;"><?= h($effectiveCompany['name'] ?? 'Unknown') ?></div> </div> <div class="meta-box"> <div class="small">Last Doc Update</div> <div style="font-weight:700;margin-top:6px;"><?= h($logicDoc['updated_at'] ?? 'Pending') ?></div> </div> </div> <?php if (!empty($module['description'])): ?> <div class="notice" style="margin-top:18px;"><?= h($module['description']) ?></div> <?php endif; ?> </div> </div> <div class="card" id="logic-editor"> <div class="card-header">Edit Logic Specs</div> <div class="card-body"> <form method="post"> <input type="hidden" name="module_id" value="<?= (int)$moduleId ?>"> <label class="field"> <span>Purpose</span> <textarea name="purpose"><?= h($logicDoc['purpose'] ?? '') ?></textarea> </label> <label class="field"> <span>Data Sources</span> <textarea name="data_sources"><?= h($logicDoc['data_sources'] ?? '') ?></textarea> </label> <label class="field"> <span>Calculation Flow</span> <textarea name="calculation_flow"><?= h($logicDoc['calculation_flow'] ?? '') ?></textarea> </label> <label class="field"> <span>Formulas</span> <textarea name="formulas"><?= h($logicDoc['formulas'] ?? '') ?></textarea> </label> <label class="field"> <span>Validations</span> <textarea name="validations"><?= h($logicDoc['validations'] ?? '') ?></textarea> </label> <label class="field"> <span>Expected Output</span> <textarea name="expected_output"><?= h($logicDoc['expected_output'] ?? '') ?></textarea> </label> <label class="field"> <span>Risk Areas</span> <textarea name="risk_areas"><?= h($logicDoc['risk_areas'] ?? '') ?></textarea> </label> <label class="field"> <span>Related Files</span> <textarea name="related_files"><?= h($logicDoc['related_files'] ?? '') ?></textarea> </label> <button type="submit" name="save_logic_doc" value="1" class="btn btn-primary">Save Logic Documentation</button> </form> </div> </div> <div class="card"> <div class="card-header">Auto Code Read</div> <div class="card-body"> <?php if (!$codeRead): ?> <div class="empty-state"> Actual page code read karne ke liye `Related Files` me file path do, jaise `erp/your_page.php`. Agar module slug se matching file mil gayi to system usko bhi auto-read karega. </div> <?php else: ?> <div class="meta-grid" style="margin-bottom:18px;"> <div class="meta-box"> <div class="small">Source File</div> <div style="font-weight:700;margin-top:6px;"><?= h($codeRead['file_label'] ?? '') ?></div> </div> <div class="meta-box"> <div class="small">Approx Lines</div> <div style="font-weight:700;margin-top:6px;"><?= (int)($codeRead['line_count'] ?? 0) ?></div> </div> </div> <div class="card" style="box-shadow:none;margin-bottom:18px;"> <div class="card-header">Page Kya Karta Hai</div> <div class="card-body prelike"><?= nl2br(h($codeRead['purpose'] ?? '')) ?></div> </div> <div class="card" style="box-shadow:none;margin-bottom:18px;"> <div class="card-header">Page Kaise Kaam Karta Hai</div> <div class="card-body"> <ul class="list"> <?php foreach (($codeRead['flow'] ?? []) as $item): ?> <li><?= h($item) ?></li> <?php endforeach; ?> </ul> </div> </div> <div class="card" style="box-shadow:none;margin-bottom:18px;"> <div class="card-header">Detected Tables / Data Sources</div> <div class="card-body"> <?php if (empty($codeRead['data_sources'])): ?> <div class="empty-state">SQL table names clearly detect nahi hue.</div> <?php else: ?> <div class="pill-row"> <?php foreach ($codeRead['data_sources'] as $table): ?> <span class="pill"><?= h($table) ?></span> <?php endforeach; ?> </div> <?php endif; ?> </div> </div> <div class="card" style="box-shadow:none;margin-bottom:18px;"> <div class="card-header">Detected Validations / Signals</div> <div class="card-body"> <ul class="list"> <?php foreach (array_merge($codeRead['validations'] ?? [], $codeRead['signals'] ?? []) as $item): ?> <li><?= h($item) ?></li> <?php endforeach; ?> </ul> </div> </div> <div class="card" style="box-shadow:none;margin-bottom:0;"> <div class="card-header">Possible Risk Areas</div> <div class="card-body"> <ul class="list"> <?php foreach (($codeRead['risks'] ?? []) as $item): ?> <li><?= h($item) ?></li> <?php endforeach; ?> </ul> </div> </div> <?php endif; ?> </div> </div> <div class="card"> <div class="card-header">Purpose</div> <div class="card-body"><?= render_block($logicDoc['purpose'] ?? '', 'Module purpose not added yet.') ?></div> </div> <div class="card"> <div class="card-header">Data Sources</div> <div class="card-body"><?= render_block($logicDoc['data_sources'] ?? '', 'Source tables and inputs not documented yet.') ?></div> </div> <div class="card"> <div class="card-header">Calculation Flow</div> <div class="card-body"><?= render_block($logicDoc['calculation_flow'] ?? '', 'Flow description pending.') ?></div> </div> <div class="card"> <div class="card-header">Formulas</div> <div class="card-body"><?= render_block($logicDoc['formulas'] ?? '', 'Formula documentation pending.') ?></div> </div> <div class="card"> <div class="card-header">Validations</div> <div class="card-body"><?= render_block($logicDoc['validations'] ?? '', 'Validation rules pending.') ?></div> </div> <div class="card"> <div class="card-header">Expected Output</div> <div class="card-body"><?= render_block($logicDoc['expected_output'] ?? '', 'Expected output not documented yet.') ?></div> </div> <div class="card"> <div class="card-header">Risk Areas</div> <div class="card-body"><?= render_block($logicDoc['risk_areas'] ?? '', 'Risk areas not documented yet.') ?></div> </div> <div class="card"> <div class="card-header">Related Files</div> <div class="card-body"> <?php if (!$relatedFiles): ?> <div class="empty-state">Related files not mapped yet.</div> <?php else: ?> <ul class="list"> <?php foreach ($relatedFiles as $file): ?> <li><?= h($file) ?></li> <?php endforeach; ?> </ul> <?php endif; ?> </div> </div> <?php endif; ?> </div> </div> </div> </body> </html>