Skip to content

Commit 9d6a435

Browse files
simonkroppjohanneskarlsson
authored andcommitted
add buildings/by-property-code endpoint to core including tests
1 parent 19386c2 commit 9d6a435

File tree

5 files changed

+171
-10
lines changed

5 files changed

+171
-10
lines changed

core/src/adapters/property-base-adapter/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,27 @@ export async function getFacilityByRentalId(
423423
}
424424
}
425425

426+
type GetBuildingsResponse = components['schemas']['Building'][]
427+
428+
export async function getBuildings(
429+
propertyCode: string
430+
): Promise<AdapterResult<GetBuildingsResponse, unknown>> {
431+
try {
432+
const fetchResponse = await client().GET('/buildings', {
433+
params: { query: { propertyCode } },
434+
})
435+
436+
if (fetchResponse.data?.content) {
437+
return { ok: true, data: fetchResponse.data.content }
438+
}
439+
440+
return { ok: false, err: 'unknown' }
441+
} catch (err) {
442+
logger.error({ err }, '@onecore/property-adapter.getBuildings')
443+
return { ok: false, err }
444+
}
445+
}
446+
426447
type GetMaintenanceUnitsByPropertyCodeResponse =
427448
components['schemas']['MaintenanceUnit'][]
428449

core/src/adapters/tests/property-base-adapter.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,43 @@ describe('@onecore/property-adapter', () => {
612612
})
613613
})
614614

615+
describe('getBuildings', () => {
616+
it('returns err if request fails', async () => {
617+
mockServer.use(
618+
http.get(
619+
`${config.propertyBaseService.url}/buildings`,
620+
() => new HttpResponse(null, { status: 500 })
621+
)
622+
)
623+
624+
const result = await propertyBaseAdapter.getBuildings('001-001')
625+
626+
expect(result.ok).toBe(false)
627+
if (!result.ok) expect(result.err).toBe('unknown')
628+
})
629+
630+
it('returns buildings', async () => {
631+
const buildingsMock = factory.building.buildList(3)
632+
mockServer.use(
633+
http.get(`${config.propertyBaseService.url}/buildings`, () =>
634+
HttpResponse.json(
635+
{
636+
content: buildingsMock,
637+
},
638+
{ status: 200 }
639+
)
640+
)
641+
)
642+
643+
const result = await propertyBaseAdapter.getBuildings('001-001')
644+
645+
expect(result).toMatchObject({
646+
ok: true,
647+
data: buildingsMock,
648+
})
649+
})
650+
})
651+
615652
describe('getMaintenanceUnitsByPropertyCode', () => {
616653
it('returns maintenance units for a property', async () => {
617654
const maintenanceUnitsMock = factory.maintenanceUnitInfo.buildList(3)

core/src/services/property-base-service/index.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,74 @@ export const routes = (router: KoaRouter) => {
121121

122122
/**
123123
* @swagger
124-
* /companies:
124+
* /propertyBase/buildings/by-property-code/{propertyCode}:
125+
* get:
126+
* summary: Get buildings by property code
127+
* tags:
128+
* - Property base Service
129+
* description: Retrieves buildings by property code
130+
* parameters:
131+
* - in: path
132+
* name: propertyCode
133+
* required: true
134+
* schema:
135+
* type: string
136+
* description: The code of the property to fetch buildings for
137+
* responses:
138+
* '200':
139+
* description: Successfully retrieved buildings
140+
* content:
141+
* application/json:
142+
* schema:
143+
* type: object
144+
* properties:
145+
* content:
146+
* type: array
147+
* items:
148+
* $ref: '#/components/schemas/Building'
149+
* '500':
150+
* description: Internal server error
151+
* content:
152+
* application/json:
153+
* schema:
154+
* type: object
155+
* properties:
156+
* error:
157+
* type: string
158+
* example: Internal server error
159+
* security:
160+
* - bearerAuth: []
161+
*/
162+
router.get(
163+
'(.*)/propertyBase/buildings/by-property-code/:propertyCode',
164+
async (ctx) => {
165+
const metadata = generateRouteMetadata(ctx)
166+
const { propertyCode } = ctx.params
167+
168+
try {
169+
const result = await propertyBaseAdapter.getBuildings(propertyCode)
170+
if (!result.ok) {
171+
logger.error(result.err, 'Internal server error', metadata)
172+
ctx.status = 500
173+
ctx.body = { error: 'Internal server error', ...metadata }
174+
return
175+
}
176+
177+
ctx.body = {
178+
content: result.data satisfies schemas.Building[],
179+
...metadata,
180+
}
181+
} catch (error) {
182+
logger.error(error, 'Internal server error', metadata)
183+
ctx.status = 500
184+
ctx.body = { error: 'Internal server error', ...metadata }
185+
}
186+
}
187+
)
188+
189+
/**
190+
* @swagger
191+
* /propertyBase/companies:
125192
* get:
126193
* summary: Get all companies
127194
* tags:

core/src/services/property-base-service/schemas.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ import { z } from 'zod'
33
export const BuildingSchema = z.object({
44
id: z.string(),
55
code: z.string(),
6-
name: z.string(),
6+
name: z.string().nullable(),
77
buildingType: z.object({
8-
id: z.string(),
9-
code: z.string(),
10-
name: z.string(),
8+
id: z.string().nullable(),
9+
code: z.string().nullable(),
10+
name: z.string().nullable(),
1111
}),
1212
construction: z.object({
13-
constructionYear: z.number(),
14-
renovationYear: z.number(),
13+
constructionYear: z.number().nullable(),
14+
renovationYear: z.number().nullable(),
1515
valueYear: z.number().nullable(),
1616
}),
1717
features: z.object({
18-
heating: z.string().nullable(),
19-
fireRating: z.string().nullable(),
18+
heating: z.string().nullable().optional(),
19+
fireRating: z.string().nullable().optional(),
2020
}),
2121
insurance: z.object({
2222
class: z.string().nullable(),

core/src/services/property-base-service/tests/index.test.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import * as leasingAdapter from '../../../adapters/leasing-adapter'
1010

1111
import * as factory from '../../../../test/factories'
1212
import {
13+
BuildingSchema,
1314
CompanySchema,
1415
PropertySchema,
1516
ResidenceSchema,
@@ -74,7 +75,42 @@ describe('@onecore/property-service', () => {
7475
})
7576
})
7677

77-
describe('GET /property/companies', () => {
78+
describe('GET /propertyBase/buildings/by-property-code/:propertyCode', () => {
79+
it('returns 200 and a list of buildings', async () => {
80+
const buildingsMock = factory.building.buildList(3)
81+
const getBuildingsSpy = jest
82+
.spyOn(propertyBaseAdapter, 'getBuildings')
83+
.mockResolvedValueOnce({ ok: true, data: buildingsMock })
84+
85+
const res = await request(app.callback()).get(
86+
'/propertyBase/buildings/by-property-code/001-001'
87+
)
88+
89+
expect(res.status).toBe(200)
90+
expect(getBuildingsSpy).toHaveBeenCalledWith('001-001')
91+
expect(JSON.stringify(res.body.content)).toEqual(
92+
JSON.stringify(buildingsMock)
93+
)
94+
expect(() =>
95+
z.array(BuildingSchema).parse(res.body.content)
96+
).not.toThrow()
97+
})
98+
99+
it('returns 500 if no buildings can be retrieved', async () => {
100+
const getBuildingsSpy = jest
101+
.spyOn(propertyBaseAdapter, 'getBuildings')
102+
.mockResolvedValueOnce({ ok: false, err: 'unknown' })
103+
104+
const res = await request(app.callback()).get(
105+
'/propertyBase/buildings/by-property-code/001-001'
106+
)
107+
108+
expect(res.status).toBe(500)
109+
expect(getBuildingsSpy).toHaveBeenCalledWith('001-001')
110+
})
111+
})
112+
113+
describe('GET /propertyBase/companies', () => {
78114
it('returns 200 and a list of companies', async () => {
79115
const companiesMock = factory.company.buildList(3)
80116
const getCompaniesSpy = jest

0 commit comments

Comments
 (0)