« Back to History
new_loom_salary_report.php
|
20260721_154032.php
Initial Bulk Import
Copy Code
<?php /* new_loom_salary_report.php Salary Report (Machine Inline method) — parse lines_json via PHP (same aggregation as Machine Inline UI) - Module-local; no global setting changes. - Keep a backup before replacing existing files. */ header('X-Frame-Options: SAMEORIGIN'); error_reporting(E_ALL); ini_set('display_errors',0); /* [0] Auth + DB */ require __DIR__ . '/modules/auth/auth.php'; require_login(); $u = auth_user(); $company_id = (int)$u['company_id']; $user_id = (int)$u['id']; $pdo = $GLOBALS['pdo'] ?? null; if(!$pdo){ require __DIR__ . '/core/db.php'; } /* [0a] Optional PDF support */ $PDF_AVAILABLE = false; $autoload = __DIR__ . '/vendor/autoload.php'; if (is_file($autoload)) { require_once $autoload; $PDF_AVAILABLE = class_exists(\Dompdf\Dompdf::class); } /* Helpers */ function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } function gv($k,$d=null){ return isset($_GET[$k])?trim((string)$_GET[$k]):$d; } function pv($k,$d=null){ return isset($_POST[$k])?trim((string)$_POST[$k]):$d; } function safe_json($s){ $a=json_decode($s,true); return is_array($a)?$a:[]; } function yrmo_half_range(int $y,int $m,string $half): array { $start = sprintf('%04d-%02d-01',$y,$m); $end = date('Y-m-t', strtotime($start)); if($half==='1'){ $end = sprintf('%04d-%02d-15',$y,$m); } if($half==='2'){ $start = sprintf('%04d-%02d-16',$y,$m); } return [$start,$end]; } function label_for_period(int $y,int $m,string $half,string $from,string $to): string { if ($half==='F') return 'FULL '.date('M', mktime(0,0,0,$m,1,$y)).' '.$y; if ($half==='1') return '1-15 '.date('M', mktime(0,0,0,$m,1,$y)).' '.$y; if ($half==='2') return '16-END '.date('M', mktime(0,0,0,$m,1,$y)).' '.$y; return $from.' to '.$to; } /* Feature flag: prefer queue adjustments */ $FF_USE_QUEUE_ADJ = true; /* Filters */ $year = (int)gv('year', date('Y')); $month = (int)gv('month', date('n')); $half = gv('half','F'); // '1','2','F' [$date_from,$date_to] = yrmo_half_range($year,$month,$half); $khata_id = (int)gv('khata_id', 0); $machine_id= (int)gv('machine_id', 0); $period_label = label_for_period($year,$month,$half,$date_from,$date_to); /* Company name */ $company_name = "Company #$company_id"; try{ $st = $pdo->prepare("SELECT name FROM companies WHERE id=?"); $st->execute([$company_id]); $nm = $st->fetchColumn(); if($nm) $company_name = $nm; }catch(Throwable $e){} /* Load quality rates */ $QUALS=[]; $QUAL_RATE=[]; try{ $q = $pdo->prepare("SELECT quality_id AS id, quality_name AS name, rate FROM quality_rates WHERE company_id=? ORDER BY quality_name"); $q->execute([$company_id]); foreach($q as $r){ $id=(int)$r['id']; $QUALS[$id]=$r['name']; $QUAL_RATE[$id]=(float)$r['rate']; } }catch(Throwable $e){} /* Karigar master maps */ $KAR_NAME=[]; $KAR_ENTRY=[]; $KAR_KHATA_CODE=[]; $KAR_KHATA_ID=[]; try{ $st=$pdo->prepare("SELECT id, karigar_name, entry_name, khata_code, khata_id FROM loom_karigar_master WHERE company_id=? ORDER BY karigar_name"); $st->execute([$company_id]); foreach($st as $r){ $id=(int)$r['id']; $KAR_NAME[$id] = $r['karigar_name'] ?: ("Karigar #$id"); $KAR_ENTRY[$id] = $r['entry_name'] ?? ''; $KAR_KHATA_CODE[$id] = $r['khata_code'] ?? ''; $KAR_KHATA_ID[$id] = (int)($r['khata_id'] ?? 0); } }catch(Throwable $e){} /* Bank map (to split bank / cash totals) */ $HAS_BANK=[]; try{ $st=$pdo->prepare("SELECT karigar_id FROM loom_bank_master WHERE company_id=? AND (is_default=1 OR is_default IS NULL) AND (COALESCE(account_no,'')<>'' OR COALESCE(upi_id,'')<>'')"); $st->execute([$company_id]); foreach($st as $r) $HAS_BANK[(int)$r['karigar_id']] = true; }catch(Throwable $e){} /* =================================================================== Core aggregation: use the same method as Machine Inline UI: - Read loom_production_entry rows in range - json_decode(lines_json) and iterate ALL array items - collect meters per karigar x quality =================================================================== */ $_skipped_bad_date = 0; $_skipped_out_range = 0; $MTR = []; // $MTR[karigar_id][quality_id] = sum meters $MTR_KAR_TOT = []; // total per karigar $quality_set = []; $karigar_set = []; $from_ts = strtotime($date_from.' 00:00:00'); $to_ts = strtotime($date_to.' 23:59:59'); try { // Pull rows covering a little earlier window to allow lines with different date formats (same as your current module) $hdr_from = date('Y-m-d', strtotime($date_from.' -31 days')); $args = [$company_id, $hdr_from, $date_to]; $wh = "company_id=? AND entry_date BETWEEN ? AND ?"; if($khata_id>0){ $wh .= " AND khata_id=?"; $args[] = $khata_id; } if($machine_id>0){ $wh .= " AND machine_id=?"; $args[] = $machine_id; } $sel = $pdo->prepare("SELECT entry_date, machine_id, khata_id, quality_id, lines_json FROM loom_production_entry WHERE $wh ORDER BY entry_date, id"); $sel->execute($args); foreach($sel as $row){ $row_entry = substr((string)$row['entry_date'],0,10); if (!preg_match('/^\d{4}-\d{2}-\d{2}$/',$row_entry)) $row_entry = date('Y-m-d', strtotime($row['entry_date'])); $lines = safe_json($row['lines_json']); if(!is_array($lines)) continue; foreach($lines as $ln){ $kid = (int)($ln['karigar_id'] ?? 0); $m = (float)($ln['meter'] ?? 0); if($kid <= 0 || $m <= 0) continue; // Normalise date (fall back to entry date) $rawd = trim((string)($ln['date'] ?? '')); if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $rawd)) { $d = $rawd; } else { $ts = strtotime($rawd); $d = $ts ? date('Y-m-d', $ts) : $row_entry; } $ts = strtotime($d); if(!$ts){ $_skipped_bad_date++; $ts = strtotime($row_entry); $d = $row_entry; } if($ts < $from_ts || $ts > $to_ts){ $_skipped_out_range++; continue; } $qid = (int)($row['quality_id'] ?? 0); if($qid <= 0) continue; // quality missing on entry -> skip because salary uses quality rate $quality_set[$qid] = true; $karigar_set[$kid] = true; if(!isset($MTR[$kid])) $MTR[$kid] = []; $MTR[$kid][$qid] = ($MTR[$kid][$qid] ?? 0.0) + $m; $MTR_KAR_TOT[$kid] = ($MTR_KAR_TOT[$kid] ?? 0.0) + $m; } } } catch(Throwable $e){ // In case of unexpected DB error, keep arrays empty and show message later. } /* Build lists */ $quality_ids = array_keys($quality_set); usort($quality_ids, fn($a,$b)=>strcasecmp($QUALS[$a] ?? '', $QUALS[$b] ?? '')); $kar_list = array_keys($karigar_set); usort($kar_list, fn($a,$b)=>strcasecmp($KAR_NAME[$a] ?? ("K$a"), $KAR_NAME[$b] ?? ("K$b"))); /* Adjustments: queue + data tables */ $EXTRA=[]; $DEDUCT=[]; $ADV=[]; $__adj_source = 'none'; $__adj_counts=['extra'=>0,'deduction'=>0]; if($FF_USE_QUEUE_ADJ){ try{ $__adj_source = 'queue'; $sq = $pdo->prepare("SELECT karigar_id, type, SUM(amount) amt FROM salary_adjust_queue WHERE company_id=? AND person_type='karigar' AND apply_start=? AND apply_end=? GROUP BY karigar_id, type"); $sq->execute([$company_id,$date_from,$date_to]); foreach($sq as $r){ $kid = (int)$r['karigar_id']; if($kid<=0) continue; $t = (string)$r['type']; $amt = (float)$r['amt']; if($t==='extra'){ $EXTRA[$kid] = ($EXTRA[$kid] ?? 0) + $amt; $__adj_counts['extra']++; } if($t==='deduction'){ $DEDUCT[$kid] = ($DEDUCT[$kid] ?? 0) + $amt; $__adj_counts['deduction']++; } } }catch(Throwable $e){ $__adj_source = 'error-queue'; } } /* Merge with *_data tables */ function sum_money_tbl($pdo,$company_id,$tbl,$kid,$from,$to){ $cols_date = ['date','entry_date','created_at']; $cols_amt = ['amount','amt','value']; foreach($cols_date as $dc){ foreach($cols_amt as $ac){ try{ $sql = "SELECT SUM($ac) s FROM $tbl WHERE company_id=? AND karigar_id=? AND $dc BETWEEN ? AND ?"; $st = $pdo->prepare($sql); $st->execute([$company_id,$kid,$from,$to]); $v = $st->fetchColumn(); if($v !== null && $v !== false) return (float)$v; }catch(Throwable $e){} } } return 0.0; } foreach($kar_list as $kid){ $EXTRA[$kid] = ($EXTRA[$kid] ?? 0) + sum_money_tbl($pdo,$company_id,'extra_data',$kid,$date_from,$date_to); $DEDUCT[$kid] = ($DEDUCT[$kid] ?? 0) + sum_money_tbl($pdo,$company_id,'deduction_data',$kid,$date_from,$date_to); $ADV[$kid] = sum_money_tbl($pdo,$company_id,'advance_data',$kid,$date_from,$date_to); } /* Compute gross/net */ $GROSS=[]; $NET=[]; $bank_total=0.0; $cash_total=0.0; $grand_net = 0.0; foreach($kar_list as $kid){ $g=0.0; foreach($quality_ids as $qid) $g += ($MTR[$kid][$qid] ?? 0.0) * ($QUAL_RATE[$qid] ?? 0.0); $GROSS[$kid] = $g; $n = $g + ($EXTRA[$kid] ?? 0) - ($DEDUCT[$kid] ?? 0) - ($ADV[$kid] ?? 0); $NET[$kid] = $n; $grand_net += $n; if(!empty($HAS_BANK[$kid])) $bank_total += $n; else $cash_total += $n; } /* Ensure report tables exist (same as loom_salary_report) */ $pdo->exec("CREATE TABLE IF NOT EXISTS salary_reports ( id BIGINT PRIMARY KEY AUTO_INCREMENT, company_id BIGINT NOT NULL, date_from DATE NOT NULL, date_to DATE NOT NULL, khata_id BIGINT NOT NULL DEFAULT 0, machine_id BIGINT NOT NULL DEFAULT 0, month INT NOT NULL, half CHAR(1) NOT NULL, year INT NOT NULL, created_by BIGINT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, meta TEXT NULL, UNIQUE KEY uniq_period (company_id, date_from, date_to, khata_id, machine_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); $pdo->exec("CREATE TABLE IF NOT EXISTS salary_report_items ( id BIGINT PRIMARY KEY AUTO_INCREMENT, company_id BIGINT NOT NULL, report_id BIGINT NOT NULL, karigar_id BIGINT NOT NULL, karigar_name VARCHAR(120) NULL, entry_name VARCHAR(120) NULL, khata_code VARCHAR(50) NULL, meters_json TEXT NULL, total_mtr DECIMAL(12,2) DEFAULT 0, gross DECIMAL(12,2) DEFAULT 0, extra DECIMAL(12,2) DEFAULT 0, deduction DECIMAL(12,2) DEFAULT 0, advance DECIMAL(12,2) DEFAULT 0, net DECIMAL(12,2) DEFAULT 0, INDEX(report_id), INDEX(company_id, karigar_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); /* Save / update report */ $flash=''; $saved_report_id = null; if($_SERVER['REQUEST_METHOD'] === 'POST' && pv('action') === 'save_report'){ $sel = $pdo->prepare("SELECT id FROM salary_reports WHERE company_id=? AND date_from=? AND date_to=? AND khata_id=? AND machine_id=? LIMIT 1"); $sel->execute([$company_id,$date_from,$date_to,$khata_id,$machine_id]); $existing = $sel->fetchColumn(); $meta = [ 'company_name'=>$company_name, 'quality_rate'=>$QUAL_RATE, 'quality_names'=>$QUALS, 'filters'=>['khata_id'=>$khata_id,'machine_id'=>$machine_id,'month'=>$month,'half'=>$half,'year'=>$year], 'skipped'=>['bad_date'=>$_skipped_bad_date,'out_of_range'=>$_skipped_out_range], 'method'=>'machine-inline-php' ]; if($existing){ $saved_report_id = (int)$existing; $up = $pdo->prepare("UPDATE salary_reports SET month=?, half=?, year=?, created_by=?, meta=? WHERE id=? AND company_id=?"); $up->execute([$month,(string)$half,$year,$user_id,json_encode($meta,JSON_UNESCAPED_UNICODE),$saved_report_id,$company_id]); $pdo->prepare("DELETE FROM salary_report_items WHERE company_id=? AND report_id=?")->execute([$company_id,$saved_report_id]); $mode='updated'; } else { $ins = $pdo->prepare("INSERT INTO salary_reports (company_id,date_from,date_to,khata_id,machine_id,month,half,year,created_by,meta) VALUES (?,?,?,?,?,?,?,?,?,?)"); $ins->execute([$company_id,$date_from,$date_to,$khata_id,$machine_id,$month,(string)$half,$year,$user_id,json_encode($meta,JSON_UNESCAPED_UNICODE)]); $saved_report_id = (int)$pdo->lastInsertId(); $mode='saved'; } $sti = $pdo->prepare("INSERT INTO salary_report_items (company_id,report_id,karigar_id,karigar_name,entry_name,khata_code,meters_json,total_mtr,gross,extra,deduction,advance,net) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"); foreach($kar_list as $kid){ $meters = []; foreach($quality_ids as $qid) if(($MTR[$kid][$qid] ?? 0) > 0) $meters[$qid] = round($MTR[$kid][$qid],2); $sti->execute([ $company_id,$saved_report_id,$kid, $KAR_NAME[$kid] ?? null, $KAR_ENTRY[$kid] ?? null, $KAR_KHATA_CODE[$kid] ?? null, json_encode($meters,JSON_UNESCAPED_UNICODE), round($MTR_KAR_TOT[$kid] ?? 0,2), round($GROSS[$kid] ?? 0,2), round($EXTRA[$kid] ?? 0,2), round($DEDUCT[$kid] ?? 0,2), round($ADV[$kid] ?? 0,2), round($NET[$kid] ?? 0,2) ]); } if($FF_USE_QUEUE_ADJ){ try{ $ap = $pdo->prepare("UPDATE salary_adjust_queue SET is_applied=1, applied_at=NOW() WHERE company_id=? AND person_type='karigar' AND apply_start=? AND apply_end=? AND is_applied=0"); $ap->execute([$company_id,$date_from,$date_to]); $cnt = $ap->rowCount(); $flash = "Report {$mode}. ID: {$saved_report_id} — Adjustments applied: {$cnt}"; }catch(Throwable $e){ $flash = "Report {$mode}. ID: {$saved_report_id} — (apply failed, but report saved)"; } } else { $flash = "Report {$mode}. ID: {$saved_report_id}"; } } /* Send to deduction / Mark paid */ if($_SERVER['REQUEST_METHOD'] === 'POST' && in_array(pv('action'), ['send_to_deduction','mark_paid'], true)){ $isPaid = (pv('action') === 'mark_paid'); $ins = $pdo->prepare("INSERT INTO deduction_data (company_id, karigar_id, khata_id, amount, date, remark, created_by) VALUES (?,?,?,?,?,?,?)"); $chk = $pdo->prepare("SELECT 1 FROM deduction_data WHERE company_id=? AND karigar_id=? AND date BETWEEN ? AND ? AND remark LIKE ? LIMIT 1"); $added = 0; $tag = $isPaid ? 'PAID' : 'AUTO'; $label = $period_label; foreach($kar_list as $kid){ $amt = (float)($NET[$kid] ?? 0); if($amt == 0.0) continue; $like = "%Salary ($label)%"; $chk->execute([$company_id,$kid,$date_from,$date_to,$like]); if($chk->fetchColumn()) continue; $remark = "Salary ($label) from new_loom_salary_report [$tag]"; $khForKid = (int)($KAR_KHATA_ID[$kid] ?? 0); $ins->execute([$company_id,$kid,$khForKid,round($amt,2),$date_to,$remark,$user_id]); $added++; } $flash = ($isPaid ? "Marked as PAID: " : "Sent to Deduction: ") . $added . " row(s) for {$label}."; } /* PDF export (similar layout) */ if(gv('export') === 'pdf'){ if(!$PDF_AVAILABLE){ http_response_code(500); exit('PDF export not available: install dompdf/dompdf'); } $orientation = (count($quality_ids) > 5) ? 'landscape' : 'portrait'; $css = 'body{font-family: DejaVu Sans, sans-serif; font-size:12px;} table{width:100%;border-collapse:collapse} th,td{border:1px solid #ddd;padding:6px 8px} thead th{background:#f0f8f0}'; $html = '<html><head><meta charset="utf-8"><style>'.$css.'</style></head><body>'; $html .= '<h2>'.h($company_name).'</h2>'; $html .= '<div>Salary (Machine Inline method) — Period: '.h($date_from).' to '.h($date_to).' - '.h($period_label).'</div>'; $html .= '<table><thead><tr><th>Karigar</th>'; foreach($quality_ids as $qid) $html .= '<th>'.h($QUALS[$qid] ?? "Q$qid").'<br>@'.number_format($QUAL_RATE[$qid]??0,2).'</th>'; $html .= '<th>Total Mtr</th><th>Gross</th><th>Extra</th><th>Deduction</th><th>Advance</th><th>Payable</th></tr></thead><tbody>'; foreach($kar_list as $kid){ $html .= '<tr><td>'.h($KAR_NAME[$kid] ?? "Karigar #$kid").'</td>'; foreach($quality_ids as $qid) $html .= '<td style="text-align:right">'.(($MTR[$kid][$qid] ?? 0)>0?number_format($MTR[$kid][$qid],2):'').'</td>'; $html .= '<td style="text-align:right">'.number_format($MTR_KAR_TOT[$kid]??0,2).'</td>'; $html .= '<td style="text-align:right">'.number_format($GROSS[$kid]??0,2).'</td>'; $html .= '<td style="text-align:right">'.number_format($EXTRA[$kid]??0,2).'</td>'; $html .= '<td style="text-align:right">'.number_format($DEDUCT[$kid]??0,2).'</td>'; $html .= '<td style="text-align:right">'.number_format($ADV[$kid]??0,2).'</td>'; $html .= '<td style="text-align:right">'.number_format($NET[$kid]??0,2).'</td></tr>'; } $html .= '</tbody></table>'; $html .= '<div style="margin-top:8px">Skipped: Bad Date='.(int)$_skipped_bad_date.' Out of Range='.(int)$_skipped_out_range.'</div>'; $html .= '</body></html>'; $dompdf = new \Dompdf\Dompdf(['defaultFont'=>'DejaVu Sans']); $dompdf->loadHtml($html, 'UTF-8'); $dompdf->setPaper('A4', $orientation); $dompdf->render(); $fname = 'new_loom_salary_report_'.$year.'-'.str_pad((string)$month,2,'0',STR_PAD_LEFT).'_'.$half.'.pdf'; header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="'.$fname.'"'); echo $dompdf->output(); exit; } /* Build export payload for payment (net) */ $export_rows = []; foreach($kar_list as $kid){ $amt = (float)($NET[$kid] ?? 0.0); if($amt != 0.0) $export_rows[] = ['employee_id'=>$kid,'amount'=>round($amt,2)]; } $export_payload = json_encode($export_rows, JSON_UNESCAPED_UNICODE); /* === HTML === */ ?><!doctype html> <html> <head> <meta charset="utf-8"> <title>New Loom Salary Report (Machine Inline method)</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <style> body{font-family:system-ui,Segoe UI,Roboto,Arial;background:#f7faf7;color:#1b2226;padding:18px} .wrap{max-width:1200px;margin:0 auto} .hbar{background:#ecf9f0;padding:12px;border-radius:10px;display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap} .hbar label{font-size:12px;display:block;margin-bottom:6px} .hbar select{padding:8px;border-radius:8px;border:1px solid #dfeee0;background:#fff} .btn{background:#1f8a3e;color:#fff;border:none;padding:8px 12px;border-radius:8px;cursor:pointer} .btn.gray{background:#6b7280} .card{background:#fff;border-radius:10px;padding:12px;margin-top:12px;border:1px solid #e6f0ea} .table{width:100%;border-collapse:collapse} .table th,.table td{padding:8px;border-bottom:1px solid #eef6ec;text-align:right} .table thead th{background:#dff1dd;color:#144a2f} .table tbody td:first-child{text-align:left} .totalcol{font-weight:700;background:#f3fbf4} .summary{background:#f1f9f2;border:1px dashed #cde8cf;padding:8px;border-radius:8px;margin-top:8px} .small{font-size:12px;color:#555} </style> </head> <body> <div class="wrap"> <h2>New Loom Salary Report <small style="font-size:13px;color:#666">— Machine Inline method</small></h2> <div class="small" style="margin-bottom:8px"><b>Company:</b> <?= h($company_name) ?></div> <?php if($flash): ?><div class="card" style="border-left:4px solid #4ade80"><strong><?= h($flash) ?></strong></div><?php endif; ?> <form class="hbar" method="get" action=""> <div><label>Khata</label> <select name="khata_id"><option value="0">All</option> <?php $KHATAS=[]; try{ $kq=$pdo->prepare("SELECT DISTINCT khata_id, khata_code FROM loom_karigar_master WHERE company_id=? AND khata_id IS NOT NULL ORDER BY khata_code"); $kq->execute([$company_id]); foreach($kq as $r) $KHATAS[(int)$r['khata_id']] = $r['khata_code']; }catch(Throwable $e){} foreach($KHATAS as $id=>$code): ?> <option value="<?= (int)$id ?>" <?= $khata_id===$id?'selected':'' ?>><?= h($code) ?></option> <?php endforeach; ?> </select> </div> <div><label>Machine</label> <select name="machine_id"><option value="0">All Machines</option> <?php $MACH=[]; try{ $st2=$pdo->prepare("SELECT id, machine_code FROM machines WHERE company_id=? ORDER BY id"); $st2->execute([$company_id]); foreach($st2 as $r) $MACH[(int)$r['id']] = $r['machine_code'] ?: ('MC '.$r['id']); }catch(Throwable $e){} foreach($MACH as $id=>$label): ?> <option value="<?= (int)$id ?>" <?= $machine_id===$id?'selected':'' ?>><?= h($label) ?></option> <?php endforeach; ?> </select> </div> <div><label>Month</label><select name="month"><?php for($m=1;$m<=12;$m++): ?><option value="<?= $m ?>" <?= $m===$month?'selected':'' ?>><?= date('M', mktime(0,0,0,$m,1,$year)) ?></option><?php endfor; ?></select></div> <div><label>Period</label><select name="half"><option value="1" <?= $half==='1'?'selected':'' ?>>1–15</option><option value="2" <?= $half==='2'?'selected':'' ?>>16–End</option><option value="F" <?= $half==='F'?'selected':'' ?>>Full</option></select></div> <div><label>Year</label><select name="year"><?php for($y=date('Y')-2;$y<=date('Y')+1;$y++): ?><option value="<?= $y ?>" <?= $y===$year?'selected':'' ?>><?= $y ?></option><?php endfor; ?></select></div> <div style="margin-left:auto;display:flex;gap:8px;align-items:center"> <button class="btn" type="submit">Show Report</button> <a class="btn gray" href="?<?= http_build_query(['khata_id'=>$khata_id,'machine_id'=>$machine_id,'month'=>$month,'half'=>$half,'year'=>$year,'export'=>'pdf']) ?>" <?= $PDF_AVAILABLE? '' : 'onclick="alert(\'Install dompdf/dompdf first\');return false;"' ?>>Export PDF</a> <button class="btn gray" type="button" onclick="window.print()">Print</button> </div> </form> <div class="summary"> <b>Summary:</b> Bank: <?= number_format($bank_total,2) ?>, Cash: <?= number_format($cash_total,2) ?>, <b>Total:</b> <?= number_format($grand_net,2) ?> <span class="small"> (method: machine-inline-php). Skipped: bad_date=<?= (int)$_skipped_bad_date ?>, out_of_range=<?= (int)$_skipped_out_range ?>.</span> </div> <form method="post" style="margin-top:10px"><input type="hidden" name="action" value="save_report"><button class="btn" type="submit">Save Salary (this period)</button></form> <div class="card" style="margin-top:12px"> <table class="table"> <thead> <tr><th>Karigar</th> <?php foreach($quality_ids as $qid): ?><th><?= h($QUALS[$qid] ?? ("Q$qid")) ?><br><span class="small">@ <?= number_format($QUAL_RATE[$qid]??0,2) ?></span></th><?php endforeach; ?> <th>Total Mtr</th><th>Gross</th><th>Extra</th><th>Deduction</th><th>Advance</th><th>Payable</th> </tr> </thead> <tbody> <?php foreach($kar_list as $kid): ?> <tr> <td><?= h($KAR_NAME[$kid] ?? ("Karigar #$kid")) ?><?php if(!empty($KAR_ENTRY[$kid])): ?><div class="small"><?= h($KAR_ENTRY[$kid]) ?></div><?php endif; ?></td> <?php foreach($quality_ids as $qid): $m = $MTR[$kid][$qid] ?? 0; ?> <td><?= $m>0 ? number_format($m,2) : '' ?></td> <?php endforeach; ?> <td class="totalcol"><?= number_format($MTR_KAR_TOT[$kid] ?? 0,2) ?></td> <td><?= number_format($GROSS[$kid] ?? 0,2) ?></td> <td><?= number_format($EXTRA[$kid] ?? 0,2) ?></td> <td><?= number_format($DEDUCT[$kid] ?? 0,2) ?></td> <td><?= number_format($ADV[$kid] ?? 0,2) ?></td> <td class="totalcol"><?= number_format($NET[$kid] ?? 0,2) ?></td> </tr> <?php endforeach; ?> </tbody> <tfoot> <tr><td>TOTAL</td> <?php $TOT_METERS_BY_Q = []; $GRAND_GROSS = 0.0; foreach($quality_ids as $qid){ $s=0.0; foreach($kar_list as $kid){ $s += $MTR[$kid][$qid] ?? 0; } $TOT_METERS_BY_Q[$qid]=$s; $GRAND_GROSS += $s * ($QUAL_RATE[$qid] ?? 0.0); echo '<td>'.number_format($s,2).'</td>'; } $grand_mtr = array_sum($TOT_METERS_BY_Q); $TOT_EXTRA = array_sum(array_intersect_key($EXTRA, array_flip($kar_list))); $TOT_DED = array_sum(array_intersect_key($DEDUCT, array_flip($kar_list))); $TOT_ADV = array_sum(array_intersect_key($ADV, array_flip($kar_list))); ?> <td class="totalcol"><?= number_format($grand_mtr,2) ?></td> <td><?= number_format($GRAND_GROSS,2) ?></td> <td><?= number_format($TOT_EXTRA,2) ?></td> <td><?= number_format($TOT_DED,2) ?></td> <td><?= number_format($TOT_ADV,2) ?></td> <td class="totalcol"><?= number_format($grand_net,2) ?></td> </tr> </tfoot> </table> </div> <form id="exportForm" method="post" action="/erp/loom_payment_export.php" style="display:none"> <input type="hidden" name="salary_rows" value='<?= h($export_payload) ?>'> <input type="hidden" name="period_label" value="<?= h($period_label) ?>"> <input type="hidden" name="period_start" value="<?= h($date_from) ?>"> <input type="hidden" name="period_end" value="<?= h($date_to) ?>"> </form> </div> </body> </html>