mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 21:20:57 +00:00
Merge branch 'freight/hot_fix' of github.com:Tria-plc/edr-platform into freight/hot_fix
This commit is contained in:
@@ -21,8 +21,8 @@ export class FuelConsumption extends BaseEntity {
|
||||
@Column({ name: 'total_cost', type: 'numeric', precision: 14, scale: 2 })
|
||||
totalCost!: number;
|
||||
|
||||
@Column({ name: 'total_distance_km', type: 'numeric', precision: 10, scale: 2 })
|
||||
totalDistanceKm!: number;
|
||||
@Column({ name: 'total_distance_km', type: 'numeric', precision: 10, scale: 2, default: 0 })
|
||||
totalDistanceKm: number = 0;
|
||||
|
||||
@Column({ name: 'fuel_efficiency_km_per_l', type: 'numeric', precision: 10, scale: 2, nullable: true })
|
||||
fuelEfficiencyKmPerL?: number;
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { IsUUID, IsString, IsDateString, IsNumber, IsOptional, IsEnum } from 'class-validator';
|
||||
import { MaintenanceType, MaintenanceStatus } from '../entities/maintenance-schedule.entity';
|
||||
|
||||
export class CreateMaintenanceScheduleDto {
|
||||
@IsUUID()
|
||||
vehicleId!: string;
|
||||
|
||||
@IsEnum(MaintenanceType)
|
||||
maintenanceType!: MaintenanceType;
|
||||
|
||||
@IsString()
|
||||
description!: string;
|
||||
|
||||
@IsDateString()
|
||||
scheduledDate!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
estimatedCost?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
serviceProvider?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
notes?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
nextDueKm?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
nextDueDate?: string;
|
||||
}
|
||||
|
||||
export class CreateMaintenanceCostDto {
|
||||
@IsUUID()
|
||||
vehicleId!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
maintenanceScheduleId?: string;
|
||||
|
||||
@IsDateString()
|
||||
incurredDate!: string;
|
||||
|
||||
@IsNumber()
|
||||
costAmount!: number;
|
||||
|
||||
@IsString()
|
||||
costType!: string;
|
||||
|
||||
@IsString()
|
||||
description!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
serviceProvider?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
invoiceNumber?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export class UpdateMaintenanceScheduleDto {
|
||||
@IsOptional()
|
||||
@IsEnum(MaintenanceStatus)
|
||||
status?: MaintenanceStatus;
|
||||
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
completedDate?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
actualCost?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
notes?: string;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { BaseEntity } from '@edr/api-common';
|
||||
import { Entity, Column, ManyToOne, JoinColumn, Index } from 'typeorm';
|
||||
import { Vehicle } from '../../vehicles/entities/vehicle.entity';
|
||||
import { MaintenanceSchedule } from './maintenance-schedule.entity';
|
||||
|
||||
@Entity({ name: 'maintenance_costs', schema: 'freight' })
|
||||
@Index(['vehicleId', 'incurredDate'])
|
||||
export class MaintenanceCost extends BaseEntity {
|
||||
@Column({ name: 'vehicle_id', type: 'uuid' })
|
||||
vehicleId!: string;
|
||||
|
||||
@ManyToOne(() => Vehicle, { eager: false })
|
||||
@JoinColumn({ name: 'vehicle_id' })
|
||||
vehicle!: Vehicle;
|
||||
|
||||
@Column({ name: 'maintenance_schedule_id', type: 'uuid', nullable: true })
|
||||
maintenanceScheduleId?: string;
|
||||
|
||||
@ManyToOne(() => MaintenanceSchedule, { eager: false, onDelete: 'SET NULL' })
|
||||
@JoinColumn({ name: 'maintenance_schedule_id' })
|
||||
maintenanceSchedule?: MaintenanceSchedule;
|
||||
|
||||
@Column({ name: 'incurred_date', type: 'timestamptz' })
|
||||
incurredDate!: Date;
|
||||
|
||||
@Column({ name: 'cost_amount', type: 'numeric', precision: 14, scale: 2 })
|
||||
costAmount!: number;
|
||||
|
||||
@Column({ name: 'cost_type' })
|
||||
costType!: string; // 'PARTS', 'LABOR', 'DIAGNOSTICS', 'OTHER'
|
||||
|
||||
@Column({ name: 'description' })
|
||||
description!: string;
|
||||
|
||||
@Column({ name: 'service_provider', nullable: true })
|
||||
serviceProvider?: string;
|
||||
|
||||
@Column({ name: 'invoice_number', nullable: true })
|
||||
invoiceNumber?: string;
|
||||
|
||||
@Column({ type: 'text', nullable: true })
|
||||
notes?: string;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { BaseEntity } from '@edr/api-common';
|
||||
import { Entity, Column, ManyToOne, JoinColumn, Index } from 'typeorm';
|
||||
import { Vehicle } from '../../vehicles/entities/vehicle.entity';
|
||||
|
||||
export enum MaintenanceType {
|
||||
PREVENTIVE = 'PREVENTIVE',
|
||||
CORRECTIVE = 'CORRECTIVE',
|
||||
INSPECTION = 'INSPECTION',
|
||||
REPAIR = 'REPAIR',
|
||||
}
|
||||
|
||||
export enum MaintenanceStatus {
|
||||
SCHEDULED = 'SCHEDULED',
|
||||
IN_PROGRESS = 'IN_PROGRESS',
|
||||
COMPLETED = 'COMPLETED',
|
||||
CANCELLED = 'CANCELLED',
|
||||
OVERDUE = 'OVERDUE',
|
||||
}
|
||||
|
||||
@Entity({ name: 'maintenance_schedules', schema: 'freight' })
|
||||
@Index(['vehicleId', 'scheduledDate'])
|
||||
export class MaintenanceSchedule extends BaseEntity {
|
||||
@Column({ name: 'vehicle_id', type: 'uuid' })
|
||||
vehicleId!: string;
|
||||
|
||||
@ManyToOne(() => Vehicle, { eager: false })
|
||||
@JoinColumn({ name: 'vehicle_id' })
|
||||
vehicle!: Vehicle;
|
||||
|
||||
@Column({ name: 'maintenance_type', type: 'varchar' })
|
||||
maintenanceType!: MaintenanceType;
|
||||
|
||||
@Column({ name: 'description' })
|
||||
description!: string;
|
||||
|
||||
@Column({ name: 'scheduled_date', type: 'timestamptz' })
|
||||
scheduledDate!: Date;
|
||||
|
||||
@Column({ name: 'completed_date', type: 'timestamptz', nullable: true })
|
||||
completedDate?: Date;
|
||||
|
||||
@Column({ name: 'estimated_cost', type: 'numeric', precision: 14, scale: 2, nullable: true })
|
||||
estimatedCost?: number;
|
||||
|
||||
@Column({ name: 'actual_cost', type: 'numeric', precision: 14, scale: 2, nullable: true })
|
||||
actualCost?: number;
|
||||
|
||||
@Column({ name: 'status', type: 'varchar', default: MaintenanceStatus.SCHEDULED })
|
||||
status!: MaintenanceStatus;
|
||||
|
||||
@Column({ name: 'odometer_reading', type: 'numeric', nullable: true })
|
||||
odometerReading?: number;
|
||||
|
||||
@Column({ name: 'service_provider', nullable: true })
|
||||
serviceProvider?: string;
|
||||
|
||||
@Column({ name: 'notes', type: 'text', nullable: true })
|
||||
notes?: string;
|
||||
|
||||
@Column({ name: 'next_due_km', type: 'numeric', nullable: true })
|
||||
nextDueKm?: number;
|
||||
|
||||
@Column({ name: 'next_due_date', type: 'timestamptz', nullable: true })
|
||||
nextDueDate?: Date;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { BaseRepository } from '@edr/api-common';
|
||||
import { Repository, Between } from 'typeorm';
|
||||
import { MaintenanceSchedule, MaintenanceStatus } from './entities/maintenance-schedule.entity';
|
||||
import { MaintenanceCost } from './entities/maintenance-cost.entity';
|
||||
|
||||
@Injectable()
|
||||
export class MaintenanceRepository extends BaseRepository<MaintenanceSchedule> {
|
||||
constructor(
|
||||
@InjectRepository(MaintenanceSchedule)
|
||||
private readonly scheduleRepository: Repository<MaintenanceSchedule>,
|
||||
@InjectRepository(MaintenanceCost)
|
||||
private readonly costRepository: Repository<MaintenanceCost>,
|
||||
) {
|
||||
super(scheduleRepository);
|
||||
}
|
||||
|
||||
async getUpcomingMaintenance(vehicleId: string, daysAhead: number = 30) {
|
||||
const futureDate = new Date(Date.now() + daysAhead * 24 * 60 * 60 * 1000);
|
||||
return this.scheduleRepository.find({
|
||||
where: {
|
||||
vehicleId,
|
||||
scheduledDate: Between(new Date(), futureDate),
|
||||
status: MaintenanceStatus.SCHEDULED,
|
||||
},
|
||||
order: { scheduledDate: 'ASC' },
|
||||
});
|
||||
}
|
||||
|
||||
async getMaintenanceCosts(vehicleId: string, startDate: Date, endDate: Date) {
|
||||
return this.costRepository.find({
|
||||
where: {
|
||||
vehicleId,
|
||||
incurredDate: Between(startDate, endDate),
|
||||
},
|
||||
order: { incurredDate: 'DESC' },
|
||||
});
|
||||
}
|
||||
|
||||
async getTotalMaintenanceCost(vehicleId: string, startDate: Date, endDate: Date) {
|
||||
const result = await this.costRepository
|
||||
.createQueryBuilder()
|
||||
.select('SUM(cost_amount)', 'total')
|
||||
.where('vehicle_id = :vehicleId', { vehicleId })
|
||||
.andWhere('incurred_date BETWEEN :startDate AND :endDate', { startDate, endDate })
|
||||
.getRawOne();
|
||||
return result?.total || 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user