feat: 판매대장 크기 필터를 봉투/음식물/폐기물 카테고리별 그룹으로
- 크기 드롭다운을 카테고리별 optgroup(봉투(일반용)/음식물/폐기물 등)으로 묶음 - 선택값을 '카테고리|크기'(예: general|3L)로 바꿔 카테고리+크기 조합 필터링 - 엑셀저장에도 size 파라미터 반영(기존 누락 수정) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -87,24 +87,59 @@ class SalesReport extends BaseController
|
|||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
};
|
};
|
||||||
// 현재(카테고리 필터까지 적용된) 결과에서 선택 가능한 크기 목록 구성
|
// 봉투(일반용)/음식물/폐기물 등 카테고리별로 선택 가능한 크기 목록을 구성한다.
|
||||||
$sizeOptions = [];
|
// (카테고리 필터까지 적용된 현재 결과 기준)
|
||||||
|
$sizeCatLabels = [
|
||||||
|
'general' => '봉투(일반용)',
|
||||||
|
'food' => '음식물',
|
||||||
|
'waste' => '폐기물',
|
||||||
|
'sticker' => '스티커',
|
||||||
|
'reuse' => '재사용',
|
||||||
|
'apt' => '공동주택용',
|
||||||
|
'public_use' => '공공용',
|
||||||
|
'container' => '용기',
|
||||||
|
];
|
||||||
|
$sizeCatOrder = ['general', 'food', 'waste', 'sticker', 'reuse', 'apt', 'public_use', 'container'];
|
||||||
|
|
||||||
|
$sizeByCat = []; // catKey => [size => true]
|
||||||
foreach ($filtered as $row) {
|
foreach ($filtered as $row) {
|
||||||
$sz = $sizeOf((string) ($row->bs_bag_name ?? ''));
|
$sz = $sizeOf((string) ($row->bs_bag_name ?? ''));
|
||||||
if ($sz !== '') {
|
if ($sz === '') {
|
||||||
$sizeOptions[$sz] = true;
|
continue;
|
||||||
}
|
}
|
||||||
|
$ck = $this->classifyLedgerProductCategory(
|
||||||
|
(string) ($row->bs_bag_name ?? ''),
|
||||||
|
(string) ($row->bs_bag_code ?? '')
|
||||||
|
);
|
||||||
|
$sizeByCat[$ck][$sz] = true;
|
||||||
|
}
|
||||||
|
$sizeGroups = [];
|
||||||
|
foreach ($sizeCatOrder as $ck) {
|
||||||
|
if (empty($sizeByCat[$ck])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$sizes = array_keys($sizeByCat[$ck]);
|
||||||
|
usort($sizes, static function (string $a, string $b): int {
|
||||||
|
return (int) preg_replace('/\D/', '', $a) <=> (int) preg_replace('/\D/', '', $b);
|
||||||
|
});
|
||||||
|
$sizeGroups[] = ['key' => $ck, 'label' => $sizeCatLabels[$ck] ?? $ck, 'sizes' => $sizes];
|
||||||
}
|
}
|
||||||
$sizeOptions = array_keys($sizeOptions);
|
|
||||||
usort($sizeOptions, static function (string $a, string $b): int {
|
|
||||||
$na = (int) preg_replace('/\D/', '', $a);
|
|
||||||
$nb = (int) preg_replace('/\D/', '', $b);
|
|
||||||
return $na <=> $nb;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// 선택값은 "카테고리|크기" 형식(예: general|10L). 구버전(크기만) 값도 호환.
|
||||||
$size = trim((string) ($this->request->getGet('size') ?? ''));
|
$size = trim((string) ($this->request->getGet('size') ?? ''));
|
||||||
if ($size !== '') {
|
if ($size !== '') {
|
||||||
$filtered = array_values(array_filter($filtered, static fn ($row): bool => $sizeOf((string) ($row->bs_bag_name ?? '')) === $size));
|
if (strpos($size, '|') !== false) {
|
||||||
|
[$selCat, $selSize] = array_pad(explode('|', $size, 2), 2, '');
|
||||||
|
$filtered = array_values(array_filter($filtered, function ($row) use ($sizeOf, $selCat, $selSize): bool {
|
||||||
|
$ck = $this->classifyLedgerProductCategory(
|
||||||
|
(string) ($row->bs_bag_name ?? ''),
|
||||||
|
(string) ($row->bs_bag_code ?? '')
|
||||||
|
);
|
||||||
|
return $ck === $selCat && $sizeOf((string) ($row->bs_bag_name ?? '')) === $selSize;
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
$filtered = array_values(array_filter($filtered, static fn ($row): bool => $sizeOf((string) ($row->bs_bag_name ?? '')) === $size));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($mode === 'daily') {
|
if ($mode === 'daily') {
|
||||||
@@ -199,7 +234,7 @@ class SalesReport extends BaseController
|
|||||||
'dsIdx' => $dsIdx,
|
'dsIdx' => $dsIdx,
|
||||||
'saIdx' => $saIdx,
|
'saIdx' => $saIdx,
|
||||||
'cats' => $cats,
|
'cats' => $cats,
|
||||||
'sizeOptions' => $sizeOptions,
|
'sizeGroups' => $sizeGroups,
|
||||||
'size' => $size,
|
'size' => $size,
|
||||||
'shops' => $shops,
|
'shops' => $shops,
|
||||||
'agencies' => $agencies,
|
'agencies' => $agencies,
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ $exportParams = [
|
|||||||
if ($cats !== []) {
|
if ($cats !== []) {
|
||||||
$exportParams['cat'] = $cats;
|
$exportParams['cat'] = $cats;
|
||||||
}
|
}
|
||||||
|
if (($size ?? '') !== '') {
|
||||||
|
$exportParams['size'] = $size;
|
||||||
|
}
|
||||||
$excelUrl = mgmt_url('reports/sales-ledger?' . http_build_query($exportParams));
|
$excelUrl = mgmt_url('reports/sales-ledger?' . http_build_query($exportParams));
|
||||||
?>
|
?>
|
||||||
<?= view('components/print_header', [
|
<?= view('components/print_header', [
|
||||||
@@ -117,10 +120,15 @@ $excelUrl = mgmt_url('reports/sales-ledger?' . http_build_query($exportParams));
|
|||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<span class="inline-flex items-center gap-1 ml-2 pl-3 border-l border-gray-200">
|
<span class="inline-flex items-center gap-1 ml-2 pl-3 border-l border-gray-200">
|
||||||
<span class="text-xs text-gray-600">크기</span>
|
<span class="text-xs text-gray-600">크기</span>
|
||||||
<select name="size" class="border border-gray-300 rounded px-2 py-1 text-sm">
|
<select name="size" class="border border-gray-300 rounded px-2 py-1 text-sm min-w-[10rem]">
|
||||||
<option value="">전체</option>
|
<option value="">전체</option>
|
||||||
<?php foreach (($sizeOptions ?? []) as $sz): ?>
|
<?php foreach (($sizeGroups ?? []) as $g): ?>
|
||||||
<option value="<?= esc($sz, 'attr') ?>" <?= ($size ?? '') === $sz ? 'selected' : '' ?>><?= esc($sz) ?></option>
|
<optgroup label="<?= esc($g['label'], 'attr') ?>">
|
||||||
|
<?php foreach (($g['sizes'] ?? []) as $sz): ?>
|
||||||
|
<?php $val = $g['key'] . '|' . $sz; ?>
|
||||||
|
<option value="<?= esc($val, 'attr') ?>" <?= ($size ?? '') === $val ? 'selected' : '' ?>><?= esc($sz) ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</optgroup>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user