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:
@@ -38,6 +38,71 @@ const adminOnly = (req, res, next) => {
|
||||
}
|
||||
};
|
||||
|
||||
// ========== 개인 정보 조회 API (관리자 권한 불필요) ==========
|
||||
// 내 정보 조회
|
||||
router.get('/me', userController.getMyInfo || ((req, res) => res.json({ success: true, data: req.user })));
|
||||
|
||||
// 내 출근 기록 조회
|
||||
router.get('/me/attendance-records', async (req, res) => {
|
||||
try {
|
||||
const { year, month } = req.query;
|
||||
const AttendanceModel = require('../models/attendanceModel');
|
||||
const startDate = `${year}-${String(month).padStart(2, '0')}-01`;
|
||||
const endDate = `${year}-${String(month).padStart(2, '0')}-31`;
|
||||
const records = await AttendanceModel.getDailyRecords(startDate, endDate, req.user.worker_id);
|
||||
res.json({ success: true, data: records });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 내 연차 잔액 조회
|
||||
router.get('/me/vacation-balance', async (req, res) => {
|
||||
try {
|
||||
const AttendanceModel = require('../models/attendanceModel');
|
||||
const year = req.query.year || new Date().getFullYear();
|
||||
const balance = await AttendanceModel.getWorkerVacationBalance(req.user.worker_id, year);
|
||||
res.json({ success: true, data: balance });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 내 작업 보고서 조회
|
||||
router.get('/me/work-reports', async (req, res) => {
|
||||
try {
|
||||
const { startDate, endDate } = req.query;
|
||||
const db = require('../config/database');
|
||||
const reports = await db.query(
|
||||
'SELECT * FROM daily_work_reports WHERE worker_id = ? AND report_date BETWEEN ? AND ? ORDER BY report_date DESC',
|
||||
[req.user.worker_id, startDate, endDate]
|
||||
);
|
||||
res.json({ success: true, data: reports });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 내 월별 통계
|
||||
router.get('/me/monthly-stats', async (req, res) => {
|
||||
try {
|
||||
const { year, month } = req.query;
|
||||
const db = require('../config/database');
|
||||
const stats = await db.query(
|
||||
`SELECT
|
||||
SUM(total_work_hours) as month_hours,
|
||||
COUNT(DISTINCT record_date) as work_days
|
||||
FROM daily_attendance_records
|
||||
WHERE worker_id = ? AND YEAR(record_date) = ? AND MONTH(record_date) = ?`,
|
||||
[req.user.worker_id, year, month]
|
||||
);
|
||||
res.json({ success: true, data: stats[0] || { month_hours: 0, work_days: 0 } });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// ========== 관리자 전용 API ==========
|
||||
/**
|
||||
* 모든 라우트에 관리자 권한 적용
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user