통계 분석(전년대비·월별·계절별), 수급계획·LOT 수불, 지정판매소·실사·메뉴 링크 등을 포함한다. Co-authored-by: Cursor <cursoragent@cursor.com>
289 lines
11 KiB
PHP
289 lines
11 KiB
PHP
<?php
|
||
$startDate = (string) ($startDate ?? date('Y-m-01'));
|
||
$endDate = (string) ($endDate ?? date('Y-m-d'));
|
||
$aggMode = (string) ($aggMode ?? 'period');
|
||
$bagCode = (string) ($bagCode ?? '');
|
||
$bagKind = (string) ($bagKind ?? '');
|
||
$saIdx = (int) ($saIdx ?? 0);
|
||
$rows = is_array($rows ?? null) ? $rows : [];
|
||
$bagProducts = is_array($bagProducts ?? null) ? $bagProducts : [];
|
||
$bagKindOptions = is_array($bagKindOptions ?? null) ? $bagKindOptions : [];
|
||
$agencies = is_array($agencies ?? null) ? $agencies : [];
|
||
$exportQuery = (string) ($exportQuery ?? 'search=1');
|
||
$queried = (bool) ($queried ?? false);
|
||
$fmt = static fn ($n): string => number_format((int) $n);
|
||
|
||
$printExtraLines = [];
|
||
if ($queried) {
|
||
$aggLabel = $aggMode === 'daily' ? '일자별' : '기간별';
|
||
$printExtraLines[] = '조회기간: ' . $startDate . ' ~ ' . $endDate . ' (' . $aggLabel . ')';
|
||
}
|
||
?>
|
||
<div class="flow-print-sheet">
|
||
<?= view('components/print_header', [
|
||
'printTitle' => '기간별 봉투 수불 현황',
|
||
'printExtraLines' => $printExtraLines,
|
||
]) ?>
|
||
|
||
<section class="border-b border-gray-300 p-2 shrink-0 bg-control-panel no-print">
|
||
<div class="flex flex-wrap items-center justify-between gap-y-2">
|
||
<span class="text-sm font-bold text-gray-700">기간별 봉투 수불 현황</span>
|
||
<div class="flex flex-wrap items-center gap-2">
|
||
<a href="<?= base_url('bag/flow/export?' . esc($exportQuery, 'attr')) ?>" class="bg-green-700 text-white px-3 py-1 rounded-sm text-sm hover:bg-green-800">엑셀저장</a>
|
||
<button type="button" onclick="window.print()" class="border border-btn-print-border text-gray-600 px-3 py-1 rounded-sm text-sm hover:bg-gray-50">인쇄</button>
|
||
<a href="<?= base_url('dashboard') ?>" class="border border-gray-400 text-gray-700 px-3 py-1 rounded-sm text-sm hover:bg-gray-50">종료</a>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="p-2 bg-white border-b border-gray-200 no-print">
|
||
<form method="get" action="<?= base_url('bag/flow') ?>" class="flex flex-wrap items-end gap-x-3 gap-y-2 text-sm">
|
||
<input type="hidden" name="search" value="1"/>
|
||
|
||
<div class="flex flex-wrap items-center gap-2">
|
||
<label class="font-bold text-gray-700 whitespace-nowrap">조회기간</label>
|
||
<input type="date" name="start_date" value="<?= esc($startDate) ?>" class="border border-gray-300 rounded px-2 py-1" required/>
|
||
<span>~</span>
|
||
<input type="date" name="end_date" value="<?= esc($endDate) ?>" class="border border-gray-300 rounded px-2 py-1" required/>
|
||
</div>
|
||
|
||
<div class="flex flex-wrap items-center gap-2">
|
||
<label class="font-bold text-gray-700 whitespace-nowrap">봉투형식</label>
|
||
<select name="bag_code" class="border border-gray-300 rounded px-2 py-1 min-w-[11rem]">
|
||
<option value="">전체 봉투</option>
|
||
<?php foreach ($bagProducts as $bp): ?>
|
||
<option value="<?= esc((string) $bp['code']) ?>" <?= $bagCode === (string) $bp['code'] ? 'selected' : '' ?>>
|
||
<?= esc((string) $bp['code']) ?> — <?= esc((string) $bp['name']) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="flex flex-wrap items-center gap-2">
|
||
<label class="font-bold text-gray-700 whitespace-nowrap">봉투구분</label>
|
||
<select name="bag_kind" class="border border-gray-300 rounded px-2 py-1 min-w-[8rem]">
|
||
<option value="">전체</option>
|
||
<?php foreach ($bagKindOptions as $opt): ?>
|
||
<option value="<?= esc((string) $opt->cd_code) ?>" <?= $bagKind === (string) $opt->cd_code ? 'selected' : '' ?>>
|
||
<?= esc((string) $opt->cd_name) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="flex flex-wrap items-center gap-2">
|
||
<label class="font-bold text-gray-700 whitespace-nowrap">대행소</label>
|
||
<select name="sa_idx" class="border border-gray-300 rounded px-2 py-1 min-w-[10rem]">
|
||
<option value="0">전체</option>
|
||
<?php foreach ($agencies as $agency): ?>
|
||
<?php
|
||
$aid = (int) ($agency->sa_idx ?? 0);
|
||
$label = (string) ($agency->sa_name ?? '');
|
||
if (isset($agency->sa_kind) && (string) $agency->sa_kind !== '') {
|
||
$label = (string) $agency->sa_kind . ' — ' . $label;
|
||
}
|
||
?>
|
||
<option value="<?= $aid ?>" <?= $saIdx === $aid ? 'selected' : '' ?>><?= esc($label) ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="flex flex-wrap items-center gap-3">
|
||
<span class="font-bold text-gray-700 whitespace-nowrap">집계방식</span>
|
||
<label class="inline-flex items-center gap-1">
|
||
<input type="radio" name="agg_mode" value="daily" <?= $aggMode === 'daily' ? 'checked' : '' ?>/>
|
||
일자별
|
||
</label>
|
||
<label class="inline-flex items-center gap-1">
|
||
<input type="radio" name="agg_mode" value="period" <?= $aggMode === 'period' ? 'checked' : '' ?>/>
|
||
기간별
|
||
</label>
|
||
</div>
|
||
|
||
<button type="submit" class="bg-btn-search text-white px-4 py-1 rounded-sm">조회</button>
|
||
<a href="<?= base_url('bag/flow') ?>" class="text-gray-500 hover:text-gray-800 px-2">초기화</a>
|
||
</form>
|
||
<p class="text-xs text-gray-500 mt-1">전일재고 = 조회 시작일 전날 기준 품목별 재고(입고·반품·기타 − 출고 누적). 대행소 선택 시 <strong>판매</strong>만 해당 대행소 소속 판매소 기준입니다.</p>
|
||
</section>
|
||
|
||
<?php if (! $queried): ?>
|
||
<div class="m-2 p-3 border border-blue-200 bg-blue-50 text-sm text-blue-900 no-print">
|
||
조회 조건을 설정한 뒤 <strong>조회</strong> 버튼을 눌러 주세요.
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($queried): ?>
|
||
<div class="p-2 overflow-auto flow-report-wrap">
|
||
<table class="w-full data-table text-sm flow-report-table">
|
||
<thead>
|
||
<tr>
|
||
<th rowspan="2" class="flow-col-date">일자</th>
|
||
<th rowspan="2" class="flow-col-item">품목</th>
|
||
<th rowspan="2" class="flow-col-num">
|
||
<span class="flow-lbl-screen">전일재고</span><span class="flow-lbl-print">전일</span>
|
||
</th>
|
||
<th colspan="4">입고</th>
|
||
<th colspan="6">출고</th>
|
||
<th rowspan="2" class="flow-col-num">잔량</th>
|
||
</tr>
|
||
<tr>
|
||
<th class="flow-col-num">입고</th>
|
||
<th class="flow-col-num">반품</th>
|
||
<th class="flow-col-num">기타</th>
|
||
<th class="flow-col-num">
|
||
<span class="flow-lbl-screen">입고계</span><span class="flow-lbl-print">입계</span>
|
||
</th>
|
||
<th class="flow-col-num">판매</th>
|
||
<th class="flow-col-num">
|
||
<span class="flow-lbl-screen">일반불출</span><span class="flow-lbl-print">일반</span>
|
||
</th>
|
||
<th class="flow-col-num">
|
||
<span class="flow-lbl-screen">무료불출</span><span class="flow-lbl-print">무료</span>
|
||
</th>
|
||
<th class="flow-col-num">반품</th>
|
||
<th class="flow-col-num">기타</th>
|
||
<th class="flow-col-num">
|
||
<span class="flow-lbl-screen">출고계</span><span class="flow-lbl-print">출계</span>
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody class="text-right">
|
||
<?php if ($rows !== []): ?>
|
||
<?php foreach ($rows as $row): ?>
|
||
<?php
|
||
$rowType = (string) ($row['row_type'] ?? 'data');
|
||
$trClass = match ($rowType) {
|
||
'subtotal', 'grand' => 'bg-amber-50 font-semibold',
|
||
default => '',
|
||
};
|
||
?>
|
||
<tr class="<?= esc($trClass) ?>">
|
||
<td class="flow-col-date text-center"><?= esc((string) ($row['date'] ?? '')) ?></td>
|
||
<td class="flow-col-item text-left pl-2"><?= esc((string) ($row['item_name'] ?? '')) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['prev_stock'] ?? 0) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['recv_in'] ?? 0) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['recv_return'] ?? 0) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['recv_misc'] ?? 0) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['recv_total'] ?? 0) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['out_sale'] ?? 0) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['out_issue_gen'] ?? 0) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['out_issue_free'] ?? 0) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['out_return'] ?? 0) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['out_misc'] ?? 0) ?></td>
|
||
<td class="flow-col-num tabular-nums"><?= $fmt($row['out_total'] ?? 0) ?></td>
|
||
<td class="flow-col-num font-semibold tabular-nums"><?= $fmt($row['balance'] ?? 0) ?></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php else: ?>
|
||
<tr>
|
||
<td colspan="15" class="text-center text-gray-400 py-8">조회 결과가 없습니다.</td>
|
||
</tr>
|
||
<?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<style>
|
||
.flow-lbl-print { display: none; }
|
||
|
||
@media screen {
|
||
.flow-report-wrap { overflow-x: auto; }
|
||
.flow-report-table { min-width: 1200px; }
|
||
}
|
||
|
||
@media print {
|
||
@page {
|
||
size: A4 portrait;
|
||
margin: 10mm 8mm;
|
||
}
|
||
|
||
html { font-size: 12px !important; }
|
||
|
||
.flow-print-sheet {
|
||
width: 100% !important;
|
||
max-width: 100% !important;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.print-header,
|
||
.print-header table,
|
||
.print-header hr {
|
||
width: 100% !important;
|
||
max-width: 100% !important;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.print-header table td[style*="width:45%"] table {
|
||
width: 160px !important;
|
||
max-width: 38% !important;
|
||
font-size: 9px !important;
|
||
}
|
||
|
||
.flow-report-wrap {
|
||
overflow: hidden !important;
|
||
padding: 0 !important;
|
||
width: 100% !important;
|
||
max-width: 100% !important;
|
||
}
|
||
|
||
.flow-report-table.data-table {
|
||
min-width: 0 !important;
|
||
width: 100% !important;
|
||
max-width: 100% !important;
|
||
table-layout: fixed !important;
|
||
font-size: 6px !important;
|
||
}
|
||
|
||
.flow-report-table.data-table th,
|
||
.flow-report-table.data-table td {
|
||
white-space: normal !important;
|
||
word-break: keep-all;
|
||
overflow-wrap: anywhere;
|
||
padding: 1px 1px !important;
|
||
line-height: 1.1;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
.flow-lbl-screen { display: none !important; }
|
||
.flow-lbl-print { display: inline !important; }
|
||
|
||
/* 세로 A4: 일자 10% + 품목 14% + 수치 12열 각 6.33% ≈ 100% */
|
||
.flow-report-table .flow-col-date {
|
||
width: 10%;
|
||
font-size: 5px !important;
|
||
text-align: center;
|
||
}
|
||
|
||
.flow-report-table .flow-col-item {
|
||
width: 14%;
|
||
text-align: left;
|
||
font-size: 5px !important;
|
||
padding-top: 3px !important;
|
||
padding-bottom: 3px !important;
|
||
line-height: 1.25;
|
||
}
|
||
|
||
.flow-report-table .flow-col-num {
|
||
width: 6.33%;
|
||
white-space: nowrap !important;
|
||
font-size: 6px !important;
|
||
text-align: right;
|
||
padding-left: 0 !important;
|
||
padding-right: 1px !important;
|
||
}
|
||
|
||
.flow-report-table thead th {
|
||
font-size: 5px !important;
|
||
font-weight: 700;
|
||
padding: 1px 0 !important;
|
||
}
|
||
|
||
.flow-report-table tbody tr {
|
||
break-inside: avoid;
|
||
page-break-inside: avoid;
|
||
}
|
||
}
|
||
</style>
|