feat: 작업자-계정 통합 및 연차/출근 관리 시스템 구축
모든 작업자가 개인 계정으로 로그인하여 본인의 연차와 출근 기록을 확인할 수 있는 시스템을 구축했습니다. 주요 기능: - 작업자-계정 1:1 통합 (기존 작업자 자동 계정 생성) - 연차 관리 시스템 (연도별 잔액 관리) - 출근 기록 시스템 (일일 근태 기록) - 나의 대시보드 페이지 (개인 정보 조회) 데이터베이스: - workers 테이블에 salary, base_annual_leave 컬럼 추가 - work_attendance_types, vacation_types 테이블 생성 - daily_attendance_records 테이블 생성 - worker_vacation_balance 테이블 생성 - 기존 작업자 자동 계정 생성 (username: 이름 기반) - Guest 역할 추가 백엔드 API: - 한글→영문 변환 유틸리티 (hangulToRoman.js) - UserRoutes에 개인 정보 조회 API 추가 - GET /api/users/me (내 정보) - GET /api/users/me/attendance-records (출근 기록) - GET /api/users/me/vacation-balance (연차 잔액) - GET /api/users/me/work-reports (작업 보고서) - GET /api/users/me/monthly-stats (월별 통계) 프론트엔드: - 나의 대시보드 페이지 (my-dashboard.html) - 연차 정보 위젯 (총/사용/잔여) - 월별 출근 캘린더 - 근무 시간 통계 - 최근 작업 보고서 목록 - 네비게이션 바에 "나의 대시보드" 메뉴 추가 배포 시 주의사항: - 마이그레이션 실행 필요 - 자동 생성된 계정 초기 비밀번호: 1234 - 작업자들에게 첫 로그인 후 비밀번호 변경 안내 필요 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -598,37 +598,41 @@ router.get('/users', verifyToken, async (req, res) => {
|
||||
try {
|
||||
connection = await mysql.createConnection(dbConfig);
|
||||
|
||||
// 기본 쿼리
|
||||
// 기본 쿼리 (role 테이블과 JOIN)
|
||||
let query = `
|
||||
SELECT
|
||||
user_id,
|
||||
username,
|
||||
name,
|
||||
email,
|
||||
access_level,
|
||||
worker_id,
|
||||
is_active,
|
||||
last_login_at,
|
||||
created_at
|
||||
FROM Users
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.username,
|
||||
u.name,
|
||||
u.email,
|
||||
u.role_id,
|
||||
r.name as role_name,
|
||||
u._access_level_old as access_level,
|
||||
u.worker_id,
|
||||
u.is_active,
|
||||
u.last_login_at,
|
||||
u.created_at
|
||||
FROM users u
|
||||
LEFT JOIN roles r ON u.role_id = r.id
|
||||
WHERE 1=1
|
||||
`;
|
||||
|
||||
|
||||
const params = [];
|
||||
|
||||
|
||||
// 필터링 옵션
|
||||
if (req.query.active !== undefined) {
|
||||
query += ' AND is_active = ?';
|
||||
query += ' AND u.is_active = ?';
|
||||
params.push(req.query.active === 'true');
|
||||
}
|
||||
|
||||
|
||||
// role_name으로 필터링 (access_level 대신)
|
||||
if (req.query.access_level) {
|
||||
query += ' AND access_level = ?';
|
||||
params.push(req.query.access_level);
|
||||
query += ' AND (u._access_level_old = ? OR r.name = ?)';
|
||||
params.push(req.query.access_level, req.query.access_level);
|
||||
}
|
||||
|
||||
query += ' ORDER BY created_at DESC';
|
||||
|
||||
|
||||
query += ' ORDER BY u.created_at DESC';
|
||||
|
||||
const [rows] = await connection.execute(query, params);
|
||||
|
||||
const userList = rows.map(user => ({
|
||||
@@ -636,7 +640,9 @@ router.get('/users', verifyToken, async (req, res) => {
|
||||
username: user.username,
|
||||
name: user.name || user.username,
|
||||
email: user.email,
|
||||
access_level: user.access_level,
|
||||
role_id: user.role_id,
|
||||
role_name: user.role_name,
|
||||
access_level: user.access_level || user.role_name?.toLowerCase(), // 하위 호환성
|
||||
worker_id: user.worker_id,
|
||||
is_active: user.is_active,
|
||||
last_login_at: user.last_login_at,
|
||||
|
||||
Reference in New Issue
Block a user