refactor: create monitoring route handler
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
119
src/server/routes/mileage/monitoring.ts
Normal file
119
src/server/routes/mileage/monitoring.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { Hono } from 'hono';
|
||||
import { getCache, queryDateMileage, buildDateFilters } from './cache.js';
|
||||
import type { CachedVehicle, MonitoringFilters, MonitoringResponse } from './types.js';
|
||||
|
||||
const app = new Hono();
|
||||
|
||||
const EMPTY_RESPONSE: MonitoringResponse = {
|
||||
vehicles: [],
|
||||
stats: { totalToday: 0, totalAll: 0, vehicleCount: 0, yesterdayTotal: 0 },
|
||||
filters: { departments: [], customers: [], plates: [], projects: [], entities: [], rentStatuses: [], platePrefixes: [], targetNames: [] },
|
||||
total: 0,
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
function applyFilters(vehicles: CachedVehicle[], params: {
|
||||
search: string; dept: string; customer: string; project: string;
|
||||
entity: string; rentStatus: string; plate: string; platePrefix: string;
|
||||
targetName: string; mileageMin: string; mileageMax: string;
|
||||
}): CachedVehicle[] {
|
||||
let result = vehicles;
|
||||
|
||||
if (params.search) {
|
||||
const q = params.search.toLowerCase();
|
||||
result = result.filter(v =>
|
||||
v.plate.toLowerCase().includes(q) ||
|
||||
(v.customer || '').toLowerCase().includes(q) ||
|
||||
(v.project || '').toLowerCase().includes(q)
|
||||
);
|
||||
}
|
||||
if (params.dept) result = result.filter(v => params.dept === '__EMPTY__' ? !v.department : v.department === params.dept);
|
||||
if (params.customer) result = result.filter(v => params.customer === '__EMPTY__' ? !v.customer : v.customer === params.customer);
|
||||
if (params.project) result = result.filter(v => v.project === params.project);
|
||||
if (params.entity) result = result.filter(v => v.entity === params.entity);
|
||||
if (params.rentStatus) result = result.filter(v => v.rentStatus === params.rentStatus);
|
||||
if (params.plate) result = result.filter(v => v.plate === params.plate);
|
||||
if (params.platePrefix) result = result.filter(v => v.plate.startsWith(params.platePrefix));
|
||||
if (params.targetName) {
|
||||
const cache = getCache();
|
||||
const tPlates = cache?.targetPlatesMap.get(params.targetName);
|
||||
result = tPlates ? result.filter(v => tPlates.has(v.plate)) : [];
|
||||
}
|
||||
if (params.mileageMin) result = result.filter(v => v.dailyKm >= Number(params.mileageMin));
|
||||
if (params.mileageMax) result = result.filter(v => v.dailyKm <= Number(params.mileageMax));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
app.get('/', async (c) => {
|
||||
const sortBy = c.req.query('sortBy') || 'today';
|
||||
const sortOrder = c.req.query('sortOrder') || 'desc';
|
||||
const limit = Number(c.req.query('limit')) || 50;
|
||||
const page = Number(c.req.query('page')) || 1;
|
||||
const date = c.req.query('date') || '';
|
||||
|
||||
const filterParams = {
|
||||
search: c.req.query('search') || '',
|
||||
dept: c.req.query('dept') || '',
|
||||
customer: c.req.query('customer') || '',
|
||||
project: c.req.query('project') || '',
|
||||
entity: c.req.query('entity') || '',
|
||||
rentStatus: c.req.query('rentStatus') || '',
|
||||
plate: c.req.query('plate') || '',
|
||||
platePrefix: c.req.query('platePrefix') || '',
|
||||
targetName: c.req.query('targetName') || '',
|
||||
mileageMin: c.req.query('mileageMin') || '',
|
||||
mileageMax: c.req.query('mileageMax') || '',
|
||||
};
|
||||
|
||||
let allVehicles: CachedVehicle[];
|
||||
let filters: MonitoringFilters;
|
||||
|
||||
if (date) {
|
||||
try {
|
||||
allVehicles = await queryDateMileage(date);
|
||||
filters = buildDateFilters(allVehicles);
|
||||
} catch (e: unknown) {
|
||||
console.error('monitoring date query error:', e);
|
||||
return c.json(EMPTY_RESPONSE, 500);
|
||||
}
|
||||
} else {
|
||||
const cache = getCache();
|
||||
if (!cache) return c.json(EMPTY_RESPONSE);
|
||||
allVehicles = cache.vehicles;
|
||||
filters = cache.filters;
|
||||
}
|
||||
|
||||
const filtered = applyFilters(allVehicles, filterParams);
|
||||
|
||||
const stats = {
|
||||
totalToday: filtered.reduce((sum, v) => sum + v.dailyKm, 0),
|
||||
totalAll: filtered.reduce((sum, v) => sum + (v.totalKm || 0), 0),
|
||||
vehicleCount: filtered.length,
|
||||
yesterdayTotal: filtered.reduce((sum, v) => sum + v.yesterdayKm, 0),
|
||||
};
|
||||
|
||||
const sorted = [...filtered].sort((a, b) => {
|
||||
const valA = sortBy === 'today' ? a.dailyKm : (a.totalKm || 0);
|
||||
const valB = sortBy === 'today' ? b.dailyKm : (b.totalKm || 0);
|
||||
return sortOrder === 'desc' ? valB - valA : valA - valB;
|
||||
});
|
||||
|
||||
const offset = (page - 1) * limit;
|
||||
const paged = sorted.slice(offset, offset + limit);
|
||||
const total = filtered.length;
|
||||
|
||||
return c.json({
|
||||
vehicles: paged,
|
||||
stats,
|
||||
filters,
|
||||
total,
|
||||
page,
|
||||
totalPages: Math.ceil(total / limit),
|
||||
updatedAt: date || getCache()?.updatedAt || new Date().toISOString(),
|
||||
});
|
||||
});
|
||||
|
||||
export default app;
|
||||
Reference in New Issue
Block a user