« Back to History
folding_entry.php
|
20260721_154032.php
Initial Bulk Import
Copy Code
<?php // ========================================================== // File: /erp/folding_entry.php // Updated complete: auto-select khata based on folder, uniqueness check // ========================================================== // ---------- Bootstrap & ACL ---------- require_once __DIR__ . '/modules/auth/page_acl.php'; $ctx = page_require_access('folding_entry'); // ensure ACL per project rules $pdo = $ctx['pdo'] ?? null; $company_id = (int)($ctx['company_id'] ?? 0); $user_id = (int)($ctx['user']['id'] ?? 0); require_once __DIR__ . '/helpers/activity_helper.php'; // ---------- Session / CSRF ---------- if (session_status() === PHP_SESSION_NONE) { session_start(); } if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(24)); } $csrf_token = $_SESSION['csrf_token']; // ---------- Helpers ---------- function e($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } // ---------- Lookups (robust & company-scoped) ---------- $folders = []; $khatas = []; $qualities = []; if ($pdo) { // FOLDERS: employees acting as Folder (department_id = 24, designation_id = 9) try { $sql = "SELECT id, name AS folder_name FROM company_employee_master WHERE company_id = :cid AND department_id = 24 AND designation_id = 9 ORDER BY name"; $stmt = $pdo->prepare($sql); $stmt->execute([':cid' => $company_id]); $folders = $stmt->fetchAll(PDO::FETCH_ASSOC); // fallback1: sometimes folder stored in company_machine_master if (empty($folders)) { $sql2 = "SELECT id, operation_name AS folder_name FROM company_machine_master WHERE company_id = :cid AND (department_name LIKE '%Folding%' OR operation_name LIKE '%Folder%') ORDER BY operation_name"; $stmt2 = $pdo->prepare($sql2); $stmt2->execute([':cid' => $company_id]); $folders = $stmt2->fetchAll(PDO::FETCH_ASSOC); } // fallback2: employees with designation_name LIKE 'Folder' if (empty($folders)) { $sql3 = "SELECT id, name AS folder_name FROM company_employee_master WHERE company_id = :cid AND designation_name LIKE '%Folder%' ORDER BY name"; $stmt3 = $pdo->prepare($sql3); $stmt3->execute([':cid' => $company_id]); $folders = $stmt3->fetchAll(PDO::FETCH_ASSOC); } } catch (Exception $ex) { $folders = []; } // KHATAS: use table `khatas` (column `name`, `code`) per your screenshot try { $sql = "SELECT id, name AS khata_name, code FROM khatas WHERE company_id = :cid ORDER BY name"; $stmt = $pdo->prepare($sql); $stmt->execute([':cid' => $company_id]); $khatas = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (Exception $ex) { $khatas = []; } // QUALITIES: table `qualities` (column `quality_name`) try { $sql = "SELECT id, quality_name FROM qualities WHERE company_id = :cid ORDER BY quality_name"; $stmt = $pdo->prepare($sql); $stmt->execute([':cid' => $company_id]); $qualities = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (Exception $ex) { $qualities = []; } } // Build mapping in PHP: map folder name (lowercase) -> khata id using khata code // Requested mapping: Satish -> MST1, Raj Kishor -> MST2A, Grish/Greesh -> MST2B $khataCodeToId = []; foreach ($khatas as $k) { $code = strtolower(trim($k['code'] ?? '')); if ($code !== '') $khataCodeToId[$code] = (int)$k['id']; } // Now build name->khataId mapping for JS $autoMap = []; if (isset($khataCodeToId['mst1'])) { $autoMap['satish'] = $khataCodeToId['mst1']; } if (isset($khataCodeToId['mst2a'])) { $autoMap['raj kishor'] = $khataCodeToId['mst2a']; } if (isset($khataCodeToId['mst2b'])) { $autoMap['grish'] = $khataCodeToId['mst2b']; $autoMap['greesh'] = $khataCodeToId['mst2b']; $autoMap['grish '] = $khataCodeToId['mst2b']; } // ---------- POST processing ---------- $errors = []; $success = false; if ($_SERVER['REQUEST_METHOD'] === 'POST') { // CSRF $posted_csrf = $_POST['csrf_token'] ?? ''; if (!hash_equals($_SESSION['csrf_token'], (string)$posted_csrf)) { $errors[] = 'Invalid request (CSRF).'; } if (!$pdo) { $errors[] = 'Database connection unavailable.'; } // company check $posted_company = (int)($_POST['company_id'] ?? 0); if ($posted_company !== $company_id) { $errors[] = 'Company mismatch.'; } // sanitize inputs $entry_date = trim($_POST['entry_date'] ?? ''); $folder_id = (int)($_POST['folder_id'] ?? 0); $khata_id = (int)($_POST['khata_id'] ?? 0); $quality_id = (int)($_POST['quality_id'] ?? 0); $total_taka = trim($_POST['total_taka'] ?? ''); $total_meter = trim($_POST['total_meter'] ?? ''); $total_saree = ($_POST['total_saree'] !== '') ? (int)$_POST['total_saree'] : null; $total_weight = trim($_POST['total_weight'] ?? ''); $remark = trim($_POST['remark'] ?? ''); // validations if ($entry_date === '') $errors[] = 'Date required.'; if ($folder_id <= 0) $errors[] = 'Select folder.'; if ($khata_id <= 0) $errors[] = 'Select khata.'; if ($quality_id <= 0) $errors[] = 'Select quality.'; // ---------- uniqueness check ---------- if (empty($errors)) { try { $chk = $pdo->prepare("SELECT COUNT(*) c FROM folding_entry WHERE company_id = :cid AND entry_date = :ed AND folder_id = :fid AND quality_id = :qid"); $chk->execute([':cid'=>$company_id, ':ed'=>$entry_date, ':fid'=>$folder_id, ':qid'=>$quality_id]); $c = (int)$chk->fetchColumn(); if ($c > 0) { $errors[] = 'An entry already exists for this date, folder and quality.'; } } catch (Exception $ex) { // fallthrough - don't block save on check failure, but log error_log("folding_entry uniqueness check failed: ".$ex->getMessage()); } } if (empty($errors)) { try { $pdo->beginTransaction(); $sql = "INSERT INTO folding_entry (company_id, entry_date, folder_id, khata_id, quality_id, total_taka, total_meter, total_saree, total_weight, remark, created_by, created_at) VALUES (:cid, :entry_date, :folder_id, :khata_id, :quality_id, :total_taka, :total_meter, :total_saree, :total_weight, :remark, :uid, NOW())"; $stmt = $pdo->prepare($sql); $stmt->execute([ ':cid' => $company_id, ':entry_date' => $entry_date, ':folder_id' => $folder_id, ':khata_id' => $khata_id, ':quality_id' => $quality_id, ':total_taka' => $total_taka !== '' ? $total_taka : null, ':total_meter' => $total_meter !== '' ? $total_meter : null, ':total_saree' => $total_saree, ':total_weight'=> $total_weight !== '' ? $total_weight : null, ':remark' => $remark !== '' ? $remark : null, ':uid' => $user_id ]); $pdo->commit(); activity_create('production', 'folding_entry_create', (int)$pdo->lastInsertId(), 'Created folding entry'); // regenerate CSRF and redirect to avoid resubmit $_SESSION['csrf_token'] = bin2hex(random_bytes(24)); header('Location: folding_entry.php?saved=1'); exit; } catch (Exception $ex) { if ($pdo && $pdo->inTransaction()) $pdo->rollBack(); $errors[] = 'Save failed: ' . $ex->getMessage(); } } } if (isset($_GET['saved']) && $_GET['saved'] == '1') { $success = true; } // ---------- Header include ---------- require_once __DIR__ . '/partials/header.php'; ?> <!-- main.css must contain .erp-entry-form, .ef-row, .ef-col, .ef-title, .ef-actions --> <link rel="stylesheet" href="/erp/public/assets/css/main.css?v=20251122"> <style> /* Strong responsive override for folding_entry - paste replacing old style */ /* Ensure mobile scaling (if not present in header) */ meta[name="viewport"] {} /* page container tiny padding */ .page-container { padding-left: 5px !important; padding-right: 5px !important; margin: 0 auto !important; } /* card - very small outer padding, less margin */ .erp-entry-form { background: #2e3b42; padding: 5px !important; /* as requested */ border-radius: 6px; max-width: 720px; width: calc(100% - 10px) !important; margin: 8px auto !important; /* reduced top/bottom margin */ color: #fff; box-shadow: 0 6px 16px rgba(0,0,0,0.18); box-sizing: border-box; } /* title */ .ef-title { text-align: center; font-size: 20px; margin: 8px 0 10px; font-weight: 600; } /* labels */ .erp-entry-form label { color: #fff !important; font-weight: 500; margin-bottom: 6px; } /* row/col base */ .ef-row { display: flex !important; gap: 10px !important; margin-bottom: 10px !important; align-items: flex-start; flex-wrap: nowrap !important; } .ef-col { flex: 1 1 50% !important; min-width: 0 !important; } /* inputs */ .ef-col input, .ef-col select, .ef-col textarea { padding: 8px 10px !important; border-radius: 6px !important; border: 1px solid #ccc !important; background: #fff !important; color: #111 !important; font-size: 14px !important; width: 100% !important; box-sizing: border-box !important; } /* actions */ .ef-actions { display:flex !important; gap:8px !important; flex-wrap:wrap !important; } .btn-success, .btn-secondary { padding:6px 12px !important; font-size:14px !important; } /* FORCE single column on mobile and narrow widths Use two breakpoints to catch emulator differences */ @media (max-width: 700px) { .ef-row { flex-direction: column !important; gap:8px !important; } .ef-col { flex: 1 1 100% !important; width:100% !important; } .erp-entry-form { width: calc(100% - 10px) !important; margin:8px 5px !important; padding:6px !important; } .ef-title { font-size:18px !important; margin-bottom:8px !important; } } /* Extra aggressive fallback for very narrow devices */ @media (max-width: 420px) { .page-container { padding-left:4px !important; padding-right:4px !important; } .erp-entry-form { padding:5px !important; border-radius:6px !important; margin:6px auto !important; } .ef-col input, .ef-col select, .ef-col textarea { padding:7px 8px !important; font-size:15px !important; } .ef-actions .btn-success, .ef-actions .btn-secondary { width:48%; min-width:120px; } } /* VERY IMPORTANT: override any theme-level float or display rules */ .ef-row, .ef-col, .erp-entry-form, .page-container { -webkit-box-sizing: border-box !important; -moz-box-sizing: border-box !important; box-sizing: border-box !important; } /* Debug helper — uncomment if you want to visually see element boundaries during testing .ef-row { outline: 1px dashed rgba(255,255,255,0.08) !important; } .ef-col { outline: 1px solid rgba(0,0,0,0.05) !important; } */ </style> <div class="page-container"> <div class="erp-entry-form"> <div class="ef-title">Folding entry</div> <?php if (!empty($errors)): ?> <div class="notice notice-danger" role="alert"> <ul> <?php foreach ($errors as $err): ?> <li><?= e($err) ?></li> <?php endforeach; ?> </ul> </div> <?php endif; ?> <?php if ($success): ?> <div class="notice notice-success">Saved successfully.</div> <?php endif; ?> <form id="foldingForm" method="post" autocomplete="off" novalidate> <input type="hidden" name="csrf_token" value="<?= e($csrf_token) ?>"> <input type="hidden" name="company_id" value="<?= e($company_id) ?>"> <input type="hidden" name="created_by" value="<?= e($user_id) ?>"> <div class="ef-row"> <div class="ef-col"> <label for="entry_date">Date</label> <input id="entry_date" name="entry_date" type="date" required value="<?= e(date('Y-m-d')) ?>"> </div> <div class="ef-col"> <label for="folder_id">Folder</label> <select id="folder_id" name="folder_id" required> <option value="">Select folder</option> <?php foreach ($folders as $f): ?> <option value="<?= e($f['id']) ?>"><?= e($f['folder_name'] ?? $f['name'] ?? '') ?></option> <?php endforeach; ?> </select> </div> </div> <div class="ef-row"> <div class="ef-col"> <label for="khata_id">Khata</label> <select id="khata_id" name="khata_id" required> <option value="">Select khata</option> <?php foreach ($khatas as $k): ?> <option value="<?= e($k['id']) ?>" data-code="<?= e($k['code']) ?>"><?= e($k['khata_name'] ?? $k['name'] ?? '') ?></option> <?php endforeach; ?> </select> </div> <div class="ef-col"> <label for="quality_id">Quality</label> <select id="quality_id" name="quality_id" required> <option value="">Select quality</option> <?php foreach ($qualities as $q): ?> <option value="<?= e($q['id']) ?>"><?= e($q['quality_name'] ?? $q['name'] ?? '') ?></option> <?php endforeach; ?> </select> </div> </div> <div class="ef-row"> <div class="ef-col"> <label for="total_taka">Total taka</label> <input id="total_taka" name="total_taka" type="text" placeholder="0-99"> </div> <div class="ef-col"> <label for="total_meter">Total meter</label> <input id="total_meter" name="total_meter" type="text"> </div> </div> <div class="ef-row"> <div class="ef-col"> <label for="total_saree">Total saree</label> <input id="total_saree" name="total_saree" type="number" min="0"> </div> <div class="ef-col"> <label for="total_weight">Total weight</label> <input id="total_weight" name="total_weight" type="text"> </div> </div> <div class="ef-row"> <div class="ef-col"> <label for="remark">Remark</label> <textarea id="remark" name="remark"></textarea> </div> </div> <div class="ef-row"> <div class="ef-col"> <div class="ef-actions"> <button class="btn btn-success" type="submit" id="btnSave">Submit</button> <button class="btn btn-secondary" type="button" onclick="window.location='folding_entry_report.php'">Report</button> </div> </div> </div> </form> </div> </div> <script> (function(){ const form = document.getElementById('foldingForm'); const btn = document.getElementById('btnSave'); // Auto-map from folder name -> khata id (provided by PHP) const autoMap = <?= json_encode($autoMap, JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP) ?> || {}; const folderEl = document.getElementById('folder_id'); const khataEl = document.getElementById('khata_id'); // helper: set khata select by id if option exists function setKhataById(id) { if (!id) return; const opt = khataEl.querySelector('option[value="'+id+'"]'); if (opt) { khataEl.value = id; khataEl.dispatchEvent(new Event('change')); } } // on folder change, try to auto select khata based on folder name mapping folderEl.addEventListener('change', function(){ const text = folderEl.options[folderEl.selectedIndex]?.text || ''; const key = (text || '').trim().toLowerCase(); if (key && autoMap[key]) { setKhataById(String(autoMap[key])); } }); // on page load, if folder already selected (edit/redirect after save), trigger mapping document.addEventListener('DOMContentLoaded', function(){ if (folderEl.value) { folderEl.dispatchEvent(new Event('change')); } }); form.addEventListener('submit', function(e){ // simple client validation for required fields const required = form.querySelectorAll('[required]'); for (let el of required){ if (!el.value){ e.preventDefault(); alert('Please fill: ' + (el.previousElementSibling ? el.previousElementSibling.textContent : el.name)); el.focus(); return false; } } // prevent double submit btn.disabled = true; btn.textContent = "Saving..."; }); })(); </script> <?php require_once __DIR__ . '/partials/footer.php'; ?>