diff --git a/apps/api/src/modules/industrial/application/queries/get-industrial-parks-by-bbox/get-industrial-parks-by-bbox.handler.ts b/apps/api/src/modules/industrial/application/queries/get-industrial-parks-by-bbox/get-industrial-parks-by-bbox.handler.ts index ffea1c5..e73c20c 100644 --- a/apps/api/src/modules/industrial/application/queries/get-industrial-parks-by-bbox/get-industrial-parks-by-bbox.handler.ts +++ b/apps/api/src/modules/industrial/application/queries/get-industrial-parks-by-bbox/get-industrial-parks-by-bbox.handler.ts @@ -47,11 +47,17 @@ export class GetIndustrialParksByBboxHandler const { south, west, north, east } = q.bbox; const includeBoundary = q.zoom >= BOUNDARY_ZOOM; const limit = Math.min(Math.max(q.limit, 1), 5000); - // Filter out raw OSM imports for public consumers; admins pass - // includeOsmRaw=true to see them. - const dataSourceFilter = q.includeOsmRaw - ? `'MANUAL', 'OSM', 'OSM_PROMOTED'` - : `'MANUAL', 'OSM_PROMOTED'`; + // Visibility logic: + // - Public callers: only `isPublic = true` rows (MANUAL + OSM_PROMOTED). + // - Admin callers (`includeOsmRaw=true`): also include OSM raw rows + // regardless of `isPublic`, so the admin map can preview the + // review queue. Other rows still respect `isPublic`. + const visibilityClause = q.includeOsmRaw + ? `( + ("isPublic" = true AND "dataSource"::text IN ('MANUAL', 'OSM_PROMOTED')) + OR "dataSource"::text = 'OSM' + )` + : `("isPublic" = true AND "dataSource"::text IN ('MANUAL', 'OSM_PROMOTED'))`; // Single PostGIS query: bbox filter + optional polygon column. // && is the bbox-intersect operator and uses the GiST index. @@ -70,8 +76,7 @@ export class GetIndustrialParksByBboxHandler ST_AsGeoJSON(location) AS point, ${includeBoundary ? `ST_AsGeoJSON(boundary)` : `NULL::text`} AS polygon FROM "IndustrialPark" - WHERE "isPublic" = true - AND "dataSource"::text IN (${dataSourceFilter}) + WHERE ${visibilityClause} AND location && ST_MakeEnvelope($1, $2, $3, $4, 4326) ORDER BY "totalAreaHa" DESC NULLS LAST LIMIT ${limit + 1}