Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 5 additions & 10 deletions packages/commons/src/events/CountryConfigQueryInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
Exact,
ExactStatus,
QueryInput,
Within,
ExactUserType
} from './EventIndex'

Expand All @@ -39,16 +38,12 @@ export const SerializedQueryExpression = z
createdAt: z.optional(DateCondition),
updatedAt: z.optional(DateCondition),
'legalStatuses.REGISTERED.createdAt': z.optional(DateCondition),
'legalStatuses.REGISTERED.createdAtLocation': z.optional(
z.union([Within, Exact])
),
'legalStatuses.DECLARED.createdAtLocation': z.optional(SerializableWithin),
'legalStatuses.REGISTERED.createdAtLocation':
z.optional(SerializableWithin),
'legalStatuses.REGISTERED.registrationNumber': z.optional(Exact),
createdAtLocation: z.optional(
z.union([SerializableWithin, SerializableExact])
),
updatedAtLocation: z.optional(
z.union([SerializableWithin, SerializableExact])
),
createdAtLocation: z.optional(SerializableWithin),
updatedAtLocation: z.optional(SerializableWithin),
assignedTo: z.optional(SerializableExact),
createdBy: z.optional(SerializableExact),
createdByUserType: ExactUserType,
Expand Down
12 changes: 4 additions & 8 deletions packages/commons/src/events/EventIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,11 @@ export const QueryExpression = z
createdAt: z.optional(DateCondition),
updatedAt: z.optional(DateCondition),
'legalStatuses.REGISTERED.acceptedAt': z.optional(DateCondition),
'legalStatuses.DECLARED.createdAtLocation': z.optional(
z.union([Within, Exact])
),
'legalStatuses.REGISTERED.createdAtLocation': z.optional(
z.union([Within, Exact])
),
'legalStatuses.DECLARED.createdAtLocation': z.optional(Within).nullable(),
'legalStatuses.REGISTERED.createdAtLocation': z.optional(Within).nullable(),
'legalStatuses.REGISTERED.registrationNumber': z.optional(Exact),
createdAtLocation: z.optional(z.union([Within, Exact])),
updatedAtLocation: z.optional(z.union([Within, Exact])),
createdAtLocation: z.optional(Within),
updatedAtLocation: z.optional(Within),
assignedTo: z.optional(Exact),
createdByUserType: z.optional(ExactUserType),
createdBy: z.optional(Exact),
Expand Down
62 changes: 32 additions & 30 deletions packages/commons/src/events/serializers/user/deserializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,15 @@ import { SerializedUserField } from './serializer'
*/
function userDeserializer(
serializedUserField: SerializedUserField | string,
user: User
user: User,
fallback: string = ''
): string {
if (typeof serializedUserField === 'string') {
return serializedUserField
}
if (typeof serializedUserField !== 'object') {
return fallback
}
if (
serializedUserField.$userField === 'name' ||
serializedUserField.$userField === 'signature' ||
Expand All @@ -58,7 +62,7 @@ function userDeserializer(
`Deserializer for ${serializedUserField.$userField} is not implemented yet`
)
}
return user[serializedUserField.$userField]
return user[serializedUserField.$userField] ?? fallback
}

function deserializeQueryExpression(
Expand All @@ -80,34 +84,32 @@ function deserializeQueryExpression(
...expression.updatedBy,
term: userDeserializer(expression.updatedBy.term, user)
},
createdAtLocation:
expression.createdAtLocation &&
(expression.createdAtLocation.type === 'within'
? {
...expression.createdAtLocation,
location: userDeserializer(
expression.createdAtLocation.location,
user
)
}
: {
...expression.createdAtLocation,
term: userDeserializer(expression.createdAtLocation.term, user)
}),
updatedAtLocation:
expression.updatedAtLocation &&
(expression.updatedAtLocation.type === 'within'
? {
...expression.updatedAtLocation,
location: userDeserializer(
expression.updatedAtLocation.location,
user
)
}
: {
...expression.updatedAtLocation,
term: userDeserializer(expression.updatedAtLocation.term, user)
})
createdAtLocation: expression.createdAtLocation && {
...expression.createdAtLocation,
location: userDeserializer(expression.createdAtLocation.location, user)
},
updatedAtLocation: expression.updatedAtLocation && {
...expression.updatedAtLocation,
location: userDeserializer(expression.updatedAtLocation.location, user)
},
['legalStatuses.DECLARED.createdAtLocation']: expression[
'legalStatuses.DECLARED.createdAtLocation'
] && {
...expression['legalStatuses.DECLARED.createdAtLocation'],
location: userDeserializer(
expression['legalStatuses.DECLARED.createdAtLocation'].location,
user
)
},
['legalStatuses.REGISTERED.createdAtLocation']: expression[
'legalStatuses.REGISTERED.createdAtLocation'
] && {
...expression['legalStatuses.REGISTERED.createdAtLocation'],
location: userDeserializer(
expression['legalStatuses.REGISTERED.createdAtLocation'].location,
user
)
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion packages/commons/src/events/serializers/user/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export const SerializedUserField = z.object({
'role',
'signature',
'avatar',
'primaryOfficeId'
'primaryOfficeId',
'administrativeAreaId'
]),
$location: z.string().optional()
})
Expand Down
9 changes: 9 additions & 0 deletions packages/events/src/router/locations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as z from 'zod/v4'
import { Location, LocationType, SCOPES, UUID } from '@opencrvs/commons'
import { router, userAndSystemProcedure } from '@events/router/trpc'
import {
getChildLocations,
getLocations,
setLocations,
syncLocations
Expand Down Expand Up @@ -56,6 +57,14 @@ export const locationRouter = router({
locationType: input?.locationType
})
),
getChild: userAndSystemProcedure
.input(
z.object({
parentId: UUID
})
)
.output(z.array(Location))
.query(async ({ input }) => getChildLocations(input.parentId)),
set: userAndSystemProcedure
.use(
requiresAnyOfScopes([SCOPES.USER_DATA_SEEDING, SCOPES.CONFIG_UPDATE_ALL])
Expand Down
25 changes: 7 additions & 18 deletions packages/events/src/service/indexing/indexing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,13 @@ const rangeRegisteredAtPayload: QueryType = {
]
}

const exactRegisteredAtLocationPayload: QueryType = {
const withinRegisteredAtLocationPayload: QueryType = {
type: 'and',
clauses: [
{
'legalStatuses.REGISTERED.createdAtLocation': {
type: 'exact',
term: RANDOM_UUID
type: 'within',
location: RANDOM_UUID
},
eventType: TENNIS_CLUB_MEMBERSHIP
}
Expand All @@ -256,7 +256,7 @@ const fullAndPayload: QueryType = {
trackingId: { type: 'exact', term: 'ABC123' },
createdAt: { type: 'range', gte: '2024-01-01', lte: '2024-12-31' },
updatedAt: { type: 'exact', term: '2024-06-01' },
createdAtLocation: { type: 'exact', term: RANDOM_UUID },
createdAtLocation: { type: 'within', location: RANDOM_UUID },
updatedAtLocation: {
type: 'within',
location: RANDOM_UUID
Expand Down Expand Up @@ -367,9 +367,9 @@ describe('test buildElasticQueryFromSearchPayload', () => {
})
})

test('builds query with exact legalStatuses.REGISTERED.createdAtLocation', async () => {
test('builds query with legalStatuses.REGISTERED.createdAtLocation', async () => {
const result = await buildElasticQueryFromSearchPayload(
exactRegisteredAtLocationPayload,
withinRegisteredAtLocationPayload,
[tennisClubMembershipEvent]
)
expect(result).toEqual({
Expand Down Expand Up @@ -438,18 +438,7 @@ describe('test buildElasticQueryFromSearchPayload', () => {
},
{ term: { updatedAt: '2024-06-01' } },
{ term: { createdAtLocation: RANDOM_UUID } },
{
bool: {
minimum_should_match: 1,
should: [
{
term: {
updatedAtLocation: RANDOM_UUID
}
}
]
}
},
{ term: { updatedAtLocation: RANDOM_UUID } },
{
match: {
'declaration.applicant____name.__fullname': 'John Doe'
Expand Down
2 changes: 1 addition & 1 deletion packages/events/src/service/indexing/indexing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ export async function findRecordsByQuery({
const events = response.hits.hits
.map((hit) => hit._source)
.filter((event): event is EncodedEventIndex => event !== undefined)
.map((eventIndex) => {
.map((eventIndex: EncodedEventIndex) => {
const eventConfig = getEventConfigById(eventConfigs, eventIndex.type)
const decodedEventIndex = decodeEventIndex(eventConfig, eventIndex)
const eventIndexWithoutLocationHierarchy =
Expand Down
32 changes: 10 additions & 22 deletions packages/events/src/service/indexing/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ import {
SearchScopeAccessLevels,
timePeriodToDateRange
} from '@opencrvs/commons/events'
import { getOrThrow, ResolvedRecordScopeV2, UUID } from '@opencrvs/commons'
import { getChildLocations } from '../locations/locations'
import { getOrThrow, ResolvedRecordScopeV2 } from '@opencrvs/commons'
import {
encodeFieldId,
generateQueryForAddressField,
Expand Down Expand Up @@ -156,10 +155,7 @@ function typedKeys<T extends object>(obj: T): (keyof T)[] {
return Object.keys(obj) as (keyof T)[]
}

async function buildClause(
clause: QueryExpression,
eventConfigs: EventConfig[]
) {
function buildClause(clause: QueryExpression, eventConfigs: EventConfig[]) {
const must: estypes.QueryDslQueryContainer[] = []

for (const key of typedKeys(clause)) {
Expand Down Expand Up @@ -216,22 +212,14 @@ async function buildClause(
case 'legalStatuses.REGISTERED.createdAtLocation': {
const value = clause[key]

if (value.type === 'exact') {
must.push({ term: { [key]: value.term } })
} else {
const childLocations = await getChildLocations(value.location as UUID)
const locationIds = [
value.location,
...childLocations.map((location) => location.id)
]

must.push({
bool: {
should: locationIds.map((id) => ({ term: { [key]: id } })),
minimum_should_match: 1
}
})
/**
* If value.location === '', it represents the root location,
* so no additional restriction needs to be applied.
*/
if (value.location !== '') {
must.push({ term: { [key]: value.location } })
}

break
}

Expand Down Expand Up @@ -282,7 +270,7 @@ async function buildClauseOrQuery(
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return buildElasticQueryFromSearchPayload(clause, eventConfigs)
} else {
const must = await buildClause(clause, eventConfigs)
const must = buildClause(clause, eventConfigs)
return {
bool: {
must,
Expand Down