erp-mecanicas-diesel-backend/src/modules/vehicle-management/services/fleet.service.ts
2025-12-12 14:39:26 -06:00

208 lines
5.1 KiB
TypeScript

/**
* Fleet Service
* Mecánicas Diesel - ERP Suite
*
* Business logic for fleet management.
*/
import { Repository, DataSource } from 'typeorm';
import { Fleet } from '../entities/fleet.entity';
import { Vehicle, VehicleStatus } from '../entities/vehicle.entity';
// DTOs
export interface CreateFleetDto {
name: string;
code?: string;
contactName?: string;
contactPhone?: string;
contactEmail?: string;
discountLaborPct?: number;
discountPartsPct?: number;
creditDays?: number;
creditLimit?: number;
notes?: string;
}
export interface UpdateFleetDto {
name?: string;
code?: string;
contactName?: string;
contactPhone?: string;
contactEmail?: string;
discountLaborPct?: number;
discountPartsPct?: number;
creditDays?: number;
creditLimit?: number;
notes?: string;
isActive?: boolean;
}
export class FleetService {
private fleetRepository: Repository<Fleet>;
private vehicleRepository: Repository<Vehicle>;
constructor(dataSource: DataSource) {
this.fleetRepository = dataSource.getRepository(Fleet);
this.vehicleRepository = dataSource.getRepository(Vehicle);
}
/**
* Create a new fleet
*/
async create(tenantId: string, dto: CreateFleetDto): Promise<Fleet> {
const fleet = this.fleetRepository.create({
tenantId,
name: dto.name,
code: dto.code,
contactName: dto.contactName,
contactPhone: dto.contactPhone,
contactEmail: dto.contactEmail,
discountLaborPct: dto.discountLaborPct || 0,
discountPartsPct: dto.discountPartsPct || 0,
creditDays: dto.creditDays || 0,
creditLimit: dto.creditLimit || 0,
notes: dto.notes,
isActive: true,
vehicleCount: 0,
});
return this.fleetRepository.save(fleet);
}
/**
* Find fleet by ID
*/
async findById(tenantId: string, id: string): Promise<Fleet | null> {
return this.fleetRepository.findOne({
where: { id, tenantId },
});
}
/**
* List fleets
*/
async findAll(
tenantId: string,
pagination = { page: 1, limit: 20 }
) {
const queryBuilder = this.fleetRepository.createQueryBuilder('fleet')
.where('fleet.tenant_id = :tenantId', { tenantId });
const skip = (pagination.page - 1) * pagination.limit;
const [data, total] = await queryBuilder
.orderBy('fleet.name', 'ASC')
.skip(skip)
.take(pagination.limit)
.getManyAndCount();
return {
data,
total,
page: pagination.page,
limit: pagination.limit,
totalPages: Math.ceil(total / pagination.limit),
};
}
/**
* Update fleet
*/
async update(tenantId: string, id: string, dto: UpdateFleetDto): Promise<Fleet | null> {
const fleet = await this.findById(tenantId, id);
if (!fleet) return null;
Object.assign(fleet, dto);
return this.fleetRepository.save(fleet);
}
/**
* Deactivate fleet
*/
async deactivate(tenantId: string, id: string): Promise<boolean> {
const fleet = await this.findById(tenantId, id);
if (!fleet) return false;
fleet.isActive = false;
await this.fleetRepository.save(fleet);
return true;
}
/**
* Get fleet with vehicle count
*/
async getFleetWithStats(tenantId: string, id: string): Promise<{
fleet: Fleet;
vehicleCount: number;
activeVehicles: number;
} | null> {
const fleet = await this.findById(tenantId, id);
if (!fleet) return null;
const [vehicleCount, activeVehicles] = await Promise.all([
this.vehicleRepository.count({ where: { tenantId, fleetId: id } }),
this.vehicleRepository.count({ where: { tenantId, fleetId: id, status: VehicleStatus.ACTIVE } }),
]);
return {
fleet,
vehicleCount,
activeVehicles,
};
}
/**
* Get active fleets
*/
async findActive(tenantId: string): Promise<Fleet[]> {
return this.fleetRepository.find({
where: { tenantId, isActive: true },
order: { name: 'ASC' },
});
}
/**
* Add vehicle to fleet
*/
async addVehicle(tenantId: string, fleetId: string, vehicleId: string): Promise<boolean> {
const fleet = await this.findById(tenantId, fleetId);
if (!fleet) return false;
const vehicle = await this.vehicleRepository.findOne({
where: { id: vehicleId, tenantId },
});
if (!vehicle) return false;
vehicle.fleetId = fleetId;
await this.vehicleRepository.save(vehicle);
// Update vehicle count
fleet.vehicleCount = await this.vehicleRepository.count({ where: { tenantId, fleetId } });
await this.fleetRepository.save(fleet);
return true;
}
/**
* Remove vehicle from fleet
*/
async removeVehicle(tenantId: string, fleetId: string, vehicleId: string): Promise<boolean> {
const vehicle = await this.vehicleRepository.findOne({
where: { id: vehicleId, tenantId, fleetId },
});
if (!vehicle) return false;
const fleet = await this.findById(tenantId, fleetId);
if (!fleet) return false;
vehicle.fleetId = undefined;
await this.vehicleRepository.save(vehicle);
// Update vehicle count
fleet.vehicleCount = await this.vehicleRepository.count({ where: { tenantId, fleetId } });
await this.fleetRepository.save(fleet);
return true;
}
}