P2-01/02 기본코드 종류 및 세부코드 관리 CRUD 구현

- CodeKindModel + CodeKind 컨트롤러 (목록/등록/수정/삭제)
- CodeDetailModel + CodeDetail 컨트롤러 (종류별 세부코드 CRUD)
- View: code_kind/(index,create,edit), code_detail/(index,create,edit)
- 라우트: /admin/code-kinds/*, /admin/code-details/*
- E2E 테스트 7개 전체 통과
- 스크린샷 2개 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
javamon1174
2026-03-25 16:20:56 +09:00
parent 34cecad2e2
commit 41442c23a1
15 changed files with 620 additions and 2 deletions

View File

@@ -0,0 +1,38 @@
<section class="border-b border-gray-300 p-2 shrink-0 bg-control-panel">
<div class="flex items-center gap-2">
<a href="<?= base_url('admin/code-details/' . (int) $kind->ck_idx) ?>" class="text-blue-600 hover:underline text-sm">&larr; <?= esc($kind->ck_name) ?></a>
<span class="text-gray-400">|</span>
<span class="text-sm font-bold text-gray-700">세부코드 등록</span>
</div>
</section>
<div class="border border-gray-300 p-4 mt-2 bg-white max-w-3xl">
<form action="<?= base_url('admin/code-details/store') ?>" method="POST" class="space-y-4">
<?= csrf_field() ?>
<input type="hidden" name="cd_ck_idx" value="<?= (int) $kind->ck_idx ?>"/>
<div class="flex flex-wrap items-center gap-2">
<label class="block text-sm font-bold text-gray-700 w-28">코드 종류</label>
<span class="text-sm"><?= esc($kind->ck_name) ?> (<?= esc($kind->ck_code) ?>)</span>
</div>
<div class="flex flex-wrap items-center gap-2">
<label class="block text-sm font-bold text-gray-700 w-28">세부코드 <span class="text-red-500">*</span></label>
<input class="border border-gray-300 rounded px-3 py-1.5 text-sm w-32 font-mono" name="cd_code" type="text" value="<?= esc(old('cd_code')) ?>" maxlength="50" required placeholder="예: 10"/>
</div>
<div class="flex flex-wrap items-center gap-2">
<label class="block text-sm font-bold text-gray-700 w-28">코드명 <span class="text-red-500">*</span></label>
<input class="border border-gray-300 rounded px-3 py-1.5 text-sm w-72" name="cd_name" type="text" value="<?= esc(old('cd_name')) ?>" maxlength="100" required placeholder="코드 이름"/>
</div>
<div class="flex flex-wrap items-center gap-2">
<label class="block text-sm font-bold text-gray-700 w-28">정렬순서</label>
<input class="border border-gray-300 rounded px-3 py-1.5 text-sm w-24" name="cd_sort" type="number" value="<?= esc(old('cd_sort', '0')) ?>" min="0"/>
</div>
<div class="flex gap-2 pt-2">
<button type="submit" class="bg-btn-search text-white px-6 py-1.5 rounded-sm text-sm shadow hover:opacity-90 transition">등록</button>
<a href="<?= base_url('admin/code-details/' . (int) $kind->ck_idx) ?>" class="bg-gray-200 text-gray-700 px-6 py-1.5 rounded-sm text-sm hover:bg-gray-300 transition">취소</a>
</div>
</form>
</div>

View File

@@ -0,0 +1,45 @@
<section class="border-b border-gray-300 p-2 shrink-0 bg-control-panel">
<div class="flex items-center gap-2">
<a href="<?= base_url('admin/code-details/' . (int) $kind->ck_idx) ?>" class="text-blue-600 hover:underline text-sm">&larr; <?= esc($kind->ck_name) ?></a>
<span class="text-gray-400">|</span>
<span class="text-sm font-bold text-gray-700">세부코드 수정</span>
</div>
</section>
<div class="border border-gray-300 p-4 mt-2 bg-white max-w-3xl">
<form action="<?= base_url('admin/code-details/update/' . (int) $item->cd_idx) ?>" method="POST" class="space-y-4">
<?= csrf_field() ?>
<div class="flex flex-wrap items-center gap-2">
<label class="block text-sm font-bold text-gray-700 w-28">코드 종류</label>
<span class="text-sm"><?= esc($kind->ck_name) ?> (<?= esc($kind->ck_code) ?>)</span>
</div>
<div class="flex flex-wrap items-center gap-2">
<label class="block text-sm font-bold text-gray-700 w-28">세부코드</label>
<span class="text-sm font-mono"><?= esc($item->cd_code) ?></span>
</div>
<div class="flex flex-wrap items-center gap-2">
<label class="block text-sm font-bold text-gray-700 w-28">코드명 <span class="text-red-500">*</span></label>
<input class="border border-gray-300 rounded px-3 py-1.5 text-sm w-72" name="cd_name" type="text" value="<?= esc(old('cd_name', $item->cd_name)) ?>" maxlength="100" required/>
</div>
<div class="flex flex-wrap items-center gap-2">
<label class="block text-sm font-bold text-gray-700 w-28">정렬순서</label>
<input class="border border-gray-300 rounded px-3 py-1.5 text-sm w-24" name="cd_sort" type="number" value="<?= esc(old('cd_sort', $item->cd_sort)) ?>" min="0"/>
</div>
<div class="flex flex-wrap items-center gap-2">
<label class="block text-sm font-bold text-gray-700 w-28">상태 <span class="text-red-500">*</span></label>
<select class="border border-gray-300 rounded px-3 py-1.5 text-sm w-32" name="cd_state" required>
<option value="1" <?= (int) old('cd_state', $item->cd_state) === 1 ? 'selected' : '' ?>>사용</option>
<option value="0" <?= (int) old('cd_state', $item->cd_state) === 0 ? 'selected' : '' ?>>미사용</option>
</select>
</div>
<div class="flex gap-2 pt-2">
<button type="submit" class="bg-btn-search text-white px-6 py-1.5 rounded-sm text-sm shadow hover:opacity-90 transition">수정</button>
<a href="<?= base_url('admin/code-details/' . (int) $kind->ck_idx) ?>" class="bg-gray-200 text-gray-700 px-6 py-1.5 rounded-sm text-sm hover:bg-gray-300 transition">취소</a>
</div>
</form>
</div>

View File

@@ -0,0 +1,44 @@
<section class="border-b border-gray-300 p-2 shrink-0 bg-control-panel">
<div class="flex flex-wrap items-center justify-between gap-y-2">
<div class="flex items-center gap-2">
<a href="<?= base_url('admin/code-kinds') ?>" class="text-blue-600 hover:underline text-sm">&larr; 코드 종류</a>
<span class="text-gray-400">|</span>
<span class="text-sm font-bold text-gray-700">세부코드 <?= esc($kind->ck_name) ?> (<?= esc($kind->ck_code) ?>)</span>
</div>
<a href="<?= base_url('admin/code-details/' . (int) $kind->ck_idx . '/create') ?>" class="bg-btn-search text-white px-4 py-1.5 rounded-sm flex items-center gap-1 text-sm shadow hover:opacity-90 transition border border-transparent">세부코드 등록</a>
</div>
</section>
<div class="border border-gray-300 overflow-auto mt-2">
<table class="w-full data-table">
<thead>
<tr>
<th class="w-16">번호</th>
<th class="w-24">코드</th>
<th>코드명</th>
<th class="w-20">정렬순서</th>
<th class="w-20">상태</th>
<th>등록일</th>
<th class="w-28">작업</th>
</tr>
</thead>
<tbody class="text-right">
<?php foreach ($list as $row): ?>
<tr>
<td class="text-center"><?= esc($row->cd_idx) ?></td>
<td class="text-center font-mono"><?= esc($row->cd_code) ?></td>
<td class="text-left pl-2"><?= esc($row->cd_name) ?></td>
<td class="text-center"><?= (int) $row->cd_sort ?></td>
<td class="text-center"><?= (int) $row->cd_state === 1 ? '사용' : '미사용' ?></td>
<td class="text-left pl-2"><?= esc($row->cd_regdate ?? '') ?></td>
<td class="text-center">
<a href="<?= base_url('admin/code-details/edit/' . (int) $row->cd_idx) ?>" class="text-blue-600 hover:underline text-sm">수정</a>
<form action="<?= base_url('admin/code-details/delete/' . (int) $row->cd_idx) ?>" method="POST" class="inline ml-1" onsubmit="return confirm('이 세부코드를 삭제하시겠습니까?');">
<?= csrf_field() ?>
<button type="submit" class="text-red-600 hover:underline text-sm">삭제</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>