feat: 실사 재고 바코드 리스트 — 창고에 있어야 하는 번호 조회/엑셀/인쇄
문의 #34: 실사 시 현재 창고에 남아있어야 하는(재고 상태) 봉투 번호(바코드) 목록을 뽑아 실물과 대조할 수 있게 신규 화면 추가. - bag/inventory/stock-barcode-list 라우트 + Bag::stockBarcodeList() - bag_receiving_pack_code 중 brpc_state='in_stock' 기준(기존 실사 스냅샷과 동일) - 품목/번호(박스·팩·시트·LOT) 필터, 인쇄, 엑셀저장(전체) - 화면 표시는 상위 2,000건 상한 + 안내 배너(합계·엑셀은 전체 기준) - 재고 관리 메뉴에 전 지자체 등록 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1312,6 +1312,111 @@ SQL);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 실사 재고 바코드 리스트 — 현재 창고에 있어야 하는(재고로 남아있는) 봉투 번호(바코드) 목록.
|
||||
* bag_receiving_pack_code 중 brpc_state='in_stock' 인 팩/박스 코드를 품목·박스·팩·시트번호(시작~끝)·매수로 뽑아
|
||||
* 실사 전 대조용으로 조회/엑셀/인쇄한다. (기존 실사 스냅샷과 동일한 in_stock 기준)
|
||||
*/
|
||||
public function stockBarcodeList(): string|ResponseInterface|RedirectResponse
|
||||
{
|
||||
$lgIdx = $this->lgIdx();
|
||||
if (! $lgIdx) {
|
||||
return redirect()->to(site_url('bag/inventory'))->with('error', '지자체를 선택해 주세요.');
|
||||
}
|
||||
|
||||
$db = \Config\Database::connect();
|
||||
$bagCode = trim((string) ($this->request->getGet('bag_code') ?? ''));
|
||||
$keyword = trim((string) ($this->request->getGet('keyword') ?? ''));
|
||||
|
||||
// 품목 선택 옵션 — 현재 재고로 남아있는 품목만
|
||||
$itemOptions = $db->table('bag_receiving_pack_code')
|
||||
->select('brpc_bag_code, MAX(brpc_bag_name) AS bag_name, COUNT(*) AS pack_cnt, SUM(brpc_sheet_qty) AS sheet_qty', false)
|
||||
->where('brpc_lg_idx', $lgIdx)
|
||||
->where('brpc_state', 'in_stock')
|
||||
->where('brpc_bag_code !=', '')
|
||||
->groupBy('brpc_bag_code')
|
||||
->orderBy('brpc_bag_code', 'ASC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
$builder = $db->table('bag_receiving_pack_code')
|
||||
->select('brpc_bag_code, brpc_bag_name, brpc_lot_no, brpc_box_code, brpc_pack_code, brpc_sheet_start_code, brpc_sheet_end_code, brpc_sheet_qty')
|
||||
->where('brpc_lg_idx', $lgIdx)
|
||||
->where('brpc_state', 'in_stock');
|
||||
if ($bagCode !== '') {
|
||||
$builder->where('brpc_bag_code', $bagCode);
|
||||
}
|
||||
if ($keyword !== '') {
|
||||
$builder->groupStart()
|
||||
->like('brpc_box_code', $keyword)
|
||||
->orLike('brpc_pack_code', $keyword)
|
||||
->orLike('brpc_sheet_start_code', $keyword)
|
||||
->orLike('brpc_sheet_end_code', $keyword)
|
||||
->orLike('brpc_lot_no', $keyword)
|
||||
->groupEnd();
|
||||
}
|
||||
$rows = $builder
|
||||
->orderBy('brpc_bag_code', 'ASC')
|
||||
->orderBy('brpc_box_code', 'ASC')
|
||||
->orderBy('brpc_pack_code', 'ASC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
// 합계 — 박스 수(고유), 팩 수, 총 매수
|
||||
$totalPacks = count($rows);
|
||||
$totalSheets = 0;
|
||||
$boxSet = [];
|
||||
foreach ($rows as $r) {
|
||||
$totalSheets += (int) ($r['brpc_sheet_qty'] ?? 0);
|
||||
$bx = trim((string) ($r['brpc_box_code'] ?? ''));
|
||||
if ($bx !== '') {
|
||||
$boxSet[$bx] = true;
|
||||
}
|
||||
}
|
||||
$totalBoxes = count($boxSet);
|
||||
|
||||
// 엑셀 다운로드 — 현재 필터 그대로
|
||||
if ((string) ($this->request->getGet('export') ?? '') === '1') {
|
||||
helper('export');
|
||||
$exportRows = [];
|
||||
foreach ($rows as $r) {
|
||||
$exportRows[] = [
|
||||
(string) ($r['brpc_bag_name'] ?? '') !== '' ? (string) $r['brpc_bag_name'] : (string) ($r['brpc_bag_code'] ?? ''),
|
||||
(string) ($r['brpc_lot_no'] ?? ''),
|
||||
(string) ($r['brpc_box_code'] ?? ''),
|
||||
(string) ($r['brpc_pack_code'] ?? ''),
|
||||
(string) ($r['brpc_sheet_start_code'] ?? ''),
|
||||
(string) ($r['brpc_sheet_end_code'] ?? ''),
|
||||
number_format((int) ($r['brpc_sheet_qty'] ?? 0)),
|
||||
];
|
||||
}
|
||||
$exportRows[] = ['합계', '', '박스 ' . number_format($totalBoxes), '팩 ' . number_format($totalPacks), '', '', number_format($totalSheets)];
|
||||
export_xlsx(
|
||||
'실사재고바코드리스트_' . date('Ymd') . '.xlsx',
|
||||
'창고재고바코드',
|
||||
['품목', 'LOT', '박스코드', '팩코드', '시작번호', '끝번호', '매수'],
|
||||
$exportRows
|
||||
);
|
||||
}
|
||||
|
||||
// 화면 표시는 성능을 위해 상위 N건까지만(합계·엑셀 저장은 항상 전체 기준)
|
||||
$displayLimit = 2000;
|
||||
$displayTruncated = count($rows) > $displayLimit;
|
||||
$displayRows = $displayTruncated ? array_slice($rows, 0, $displayLimit) : $rows;
|
||||
|
||||
return $this->render('실사 재고 바코드 리스트', 'bag/inventory_stock_barcode_list', [
|
||||
'bagCode' => $bagCode,
|
||||
'keyword' => $keyword,
|
||||
'itemOptions' => $itemOptions,
|
||||
'rows' => $displayRows,
|
||||
'totalBoxes' => $totalBoxes,
|
||||
'totalPacks' => $totalPacks,
|
||||
'totalSheets' => $totalSheets,
|
||||
'displayTruncated' => $displayTruncated,
|
||||
'displayLimit' => $displayLimit,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{
|
||||
* rows: list<array{group:string,name:string,total_qty:int,gugun_qty:int,agency_qty:int}>,
|
||||
|
||||
Reference in New Issue
Block a user