// 공차중계 운전자 컨트롤러 import { Request, Response } from "express"; import { query } from "../database/db"; import { logger } from "../utils/logger"; export class DriverController { /** * GET /api/driver/profile * 운전자 프로필 조회 */ static async getProfile(req: Request, res: Response): Promise { try { const userId = req.user?.userId; if (!userId) { res.status(401).json({ success: false, message: "인증이 필요합니다.", }); return; } // 사용자 정보 조회 const userResult = await query( `SELECT user_id, user_name, cell_phone, license_number, vehicle_number, signup_type FROM user_info WHERE user_id = $1`, [userId] ); if (userResult.length === 0) { res.status(404).json({ success: false, message: "사용자를 찾을 수 없습니다.", }); return; } const user = userResult[0]; // 공차중계 사용자가 아닌 경우 if (user.signup_type !== "DRIVER") { res.status(403).json({ success: false, message: "공차중계 사용자만 접근할 수 있습니다.", }); return; } // 차량 정보 조회 const vehicleResult = await query( `SELECT vehicle_number, vehicle_type, driver_name, driver_phone, status FROM vehicles WHERE user_id = $1`, [userId] ); const vehicle = vehicleResult.length > 0 ? vehicleResult[0] : null; res.status(200).json({ success: true, data: { userId: user.user_id, userName: user.user_name, phoneNumber: user.cell_phone, licenseNumber: user.license_number, vehicleNumber: user.vehicle_number, vehicleType: vehicle?.vehicle_type || null, vehicleStatus: vehicle?.status || null, }, }); } catch (error) { logger.error("운전자 프로필 조회 오류:", error); res.status(500).json({ success: false, message: "프로필 조회 중 오류가 발생했습니다.", }); } } /** * PUT /api/driver/profile * 운전자 프로필 수정 (이름, 연락처, 면허정보, 차량번호, 차종) */ static async updateProfile(req: Request, res: Response): Promise { try { const userId = req.user?.userId; if (!userId) { res.status(401).json({ success: false, message: "인증이 필요합니다.", }); return; } const { userName, phoneNumber, licenseNumber, vehicleNumber, vehicleType } = req.body; // 공차중계 사용자 확인 const userCheck = await query( `SELECT signup_type, vehicle_number FROM user_info WHERE user_id = $1`, [userId] ); if (userCheck.length === 0) { res.status(404).json({ success: false, message: "사용자를 찾을 수 없습니다.", }); return; } if (userCheck[0].signup_type !== "DRIVER") { res.status(403).json({ success: false, message: "공차중계 사용자만 접근할 수 있습니다.", }); return; } const oldVehicleNumber = userCheck[0].vehicle_number; // 차량번호 변경 시 중복 확인 if (vehicleNumber && vehicleNumber !== oldVehicleNumber) { const duplicateCheck = await query( `SELECT vehicle_number FROM vehicles WHERE vehicle_number = $1 AND user_id != $2`, [vehicleNumber, userId] ); if (duplicateCheck.length > 0) { res.status(400).json({ success: false, message: "이미 등록된 차량번호입니다.", }); return; } } // user_info 업데이트 await query( `UPDATE user_info SET user_name = COALESCE($1, user_name), cell_phone = COALESCE($2, cell_phone), license_number = COALESCE($3, license_number), vehicle_number = COALESCE($4, vehicle_number) WHERE user_id = $5`, [userName || null, phoneNumber || null, licenseNumber || null, vehicleNumber || null, userId] ); // vehicles 테이블 업데이트 await query( `UPDATE vehicles SET vehicle_number = COALESCE($1, vehicle_number), vehicle_type = COALESCE($2, vehicle_type), driver_name = COALESCE($3, driver_name), driver_phone = COALESCE($4, driver_phone), updated_at = NOW() WHERE user_id = $5`, [vehicleNumber || null, vehicleType || null, userName || null, phoneNumber || null, userId] ); logger.info(`운전자 프로필 수정 완료: ${userId}`); res.status(200).json({ success: true, message: "프로필이 수정되었습니다.", }); } catch (error) { logger.error("운전자 프로필 수정 오류:", error); res.status(500).json({ success: false, message: "프로필 수정 중 오류가 발생했습니다.", }); } } /** * PUT /api/driver/status * 차량 상태 변경 (대기/정비만 가능) */ static async updateStatus(req: Request, res: Response): Promise { try { const userId = req.user?.userId; if (!userId) { res.status(401).json({ success: false, message: "인증이 필요합니다.", }); return; } const { status } = req.body; // 허용된 상태값만 (대기: off, 정비: maintenance) const allowedStatuses = ["off", "maintenance"]; if (!status || !allowedStatuses.includes(status)) { res.status(400).json({ success: false, message: "유효하지 않은 상태값입니다. (off: 대기, maintenance: 정비)", }); return; } // 공차중계 사용자 확인 const userCheck = await query( `SELECT signup_type FROM user_info WHERE user_id = $1`, [userId] ); if (userCheck.length === 0 || userCheck[0].signup_type !== "DRIVER") { res.status(403).json({ success: false, message: "공차중계 사용자만 접근할 수 있습니다.", }); return; } // vehicles 테이블 상태 업데이트 const updateResult = await query( `UPDATE vehicles SET status = $1, updated_at = NOW() WHERE user_id = $2`, [status, userId] ); logger.info(`차량 상태 변경: ${userId} -> ${status}`); res.status(200).json({ success: true, message: `차량 상태가 ${status === "off" ? "대기" : "정비"}로 변경되었습니다.`, }); } catch (error) { logger.error("차량 상태 변경 오류:", error); res.status(500).json({ success: false, message: "상태 변경 중 오류가 발생했습니다.", }); } } /** * DELETE /api/driver/account * 회원 탈퇴 (차량 정보 포함 삭제) */ static async deleteAccount(req: Request, res: Response): Promise { try { const userId = req.user?.userId; if (!userId) { res.status(401).json({ success: false, message: "인증이 필요합니다.", }); return; } // 공차중계 사용자 확인 const userCheck = await query( `SELECT signup_type FROM user_info WHERE user_id = $1`, [userId] ); if (userCheck.length === 0) { res.status(404).json({ success: false, message: "사용자를 찾을 수 없습니다.", }); return; } if (userCheck[0].signup_type !== "DRIVER") { res.status(403).json({ success: false, message: "공차중계 사용자만 탈퇴할 수 있습니다.", }); return; } // vehicles 테이블에서 삭제 await query(`DELETE FROM vehicles WHERE user_id = $1`, [userId]); // user_info 테이블에서 삭제 await query(`DELETE FROM user_info WHERE user_id = $1`, [userId]); logger.info(`회원 탈퇴 완료: ${userId}`); res.status(200).json({ success: true, message: "회원 탈퇴가 완료되었습니다.", }); } catch (error) { logger.error("회원 탈퇴 오류:", error); res.status(500).json({ success: false, message: "회원 탈퇴 처리 중 오류가 발생했습니다.", }); } } }