more workbench usability
This commit is contained in:
@@ -2,6 +2,7 @@ import type {
|
||||
GanttLinkDto,
|
||||
GanttTaskDto,
|
||||
PlanningReadinessState,
|
||||
PlanningStationDayLoadDto,
|
||||
PlanningStationLoadDto,
|
||||
PlanningTaskActionDto,
|
||||
PlanningTimelineDto,
|
||||
@@ -94,6 +95,15 @@ type StationAccumulator = {
|
||||
workingDays: number[];
|
||||
};
|
||||
|
||||
type StationDayAccumulator = {
|
||||
stationId: string;
|
||||
dateKey: string;
|
||||
plannedMinutes: number;
|
||||
actualMinutes: number;
|
||||
operationCount: number;
|
||||
capacityMinutes: number;
|
||||
};
|
||||
|
||||
function clampProgress(value: number) {
|
||||
return Math.max(0, Math.min(100, Math.round(value)));
|
||||
}
|
||||
@@ -199,6 +209,23 @@ function createStationLoad(record: StationAccumulator): PlanningStationLoadDto {
|
||||
};
|
||||
}
|
||||
|
||||
function createStationDayLoad(record: StationDayAccumulator): PlanningStationDayLoadDto {
|
||||
const capacityMinutes = Math.max(record.capacityMinutes, 1);
|
||||
const utilizationPercent = Math.round((record.plannedMinutes / capacityMinutes) * 100);
|
||||
const actualUtilizationPercent = Math.round((record.actualMinutes / capacityMinutes) * 100);
|
||||
return {
|
||||
stationId: record.stationId,
|
||||
dateKey: record.dateKey,
|
||||
plannedMinutes: record.plannedMinutes,
|
||||
actualMinutes: record.actualMinutes,
|
||||
capacityMinutes,
|
||||
utilizationPercent,
|
||||
actualUtilizationPercent,
|
||||
operationCount: record.operationCount,
|
||||
overloaded: utilizationPercent > 100,
|
||||
};
|
||||
}
|
||||
|
||||
function buildProjectTask(
|
||||
project: PlanningProjectRecord,
|
||||
projectWorkOrders: PlanningWorkOrderRecord[],
|
||||
@@ -492,6 +519,7 @@ export async function getPlanningTimeline(): Promise<PlanningTimelineDto> {
|
||||
}
|
||||
|
||||
const stationAccumulators = new Map<string, StationAccumulator>();
|
||||
const stationDayAccumulators = new Map<string, StationDayAccumulator>();
|
||||
for (const workOrder of openWorkOrders) {
|
||||
const insight = workOrderInsights.get(workOrder.id);
|
||||
for (const operation of workOrder.operations) {
|
||||
@@ -525,7 +553,22 @@ export async function getPlanningTimeline(): Promise<PlanningTimelineDto> {
|
||||
current.lateCount += 1;
|
||||
}
|
||||
for (let cursor = startOfDay(operation.plannedStart).getTime(); cursor <= startOfDay(operation.plannedEnd).getTime(); cursor += DAY_MS) {
|
||||
current.dayKeys.add(dateKey(new Date(cursor)));
|
||||
const currentDate = new Date(cursor);
|
||||
const currentDateKey = dateKey(currentDate);
|
||||
current.dayKeys.add(currentDateKey);
|
||||
const dayAccumulatorKey = `${operation.station.id}:${currentDateKey}`;
|
||||
const dayAccumulator = stationDayAccumulators.get(dayAccumulatorKey) ?? {
|
||||
stationId: operation.station.id,
|
||||
dateKey: currentDateKey,
|
||||
plannedMinutes: 0,
|
||||
actualMinutes: 0,
|
||||
operationCount: 0,
|
||||
capacityMinutes: Math.max(operation.station.dailyCapacityMinutes, 60) * Math.max(operation.station.parallelCapacity, 1),
|
||||
};
|
||||
dayAccumulator.plannedMinutes += operation.plannedMinutes;
|
||||
dayAccumulator.actualMinutes += operation.actualMinutes;
|
||||
dayAccumulator.operationCount += 1;
|
||||
stationDayAccumulators.set(dayAccumulatorKey, dayAccumulator);
|
||||
}
|
||||
stationAccumulators.set(operation.station.id, current);
|
||||
}
|
||||
@@ -537,6 +580,14 @@ export async function getPlanningTimeline(): Promise<PlanningTimelineDto> {
|
||||
}
|
||||
return left.stationCode.localeCompare(right.stationCode);
|
||||
});
|
||||
const stationDayLoads = [...stationDayAccumulators.values()]
|
||||
.map(createStationDayLoad)
|
||||
.sort((left, right) => {
|
||||
if (left.dateKey !== right.dateKey) {
|
||||
return left.dateKey.localeCompare(right.dateKey);
|
||||
}
|
||||
return left.stationId.localeCompare(right.stationId);
|
||||
});
|
||||
const stationLoadById = new Map(stationLoads.map((load) => [load.stationId, load]));
|
||||
|
||||
const tasks: GanttTaskDto[] = [];
|
||||
@@ -863,5 +914,6 @@ export async function getPlanningTimeline(): Promise<PlanningTimelineDto> {
|
||||
})
|
||||
.slice(0, 12),
|
||||
stationLoads,
|
||||
stationDayLoads,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user