feat: '발주파일 생성'(구 LOT-No 디스켓 불출) 이름변경 + 생성 전 내용 확인
- 메뉴/화면/매뉴얼 명칭을 '발주파일 생성'으로 변경(메뉴 rename 마이그레이션 SQL 포함) - 발주파일(seed) 생성 전 '내용 확인' 미리보기 추가(암호화 전 발주 메타·품목 표시) · GET bag/order/lot-seed/preview 신설, 생성/미리보기 데이터 구성 공용화 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,7 @@ for ($year = $baseYear - 2; $year <= $baseYear + 2; $year++) {
|
||||
?>
|
||||
|
||||
<section class="border-b border-gray-300 p-2 shrink-0 bg-control-panel">
|
||||
<span class="text-sm font-bold text-gray-700">LOT-No 디스켓 불출</span>
|
||||
<span class="text-sm font-bold text-gray-700">발주파일 생성</span>
|
||||
</section>
|
||||
|
||||
<section class="border border-gray-300 rounded-lg p-2 mt-2 bg-white">
|
||||
@@ -92,11 +92,12 @@ for ($year = $baseYear - 2; $year <= $baseYear + 2; $year++) {
|
||||
?>
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<form method="post" action="<?= base_url('bag/order/lot-seed/generate') ?>" class="inline">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="bo_idx" value="<?= $boIdx ?>" />
|
||||
<button type="submit" class="text-blue-600 hover:underline text-xs">seed 생성</button>
|
||||
</form>
|
||||
<button type="button"
|
||||
class="lot-preview-btn text-blue-600 hover:underline text-xs"
|
||||
data-bo-idx="<?= $boIdx ?>"
|
||||
data-lot="<?= esc((string) ($order->bo_lot_no ?? ''), 'attr') ?>">
|
||||
내용 확인
|
||||
</button>
|
||||
</td>
|
||||
<td class="text-center"><?= esc((string) ($order->bo_order_date ?? '')) ?></td>
|
||||
<td class="text-center font-mono"><?= esc((string) ($order->bo_lot_no ?? '')) ?></td>
|
||||
@@ -128,3 +129,133 @@ for ($year = $baseYear - 2; $year <= $baseYear + 2; $year++) {
|
||||
<?php if (isset($pager)): ?>
|
||||
<div class="mt-2 mb-2 no-print"><?= $pager->links() ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 발주파일 생성 전 '내용 확인' 모달 -->
|
||||
<div id="lot-preview-overlay" class="fixed inset-0 z-50 hidden items-center justify-center bg-black/40 p-4">
|
||||
<div class="bg-white rounded-lg shadow-xl w-full max-w-3xl max-h-[85vh] flex flex-col">
|
||||
<div class="flex items-center justify-between border-b border-gray-200 px-4 py-2">
|
||||
<span class="text-sm font-bold text-gray-800">발주파일 내용 확인</span>
|
||||
<button type="button" id="lot-preview-close" class="text-gray-400 hover:text-gray-700 text-lg leading-none">×</button>
|
||||
</div>
|
||||
<div class="p-4 overflow-auto text-sm">
|
||||
<div id="lot-preview-loading" class="text-center text-gray-400 py-8">불러오는 중…</div>
|
||||
<div id="lot-preview-error" class="hidden text-center text-red-600 py-8"></div>
|
||||
<div id="lot-preview-body" class="hidden">
|
||||
<p class="text-xs text-gray-500 mb-2">아래 내용으로 <b>암호화된 발주파일(.seed.json)</b>이 생성·다운로드됩니다. 생성 전 내용을 확인하세요.</p>
|
||||
<dl class="grid grid-cols-[6rem_1fr] gap-y-1 text-[13px] mb-3 border border-gray-200 rounded p-2 bg-gray-50">
|
||||
<dt class="font-semibold text-gray-600">LOT-No</dt><dd class="font-mono" id="lp-lot"></dd>
|
||||
<dt class="font-semibold text-gray-600">발주일</dt><dd id="lp-date"></dd>
|
||||
<dt class="font-semibold text-gray-600">제작업체</dt><dd id="lp-company"></dd>
|
||||
<dt class="font-semibold text-gray-600">버전</dt><dd id="lp-version"></dd>
|
||||
<dt class="font-semibold text-gray-600">무결성해시</dt><dd class="font-mono text-[11px] text-gray-500 break-all" id="lp-hash"></dd>
|
||||
</dl>
|
||||
<div class="overflow-auto border border-gray-200 rounded">
|
||||
<table class="w-full data-table text-[13px]">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left pl-2">봉투코드</th>
|
||||
<th class="text-left">봉투명</th>
|
||||
<th class="w-20 text-right">단가</th>
|
||||
<th class="w-16 text-right">박스</th>
|
||||
<th class="w-16 text-right">팩</th>
|
||||
<th class="w-20 text-right">낱장</th>
|
||||
<th class="w-24 text-right pr-2">금액</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="lp-items"></tbody>
|
||||
<tfoot>
|
||||
<tr class="font-semibold bg-gray-50">
|
||||
<td class="pl-2" colspan="3">합계 (<span id="lp-line-count">0</span>품목)</td>
|
||||
<td class="text-right" id="lp-sum-box">0</td>
|
||||
<td class="text-right">—</td>
|
||||
<td class="text-right" id="lp-sum-sheet">0</td>
|
||||
<td class="text-right pr-2" id="lp-sum-amount">0</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-gray-200 px-4 py-2 flex items-center justify-end gap-2">
|
||||
<button type="button" id="lot-preview-cancel" class="border border-gray-300 text-gray-600 px-3 py-1.5 rounded-sm text-sm hover:bg-gray-50">닫기</button>
|
||||
<form method="post" action="<?= base_url('bag/order/lot-seed/generate') ?>" class="inline" id="lot-generate-form">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="bo_idx" id="lot-generate-bo-idx" value="" />
|
||||
<button type="submit" id="lot-generate-submit" class="bg-btn-search text-white px-4 py-1.5 rounded-sm text-sm shadow hover:opacity-90 disabled:opacity-50" disabled>발주파일 생성(다운로드)</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var previewUrl = '<?= base_url('bag/order/lot-seed/preview') ?>';
|
||||
var overlay = document.getElementById('lot-preview-overlay');
|
||||
var elLoading = document.getElementById('lot-preview-loading');
|
||||
var elError = document.getElementById('lot-preview-error');
|
||||
var elBody = document.getElementById('lot-preview-body');
|
||||
var elSubmit = document.getElementById('lot-generate-submit');
|
||||
var elBoIdx = document.getElementById('lot-generate-bo-idx');
|
||||
var nf = function (n) { return new Intl.NumberFormat('ko-KR').format(n || 0); };
|
||||
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>]/g, function (c) { return ({ '&': '&', '<': '<', '>': '>' })[c]; }); };
|
||||
|
||||
function openModal() { overlay.classList.remove('hidden'); overlay.classList.add('flex'); }
|
||||
function closeModal() { overlay.classList.add('hidden'); overlay.classList.remove('flex'); }
|
||||
|
||||
function showState(state) {
|
||||
elLoading.classList.toggle('hidden', state !== 'loading');
|
||||
elError.classList.toggle('hidden', state !== 'error');
|
||||
elBody.classList.toggle('hidden', state !== 'body');
|
||||
elSubmit.disabled = state !== 'body';
|
||||
}
|
||||
|
||||
document.querySelectorAll('.lot-preview-btn').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
var boIdx = btn.getAttribute('data-bo-idx');
|
||||
elBoIdx.value = boIdx;
|
||||
openModal();
|
||||
showState('loading');
|
||||
fetch(previewUrl + '?bo_idx=' + encodeURIComponent(boIdx), { credentials: 'same-origin' })
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (d) {
|
||||
if (!d || !d.ok) {
|
||||
elError.textContent = (d && d.error) || '내용을 불러오지 못했습니다.';
|
||||
showState('error');
|
||||
return;
|
||||
}
|
||||
document.getElementById('lp-lot').textContent = d.lot_no || '';
|
||||
document.getElementById('lp-date').textContent = d.order_date || '';
|
||||
document.getElementById('lp-company').textContent = d.company || '-';
|
||||
document.getElementById('lp-version').textContent = 'v' + (d.version || 1);
|
||||
document.getElementById('lp-hash').textContent = d.order_hash || '';
|
||||
var rows = (d.items || []).map(function (it) {
|
||||
return '<tr>'
|
||||
+ '<td class="pl-2 font-mono">' + esc(it.bag_code) + '</td>'
|
||||
+ '<td>' + esc(it.bag_name) + '</td>'
|
||||
+ '<td class="text-right">' + nf(it.unit_price) + '</td>'
|
||||
+ '<td class="text-right">' + nf(it.qty_box) + '</td>'
|
||||
+ '<td class="text-right">' + nf(it.qty_pack) + '</td>'
|
||||
+ '<td class="text-right">' + nf(it.qty_sheet) + '</td>'
|
||||
+ '<td class="text-right pr-2">' + nf(it.amount) + '</td>'
|
||||
+ '</tr>';
|
||||
}).join('');
|
||||
document.getElementById('lp-items').innerHTML = rows || '<tr><td colspan="7" class="text-center text-gray-400 py-4">품목이 없습니다.</td></tr>';
|
||||
var t = d.totals || {};
|
||||
document.getElementById('lp-line-count').textContent = nf(t.line_count);
|
||||
document.getElementById('lp-sum-box').textContent = nf(t.qty_box);
|
||||
document.getElementById('lp-sum-sheet').textContent = nf(t.qty_sheet);
|
||||
document.getElementById('lp-sum-amount').textContent = nf(t.amount);
|
||||
showState('body');
|
||||
})
|
||||
.catch(function () {
|
||||
elError.textContent = '통신 오류가 발생했습니다.';
|
||||
showState('error');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('lot-preview-close').addEventListener('click', closeModal);
|
||||
document.getElementById('lot-preview-cancel').addEventListener('click', closeModal);
|
||||
overlay.addEventListener('click', function (e) { if (e.target === overlay) closeModal(); });
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user