Skip to content

Commit 07d8009

Browse files
authored
Merge pull request #77 from Bostads-AB-Mimer/feature/mim-572-skapa-endpoint-for-att-hamta-byggnad
MIM-572: Create endpoint to get building by code
2 parents 67c6cd1 + c4c2a34 commit 07d8009

File tree

6 files changed

+2463
-2349
lines changed

6 files changed

+2463
-2349
lines changed

packages/property-base/src/adapters/building-adapter.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,29 @@ const getBuildingById = async (
8181
.then(trimStrings)
8282
}
8383

84+
const getBuildingByCode = async (
85+
code: string
86+
): Promise<BuildingWithRelations | null> => {
87+
return prisma.building
88+
.findFirst({
89+
where: {
90+
buildingCode: code,
91+
},
92+
include: {
93+
buildingType: true,
94+
marketArea: true,
95+
propertyDesignation: true,
96+
district: true,
97+
propertyObject: {
98+
include: {
99+
property: true,
100+
},
101+
},
102+
},
103+
})
104+
.then(trimStrings)
105+
}
106+
84107
/**
85108
* Searches buildings by name
86109
* At the moment this function has an "under investigation" approach to fetchin
@@ -168,4 +191,4 @@ const searchBuildings = async (
168191
}
169192
}
170193

171-
export { getBuildings, getBuildingById, searchBuildings }
194+
export { getBuildings, getBuildingById, getBuildingByCode, searchBuildings }

packages/property-base/src/routes/buildings-route.ts

Lines changed: 66 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ import { logger, generateRouteMetadata } from 'onecore-utilities'
88
import { z } from 'zod'
99

1010
import {
11+
getBuildingByCode,
1112
getBuildingById,
1213
getBuildings,
1314
searchBuildings,
1415
} from '../adapters/building-adapter'
1516
import { buildingsQueryParamsSchema, BuildingSchema } from '../types/building'
1617
import { parseRequest } from '../middleware/parse-request'
18+
import { transformBuildingData } from '../utils/buildings'
1719

1820
/**
1921
* @swagger
@@ -73,30 +75,9 @@ export const routes = (router: KoaRouter) => {
7375
const buildings = await getBuildings(propertyCode)
7476

7577
const responseContent = buildings.map((building) => {
76-
const parsedBuilding = BuildingSchema.parse({
77-
id: building.id,
78-
code: building.buildingCode,
79-
name: building.name || '',
80-
buildingType: {
81-
id: building.buildingType?.id || '',
82-
code: building.buildingType?.code || '',
83-
name: building.buildingType?.name || '',
84-
},
85-
construction: {
86-
constructionYear: building.constructionYear,
87-
renovationYear: building.renovationYear,
88-
valueYear: building.valueYear,
89-
},
90-
features: {
91-
heating: building.heating || '',
92-
fireRating: building.fireRating || '',
93-
},
94-
insurance: {
95-
class: building.insuranceClass,
96-
value: building.insuranceValue,
97-
},
98-
deleted: Boolean(building.deleteMark),
99-
})
78+
const parsedBuilding = BuildingSchema.parse(
79+
transformBuildingData(building)
80+
)
10081

10182
return parsedBuilding
10283
})
@@ -202,6 +183,65 @@ export const routes = (router: KoaRouter) => {
202183
}
203184
)
204185

186+
/**
187+
* @swagger
188+
* /buildings/by-building-code/{buildingCode}:
189+
* get:
190+
* summary: Get detailed information about a specific building by building code
191+
* description: |
192+
* Retrieves comprehensive information about a building using its building code.
193+
* Returns details including construction year, renovation history, insurance information,
194+
* and associated property data.
195+
* tags:
196+
* - Buildings
197+
* parameters:
198+
* - in: path
199+
* name: buildingCode
200+
* required: true
201+
* schema:
202+
* type: string
203+
* description: The building code of the building
204+
* responses:
205+
* 200:
206+
* description: Successfully retrieved building information
207+
* content:
208+
* application/json:
209+
* schema:
210+
* type: object
211+
* properties:
212+
* content:
213+
* $ref: '#/components/schemas/Building'
214+
* 404:
215+
* description: Building not found
216+
* 500:
217+
* description: Internal server error
218+
*/
219+
router.get('(.*)/buildings/by-building-code/:buildingCode', async (ctx) => {
220+
const metadata = generateRouteMetadata(ctx)
221+
const buildingCode = ctx.params.buildingCode
222+
logger.info(`GET /buildings/by-building-code/${buildingCode}`, metadata)
223+
224+
try {
225+
const building = await getBuildingByCode(buildingCode)
226+
227+
if (!building) {
228+
ctx.status = 404
229+
return
230+
}
231+
232+
const transformedData = transformBuildingData(building)
233+
234+
ctx.body = {
235+
content: BuildingSchema.parse(transformedData),
236+
...metadata,
237+
}
238+
} catch (err) {
239+
ctx.status = 500
240+
const errorMessage = err instanceof Error ? err.message : 'unknown error'
241+
ctx.body = { reason: errorMessage, ...metadata }
242+
}
243+
})
244+
205245
/**
206246
* @swagger
207247
* /buildings/{id}:
@@ -249,33 +289,10 @@ export const routes = (router: KoaRouter) => {
249289
return
250290
}
251291

252-
const parsedBuilding = BuildingSchema.parse({
253-
id: building.id,
254-
code: building.buildingCode,
255-
name: building.name || '',
256-
buildingType: {
257-
id: building.buildingType?.id || '',
258-
code: building.buildingType?.code || '',
259-
name: building.buildingType?.name || '',
260-
},
261-
construction: {
262-
constructionYear: building.constructionYear,
263-
renovationYear: building.renovationYear,
264-
valueYear: building.valueYear,
265-
},
266-
features: {
267-
heating: building.heating,
268-
fireRating: building.fireRating,
269-
},
270-
insurance: {
271-
class: building.insuranceClass,
272-
value: building.insuranceValue,
273-
},
274-
deleted: Boolean(building.deleteMark),
275-
})
292+
const transformedData = transformBuildingData(building)
276293

277294
ctx.body = {
278-
content: parsedBuilding,
295+
content: BuildingSchema.parse(transformedData),
279296
...metadata,
280297
}
281298
} catch (err) {

packages/property-base/src/types/building.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ export const buildingsQueryParamsSchema = z.object({
99
export const BuildingSchema = z.object({
1010
id: z.string(),
1111
code: z.string(),
12-
name: z.string(),
12+
name: z.string().nullable(),
1313
buildingType: z.object({
14-
id: z.string(),
15-
code: z.string(),
16-
name: z.string(),
14+
id: z.string().nullable(),
15+
code: z.string().nullable(),
16+
name: z.string().nullable(),
1717
}),
1818
construction: z.object({
1919
constructionYear: z.number().nullable(),
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { BuildingWithRelations } from '@src/adapters/building-adapter'
2+
import { Building } from '@src/types/building'
3+
4+
/**
5+
* Transforms a building entity with relations into a normalized building data object.
6+
*
7+
* @param building - The building entity with all its related data
8+
* @returns A transformed building object with normalized structure containing:
9+
* - Basic info (id, code, name)
10+
* - Building type details (id, code, name)
11+
* - Construction information (construction year, renovation year, value year)
12+
* - Building features (heating, fire rating)
13+
* - Insurance details (class, value)
14+
* - Deletion status
15+
*/
16+
export function transformBuildingData(
17+
building: BuildingWithRelations
18+
): Building {
19+
return {
20+
id: building.id,
21+
code: building.buildingCode,
22+
name: building.name || null,
23+
buildingType: {
24+
id: building.buildingType?.id || null,
25+
code: building.buildingType?.code || null,
26+
name: building.buildingType?.name || null,
27+
},
28+
construction: {
29+
constructionYear: building.constructionYear,
30+
renovationYear: building.renovationYear,
31+
valueYear: building.valueYear,
32+
},
33+
features: {
34+
heating: building.heating || null,
35+
fireRating: building.fireRating || null,
36+
},
37+
insurance: {
38+
class: building.insuranceClass,
39+
value: building.insuranceValue,
40+
},
41+
deleted: Boolean(building.deleteMark),
42+
}
43+
}

0 commit comments

Comments
 (0)