« Back to History
daily_report.php
|
20260721_154032.php
Initial Bulk Import
Copy Code
<?php /* ============================================================================= File: /erp/daily_report.php Title: (Company) Daily Report — Pissing • Pasaria • Beam Entry • Folding (IN/OUT/Stock) Scope: Page-local only. NO global/base edits. Updated: uses page_acl auth pattern. Quality resolution tuned: - Beam rows -> beam_qualities table - Folding rows -> qualities table ============================================================================= */ header('X-Frame-Options: SAMEORIGIN'); error_reporting(E_ALL); ini_set('display_errors', 1); require_once __DIR__ . '/modules/auth/page_acl.php'; $ctx = page_require_access('taka_out_entry'); $u = $ctx['user'] ?? null; $COMPANY_ID = (int)($ctx['company_id'] ?? 0); $USER_ID = (int)($u['id'] ?? 0); $pdo = $ctx['pdo'] ?? null; /* CSRF init */ if (!isset($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } $company_id = (int) $COMPANY_ID; /* --- Helpers (page-only) ---------------------------------------------- */ function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } function table_exists(PDO $pdo, string $name): bool { try { $q=$pdo->prepare("SHOW TABLES LIKE ?"); $q->execute([$name]); return (bool)$q->fetchColumn(); } catch(Exception $e){ return false; } } function columns_of(PDO $pdo, string $table): array { static $cache = []; if (isset($cache[$table])) return $cache[$table]; $cols = []; try { $stmt = $pdo->query("DESCRIBE `$table`"); while ($r=$stmt->fetch(PDO::FETCH_ASSOC)) $cols[]=$r['Field']; } catch(Exception $e){} return $cache[$table]=$cols; } function pick_col(array $cols, array $candidates){ foreach ($candidates as $c) if (in_array($c, $cols, true)) return $c; return null; } function pick_first_existing(array $row, array $candidates){ foreach ($candidates as $c) if (array_key_exists($c,$row) && $row[$c]!==null && $row[$c]!=='') return $c; return null; } function fetch_company_name(PDO $pdo, $company_id): string { $company_id = is_numeric($company_id) ? (int)$company_id : 0; if ($company_id <= 0) return 'Maa Sharda Textile'; $name = ''; foreach (['companies','company'] as $tbl) { if (!table_exists($pdo,$tbl)) continue; $cols = columns_of($pdo,$tbl); $nameCol = pick_col($cols, ['name','company_name','title']); if (!$nameCol) continue; $stmt = $pdo->prepare("SELECT `$nameCol` AS n FROM `$tbl` WHERE id = :id LIMIT 1"); $stmt->execute([':id'=>$company_id]); $name = (string)($stmt->fetchColumn() ?: ''); if ($name) break; } if (!$name) $name = 'Maa Sharda Textile'; return $name; } function resolve_employee_name(PDO $pdo, $row): string { static $cache = []; $inlineNameKey = pick_first_existing($row, ['employee_name','emp_name','karigar_name','worker_name','pasaria_name']); if ($inlineNameKey) { $n = trim((string)$row[$inlineNameKey]); if ($n !== '') return $n; } $idKey = pick_first_existing($row, ['employee_id','karigar_id','warper_id','user_id','created_by']); if ($idKey && is_numeric($row[$idKey])) { $id = (int)$row[$idKey]; if (isset($cache[$id])) return $cache[$id]; $sources = [ ['tbl'=>'employees', 'nameCols'=>['name','full_name','employee_name']], ['tbl'=>'company_employee_master','nameCols'=>['name','full_name','employee_name']], ['tbl'=>'loom_karigar_master', 'nameCols'=>['name','karigar_name']], ['tbl'=>'users', 'nameCols'=>['name']], ]; foreach ($sources as $src) { if (!table_exists($pdo, $src['tbl'])) continue; $cols = columns_of($pdo, $src['tbl']); $nameCol = pick_col($cols, $src['nameCols']); if (!$nameCol || !in_array('id',$cols,true)) continue; $st = $pdo->prepare("SELECT `$nameCol` AS n FROM `{$src['tbl']}` WHERE id=:id LIMIT 1"); $st->execute([':id'=>$id]); $n = (string)($st->fetchColumn() ?: ''); if ($n) { $cache[$id] = $n; return $n; } } return "ID $id"; } return ''; } /* ------------------------------------------------------------------------ Robust generic quality resolver (final tuned version) - Beam rows => resolve from beam_qualities table - Folding rows => resolve from qualities table - Uses inline fields if present ------------------------------------------------------------------------ */ function resolve_quality_name(PDO $pdo, $row): string { static $cache = []; // Inline text quality? $inline = pick_first_existing($row, ['quality','quality_name','quality_label','name','title']); if ($inline && trim((string)$row[$inline]) !== '') { return trim((string)$row[$inline]); } // quality_id? $qidKey = pick_first_existing($row, ['quality_id','q_id','qualityId','qid']); if (!$qidKey || !is_numeric($row[$qidKey])) { return ''; } $qid = (int)$row[$qidKey]; if ($qid === 0) return ''; if (isset($cache[$qid])) return $cache[$qid]; /* -------------------------------------------------------- TABLE DETECTION LOGIC - Beam rows usually have beam_no OR warping_rate - Folding rows usually have saree_no / taka_no (and no beam_no) -------------------------------------------------------- */ $isBeam = false; if (array_key_exists('beam_no', $row) || array_key_exists('warping_rate', $row) || array_key_exists('slot_pref', $row)) { $isBeam = true; } /* CASE 1: BEAM ENTRY -> beam_qualities */ if ($isBeam) { if (table_exists($pdo, 'beam_qualities')) { $cols = columns_of($pdo,'beam_qualities'); $nameCol = pick_col($cols, ['name','quality_name','label','title','quality_label']); if ($nameCol && in_array('id',$cols,true)) { try { $st = $pdo->prepare("SELECT `$nameCol` FROM beam_qualities WHERE id=:id LIMIT 1"); $st->execute([':id'=>$qid]); $name = (string)($st->fetchColumn() ?: ''); if ($name !== '') { $cache[$qid] = $name; return $name; } } catch (Throwable $e) { error_log("resolve_quality_name: beam_qualities lookup failed: ".$e->getMessage()); } } } // also try beam_quality (singular) as alternative if (table_exists($pdo, 'beam_quality')) { $cols = columns_of($pdo,'beam_quality'); $nameCol = pick_col($cols, ['name','quality_name','label','title','quality_label']); if ($nameCol && in_array('id',$cols,true)) { try { $st = $pdo->prepare("SELECT `$nameCol` FROM beam_quality WHERE id=:id LIMIT 1"); $st->execute([':id'=>$qid]); $name = (string)($st->fetchColumn() ?: ''); if ($name !== '') { $cache[$qid] = $name; return $name; } } catch (Throwable $e) { error_log("resolve_quality_name: beam_quality lookup failed: ".$e->getMessage()); } } } } /* CASE 2: FOLDING / GENERIC -> qualities */ if (table_exists($pdo,'qualities')) { $cols = columns_of($pdo,'qualities'); $nameCol = pick_col($cols, ['quality_name','name','title','label']); if ($nameCol && in_array('id',$cols,true)) { try { $st = $pdo->prepare("SELECT `$nameCol` FROM qualities WHERE id=:id LIMIT 1"); $st->execute([':id'=>$qid]); $name = (string)($st->fetchColumn() ?: ''); if ($name !== '') { $cache[$qid] = $name; return $name; } } catch (Throwable $e) { error_log("resolve_quality_name: qualities lookup failed: ".$e->getMessage()); } } } /* fallback: try loom_quality_master etc. */ $candidates = [ ['tbl'=>'loom_quality_master','nameCols'=>['quality','name','title','label']], ['tbl'=>'loom_quality','nameCols'=>['name','quality_name','label','title']], ]; foreach ($candidates as $cand) { if (!table_exists($pdo,$cand['tbl'])) continue; $cols = columns_of($pdo,$cand['tbl']); if (!in_array('id',$cols,true)) continue; $nameCol = pick_col($cols, $cand['nameCols']); if (!$nameCol) continue; try { $st = $pdo->prepare("SELECT `$nameCol` FROM {$cand['tbl']} WHERE id=:id LIMIT 1"); $st->execute([':id'=>$qid]); $n = (string)($st->fetchColumn() ?: ''); if ($n !== '') { $cache[$qid] = $n; return $n; } } catch (Throwable $e) { error_log("resolve_quality_name: {$cand['tbl']} lookup failed: ".$e->getMessage()); continue; } } // If still nothing, return placeholder so caller sees an id existed $cache[$qid] = "QID $qid"; return $cache[$qid]; } /* --- Date (default: yesterday IST) ----------------------------------- */ date_default_timezone_set('Asia/Kolkata'); $today = new DateTime('today'); $yesterday = (clone $today)->modify('-1 day'); $pickedDate = (isset($_GET['date']) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $_GET['date'])) ? DateTime::createFromFormat('Y-m-d', $_GET['date']) : $yesterday; $DATE = $pickedDate->format('Y-m-d'); $FNAME_DATE = $pickedDate->format('d-m-y'); /* --- Data fetch blocks ---------------------------------------------- */ $beamRows = (function() use($pdo,$company_id,$DATE){ $t='beam_entry'; if(!table_exists($pdo,$t)) return []; $cols=columns_of($pdo,$t); $dateCol = pick_col($cols,['entry_date','date','work_date','created_at']) ?: 'created_at'; $st=$pdo->prepare("SELECT * FROM `$t` WHERE " . ($company_id>0 ? "company_id=:cid AND " : "") . "DATE(`$dateCol`)=:d ORDER BY id DESC"); $params = [':d'=>$DATE]; if ($company_id>0) $params[':cid']=$company_id; $st->execute($params); return $st->fetchAll(PDO::FETCH_ASSOC); })(); $pissingRows = (function() use($pdo,$company_id,$DATE){ $t = 'beam_load_data'; if (!table_exists($pdo, $t)) return []; $sql = " SELECT id, company_id, machine_type, machine_no, beam_no, beam_slot, quality_id, employee_id, load_date AS entry_date, 'Pissing' AS job_type FROM {$t} WHERE load_type = 'pissing' AND company_id = :cid AND DATE(load_date) = :d ORDER BY id DESC "; $st = $pdo->prepare($sql); $st->execute([ ':cid' => $company_id, ':d' => $DATE ]); return $st->fetchAll(PDO::FETCH_ASSOC); })(); $pasariaRows = (function() use($pdo,$company_id,$DATE){ if (table_exists($pdo,'pasaria_entry')) { $t='pasaria_entry'; $cols=columns_of($pdo,$t); $dateCol = pick_col($cols,['entry_date','date','work_date','created_at']) ?: 'created_at'; $st=$pdo->prepare("SELECT * FROM `$t` WHERE " . ($company_id>0?"company_id=:cid AND ":"") . "DATE(`$dateCol`)=:d ORDER BY id DESC"); $params=[':d'=>$DATE]; if ($company_id>0) $params[':cid']=$company_id; $st->execute($params); return $st->fetchAll(PDO::FETCH_ASSOC); } $t='pissing_entry'; if(!table_exists($pdo,$t)) return []; $cols=columns_of($pdo,$t); $dateCol = pick_col($cols,['entry_date','date','work_date','created_at']) ?: 'created_at'; $jobCol = pick_col($cols,['job_type','type','pissing_type']); if ($jobCol) { $sql="SELECT * FROM `$t` WHERE " . ($company_id>0?"company_id=:cid AND ":"") . "DATE(`$dateCol`)=:d AND `$jobCol` LIKE '%Pasaria%' ORDER BY id DESC"; } else { $sql="SELECT * FROM `$t` WHERE 1=0"; } $st=$pdo->prepare($sql); $params=[':d'=>$DATE]; if ($company_id>0) $params[':cid']=$company_id; $st->execute($params); return $st->fetchAll(PDO::FETCH_ASSOC); })(); /* Folding fetch (IN / OUT) */ $fetch_folding = function($pdo, $company_id, $date) { $inCandidates = ['folding_in_entry','folding_in','folding_entry']; $outCandidates = ['folding_out_entry','folding_out']; $inTable = null; foreach ($inCandidates as $t) { if (table_exists($pdo,$t)) { $inTable=$t; break; } } $outTable = null; foreach ($outCandidates as $t) { if (table_exists($pdo,$t)) { $outTable=$t; break; } } $fetchRows = function($pdo, $tbl, $company_id, $date) { $rows = []; if (!table_exists($pdo,$tbl)) return $rows; $cols = columns_of($pdo,$tbl); $dateCol = pick_col($cols,['entry_date','date','work_date','created_at']) ?: (in_array('created_at',$cols)?'created_at':(in_array('date',$cols)?'date':($cols[0] ?? 'created_at'))); $sql = "SELECT * FROM `{$tbl}` WHERE "; $params = []; if ($company_id>0) { $sql .= "company_id = :cid AND "; $params[':cid']=$company_id; } $sql .= "DATE(`{$dateCol}`) = :d ORDER BY id DESC"; $params[':d']=$date; try { $st = $pdo->prepare($sql); $st->execute($params); $rows = $st->fetchAll(PDO::FETCH_ASSOC); } catch(Throwable $e){ error_log("fetchRows({$tbl}) ".$e->getMessage()); } return $rows; }; $res = ['in'=>[], 'out'=>[]]; if ($inTable) $res['in'] = $fetchRows($pdo, $inTable, $company_id, $date); if ($outTable) $res['out'] = $fetchRows($pdo, $outTable, $company_id, $date); return $res; }; $foldingRows = $fetch_folding($pdo, $company_id, $DATE); // ['in'=>[], 'out'=>[]] /* Header counts */ $loomCount = $rapierCount = 0; foreach ($pissingRows as $r){ $mtKey = pick_first_existing($r,['machine_type','loom_type','type_machine']); $mtVal = strtolower((string)($mtKey ? $r[$mtKey] : '')); if (strpos($mtVal,'rapier') !== false) $rapierCount++; elseif (strpos($mtVal,'loom') !== false) $loomCount++; } $beamNoSet = []; $totalTaka = 0; foreach ($beamRows as $r){ $bnKey = pick_first_existing($r,['beam_no','beam','pbn','sbn']); if ($bnKey) $beamNoSet[ trim((string)$r[$bnKey]) ] = true; $tkKey = pick_first_existing($r,['taka','taka_no','taka_count']); if ($tkKey && is_numeric($r[$tkKey])) $totalTaka += (int)$r[$tkKey]; } $totalBeams = count($beamNoSet) ?: count($beamRows); $companyName = fetch_company_name($pdo, $company_id); /* CSV export handling (raw rows + folding) */ $export = isset($_GET['export']) ? strtolower($_GET['export']) : null; if ($export && in_array($export, ['pissing','pasaria','beam','csv','folding_in','folding_out','folding_stock'])) { $section = $export === 'csv' ? 'pissing' : $export; if ($section === 'folding_in') { $data = $foldingRows['in']; $filename = "folding_in_{$DATE}.csv"; } elseif ($section === 'folding_out') { $data = $foldingRows['out']; $filename = "folding_out_{$DATE}.csv"; } elseif ($section === 'folding_stock') { $inRows = $foldingRows['in']; $outRows = $foldingRows['out']; $inMap = []; $outMap = []; foreach ($inRows as $r) { $q = resolve_quality_name($pdo,$r) ?: 'UNKN'; $col = pick_first_existing($r,['total_taka','taka','taka_no','taka_count']); $val = is_numeric($r[$col]??null)?(float)$r[$col]:0; $inMap[$q]=($inMap[$q]??0)+$val; } foreach ($outRows as $r) { $q = resolve_quality_name($pdo,$r) ?: 'UNKN'; $col = pick_first_existing($r,['taka_no','taka','quantity','qty']); $val = is_numeric($r[$col]??null)?(float)$r[$col]:0; $outMap[$q]=($outMap[$q]??0)+$val; } $keys = array_unique(array_merge(array_keys($inMap), array_keys($outMap))); header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename="folding_stock_'.$DATE.'.csv"'); $out = fopen('php://output','w'); fputcsv($out, ['Quality','IN_Taka','OUT_Taka','STOCK_Taka']); foreach ($keys as $k) { $in=(float)($inMap[$k]??0); $outv=(float)($outMap[$k]??0); fputcsv($out, [$k,$in,$outv,$in-$outv]); } fclose($out); exit; } else { $section = $section === 'pissing' ? 'pissing' : ($section === 'pasaria' ? 'pasaria' : ($section === 'beam' ? 'beam' : $section)); $data = $section==='beam' ? $beamRows : ($section==='pasaria' ? $pasariaRows : $pissingRows); $filename = "daily_{$section}_{$DATE}.csv"; } header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename="'.$filename.'"'); $out = fopen('php://output','w'); if (!empty($data)) { $allKeys = array_keys(array_reduce($data,function($c,$r){foreach($r as $k=>$v)$c[$k]=1;return $c;},[])); fputcsv($out, $allKeys); foreach ($data as $r) fputcsv($out, array_map(fn($k)=>$r[$k]??'', $allKeys)); } else { fputcsv($out,['No data']); } fclose($out); exit; } /* PDF export helpers */ function ensure_dompdf_autoload() { $paths = [ __DIR__ . '/lib/dompdf/autoload.inc.php', __DIR__ . '/vendor/autoload.php', dirname(__DIR__) . '/vendor/autoload.php' ]; foreach ($paths as $p) { if (is_file($p)) { require_once $p; return true; } } return false; } function render_report_html($companyName, $DATE, $pickedDate, $pissingRows, $pasariaRows, $beamRows, $loomCount, $rapierCount, $totalBeams, $totalTaka, $pdo) { ob_start(); ?> <!doctype html><html><head><meta charset="utf-8"><title>(<?=h($companyName)?>) Daily Report</title> <link rel="stylesheet" href="/erp/public/assets/css/main.css?v=20250917"> <style>body{background:#fff;color:#111;font-family:Arial,Helvetica,sans-serif} .card{border:1px solid #eee;padding:8px;margin:6px 0}</style> </head><body> <h1>(<?=h($companyName)?>) Daily Report — <?=h($pickedDate->format('d M Y'))?></h1> <div class="card"><h2>Pissing (Rows: <?=count($pissingRows)?>)</h2> <?php if($pissingRows): ?> <table border="1" cellspacing="0" cellpadding="4"><thead><tr><th>#</th><th>Machine</th><th>Machine No</th><th>Beam</th><th>Quality</th><th>Employee</th><th>Type</th><th>Date</th></tr></thead><tbody> <?php foreach($pissingRows as $i=>$r): $machineType = $r[pick_first_existing($r,['machine_type','loom_type','type_machine'])] ?? ''; $machNo = $r[pick_first_existing($r,['machine_no','machine','loom_no'])] ?? ''; $beam = $r[pick_first_existing($r,['beam_no','beam','primary_beam','pbn'])] ?? ''; $qualName = resolve_quality_name($pdo, $r); $empName = resolve_employee_name($pdo, $r); $type = $r[pick_first_existing($r,['job_type','pissing_type','type'])] ?? ''; $dateVal = $r[pick_first_existing($r,['entry_date','date','work_date','created_at'])] ?? ''; ?> <tr><td><?=($i+1)?></td><td><?=h($machineType)?></td><td><?=h($machNo)?></td><td><?=h($beam)?></td><td><?=h($qualName)?></td><td><?=h($empName)?></td><td><?=h($type)?></td><td><?=h(substr($dateVal,0,16))?></td></tr> <?php endforeach; ?> </tbody></table> <?php else: ?><p>No pissing rows.</p><?php endif; ?> </div> <div class="card"><h2>Pasaria (Rows: <?=count($pasariaRows)?>)</h2> <?php if($pasariaRows): ?> <table border="1" cellspacing="0" cellpadding="4"><thead><tr><th>#</th><th>Machine No</th><th>Quality</th><th>Type</th><th>Employee</th><th>Date</th></tr></thead><tbody> <?php foreach($pasariaRows as $i=>$r): $machNo = $r[pick_first_existing($r,['machine_no','machine','loom_no'])] ?? ''; $qualName = resolve_quality_name($pdo, $r); $typeKey = pick_first_existing($r, ['pasaria_type','job_subtype','with_jog','jog_type','type_detail','job_type','type']); $typeVal = $typeKey ? (string)$r[$typeKey] : ''; $empName = resolve_employee_name($pdo, $r); $dateVal = $r[pick_first_existing($r,['entry_date','date','work_date','created_at'])] ?? ''; ?> <tr><td><?=($i+1)?></td><td><?=h($machNo)?></td><td><?=h($qualName)?></td><td><?=h($typeVal?:'Pasaria')?></td><td><?=h($empName)?></td><td><?=h(substr($dateVal,0,16))?></td></tr> <?php endforeach; ?> </tbody></table> <?php else: ?><p>No pasaria rows.</p><?php endif; ?> </div> <div class="card"><h2>Beam (Rows: <?=count($beamRows)?>) — Beams: <?= (int)$totalBeams ?> Taka: <?= (int)$totalTaka ?></h2> <?php if($beamRows): ?> <table border="1" cellspacing="0" cellpadding="4"><thead><tr><th>#</th><th>Beam No</th><th>Taka</th><th>Quality</th><th>Employee</th><th>Date</th></tr></thead><tbody> <?php foreach($beamRows as $i=>$r): $beam = $r[pick_first_existing($r,['beam_no'])] ?? ''; $taka = $r[pick_first_existing($r,['taka','taka_no','taka_count'])] ?? ''; $qual = resolve_quality_name($pdo, $r); // beam-specific detection inside resolver $empName = resolve_employee_name($pdo, $r); $dateVal = $r[pick_first_existing($r,['entry_date','date','work_date','created_at'])] ?? ''; ?> <tr><td><?=($i+1)?></td><td><?=h($beam)?></td><td><?=h($taka)?></td><td><?=h($qual)?></td><td><?=h($empName)?></td><td><?=h(substr($dateVal,0,16))?></td></tr> <?php endforeach; ?> </tbody></table> <?php else: ?><p>No beam rows.</p><?php endif; ?> </div> </body></html> <?php return ob_get_clean(); } /* If export=pdf requested, try Dompdf then wkhtmltopdf then fallback */ if ($export === 'pdf') { ensure_dompdf_autoload(); $html = render_report_html($companyName, $DATE, $pickedDate, $pissingRows, $pasariaRows, $beamRows, $loomCount, $rapierCount, $totalBeams, $totalTaka, $pdo); $pdfFilename = "Daily report " . $FNAME_DATE . ".pdf"; if (class_exists('\Dompdf\Dompdf')) { try { $dompdf = new \Dompdf\Dompdf(); $dompdf->set_option('isRemoteEnabled', true); $dompdf->loadHtml($html); $dompdf->setPaper('A4', 'landscape'); $dompdf->render(); $pdfOut = $dompdf->output(); header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="' . $pdfFilename . '"'); echo $pdfOut; exit; } catch (Throwable $e) { /* fallback */ } } $wk = null; try { $which = trim((string)@shell_exec('which wkhtmltopdf 2>/dev/null')); if ($which) $wk = $which; } catch(Throwable $e){ $wk=null; } if ($wk) { $tmpHtml = tempnam(sys_get_temp_dir(), 'dr_html_') . '.html'; $tmpPdf = tempnam(sys_get_temp_dir(), 'dr_pdf_') . '.pdf'; file_put_contents($tmpHtml, $html); $cmd = escapeshellcmd($wk) . ' --enable-local-file-access --page-size A4 --orientation Landscape ' . escapeshellarg($tmpHtml) . ' ' . escapeshellarg($tmpPdf) . ' 2>&1'; exec($cmd, $out, $ret); if ($ret === 0 && is_file($tmpPdf)) { header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="' . $pdfFilename . '"'); header('Content-Length: ' . filesize($tmpPdf)); readfile($tmpPdf); @unlink($tmpHtml); @unlink($tmpPdf); exit; } @unlink($tmpHtml); @unlink($tmpPdf); } header('Content-Type: text/html; charset=utf-8'); echo "<!doctype html><html><head><meta charset='utf-8'><title>Printable: " . h($companyName) . "</title>"; echo "<link rel='stylesheet' href='/erp/public/assets/css/main.css?v=20250917'>"; echo "<style>body{padding:12px} .notice{background:#fffae6;padding:8px;border:1px solid #f0e1b4}</style></head><body>"; echo "<div class='notice'>Server could not generate a PDF automatically. Use your browser Print → Save as PDF. Filename suggestion: <strong>" . h($pdfFilename) . "</strong></div>"; echo $html; echo "</body></html>"; exit; } /* --- Render normal HTML page with header/footer partials ------------- */ $possible_headers = [ __DIR__ . '/partials/header.php', __DIR__ . '/erp/partials/header.php', dirname(__DIR__) . '/erp/partials/header.php', dirname(__DIR__) . '/partials/header.php', ]; $header_included = false; foreach ($possible_headers as $p) { if (is_file($p)) { include $p; $header_included = true; break; } } ?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>(<?=h($companyName)?>) Daily Report — <?=h($DATE)?></title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/erp/public/assets/css/main.css?v=20250917"> <style> .wrap{max-width:1200px;margin:12px auto;padding:0 12px} .card{background:#fff;border-radius:12px;box-shadow:0 2px 6px rgba(0,0,0,.04);margin:12px 0;padding:0;border:1px solid #eef2f3;overflow:hidden} .card .hd{padding:10px 14px;border-bottom:1px solid #f6faf8} .pill{display:inline-block;padding:4px 8px;border-radius:999px;background:#fff3cd;border:1px solid #f1e7b5;margin-left:8px;font-size:12px} .muted{color:#6b7280} table{width:100%;border-collapse:collapse} th,td{padding:8px 10px;border-bottom:1px solid #f3f6f6;font-size:13px;vertical-align:top} th{background:#fafcfb;text-align:left} .top-actions{display:flex;gap:8px;align-items:center;margin-bottom:10px} .small{font-size:13px;color:#555} .export-btn{display:inline-block;padding:6px 10px;background:#0a58ca;color:#fff;border-radius:6px;text-decoration:none;margin-left:6px} .btn-print{display:inline-block;padding:6px 10px;background:#6c757d;color:#fff;border-radius:6px;text-decoration:none;margin-left:6px} </style> </head> <body> <?php if (! $header_included): ?> <header style="background:#f5f7f6;padding:10px;border-bottom:1px solid #e6ecea"> <div style="max-width:1200px;margin:0 auto;padding:0 12px"> <strong>(<?=h($companyName)?>)</strong> Daily Report — <?=h($pickedDate->format('d M Y'))?> </div> </header> <?php endif; ?> <div class="wrap"> <div class="top-actions"> <form method="get" style="margin:0;display:inline-flex;gap:8px;align-items:center"> <input type="date" name="date" value="<?=h($DATE)?>"> <button class="btn" type="submit">Load</button> </form> <div style="margin-left:auto"> <a class="export-btn" href="?date=<?=h($DATE)?>&export=pissing">Pissing CSV</a> <a class="export-btn" href="?date=<?=h($DATE)?>&export=pasaria">Pasaria CSV</a> <a class="export-btn" href="?date=<?=h($DATE)?>&export=beam">Beam CSV</a> <a class="export-btn" href="?date=<?=h($DATE)?>&export=folding_in">Folding IN CSV</a> <a class="export-btn" href="?date=<?=h($DATE)?>&export=folding_out">Folding OUT CSV</a> <a class="export-btn" href="?date=<?=h($DATE)?>&export=folding_stock">Folding STOCK CSV</a> <a class="btn-print" href="?date=<?=h($DATE)?>" onclick="window.print();return false;">Print</a> <a class="btn-print" href="?date=<?=h($DATE)?>&export=pdf">PDF</a> </div> </div> <!-- Pissing --> <section class="card"> <div class="hd"> <h3 style="margin:0">Pissing Entries <span class="pill">Loom: <?= (int)$loomCount ?></span> <span class="pill">Rapier: <?= (int)$rapierCount ?></span> <span class="pill"><?= count($pissingRows) ?> rows</span> </h3> </div> <div style="padding:10px"> <?php if (!$pissingRows): ?> <p class="muted">No pissing entries for this date.</p> <?php else: ?> <table> <thead><tr><th>#</th><th>Machine Type</th><th>Machine No</th><th>Beam</th><th>Quality</th><th>Employee Name</th><th>Pissing Type</th><th>Date</th></tr></thead> <tbody> <?php foreach ($pissingRows as $i=>$r): $machineType = $r[pick_first_existing($r,['machine_type','loom_type','type_machine'])] ?? ''; $machNo = $r[pick_first_existing($r,['machine_no','machine','loom_no'])] ?? ''; $beam = $r[pick_first_existing($r,['beam_no','beam','primary_beam','pbn'])] ?? ''; $qualName = resolve_quality_name($pdo, $r); $empName = resolve_employee_name($pdo, $r); $type = $r[pick_first_existing($r,['job_type','pissing_type','type'])] ?? 'Pissing'; $dateVal = $r[pick_first_existing($r,['entry_date','date','work_date','created_at'])] ?? ''; ?> <tr> <td><?=($i+1)?></td> <td><?=h($machineType)?></td> <td><?=h($machNo)?></td> <td><?=h($beam)?></td> <td><?=h($qualName)?></td> <td><?=h($empName)?></td> <td><?=h($type)?></td> <td><?=h(substr($dateVal,0,16))?></td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> </div> </section> <!-- Pasaria --> <section class="card"> <div class="hd"><h3 style="margin:0">Pasaria Entries <span class="pill"><?=count($pasariaRows)?> rows</span></h3></div> <div style="padding:10px"> <?php if (!$pasariaRows): ?> <p class="muted">No pasaria entries for this date.</p> <?php else: ?> <table> <thead><tr><th>#</th><th>Machine No</th><th>Quality</th><th>Pasaria Type</th><th>Pasaria Name</th><th>Date</th><th>Remarks</th></tr></thead> <tbody> <?php foreach ($pasariaRows as $i=>$r): $machNo = $r[pick_first_existing($r,['machine_no','machine','loom_no'])] ?? ''; $qualName = resolve_quality_name($pdo, $r); $typeKey = pick_first_existing($r, ['pasaria_type','job_subtype','with_jog','jog_type','type_detail','job_type','type']); $typeVal = $typeKey ? (string)$r[$typeKey] : ''; if ($typeVal) { if (stripos($typeVal,'with')!==false && stripos($typeVal,'jog')!==false) $typeVal = 'With JOG'; elseif (stripos($typeVal,'without')!==false && stripos($typeVal,'jog')!==false) $typeVal = 'Without JOG'; } $empName = resolve_employee_name($pdo, $r); $dateVal = $r[pick_first_existing($r,['entry_date','date','work_date','created_at'])] ?? ''; $remark = $r[pick_first_existing($r,['remarks','remark','note'])] ?? ''; ?> <tr> <td><?=($i+1)?></td> <td><?=h($machNo)?></td> <td><?=h($qualName)?></td> <td><?=h($typeVal ?: 'Pasaria')?></td> <td><?=h($empName)?></td> <td><?=h(substr($dateVal,0,16))?></td> <td><?=h($remark)?></td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> </div> </section> <!-- Beam --> <section class="card"> <div class="hd"><h3 style="margin:0">Beam Entry (Warping) <span class="pill">Total Beams: <?= (int)$totalBeams ?></span> <span class="pill">Total Taka: <?= (int)$totalTaka ?></span> <span class="pill"><?= count($beamRows) ?> rows</span> </h3></div> <div style="padding:10px"> <?php if (!$beamRows): ?> <p class="muted">No beam entries for this date.</p> <?php else: ?> <table> <thead><tr><th>#</th><th>Beam No</th><th>Taka</th><th>Quality</th><th>Employee Name</th><th>Date</th><th>Remarks</th></tr></thead> <tbody> <?php foreach ($beamRows as $i=>$r): $beam = $r[pick_first_existing($r,['beam_no'])] ?? ''; $taka = $r[pick_first_existing($r,['taka','taka_no','taka_count'])] ?? ''; $qual = resolve_quality_name($pdo, $r); // beam-specific detection inside resolver $empName = resolve_employee_name($pdo, $r) ?: ($r[pick_first_existing($r,['warper_name','employee_name'])] ?? ''); $dateVal = $r[pick_first_existing($r,['entry_date','date','work_date','created_at'])] ?? ''; $remark = $r[pick_first_existing($r,['remarks','remark','note'])] ?? ''; ?> <tr> <td><?=($i+1)?></td> <td><?=h($beam)?></td> <td><?=h($taka)?></td> <td><?=h($qual)?></td> <td><?=h($empName)?></td> <td><?=h(substr($dateVal,0,16))?></td> <td><?=h($remark)?></td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> </div> </section> <!-- Folding (IN / OUT / STOCK) --> <section class="card"> <div class="hd"><h3 style="margin:0">Folding — IN / OUT / STOCK</h3></div> <div style="padding:10px"> <?php $ins = $foldingRows['in'] ?? []; $outs = $foldingRows['out'] ?? []; $sum_in = 0; $in_by_q = []; foreach ($ins as $r) { $col = pick_first_existing($r, ['total_taka','taka','taka_no','taka_count']); $val = is_numeric($r[$col] ?? null) ? (float)$r[$col] : 0; $q = resolve_quality_name($pdo, $r) ?: 'UNKN'; $in_by_q[$q] = ($in_by_q[$q] ?? 0) + $val; $sum_in += $val; } $sum_out = 0; $out_by_q = []; foreach ($outs as $r) { $col = pick_first_existing($r, ['taka_no','taka','quantity','qty']); $val = is_numeric($r[$col] ?? null) ? (float)$r[$col] : 0; $q = resolve_quality_name($pdo, $r) ?: 'UNKN'; $out_by_q[$q] = ($out_by_q[$q] ?? 0) + $val; $sum_out += $val; } ?> <div class="small" style="margin-bottom:8px">IN Taka: <strong><?=h((int)$sum_in)?></strong> OUT Taka: <strong><?=h((int)$sum_out)?></strong> STOCK: <strong><?=h((int)($sum_in - $sum_out))?></strong></div> <h4>Stock by Quality</h4> <?php $keys = array_unique(array_merge(array_keys($in_by_q), array_keys($out_by_q))); if (empty($keys)) { echo "<p class='muted'>No folding data for this date.</p>"; } else { echo "<table><thead><tr><th>#</th><th>Quality</th><th>IN</th><th>OUT</th><th>STOCK</th></tr></thead><tbody>"; $i=0; foreach ($keys as $k) { $i++; $inval=(int)($in_by_q[$k] ?? 0); $outval=(int)($out_by_q[$k] ?? 0); echo "<tr><td>{$i}</td><td>".h($k)."</td><td>".h($inval)."</td><td>".h($outval)."</td><td>".h($inval-$outval)."</td></tr>"; } echo "</tbody></table>"; } ?> <h4 style="margin-top:12px">Folding IN Details (<?=count($ins)?>)</h4> <?php if (empty($ins)) { echo "<p class='muted'>No IN rows.</p>"; } else { ?> <table><thead><tr><th>#</th><th>Date</th><th>Quality</th><th>Taka</th><th>Meter</th><th>Saree</th><th>Remark</th></tr></thead><tbody> <?php foreach ($ins as $i=>$r): $dateVal = $r[pick_first_existing($r,['entry_date','date','work_date','created_at'])] ?? ''; $qual = resolve_quality_name($pdo,$r); $taka = $r[pick_first_existing($r,['total_taka','taka','taka_no','taka_count'])] ?? ''; $meter = $r[pick_first_existing($r,['total_meter','meter'])] ?? ''; $saree = $r[pick_first_existing($r,['total_saree','saree_no','saree'])] ?? ''; $remark = $r[pick_first_existing($r,['remark','remarks','note'])] ?? ''; ?> <tr><td><?=($i+1)?></td><td><?=h(substr($dateVal,0,16))?></td><td><?=h($qual)?></td><td><?=h($taka)?></td><td><?=h($meter)?></td><td><?=h($saree)?></td><td><?=h($remark)?></td></tr> <?php endforeach; ?> </tbody></table> <?php } ?> <h4 style="margin-top:12px">Folding OUT Details (<?=count($outs)?>)</h4> <?php if (empty($outs)) { echo "<p class='muted'>No OUT rows.</p>"; } else { ?> <table><thead><tr><th>#</th><th>Date</th><th>Quality</th><th>Taka</th><th>Saree No</th><th>Party</th><th>Remark</th></tr></thead><tbody> <?php foreach ($outs as $i=>$r): $dateVal = $r[pick_first_existing($r,['entry_date','date','work_date','created_at'])] ?? ''; $qual = resolve_quality_name($pdo,$r); $taka = $r[pick_first_existing($r,['taka_no','taka','quantity'])] ?? ''; $saree = $r[pick_first_existing($r,['saree_no','saree'])] ?? ''; $party = $r[pick_first_existing($r,['party','client'])] ?? ''; $remark = $r[pick_first_existing($r,['remark','remarks','note'])] ?? ''; ?> <tr><td><?=($i+1)?></td><td><?=h(substr($dateVal,0,16))?></td><td><?=h($qual)?></td><td><?=h($taka)?></td><td><?=h($saree)?></td><td><?=h($party)?></td><td><?=h($remark)?></td></tr> <?php endforeach; ?> </tbody></table> <?php } ?> </div> </section> </div> <?php /* footer include */ $possible_footers = [ __DIR__ . '/partials/footer.php', __DIR__ . '/erp/partials/footer.php', dirname(__DIR__) . '/erp/partials/footer.php', dirname(__DIR__) . '/partials/footer.php', ]; $footer_included = false; foreach ($possible_footers as $p) { if (is_file($p)) { include $p; $footer_included = true; break; } } if (! $footer_included) { echo '<footer style="text-align:center;padding:14px;color:#888">© ' . date('Y') . ' ' . h($companyName) . '</footer>'; } ?> </body> </html>