import { Injectable } from '@nestjs/common';
import { randomUUID } from 'node:crypto';
import { DatabaseService } from '../../../infrastructure/database/database.service';
import { DomainConflictError } from '../../../common/errors/domain-conflict.error';
import {
assertEquipmentCreateInput,
assertEquipmentMaintenanceInput,
assertEquipmentStatusInput,
} from './equipment-input-validation';
@Injectable()
export class EquipmentService {
constructor(private readonly database:DatabaseService) {}
async create(input:unknown) {
assertEquipmentCreateInput(input);
const id=randomUUID();
await this.database.query(
`insert into equipment(
id,organization_id,location_id,name,equipment_type,manufacturer,model,
serial_number,status,area_id,installed_at,notes
) values($1,$2,$3,$4,$5,$6,$7,$8,'active',$9,$10::date,$11)`,
[id,input.organizationId,input.locationId,input.name,input.equipmentType,input.manufacturer??null,input.model??null,input.serialNumber??null,input.areaId??null,input.installedAt??null,input.notes??null],
);
return {id,status:'active'};
}
async setStatus(input:unknown) {
assertEquipmentStatusInput(input);
const rows=await this.database.query<any>(
`update equipment set status=$1,updated_at=now(),version=version+1
where id=$2 and organization_id=$3 and location_id=$4 and status<>'retired'
returning id,status`,
[input.status,input.equipmentId,input.organizationId,input.locationId],
);
if(!rows[0]) throw new DomainConflictError('equipment.status_invalid');
return rows[0];
}
async addMaintenance(input:unknown) {
assertEquipmentMaintenanceInput(input);
const id=randomUUID();
const rows=await this.database.query<any>(
`insert into maintenance_records(
id,equipment_id,maintenance_type,description,performed_at,performed_by,
next_due_at
)
select $1,e.id,$2,$3,coalesce($4::timestamptz,now()),$5,$6
from equipment e
where e.id=$7 and e.organization_id=$8 and e.location_id=$9
returning id`,
[id,input.maintenanceType,input.description,input.performedAt??null,input.employeeId??null,input.dueAt??null,input.equipmentId,input.organizationId,input.locationId],
);
if(!rows[0]) throw new DomainConflictError('equipment.maintenance_invalid');
return {id};
}
}
