« Back to History
yarn_entrybn.php
|
20260723_000646.php
Initial Domain Snapshot
Copy Code
<?php /* ========================================================= File: /erp/yarn_entrybn.php Purpose: Yarn/TFO/TPM/Zari In-Out Entry Form (bn system with boxes_master) NOTE: header/footer includes removed to avoid interference as requested ========================================================= */ error_reporting(E_ALL); ini_set('display_errors',1); /* ---- Auth + scope (AUTH FILES UNTOUCHED) ---- */ require_once __DIR__ . '/modules/auth/page_acl.php'; $ctx = page_require_access('yarn_entry'); $company_id = (int)($ctx['company_id'] ?? 3); $pdo = $ctx['pdo'] ?? null; $u = $ctx['user'] ?? null; /* ---- Hardened JSON helper ---- */ function jsend($ok,$data=[],$code=200){ while (ob_get_level()>0) { @ob_end_clean(); } if (!headers_sent()) { header_remove(); header('Content-Type: application/json; charset=utf-8'); http_response_code($code); } echo json_encode($ok?['ok'=>true,'data'=>$data]:['ok'=>false,'error'=>$data], JSON_UNESCAPED_UNICODE); exit; } /* ---- AJAX guard ---- */ if (isset($_GET['ajax'])) { if (!is_array($ctx) || empty($ctx['user'] ?? null)) { jsend(false,'unauthenticated',401); } set_error_handler(function($severity,$message,$file,$line){ if (!(error_reporting() & $severity)) return false; throw new ErrorException($message,0,$severity,$file,$line); }); @ini_set('display_errors','0'); } /* ---- PDO bootstrap (robust) ---- */ if (!($pdo instanceof PDO)) { $tryInclude = function(string $path) use (&$pdo) { @include_once $path; if ($pdo instanceof PDO) return true; if (isset($db) && $db instanceof PDO) { $pdo = $db; return true; } if (isset($dbh) && $dbh instanceof PDO) { $pdo = $dbh; return true; } if (isset($conn) && $conn instanceof PDO){ $pdo = $conn; return true; } return false; }; foreach ([__DIR__.'/core/db.php', __DIR__.'/db.php', __DIR__.'/config/db.php', __DIR__.'/config.php'] as $p) { if (is_file($p) && $tryInclude($p)) { break; } } if (!($pdo instanceof PDO)) { http_response_code(500); exit('DB bootstrap failed.'); } } /* ---- Legacy company var for header ---- */ if (!isset($company) || !is_array($company)) { $company = ['id'=>$company_id, 'name'=>($u['company_name'] ?? '')]; } /* ---- constants / init state ---- */ $MATERIALS = ['yarn','tfo','tpm','zari']; $FLOWS = ['in','out']; $init_material = isset($_POST['material']) && in_array(strtolower($_POST['material']),$MATERIALS,true) ? strtolower($_POST['material']) : (isset($_GET['material'])?strtolower($_GET['material']):'yarn'); $init_flow = isset($_POST['flow']) && in_array(strtolower($_POST['flow']),$FLOWS,true) ? strtolower($_POST['flow']) : (isset($_GET['flow'])?strtolower($_GET['flow']):'in'); $init_ytype = trim($_POST['yarn_type'] ?? ($_GET['yarn_type'] ?? '')); $init_company = trim($_POST['company'] ?? ($_GET['company'] ?? '')); $init_denier = trim($_POST['denier'] ?? ($_GET['denier'] ?? '')); $init_color = trim($_POST['color'] ?? ($_GET['color'] ?? '')); $init_assign = trim($_POST['assign_to'] ?? ''); /* ----------------------------------------------------------------- Ensure required new tables exist: boxes_master + bn* tables ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- Helpers: create/consume boxes ----------------------------------------------------------------- */ function create_boxes_for_in(PDO $pdo, int $company_id, string $material, string $yarn_type, string $company_name, string $denier, string $color, array $boxRows, string $inTable, int $inId) : array { $out = []; $ins = $pdo->prepare("INSERT IGNORE INTO boxes_master (company_id,material,yarn_type,company_name,denier,color,box_no,weight,status,in_txn_table,in_txn_id,created_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)"); foreach ($boxRows as $r) { $box_no = trim($r['box_no'] ?? ''); if ($box_no === '') $box_no = 'AUTO-'.uniqid(); $weight = isset($r['weight']) ? floatval($r['weight']) : 0.0; $ins->execute([$company_id,$material,$yarn_type,$company_name,$denier,$color,$box_no,$weight,'IN',$inTable,$inId,date('Y-m-d H:i:s')]); $id = $pdo->lastInsertId(); $out[] = ['id'=>$id,'box_no'=>$box_no,'weight'=>$weight]; } return $out; } function consume_boxes_on_out(PDO $pdo, int $company_id, string $material, string $yarn_type, string $company_name, string $denier, string $color, array $boxNos, string $outTable, int $outId) : array { $consumed = []; $errors = []; $upd = $pdo->prepare("UPDATE boxes_master SET status='OUT', out_txn_table=?, out_txn_id=? WHERE company_id=? AND material=? AND yarn_type=? AND company_name=? AND denier=? AND color=? AND box_no=? AND status='IN' LIMIT 1"); foreach ($boxNos as $bno) { $bno = trim($bno); if ($bno === '') { $errors[] = "Empty box no"; continue; } $upd->execute([$outTable, $outId, $company_id, $material, $yarn_type, $company_name, $denier, $color, $bno]); if ($upd->rowCount() > 0) { $st = $pdo->prepare("SELECT id FROM boxes_master WHERE company_id=? AND box_no=? LIMIT 1"); $st->execute([$company_id,$bno]); $r = $st->fetch(PDO::FETCH_ASSOC); if($r) $consumed[] = intval($r['id']); } else { $errors[] = "Box not available or already OUT: $bno"; } } return ['consumed'=>$consumed,'errors'=>$errors]; } /* ========================================================= AJAX handlers (same as earlier) ========================================================= */ if (isset($_GET['ajax'])) { try { $ajax = $_GET['ajax']; if ($ajax === 'options') { $level = strtolower($_GET['level'] ?? 'type'); $material = strtolower($_GET['material'] ?? 'yarn'); $okL = ['type','company','denier','color']; if(!in_array($level,$okL,true)) jsend(false,'bad level',400); $mapMaterialToStockType = ['yarn'=>'Yarn','tfo'=>'TFO','tpm'=>'TPM','zari'=>'Zari']; $stockType = $mapMaterialToStockType[$material] ?? 'Yarn'; $yt = trim($_GET['yarn_type'] ?? ''); $co = trim($_GET['company'] ?? ''); $de = trim($_GET['denier'] ?? ''); $filters = [ 'company_id = :cid', 'TRIM(stock_type) COLLATE utf8mb4_unicode_ci = TRIM(:st) COLLATE utf8mb4_unicode_ci' ]; $params = [':cid'=>$company_id, ':st'=>$stockType]; if ($level !== 'type' && $yt !== '') { $filters[] = 'TRIM(yarn_types) COLLATE utf8mb4_unicode_ci = TRIM(:yt) COLLATE utf8mb4_unicode_ci'; $params[':yt'] = $yt; } if (in_array($level,['denier','color','company'],true) && $co !== '') { $filters[] = 'TRIM(company_name) COLLATE utf8mb4_unicode_ci = TRIM(:co) COLLATE utf8mb4_unicode_ci'; $params[':co'] = $co; } if ($level === 'color' && $de !== '') { $filters[] = 'TRIM(denier) COLLATE utf8mb4_unicode_ci = TRIM(:de) COLLATE utf8mb4_unicode_ci'; $params[':de'] = $de; } $colMap = [ 'type' => 'yarn_types', 'company' => 'company_name', 'denier' => 'denier', 'color' => 'color' ]; $col = $colMap[$level] ?? null; if(!$col) jsend(false,'bad col',400); $sql = "SELECT DISTINCT TRIM($col) COLLATE utf8mb4_unicode_ci AS v FROM yarn_company_data WHERE ".implode(' AND ',$filters)." AND $col IS NOT NULL AND TRIM($col) <> '' ORDER BY v"; $st = $pdo->prepare($sql); $st->execute($params); $out = []; while ($r = $st->fetch(PDO::FETCH_ASSOC)) { $v = trim((string)($r['v'] ?? '')); if ($v !== '') $out[] = $v; } jsend(true, ['options'=>$out]); } if ($ajax === 'assign_options') { $st = $pdo->prepare("SELECT name FROM yarn_assigne WHERE company_id = ? ORDER BY name"); $st->execute([$company_id]); $opts = array_map(fn($r)=>$r['name'], $st->fetchAll(PDO::FETCH_ASSOC)); jsend(true, ['options'=>$opts]); } if ($ajax === 'assign_add') { $name = trim($_POST['name'] ?? ''); if($name==='') jsend(false,'Name required',400); if(mb_strlen($name)>120) jsend(false,'Name too long (max 120)',400); $ins = $pdo->prepare("INSERT IGNORE INTO yarn_assigne (company_id, name) VALUES (?,?)"); $ok = $ins->execute([$company_id, $name]); if(!$ok) jsend(false,'DB insert failed',500); jsend(true, ['created'=>($ins->rowCount()>0), 'name'=>$name]); } if ($ajax === 'stock') { $material = strtolower($_GET['material'] ?? 'yarn'); $flow = strtolower($_GET['flow'] ?? 'in'); if(!in_array($material,$MATERIALS,true)||!in_array($flow,$FLOWS,true)) jsend(false,'bad material/flow',400); $yt = trim($_GET['yarn_type'] ?? ''); $co = trim($_GET['company'] ?? ''); $de = trim($_GET['denier'] ?? ''); $cl = trim($_GET['color'] ?? ''); $tbl = "bn{$material}_{$flow}"; $sqlL = "SELECT id, txn_date, yarn_type, company, denier, color, boxes, weight, assign_to, box_nos, created_at FROM `$tbl` WHERE company_id = :cid ORDER BY id DESC LIMIT 1"; $st=$pdo->prepare($sqlL); $st->execute([':cid'=>$company_id]); $last=$st->fetch(PDO::FETCH_ASSOC); $haveKeys = ($yt!=='' && $co!=='' && $de!=='' && $cl!==''); $current = null; $future = null; $form = ['boxes'=>0,'weight'=>0,'avg'=>0]; $diff_pct = null; $status = 'NA'; if ($haveKeys) { $filters = ['company_id=:cid','yarn_type=:yt','company=:co','denier=:de','color=:cl']; $params = [':cid'=>$company_id,':yt'=>$yt,':co'=>$co,':de'=>$de,':cl'=>$cl]; $sumSQL = fn($tbl,$filters)=>"SELECT COALESCE(SUM(boxes),0) boxes, COALESCE(SUM(weight),0) weight FROM `$tbl` WHERE ".implode(' AND ',$filters); $st=$pdo->prepare($sumSQL("bn{$material}_in",$filters)); $st->execute($params); $in = $st->fetch(PDO::FETCH_ASSOC) ?: ['boxes'=>0,'weight'=>0]; $st=$pdo->prepare($sumSQL("bn{$material}_out",$filters)); $st->execute($params); $out = $st->fetch(PDO::FETCH_ASSOC) ?: ['boxes'=>0,'weight'=>0]; $cur_boxes = max(0.0,(float)$in['boxes'] - (float)$out['boxes']); $cur_weight = max(0.0,(float)$in['weight'] - (float)$out['weight']); $cur_avg = ($cur_boxes>0) ? ($cur_weight/$cur_boxes) : 0.0; $f_boxes = max(0.0,(float)($_GET['form_boxes'] ?? 0)); $f_weight = max(0.0,(float)($_GET['form_weight'] ?? 0)); if($flow==='in'){ $fut_boxes=$cur_boxes+$f_boxes; $fut_weight=$cur_weight+$f_weight; } else{ $fut_boxes=max(0,$cur_boxes-$f_boxes); $fut_weight=max(0,$cur_weight-$f_weight); } $fut_avg = ($fut_boxes>0) ? ($fut_weight/$fut_boxes) : 0.0; $form_avg = ($f_boxes>0) ? ($f_weight/$f_boxes) : 0.0; if ($cur_boxes==0 && $flow==='in') { $diff_pct = 0.0; $status = 'OK'; } else { $base = ($cur_avg>0) ? $cur_avg : ($form_avg>0 ? $form_avg : 1); $diff_pct = ($base>0) ? (($form_avg - $cur_avg)/$base*100.0) : 0.0; $abs = abs($diff_pct); $status = ($abs<=20)?'OK':(($abs<=30)?'NOT_OK':'PROBLEM'); } $current = ['boxes'=>round($cur_boxes,3),'weight'=>round($cur_weight,3),'avg_box_weight'=>round($cur_avg,3)]; $future = ['boxes'=>round($fut_boxes,3),'weight'=>round($fut_weight,3),'avg_box_weight'=>round($fut_avg,3)]; $form = ['boxes'=>$f_boxes,'weight'=>$f_weight,'avg'=>$form_avg]; } jsend(true,[ 'current'=>$current, 'future' =>$future, 'form'=>$form, 'diff_pct'=> is_null($diff_pct)? null : round($diff_pct,2), 'status'=>$status, 'target_table'=>$tbl, 'last_entry'=>$last ]); } if ($ajax === 'records') { $material=strtolower($_GET['material'] ?? 'yarn'); $flow =strtolower($_GET['flow'] ?? 'in'); if(!in_array($material,$MATERIALS,true)||!in_array($flow,$FLOWS,true)) jsend(false,'bad material/flow',400); $yt=trim($_GET['yarn_type'] ?? ''); $co=trim($_GET['company'] ?? ''); $de=trim($_GET['denier'] ?? ''); $cl=trim($_GET['color'] ?? ''); $tbl="bn{$material}_{$flow}"; $filters=['company_id=:cid']; $params=[ ':cid'=>$company_id ]; if($yt!==''){ $filters[]='yarn_type=:yt'; $params[':yt']=$yt; } if($co!==''){ $filters[]='company=:co'; $params[':co']=$co; } if($de!==''){ $filters[]='denier=:de'; $params[':de']=$de; } if($cl!==''){ $filters[]='color=:cl'; $params[':cl']=$cl; } $sql="SELECT id, txn_date, yarn_type, company, denier, color, boxes, weight, assign_to, box_nos, created_at FROM `$tbl` WHERE ".implode(' AND ',$filters)." ORDER BY id DESC LIMIT 50"; $st=$pdo->prepare($sql); $st->execute($params); jsend(true,['rows'=>$st->fetchAll(PDO::FETCH_ASSOC),'table'=>$tbl]); } if ($ajax === 'available_boxes') { $material = strtolower($_GET['material'] ?? 'yarn'); $yt = trim($_GET['yarn_type'] ?? ''); $co = trim($_GET['company'] ?? ''); $de = trim($_GET['denier'] ?? ''); $cl = trim($_GET['color'] ?? ''); if ($yt==='' || $co==='' || $de==='' || $cl==='') jsend(false,'filters required',400); $st = $pdo->prepare("SELECT id, box_no, weight, in_txn_table, in_txn_id, created_at FROM boxes_master WHERE company_id=:cid AND material=:mat AND yarn_type=:yt AND company_name=:co AND denier=:de AND color=:cl AND status='IN' ORDER BY created_at, id"); $st->execute([':cid'=>$company_id, ':mat'=>$material, ':yt'=>$yt, ':co'=>$co, ':de'=>$de, ':cl'=>$cl]); $rows = $st->fetchAll(PDO::FETCH_ASSOC); jsend(true, ['boxes'=>$rows]); } jsend(false,'unknown ajax',400); } catch (Throwable $e) { jsend(false, 'server: '.$e->getMessage(), 500); } } /* ------------------ POST: SAVE (IN / OUT) ------------------ */ $flash=null; if($_SERVER['REQUEST_METHOD']==='POST' && ($_POST['do'] ?? '')==='save'){ $material = $init_material; $flow = $init_flow; if(!in_array($material,$MATERIALS,true) || !in_array($flow,$FLOWS,true)) { $flash=['type'=>'error','msg'=>'Bad material/flow']; } else { $tbl = "bn{$material}_{$flow}"; $txn_date=trim($_POST['txn_date'] ?? ''); $ytype =trim($_POST['yarn_type'] ?? ''); $company =trim($_POST['company'] ?? ''); $denier =trim($_POST['denier'] ?? ''); $color =trim($_POST['color'] ?? ''); $boxes =(float)($_POST['boxes'] ?? 0); $weight =(float)($_POST['weight'] ?? 0); $assign_to=null; if($material==='yarn' && $flow==='out'){ $assign_to=trim($_POST['assign_to'] ?? '') ?: null; } $box_nos_raw = trim($_POST['box_nos'] ?? ''); // for IN (json rows) or empty $selected_box_nos = []; // for OUT (array or json) if ($flow==='out') { if (!empty($_POST['selected_box_nos'])) { $selected_box_nos = is_array($_POST['selected_box_nos']) ? $_POST['selected_box_nos'] : json_decode($_POST['selected_box_nos'], true); } elseif (!empty($box_nos_raw)) { $selected_box_nos = json_decode($box_nos_raw, true) ?: []; } } $errs=[]; if($txn_date==='') $errs[]='Date required'; if($ytype==='') $errs[]='Yarn Type required'; if($company==='') $errs[]='Company required'; if($denier==='') $errs[]='Denier required'; if($color==='') $errs[]='Color required'; if($boxes<=0) $errs[]='Boxes must be > 0'; if($weight<=0) $errs[]='Weight must be > 0'; if($material==='yarn' && $flow==='out' && !$assign_to) $errs[]='Assign is required for Yarn Out'; if($flow==='out' && empty($selected_box_nos)) $errs[]='Select Box Nos for OUT'; if($errs){ $flash=['type'=>'error','msg'=>implode(', ',$errs)]; } else { $okSave = true; if ($flow==='out') { $st = $pdo->prepare("SELECT COUNT(*) c, COALESCE(SUM(weight),0) w FROM boxes_master WHERE company_id=:cid AND material=:mat AND yarn_type=:yt AND company_name=:co AND denier=:de AND color=:cl AND status='IN'"); $st->execute([':cid'=>$company_id,':mat'=>$material,':yt'=>$ytype,':co'=>$company,':de'=>$denier,':cl'=>$color]); $r = $st->fetch(PDO::FETCH_ASSOC) ?: ['c'=>0,'w'=>0]; $avail_boxes = intval($r['c']); $avail_weight = floatval($r['w']); if (count($selected_box_nos) > $avail_boxes || $weight > $avail_weight) { $flash=['type'=>'error','msg'=>'Selected boxes/weight exceed available stock.']; $okSave = false; } } if ($okSave) { if ($flow === 'in') { $st = $pdo->prepare("INSERT INTO `$tbl` (company_id, txn_date, yarn_type, company, denier, color, boxes, weight, assign_to, box_nos) VALUES (:cid,:dt,:yt,:co,:de,:cl,:bx,:wt,:asgn,:box_nos)"); $ok = $st->execute([ ':cid'=>$company_id, ':dt'=>$txn_date, ':yt'=>$ytype, ':co'=>$company, ':de'=>$denier, ':cl'=>$color, ':bx'=>$boxes, ':wt'=>$weight, ':asgn'=>$assign_to, ':box_nos'=>($box_nos_raw !== '' ? $box_nos_raw : null) ]); if (!$ok) { $flash=['type'=>'error','msg'=>'DB error while inserting IN row.']; } else { $newId = $pdo->lastInsertId(); $boxRows = []; if ($box_nos_raw !== '') { $arr = json_decode($box_nos_raw, true); if (json_last_error() === JSON_ERROR_NONE && is_array($arr)) $boxRows = $arr; } if (empty($boxRows)) { $cnt = max(0, (int)round($boxes)); for ($i=1;$i<=$cnt;$i++){ $boxRows[] = ['box_no'=>"AUTO-{$material}-{$newId}-{$i}", 'weight'=>($weight>0 && $cnt>0? $weight/$cnt : 0)]; } } $createdBoxes = create_boxes_for_in($pdo, $company_id, $material, $ytype, $company, $denier, $color, $boxRows, $tbl, $newId); $enhanced = array_map(function($b){ return ['box_no'=>$b['box_no'],'weight'=>$b['weight'],'box_master_id'=>$b['id']]; }, $createdBoxes); $upd = $pdo->prepare("UPDATE `$tbl` SET box_nos = :bn WHERE id = :id"); $upd->execute([':bn'=>json_encode($enhanced, JSON_UNESCAPED_UNICODE), ':id'=>$newId]); $flash=['type'=>'success','msg'=>"Saved to $tbl"]; } } else { $selBoxesArr = array_map(function($b){ return is_array($b)?$b:['box_no'=>$b]; }, $selected_box_nos); $boxes_count = count($selBoxesArr); $total_w = 0; foreach ($selBoxesArr as $s) $total_w += floatval($s['weight'] ?? 0); $box_nos_json_to_store = json_encode($selBoxesArr, JSON_UNESCAPED_UNICODE); $st = $pdo->prepare("INSERT INTO `$tbl` (company_id, txn_date, yarn_type, company, denier, color, boxes, weight, assign_to, box_nos) VALUES (:cid,:dt,:yt,:co,:de,:cl,:bx,:wt,:asgn,:box_nos)"); $ok = $st->execute([ ':cid'=>$company_id, ':dt'=>$txn_date, ':yt'=>$ytype, ':co'=>$company, ':de'=>$denier, ':cl'=>$color, ':bx'=>$boxes_count, ':wt'=>$total_w, ':asgn'=>$assign_to, ':box_nos'=>$box_nos_json_to_store ]); if (!$ok) { $flash=['type'=>'error','msg'=>'DB error while inserting OUT row.']; } else { $outId = $pdo->lastInsertId(); $boxNosOnly = array_map(function($b){ return is_array($b)?$b['box_no']:$b; }, $selected_box_nos); $consume = consume_boxes_on_out($pdo, $company_id, $material, $ytype, $company, $denier, $color, $boxNosOnly, $tbl, $outId); if (!empty($consume['errors'])) { $pdo->prepare("DELETE FROM `$tbl` WHERE id = ?")->execute([$outId]); $flash=['type'=>'error','msg'=>'Box consumption failed: '.implode('; ',$consume['errors'])]; } else { $flash=['type'=>'success','msg'=>"Saved to $tbl and boxes consumed"]; } } } } } } } /* ---------- (header/footer includes removed) ---------- */ /* If you want them back, uncomment below lines */ // $__header = __DIR__ . '/partials/header.php'; if (is_file($__header)) include_once $__header; // $__footer = __DIR__ . '/partials/footer.php'; $cssVersion = '20251003'; $cssPath = '/erp/public/assets/css/main.css?v='.$cssVersion; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Yarn Entry (BN) • Mister Manager</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="<?=htmlspecialchars($cssPath)?>"> </head> <body> <div class="wrap"> <div class="hdr"> <div class="seg" id="segMaterial"> <button data-v="yarn">Yarn</button> <button data-v="tfo">TFO</button> <button data-v="tpm">TPM</button> <button data-v="zari">Zari</button> </div> <div class="links center-link"> <a class="linkbtn" href="/erp/yarn_stock.php" target="_blank">Yarn Stock (Summary)</a> </div> <div class="seg" id="segFlow"> <button data-v="in">In</button> <button data-v="out">Out</button> </div> </div> <?php if($flash){ ?><div class="flash <?=$flash['type']?>"><?=htmlspecialchars($flash['msg'])?></div><?php } ?> <div class="grid"> <!-- LEFT --> <div class="card"> <div class="title">AVG Box Weight Difference</div> <div class="muted" id="diffLine">—</div> <div style="margin-top:8px" id="diffPill"></div> <hr style="border:none;border-top:1px solid #eee;margin:12px 0"> <div class="title">Last Entry</div> <div id="lastEntry">—</div> </div> <!-- CENTER --> <div class="card"> <div class="title">Entry Form (BN)</div> <form method="post" id="entryForm" autocomplete="off"> <input type="hidden" name="do" value="save"> <input type="hidden" name="material" id="f_material" value="<?=htmlspecialchars($init_material)?>"> <input type="hidden" name="flow" id="f_flow" value="<?=htmlspecialchars($init_flow)?>"> <input type="hidden" name="box_nos" id="f_box_nos" value=""> <input type="hidden" name="selected_box_nos" id="f_selected_box_nos" value=""> <div class="row"> <div> <label>Date</label> <input type="date" name="txn_date" id="f_date" required value="<?=htmlspecialchars($_POST['txn_date'] ?? date('Y-m-d'))?>"> </div> <div> <label>Yarn Type</label> <select name="yarn_type" id="f_yarn_type" required style="min-width:200px;background:#fff;color:#111;"></select> </div> </div> <div class="row"> <div> <label>Company</label> <div style="display:flex; gap:8px; align-items:center"> <select name="company" id="f_company" required style="min-width:200px;background:#fff;color:#111;"></select> <a href="/erp/yarn_company_add.php" target="_blank" class="muted" style="white-space:nowrap;text-decoration:none;border:1px solid #ddd;border-radius:8px;padding:6px 10px">+</a> </div> </div> <div> <label>Denier</label> <select name="denier" id="f_denier" required style="min-width:160px;background:#fff;color:#111;"></select> </div> </div> <div class="row"> <div> <label>Color</label> <select name="color" id="f_color" required style="min-width:200px;background:#fff;color:#111;"></select> </div> <div> <label>Box</label> <input type="number" step="1" min="0" name="boxes" id="f_boxes" required placeholder="e.g., 10" value="<?= isset($flash['type']) && $flash['type']==='success' ? '' : htmlspecialchars($_POST['boxes'] ?? '') ?>"> <div style="margin-top:6px"> <button type="button" id="btnAddBoxNos" class="btn ghost" style="padding:4px 8px;font-size:.85rem">Add Box Nos (IN)</button> <button type="button" id="btnSelectBoxes" class="btn ghost" style="padding:4px 8px;font-size:.85rem; display:none;">Select Boxes (OUT)</button> <span class="muted" style="font-size:.85rem;margin-left:8px">Box-level management</span> </div> </div> </div> <button type="button" id="btnGenerateRows" class="btn primary" style="padding:6px 10px">Generate Rows</button> <button type="button" id="btnClearRows" class="btn ghost" style="padding:6px 10px">Clear</button> <div class="muted" style="font-size:.8rem;margin-top:6px">Generate rows = number in Box field.</div> </div> </div> <div class="row"> <div> <label>Weight (kg)</label> <input type="number" step="0.001" min="0" name="weight" id="f_weight" required placeholder="e.g., 250" value="<?= isset($flash['type']) && $flash['type']==='success' ? '' : htmlspecialchars($_POST['weight'] ?? '') ?>"> </div> <div id="assignWrap" style="display:none"> <label>Assign (Only required for Yarn Out)</label> <div style="display:flex; gap:8px; align-items:center"> <select name="assign_to" id="f_assign" style="min-width:150px;background:#fff;color:#111;"></select> <a href="/erp/yarn_assign_add.php" target="_blank" class="muted" style="white-space:nowrap;text-decoration:none;border:1px solid #ddd;border-radius:8px;padding:6px 10px">+ Add Assign</a> </div> <div class="muted" style="font-size:.8rem;margin-top:4px">Dropdown se “+ Add New…” choose karke bhi add kar sakte hain.</div> </div> </div> <br> <div class="btns"> <button class="btn primary" type="submit">Submit</button> <button class="btn ghost" type="button" id="btnRecords"><?=strtoupper($init_material)?> Entry Records</button> <button class="btn ghost" type="button" id="btnReset">Reset</button> </div> </form> </div> <!-- RIGHT --> <div class="card"> <div class="title">Current Stock</div> <div id="curStock">—</div> <div class="muted">AVG Box Weight</div> <hr style="border:none;border-top:1px solid #eee;margin:12px 0"> <div class="title">Future Stock</div> <div id="futStock">—</div> </div> </div> <div class="card" style="margin-top:16px"> <div class="title" id="dynTitle">—</div> <div id="dynArea">—</div> </div> </div> <!-- Modal container for selecting boxes --> <div id="modalBoxes" style="display:none; position:fixed; left:0; right:0; top:0; bottom:0; background:rgba(0,0,0,0.4); align-items:center; justify-content:center;"> <div style="background:#fff; max-width:900px; width:95%; max-height:80vh; overflow:auto; padding:16px; border-radius:8px;"> <div style="display:flex; justify-content:space-between; align-items:center;"> <h3 style="margin:0">Select Boxes (Available)</h3> <button id="modalClose" class="btn ghost">Close</button> </div> <hr> <div id="modalContent">Loading...</div> <div style="margin-top:12px; display:flex; gap:8px; justify-content:flex-end;"> <div style="margin-right:auto" id="modalSummary" class="muted"></div> <button id="modalConfirm" class="btn primary">Confirm Selection</button> </div> </div> </div> <script> /* ------------------------- Client JS (fixed syntax errors) ------------------------- */ const $ = s => document.querySelector(s); const $$= s => Array.from(document.querySelectorAll(s)); let state = { material: <?=json_encode($init_material)?>, flow: <?=json_encode($init_flow)?>, yarn_type: <?=json_encode($init_ytype)?>, company: <?=json_encode($init_company)?>, denier: <?=json_encode($init_denier)?>, color: <?=json_encode($init_color)?>, assign_to: <?=json_encode($init_assign)?>, form_boxes: parseFloat(document.querySelector('#f_boxes').value||'0')||0, form_weight: parseFloat(document.querySelector('#f_weight').value||'0')||0 }; function setSegActiveStyles(containerSel,val){ const buttons = $$(containerSel+' button'); buttons.forEach(b=>{ const isActive = b.dataset.v === val; if(isActive){ b.style.background = '#2fb36f'; b.style.color = '#fff'; } else { b.style.background = ''; b.style.color = ''; } b.classList.toggle('active', isActive); }); } /* loadOptions with retry + fallback */ function loadOptions(level, attempt=0){ const p=new URLSearchParams({ajax:'options',level,material:state.material}); if(state.yarn_type) p.append('yarn_type',state.yarn_type); if(state.company) p.append('company',state.company); if(state.denier) p.append('denier',state.denier); const url = location.pathname+'?'+p.toString(); return fetch(url, {cache:'no-store', headers:{'X-Requested-With':'XMLHttpRequest'}}) .then(async r=>{ const ct = r.headers.get('content-type') || ''; if(!r.ok){ const body = await r.text().catch(()=>'(no body)'); throw new Error('http '+r.status+ ' ' + body); } if(!ct.includes('application/json')){ const body = await r.text().catch(()=>'(no body)'); throw new Error('non-json: '+body); } return r.json(); }) .then(j=>{ if(!j || !j.ok) return; const opts = j.data.options||[]; const fill=(id,val)=>{ const el=document.querySelector(id); if(!el) return; el.innerHTML='<option value="">— Select —</option>'; if(opts.length===0){ const o=document.createElement('option'); o.value=''; o.textContent='— No options —'; el.appendChild(o); el.style.background = '#fff'; el.style.color = '#111'; el.style.minWidth='160px'; return; } opts.forEach(v=>{ const o=document.createElement('option'); o.value=v; o.textContent=v; el.appendChild(o); }); el.style.background = '#fff'; el.style.color = '#111'; el.style.minWidth='160px'; if(opts.length===1){ el.value = opts[0]; el.dispatchEvent(new Event('change', { bubbles:true })); } else if(val){ el.value = val; } }; if(level==='type') fill('#f_yarn_type',state.yarn_type); if(level==='company')fill('#f_company',state.company); if(level==='denier') fill('#f_denier',state.denier); if(level==='color') fill('#f_color',state.color); }) .catch(err=>{ console.error('loadOptions error', level, err); if(attempt < 1){ return new Promise(resolve=>setTimeout(resolve,200)).then(()=>loadOptions(level, attempt+1)); } else { const elMap = {'type':'#f_yarn_type','company':'#f_company','denier':'#f_denier','color':'#f_color'}; const id = elMap[level] || null; if(id && document.querySelector(id)){ const sel = document.querySelector(id); sel.innerHTML = '<option value=\"\">— No options (load failed) —</option>'; sel.style.background = '#fff'; sel.style.color = '#111'; } } }); } function resetBelow(level){ if(level==='type'){ state.company=''; $('#f_company').innerHTML=''; } if(level==='type'||level==='company'){ state.denier=''; $('#f_denier').innerHTML=''; } if(level!=='color'){ state.color=''; $('#f_color').innerHTML=''; } } /* assign loader */ function loadAssignOptions(selectVal){ const sel = $('#f_assign'); if(!sel) return Promise.resolve(); sel.innerHTML = '<option value="">— Select —</option>'; return fetch(location.pathname+'?ajax=assign_options').then(r=>r.json()).then(j=>{ if(!j.ok) return; (j.data.options||[]).forEach(v=>{ const o=document.createElement('option'); o.value=v; o.textContent=v; sel.appendChild(o); }); const add=document.createElement('option'); add.value='__addnew__'; add.textContent='+ Add New…'; sel.appendChild(add); if(selectVal) sel.value=selectVal; else if(state.assign_to) sel.value=state.assign_to; }); } function hookAssignAdd(){ const sel = $('#f_assign'); if(!sel || sel.dataset.bound==='1') return; sel.dataset.bound='1'; sel.addEventListener('change', ()=>{ if(sel.value==='__addnew__'){ const nameRaw = prompt('Enter new Assign name:'); if(!nameRaw){ sel.value=''; return; } const name=nameRaw.trim(); if(!name){ sel.value=''; return; } const form=new FormData(); form.append('name',name); fetch(location.pathname+'?ajax=assign_add',{method:'POST',body:form}).then(r=>r.json()).then(j=>{ if(!j.ok){ alert('Failed to add: '+(j.error||'Unknown')); sel.value=''; return; } state.assign_to=j.data.name; loadAssignOptions(j.data.name); }); } else { state.assign_to = sel.value; } }); } /* stock panel */ let lastStockResp=null; function loadStockPanel(){ const p = new URLSearchParams({ ajax:'stock', material:state.material, flow:state.flow, yarn_type:state.yarn_type||'', company:state.company||'', denier:state.denier||'', color:state.color||'', form_boxes:state.form_boxes||0, form_weight:state.form_weight||0 }); return fetch(location.pathname+'?'+p.toString()).then(r=>r.json()).then(j=>{ if(!j.ok) return; lastStockResp=j.data; const c=j.data.current, f=j.data.future; if(c) $('#curStock').innerHTML=`<div>Boxes: <b>${c.boxes}</b></div><div>Weight: <b>${c.weight}</b> kg</div><div>AVG/Box: <b>${c.avg_box_weight}</b> kg</div>`; else $('#curStock').textContent='—'; if(f) $('#futStock').innerHTML=`<div>Boxes: <b>${f.boxes}</b></div><div>Weight: <b>${f.weight}</b> kg</div><div>AVG/Box: <b>${f.avg_box_weight}</b> kg</div>`; else $('#futStock').textContent='—'; if(c && typeof j.data.diff_pct === 'number'){ $('#diffLine').textContent=`Form AVG: ${Number(j.data.form.avg||0).toFixed(3)} • Current AVG: ${c.avg_box_weight} • Diff: ${j.data.diff_pct}%`; let pill=`<span class="pill ok">OK (≤20%)</span>`; if(j.data.status==='NOT_OK') pill=`<span class="pill warn">Not OK (21–30%)</span>`; if(j.data.status==='PROBLEM') pill=`<span class="pill bad">Problem (>30%)</span>`; $('#diffPill').innerHTML=pill; } else { $('#diffLine').textContent='—'; $('#diffPill').innerHTML=`<span class="pill na">N/A</span>`; } const last=j.data.last_entry; if(last){ let boxInfo=''; if(last.box_nos){ try{ const arr=JSON.parse(last.box_nos); boxInfo='<div style="margin-top:6px"><b>Box Details:</b><ul style="margin:6px 0 0 18px">'; arr.forEach(x=>{ boxInfo+=`<li>${x.box_no||'—'} • ${Number(x.weight||0).toFixed(3)} kg</li>`; }); boxInfo += '</ul></div>'; } catch(e){ boxInfo=`<div class="muted">Box data: ${last.box_nos}</div>`; } } $('#lastEntry').innerHTML=`<div><b>${j.data.target_table}</b> • #${last.id}</div><div class="muted">${last.txn_date}</div><div>${last.yarn_type} • ${last.company} • ${last.denier} • ${last.color}</div><div>Boxes: <b>${Number(last.boxes).toFixed(3)}</b>, Weight: <b>${Number(last.weight).toFixed(3)} kg</b>${last.assign_to?' • Assign: '+last.assign_to:''}</div>${boxInfo}`; } else $('#lastEntry').textContent='No entries yet.'; }).catch(e=>{ console.error('loadStockPanel error',e); }); } /* records view */ function loadRecordsView(){ $('#dynTitle').textContent=`${state.material.toUpperCase()} ${state.flow.toUpperCase()} — Entry Records (last 50)`; const p=new URLSearchParams({ ajax:'records', material:state.material, flow:state.flow, yarn_type:state.yarn_type||'', company:state.company||'', denier:state.denier||'', color:state.color||'' }); fetch(location.pathname+'?'+p.toString()).then(r=>r.json()).then(j=>{ if(!j.ok) return; const rows=j.data.rows||[]; if(rows.length===0){ $('#dynArea').textContent='No data.'; return; } const html=['<table>','<thead><tr><th>ID</th><th>Date</th><th>Type</th><th>Company</th><th>Denier</th><th>Color</th><th>Boxes</th><th>Weight</th><th>Boxes Detail</th><th>Assign</th></tr></thead>','<tbody>', ...rows.map(r=>{ let boxDetails=''; if(r.box_nos){ try{ const arr=JSON.parse(r.box_nos); boxDetails='<ul style="margin:6px 0 0 12px;">'+arr.map(x=>`<li>${x.box_no||'—'} : ${Number(x.weight||0).toFixed(3)} kg</li>`).join('')+'</ul>'; }catch(e){ boxDetails=(r.box_nos+'').slice(0,200); } } return `<tr><td>${r.id}</td><td>${r.txn_date}</td><td>${r.yarn_type}</td><td>${r.company}</td><td>${r.denier}</td><td>${r.color}</td><td>${Number(r.boxes).toFixed(3)}</td><td>${Number(r.weight).toFixed(3)}</td><td>${boxDetails}</td><td>${r.assign_to||''}</td></tr>` }), '</tbody></table>'].join(''); $('#dynArea').innerHTML=html; }); } /* ---------- segmented controls + visibility ------ */ function applySegStates(){ setSegActiveStyles('#segMaterial', state.material); setSegActiveStyles('#segFlow', state.flow); if($('#f_material')) $('#f_material').value = state.material; if($('#f_flow')) $('#f_flow').value = state.flow; if($('#btnRecords')) $('#btnRecords').textContent = `${state.material.toUpperCase()} Entry Records`; const showAssign = (state.flow === 'out'); if($('#assignWrap')) $('#assignWrap').style.display = showAssign ? '' : 'none'; if($('#btnSelectBoxes')) $('#btnSelectBoxes').style.display = showAssign ? '' : 'none'; if($('#btnAddBoxNos')) $('#btnAddBoxNos').style.display = showAssign ? 'none' : ''; if(showAssign){ loadAssignOptions(state.assign_to || '').then(()=>{ hookAssignAdd(); }); } } $$('#segMaterial button').forEach(b=>b.addEventListener('click', ()=>{ state.material=b.dataset.v; if($('#f_material')) $('#f_material').value = state.material; state.yarn_type=state.company=state.denier=state.color=''; applySegStates(); initDropdowns(); loadStockPanel(); })); $$('#segFlow button').forEach(b=>b.addEventListener('click', ()=>{ state.flow=b.dataset.v; if($('#f_flow')) $('#f_flow').value = state.flow; applySegStates(); loadStockPanel(); })); /* dropdown chain */ function initDropdowns(){ loadOptions('type').then(()=>{ if(state.yarn_type && $('#f_yarn_type')) $('#f_yarn_type').value = state.yarn_type; return loadOptions('company'); }).then(()=>{ if(state.company && $('#f_company')) $('#f_company').value = state.company; return loadOptions('denier'); }).then(()=>{ if(state.denier && $('#f_denier')) $('#f_denier').value = state.denier; return loadOptions('color'); }).then(()=>{ if(state.color && $('#f_color')) $('#f_color').value = state.color; loadStockPanel(); }); } $('#f_yarn_type').addEventListener('change', e => { state.yarn_type = e.target.value; resetBelow('type'); loadOptions('company').then(()=>loadStockPanel()); }); $('#f_company').addEventListener('change', e => { state.company = e.target.value; resetBelow('company'); loadOptions('denier').then(loadStockPanel); }); $('#f_denier').addEventListener('change', e=>{ state.denier = e.target.value; resetBelow('denier'); loadOptions('color').then(loadStockPanel); }); $('#f_color').addEventListener('change', e=>{ state.color = e.target.value; loadStockPanel(); }); /* live averages */ function syncFormNumbers(){ state.form_boxes=parseFloat($('#f_boxes').value||'0')||0; state.form_weight=parseFloat($('#f_weight').value||'0')||0; loadStockPanel(); } $('#f_boxes').addEventListener('input',syncFormNumbers); $('#f_weight').addEventListener('input',syncFormNumbers); $('#f_boxes').addEventListener('change',syncFormNumbers); $('#f_weight').addEventListener('change',syncFormNumbers); /* ------------------ BOX NOS / Modal handlers (fixed) ------------------ */ (function(){ function htmlEscape(s){ return (''+s).replace(/&/g,'&').replace(/</g,'<'); } const btnAddBoxNos = $('#btnAddBoxNos'); const boxNosPanel = $('#boxNosPanel'); const btnGenerateRows = $('#btnGenerateRows'); const btnClearRows = $('#btnClearRows'); const boxNosRows = $('#boxNosRows'); const fBoxes = $('#f_boxes'); const fBoxNosHidden = $('#f_box_nos'); const btnSelectBoxes = $('#btnSelectBoxes'); const modalBoxes = $('#modalBoxes'); const modalContent = $('#modalContent'); const modalSummary = $('#modalSummary'); const modalClose = $('#modalClose'); const modalConfirm = $('#modalConfirm'); const fSelectedHidden = $('#f_selected_box_nos'); function createRow(idx){ const row = document.createElement('div'); row.className = 'bn-box-row'; row.style.display = 'flex'; row.style.alignItems = 'center'; row.style.gap = '8px'; row.style.marginBottom = '6px'; row.style.minWidth = '0'; const inpBoxNo = document.createElement('input'); inpBoxNo.type = 'text'; inpBoxNo.name = 'box_no[]'; inpBoxNo.className = 'box_no'; inpBoxNo.placeholder = `Box No. (e.g. B-${idx+1})`; inpBoxNo.autocomplete = 'off'; inpBoxNo.style.flex = '1'; inpBoxNo.style.padding = '8px'; inpBoxNo.style.border = '1px solid #e6e6e6'; inpBoxNo.style.borderRadius = '8px'; inpBoxNo.style.minWidth = '0'; inpBoxNo.style.boxSizing = 'border-box'; const inpWeight = document.createElement('input'); inpWeight.type = 'number'; inpWeight.name = 'box_weight[]'; inpWeight.className = 'box_weight'; inpWeight.placeholder = 'Weight (kg)'; inpWeight.step = '0.001'; inpWeight.style.width = '160px'; inpWeight.style.padding = '8px'; inpWeight.style.border = '1px solid #e6e6e6'; inpWeight.style.borderRadius = '8px'; inpWeight.style.boxSizing = 'border-box'; row.appendChild(inpBoxNo); row.appendChild(inpWeight); return row; } function generateRowsFromCountSafe(rawCount){ let cnt = 0; try { const s = String(rawCount||'').trim(); if (s === '') cnt = 0; else cnt = parseInt(s.split('.')[0],10); if (Number.isNaN(cnt) || cnt < 0) cnt = 0; } catch(e){ cnt = 0; console.error('parse count error', e); } while(boxNosRows.firstChild){ boxNosRows.removeChild(boxNosRows.firstChild); } if (cnt === 0) { const d = document.createElement('div'); d.className='muted'; d.textContent='No rows generated. Enter box count first (positive integer).'; boxNosRows.appendChild(d); if(fBoxNosHidden) fBoxNosHidden.value = ''; return; } const frag = document.createDocumentFragment(); for(let i=0;i<cnt;i++){ frag.appendChild(createRow(i)); } boxNosRows.appendChild(frag); const first = boxNosRows.querySelector('.box_no'); if(first) first.focus(); if(fBoxNosHidden) fBoxNosHidden.value = ''; } if(btnGenerateRows){ btnGenerateRows.addEventListener('click', ()=>{ const raw = (fBoxes && fBoxes.value) ? fBoxes.value : ''; generateRowsFromCountSafe(raw); }); } if(btnClearRows){ btnClearRows.addEventListener('click', ()=>{ while(boxNosRows.firstChild) boxNosRows.removeChild(boxNosRows.firstChild); if(fBoxNosHidden) fBoxNosHidden.value = ''; }); } if(boxNosPanel){ const mo = new MutationObserver(()=> { const vis = window.getComputedStyle(boxNosPanel).display !== 'none'; if(vis){ const existing = boxNosPanel.querySelectorAll('.bn-box-row').length; const raw = (fBoxes && fBoxes.value) ? fBoxes.value : ''; const num = parseInt(String(raw||'').trim().split('.')[0],10); if (existing === 0 && !Number.isNaN(num) && num > 0) { generateRowsFromCountSafe(raw); } } }); mo.observe(boxNosPanel, { attributes: true, attributeFilter: ['style', 'class'], childList: false, subtree: false }); } if (btnAddBoxNos) { btnAddBoxNos.addEventListener('click', ()=>{ if (state.flow && state.flow.toLowerCase() === 'out') { alert('IN mode me Add Box Nos tab IN ke liye hi kaam karega. Out ke liye "Select Boxes" use karein.'); return; } const currently = boxNosPanel.style.display === 'block'; boxNosPanel.style.display = currently ? 'none' : 'block'; if (!currently) { const raw = (fBoxes && fBoxes.value) ? fBoxes.value : ''; generateRowsFromCountSafe(raw); } }); } if (btnSelectBoxes) { btnSelectBoxes.addEventListener('click', ()=>{ if (state.flow && state.flow.toLowerCase() !== 'out') { alert('Select Boxes only for OUT flow.'); return; } if (!state.yarn_type || !state.company || !state.denier || !state.color) { alert('Select Type/Company/Denier/Color first'); return; } const p=new URLSearchParams({ajax:'available_boxes', material:state.material, yarn_type:state.yarn_type, company:state.company, denier:state.denier, color:state.color}); fetch(location.pathname+'?'+p.toString()).then(r=>r.json()).then(j=>{ if(!j.ok){ alert('Failed to fetch boxes: '+(j.error||'unknown')); return; } const boxes = j.data.boxes || []; modalContent.innerHTML = ''; if(boxes.length===0){ modalContent.innerHTML='<div class="muted">No available boxes for selected filters.</div>'; modalSummary.textContent='No boxes'; modalBoxes.style.display='flex'; return; } const table = document.createElement('table'); table.style.width='100%'; table.innerHTML='<thead><tr><th></th><th>Box No</th><th>Weight (kg)</th><th>In Txn</th><th>Created</th></tr></thead>'; const tbody = document.createElement('tbody'); boxes.forEach(b=>{ const tr = document.createElement('tr'); const bn = htmlEscape(b.box_no || ''); tr.innerHTML = `<td style="padding:6px"><input type="checkbox" data-box-no="${bn}" data-weight="${b.weight||0}"></td><td style="padding:6px">${bn}</td><td style="padding:6px">${Number(b.weight||0).toFixed(3)}</td><td style="padding:6px">${htmlEscape(b.in_txn_table||'')}#${b.in_txn_id||''}</td><td style="padding:6px">${b.created_at||''}</td>`; tbody.appendChild(tr); }); table.appendChild(tbody); modalContent.appendChild(table); modalSummary.textContent = `${boxes.length} available boxes`; modalBoxes.style.display = 'flex'; }).catch(e=>{ console.error(e); alert('Error fetching boxes'); }); }); } if (modalClose) modalClose.addEventListener('click', ()=>{ if(modalBoxes) modalBoxes.style.display='none'; }); if (modalConfirm) modalConfirm.addEventListener('click', ()=>{ try { const checks = Array.from((modalContent.querySelectorAll('tbody input[type=checkbox]:checked') || [])); if(checks.length===0){ alert('Select at least one box.'); return; } const selected = checks.map(c=>({box_no:c.dataset.boxNo, weight: parseFloat(c.dataset.weight||'0')||0})); if(fSelectedHidden) fSelectedHidden.value = JSON.stringify(selected); if($('#f_boxes')) $('#f_boxes').value = selected.length; const totalW = selected.reduce((s,x)=>s + (parseFloat(x.weight)||0), 0); if($('#f_weight')) $('#f_weight').value = (Math.round((totalW + Number.EPSILON) * 1000)/1000).toFixed(3); if(modalBoxes) modalBoxes.style.display='none'; syncFormNumbers(); } catch(e){ console.error('modalConfirm error',e); alert('Selection failed'); } }); const entryForm = $('#entryForm'); if (entryForm) { entryForm.addEventListener('submit', (e)=>{ if (state.flow && state.flow.toLowerCase() === 'in') { const rows = Array.from((boxNosRows? boxNosRows.querySelectorAll('div.bn-box-row') : [])); if (rows.length > 0) { const arr2 = rows.map(r => { return { box_no: (r.querySelector('.box_no')?.value || '').trim(), weight: parseFloat((r.querySelector('.box_weight')?.value || '0')) || 0 }; }); if (arr2.some(x => !x.box_no)) { if (!confirm('Kuch Box No blank hain. Kya aap continue karna chahte hain?')) { e.preventDefault(); return; } } if(fBoxNosHidden) fBoxNosHidden.value = JSON.stringify(arr2); } else { if(fBoxNosHidden) fBoxNosHidden.value = ''; } } if (state.flow && state.flow.toLowerCase() === 'out') { const sel = (fSelectedHidden && fSelectedHidden.value) ? fSelectedHidden.value : ''; if (!sel) { alert('OUT ke liye pehle "Select Boxes" se box choose karein.'); e.preventDefault(); return; } } }); } })(); // end box module /* buttons */ $('#btnRecords').addEventListener('click',()=>loadRecordsView()); $('#btnReset').addEventListener('click',()=>{ state.yarn_type=state.company=state.denier=state.color=''; $('#f_yarn_type').innerHTML=''; $('#f_company').innerHTML=''; $('#f_denier').innerHTML=''; $('#f_color').innerHTML=''; $('#f_boxes').value=''; $('#f_weight').value=''; state.form_boxes=0; state.form_weight=0; $('#boxNosRows').innerHTML=''; $('#boxNosPanel').style.display='none'; $('#f_box_nos').value=''; $('#f_selected_box_nos').value=''; initDropdowns(); $('#f_yarn_type').focus(); }); /* init */ applySegStates(); initDropdowns(); if(state.material==='yarn' && state.flow==='out'){ loadAssignOptions(state.assign_to || '').then(()=>{ hookAssignAdd(); }); } <?php if(isset($flash['type']) && $flash['type']==='success'): ?> (function(){ document.querySelector('#f_boxes').value=''; document.querySelector('#f_weight').value=''; document.querySelector('#boxNosRows').innerHTML=''; document.querySelector('#boxNosPanel').style.display='none'; document.querySelector('#f_box_nos').value=''; document.querySelector('#f_selected_box_nos').value=''; loadStockPanel(); document.querySelector('#f_boxes').focus(); })(); <?php endif; ?> </script> </body> </html>