« Back to History
loom_machine_status_update.php
|
20260920_164915.php
Initial Domain Snapshot
Copy Code
<?php require_once __DIR__ . '/modules/auth/page_acl.php'; $ctx = page_require_access('loom_machine_status'); $pdo = $ctx['pdo'] ?? null; $company_id = (int)($ctx['company_id'] ?? 0); $u = $ctx['user'] ?? null; if (!$pdo) { require_once __DIR__ . '/core/db.php'; $pdo = $GLOBALS['pdo']; } /* CSRF */ if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } /* ── Fetch khatas (Range based) ────────────────────────────────────────── */ $st = $pdo->prepare("SELECT id, name, code, machine_from, machine_to FROM khatas WHERE company_id = ? AND is_active = 1 ORDER BY machine_from"); $st->execute([$company_id]); $khatas = $st->fetchAll(PDO::FETCH_ASSOC); /* ── Fetch status options from existing machine status data ────────────── */ $status_options = []; try { $col = $pdo->query("SHOW COLUMNS FROM loom_machine_status LIKE 'status'")->fetch(PDO::FETCH_ASSOC); $column_type = strtolower((string)($col['Type'] ?? '')); if (preg_match('/^enum\((.*)\)$/', $column_type, $m)) { $raw_values = str_getcsv($m[1], ',', "'", '\\'); foreach ($raw_values as $raw_value) { $value = trim((string)$raw_value); if ($value !== '') { $status_options[] = $value; } } } if (!$status_options) { $st = $pdo->prepare(" SELECT DISTINCT TRIM(status) AS status_name FROM loom_machine_status WHERE company_id = ? AND status IS NOT NULL AND TRIM(status) <> '' ORDER BY CASE WHEN LOWER(TRIM(status)) = 'running' THEN 0 ELSE 1 END, TRIM(status) "); $st->execute([$company_id]); $status_options = $st->fetchAll(PDO::FETCH_COLUMN); } } catch (Throwable $e) { $status_options = []; } if (!in_array('Running', $status_options, true)) { array_unshift($status_options, 'Running'); } /* ── POST handler ───────────────────────────────────────────────────────── */ $msg = ''; $msg_type = 'success'; if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'] ?? '')) { die('Invalid CSRF token'); } $status_date = $_POST['status_date'] ?? date('Y-m-d'); $khata_id = (int)($_POST['khata_id'] ?? 0); $shift = in_array($_POST['shift'] ?? '', ['Day','Night']) ? $_POST['shift'] : 'Day'; $status = trim($_POST['status'] ?? 'Running'); $remarks = substr(trim($_POST['remarks'] ?? ''), 0, 500); $machine_numbers = json_decode($_POST['machine_numbers'] ?? '[]', true); if ($khata_id <= 0) { $msg = 'Khata select karein.'; $msg_type = 'danger'; } elseif (!is_array($machine_numbers) || empty($machine_numbers)) { $msg = 'Kam se kam ek machine select karein.'; $msg_type = 'danger'; } else { try { $pdo->beginTransaction(); $khata_st = $pdo->prepare("SELECT machine_from, machine_to FROM khatas WHERE id = ? AND company_id = ? AND is_active = 1 LIMIT 1"); $khata_st->execute([$khata_id, $company_id]); $khata_row = $khata_st->fetch(PDO::FETCH_ASSOC); if (!$khata_row) { throw new Exception('Selected khata nahi mila.'); } $machine_from = (int)($khata_row['machine_from'] ?? 0); $machine_to = (int)($khata_row['machine_to'] ?? 0); if ($machine_from <= 0 || $machine_to <= 0 || $machine_from > $machine_to) { throw new Exception('Selected khata ka machine range invalid hai.'); } $selected_lookup = []; foreach ($machine_numbers as $machine_number) { $selected_lookup[(int)$machine_number] = true; } $machine_keys = []; $machine_labels = []; for ($mno = $machine_from; $mno <= $machine_to; $mno++) { $formatted_no = 'loom ' . str_pad($mno, 3, '0', STR_PAD_LEFT); $machine_labels[] = $formatted_no; $machine_keys[$mno] = strtolower(trim($formatted_no)); } $in = implode(',', array_fill(0, count($machine_labels), '?')); $existing_status_sql = sprintf( "SELECT machine_no, status FROM loom_machine_status WHERE company_id = ? AND shift = ? AND status_date = ? AND machine_no IN (%s)", $in ); $existing_status_st = $pdo->prepare($existing_status_sql); $existing_status_st->execute(array_merge([$company_id, $shift, $status_date], $machine_labels)); $existing_status_map = []; while ($existing_row = $existing_status_st->fetch(PDO::FETCH_ASSOC)) { $existing_machine_key = strtolower(trim((string)($existing_row['machine_no'] ?? ''))); if ($existing_machine_key !== '') { $existing_status_map[$existing_machine_key] = trim((string)($existing_row['status'] ?? '')); } } // Insert or Update logic $ins = $pdo->prepare(" INSERT INTO loom_machine_status (company_id, machine_no, shift, status, status_date, remarks, created_at) VALUES (:cid, :mc, :sh, :st, :dt, :rmk, NOW()) ON DUPLICATE KEY UPDATE status = VALUES(status), remarks = VALUES(remarks), updated_at = NOW() "); for ($mno = $machine_from; $mno <= $machine_to; $mno++) { // Formatting machine number as 'loom XXX' for consistency with your DB image $formatted_no = 'loom ' . str_pad($mno, 3, '0', STR_PAD_LEFT); $machine_key = $machine_keys[$mno] ?? strtolower(trim($formatted_no)); if (!isset($selected_lookup[$mno]) && isset($existing_status_map[$machine_key])) { continue; } $machine_status = isset($selected_lookup[$mno]) ? $status : 'Running'; $machine_remarks = $machine_status === 'Running' ? null : $remarks; $ins->execute([ ':cid' => $company_id, ':mc' => $formatted_no, ':sh' => $shift, ':st' => $machine_status, ':dt' => $status_date, ':rmk' => $machine_remarks ]); } $pdo->commit(); $msg = "Selected machines update ho gayi. Jinki koi status entry nahi thi unko Running set kar diya gaya."; } catch (Exception $e) { $pdo->rollBack(); $msg = "Error: " . $e->getMessage(); $msg_type = 'danger'; } } } /* ── Summary Query (Khata wise) ─────────────────────────────────────────── */ $sum_date = $_GET['sum_date'] ?? date('Y-m-d'); $sum_sql = " SELECT status, COUNT(*) as qty, GROUP_CONCAT(machine_no ORDER BY machine_no) as list FROM loom_machine_status WHERE company_id = :cid AND status_date = :dt GROUP BY status "; $sum_st = $pdo->prepare($sum_sql); $sum_st->execute([':cid' => $company_id, ':dt' => $sum_date]); $summary = $sum_st->fetchAll(PDO::FETCH_ASSOC); require_once __DIR__ . '/partials/header.php'; ?> <div class="container-fluid mt-3" style="max-width:900px;"> <div class="card mb-3 border-0 shadow-sm bg-primary text-white"> <div class="card-body py-3 d-flex justify-content-between align-items-center"> <h5 class="mb-0 fw-bold">Loom Machine Status Update</h5> <div class="small fw-normal">Default: Running</div> </div> </div> <?php if ($msg): ?> <div class="alert alert-<?= $msg_type ?> alert-dismissible fade show"> <?= htmlspecialchars($msg) ?> <button type="button" class="btn-close" data-bs-dismiss="alert"></button> </div> <?php endif; ?> <div class="card border-0 shadow-sm mb-4"> <div class="card-body"> <form method="POST" id="statusForm"> <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>"> <input type="hidden" name="machine_numbers" id="machine_numbers" value="[]"> <div class="row g-3 mb-4"> <div class="col-md-3 col-6"> <label class="form-label small fw-bold text-muted">Status Date</label> <input type="date" name="status_date" class="form-control" value="<?= date('Y-m-d') ?>" required> </div> <div class="col-md-3 col-6"> <label class="form-label small fw-bold text-muted">Shift</label> <select name="shift" class="form-select"> <option value="Day">Day</option> <option value="Night">Night</option> </select> </div> <div class="col-md-3"> <label class="form-label small fw-bold text-muted">Select Khata</label> <select name="khata_id" id="khata_sel" class="form-select" required onchange="buildPicker()"> <option value="">-- Select --</option> <?php foreach ($khatas as $k): ?> <option value="<?= $k['id'] ?>" data-from="<?= $k['machine_from'] ?>" data-to="<?= $k['machine_to'] ?>"> <?= htmlspecialchars($k['name']) ?> (<?= $k['machine_from'] ?>-<?= $k['machine_to'] ?>) </option> <?php endforeach; ?> </select> </div> <div class="col-md-3"> <label class="form-label small fw-bold text-muted">Machine Status</label> <select name="status" class="form-select bg-light fw-bold text-danger"> <?php foreach ($status_options as $status_option): ?> <option value="<?= htmlspecialchars($status_option) ?>" <?= $status_option === 'Running' ? 'selected' : '' ?> class="<?= strtolower($status_option) === 'running' ? 'text-success' : '' ?>"> <?= htmlspecialchars($status_option) ?> </option> <?php endforeach; ?> </select> </div> </div> <div class="mb-3"> <label class="form-label small fw-bold text-muted">Remarks (Optional)</label> <input type="text" name="remarks" class="form-control form-control-sm" placeholder="Kuch extra detail..."> </div> <!-- Machine Selection Area --> <div id="pickerWrap" class="p-3 border rounded bg-light d-none"> <div class="d-flex justify-content-between align-items-center mb-2"> <div class="fw-bold small text-primary text-uppercase">Select Machines</div> <button type="button" class="btn btn-sm btn-link text-decoration-none" onclick="clearSelection()">Clear All</button> </div> <div id="ind_buttons" class="d-flex flex-wrap gap-1"></div> <div id="sel_summary" class="mt-2 small fw-bold text-danger"></div> </div> <div class="mt-4 text-center"> <button type="submit" class="btn btn-primary px-5 shadow" onclick="return prepareSubmit()"> Save Machine Status </button> </div> </form> </div> </div> <!-- Summary Report Table --> <div class="card border-0 shadow-sm"> <div class="card-header bg-white fw-bold">Report: <?= date('d-m-Y', strtotime($sum_date)) ?></div> <div class="table-responsive"> <table class="table table-sm table-bordered mb-0 small"> <thead class="table-light"> <tr> <th>Status</th> <th class="text-center">Qty</th> <th>Machines</th> </tr> </thead> <tbody> <?php if(empty($summary)): ?> <tr><td colspan="3" class="text-center text-muted py-3">Aaj ki koi entry nahi hai.</td></tr> <?php else: foreach($summary as $s): ?> <tr> <td class="fw-bold <?= $s['status']=='Running'?'text-success':'text-danger' ?>"><?= $s['status'] ?></td> <td class="text-center fw-bold"><?= $s['qty'] ?></td> <td class="text-muted"><?= $s['list'] ?></td> </tr> <?php endforeach; endif; ?> </tbody> </table> </div> </div> </div> <script> let selected = new Set(); function buildPicker() { const sel = document.getElementById('khata_sel'); const opt = sel.options[sel.selectedIndex]; const wrap = document.getElementById('pickerWrap'); const btnContainer = document.getElementById('ind_buttons'); if (!opt || !opt.value) { wrap.classList.add('d-none'); return; } wrap.classList.remove('d-none'); btnContainer.innerHTML = ''; selected.clear(); updateSummary(); const from = parseInt(opt.dataset.from); const to = parseInt(opt.dataset.to); for (let n = from; n <= to; n++) { const btn = document.createElement('button'); btn.type = 'button'; btn.className = 'btn btn-outline-secondary btn-sm'; btn.style.minWidth = '45px'; btn.textContent = n; btn.onclick = () => { if (selected.has(n)) { selected.delete(n); btn.classList.replace('btn-danger', 'btn-outline-secondary'); } else { selected.add(n); btn.classList.replace('btn-outline-secondary', 'btn-danger'); } updateSummary(); }; btnContainer.appendChild(btn); } } function clearSelection() { selected.clear(); document.querySelectorAll('#ind_buttons button').forEach(b => { b.classList.replace('btn-danger', 'btn-outline-secondary'); }); updateSummary(); } function updateSummary() { const box = document.getElementById('sel_summary'); box.innerHTML = selected.size > 0 ? selected.size + ' machines selected' : ''; } function prepareSubmit() { if (selected.size === 0) { alert('Pehle machines select karein!'); return false; } document.getElementById('machine_numbers').value = JSON.stringify([...selected]); return true; } </script> <?php require_once __DIR__ . '/partials/footer.php'; ?>