버튼 과정이 조금 복잡하지만 위도경도 연속추적기능도 넣음
This commit is contained in:
@@ -1731,6 +1731,191 @@ export class DynamicFormService {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 위치 이력 저장 (연속 위치 추적용)
|
||||
*/
|
||||
async saveLocationHistory(data: {
|
||||
userId: string;
|
||||
companyCode: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
accuracy?: number;
|
||||
altitude?: number;
|
||||
speed?: number;
|
||||
heading?: number;
|
||||
tripId?: string;
|
||||
tripStatus?: string;
|
||||
departure?: string;
|
||||
arrival?: string;
|
||||
departureName?: string;
|
||||
destinationName?: string;
|
||||
recordedAt?: string;
|
||||
vehicleId?: number;
|
||||
}): Promise<{ id: number }> {
|
||||
const pool = getPool();
|
||||
const client = await pool.connect();
|
||||
|
||||
try {
|
||||
console.log("📍 [saveLocationHistory] 저장 시작:", data);
|
||||
|
||||
const sqlQuery = `
|
||||
INSERT INTO vehicle_location_history (
|
||||
user_id,
|
||||
company_code,
|
||||
latitude,
|
||||
longitude,
|
||||
accuracy,
|
||||
altitude,
|
||||
speed,
|
||||
heading,
|
||||
trip_id,
|
||||
trip_status,
|
||||
departure,
|
||||
arrival,
|
||||
departure_name,
|
||||
destination_name,
|
||||
recorded_at,
|
||||
vehicle_id
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
|
||||
RETURNING id
|
||||
`;
|
||||
|
||||
const params = [
|
||||
data.userId,
|
||||
data.companyCode,
|
||||
data.latitude,
|
||||
data.longitude,
|
||||
data.accuracy || null,
|
||||
data.altitude || null,
|
||||
data.speed || null,
|
||||
data.heading || null,
|
||||
data.tripId || null,
|
||||
data.tripStatus || "active",
|
||||
data.departure || null,
|
||||
data.arrival || null,
|
||||
data.departureName || null,
|
||||
data.destinationName || null,
|
||||
data.recordedAt ? new Date(data.recordedAt) : new Date(),
|
||||
data.vehicleId || null,
|
||||
];
|
||||
|
||||
const result = await client.query(sqlQuery, params);
|
||||
|
||||
console.log("✅ [saveLocationHistory] 저장 완료:", {
|
||||
id: result.rows[0]?.id,
|
||||
});
|
||||
|
||||
return { id: result.rows[0]?.id };
|
||||
} catch (error) {
|
||||
console.error("❌ [saveLocationHistory] 오류:", error);
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 위치 이력 조회 (경로 조회용)
|
||||
*/
|
||||
async getLocationHistory(params: {
|
||||
companyCode: string;
|
||||
tripId?: string;
|
||||
userId?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
limit?: number;
|
||||
}): Promise<any[]> {
|
||||
const pool = getPool();
|
||||
const client = await pool.connect();
|
||||
|
||||
try {
|
||||
console.log("📍 [getLocationHistory] 조회 시작:", params);
|
||||
|
||||
const conditions: string[] = [];
|
||||
const queryParams: any[] = [];
|
||||
let paramIndex = 1;
|
||||
|
||||
// 멀티테넌시: company_code 필터
|
||||
if (params.companyCode && params.companyCode !== "*") {
|
||||
conditions.push(`company_code = $${paramIndex}`);
|
||||
queryParams.push(params.companyCode);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
// trip_id 필터
|
||||
if (params.tripId) {
|
||||
conditions.push(`trip_id = $${paramIndex}`);
|
||||
queryParams.push(params.tripId);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
// user_id 필터
|
||||
if (params.userId) {
|
||||
conditions.push(`user_id = $${paramIndex}`);
|
||||
queryParams.push(params.userId);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
// 날짜 범위 필터
|
||||
if (params.startDate) {
|
||||
conditions.push(`recorded_at >= $${paramIndex}`);
|
||||
queryParams.push(new Date(params.startDate));
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (params.endDate) {
|
||||
conditions.push(`recorded_at <= $${paramIndex}`);
|
||||
queryParams.push(new Date(params.endDate));
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
||||
const limitClause = params.limit ? `LIMIT ${params.limit}` : "LIMIT 1000";
|
||||
|
||||
const sqlQuery = `
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
vehicle_id,
|
||||
latitude,
|
||||
longitude,
|
||||
accuracy,
|
||||
altitude,
|
||||
speed,
|
||||
heading,
|
||||
trip_id,
|
||||
trip_status,
|
||||
departure,
|
||||
arrival,
|
||||
departure_name,
|
||||
destination_name,
|
||||
recorded_at,
|
||||
created_at,
|
||||
company_code
|
||||
FROM vehicle_location_history
|
||||
${whereClause}
|
||||
ORDER BY recorded_at ASC
|
||||
${limitClause}
|
||||
`;
|
||||
|
||||
console.log("🔍 [getLocationHistory] 쿼리:", sqlQuery);
|
||||
console.log("🔍 [getLocationHistory] 파라미터:", queryParams);
|
||||
|
||||
const result = await client.query(sqlQuery, queryParams);
|
||||
|
||||
console.log("✅ [getLocationHistory] 조회 완료:", {
|
||||
count: result.rowCount,
|
||||
});
|
||||
|
||||
return result.rows;
|
||||
} catch (error) {
|
||||
console.error("❌ [getLocationHistory] 오류:", error);
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 싱글톤 인스턴스 생성 및 export
|
||||
|
||||
Reference in New Issue
Block a user