302 lines
7.4 KiB
TypeScript
302 lines
7.4 KiB
TypeScript
|
|
/**
|
||
|
|
* 차량 운행 이력 컨트롤러
|
||
|
|
*/
|
||
|
|
import { Response } from "express";
|
||
|
|
import { AuthenticatedRequest } from "../middleware/authMiddleware";
|
||
|
|
import { vehicleTripService } from "../services/vehicleTripService";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 운행 시작
|
||
|
|
* POST /api/vehicle/trip/start
|
||
|
|
*/
|
||
|
|
export const startTrip = async (
|
||
|
|
req: AuthenticatedRequest,
|
||
|
|
res: Response
|
||
|
|
): Promise<Response | void> => {
|
||
|
|
try {
|
||
|
|
const { companyCode, userId } = req.user as any;
|
||
|
|
const { vehicleId, departure, arrival, departureName, destinationName, latitude, longitude } = req.body;
|
||
|
|
|
||
|
|
console.log("🚗 [startTrip] 요청:", { userId, companyCode, departure, arrival });
|
||
|
|
|
||
|
|
if (latitude === undefined || longitude === undefined) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "위치 정보(latitude, longitude)가 필요합니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const result = await vehicleTripService.startTrip({
|
||
|
|
userId,
|
||
|
|
companyCode,
|
||
|
|
vehicleId,
|
||
|
|
departure,
|
||
|
|
arrival,
|
||
|
|
departureName,
|
||
|
|
destinationName,
|
||
|
|
latitude,
|
||
|
|
longitude,
|
||
|
|
});
|
||
|
|
|
||
|
|
console.log("✅ [startTrip] 성공:", result);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: result,
|
||
|
|
message: "운행이 시작되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error: any) {
|
||
|
|
console.error("❌ [startTrip] 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: error.message || "운행 시작에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 운행 종료
|
||
|
|
* POST /api/vehicle/trip/end
|
||
|
|
*/
|
||
|
|
export const endTrip = async (
|
||
|
|
req: AuthenticatedRequest,
|
||
|
|
res: Response
|
||
|
|
): Promise<Response | void> => {
|
||
|
|
try {
|
||
|
|
const { companyCode, userId } = req.user as any;
|
||
|
|
const { tripId, latitude, longitude } = req.body;
|
||
|
|
|
||
|
|
console.log("🚗 [endTrip] 요청:", { userId, companyCode, tripId });
|
||
|
|
|
||
|
|
if (!tripId) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "tripId가 필요합니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if (latitude === undefined || longitude === undefined) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "위치 정보(latitude, longitude)가 필요합니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const result = await vehicleTripService.endTrip({
|
||
|
|
tripId,
|
||
|
|
userId,
|
||
|
|
companyCode,
|
||
|
|
latitude,
|
||
|
|
longitude,
|
||
|
|
});
|
||
|
|
|
||
|
|
console.log("✅ [endTrip] 성공:", result);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: result,
|
||
|
|
message: "운행이 종료되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error: any) {
|
||
|
|
console.error("❌ [endTrip] 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: error.message || "운행 종료에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 위치 기록 추가 (연속 추적)
|
||
|
|
* POST /api/vehicle/trip/location
|
||
|
|
*/
|
||
|
|
export const addTripLocation = async (
|
||
|
|
req: AuthenticatedRequest,
|
||
|
|
res: Response
|
||
|
|
): Promise<Response | void> => {
|
||
|
|
try {
|
||
|
|
const { companyCode, userId } = req.user as any;
|
||
|
|
const { tripId, latitude, longitude, accuracy, speed } = req.body;
|
||
|
|
|
||
|
|
if (!tripId) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "tripId가 필요합니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if (latitude === undefined || longitude === undefined) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "위치 정보(latitude, longitude)가 필요합니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const result = await vehicleTripService.addLocation({
|
||
|
|
tripId,
|
||
|
|
userId,
|
||
|
|
companyCode,
|
||
|
|
latitude,
|
||
|
|
longitude,
|
||
|
|
accuracy,
|
||
|
|
speed,
|
||
|
|
});
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: result,
|
||
|
|
});
|
||
|
|
} catch (error: any) {
|
||
|
|
console.error("❌ [addTripLocation] 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: error.message || "위치 기록에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 운행 이력 목록 조회
|
||
|
|
* GET /api/vehicle/trips
|
||
|
|
*/
|
||
|
|
export const getTripList = async (
|
||
|
|
req: AuthenticatedRequest,
|
||
|
|
res: Response
|
||
|
|
): Promise<Response | void> => {
|
||
|
|
try {
|
||
|
|
const { companyCode } = req.user as any;
|
||
|
|
const { userId, vehicleId, status, startDate, endDate, departure, arrival, limit, offset } = req.query;
|
||
|
|
|
||
|
|
console.log("🚗 [getTripList] 요청:", { companyCode, userId, status, startDate, endDate });
|
||
|
|
|
||
|
|
const result = await vehicleTripService.getTripList(companyCode, {
|
||
|
|
userId: userId as string,
|
||
|
|
vehicleId: vehicleId ? parseInt(vehicleId as string) : undefined,
|
||
|
|
status: status as string,
|
||
|
|
startDate: startDate as string,
|
||
|
|
endDate: endDate as string,
|
||
|
|
departure: departure as string,
|
||
|
|
arrival: arrival as string,
|
||
|
|
limit: limit ? parseInt(limit as string) : 50,
|
||
|
|
offset: offset ? parseInt(offset as string) : 0,
|
||
|
|
});
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: result.data,
|
||
|
|
total: result.total,
|
||
|
|
});
|
||
|
|
} catch (error: any) {
|
||
|
|
console.error("❌ [getTripList] 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: error.message || "운행 이력 조회에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 운행 상세 조회 (경로 포함)
|
||
|
|
* GET /api/vehicle/trips/:tripId
|
||
|
|
*/
|
||
|
|
export const getTripDetail = async (
|
||
|
|
req: AuthenticatedRequest,
|
||
|
|
res: Response
|
||
|
|
): Promise<Response | void> => {
|
||
|
|
try {
|
||
|
|
const { companyCode } = req.user as any;
|
||
|
|
const { tripId } = req.params;
|
||
|
|
|
||
|
|
console.log("🚗 [getTripDetail] 요청:", { companyCode, tripId });
|
||
|
|
|
||
|
|
const result = await vehicleTripService.getTripDetail(tripId, companyCode);
|
||
|
|
|
||
|
|
if (!result) {
|
||
|
|
return res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: "운행 정보를 찾을 수 없습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: result,
|
||
|
|
});
|
||
|
|
} catch (error: any) {
|
||
|
|
console.error("❌ [getTripDetail] 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: error.message || "운행 상세 조회에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 활성 운행 조회 (현재 진행 중)
|
||
|
|
* GET /api/vehicle/trip/active
|
||
|
|
*/
|
||
|
|
export const getActiveTrip = async (
|
||
|
|
req: AuthenticatedRequest,
|
||
|
|
res: Response
|
||
|
|
): Promise<Response | void> => {
|
||
|
|
try {
|
||
|
|
const { companyCode, userId } = req.user as any;
|
||
|
|
|
||
|
|
const result = await vehicleTripService.getActiveTrip(userId, companyCode);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: result,
|
||
|
|
hasActiveTrip: !!result,
|
||
|
|
});
|
||
|
|
} catch (error: any) {
|
||
|
|
console.error("❌ [getActiveTrip] 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: error.message || "활성 운행 조회에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 운행 취소
|
||
|
|
* POST /api/vehicle/trip/cancel
|
||
|
|
*/
|
||
|
|
export const cancelTrip = async (
|
||
|
|
req: AuthenticatedRequest,
|
||
|
|
res: Response
|
||
|
|
): Promise<Response | void> => {
|
||
|
|
try {
|
||
|
|
const { companyCode } = req.user as any;
|
||
|
|
const { tripId } = req.body;
|
||
|
|
|
||
|
|
if (!tripId) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "tripId가 필요합니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const result = await vehicleTripService.cancelTrip(tripId, companyCode);
|
||
|
|
|
||
|
|
if (!result) {
|
||
|
|
return res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: "취소할 운행을 찾을 수 없습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
message: "운행이 취소되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error: any) {
|
||
|
|
console.error("❌ [cancelTrip] 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: error.message || "운행 취소에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|