Skip to content

Commit 096daf2

Browse files
mittistormenlalmqvist
authored andcommitted
Feat/uth 236 get all parking space listings from one core (#35)
* Feat: UTH-236 Get All Parking Space Listings From OneCore Added missing functionality to filter result based on a ContactCode. Scored/internal Listings where the user doesn't have a housing contract is filtered out.
1 parent e786f93 commit 096daf2

File tree

4 files changed

+151
-14
lines changed

4 files changed

+151
-14
lines changed

core/src/adapters/leasing-adapter/listings.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@ type GetListingsParams = {
208208
listingCategory?: 'PARKING_SPACE' | 'APARTMENT' | 'STORAGE'
209209
published?: boolean
210210
rentalRule?: 'SCORED' | 'NON_SCORED'
211-
validToRentForContactCode?: string
212211
}
213212

214213
const getListings = async (
@@ -220,11 +219,6 @@ const getListings = async (
220219
if (params.published !== undefined)
221220
queryParams.append('published', params.published.toString())
222221
if (params.rentalRule) queryParams.append('rentalRule', params.rentalRule)
223-
if (params.validToRentForContactCode)
224-
queryParams.append(
225-
'validToRentForContactCode',
226-
params.validToRentForContactCode
227-
)
228222

229223
try {
230224
const response = await axios.get(
@@ -233,17 +227,21 @@ const getListings = async (
233227

234228
if (response.status !== 200) {
235229
logger.error(
236-
{ status: response.status, data: response.data },
237-
`Error getting listings from leasing, by: published ${params.published}, rentalRule ${params.rentalRule} and validToRentForContactCode ${params.validToRentForContactCode}`
230+
{
231+
status: response.status,
232+
data: response.data,
233+
query: queryParams.toString(),
234+
},
235+
`Error getting listings from leasing`
238236
)
239237
return { ok: false, err: 'unknown' }
240238
}
241239

242240
return { ok: true, data: response.data.content }
243241
} catch (error) {
244242
logger.error(
245-
error,
246-
`Unknown error fetching listings by published ${params.published}, rentalRule ${params.rentalRule} and validToRentForContactCode ${params.validToRentForContactCode}`
243+
{ error: error, queryParams: queryParams.toString() },
244+
`Unknown error fetching listings by published`
247245
)
248246
return { ok: false, err: 'unknown' }
249247
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Tenant } from '@onecore/types'
2+
3+
export const isTenantAllowedToRentAParkingSpaceInThisResidentialArea = (
4+
residentialAreaCode: string,
5+
tenant: Tenant
6+
) => {
7+
if (
8+
tenant.upcomingHousingContract &&
9+
tenant.upcomingHousingContract.residentialArea?.code === residentialAreaCode
10+
) {
11+
return true
12+
}
13+
14+
if (
15+
tenant.currentHousingContract &&
16+
tenant.currentHousingContract.residentialArea?.code === residentialAreaCode
17+
) {
18+
return true
19+
}
20+
}

core/src/services/lease-service/listings.ts

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { z } from 'zod'
1313
import * as leasingAdapter from '../../adapters/leasing-adapter'
1414
import * as internalParkingSpaceProcesses from '../../processes/parkingspaces/internal'
1515
import { ProcessStatus } from '../../common/types'
16+
import { isTenantAllowedToRentAParkingSpaceInThisResidentialArea } from './helpers/lease'
1617

1718
export const routes = (router: KoaRouter) => {
1819
/**
@@ -75,11 +76,12 @@ export const routes = (router: KoaRouter) => {
7576
})
7677
const query = querySchema.safeParse(ctx.query)
7778

79+
logger.debug({ query }, 'Parsed query parameters for GET /listings')
80+
7881
const result = await leasingAdapter.getListings({
7982
listingCategory: query.data?.listingCategory,
8083
published: query.data?.published,
8184
rentalRule: query.data?.rentalRule,
82-
validToRentForContactCode: query.data?.validToRentForContactCode,
8385
})
8486

8587
if (!result.ok) {
@@ -114,8 +116,58 @@ export const routes = (router: KoaRouter) => {
114116
})
115117
.filter((item): item is Listing => !!item)
116118

117-
ctx.status = 200
118-
ctx.body = { content: listingsWithRentalObjects, ...metadata }
119+
logger.info(
120+
{
121+
numberOfListings: listingsWithRentalObjects.length,
122+
},
123+
'Listings Retrieved from Leasing GET /listings'
124+
)
125+
126+
if (!query.data?.validToRentForContactCode) {
127+
ctx.status = 200
128+
ctx.body = { content: listingsWithRentalObjects, ...metadata }
129+
} else {
130+
//filter listings on validToRentForContactCode
131+
const tenantResult = await leasingAdapter.getTenantByContactCode(
132+
query.data?.validToRentForContactCode
133+
)
134+
let isTenant = true
135+
136+
if (!tenantResult.ok) {
137+
if (tenantResult.err === 'contact-not-tenant') {
138+
isTenant = false
139+
} else {
140+
ctx.status = 500
141+
ctx.body = { error: 'Tenant could not be retrieved', ...metadata }
142+
return
143+
}
144+
}
145+
146+
var listings = listingsWithRentalObjects.filter((listing) => {
147+
return (
148+
listing.rentalRule == 'NON_SCORED' || //all NON_SCORED will be included
149+
(listing.rentalRule == 'SCORED' &&
150+
isTenant &&
151+
tenantResult.ok &&
152+
listing.rentalObject.residentialAreaCode &&
153+
isTenantAllowedToRentAParkingSpaceInThisResidentialArea(
154+
listing.rentalObject.residentialAreaCode,
155+
tenantResult.data
156+
)) // all SCORED where tenant is allowed to rent will be included
157+
)
158+
})
159+
160+
logger.debug(
161+
{
162+
numberOfListings: listings.length,
163+
contactCode: query.data?.validToRentForContactCode,
164+
},
165+
'Listings filtered on contact GET /listings'
166+
)
167+
168+
ctx.status = 200
169+
ctx.body = { content: listings, ...metadata }
170+
}
119171
} catch (error) {
120172
logger.error(error, 'Error fetching listings with rental objects')
121173
ctx.status = 500

core/src/services/lease-service/tests/listings.test.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ describe('GET /listings', () => {
103103
})
104104
const parkingSpace = factory.vacantParkingSpace.build({
105105
rentalObjectCode: '12345',
106+
residentialAreaCode: 'AREA123',
106107
})
107108

108109
const getListingsSpy = jest
@@ -113,17 +114,83 @@ describe('GET /listings', () => {
113114
.spyOn(tenantLeaseAdapter, 'getParkingSpaces')
114115
.mockResolvedValueOnce({ ok: true, data: [parkingSpace] })
115116

117+
jest
118+
.spyOn(tenantLeaseAdapter, 'getTenantByContactCode')
119+
.mockResolvedValueOnce({
120+
ok: true,
121+
data: factory.tenant.build({
122+
currentHousingContract: { residentialArea: { code: 'AREA123' } },
123+
}),
124+
})
125+
116126
const res = await request(app.callback()).get(
117127
'/listings?validToRentForContactCode=abc123'
118128
)
119129

120130
expect(getListingsSpy).toHaveBeenCalledWith({
121-
validToRentForContactCode: 'abc123',
131+
listingCategory: undefined,
132+
published: undefined,
133+
rentalRule: undefined,
134+
})
135+
expect(res.status).toBe(200)
136+
expect(res.body).toEqual({
137+
content: [expect.objectContaining({ id: 1337 })],
138+
})
139+
})
140+
141+
it('responds with a filtered list with filter on validToRentForContactCode', async () => {
142+
const listings = [
143+
factory.listing.build({
144+
id: 1337,
145+
rentalObjectCode: '12345',
146+
}),
147+
factory.listing.build({
148+
id: 1339,
149+
rentalObjectCode: '32345',
150+
}),
151+
]
152+
const parkingSpaces = [
153+
factory.vacantParkingSpace.build({
154+
rentalObjectCode: '12345',
155+
residentialAreaCode: 'AREA123',
156+
}),
157+
factory.vacantParkingSpace.build({
158+
rentalObjectCode: '32345',
159+
residentialAreaCode: 'ANOTHER_AREA',
160+
}),
161+
]
162+
163+
const getListingsSpy = jest
164+
.spyOn(tenantLeaseAdapter, 'getListings')
165+
.mockResolvedValueOnce({ ok: true, data: listings })
166+
167+
jest
168+
.spyOn(tenantLeaseAdapter, 'getParkingSpaces')
169+
.mockResolvedValueOnce({ ok: true, data: parkingSpaces })
170+
171+
jest
172+
.spyOn(tenantLeaseAdapter, 'getTenantByContactCode')
173+
.mockResolvedValueOnce({
174+
ok: true,
175+
data: factory.tenant.build({
176+
currentHousingContract: { residentialArea: { code: 'AREA123' } },
177+
}),
178+
})
179+
180+
const res = await request(app.callback()).get(
181+
'/listings?validToRentForContactCode=abc123'
182+
)
183+
184+
expect(getListingsSpy).toHaveBeenCalledWith({
185+
listingCategory: undefined,
186+
published: undefined,
187+
rentalRule: undefined,
122188
})
123189
expect(res.status).toBe(200)
124190
expect(res.body).toEqual({
125191
content: [expect.objectContaining({ id: 1337 })],
126192
})
193+
expect(res.body.content).toHaveLength(1)
127194
})
128195

129196
it('responds with 500 on error', async () => {

0 commit comments

Comments
 (0)