diff --git a/user-management/api/models/userModel.js b/user-management/api/models/userModel.js index 297e215..5c438bc 100644 --- a/user-management/api/models/userModel.js +++ b/user-management/api/models/userModel.js @@ -79,7 +79,7 @@ async function findById(userId) { async function findAll() { const db = getPool(); const [rows] = await db.query( - 'SELECT user_id, username, name, department, department_id, role, system1_access, system2_access, system3_access, is_active, last_login, created_at FROM sso_users WHERE partner_company_id IS NULL ORDER BY user_id' + 'SELECT user_id, username, name, department, department_id, role, system1_access, system2_access, system3_access, is_active, last_login, created_at, hire_date FROM sso_users WHERE partner_company_id IS NULL ORDER BY user_id' ); return rows; } @@ -108,6 +108,7 @@ async function update(userId, data) { if (data.system2_access !== undefined) { fields.push('system2_access = ?'); values.push(data.system2_access); } if (data.system3_access !== undefined) { fields.push('system3_access = ?'); values.push(data.system3_access); } if (data.is_active !== undefined) { fields.push('is_active = ?'); values.push(data.is_active); } + if (data.hire_date !== undefined) { fields.push('hire_date = ?'); values.push(data.hire_date || null); } if (data.password) { fields.push('password_hash = ?'); values.push(await hashPassword(data.password)); diff --git a/user-management/web/index.html b/user-management/web/index.html index 1ce3217..5a485ca 100644 --- a/user-management/web/index.html +++ b/user-management/web/index.html @@ -1043,6 +1043,10 @@ +
+ + +
@@ -1201,6 +1205,7 @@ +

타부서 임원 등도 선택 가능

@@ -2322,9 +2327,9 @@ - + - + diff --git a/user-management/web/static/js/tkuser-departments.js b/user-management/web/static/js/tkuser-departments.js index 8d56d33..9e00e2a 100644 --- a/user-management/web/static/js/tkuser-departments.js +++ b/user-management/web/static/js/tkuser-departments.js @@ -106,13 +106,30 @@ async function editDepartment(id) { if (!deptUsers || !deptUsers.length) { try { const r = await api('/users'); deptUsers = r.data || r; } catch(e) { /* ignore */ } } - const members = (deptUsers || []).filter(u => u.department_id === d.department_id && u.is_active !== 0 && u.is_active !== false); - members.forEach(u => { - const o = document.createElement('option'); - o.value = u.id; - o.textContent = u.name || u.username; - if (d.leader_user_id && d.leader_user_id === u.id) o.selected = true; - leaderSel.appendChild(o); + const activeUsers = (deptUsers || []).filter(u => u.is_active !== 0 && u.is_active !== false); + const byDept = {}; + activeUsers.forEach(u => { + const dName = deptLabel(u.department, u.department_id); + if (!byDept[dName]) byDept[dName] = []; + byDept[dName].push(u); + }); + const currentDeptName = d.department_name; + const sortedKeys = Object.keys(byDept).sort((a, b) => { + if (a === currentDeptName) return -1; + if (b === currentDeptName) return 1; + return a.localeCompare(b, 'ko'); + }); + sortedKeys.forEach(dName => { + const grp = document.createElement('optgroup'); + grp.label = dName; + byDept[dName].forEach(u => { + const o = document.createElement('option'); + o.value = u.user_id; + o.textContent = u.name || u.username; + if (d.leader_user_id && d.leader_user_id === u.user_id) o.selected = true; + grp.appendChild(o); + }); + leaderSel.appendChild(grp); }); document.getElementById('editDepartmentModal').classList.remove('hidden'); diff --git a/user-management/web/static/js/tkuser-users.js b/user-management/web/static/js/tkuser-users.js index 41d0668..7c12622 100644 --- a/user-management/web/static/js/tkuser-users.js +++ b/user-management/web/static/js/tkuser-users.js @@ -138,6 +138,7 @@ function displayUsers() { ${u.username} ${u.department||u.department_id?`${deptLabel(u.department, u.department_id)}`:''} ${u.role==='admin'?'관리자':'사용자'} + ${u.hire_date ? `입사 ${formatDate(u.hire_date)}` : '입사일 미등록'} ${u.is_active===0||u.is_active===false?'비활성':''}
@@ -165,6 +166,7 @@ function editUser(id) { populateUserDeptSelects(); document.getElementById('editDepartmentId').value=u.department_id||''; document.getElementById('editRole').value=u.role; + document.getElementById('editHireDate').value = formatDate(u.hire_date); document.getElementById('editUserModal').classList.remove('hidden'); } function closeEditModal() { document.getElementById('editUserModal').classList.add('hidden'); } @@ -173,7 +175,7 @@ document.getElementById('editUserForm').addEventListener('submit', async e => { e.preventDefault(); const deptIdVal = document.getElementById('editDepartmentId').value; try { - await api(`/users/${document.getElementById('editUserId').value}`, { method:'PUT', body: JSON.stringify({ name: document.getElementById('editFullName').value.trim()||null, department_id: deptIdVal ? parseInt(deptIdVal) : null, role: document.getElementById('editRole').value }) }); + await api(`/users/${document.getElementById('editUserId').value}`, { method:'PUT', body: JSON.stringify({ name: document.getElementById('editFullName').value.trim()||null, department_id: deptIdVal ? parseInt(deptIdVal) : null, role: document.getElementById('editRole').value, hire_date: document.getElementById('editHireDate').value || null }) }); showToast('수정되었습니다.'); closeEditModal(); await loadUsers(); } catch(e) { showToast(e.message,'error'); } });