실사 저장 안정화와 메뉴 운영 정책을 일관되게 반영한다.
실사 저장값이 페이지 이동 후 원복되지 않도록 저장/조회 경로를 보강하고, 코드 범위 보정과 bis 간 동기화를 추가했다. 또한 메뉴 관리를 레벨4 이상으로 제한하고 메뉴 변경 사항을 모든 지자체에 일괄 반영하도록 동기화 로직을 도입했다. Made-with: Cursor
This commit is contained in:
@@ -23,6 +23,9 @@ class Menu extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
|
if ($deny = $this->denyUnlessLevel4Plus()) {
|
||||||
|
return $deny;
|
||||||
|
}
|
||||||
helper('admin');
|
helper('admin');
|
||||||
$lgIdx = admin_effective_lg_idx();
|
$lgIdx = admin_effective_lg_idx();
|
||||||
if ($lgIdx === null) {
|
if ($lgIdx === null) {
|
||||||
@@ -93,6 +96,9 @@ class Menu extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function list()
|
public function list()
|
||||||
{
|
{
|
||||||
|
if ($deny = $this->denyUnlessLevel4Plus(true)) {
|
||||||
|
return $deny;
|
||||||
|
}
|
||||||
$lgIdx = admin_effective_lg_idx();
|
$lgIdx = admin_effective_lg_idx();
|
||||||
if ($lgIdx === null) {
|
if ($lgIdx === null) {
|
||||||
return $this->response->setJSON(['status' => 0, 'msg' => '지자체를 선택하세요.']);
|
return $this->response->setJSON(['status' => 0, 'msg' => '지자체를 선택하세요.']);
|
||||||
@@ -112,6 +118,9 @@ class Menu extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function store()
|
public function store()
|
||||||
{
|
{
|
||||||
|
if ($deny = $this->denyUnlessLevel4Plus()) {
|
||||||
|
return $deny;
|
||||||
|
}
|
||||||
$lgIdx = admin_effective_lg_idx();
|
$lgIdx = admin_effective_lg_idx();
|
||||||
if ($lgIdx === null) {
|
if ($lgIdx === null) {
|
||||||
return redirect()->to(base_url('admin/select-local-government'))
|
return redirect()->to(base_url('admin/select-local-government'))
|
||||||
@@ -144,6 +153,7 @@ class Menu extends BaseController
|
|||||||
if ($mmPidx > 0) {
|
if ($mmPidx > 0) {
|
||||||
$this->menuModel->updateCnode($mmPidx, 1);
|
$this->menuModel->updateCnode($mmPidx, 1);
|
||||||
}
|
}
|
||||||
|
$this->menuModel->syncTypeToAllLgs($mtIdx, $lgIdx);
|
||||||
return redirect()->back()->with('success', '메뉴가 등록되었습니다.');
|
return redirect()->back()->with('success', '메뉴가 등록되었습니다.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +162,9 @@ class Menu extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function update(int $id)
|
public function update(int $id)
|
||||||
{
|
{
|
||||||
|
if ($deny = $this->denyUnlessLevel4Plus()) {
|
||||||
|
return $deny;
|
||||||
|
}
|
||||||
$lgIdx = admin_effective_lg_idx();
|
$lgIdx = admin_effective_lg_idx();
|
||||||
if ($lgIdx === null) {
|
if ($lgIdx === null) {
|
||||||
return redirect()->to(base_url('admin/select-local-government'))
|
return redirect()->to(base_url('admin/select-local-government'))
|
||||||
@@ -171,6 +184,7 @@ class Menu extends BaseController
|
|||||||
'mm_is_view' => $this->request->getPost('mm_is_view') ? 'Y' : 'N',
|
'mm_is_view' => $this->request->getPost('mm_is_view') ? 'Y' : 'N',
|
||||||
];
|
];
|
||||||
$this->menuModel->update($id, $data);
|
$this->menuModel->update($id, $data);
|
||||||
|
$this->menuModel->syncTypeToAllLgs((int) $row->mt_idx, $lgIdx);
|
||||||
return redirect()->back()->with('success', '메뉴가 수정되었습니다.');
|
return redirect()->back()->with('success', '메뉴가 수정되었습니다.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +193,9 @@ class Menu extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function delete(int $id)
|
public function delete(int $id)
|
||||||
{
|
{
|
||||||
|
if ($deny = $this->denyUnlessLevel4Plus()) {
|
||||||
|
return $deny;
|
||||||
|
}
|
||||||
$lgIdx = admin_effective_lg_idx();
|
$lgIdx = admin_effective_lg_idx();
|
||||||
if ($lgIdx === null) {
|
if ($lgIdx === null) {
|
||||||
return redirect()->to(base_url('admin/select-local-government'))
|
return redirect()->to(base_url('admin/select-local-government'))
|
||||||
@@ -190,6 +207,7 @@ class Menu extends BaseController
|
|||||||
}
|
}
|
||||||
$result = $this->menuModel->deleteSafe($id);
|
$result = $this->menuModel->deleteSafe($id);
|
||||||
if ($result['ok']) {
|
if ($result['ok']) {
|
||||||
|
$this->menuModel->syncTypeToAllLgs((int) $row->mt_idx, $lgIdx);
|
||||||
return redirect()->back()->with('success', '메뉴가 삭제되었습니다.');
|
return redirect()->back()->with('success', '메뉴가 삭제되었습니다.');
|
||||||
}
|
}
|
||||||
return redirect()->back()->with('error', $result['msg']);
|
return redirect()->back()->with('error', $result['msg']);
|
||||||
@@ -200,6 +218,9 @@ class Menu extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function move()
|
public function move()
|
||||||
{
|
{
|
||||||
|
if ($deny = $this->denyUnlessLevel4Plus()) {
|
||||||
|
return $deny;
|
||||||
|
}
|
||||||
$lgIdx = admin_effective_lg_idx();
|
$lgIdx = admin_effective_lg_idx();
|
||||||
if ($lgIdx === null) {
|
if ($lgIdx === null) {
|
||||||
return redirect()->to(base_url('admin/select-local-government'))
|
return redirect()->to(base_url('admin/select-local-government'))
|
||||||
@@ -209,7 +230,12 @@ class Menu extends BaseController
|
|||||||
if (! is_array($ids) || empty($ids)) {
|
if (! is_array($ids) || empty($ids)) {
|
||||||
return redirect()->back()->with('error', '순서를 적용할 메뉴가 없습니다.');
|
return redirect()->back()->with('error', '순서를 적용할 메뉴가 없습니다.');
|
||||||
}
|
}
|
||||||
|
$firstId = (int) ($ids[0] ?? 0);
|
||||||
|
$firstRow = $firstId > 0 ? $this->menuModel->find($firstId) : null;
|
||||||
$this->menuModel->setOrder($ids, $lgIdx);
|
$this->menuModel->setOrder($ids, $lgIdx);
|
||||||
|
if ($firstRow && (int) $firstRow->lg_idx === $lgIdx) {
|
||||||
|
$this->menuModel->syncTypeToAllLgs((int) $firstRow->mt_idx, $lgIdx);
|
||||||
|
}
|
||||||
return redirect()->back()->with('success', '순서가 적용되었습니다.');
|
return redirect()->back()->with('success', '순서가 적용되었습니다.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,4 +292,27 @@ class Menu extends BaseController
|
|||||||
|
|
||||||
return (int) $types[0]->mt_idx;
|
return (int) $types[0]->mt_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 메뉴 관리는 레벨4 이상(슈퍼/본부 관리자)만 허용.
|
||||||
|
*
|
||||||
|
* @return \CodeIgniter\HTTP\RedirectResponse|\CodeIgniter\HTTP\ResponseInterface|null
|
||||||
|
*/
|
||||||
|
private function denyUnlessLevel4Plus(bool $json = false)
|
||||||
|
{
|
||||||
|
$level = (int) session()->get('mb_level');
|
||||||
|
if (Roles::isSuperAdminEquivalent($level)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($json) {
|
||||||
|
return $this->response->setJSON([
|
||||||
|
'status' => 0,
|
||||||
|
'msg' => '메뉴 관리는 레벨4 이상만 접근할 수 있습니다.',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->to(base_url('admin/dashboard'))
|
||||||
|
->with('error', '메뉴 관리는 레벨4 이상만 접근할 수 있습니다.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -189,4 +189,67 @@ class MenuModel extends Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 특정 메뉴 타입(mt_idx)을 source 지자체 기준으로 모든 지자체에 재배포.
|
||||||
|
* 기존 대상 지자체의 해당 타입 메뉴는 삭제 후 source 구조로 재생성한다.
|
||||||
|
*/
|
||||||
|
public function syncTypeToAllLgs(int $mtIdx, int $sourceLg): void
|
||||||
|
{
|
||||||
|
if ($mtIdx <= 0 || $sourceLg <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$source = $this->where('mt_idx', $mtIdx)
|
||||||
|
->where('lg_idx', $sourceLg)
|
||||||
|
->orderBy('mm_dep', 'ASC')
|
||||||
|
->orderBy('mm_num', 'ASC')
|
||||||
|
->findAll();
|
||||||
|
if (empty($source)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lgRows = $this->db->table('local_government')
|
||||||
|
->select('lg_idx')
|
||||||
|
->orderBy('lg_idx', 'ASC')
|
||||||
|
->get()
|
||||||
|
->getResultArray();
|
||||||
|
|
||||||
|
foreach ($lgRows as $lgRow) {
|
||||||
|
$destLg = (int) ($lgRow['lg_idx'] ?? 0);
|
||||||
|
if ($destLg <= 0 || $destLg === $sourceLg) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->db->transStart();
|
||||||
|
$this->where('mt_idx', $mtIdx)
|
||||||
|
->where('lg_idx', $destLg)
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
$idMap = [];
|
||||||
|
foreach ($source as $row) {
|
||||||
|
$oldId = (int) ($row->mm_idx ?? 0);
|
||||||
|
$oldP = (int) ($row->mm_pidx ?? 0);
|
||||||
|
$newPidx = 0;
|
||||||
|
if ($oldP > 0 && isset($idMap[$oldP])) {
|
||||||
|
$newPidx = (int) $idMap[$oldP];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->insert([
|
||||||
|
'mt_idx' => $mtIdx,
|
||||||
|
'lg_idx' => $destLg,
|
||||||
|
'mm_name' => (string) ($row->mm_name ?? ''),
|
||||||
|
'mm_link' => (string) ($row->mm_link ?? ''),
|
||||||
|
'mm_pidx' => $newPidx,
|
||||||
|
'mm_dep' => (int) ($row->mm_dep ?? 0),
|
||||||
|
'mm_num' => (int) ($row->mm_num ?? 0),
|
||||||
|
'mm_cnode' => (int) ($row->mm_cnode ?? 0),
|
||||||
|
'mm_level' => (string) ($row->mm_level ?? ''),
|
||||||
|
'mm_is_view' => (string) ($row->mm_is_view ?? 'Y'),
|
||||||
|
]);
|
||||||
|
$idMap[$oldId] = (int) $this->getInsertID();
|
||||||
|
}
|
||||||
|
$this->db->transComplete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
396
app/Views/bag/inventory_inspection_select.php
Normal file
396
app/Views/bag/inventory_inspection_select.php
Normal file
@@ -0,0 +1,396 @@
|
|||||||
|
<?php
|
||||||
|
$startDate = (string) ($startDate ?? date('Y-m-01'));
|
||||||
|
$endDate = (string) ($endDate ?? date('Y-m-d'));
|
||||||
|
$workDate = (string) ($workDate ?? date('Y-m-d'));
|
||||||
|
$itemCode = (string) ($itemCode ?? '');
|
||||||
|
$viewType = (string) ($viewType ?? 'box');
|
||||||
|
$inspectionRuns = is_array($inspectionRuns ?? null) ? $inspectionRuns : [];
|
||||||
|
$popupItems = is_array($popupItems ?? null) ? $popupItems : [];
|
||||||
|
$items = is_array($items ?? null) ? $items : [];
|
||||||
|
$overviewRows = is_array($overviewRows ?? null) ? $overviewRows : [];
|
||||||
|
$selectedInspectionItemId = (int) ($selectedInspectionItemId ?? 0);
|
||||||
|
$selectedInspectionId = (int) ($selectedInspectionId ?? 0);
|
||||||
|
$boxRows = is_array($boxRows ?? null) ? $boxRows : [];
|
||||||
|
$selectedBoxCode = (string) ($selectedBoxCode ?? '');
|
||||||
|
$selectedPackCode = (string) ($selectedPackCode ?? '');
|
||||||
|
$sheetRows = is_array($sheetRows ?? null) ? $sheetRows : [];
|
||||||
|
$overviewTotalQty = 0;
|
||||||
|
foreach ($overviewRows as $row) {
|
||||||
|
$overviewTotalQty += (int) ($row['bisi_system_qty'] ?? 0);
|
||||||
|
}
|
||||||
|
$overviewTotalActual = 0;
|
||||||
|
foreach ($overviewRows as $row) {
|
||||||
|
$overviewTotalActual += (int) ($row['bisi_actual_qty'] ?? 0);
|
||||||
|
}
|
||||||
|
$overviewTotalDiff = $overviewTotalActual - $overviewTotalQty;
|
||||||
|
$packTotalQty = 0;
|
||||||
|
foreach ($boxRows as $row) {
|
||||||
|
$packTotalQty += (int) ($row['bisp_sheet_qty'] ?? 0);
|
||||||
|
}
|
||||||
|
$packTotalActual = 0;
|
||||||
|
foreach ($boxRows as $row) {
|
||||||
|
$packTotalActual += (int) ($row['bisp_actual_qty'] ?? 0);
|
||||||
|
}
|
||||||
|
$packTotalDiff = $packTotalActual - $packTotalQty;
|
||||||
|
$sheetTotalQty = 0;
|
||||||
|
foreach ($sheetRows as $row) {
|
||||||
|
$sheetTotalQty += (int) ($row['biss_system_qty'] ?? 0);
|
||||||
|
}
|
||||||
|
$sheetTotalActual = 0;
|
||||||
|
foreach ($sheetRows as $row) {
|
||||||
|
$sheetTotalActual += (int) ($row['biss_actual_qty'] ?? 0);
|
||||||
|
}
|
||||||
|
$sheetTotalDiff = $sheetTotalActual - $sheetTotalQty;
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="space-y-2">
|
||||||
|
<section class="border border-gray-300 bg-white p-2">
|
||||||
|
<form method="get" class="flex flex-wrap items-end justify-between gap-2 text-sm">
|
||||||
|
<div class="flex flex-wrap items-end gap-2">
|
||||||
|
<label class="font-bold text-gray-700">실사기간</label>
|
||||||
|
<input type="date" name="start_date" value="<?= esc($startDate) ?>" class="border border-gray-300 rounded px-2 py-1">
|
||||||
|
<span>~</span>
|
||||||
|
<input type="date" name="end_date" value="<?= esc($endDate) ?>" class="border border-gray-300 rounded px-2 py-1">
|
||||||
|
|
||||||
|
<label class="font-bold text-gray-700 ml-2">실사품목</label>
|
||||||
|
<select name="item_code" class="border border-gray-300 rounded px-2 py-1 min-w-[11rem]">
|
||||||
|
<option value="">전체</option>
|
||||||
|
<?php foreach ($items as $it): ?>
|
||||||
|
<?php $code = (string) ($it['bag_code'] ?? ''); ?>
|
||||||
|
<option value="<?= esc($code) ?>" <?= $itemCode === $code ? 'selected' : '' ?>>
|
||||||
|
<?= esc((string) ($it['bag_name'] ?? '')) ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label class="font-bold text-gray-700 ml-2">조회구분</label>
|
||||||
|
<select name="view_type" class="border border-gray-300 rounded px-2 py-1 min-w-[7rem]">
|
||||||
|
<option value="box" <?= $viewType === 'box' ? 'selected' : '' ?>>박스별</option>
|
||||||
|
<option value="pack" <?= $viewType === 'pack' ? 'selected' : '' ?>>팩별</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<button type="submit" class="bg-btn-search text-white px-3 py-1 rounded-sm">조회</button>
|
||||||
|
<button type="button" id="open-inspection-popup" class="border border-blue-300 text-blue-700 px-3 py-1 rounded-sm hover:bg-blue-50">실사 선별</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<p class="mt-1 text-xs text-blue-700">※ 해당 박스와 팩을 클릭하면 팩과 낱장이 조회됩니다.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="grid grid-cols-1 xl:grid-cols-2 gap-2">
|
||||||
|
<div class="border border-gray-300 bg-white">
|
||||||
|
<div class="border-b border-gray-300 bg-gray-50 px-2 py-1 text-sm font-bold text-gray-700">실사 선별자</div>
|
||||||
|
<div class="overflow-auto max-h-[500px]">
|
||||||
|
<table class="w-full data-table text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="w-24">실사일자</th>
|
||||||
|
<th>종류</th>
|
||||||
|
<th class="w-40">박스</th>
|
||||||
|
<th class="w-20">전산재고</th>
|
||||||
|
<th class="w-20">실사재고</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if ($overviewRows !== []): ?>
|
||||||
|
<?php $prevBagName = null; ?>
|
||||||
|
<?php foreach ($overviewRows as $row): ?>
|
||||||
|
<?php
|
||||||
|
$itemId = (int) ($row['bisi_idx'] ?? 0);
|
||||||
|
$bagName = (string) ($row['bisi_bag_name'] ?? '');
|
||||||
|
$showBagName = $prevBagName !== $bagName;
|
||||||
|
$prevBagName = $bagName;
|
||||||
|
$boxCode = (string) ($row['box_code'] ?? '');
|
||||||
|
$isSelected = $itemId === $selectedInspectionItemId
|
||||||
|
&& ($selectedBoxCode === '' || $selectedBoxCode === $boxCode);
|
||||||
|
$url = base_url('bag/inventory/inspection-work?' . http_build_query([
|
||||||
|
'start_date' => $startDate,
|
||||||
|
'end_date' => $endDate,
|
||||||
|
'bis_id' => $selectedInspectionId,
|
||||||
|
'item_code' => $itemCode,
|
||||||
|
'view_type' => $viewType,
|
||||||
|
'sel_item_id' => $itemId,
|
||||||
|
'sel_box_code' => $boxCode,
|
||||||
|
'sel_pack_code' => '',
|
||||||
|
]));
|
||||||
|
?>
|
||||||
|
<tr class="<?= $isSelected ? 'bg-blue-100' : 'cursor-pointer hover:bg-blue-50' ?>" onclick="window.location.href='<?= esc($url, 'attr') ?>'">
|
||||||
|
<td class="text-center"><?= esc((string) ($row['bis_work_date'] ?? '')) ?></td>
|
||||||
|
<td class="pl-2"><?= $showBagName ? esc($bagName) : '' ?></td>
|
||||||
|
<td class="text-center"><?= esc((string) ($row['box_code'] ?? '')) ?></td>
|
||||||
|
<td class="text-right pr-2"><?= number_format((int) ($row['bisi_system_qty'] ?? 0)) ?></td>
|
||||||
|
<td class="text-right pr-2"><?= number_format((int) ($row['bisi_actual_qty'] ?? 0)) ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<tr><td colspan="5" class="text-center text-gray-400 py-4">조회 결과가 없습니다.</td></tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr class="bg-gray-100 font-semibold">
|
||||||
|
<td class="text-center" colspan="3">합계</td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($overviewTotalQty) ?></td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($overviewTotalActual) ?></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-2">
|
||||||
|
<div class="border border-gray-300 bg-white">
|
||||||
|
<div class="border-b border-gray-300 bg-gray-50 px-2 py-1 text-sm font-bold text-gray-700">실사 선별 품목(선택 박스 조회)</div>
|
||||||
|
<form method="post" action="<?= base_url('bag/inventory/inspection-select/save') ?>" id="inspection-save-form">
|
||||||
|
<?= csrf_field() ?>
|
||||||
|
<input type="hidden" name="bisi_idx" value="<?= esc((string) $selectedInspectionItemId) ?>">
|
||||||
|
<input type="hidden" name="bis_id" value="<?= esc((string) $selectedInspectionId) ?>">
|
||||||
|
<input type="hidden" name="start_date" value="<?= esc($startDate) ?>">
|
||||||
|
<input type="hidden" name="end_date" value="<?= esc($endDate) ?>">
|
||||||
|
<input type="hidden" name="item_code" value="<?= esc($itemCode) ?>">
|
||||||
|
<input type="hidden" name="view_type" value="<?= esc($viewType) ?>">
|
||||||
|
<input type="hidden" name="sel_item_id" value="<?= esc((string) $selectedInspectionItemId) ?>">
|
||||||
|
<input type="hidden" name="sel_box_code" value="<?= esc($selectedBoxCode) ?>">
|
||||||
|
<input type="hidden" name="sel_pack_code" value="<?= esc($selectedPackCode) ?>">
|
||||||
|
<input type="hidden" name="pack_actual_json" value="">
|
||||||
|
<div class="overflow-auto max-h-[260px]">
|
||||||
|
<table class="w-full data-table text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>팩코드</th>
|
||||||
|
<th class="w-16">포장량</th>
|
||||||
|
<th class="w-16">재고</th>
|
||||||
|
<th class="w-20">실사재고</th>
|
||||||
|
<th class="w-16">차이</th>
|
||||||
|
<th>낱장(시작)</th>
|
||||||
|
<th>낱장(끝)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if ($boxRows !== []): ?>
|
||||||
|
<?php foreach ($boxRows as $row): ?>
|
||||||
|
<?php
|
||||||
|
$code = (string) ($row['bisp_box_code'] ?? '');
|
||||||
|
$packCode = (string) ($row['bisp_pack_code'] ?? '');
|
||||||
|
$systemQty = (int) ($row['bisp_sheet_qty'] ?? 0);
|
||||||
|
$actualQty = isset($row['bisp_actual_qty']) ? (int) $row['bisp_actual_qty'] : $systemQty;
|
||||||
|
$url = base_url('bag/inventory/inspection-work?' . http_build_query([
|
||||||
|
'start_date' => $startDate,
|
||||||
|
'end_date' => $endDate,
|
||||||
|
'bis_id' => $selectedInspectionId,
|
||||||
|
'item_code' => $itemCode,
|
||||||
|
'view_type' => $viewType,
|
||||||
|
'sel_item_id' => $selectedInspectionItemId,
|
||||||
|
'sel_box_code' => $code,
|
||||||
|
'sel_pack_code' => $packCode,
|
||||||
|
]));
|
||||||
|
$isSelected = $selectedBoxCode === $code && $selectedPackCode === $packCode;
|
||||||
|
?>
|
||||||
|
<tr class="<?= $isSelected ? 'bg-blue-100' : 'cursor-pointer hover:bg-blue-50' ?>" onclick="window.location.href='<?= esc($url, 'attr') ?>'">
|
||||||
|
<td class="pl-2"><?= esc($packCode) ?></td>
|
||||||
|
<td class="text-center js-pack-system"><?= number_format($systemQty) ?></td>
|
||||||
|
<td class="text-right pr-2 js-pack-stock"><?= number_format($systemQty) ?></td>
|
||||||
|
<td class="text-right pr-2">
|
||||||
|
<input type="number" min="0"
|
||||||
|
value="<?= esc((string) $actualQty) ?>"
|
||||||
|
data-pack-idx="<?= esc((string) ($row['bisp_idx'] ?? 0), 'attr') ?>"
|
||||||
|
data-original-value="<?= esc((string) $systemQty, 'attr') ?>"
|
||||||
|
data-system-qty="<?= esc((string) $systemQty, 'attr') ?>"
|
||||||
|
class="border border-gray-300 rounded px-1 py-0.5 w-20 text-right"
|
||||||
|
onclick="event.stopPropagation();">
|
||||||
|
</td>
|
||||||
|
<?php $diff = (int) ($row['bisp_diff_qty'] ?? 0); ?>
|
||||||
|
<td class="text-right pr-2 js-pack-diff <?= $diff === 0 ? '' : ($diff > 0 ? 'text-blue-700' : 'text-red-700') ?>"><?= number_format($diff) ?></td>
|
||||||
|
<td class="text-center"><?= esc((string) ($row['bisp_sheet_start_code'] ?? '')) ?></td>
|
||||||
|
<td class="text-center"><?= esc((string) ($row['bisp_sheet_end_code'] ?? '')) ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<tr><td colspan="7" class="text-center text-gray-400 py-4">선택된 품목이 없습니다.</td></tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr class="bg-gray-100 font-semibold">
|
||||||
|
<td class="text-center" colspan="2">합계</td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($packTotalQty) ?></td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($packTotalActual) ?></td>
|
||||||
|
<td class="text-right pr-2 <?= $packTotalDiff === 0 ? '' : ($packTotalDiff > 0 ? 'text-blue-700' : 'text-red-700') ?>"><?= number_format($packTotalDiff) ?></td>
|
||||||
|
<td colspan="2"></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="p-2 border-t border-gray-300 flex items-center justify-between">
|
||||||
|
<span class="text-xs text-gray-500">선택 품목의 팩 실사수량을 입력 후 저장하세요.</span>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<button type="submit" class="bg-btn-search text-white px-3 py-1 rounded-sm text-sm">실사 저장</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="border border-gray-300 bg-white">
|
||||||
|
<div class="border-b border-gray-300 bg-gray-50 px-2 py-1 text-sm font-bold text-gray-700">실사 선별 내용(선택 낱장 코드 조회)</div>
|
||||||
|
<div class="overflow-auto max-h-[240px]">
|
||||||
|
<table class="w-full data-table text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="w-12">No</th>
|
||||||
|
<th>낱장</th>
|
||||||
|
<th class="w-16">전산</th>
|
||||||
|
<th class="w-16">실사</th>
|
||||||
|
<th class="w-16">차이</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if ($sheetRows !== []): ?>
|
||||||
|
<?php foreach ($sheetRows as $row): ?>
|
||||||
|
<?php
|
||||||
|
$sSystem = (int) ($row['biss_system_qty'] ?? 1);
|
||||||
|
$sActual = (int) ($row['biss_actual_qty'] ?? 0);
|
||||||
|
$sDiff = (int) ($row['biss_diff_qty'] ?? 0);
|
||||||
|
?>
|
||||||
|
<tr>
|
||||||
|
<td class="text-center"><?= esc((string) ($row['no'] ?? '')) ?></td>
|
||||||
|
<td class="pl-2"><?= esc((string) ($row['biss_sheet_code'] ?? '')) ?></td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($sSystem) ?></td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($sActual) ?></td>
|
||||||
|
<td class="text-right pr-2 <?= $sDiff === 0 ? '' : ($sDiff > 0 ? 'text-blue-700' : 'text-red-700') ?>"><?= number_format($sDiff) ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<tr><td colspan="5" class="text-center text-gray-400 py-4">선택된 팩/박스가 없습니다.</td></tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr class="bg-gray-100 font-semibold">
|
||||||
|
<td class="text-center" colspan="2">합계</td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($sheetTotalQty) ?></td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($sheetTotalActual) ?></td>
|
||||||
|
<td class="text-right pr-2 <?= $sheetTotalDiff === 0 ? '' : ($sheetTotalDiff > 0 ? 'text-blue-700' : 'text-red-700') ?>"><?= number_format($sheetTotalDiff) ?></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="border border-gray-300 bg-white p-2 text-sm text-gray-600">
|
||||||
|
실사 저장 시 차이수량이 즉시 장부 재고에 반영됩니다.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="inspection-popup" class="fixed inset-0 bg-black/40 hidden items-center justify-center z-[999]">
|
||||||
|
<div class="bg-white border border-gray-400 w-[min(720px,95vw)] max-h-[90vh] overflow-auto p-4">
|
||||||
|
<div class="flex items-center justify-between mb-3">
|
||||||
|
<h3 class="text-lg font-bold">실사 선별</h3>
|
||||||
|
<button type="button" id="close-inspection-popup" class="text-gray-600 hover:text-gray-900">닫기</button>
|
||||||
|
</div>
|
||||||
|
<form method="post" action="<?= base_url('bag/inventory/inspection-run') ?>" id="inspection-run-form" class="space-y-3">
|
||||||
|
<?= csrf_field() ?>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<label class="font-bold text-gray-700 text-sm">작업 일자</label>
|
||||||
|
<input type="date" name="work_date" value="<?= esc($workDate) ?>" class="border border-gray-300 rounded px-2 py-1 text-sm">
|
||||||
|
</div>
|
||||||
|
<p class="text-red-600 font-semibold">바코드가 없는 봉투는 실사에서 제외 됩니다.</p>
|
||||||
|
<div class="overflow-auto border border-gray-300 max-h-[55vh]">
|
||||||
|
<table class="w-full data-table text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr><th>종류</th><th class="w-20">선택구분</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($popupItems as $row): ?>
|
||||||
|
<?php $hasBarcode = (bool) ($row['has_barcode'] ?? false); ?>
|
||||||
|
<tr class="<?= $hasBarcode ? '' : 'bg-gray-50 text-gray-400' ?>">
|
||||||
|
<td class="pl-2"><?= esc((string) ($row['bag_name'] ?? '')) ?></td>
|
||||||
|
<td class="text-center">
|
||||||
|
<input type="checkbox" name="bag_codes[]" value="<?= esc((string) ($row['bag_code'] ?? ''), 'attr') ?>" <?= $hasBarcode ? '' : 'disabled' ?>>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<button type="submit" class="bg-btn-search text-white px-5 py-1.5 rounded-sm text-sm">실행</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(() => {
|
||||||
|
const popup = document.getElementById('inspection-popup');
|
||||||
|
const openBtn = document.getElementById('open-inspection-popup');
|
||||||
|
const closeBtn = document.getElementById('close-inspection-popup');
|
||||||
|
if (openBtn && popup) {
|
||||||
|
openBtn.addEventListener('click', () => {
|
||||||
|
popup.classList.remove('hidden');
|
||||||
|
popup.classList.add('flex');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (closeBtn && popup) {
|
||||||
|
closeBtn.addEventListener('click', () => {
|
||||||
|
popup.classList.add('hidden');
|
||||||
|
popup.classList.remove('flex');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const form = document.getElementById('inspection-run-form');
|
||||||
|
if (form) {
|
||||||
|
form.addEventListener('submit', (event) => {
|
||||||
|
if (!window.confirm('전산 선별 처리를 실행하시겠습니까?')) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveForm = document.getElementById('inspection-save-form');
|
||||||
|
if (saveForm) {
|
||||||
|
const formatNumber = (value) => {
|
||||||
|
const n = Number.isFinite(value) ? value : 0;
|
||||||
|
return n.toLocaleString('ko-KR');
|
||||||
|
};
|
||||||
|
const updateDiff = (input) => {
|
||||||
|
const row = input.closest('tr');
|
||||||
|
if (!row) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const system = parseInt(String(input.getAttribute('data-system-qty') ?? '0'), 10) || 0;
|
||||||
|
const actual = Math.max(0, parseInt(String(input.value ?? '0'), 10) || 0);
|
||||||
|
const diff = actual - system;
|
||||||
|
const diffCell = row.querySelector('.js-pack-diff');
|
||||||
|
if (!diffCell) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
diffCell.textContent = formatNumber(diff);
|
||||||
|
diffCell.classList.remove('text-blue-700', 'text-red-700');
|
||||||
|
if (diff > 0) {
|
||||||
|
diffCell.classList.add('text-blue-700');
|
||||||
|
} else if (diff < 0) {
|
||||||
|
diffCell.classList.add('text-red-700');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const qtyInputs = saveForm.querySelectorAll('input[data-pack-idx]');
|
||||||
|
qtyInputs.forEach((input) => {
|
||||||
|
input.addEventListener('input', () => updateDiff(input));
|
||||||
|
updateDiff(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
saveForm.addEventListener('submit', () => {
|
||||||
|
const payload = {};
|
||||||
|
qtyInputs.forEach((input) => {
|
||||||
|
const idx = String(input.getAttribute('data-pack-idx') ?? '').trim();
|
||||||
|
if (idx === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
payload[idx] = Math.max(0, parseInt(String(input.value ?? '0'), 10) || 0);
|
||||||
|
});
|
||||||
|
const jsonInput = saveForm.querySelector('input[name="pack_actual_json"]');
|
||||||
|
if (jsonInput) {
|
||||||
|
jsonInput.value = JSON.stringify(payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
273
app/Views/bag/inventory_inspection_select_overview.php
Normal file
273
app/Views/bag/inventory_inspection_select_overview.php
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
<?php
|
||||||
|
$startDate = (string) ($startDate ?? date('Y-m-01'));
|
||||||
|
$endDate = (string) ($endDate ?? date('Y-m-d'));
|
||||||
|
$workDate = (string) ($workDate ?? date('Y-m-d'));
|
||||||
|
$itemCode = (string) ($itemCode ?? '');
|
||||||
|
$viewType = (string) ($viewType ?? 'box');
|
||||||
|
$inspectionRuns = is_array($inspectionRuns ?? null) ? $inspectionRuns : [];
|
||||||
|
$items = is_array($items ?? null) ? $items : [];
|
||||||
|
$popupItems = is_array($popupItems ?? null) ? $popupItems : [];
|
||||||
|
$overviewRows = is_array($overviewRows ?? null) ? $overviewRows : [];
|
||||||
|
$boxRows = is_array($boxRows ?? null) ? $boxRows : [];
|
||||||
|
$sheetRows = is_array($sheetRows ?? null) ? $sheetRows : [];
|
||||||
|
$selectedInspectionId = (int) ($selectedInspectionId ?? 0);
|
||||||
|
$selectedInspectionItemId = (int) ($selectedInspectionItemId ?? 0);
|
||||||
|
$selectedBoxCode = (string) ($selectedBoxCode ?? '');
|
||||||
|
$selectedPackCode = (string) ($selectedPackCode ?? '');
|
||||||
|
$overviewTotalQty = 0;
|
||||||
|
foreach ($overviewRows as $row) {
|
||||||
|
$overviewTotalQty += (int) ($row['bisi_system_qty'] ?? 0);
|
||||||
|
}
|
||||||
|
$packTotalQty = 0;
|
||||||
|
foreach ($boxRows as $row) {
|
||||||
|
$packTotalQty += (int) ($row['bisp_sheet_qty'] ?? 0);
|
||||||
|
}
|
||||||
|
$sheetTotalQty = 0;
|
||||||
|
foreach ($sheetRows as $row) {
|
||||||
|
$sheetTotalQty += (int) ($row['biss_system_qty'] ?? 0);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="space-y-2">
|
||||||
|
<section class="border border-gray-300 bg-white p-2">
|
||||||
|
<form method="get" class="flex flex-wrap items-end justify-between gap-2 text-sm">
|
||||||
|
<div class="flex flex-wrap items-end gap-2">
|
||||||
|
<label class="font-bold text-gray-700">실사기간</label>
|
||||||
|
<input type="date" name="start_date" value="<?= esc($startDate) ?>" class="border border-gray-300 rounded px-2 py-1">
|
||||||
|
<span>~</span>
|
||||||
|
<input type="date" name="end_date" value="<?= esc($endDate) ?>" class="border border-gray-300 rounded px-2 py-1">
|
||||||
|
|
||||||
|
<label class="font-bold text-gray-700 ml-2">실사품목</label>
|
||||||
|
<select name="item_code" class="border border-gray-300 rounded px-2 py-1 min-w-[11rem]">
|
||||||
|
<option value="">전체</option>
|
||||||
|
<?php foreach ($items as $it): ?>
|
||||||
|
<?php $code = (string) ($it['bag_code'] ?? ''); ?>
|
||||||
|
<option value="<?= esc($code) ?>" <?= $itemCode === $code ? 'selected' : '' ?>><?= esc((string) ($it['bag_name'] ?? '')) ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<label class="font-bold text-gray-700 ml-2">조회구분</label>
|
||||||
|
<select name="view_type" class="border border-gray-300 rounded px-2 py-1 min-w-[7rem]">
|
||||||
|
<option value="box" <?= $viewType === 'box' ? 'selected' : '' ?>>박스별</option>
|
||||||
|
<option value="pack" <?= $viewType === 'pack' ? 'selected' : '' ?>>팩별</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<button type="submit" class="bg-btn-search text-white px-3 py-1 rounded-sm">조회</button>
|
||||||
|
<button type="button" id="open-inspection-popup" class="border border-blue-300 text-blue-700 px-3 py-1 rounded-sm hover:bg-blue-50">실사 선별</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<p class="mt-1 text-xs text-blue-700">※ 실사 선별 처리 결과를 조회하는 화면입니다(읽기 전용).</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="grid grid-cols-1 xl:grid-cols-2 gap-2">
|
||||||
|
<div class="border border-gray-300 bg-white">
|
||||||
|
<div class="border-b border-gray-300 bg-gray-50 px-2 py-1 text-sm font-bold text-gray-700">실사 선별자</div>
|
||||||
|
<div class="overflow-auto max-h-[500px]">
|
||||||
|
<table class="w-full data-table text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="w-24">실사일자</th>
|
||||||
|
<th>종류</th>
|
||||||
|
<th class="w-40">박스</th>
|
||||||
|
<th class="w-20">전산재고</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if ($overviewRows !== []): ?>
|
||||||
|
<?php $prevBagName = null; ?>
|
||||||
|
<?php foreach ($overviewRows as $row): ?>
|
||||||
|
<?php
|
||||||
|
$itemId = (int) ($row['bisi_idx'] ?? 0);
|
||||||
|
$bagName = (string) ($row['bisi_bag_name'] ?? '');
|
||||||
|
$showBagName = $prevBagName !== $bagName;
|
||||||
|
$prevBagName = $bagName;
|
||||||
|
$isSelected = $itemId === $selectedInspectionItemId;
|
||||||
|
$url = base_url('bag/inventory/inspection-select?' . http_build_query([
|
||||||
|
'start_date' => $startDate,
|
||||||
|
'end_date' => $endDate,
|
||||||
|
'bis_id' => $selectedInspectionId,
|
||||||
|
'item_code' => $itemCode,
|
||||||
|
'view_type' => $viewType,
|
||||||
|
'sel_item_id' => $itemId,
|
||||||
|
]));
|
||||||
|
?>
|
||||||
|
<tr class="<?= $isSelected ? 'bg-blue-100' : 'cursor-pointer hover:bg-blue-50' ?>" onclick="window.location.href='<?= esc($url, 'attr') ?>'">
|
||||||
|
<td class="text-center"><?= esc((string) ($row['bis_work_date'] ?? '')) ?></td>
|
||||||
|
<td class="pl-2"><?= $showBagName ? esc($bagName) : '' ?></td>
|
||||||
|
<td class="text-center"><?= esc((string) ($row['box_code'] ?? '')) ?></td>
|
||||||
|
<td class="text-right pr-2"><?= number_format((int) ($row['bisi_system_qty'] ?? 0)) ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<tr><td colspan="4" class="text-center text-gray-400 py-4">조회 결과가 없습니다.</td></tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr class="bg-gray-100 font-semibold">
|
||||||
|
<td class="text-center" colspan="3">합계</td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($overviewTotalQty) ?></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-2">
|
||||||
|
<div class="border border-gray-300 bg-white">
|
||||||
|
<div class="border-b border-gray-300 bg-gray-50 px-2 py-1 text-sm font-bold text-gray-700">실사 선별 품목(읽기 전용)</div>
|
||||||
|
<div class="overflow-auto max-h-[260px]">
|
||||||
|
<table class="w-full data-table text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>팩코드</th>
|
||||||
|
<th class="w-16">포장량</th>
|
||||||
|
<th class="w-16">재고</th>
|
||||||
|
<th>낱장(시작)</th>
|
||||||
|
<th>낱장(끝)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if ($boxRows !== []): ?>
|
||||||
|
<?php foreach ($boxRows as $row): ?>
|
||||||
|
<?php
|
||||||
|
$code = (string) ($row['bisp_box_code'] ?? '');
|
||||||
|
$packCode = (string) ($row['bisp_pack_code'] ?? '');
|
||||||
|
$systemQty = (int) ($row['bisp_sheet_qty'] ?? 0);
|
||||||
|
$url = base_url('bag/inventory/inspection-select?' . http_build_query([
|
||||||
|
'start_date' => $startDate,
|
||||||
|
'end_date' => $endDate,
|
||||||
|
'bis_id' => $selectedInspectionId,
|
||||||
|
'item_code' => $itemCode,
|
||||||
|
'view_type' => $viewType,
|
||||||
|
'sel_item_id' => $selectedInspectionItemId,
|
||||||
|
'sel_box_code' => $code,
|
||||||
|
'sel_pack_code' => $packCode,
|
||||||
|
]));
|
||||||
|
$isSelected = $selectedBoxCode === $code && $selectedPackCode === $packCode;
|
||||||
|
?>
|
||||||
|
<tr class="<?= $isSelected ? 'bg-blue-100' : 'cursor-pointer hover:bg-blue-50' ?>" onclick="window.location.href='<?= esc($url, 'attr') ?>'">
|
||||||
|
<td class="pl-2"><?= esc($packCode) ?></td>
|
||||||
|
<td class="text-center"><?= number_format($systemQty) ?></td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($systemQty) ?></td>
|
||||||
|
<td class="text-center"><?= esc((string) ($row['bisp_sheet_start_code'] ?? '')) ?></td>
|
||||||
|
<td class="text-center"><?= esc((string) ($row['bisp_sheet_end_code'] ?? '')) ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<tr><td colspan="5" class="text-center text-gray-400 py-4">선택된 품목이 없습니다.</td></tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr class="bg-gray-100 font-semibold">
|
||||||
|
<td class="text-center" colspan="2">합계</td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($packTotalQty) ?></td>
|
||||||
|
<td colspan="2"></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="border border-gray-300 bg-white">
|
||||||
|
<div class="border-b border-gray-300 bg-gray-50 px-2 py-1 text-sm font-bold text-gray-700">실사 선별 내용(읽기 전용)</div>
|
||||||
|
<div class="overflow-auto max-h-[240px]">
|
||||||
|
<table class="w-full data-table text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="w-12">No</th>
|
||||||
|
<th>낱장</th>
|
||||||
|
<th class="w-16">수량</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php if ($sheetRows !== []): ?>
|
||||||
|
<?php foreach ($sheetRows as $row): ?>
|
||||||
|
<tr>
|
||||||
|
<td class="text-center"><?= esc((string) ($row['no'] ?? '')) ?></td>
|
||||||
|
<td class="pl-2"><?= esc((string) ($row['biss_sheet_code'] ?? '')) ?></td>
|
||||||
|
<td class="text-right pr-2"><?= number_format((int) ($row['biss_system_qty'] ?? 0)) ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<tr><td colspan="3" class="text-center text-gray-400 py-4">선택된 팩/박스가 없습니다.</td></tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr class="bg-gray-100 font-semibold">
|
||||||
|
<td class="text-center" colspan="2">합계</td>
|
||||||
|
<td class="text-right pr-2"><?= number_format($sheetTotalQty) ?></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="inspection-popup" class="fixed inset-0 bg-black/40 hidden items-center justify-center z-[999]">
|
||||||
|
<div class="bg-white border border-gray-400 w-[min(720px,95vw)] max-h-[90vh] overflow-auto p-4">
|
||||||
|
<div class="flex items-center justify-between mb-3">
|
||||||
|
<h3 class="text-lg font-bold">실사 선별</h3>
|
||||||
|
<button type="button" id="close-inspection-popup" class="text-gray-600 hover:text-gray-900">닫기</button>
|
||||||
|
</div>
|
||||||
|
<form method="post" action="<?= base_url('bag/inventory/inspection-run') ?>" id="inspection-run-form" class="space-y-3">
|
||||||
|
<?= csrf_field() ?>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<label class="font-bold text-gray-700 text-sm">작업 일자</label>
|
||||||
|
<input type="date" name="work_date" value="<?= esc($workDate) ?>" class="border border-gray-300 rounded px-2 py-1 text-sm">
|
||||||
|
</div>
|
||||||
|
<p class="text-red-600 font-semibold">바코드가 없는 봉투는 실사에서 제외 됩니다.</p>
|
||||||
|
<div class="overflow-auto border border-gray-300 max-h-[55vh]">
|
||||||
|
<table class="w-full data-table text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr><th>종류</th><th class="w-20">선택구분</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($popupItems as $row): ?>
|
||||||
|
<?php $hasBarcode = (bool) ($row['has_barcode'] ?? false); ?>
|
||||||
|
<tr class="<?= $hasBarcode ? '' : 'bg-gray-50 text-gray-400' ?>">
|
||||||
|
<td class="pl-2"><?= esc((string) ($row['bag_name'] ?? '')) ?></td>
|
||||||
|
<td class="text-center">
|
||||||
|
<input type="checkbox" name="bag_codes[]" value="<?= esc((string) ($row['bag_code'] ?? ''), 'attr') ?>" <?= $hasBarcode ? '' : 'disabled' ?>>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<button type="submit" class="bg-btn-search text-white px-5 py-1.5 rounded-sm text-sm">실행</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(() => {
|
||||||
|
const popup = document.getElementById('inspection-popup');
|
||||||
|
const openBtn = document.getElementById('open-inspection-popup');
|
||||||
|
const closeBtn = document.getElementById('close-inspection-popup');
|
||||||
|
if (openBtn && popup) {
|
||||||
|
openBtn.addEventListener('click', () => {
|
||||||
|
popup.classList.remove('hidden');
|
||||||
|
popup.classList.add('flex');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (closeBtn && popup) {
|
||||||
|
closeBtn.addEventListener('click', () => {
|
||||||
|
popup.classList.add('hidden');
|
||||||
|
popup.classList.remove('flex');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const form = document.getElementById('inspection-run-form');
|
||||||
|
if (form) {
|
||||||
|
form.addEventListener('submit', (event) => {
|
||||||
|
if (!window.confirm('전산 선별 처리를 실행하시겠습니까?')) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user