« Back to History
loom_patia_1_.php
|
20260721_154032.php
Initial Bulk Import
Copy Code
<?php /* ============================================================================= File: /public_html/karigar/loom_patia.php Purpose: Patia report (Date × Karigar grid) with dual access (Karigar or ERP) Filters: Khata → dependent Machine, Month, Half Extras: CSV Export, Print/PDF Scope: Page-local only. No global/base changes. ============================================================================= */ header('X-Frame-Options: SAMEORIGIN'); error_reporting(E_ALL); ini_set('display_errors', 1); /* ---------- [0] Dual Auth Bootstrap (karigar OR ERP) ---------- */ $CTX = ['mode'=>'none','company_id'=>0,'user_id'=>0,'role'=>'','karigar_id'=>0,'name'=>'']; /* Try karigar portal auth (non-blocking) */ $karigar_auth_file = __DIR__.'/_auth.php'; if (is_file($karigar_auth_file)) { require_once $karigar_auth_file; if (function_exists('karigar_user')) { $ku = karigar_user(); // NOTE: no karigar_require_login(); soft-detect only if (is_array($ku) && !empty($ku['karigar_id'])) { $CTX = [ 'mode' => 'karigar', 'company_id' => (int)$ku['company_id'], 'user_id' => (int)($ku['user_id'] ?? 0), 'role' => 'karigar', 'karigar_id' => (int)$ku['karigar_id'], 'name' => (string)($ku['name'] ?? 'Karigar') ]; } } } /* Try ERP auth if still none */ if ($CTX['mode']==='none') { $erp_auth = __DIR__.'/../erp/modules/auth/auth.php'; if (is_file($erp_auth)) { require_once $erp_auth; if (function_exists('auth_user')) { // don't redirect; only read if already logged-in $eu = auth_user(); if (is_array($eu) && !empty($eu['id'])) { $CTX = [ 'mode' => 'erp', 'company_id' => (int)$eu['company_id'], 'user_id' => (int)$eu['id'], 'role' => strtolower((string)$eu['role']), 'karigar_id' => 0, 'name' => (string)($eu['name'] ?? 'User') ]; } } } } /* If none → 403 */ if ($CTX['mode']==='none') { http_response_code(403); echo "<h1>403</h1><p>Please login: Karigar portal or ERP (Owner/Admin/Folder).</p>"; exit; } /* ---------- [0A] ERP role check (when mode=erp) ---------- */ $ALLOWED_ROLES = ['owner','admin','folder']; // case-insensitive $PAGE_KEY = 'loom_patia'; $has_access = ($CTX['mode']==='karigar'); // karigar always allowed (self data only) if ($CTX['mode']==='erp') { $has_access = in_array($CTX['role'], $ALLOWED_ROLES, true); } /* ---------- [1] DB ---------- */ require __DIR__ . '/../erp/core/db.php'; $pdo = $GLOBALS['pdo'] ?? $pdo; /* page_access override (ERP only, if role not in allowed) */ if ($CTX['mode']==='erp' && !$has_access) { try { $q = $pdo->prepare("SELECT 1 FROM page_access WHERE company_id=? AND page_key=? AND user_id=? AND (granted=1 OR granted IS NULL) LIMIT 1"); $q->execute([$CTX['company_id'], $PAGE_KEY, $CTX['user_id']]); $has_access = (bool)$q->fetchColumn(); } catch(Exception $e) { /* ignore */ } } if (!$has_access) { http_response_code(403); echo "<h1>403</h1><p>Access denied. Ask Owner to grant access.</p>"; exit; } /* ---------- [2] Helpers ---------- */ function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } function gv($k,$d=null){ return isset($_GET[$k]) ? (is_array($_GET[$k])?$_GET[$k]:trim((string)$_GET[$k])) : $d; } function n($v,$dec=0){ return number_format((float)$v, $dec, '.', ''); } function _table_exists(PDO $pdo, $name){ try { $pdo->query("SELECT 1 FROM `$name` LIMIT 1"); return true; } catch(Exception $e){ return false; } } function half_month_range(int $y,int $m,int $half){ $start = sprintf('%04d-%02d-%02d', $y, $m, $half===1?1:16); $end = (new DateTime("$y-$m-01"))->modify($half===1?'+14 days':'last day of this month')->format('Y-m-d'); return [$start,$end]; } function date_list($start,$end){ $out=[]; $d=new DateTime($start); $e=new DateTime($end); for(; $d <= $e; $d->modify('+1 day')) $out[]=$d->format('Y-m-d'); return $out; } /* ---------- [3] Filters ---------- */ $today = new DateTime('now'); $defY = (int)$today->format('Y'); $defM=(int)$today->format('m'); $month_str = gv('month', sprintf('%04d-%02d', $defY, $defM)); $half = (int)gv('half', 1); [$Y,$M] = array_map('intval', explode('-', $month_str)); [$date_from,$date_to] = half_month_range($Y,$M,$half); $khata_id = (int)gv('khata_id', 0); $machine_id = (int)gv('machine_id', 0); $do_csv = (int)gv('csv',0) === 1; $company_id = (int)$CTX['company_id']; $self_karigar_id = (int)$CTX['karigar_id']; /* ---------- [4] Khatas list (with machine ranges) ---------- */ $KHATAS=[]; $KHATA_MAP=[]; $st = $pdo->prepare("SELECT id, code, name, machine_from, machine_to FROM khatas WHERE company_id=? AND (is_active=1 OR is_active IS NULL) ORDER BY id"); $st->execute([$company_id]); foreach($st->fetchAll(PDO::FETCH_ASSOC) as $r){ $KHATAS[] = $r; $KHATA_MAP[(int)$r['id']] = [ 'code'=>$r['code'], 'name'=>$r['name'], 'from'=>(int)$r['machine_from'], 'to'=>(int)$r['machine_to'] ]; } /* ---------- [5] Dependent machine options ---------- */ $MACHINE_OPTS=[]; if ($khata_id>0 && isset($KHATA_MAP[$khata_id])){ $mf = (int)$KHATA_MAP[$khata_id]['from']; $mt=(int)$KHATA_MAP[$khata_id]['to']; if ($mf>0 && $mt >= $mf){ for($i=$mf;$i<=$mt;$i++) $MACHINE_OPTS[]=$i; } } else { $stmt=$pdo->prepare("SELECT DISTINCT machine_id FROM loom_production_entry WHERE company_id=? ORDER BY machine_id"); $stmt->execute([$company_id]); $MACHINE_OPTS = array_map(fn($r)=>(int)$r['machine_id'],$stmt->fetchAll(PDO::FETCH_ASSOC)); } /* ---------- [6] Fetch entries ---------- */ $params = [$company_id, $date_from, $date_to]; $where = "company_id=? AND entry_date BETWEEN ? AND ?"; if ($khata_id>0){ $where.=" AND khata_id=?"; $params[]=$khata_id; } if ($machine_id>0){ $where.=" AND machine_id=?"; $params[]=$machine_id; } $sql = "SELECT id, entry_date, machine_id, khata_id, lines_json, meter_total FROM loom_production_entry WHERE $where ORDER BY entry_date, id"; $stmt = $pdo->prepare($sql); $stmt->execute($params); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); /* ---------- [7] Build grid (Date × Karigar) ---------- */ $DATES = date_list($date_from,$date_to); $KARIGAR_SET = []; $GRID=[]; $ROW_TOTAL=[]; $COL_TOTAL=[]; $GRAND=0.0; foreach($DATES as $d){ $GRID[$d]=[]; $ROW_TOTAL[$d]=0.0; } foreach($rows as $r){ $ej = $r['lines_json']; if(!$ej) continue; $decoded = json_decode($ej,true); if(!is_array($decoded)) continue; if (isset($decoded['karigar_id']) || isset($decoded['meter'])) $decoded = [$decoded]; foreach($decoded as $line){ if(!is_array($line)) continue; $kid = (int)($line['karigar_id'] ?? 0); $mtr = (float)($line['meter'] ?? 0.0); $dt = isset($line['date']) && $line['date'] ? substr($line['date'],0,10) : substr($r['entry_date'],0,10); if($mtr==0) continue; if($dt<$date_from || $dt>$date_to) continue; // Karigar mode → only self data if ($self_karigar_id>0 && $kid !== $self_karigar_id) continue; $KARIGAR_SET[$kid]=true; if(!isset($GRID[$dt][$kid])) $GRID[$dt][$kid]=0.0; $GRID[$dt][$kid]+=$mtr; $ROW_TOTAL[$dt]+=$mtr; if(!isset($COL_TOTAL[$kid])) $COL_TOTAL[$kid]=0.0; $COL_TOTAL[$kid]+=$mtr; $GRAND += $mtr; } } $KARIGAR_IDS = array_keys($KARIGAR_SET); sort($KARIGAR_IDS); /* ---------- [8] Karigar names from loom_karigar_master ---------- */ $KNAME=[]; if($KARIGAR_IDS){ $in = implode(',', array_fill(0,count($KARIGAR_IDS),'?')); $args = array_merge([$company_id], $KARIGAR_IDS); $q = $pdo->prepare("SELECT id, karigar_name FROM loom_karigar_master WHERE company_id=? AND id IN ($in)"); $q->execute($args); foreach($q->fetchAll(PDO::FETCH_ASSOC) as $r){ $nm = trim((string)$r['karigar_name']); if($nm==='') $nm='Karigar#'.$r['id']; $KNAME[(int)$r['id']]=$nm; } } foreach($KARIGAR_IDS as $kid){ if(!isset($KNAME[$kid])) $KNAME[$kid]='Karigar#'.$kid; } /* ---------- [9] CSV export ---------- */ if ($do_csv){ header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename=loom_patia_'.$month_str.'_H'.$half.( $self_karigar_id?('_K'.$self_karigar_id):'' ).'.csv'); $out = fopen('php://output','w'); $head = array_merge(['Date'], array_map(fn($k)=>$KNAME[$k], $KARIGAR_IDS), ['Day Total']); fputcsv($out,$head); foreach($DATES as $d){ $row = [$d]; foreach($KARIGAR_IDS as $k){ $row[] = isset($GRID[$d][$k]) ? n($GRID[$d][$k],0) : ''; } $row[] = n($ROW_TOTAL[$d],0); fputcsv($out,$row); } $last = array_merge(['TOTAL'], array_map(fn($k)=>n($COL_TOTAL[$k]??0,0), $KARIGAR_IDS), [n($GRAND,0)]); fputcsv($out,$last); fclose($out); exit; } /* ---------- [10] UI ---------- */ $MM_GREEN='#34A853'; $MM_BG='#F5FFF7'; $MM_STONE='#5F6368'; $period_lbl = sprintf('%s (Half %d) [%s ➜ %s]', $month_str, $half, $date_from, $date_to); ?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Patia (Machine → Karigar) — Dual Access</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,'Helvetica Neue',Arial;margin:0;background:<?=h($MM_BG)?>;color:#222;} .wrap{max-width:1180px;margin:20px auto;padding:0 16px;} .card{background:#fff;border-radius:14px;box-shadow:0 6px 18px rgba(0,0,0,.06);padding:14px 16px;margin-bottom:14px;} .row{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end} .field{display:flex;flex-direction:column;min-width:160px} label{font-size:12px;color:<?=$MM_STONE?>;margin-bottom:4px} select,input[type="month"]{padding:8px 10px;border:1px solid #ddd;border-radius:10px} .btn{background:<?=$MM_GREEN?>;color:#fff;border:none;border-radius:10px;padding:10px 14px;cursor:pointer} .btn-outline{background:#fff;color:<?=$MM_GREEN?>;border:1px solid <?=$MM_GREEN?>} .pill{display:inline-block;padding:6px 10px;background:#eaf7ee;border-radius:999px;color:#0b6e2b;font-size:12px;margin-left:6px} table{width:100%;border-collapse:separate;border-spacing:0;margin-top:10px} th,td{border-bottom:1px solid #eee;padding:8px 10px;text-align:right;white-space:nowrap} th:first-child,td:first-child{text-align:left;position:sticky;left:0;background:#fff} thead th{position:sticky;top:0;background:#fafafa} tfoot td{font-weight:600;background:#fafafa} .muted{color:<?=$MM_STONE?>} @media print{ .no-print{display:none !important;} body{background:#fff;} .wrap{max-width:100%;margin:0;padding:0;} .card{box-shadow:none;border-radius:0;margin:0;padding:0;} thead{display:table-header-group} tfoot{display:table-footer-group} } </style> </head> <body> <div class="wrap"> <div class="card no-print"> <form class="row" method="get" id="filterForm"> <!-- Khata --> <div class="field"> <label>Khata</label> <select name="khata_id" id="khata"> <option value="0" data-from="0" data-to="0">All Khata</option> <?php foreach($KHATAS as $k): ?> <option value="<?=h($k['id'])?>" data-from="<?=h((int)$k['machine_from'])?>" data-to="<?=h((int)$k['machine_to'])?>" <?= $khata_id===(int)$k['id']?'selected':''?>> <?=h($k['code'])?> — <?=h($k['name'])?> </option> <?php endforeach; ?> </select> </div> <!-- Dependent Machine --> <div class="field"> <label>Machine</label> <select name="machine_id" id="machine"> <option value="0">All Machines</option> <?php foreach($MACHINE_OPTS as $mid): ?> <option value="<?=h($mid)?>" <?= $machine_id===$mid?'selected':''?>>MC <?=h($mid)?></option> <?php endforeach; ?> </select> </div> <div class="field"> <label>Month</label> <input type="month" name="month" value="<?=h($month_str)?>"> </div> <div class="field"> <label>Half</label> <select name="half"> <option value="1" <?= $half===1?'selected':''?>>1–15</option> <option value="2" <?= $half===2?'selected':''?>>16–End</option> </select> </div> <div class="field"> <button class="btn" type="submit">Apply</button> </div> <div class="field"> <a class="btn btn-outline" href="?<?=http_build_query([ 'khata_id'=>$khata_id,'machine_id'=>$machine_id,'month'=>$month_str,'half'=>$half,'csv'=>1 ])?>">Export CSV</a> </div> <div class="field"> <button type="button" class="btn" onclick="window.print()">Print</button> </div> <div class="field"> <button type="button" class="btn btn-outline" onclick="window.print()">PDF</button> </div> <div style="margin-left:auto" class="muted"> Period: <span class="pill"><?=h($period_lbl)?></span> <?php if($self_karigar_id): ?><span class="pill">Your Data</span><?php endif; ?> </div> </form> </div> <div class="card"> <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px"> <div> <strong>Patia</strong> <?php if($khata_id>0): ?><span class="pill">Khata <?=h($KHATA_MAP[$khata_id]['code']??$khata_id)?></span><?php endif; ?> <?php if($machine_id>0): ?><span class="pill">MC <?=h($machine_id)?></span><?php endif; ?> </div> <div class="muted no-print"> <?= $self_karigar_id ? 'Karigar: only you' : ('Unique Karigar: '.count($KARIGAR_IDS)) ?> | Days: <?=count($DATES)?> </div> </div> <?php if (!$rows): ?> <div class="muted">No entries found in selected period/filters.</div> <?php else: ?> <div style="overflow:auto;max-height:70vh"> <table> <thead> <tr> <th>Date</th> <?php foreach($KARIGAR_IDS as $kid): ?> <th><?=h($KNAME[$kid])?></th> <?php endforeach; ?> <th>Day Total</th> </tr> </thead> <tbody> <?php foreach($DATES as $d): ?> <tr> <td><?=h($d)?></td> <?php foreach($KARIGAR_IDS as $kid): ?> <td><?= isset($GRID[$d][$kid]) ? n($GRID[$d][$kid],0) : '' ?></td> <?php endforeach; ?> <td><strong><?= n($ROW_TOTAL[$d],0) ?></strong></td> </tr> <?php endforeach; ?> </tbody> <tfoot> <tr> <td><strong>TOTAL</strong></td> <?php foreach($KARIGAR_IDS as $kid): ?> <td><strong><?= n($COL_TOTAL[$kid]??0,0) ?></strong></td> <?php endforeach; ?> <td><strong><?= n($GRAND,0) ?></strong></td> </tr> </tfoot> </table> </div> <?php endif; ?> </div> </div> <script> // Dependent Machine options from selected Khata (function(){ const khata = document.getElementById('khata'); const machine = document.getElementById('machine'); function rebuildMachine(){ const opt = khata.options[khata.selectedIndex]; const from = parseInt(opt.getAttribute('data-from')||'0',10); const to = parseInt(opt.getAttribute('data-to')||'0',10); const current = machine.value; machine.innerHTML = ''; const oAll = document.createElement('option'); oAll.value='0'; oAll.textContent='All Machines'; machine.appendChild(oAll); if(from>0 && to>=from){ for(let i=from;i<=to;i++){ const o=document.createElement('option'); o.value=String(i); o.textContent='MC '+i; machine.appendChild(o); } } if([...machine.options].some(o=>o.value===current)){ machine.value=current; } } khata.addEventListener('change', rebuildMachine); })(); </script> </body> </html>