feat: 발주 등록/변경/삭제 화면 개선 + 발주담당 추가

- 발주 등록: 폼(좌)·발주품목 선택(우, 스크롤)·발주 이력(하단) 재배치, 수량→박스수량
- 발주담당(담당자) 선택 항목 추가(bo_manager_idx), 등록/변경 시 저장
- 발주 이력 발주일 클릭 → 발주 내역 보기 모달(변경/삭제 버튼), 삭제·취소 발주는 두 버튼 숨김
- 발주 변경: 변경구분 라디오 제거, 원 발주번호(LOT)·이력 안내 표시, 취소 시 발주 등록 화면으로 이동
- 발주 등록 화면에서도 삭제 가능(정상 발주만), 삭제 후 등록 화면 복귀
- 삭제 화면에서 삭제 대상 발주 내역 표시
- 발주 상세 JSON 엔드포인트(bag/order/detail-json) 추가

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
taekyoungc
2026-07-06 18:39:32 +09:00
parent 952ca3e3e7
commit 26384dbe2a
6 changed files with 297 additions and 64 deletions

View File

@@ -539,6 +539,11 @@ class BagOrder extends BaseController
'bo_regdate' => date('Y-m-d H:i:s'),
];
// 발주담당(manager.mg_idx) — 컬럼이 있을 때만 저장
if (\Config\Database::connect()->fieldExists('bo_manager_idx', 'bag_order')) {
$orderData['bo_manager_idx'] = $this->request->getPost('bo_manager_idx') ?: null;
}
// 품목 입력 후 최종 payload 기준으로 해시를 계산하므로 우선 빈값으로 생성
$orderData['bo_hash'] = '';

View File

@@ -3873,6 +3873,66 @@ SQL);
return redirect()->to(site_url('bag/issue/cancel'))->with('success', session()->getFlashdata('success') ?? '취소되었습니다.');
}
/**
* [AJAX] 발주 1건의 내역(헤더+품목)을 JSON으로 반환 — 발주 이력 "보기" 모달·삭제 화면 상세용.
*/
public function orderDetailJson(int $id)
{
helper('admin');
$lgIdx = $this->lgIdx();
if (! $lgIdx) {
return $this->response->setStatusCode(403)->setJSON(['ok' => false, 'error' => '지자체가 선택되지 않았습니다.']);
}
$order = model(BagOrderModel::class)->find($id);
if ($order === null || (int) $order->bo_lg_idx !== (int) $lgIdx) {
return $this->response->setStatusCode(404)->setJSON(['ok' => false, 'error' => '발주를 찾을 수 없습니다.']);
}
$companyName = '';
if ($order->bo_company_idx) {
$c = model(CompanyModel::class)->find($order->bo_company_idx);
$companyName = $c ? (string) $c->cp_name : '';
}
$agencyName = '';
if ($order->bo_agency_idx) {
$a = model(SalesAgencyModel::class)->find($order->bo_agency_idx);
if ($a) {
$agencyName = '[' . ($a->sa_kind ?? '') . '] ' . ($a->sa_code ?? '') . ' — ' . ($a->sa_name ?? '');
}
}
$managerName = '';
if (\Config\Database::connect()->fieldExists('bo_manager_idx', 'bag_order') && ($order->bo_manager_idx ?? null)) {
$mg = model(ManagerModel::class)->find($order->bo_manager_idx);
$managerName = $mg ? (string) $mg->mg_name : '';
}
$items = [];
foreach (model(BagOrderItemModel::class)->where('boi_bo_idx', $id)->orderBy('boi_idx', 'ASC')->findAll() as $it) {
$items[] = [
'bag_code' => (string) ($it->boi_bag_code ?? ''),
'bag_name' => (string) ($it->boi_bag_name ?? ''),
'unit_price' => (float) ($it->boi_unit_price ?? 0),
'qty_box' => (int) ($it->boi_qty_box ?? 0),
'qty_sheet' => (int) ($it->boi_qty_sheet ?? 0),
'amount' => (float) ($it->boi_amount ?? 0),
];
}
return $this->response->setJSON([
'ok' => true,
'bo_idx' => (int) $order->bo_idx,
'bo_lot_no' => (string) ($order->bo_lot_no ?? ''),
'bo_version' => (int) ($order->bo_version ?? 1),
'order_date' => (string) ($order->bo_order_date ?? ''),
'fee_rate' => (float) ($order->bo_fee_rate ?? 0),
'status' => (string) ($order->bo_status ?? ''),
'company' => $companyName,
'agency' => $agencyName,
'manager' => $managerName,
'items' => $items,
]);
}
// --- 발주 등록 ---
public function orderCreate(): string
{
@@ -3885,6 +3945,7 @@ SQL);
? model(CompanyModel::class)->where('cp_lg_idx', $lgIdx)->where('cp_type', '협회')->where('cp_state', 1)->findAll()
: [];
$agencies = $lgIdx ? model(SalesAgencyModel::class)->where('sa_lg_idx', $lgIdx)->orderForDisplay()->findAll() : [];
$managers = $lgIdx ? model(ManagerModel::class)->where('mg_lg_idx', $lgIdx)->where('mg_state', 1)->orderBy('mg_name', 'ASC')->findAll() : [];
$kind = model(CodeKindModel::class)->where('ck_code', 'O')->first();
$bagCodes = $kind ? model(CodeDetailModel::class)->getByKind((int) $kind->ck_idx, true, $lgIdx) : [];
$priceMapRows = $lgIdx ? model(BagPriceModel::class)->latestActiveMapByBagCode($lgIdx) : [];
@@ -3941,6 +4002,7 @@ SQL);
'companies',
'associations',
'agencies',
'managers',
'bagCodes',
'recentOrders',
'companyMap',
@@ -4402,6 +4464,7 @@ SQL);
? model(CompanyModel::class)->where('cp_lg_idx', $lgIdx)->where('cp_type', '협회')->where('cp_state', 1)->findAll()
: [];
$agencies = $lgIdx ? model(SalesAgencyModel::class)->where('sa_lg_idx', $lgIdx)->orderForDisplay()->findAll() : [];
$managers = $lgIdx ? model(ManagerModel::class)->where('mg_lg_idx', $lgIdx)->where('mg_state', 1)->orderBy('mg_name', 'ASC')->findAll() : [];
$kind = model(CodeKindModel::class)->where('ck_code', 'O')->first();
$bagCodes = $kind ? model(CodeDetailModel::class)->getByKind((int) $kind->ck_idx, true, $lgIdx) : [];
$priceMapRows = $lgIdx ? model(BagPriceModel::class)->latestActiveMapByBagCode($lgIdx) : [];
@@ -4492,6 +4555,7 @@ SQL);
'bo_association_idx' => (string) ($target->bo_association_idx ?? ''),
'bo_company_idx' => (string) ($target->bo_company_idx ?? ''),
'bo_agency_idx' => (string) ($target->bo_agency_idx ?? ''),
'bo_manager_idx' => (string) ($target->bo_manager_idx ?? ''),
'item_bag_code' => $itemCodes,
'item_qty_box' => $itemQtyBoxes,
'item_qty_sheet' => $itemQtySheets,
@@ -4504,6 +4568,7 @@ SQL);
'companies',
'associations',
'agencies',
'managers',
'bagCodes',
'recentOrders',
'companyMap',
@@ -4589,16 +4654,22 @@ SQL);
}
$month = substr((string) ($order->bo_order_date ?? date('Y-m-d')), 0, 7);
// 삭제 후 돌아갈 화면: 발주 등록에서 삭제한 경우 등록 화면으로 복귀
$returnTo = (string) ($this->request->getPost('return_to') ?? '');
$redirectUrl = $returnTo === 'create'
? site_url('bag/order/create')
: site_url('bag/order/change?month=' . $month);
$admin = new \App\Controllers\Admin\BagOrder();
$admin->initController($this->request, $this->response, service('logger'));
$response = $admin->delete($id);
if ($response instanceof RedirectResponse) {
$msg = session()->getFlashdata('success') ?? '발주가 삭제 처리되었습니다.';
return redirect()->to(site_url('bag/order/change?month=' . $month))->with('success', $msg);
return redirect()->to($redirectUrl)->with('success', $msg);
}
return redirect()->to(site_url('bag/order/change?month=' . $month))->with('success', '처리되었습니다.');
return redirect()->to($redirectUrl)->with('success', '처리되었습니다.');
}
public function orderCancel(int $id)