Skip to content

Commit 54a8998

Browse files
authored
Merge pull request #41 from Bostads-AB-Mimer/feature/mim-608-hamta-byggnader-pa-fastighetskod-endpoint-i-core
MIM-608: Fetch building on property code in core
2 parents 0e784c4 + 407b60d commit 54a8998

File tree

5 files changed

+175
-8
lines changed

5 files changed

+175
-8
lines changed

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

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

426+
type GetBuildingsResponse = components['schemas']['Building'][]
427+
428+
export async function getBuildingsByPropertyCode(
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(
443+
{ err },
444+
'@onecore/property-adapter.getBuildingsByPropertyCode'
445+
)
446+
return { ok: false, err }
447+
}
448+
}
449+
426450
type GetMaintenanceUnitsByPropertyCodeResponse =
427451
components['schemas']['MaintenanceUnit'][]
428452

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,45 @@ describe('@onecore/property-adapter', () => {
614614
})
615615
})
616616

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

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

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,74 @@ export const routes = (router: KoaRouter) => {
122122
}
123123
)
124124

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

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: 36 additions & 0 deletions
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,6 +75,41 @@ describe('@onecore/property-service', () => {
7475
})
7576
})
7677

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, 'getBuildingsByPropertyCode')
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, 'getBuildingsByPropertyCode')
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+
77113
describe('GET /propertyBase/companies', () => {
78114
it('returns 200 and a list of companies', async () => {
79115
const companiesMock = factory.company.buildList(3)

0 commit comments

Comments
 (0)