Skip to content

Commit

Permalink
feat(condo): DOMA-7262 skip discovering if user has 7+ residents in p…
Browse files Browse the repository at this point in the history
…roperty (#4347)

* feat(condo): DOMA-7262 skip discovering if user has 7+ residents in property

* feat(condo): DOMA-7262 fix typos and fix residents query

* feat(condo): DOMA-7262 fix typo
  • Loading branch information
AleX83Xpert authored Feb 7, 2024
1 parent 5c04462 commit c422e4e
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const { Property } = require('@condo/domains/property/utils/serverSchema')
const access = require('@condo/domains/resident/access/DiscoverServiceConsumersService')
const { Resident, ServiceConsumer } = require('@condo/domains/resident/utils/serverSchema')

const MAX_RESIDENTS_COUNT_FOR_USER_PROPERTY = 6

const logger = getLogger('DiscoverServiceConsumersMutation')

/**
Expand Down Expand Up @@ -433,7 +435,7 @@ const DiscoverServiceConsumersService = new GQLCustomSchema('DiscoverServiceCons

const definedCombinations = combinations.filter(Boolean)

const serviceConsumersData = definedCombinations.map(([resident, account]) => {
let serviceConsumersData = definedCombinations.map(([resident, account]) => {
const organizationId = get(account, 'organizationId', null)
const billingContextId = get(account, 'billingContextId', null)
const [acquiringContextId] = get(organizationsToAcquiringContextsMap, organizationId, [null])
Expand All @@ -447,6 +449,8 @@ const DiscoverServiceConsumersService = new GQLCustomSchema('DiscoverServiceCons
billingAccount: account.id,
billingIntegrationContext: billingContextId || null,
acquiringIntegrationContext: acquiringContextId || null,
property: get(resident, ['property', 'id']),
user: get(resident, ['user', 'id']),
}
})

Expand All @@ -468,6 +472,39 @@ const DiscoverServiceConsumersService = new GQLCustomSchema('DiscoverServiceCons
existingServiceConsumers: map(existingServiceConsumers, (x) => pick(x, ['id', 'resident', 'organization', 'accountNumber', 'billingAccount'])),
})

// count residents per property for each user to prevent discover service consumers if there are more than MAX_CONSUMERS_COUNT_FOR_USER_PROPERTY residents at the property
const residentsCountByUserAndProperty = {}
await loadListByChunks({
context,
list: Resident,
chunkSize: 20,
where: { user: { id_in: map(serviceConsumersData, 'user') }, deletedAt: null },
chunkProcessor: (/** @type {Resident[]} */ chunk) => {
for (const resident of chunk) {
const userId = get(resident, ['user', 'id'])
const propertyId = get(resident, ['property', 'id'])
if (!!userId && !!propertyId) {
set(
residentsCountByUserAndProperty,
[userId, propertyId],
get(residentsCountByUserAndProperty, [userId, propertyId], 0) + 1,
)
}
}
return []
},
})

serviceConsumersData = serviceConsumersData.filter(({
user,
property,
}) => get(residentsCountByUserAndProperty, [user, property], 0) <= MAX_RESIDENTS_COUNT_FOR_USER_PROPERTY)

discoveringSteps.push({
name: `filter out users with ${MAX_RESIDENTS_COUNT_FOR_USER_PROPERTY + 1}+ existing residents for property`,
residentsCountByUserAndProperty,
})

const createdServiceConsumers = await Promise.all(
serviceConsumersData.map((serviceConsumerData) => {
const [existingServiceConsumer] = filter(existingServiceConsumers, {
Expand All @@ -477,7 +514,16 @@ const DiscoverServiceConsumersService = new GQLCustomSchema('DiscoverServiceCons
})

const data = {
...serviceConsumerData,
...pick(serviceConsumerData, [
'dv',
'sender',
'resident',
'accountNumber',
'organization',
'billingAccount',
'billingIntegrationContext',
'acquiringIntegrationContext',
]),
resident: { connect: { id: serviceConsumerData.resident } },
organization: { connect: { id: serviceConsumerData.organization } },
billingAccount: { connect: { id: serviceConsumerData.billingAccount } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
const { faker } = require('@faker-js/faker')
const dayjs = require('dayjs')
const { map } = require('lodash')

const { getRedisClient } = require('@open-condo/keystone/redis')
const {
Expand Down Expand Up @@ -1134,6 +1135,97 @@ describe('DiscoverServiceConsumersService', () => {

expect(createdServiceConsumers).toHaveLength(0)
})

test('Can\'t discover if already 6+ residents exist', async () => {
const userClient = await makeClientWithProperty()

await addAcquiringIntegrationAndContext(admin, userClient.organization, {}, { status: CONTEXT_FINISHED_STATUS })
const { billingIntegrationContext } = await addBillingIntegrationAndContext(admin, userClient.organization, {}, { status: CONTEXT_FINISHED_STATUS })

const [billingProperty] = await createTestBillingProperty(admin, billingIntegrationContext, { address: userClient.property.address })

const residents = []
const billingAccounts = []
for (let i = 0; i < 6; i++) {
const [resident] = await createTestResident(admin, userClient.user, userClient.property, { address: billingProperty.address })
residents.push(resident)

const [billingAccount] = await createTestBillingAccount(admin, billingIntegrationContext, billingProperty,
{ unitName: resident.unitName, unitType: resident.unitType },
)
billingAccounts.push(billingAccount)

const now = dayjs()
const receiptsPayload = {
context: { id: billingIntegrationContext.id },
receipts: [
createRegisterBillingReceiptsPayload({
address: billingProperty.address,
unitType: resident.unitType,
unitName: resident.unitName,
accountNumber: billingAccount.number,
year: Number(now.format('YYYY')),
month: Number(now.format('MM')),
}),
],
}
await registerBillingReceiptsByTestClient(admin, receiptsPayload)
}

await _internalScheduleTaskByNameByTestClient(admin, { taskName: cronTaskName })

await waitFor(async () => {
const createdServiceConsumers = await ServiceConsumer.getAll(admin, {
resident: { id_in: map(residents, 'id') },
deletedAt: null,
})
const residentIds = createdServiceConsumers.map(serviceConsumer => serviceConsumer.resident.id)
const accountNumbers = createdServiceConsumers.map(serviceConsumer => serviceConsumer.accountNumber)

expect(createdServiceConsumers).toHaveLength(6)
expect(residentIds).toEqual(expect.arrayContaining(map(residents, 'id')))
expect(accountNumbers).toEqual(expect.arrayContaining(map(billingAccounts, 'number')))
}, { delay: 500 })

// add another one resident with receipts
const [nextResident] = await createTestResident(admin, userClient.user, userClient.property, { address: billingProperty.address })

const [nextBillingAccount] = await createTestBillingAccount(admin, billingIntegrationContext, billingProperty,
{ unitName: nextResident.unitName, unitType: nextResident.unitType },
)

const now = dayjs()
const receiptsPayload = {
context: { id: billingIntegrationContext.id },
receipts: [
createRegisterBillingReceiptsPayload({
address: billingProperty.address,
unitType: nextResident.unitType,
unitName: nextResident.unitName,
accountNumber: nextBillingAccount.number,
year: Number(now.format('YYYY')),
month: Number(now.format('MM')),
}),
],
}
await registerBillingReceiptsByTestClient(admin, receiptsPayload)

// start discovering
await _internalScheduleTaskByNameByTestClient(admin, { taskName: cronTaskName })
// It must still be 6 consumers
await waitFor(async () => {
const createdServiceConsumers = await ServiceConsumer.getAll(admin, {
resident: { id_in: [...map(residents, 'id'), nextResident.id] },
deletedAt: null,
})
const residentIds = createdServiceConsumers.map(serviceConsumer => serviceConsumer.resident.id)
const accountNumbers = createdServiceConsumers.map(serviceConsumer => serviceConsumer.accountNumber)

expect(createdServiceConsumers).toHaveLength(6)
expect(residentIds).toEqual(expect.arrayContaining(map(residents, 'id')))
expect(accountNumbers).toEqual(expect.arrayContaining(map(billingAccounts, 'number')))
}, { delay: 500 })
})
})

describe('real life cases', () => {
Expand Down

0 comments on commit c422e4e

Please sign in to comment.