« Back to History
loom_patia_karigar.php
|
20260920_164915.php
Initial Domain Snapshot
Copy Code
<?php /* ============================================================================= File: /erp/public/loom_patia_karigar.php Purpose: Patia report (Date × Machine grid) for a selected Karigar Filters: Khata, Karigar, Month, Half Extras: CSV Export, Print/PDF, role-based scoping Data: loom_production_entry.lines_json [{"date","karigar_id","meter"},...] Names: loom_karigar_master (id → karigar_name) Scope: Page-local only. No global/base changes. Company-scoped. ============================================================================= */ header('X-Frame-Options: SAMEORIGIN'); error_reporting(E_ALL); ini_set('display_errors', 1); /* ---------- [0] Auth ---------- */ require __DIR__ . '/../modules/auth/auth.php'; require_login(); $u = auth_user(); $company_id = (int)$u['company_id']; $user_id = (int)$u['id']; $role = strtolower($u['role'] ?? ''); $pdo = $GLOBALS['pdo'] ?? null; if (!$pdo) { require __DIR__ . '/../core/db.php'; } /* ---------- [0A] 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; } /* ---------- [1] Filters ---------- */ $today = new DateTime('now'); $month_str = gv('month', $today->format('Y-m')); $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); $karigar_id = (int)gv('karigar_id', 0); $do_csv = (int)gv('csv',0) === 1; /* ---------- [2] Role-based access: Owner/Admin full; Karigar = self only ---------- */ $allow = in_array($role, ['owner','admin'], true); $self_karigar_id = 0; if (!$allow && $role==='karigar') { if (_table_exists($pdo,'loom_karigar_login')) { $q=$pdo->prepare("SELECT karigar_id FROM loom_karigar_login WHERE company_id=? AND user_id=? LIMIT 1"); $q->execute([$company_id,$user_id]); $self_karigar_id = (int)$q->fetchColumn(); } if ($self_karigar_id>0) { $allow=true; $karigar_id=$self_karigar_id; } } if(!$allow){ http_response_code(403); echo "<h1>403</h1><p>Access denied. Only Owner/Admin or mapped Karigar can view.</p>"; exit; } /* ---------- [3] Khatas (with ranges) ---------- */ $KHATAS=[]; $KHATA_MAP=[]; if (_table_exists($pdo,'khatas')){ $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'] ]; } } /* ---------- [4] Karigar dropdown source ---------- */ $KARIGAR_LIST = []; // [{id,name}] if (_table_exists($pdo,'loom_karigar_master')){ $sql = "SELECT id, karigar_name, khata_id FROM loom_karigar_master WHERE company_id=?"; $args= [$company_id]; if ($khata_id>0){ $sql .= " AND khata_id=?"; $args[]=$khata_id; } $sql .= " ORDER BY karigar_name"; $q=$pdo->prepare($sql); $q->execute($args); foreach($q->fetchAll(PDO::FETCH_ASSOC) as $r){ $nm = trim((string)$r['karigar_name']); if($nm==='') $nm='Karigar#'.$r['id']; $KARIGAR_LIST[]=['id'=>(int)$r['id'],'name'=>$nm]; } } /* ---------- [5] Fetch entries (company/date + optional khata) ---------- */ $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; } $sql = "SELECT id, entry_date, machine_id, khata_id, lines_json FROM production_entry WHERE $where ORDER BY entry_date, id"; $stmt = $pdo->prepare($sql); $stmt->execute($params); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); /* ---------- [6] Build grid: Date × Machine (for selected karigar) ---------- */ $DATES = date_list($date_from,$date_to); $GRID=[]; $ROW_TOTAL=[]; $COL_TOTAL=[]; $GRAND=0.0; $MACHINE_SET = []; // machines where this karigar has meters foreach($DATES as $d){ $GRID[$d]=[]; $ROW_TOTAL[$d]=0.0; } if ($karigar_id>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); if ($kid !== $karigar_id) continue; // only selected karigar $mtr = (float)($line['meter'] ?? 0.0); if($mtr==0) continue; $dt = isset($line['date']) && $line['date'] ? substr($line['date'],0,10) : substr($r['entry_date'],0,10); if($dt<$date_from || $dt>$date_to) continue; $mc = (int)$r['machine_id']; if(!isset($GRID[$dt][$mc])) $GRID[$dt][$mc]=0.0; $GRID[$dt][$mc] += $mtr; $ROW_TOTAL[$dt] += $mtr; if(!isset($COL_TOTAL[$mc])) $COL_TOTAL[$mc]=0.0; $COL_TOTAL[$mc] += $mtr; $MACHINE_SET[$mc]=true; $GRAND += $mtr; } } } /* Machines for header: unique where this karigar produced (sorted asc) */ $MACHINES = array_keys($MACHINE_SET); sort($MACHINES); /* ---------- [7] CSV export ---------- */ if ($do_csv){ header('Content-Type: text/csv; charset=utf-8'); $kar_lbl = $karigar_id>0 ? $karigar_id : 'ALL'; header('Content-Disposition: attachment; filename=loom_patia_by_karigar_'.$kar_lbl.'_'.$month_str.'_H'.$half.'.csv'); $out = fopen('php://output','w'); $head = array_merge(['Date'], array_map(fn($m)=>'MC '.$m, $MACHINES), ['Day Total']); fputcsv($out,$head); foreach($DATES as $d){ $row = [$d]; foreach($MACHINES as $m){ $row[] = isset($GRID[$d][$m]) ? n($GRID[$d][$m],0) : ''; } $row[] = n($ROW_TOTAL[$d]??0,0); fputcsv($out,$row); } $last = array_merge(['TOTAL'], array_map(fn($m)=>n($COL_TOTAL[$m]??0,0), $MACHINES), [n($GRAND,0)]); fputcsv($out,$last); fclose($out); exit; } /* ---------- [8] 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); /* Karigar label for header */ $KNAME = 'Select Karigar'; if ($karigar_id>0){ foreach($KARIGAR_LIST as $k){ if($k['id']===$karigar_id){ $KNAME=$k['name']; break; } } if ($KNAME==='Select Karigar') $KNAME='Karigar#'.$karigar_id; } /* hide dropdown for mapped karigar */ $hide_dropdown = ($role==='karigar' && $self_karigar_id>0); ?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Patia (Karigar → Machine)</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">All Khata</option> <?php foreach($KHATAS as $k): ?> <option value="<?=h($k['id'])?>" <?= $khata_id===(int)$k['id']?'selected':''?>> <?=h($k['code'])?> — <?=h($k['name'])?> </option> <?php endforeach; ?> </select> </div> <!-- Karigar (hidden if mapped karigar login) --> <?php if(!$hide_dropdown): ?> <div class="field"> <label>Karigar</label> <select name="karigar_id" id="karigar"> <option value="0">Select Karigar</option> <?php foreach($KARIGAR_LIST as $k): ?> <option value="<?=h($k['id'])?>" <?= $karigar_id===$k['id']?'selected':''?>><?=h($k['name'])?></option> <?php endforeach; ?> </select> </div> <?php else: ?> <input type="hidden" name="karigar_id" value="<?=h($karigar_id)?>"> <div class="field"> <label>Karigar</label> <div class="pill">Your Data</div> </div> <?php endif; ?> <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,'karigar_id'=>$karigar_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> </div> </form> </div> <div class="card"> <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px"> <div> <strong>Patia (Karigar → Machine)</strong> <?php if($khata_id>0): ?><span class="pill">Khata <?=h($KHATA_MAP[$khata_id]['code']??$khata_id)?></span><?php endif; ?> <?php if($karigar_id>0): ?><span class="pill"><?=h($KNAME)?></span><?php endif; ?> </div> <div class="muted no-print">Unique Machines: <?=count($MACHINES)?> | Days: <?=count($DATES)?></div> </div> <?php if ($karigar_id<=0): ?> <div class="muted">Please select a Karigar (or login as Karigar).</div> <?php else: ?> <div style="overflow:auto;max-height:70vh"> <table> <thead> <tr> <th>Date</th> <?php foreach($MACHINES as $mc): ?> <th>MC <?=h($mc)?></th> <?php endforeach; ?> <th>Day Total</th> </tr> </thead> <tbody> <?php foreach($DATES as $d): ?> <tr> <td><?=h($d)?></td> <?php foreach($MACHINES as $mc): ?> <td><?= isset($GRID[$d][$mc]) ? n($GRID[$d][$mc],0) : '' ?></td> <?php endforeach; ?> <td><strong><?= n($ROW_TOTAL[$d]??0,0) ?></strong></td> </tr> <?php endforeach; ?> </tbody> <tfoot> <tr> <td><strong>TOTAL</strong></td> <?php foreach($MACHINES as $mc): ?> <td><strong><?= n($COL_TOTAL[$mc]??0,0) ?></strong></td> <?php endforeach; ?> <td><strong><?= n($GRAND,0) ?></strong></td> </tr> </tfoot> </table> </div> <?php endif; ?> </div> </div> </body> </html>