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:
taekyoungc
2026-07-06 18:26:58 +09:00
parent a5d995588b
commit de15cc9e47
9 changed files with 270 additions and 33 deletions

View File

@@ -47,7 +47,7 @@ class Manual extends BaseConfig
*/ */
public array $screenHelp = [ public array $screenHelp = [
'bag/order/phone' => 'sales#전화 주문 접수', 'bag/order/phone' => 'sales#전화 주문 접수',
'bag/order/lot-seed' => 'order#LOT-No 디스켓 불출', 'bag/order/lot-seed' => 'order#발주파일 생성',
'bag/order' => 'order#발주 등록', 'bag/order' => 'order#발주 등록',
'bag/password-change' => 'account#비밀번호 변경', 'bag/password-change' => 'account#비밀번호 변경',
'bag/bag-orders' => 'order#발주 현황', 'bag/bag-orders' => 'order#발주 현황',

View File

@@ -83,6 +83,7 @@ $routes->get('bag/order/phone/receipt/(:num)', 'Bag::phoneOrderReceipt/$1');
$routes->get('bag/order/change', 'Bag::orderChange'); $routes->get('bag/order/change', 'Bag::orderChange');
$routes->get('bag/order/revise/(:num)', 'Bag::orderRevise/$1'); $routes->get('bag/order/revise/(:num)', 'Bag::orderRevise/$1');
$routes->get('bag/order/lot-seed', 'Bag::orderLotSeed'); $routes->get('bag/order/lot-seed', 'Bag::orderLotSeed');
$routes->get('bag/order/lot-seed/preview', 'Bag::orderLotSeedPreview');
$routes->post('bag/order/lot-seed/generate', 'Bag::orderLotSeedGenerate'); $routes->post('bag/order/lot-seed/generate', 'Bag::orderLotSeedGenerate');
$routes->post('bag/order/store', 'Bag::orderStore'); $routes->post('bag/order/store', 'Bag::orderStore');
$routes->post('bag/order/cancel/(:num)', 'Bag::orderCancel/$1'); $routes->post('bag/order/cancel/(:num)', 'Bag::orderCancel/$1');

View File

@@ -3953,7 +3953,7 @@ SQL);
} }
/** /**
* LOT-No 디스켓 불출: 발주 건을 선택해 암호화 seed 파일 생성/다운로드. * 발주파일 생성(구 'LOT-No 디스켓 불출'): 발주 건을 선택해 암호화 seed 파일 생성/다운로드.
*/ */
public function orderLotSeed(): string|RedirectResponse public function orderLotSeed(): string|RedirectResponse
{ {
@@ -4031,7 +4031,7 @@ SQL);
} }
} }
return $this->render('LOT-No 디스켓 불출', 'bag/order_lot_seed', [ return $this->render('발주파일 생성', 'bag/order_lot_seed', [
'orders' => $orders, 'orders' => $orders,
'pager' => $pager, 'pager' => $pager,
'startMonth' => $startMonth, 'startMonth' => $startMonth,
@@ -4044,17 +4044,16 @@ SQL);
]); ]);
} }
public function orderLotSeedGenerate(): RedirectResponse|ResponseInterface /**
* 발주파일(seed) 생성·미리보기가 공용으로 쓰는 데이터 구성.
* 발주 메타(order_data)와 품목(items, 팩/박스 환산 포함), 무결성 해시를 만든다.
*
* @return array{ok: bool, error?: string, order?: object, order_data?: array<string,mixed>, items?: array<int,array<string,mixed>>, lot_no?: string, uuid?: string, version?: int, order_hash?: string}
*/
private function buildLotSeedData(int $lgIdx, int $boIdx): array
{ {
helper('admin');
$lgIdx = $this->lgIdx();
if (! $lgIdx) {
return redirect()->to(site_url('bag/purchase-inbound'))->with('error', '지자체를 선택해 주세요.');
}
$boIdx = (int) ($this->request->getPost('bo_idx') ?? 0);
if ($boIdx <= 0) { if ($boIdx <= 0) {
return redirect()->back()->with('error', '발주 건을 선택해 주세요.'); return ['ok' => false, 'error' => '발주 건을 선택해 주세요.'];
} }
$order = model(BagOrderModel::class) $order = model(BagOrderModel::class)
@@ -4062,14 +4061,14 @@ SQL);
->where('bo_idx', $boIdx) ->where('bo_idx', $boIdx)
->first(); ->first();
if (! $order) { if (! $order) {
return redirect()->back()->with('error', '발주 정보를 찾을 수 없습니다.'); return ['ok' => false, 'error' => '발주 정보를 찾을 수 없습니다.'];
} }
$lotNo = trim((string) ($order->bo_lot_no ?? '')); $lotNo = trim((string) ($order->bo_lot_no ?? ''));
$uuid = trim((string) ($order->bo_uuid ?? '')); $uuid = trim((string) ($order->bo_uuid ?? ''));
$version = max(1, (int) ($order->bo_version ?? 1)); $version = max(1, (int) ($order->bo_version ?? 1));
if ($lotNo === '' || $uuid === '') { if ($lotNo === '' || $uuid === '') {
return redirect()->back()->with('error', '발주의 LOT/UUID 정보가 없어 seed 파일을 생성할 수 없습니다.'); return ['ok' => false, 'error' => '발주의 LOT/UUID 정보가 없어 발주파일을 생성할 수 없습니다.'];
} }
$items = model(BagOrderItemModel::class) $items = model(BagOrderItemModel::class)
@@ -4077,7 +4076,7 @@ SQL);
->orderBy('boi_idx', 'ASC') ->orderBy('boi_idx', 'ASC')
->findAll(); ->findAll();
if ($items === []) { if ($items === []) {
return redirect()->back()->with('error', '발주 품목이 없어 seed 파일을 생성할 수 없습니다.'); return ['ok' => false, 'error' => '발주 품목이 없어 발주파일을 생성할 수 없습니다.'];
} }
$unitRows = model(PackagingUnitModel::class) $unitRows = model(PackagingUnitModel::class)
@@ -4142,10 +4141,100 @@ SQL);
$orderHash = hash('sha256', $payloadJson); $orderHash = hash('sha256', $payloadJson);
} }
$seedPath = $this->generateLotSeedFile($uuid, $version, $lotNo, $orderData, $hashItems, $orderHash); return [
'ok' => true,
'order' => $order,
'order_data' => $orderData,
'items' => $hashItems,
'lot_no' => $lotNo,
'uuid' => $uuid,
'version' => $version,
'order_hash' => $orderHash,
];
}
/**
* 발주파일 생성 전 '내용 확인'(미리보기): 암호화 전 평문 내용을 JSON 으로 반환.
*/
public function orderLotSeedPreview(): ResponseInterface
{
helper('admin');
$lgIdx = $this->lgIdx();
if (! $lgIdx) {
return $this->response->setJSON(['ok' => false, 'error' => '지자체를 선택해 주세요.']);
}
$boIdx = (int) ($this->request->getGet('bo_idx') ?? 0);
$data = $this->buildLotSeedData($lgIdx, $boIdx);
if (! ($data['ok'] ?? false)) {
return $this->response->setJSON(['ok' => false, 'error' => (string) ($data['error'] ?? '내용을 확인할 수 없습니다.')]);
}
$order = $data['order'];
$companyIdx = (int) ($order->bo_company_idx ?? 0);
$companyName = '';
if ($companyIdx > 0) {
$company = model(CompanyModel::class)
->where('cp_lg_idx', $lgIdx)
->where('cp_idx', $companyIdx)
->first();
$companyName = (string) ($company->cp_name ?? '');
}
$items = array_map(static fn (array $it): array => [
'bag_code' => (string) $it['boi_bag_code'],
'bag_name' => (string) $it['boi_bag_name'],
'unit_price' => (float) $it['boi_unit_price'],
'qty_box' => (int) $it['boi_qty_box'],
'qty_pack' => (int) $it['boi_qty_pack'],
'qty_sheet' => (int) $it['boi_qty_sheet'],
'amount' => (float) $it['boi_amount'],
], $data['items']);
return $this->response->setJSON([
'ok' => true,
'bo_idx' => $boIdx,
'lot_no' => $data['lot_no'],
'uuid' => $data['uuid'],
'version' => $data['version'],
'order_date' => (string) ($order->bo_order_date ?? ''),
'company' => $companyName,
'order_hash' => $data['order_hash'],
'items' => $items,
'totals' => [
'line_count' => count($items),
'qty_box' => array_sum(array_map(static fn ($i) => (int) $i['qty_box'], $items)),
'qty_sheet' => array_sum(array_map(static fn ($i) => (int) $i['qty_sheet'], $items)),
'amount' => array_sum(array_map(static fn ($i) => (float) $i['amount'], $items)),
],
]);
}
public function orderLotSeedGenerate(): RedirectResponse|ResponseInterface
{
helper('admin');
$lgIdx = $this->lgIdx();
if (! $lgIdx) {
return redirect()->to(site_url('bag/purchase-inbound'))->with('error', '지자체를 선택해 주세요.');
}
$boIdx = (int) ($this->request->getPost('bo_idx') ?? 0);
$data = $this->buildLotSeedData($lgIdx, $boIdx);
if (! ($data['ok'] ?? false)) {
return redirect()->back()->with('error', (string) ($data['error'] ?? '발주파일을 생성할 수 없습니다.'));
}
$seedPath = $this->generateLotSeedFile(
$data['uuid'],
$data['version'],
$data['lot_no'],
$data['order_data'],
$data['items'],
$data['order_hash']
);
$seedBinary = @file_get_contents($seedPath); $seedBinary = @file_get_contents($seedPath);
if (! is_string($seedBinary) || $seedBinary === '') { if (! is_string($seedBinary) || $seedBinary === '') {
return redirect()->back()->with('error', 'seed 파일 생성에는 성공했으나 파일을 읽을 수 없습니다.'); return redirect()->back()->with('error', '발주파일 생성에는 성공했으나 파일을 읽을 수 없습니다.');
} }
return $this->response return $this->response

View File

@@ -67,14 +67,17 @@
--- ---
## LOT-No 디스켓 불출 · *발주 입고 관리 LOT-No 디스켓 불출* ## 발주파일 생성 · *발주 입고 관리 발주파일 생성*
발주별 **LOT 번호 시드(seed) 데이터를 파일로 생성**하는 화면입니다. (바코드·LOT 부여에 쓰는 디스켓/파일 형태 데이터) 선택한 발주 건의 내용을 **봉투 생산기(바코드 인쇄) 전달용 파일**로 만드는 화면입니다. (예전 이름: *LOT-No 디스켓 불출*) 생성되는 파일은 발주 정보와 품목이 담긴 **암호화된 발주파일**(`.seed.json`)이며, 봉투 생산 장비가 이 파일을 읽어 그 발주의 바코드를 인쇄합니다.
**LOT-No란?** 발주를 등록할 때 그 건에 자동 부여되는 **6자리 배치(묶음) 번호**입니다. 이후 그 발주로 인쇄되는 모든 봉투 바코드의 앞자리(예: `ZLCH2M-000006-…`)가 되어, 어느 발주에서 나온 봉투인지 구분하는 기준이 됩니다.
**필터**: 시작월 · 종료월 · LOT-No · 제작업체. **필터**: 시작월 · 종료월 · LOT-No · 제작업체.
**순서** **순서**
1. 기간·조건으로 발주 목록을 조회합니다. 1. 기간·조건으로 발주 목록을 조회합니다.
2. 해당 발주 행의 **`seed 생성`** 을 눌러 그 발주의 LOT 시드 파일을 만듭니다. 2. 대상 발주 행의 **`내용 확인`** 을 누르면, 파일에 담길 **발주 정보와 품목 목록(봉투코드·수량·금액 등)** 을 팝업으로 미리 볼 수 있습니다.
3. 내용을 확인한 뒤 **`발주파일 생성(다운로드)`** 을 누르면 암호화된 발주파일이 내려받아집니다.
**표 컬럼**: 발주일자 · LOT-No · 품명 · 수량 · 제작업체 · (생성 버튼). **표 컬럼**: 발주일자 · LOT-No · 품명 · 수량 · 제작업체 · (내용 확인 버튼).
> 정상·취소 발주가 함께 조회되며, 시드 생성은 발주 단위로 동작합니다. > 정상·취소 발주가 함께 조회되며, 파일 생성은 발주 단위로 동작합니다. 생성 전 **`내용 확인`** 단계에서 반드시 품목·수량을 검토하세요.

View File

@@ -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"> <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>
<section class="border border-gray-300 rounded-lg p-2 mt-2 bg-white"> <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> <tr>
<td class="text-center"> <td class="text-center">
<form method="post" action="<?= base_url('bag/order/lot-seed/generate') ?>" class="inline"> <button type="button"
<?= csrf_field() ?> class="lot-preview-btn text-blue-600 hover:underline text-xs"
<input type="hidden" name="bo_idx" value="<?= $boIdx ?>" /> data-bo-idx="<?= $boIdx ?>"
<button type="submit" class="text-blue-600 hover:underline text-xs">seed 생성</button> data-lot="<?= esc((string) ($order->bo_lot_no ?? ''), 'attr') ?>">
</form> 내용 확인
</button>
</td> </td>
<td class="text-center"><?= esc((string) ($order->bo_order_date ?? '')) ?></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> <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)): ?> <?php if (isset($pager)): ?>
<div class="mt-2 mb-2 no-print"><?= $pager->links() ?></div> <div class="mt-2 mb-2 no-print"><?= $pager->links() ?></div>
<?php endif; ?> <?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">&times;</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 ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' })[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>

View File

@@ -1,4 +1,4 @@
-- LOT-No 디스켓 불출 소메뉴 링크 보정 -- 발주파일 생성(구 LOT-No 디스켓 불출) 소메뉴 링크 보정
-- 실행: -- 실행:
-- mysql --default-character-set=utf8mb4 -u ... -p DBNAME < writable/database/menu_link_lot_seed_issue.sql -- mysql --default-character-set=utf8mb4 -u ... -p DBNAME < writable/database/menu_link_lot_seed_issue.sql
@@ -8,4 +8,4 @@ SET CHARACTER_SET_CLIENT = utf8mb4;
UPDATE `menu` m UPDATE `menu` m
INNER JOIN `menu_type` t ON t.mt_idx = m.mt_idx AND t.mt_code = 'site' INNER JOIN `menu_type` t ON t.mt_idx = m.mt_idx AND t.mt_code = 'site'
SET m.mm_link = 'bag/order/lot-seed' SET m.mm_link = 'bag/order/lot-seed'
WHERE m.mm_name = 'LOT-No 디스켓 불출'; WHERE m.mm_name IN ('발주파일 생성', 'LOT-No 디스켓 불출');

View File

@@ -27,7 +27,7 @@ SET m.mm_link = CASE m.mm_name
WHEN '지정 판매소 현황' THEN 'bag/designated-shops/district-new-cancel' WHEN '지정 판매소 현황' THEN 'bag/designated-shops/district-new-cancel'
WHEN '발주 등록' THEN 'bag/order/create' WHEN '발주 등록' THEN 'bag/order/create'
WHEN '발주 변경' THEN 'bag/order/change' WHEN '발주 변경' THEN 'bag/order/change'
WHEN 'LOT-No 디스켓 불출' THEN 'bag/order/lot-seed' WHEN '발주파일 생성' THEN 'bag/order/lot-seed'
WHEN '발주 현황' THEN 'bag/bag-orders' WHEN '발주 현황' THEN 'bag/bag-orders'
WHEN '발주 입고[스캐너]' THEN 'bag/receiving/create' WHEN '발주 입고[스캐너]' THEN 'bag/receiving/create'
WHEN '입고 현황' THEN 'bag/bag-receivings' WHEN '입고 현황' THEN 'bag/bag-receivings'

View File

@@ -83,7 +83,7 @@ SELECT @mt_site, 1, t.mm_name,
CASE t.mm_name CASE t.mm_name
WHEN '발주 등록' THEN 'bag/order/create' WHEN '발주 등록' THEN 'bag/order/create'
WHEN '발주 변경' THEN 'bag/order/change' WHEN '발주 변경' THEN 'bag/order/change'
WHEN 'LOT-No 디스켓 불출' THEN 'bag/order/lot-seed' WHEN '발주파일 생성' THEN 'bag/order/lot-seed'
WHEN '발주 현황' THEN 'bag/bag-orders' WHEN '발주 현황' THEN 'bag/bag-orders'
WHEN '발주 입고[스캐너]' THEN 'bag/receiving/create' WHEN '발주 입고[스캐너]' THEN 'bag/receiving/create'
WHEN '입고 현황' THEN 'bag/bag-receivings' WHEN '입고 현황' THEN 'bag/bag-receivings'
@@ -93,7 +93,7 @@ SELECT @mt_site, 1, t.mm_name,
FROM ( FROM (
SELECT 0 AS mm_num, '발주 등록' AS mm_name UNION ALL SELECT 0 AS mm_num, '발주 등록' AS mm_name UNION ALL
SELECT 1, '발주 변경' UNION ALL SELECT 1, '발주 변경' UNION ALL
SELECT 2, 'LOT-No 디스켓 불출' UNION ALL SELECT 2, '발주파일 생성' UNION ALL
SELECT 3, '발주 현황' UNION ALL SELECT 3, '발주 현황' UNION ALL
SELECT 4, '발주 입고[스캐너]' UNION ALL SELECT 4, '발주 입고[스캐너]' UNION ALL
SELECT 5, '일괄입고' UNION ALL SELECT 5, '일괄입고' UNION ALL

View File

@@ -0,0 +1,13 @@
-- 메뉴명 변경: 'LOT-No 디스켓 불출' → '발주파일 생성'
-- 링크(mm_link='bag/order/lot-seed') 기준으로, 기본 이름을 쓰는 항목만 안전하게 변경한다.
-- (지자체가 직접 다른 이름으로 바꿔 둔 항목은 건드리지 않음)
-- 실행:
-- mysql --default-character-set=utf8mb4 -u USER -p DBNAME < writable/database/rename_lot_seed_menu_to_order_file.sql
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
SET CHARACTER_SET_CLIENT = utf8mb4;
UPDATE `menu`
SET `mm_name` = '발주파일 생성'
WHERE `mm_link` = 'bag/order/lot-seed'
AND `mm_name` = 'LOT-No 디스켓 불출';