import { Injectable } from '@nestjs/common';
import { DatabaseService } from '../../../infrastructure/database/database.service';
/**
* Organization-scoped, read-only evidence for the Hotel F&B outlet network.
* Organization units and locations remain canonical; this projection never
* creates a second property, outlet, guest or PMS truth model.
*/
@Injectable()
export class HotelOutletNetworkService {
constructor(private readonly database: DatabaseService) {}
async overview(input: { organizationId: string }) {
const [locations, units] = await Promise.all([
this.database.query<any>(
`select l.id as location_id,
l.name as location_name,
l.code as location_code,
ou.id as organization_unit_id,
ou.name as organization_unit_name,
ou.unit_type as organization_unit_type
from locations l
left join organization_units ou on ou.id=l.organization_unit_id
where l.organization_id=$1 and l.status='active'
and (ou.id is null or ou.status='active')
order by coalesce(ou.name,''), l.name, l.id`,
[input.organizationId],
),
this.database.query<any>(
`select ou.location_id,
count(*)::int as active_unit_count,
coalesce(
jsonb_agg(
jsonb_build_object(
'id', ou.id,
'name', ou.name,
'code', ou.code,
'archetype', ou.archetype
) order by ou.name, ou.id
),
'[]'::jsonb
) as operational_units
from operational_units ou
where ou.organization_id=$1 and ou.status='active'
group by ou.location_id`,
[input.organizationId],
),
]);
const unitsByLocation = new Map<string, any>();
for (const row of units) unitsByLocation.set(row.location_id, row);
return {
locations: locations.map((location: any) => {
const unit = unitsByLocation.get(location.location_id);
return {
...location,
active_unit_count: unit?.active_unit_count ?? 0,
operational_units: unit?.operational_units ?? [],
};
}),
};
}
}
