Files
jongryangje/app/Views/admin/sales_report/hometax_process.php

323 lines
11 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
/** @var string $startDate */
/** @var string $endDate */
/** @var string $writeDate */
/** @var bool $searched */
/** @var list<string> $headers */
/** @var list<list<string>> $displayRows */
/** @var int $totalCount */
/** @var float $totalSupplyAmount */
/** @var float $totalTaxAmount */
/** @var int $missingBizCount */
/** @var string $lgName */
/** @var list<string> $printExtraLines */
/** @var list<array{label: string, sheet_name: string, cols: list<int>}> $hometaxPrintPages */
/** @var list<int> $hometaxColMinPx */
helper('admin');
$baseParams = [
'start_date' => $startDate ?? '',
'end_date' => $endDate ?? '',
'write_date' => $writeDate ?? '',
];
$searchParams = array_merge($baseParams, ['search' => '1']);
$exportParams = array_merge($searchParams, ['export' => '1']);
$searchUrl = mgmt_url('reports/hometax-export?' . http_build_query($searchParams));
$excelUrl = mgmt_url('reports/hometax-export?' . http_build_query($exportParams));
$totalGrand = (float) ($totalSupplyAmount ?? 0) + (float) ($totalTaxAmount ?? 0);
$colCount = max(1, count($headers ?? []));
/** 홈택스 28열 — 주소·상호·이메일 등 텍스트 열을 넓게 (합계 100%) */
$hometaxColWidths = [
'4.5%', '4%', '4%', '6%', '3%', '6.5%', '3.5%', '11%', '3%', '3%', '5.5%',
'6%', '3%', '6.5%', '3.5%', '11%', '3%', '3%', '5.5%',
'4%', '4%', '3%', '5.5%', '3%', '3%', '3.5%', '3.5%', '3.5%',
];
$hometaxColMinPx = $hometaxColMinPx ?? [];
$hometaxPrintPages = $hometaxPrintPages ?? [];
$hometaxWrapColIdx = [7, 15, 5, 6, 13, 14, 10, 18, 22, 27];
$hometaxNumColIdx = [19, 20, 24, 25, 26, 27];
$hometaxNormalizeColWidths = static function (array $colIndices) use ($hometaxColWidths): array {
$sum = 0.0;
foreach ($colIndices as $ci) {
$sum += (float) str_replace('%', '', (string) ($hometaxColWidths[$ci] ?? '3'));
}
$normalized = [];
foreach ($colIndices as $ci) {
$pct = (float) str_replace('%', '', (string) ($hometaxColWidths[$ci] ?? '3'));
$normalized[$ci] = ($sum > 0 ? round($pct / $sum * 100, 2) : round(100 / max(1, count($colIndices)), 2)) . '%';
}
return $normalized;
};
$hometaxCellClass = static function (int $ci) use ($hometaxWrapColIdx, $hometaxNumColIdx): string {
$class = 'text-left px-1 py-1';
if (in_array($ci, $hometaxWrapColIdx, true)) {
$class .= ' ht-wrap';
}
if (in_array($ci, $hometaxNumColIdx, true)) {
$class .= ' ht-num';
}
return $class;
};
/**
* @param list<int> $colIndices
*/
$hometaxRenderTable = static function (
array $colIndices,
string $tableExtraClass,
string $tableId,
bool $forPrint
) use (
$headers,
$displayRows,
$searched,
$colCount,
$hometaxColWidths,
$hometaxColMinPx,
$hometaxCellClass,
$hometaxNormalizeColWidths
): void {
$sliceCount = count($colIndices);
$widthsForSet = $hometaxNormalizeColWidths($colIndices);
?>
<table
class="w-full data-table text-xs <?= esc($tableExtraClass, 'attr') ?>"
id="<?= esc($tableId, 'attr') ?>"
<?= $forPrint ? 'data-hometax-print="1"' : '' ?>
>
<colgroup>
<?php foreach ($colIndices as $ci):
$wPct = $widthsForSet[$ci] ?? (string) round(100 / max(1, $sliceCount), 2) . '%';
$wPx = (int) ($hometaxColMinPx[$ci] ?? 56);
?>
<col style="width: <?= esc($wPct, 'attr') ?>;<?= $forPrint ? '' : ' min-width: ' . $wPx . 'px' ?>"/>
<?php endforeach; ?>
</colgroup>
<thead>
<tr>
<?php foreach ($colIndices as $ci): ?>
<th class="<?= esc($hometaxCellClass($ci), 'attr') ?>"><?= esc((string) ($headers[$ci] ?? '')) ?></th>
<?php endforeach; ?>
</tr>
</thead>
<tbody class="text-right">
<?php if (! ($searched ?? true)): ?>
<tr>
<td colspan="<?= (int) $sliceCount ?>" class="text-center text-gray-500 py-8">조회를 건너뛴 상태입니다. <strong>조회</strong> 눌러 주세요.</td>
</tr>
<?php elseif (($displayRows ?? []) === []): ?>
<tr>
<td colspan="<?= (int) $sliceCount ?>" class="text-center text-gray-500 py-8">조회된 판매 내역이 없습니다.</td>
</tr>
<?php else: ?>
<?php foreach ($displayRows as $row): ?>
<tr>
<?php foreach ($colIndices as $ci):
$tdClass = 'tabular-nums text-left px-1 py-0.5 border-t border-gray-100 ' . $hometaxCellClass($ci);
?>
<td class="<?= esc(trim($tdClass), 'attr') ?>"><?= esc((string) ($row[$ci] ?? '')) ?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
<?php
};
?>
<?= view('components/print_header', [
'printTitle' => '홈택스 처리',
'printExtraLines' => $printExtraLines ?? [],
]) ?>
<section class="border-b border-gray-300 p-3 shrink-0 bg-control-panel no-print">
<div class="flex flex-wrap items-center justify-between gap-2 mb-2">
<h1 class="text-base font-bold text-gray-800">홈택스 처리</h1>
<div class="flex flex-wrap gap-2 items-center">
<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 transition">인쇄</button>
<a href="<?= esc($excelUrl, 'attr') ?>" class="inline-flex items-center border border-green-600 text-green-700 px-3 py-1 rounded-sm text-sm hover:bg-green-50 transition">엑셀저장</a>
</div>
</div>
<form method="get" action="<?= esc(mgmt_url('reports/hometax-export'), 'attr') ?>" id="hometax-process-form" class="flex flex-wrap items-end gap-3 text-sm">
<input type="hidden" name="search" value="1"/>
<div>
<label class="block text-gray-600 mb-0.5">판매일자</label>
<div class="flex items-center gap-1">
<input type="date" name="start_date" value="<?= esc($startDate ?? '') ?>" class="border border-gray-300 rounded px-2 py-1 text-sm"/>
<span class="text-gray-500">~</span>
<input type="date" name="end_date" value="<?= esc($endDate ?? '') ?>" class="border border-gray-300 rounded px-2 py-1 text-sm"/>
</div>
</div>
<div>
<label class="block text-gray-600 mb-0.5">작성일자</label>
<input type="date" name="write_date" value="<?= esc($writeDate ?? '') ?>" class="border border-gray-300 rounded px-2 py-1 text-sm"/>
</div>
<div class="pt-5">
<button type="submit" class="border border-blue-600 bg-blue-50 text-blue-800 px-4 py-1 rounded-sm text-sm font-medium hover:bg-blue-100 transition">조회</button>
</div>
</form>
</section>
<section class="p-3 bg-white border-b border-gray-200 hometax-report-section">
<style>
.hometax-print-only { display: none; }
@media print {
@page {
size: A4 landscape;
margin: 4mm 5mm;
}
.hometax-report-section {
padding: 0 !important;
border: none !important;
}
.hometax-screen-only {
display: none !important;
}
.hometax-print-only {
display: block !important;
}
.hometax-print-page {
page-break-after: always;
break-after: page;
}
.hometax-print-page:last-child {
page-break-after: auto;
break-after: auto;
}
.hometax-print-page-label {
font-size: 8pt;
font-weight: 700;
margin: 0 0 4px;
}
.hometax-print-scroll {
overflow: visible !important;
border: 1px solid #333 !important;
}
.hometax-print-table {
font-size: 8pt !important;
width: 100% !important;
table-layout: fixed !important;
}
.hometax-print-table th,
.hometax-print-table td {
padding: 3px 5px !important;
white-space: normal !important;
word-break: break-word;
overflow-wrap: break-word;
line-height: 1.3;
vertical-align: top;
}
.hometax-print-table th {
font-size: 7.5pt !important;
font-weight: 600;
}
.hometax-print-table .ht-num {
white-space: nowrap !important;
word-break: normal !important;
}
.hometax-print-table thead {
display: table-header-group;
}
.hometax-print-table tr {
page-break-inside: avoid;
break-inside: avoid;
}
}
@media screen {
#hometax-result-table {
width: max(100%, 4200px);
min-width: 4200px;
table-layout: fixed;
}
#hometax-result-table th,
#hometax-result-table td {
white-space: nowrap;
padding: 4px 6px !important;
}
#hometax-result-table .ht-wrap {
white-space: normal;
word-break: break-word;
max-width: 220px;
}
}
</style>
<div class="text-sm font-semibold text-gray-700 mb-2 no-print">조회결과</div>
<div class="hometax-screen-only hometax-scroll-wrap overflow-x-auto border border-gray-300" style="max-width: 100%;">
<?php
$hometaxRenderTable(
range(0, max(0, $colCount - 1)),
'',
'hometax-result-table',
false
);
?>
</div>
<div class="hometax-print-only" aria-hidden="true">
<?php foreach ($hometaxPrintPages as $ppi => $page):
$pageCols = $page['cols'];
if ($pageCols === []) {
continue;
}
?>
<section class="hometax-print-page">
<p class="hometax-print-page-label"><?= esc((string) ($page['label'] ?? '')) ?></p>
<div class="hometax-print-scroll">
<?php
$hometaxRenderTable(
$pageCols,
'hometax-print-table',
'hometax-print-table-' . (int) $ppi,
true
);
?>
</div>
</section>
<?php endforeach; ?>
</div>
<div class="mt-4 flex flex-wrap gap-6 text-sm border-t border-gray-200 pt-3 no-print">
<div><span class="text-gray-600"> 건수</span> <strong class="tabular-nums"><?= (int) ($totalCount ?? 0) ?></strong> 건</div>
<div><span class="text-gray-600"> 금액</span> <strong class="tabular-nums"><?= esc(number_format((int) round($totalGrand))) ?></strong> 원 <span class="text-gray-400 text-xs">(공급가액+세액)</span></div>
<div><span class="text-gray-600">사업자등록번호 없음</span> <strong class="tabular-nums text-amber-800"><?= (int) ($missingBizCount ?? 0) ?></strong> 건</div>
</div>
<div class="mt-2 text-xs text-gray-500 no-print print:hidden">
인쇄·엑셀저장은 동일하게 2 구성입니다(1: 공급자·공급받는자, 2: 금액·품목). 요약·결재란은 인쇄용 헤더에 포함됩니다.
</div>
</section>
<style media="print">
.no-print { display: none !important; }
</style>
<script>
(function () {
let savedTitle = document.title;
function stamp() {
const d = new Date();
const p = (n) => String(n).padStart(2, '0');
return d.getFullYear() + p(d.getMonth() + 1) + p(d.getDate()) + '_' + p(d.getHours()) + p(d.getMinutes()) + p(d.getSeconds());
}
window.addEventListener('beforeprint', function () {
savedTitle = document.title;
document.title = '홈택스처리_' + stamp();
});
window.addEventListener('afterprint', function () {
document.title = savedTitle;
});
})();
</script>