CT-01: 페이지네이션 - 커스텀 Tailwind 페이저 뷰 (components/pager.php) - 18개 admin 컨트롤러 findAll() → paginate(20) 전환 - Bag 컨트롤러 7개 리스트도 paginate 적용 - 19개 admin index 뷰에 페이저 링크 추가 CT-02: 엑셀 저장 - export_helper.php (UTF-8 BOM CSV) - 발주/판매/지정판매소/재고 4개 엑셀 내보내기 라우트+메서드 - 해당 뷰에 "엑셀저장" 버튼 추가 CT-03: 인쇄 - print_header.php (지자체명/제목/결재란 컴포넌트) - admin/bag 레이아웃에 @media print CSS 추가 - 23개 뷰에 인쇄 버튼 + print_header 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
214 lines
8.0 KiB
PHP
214 lines
8.0 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers\Admin;
|
|
|
|
use App\Controllers\BaseController;
|
|
use App\Models\MemberApprovalRequestModel;
|
|
use App\Models\MemberModel;
|
|
use Config\Roles;
|
|
|
|
class User extends BaseController
|
|
{
|
|
private MemberModel $memberModel;
|
|
private MemberApprovalRequestModel $approvalModel;
|
|
private Roles $roles;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->memberModel = model(MemberModel::class);
|
|
$this->approvalModel = model(MemberApprovalRequestModel::class);
|
|
$this->roles = config('Roles');
|
|
helper('pii_encryption');
|
|
}
|
|
|
|
/**
|
|
* 회원 목록
|
|
*/
|
|
public function index(): string
|
|
{
|
|
$list = $this->memberModel->orderBy('mb_idx', 'DESC')->paginate(20);
|
|
$pager = $this->memberModel->pager;
|
|
$approvalMap = [];
|
|
try {
|
|
$memberIds = array_map(static fn ($row) => (int) $row->mb_idx, $list);
|
|
if (! empty($memberIds)) {
|
|
$approvalRows = $this->approvalModel
|
|
->whereIn('mb_idx', $memberIds)
|
|
->orderBy('mar_idx', 'DESC')
|
|
->findAll();
|
|
foreach ($approvalRows as $approvalRow) {
|
|
$mbIdx = (int) $approvalRow->mb_idx;
|
|
if (! isset($approvalMap[$mbIdx])) {
|
|
$approvalMap[$mbIdx] = (string) $approvalRow->mar_status;
|
|
}
|
|
}
|
|
}
|
|
} catch (\Throwable $e) {
|
|
// 승인요청 테이블 미생성 등 예외 시 기존 상태 표시로 폴백
|
|
}
|
|
|
|
foreach ($list as $row) {
|
|
$row->mb_email = pii_decrypt($row->mb_email ?? '');
|
|
$row->mb_phone = pii_decrypt($row->mb_phone ?? '');
|
|
}
|
|
return view('admin/layout', [
|
|
'title' => '회원 관리',
|
|
'content' => view('admin/user/index', [
|
|
'list' => $list,
|
|
'roles' => $this->roles,
|
|
'approvalMap' => $approvalMap,
|
|
'pager' => $pager,
|
|
]),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 회원 등록 폼
|
|
*/
|
|
public function create(): string
|
|
{
|
|
return view('admin/layout', [
|
|
'title' => '회원 등록',
|
|
'content' => view('admin/user/create', [
|
|
'roles' => $this->roles,
|
|
'assignableLevels' => $this->getAssignableLevels(),
|
|
]),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 회원 등록 처리
|
|
*/
|
|
public function store()
|
|
{
|
|
$rules = [
|
|
'mb_id' => 'required|min_length[2]|max_length[50]|is_unique[member.mb_id]',
|
|
'mb_passwd' => 'required|min_length[4]|max_length[255]',
|
|
'mb_name' => 'required|max_length[50]',
|
|
'mb_email' => 'permit_empty|valid_email|max_length[100]',
|
|
'mb_phone' => 'permit_empty|max_length[20]',
|
|
'mb_level' => 'required',
|
|
];
|
|
if (! $this->validate($rules)) {
|
|
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
|
|
}
|
|
$allowedLevels = array_keys($this->getAssignableLevels());
|
|
$requestedLevel = (int) $this->request->getPost('mb_level');
|
|
if (! in_array($requestedLevel, $allowedLevels, true)) {
|
|
return redirect()->back()->withInput()->with('error', '현재 권한으로는 해당 역할을 등록할 수 없습니다.');
|
|
}
|
|
$data = [
|
|
'mb_id' => $this->request->getPost('mb_id'),
|
|
'mb_passwd' => password_hash((string) $this->request->getPost('mb_passwd'), PASSWORD_DEFAULT),
|
|
'mb_name' => $this->request->getPost('mb_name'),
|
|
'mb_email' => pii_encrypt($this->request->getPost('mb_email')),
|
|
'mb_phone' => pii_encrypt($this->request->getPost('mb_phone')),
|
|
'mb_level' => $requestedLevel,
|
|
'mb_state' => 1,
|
|
'mb_regdate' => date('Y-m-d H:i:s'),
|
|
'mb_latestdate' => null,
|
|
];
|
|
$this->memberModel->insert($data);
|
|
return redirect()->to(site_url('admin/users'))->with('success', '회원이 등록되었습니다.');
|
|
}
|
|
|
|
/**
|
|
* 회원 수정 폼
|
|
*/
|
|
public function edit(int $id): string
|
|
{
|
|
$member = $this->memberModel->find($id);
|
|
if (! $member) {
|
|
return redirect()->to(site_url('admin/users'))->with('error', '회원을 찾을 수 없습니다.');
|
|
}
|
|
$member->mb_email = pii_decrypt($member->mb_email ?? '');
|
|
$member->mb_phone = pii_decrypt($member->mb_phone ?? '');
|
|
return view('admin/layout', [
|
|
'title' => '회원 수정',
|
|
'content' => view('admin/user/edit', [
|
|
'member' => $member,
|
|
'roles' => $this->roles,
|
|
'assignableLevels' => $this->getAssignableLevels(),
|
|
]),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 회원 수정 처리
|
|
*/
|
|
public function update(int $id)
|
|
{
|
|
$member = $this->memberModel->find($id);
|
|
if (! $member) {
|
|
return redirect()->to(site_url('admin/users'))->with('error', '회원을 찾을 수 없습니다.');
|
|
}
|
|
$rules = [
|
|
'mb_id' => "required|min_length[2]|max_length[50]|is_unique[member.mb_id,mb_idx,{$id}]",
|
|
'mb_name' => 'required|max_length[50]',
|
|
'mb_email' => 'permit_empty|valid_email|max_length[100]',
|
|
'mb_phone' => 'permit_empty|max_length[20]',
|
|
'mb_level' => 'required',
|
|
'mb_state' => 'required|in_list[0,1,2]',
|
|
];
|
|
$passwd = $this->request->getPost('mb_passwd');
|
|
if ($passwd !== '') {
|
|
$rules['mb_passwd'] = 'min_length[4]|max_length[255]';
|
|
}
|
|
if (! $this->validate($rules)) {
|
|
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
|
|
}
|
|
$allowedLevels = array_keys($this->getAssignableLevels());
|
|
$requestedLevel = (int) $this->request->getPost('mb_level');
|
|
if (! in_array($requestedLevel, $allowedLevels, true)) {
|
|
return redirect()->back()->withInput()->with('error', '현재 권한으로는 해당 역할로 수정할 수 없습니다.');
|
|
}
|
|
$data = [
|
|
'mb_id' => $this->request->getPost('mb_id'),
|
|
'mb_name' => $this->request->getPost('mb_name'),
|
|
'mb_email' => pii_encrypt($this->request->getPost('mb_email')),
|
|
'mb_phone' => pii_encrypt($this->request->getPost('mb_phone')),
|
|
'mb_level' => $requestedLevel,
|
|
'mb_state' => (int) $this->request->getPost('mb_state'),
|
|
];
|
|
if ($passwd !== '') {
|
|
$data['mb_passwd'] = password_hash($passwd, PASSWORD_DEFAULT);
|
|
}
|
|
$this->memberModel->update($id, $data);
|
|
return redirect()->to(site_url('admin/users'))->with('success', '회원 정보가 수정되었습니다.');
|
|
}
|
|
|
|
/**
|
|
* 현재 로그인한 관리자가 부여 가능한 역할 목록.
|
|
* super/본부만 4·5 부여 가능, 지자체 관리자는 1~3만.
|
|
*
|
|
* @return array<int,string>
|
|
*/
|
|
private function getAssignableLevels(): array
|
|
{
|
|
$levelNames = $this->roles->levelNames;
|
|
$myLevel = (int) session()->get('mb_level');
|
|
if (Roles::isSuperAdminEquivalent($myLevel)) {
|
|
return $levelNames;
|
|
}
|
|
unset($levelNames[Roles::LEVEL_SUPER_ADMIN], $levelNames[Roles::LEVEL_HEADQUARTERS_ADMIN]);
|
|
|
|
return $levelNames;
|
|
}
|
|
|
|
/**
|
|
* 회원 삭제(탈퇴 처리: mb_state=0, mb_leavedate 기록)
|
|
*/
|
|
public function delete(int $id)
|
|
{
|
|
$member = $this->memberModel->find($id);
|
|
if (! $member) {
|
|
return redirect()->to(site_url('admin/users'))->with('error', '회원을 찾을 수 없습니다.');
|
|
}
|
|
$this->memberModel->update($id, [
|
|
'mb_state' => 0,
|
|
'mb_leavedate' => date('Y-m-d H:i:s'),
|
|
]);
|
|
return redirect()->to(site_url('admin/users'))->with('success', '회원이 탈퇴 처리되었습니다.');
|
|
}
|
|
}
|