117 lines
4.7 KiB
TypeScript
117 lines
4.7 KiB
TypeScript
import { BadRequestException, Injectable } from '@nestjs/common';
|
|
import { DataSource } from 'typeorm';
|
|
|
|
export interface InspectionPlanningHierarchyItem {
|
|
id: string;
|
|
code: string;
|
|
name: string;
|
|
}
|
|
|
|
@Injectable()
|
|
export class InspectionPlanningHierarchyService {
|
|
constructor(private readonly dataSource: DataSource) {}
|
|
|
|
async departments(): Promise<{ data: InspectionPlanningHierarchyItem[] }> {
|
|
const data = await this.dataSource.query(`
|
|
SELECT department.id, department.code, department.name
|
|
FROM assets department
|
|
INNER JOIN asset_types type ON type.id=department.asset_type_id
|
|
WHERE lower(type.code)='departamento'
|
|
AND type.is_active=true
|
|
AND department.information_status<>'INACTIVE'
|
|
AND EXISTS (
|
|
SELECT 1
|
|
FROM assets area
|
|
INNER JOIN asset_types area_type ON area_type.id=area.asset_type_id
|
|
WHERE area.parent_id=department.id
|
|
AND lower(area_type.code)='area'
|
|
AND area.information_status<>'INACTIVE'
|
|
)
|
|
ORDER BY department.name, department.code
|
|
`) as InspectionPlanningHierarchyItem[];
|
|
return { data };
|
|
}
|
|
|
|
async areasForDepartment(departmentId: string): Promise<{ data: InspectionPlanningHierarchyItem[] }> {
|
|
await this.requireType(departmentId, 'departamento', 'El Departamento seleccionado no es válido');
|
|
const data = await this.dataSource.query(`
|
|
SELECT area.id, area.code, area.name
|
|
FROM assets area
|
|
INNER JOIN asset_types type ON type.id=area.asset_type_id
|
|
WHERE area.parent_id=$1::uuid
|
|
AND lower(type.code)='area'
|
|
AND type.is_active=true
|
|
AND area.information_status<>'INACTIVE'
|
|
ORDER BY area.name, area.code
|
|
`, [departmentId]) as InspectionPlanningHierarchyItem[];
|
|
return { data };
|
|
}
|
|
|
|
async yacimientosForArea(areaId: string): Promise<{ data: InspectionPlanningHierarchyItem[] }> {
|
|
await this.requireType(areaId, 'area', 'El Área seleccionada no es válida');
|
|
const data = await this.dataSource.query(`
|
|
SELECT yacimiento.id, yacimiento.code, yacimiento.name
|
|
FROM assets yacimiento
|
|
INNER JOIN asset_types type ON type.id=yacimiento.asset_type_id
|
|
WHERE yacimiento.parent_id=$1::uuid
|
|
AND lower(type.code)='yacimiento'
|
|
AND type.is_active=true
|
|
AND yacimiento.information_status<>'INACTIVE'
|
|
ORDER BY yacimiento.name, yacimiento.code
|
|
`, [areaId]) as InspectionPlanningHierarchyItem[];
|
|
return { data };
|
|
}
|
|
|
|
async operatorsForArea(
|
|
areaId: string,
|
|
at?: string,
|
|
): Promise<{ data: InspectionPlanningHierarchyItem[] }> {
|
|
await this.requireType(areaId, 'area', 'El Área seleccionada no es válida');
|
|
if (at) {
|
|
const effectiveAt = new Date(at);
|
|
if (!Number.isFinite(effectiveAt.getTime())) {
|
|
throw new BadRequestException({
|
|
code: 'INSPECTION_PLANNING_DATE_INVALID',
|
|
message: 'La fecha de planificación no es válida',
|
|
});
|
|
}
|
|
}
|
|
// Modelo autoritativo: la Empresa pertenece al Yacimiento. Para mantener el
|
|
// selector de planificación por Área, se proyectan las Empresas de todos los
|
|
// Yacimientos activos que pertenecen a esa Área.
|
|
const data = await this.dataSource.query(`
|
|
SELECT DISTINCT company.id, company.code, COALESCE(profile.legal_name,company.name) AS name
|
|
FROM assets yacimiento
|
|
INNER JOIN asset_types yacimiento_type ON yacimiento_type.id=yacimiento.asset_type_id
|
|
INNER JOIN assets company ON company.id=yacimiento.operator_company_id
|
|
INNER JOIN asset_types company_type ON company_type.id=company.asset_type_id
|
|
LEFT JOIN organization_profiles profile ON profile.asset_id=company.id
|
|
WHERE yacimiento.parent_id=$1::uuid
|
|
AND lower(yacimiento_type.code)='yacimiento'
|
|
AND yacimiento_type.is_active=true
|
|
AND yacimiento.information_status<>'INACTIVE'
|
|
AND company_type.operational_role='COMPANY'
|
|
AND company_type.is_active=true
|
|
AND company.information_status<>'INACTIVE'
|
|
ORDER BY name, company.code
|
|
`, [areaId]) as InspectionPlanningHierarchyItem[];
|
|
return { data };
|
|
}
|
|
|
|
private async requireType(id: string, typeCode: string, message: string): Promise<void> {
|
|
const [row] = await this.dataSource.query(`
|
|
SELECT 1
|
|
FROM assets asset
|
|
INNER JOIN asset_types type ON type.id=asset.asset_type_id
|
|
WHERE asset.id=$1::uuid
|
|
AND lower(type.code)=lower($2)
|
|
AND type.is_active=true
|
|
AND asset.information_status<>'INACTIVE'
|
|
LIMIT 1
|
|
`, [id, typeCode]) as Array<{ '?column?': number }>;
|
|
if (!row) {
|
|
throw new BadRequestException({ code: 'INSPECTION_PLANNING_HIERARCHY_INVALID', message });
|
|
}
|
|
}
|
|
}
|