302 lines
8.5 KiB
TypeScript
302 lines
8.5 KiB
TypeScript
|
|
// 공차중계 운전자 컨트롤러
|
||
|
|
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<void> {
|
||
|
|
try {
|
||
|
|
const userId = req.user?.userId;
|
||
|
|
|
||
|
|
if (!userId) {
|
||
|
|
res.status(401).json({
|
||
|
|
success: false,
|
||
|
|
message: "인증이 필요합니다.",
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 사용자 정보 조회
|
||
|
|
const userResult = await query<any>(
|
||
|
|
`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<any>(
|
||
|
|
`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<void> {
|
||
|
|
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<any>(
|
||
|
|
`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<any>(
|
||
|
|
`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<void> {
|
||
|
|
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<any>(
|
||
|
|
`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<void> {
|
||
|
|
try {
|
||
|
|
const userId = req.user?.userId;
|
||
|
|
|
||
|
|
if (!userId) {
|
||
|
|
res.status(401).json({
|
||
|
|
success: false,
|
||
|
|
message: "인증이 필요합니다.",
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 공차중계 사용자 확인
|
||
|
|
const userCheck = await query<any>(
|
||
|
|
`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: "회원 탈퇴 처리 중 오류가 발생했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|