Skip to content

Commit 4e4dd48

Browse files
authored
Merge branch 'main' into fix/member-enrichment-savepoint-race
2 parents 8263e24 + 18ae414 commit 4e4dd48

5 files changed

Lines changed: 74 additions & 2 deletions

File tree

backend/src/database/repositories/organizationRepository.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,7 @@ class OrganizationRepository {
13161316
limit = 20,
13171317
offset = 0,
13181318
orderBy = undefined,
1319+
search = undefined as string | undefined,
13191320
segmentId = undefined,
13201321
},
13211322
options: IRepositoryOptions,
@@ -1332,6 +1333,7 @@ class OrganizationRepository {
13321333
limit,
13331334
offset,
13341335
orderBy,
1336+
search,
13351337
segmentId,
13361338
})
13371339

@@ -1345,6 +1347,7 @@ class OrganizationRepository {
13451347
cacheKey,
13461348
{
13471349
filter,
1350+
search,
13481351
limit,
13491352
offset,
13501353
orderBy,
@@ -1366,6 +1369,7 @@ class OrganizationRepository {
13661369
cacheKey,
13671370
{
13681371
filter,
1372+
search,
13691373
segmentId,
13701374
include,
13711375
},
@@ -1386,6 +1390,7 @@ class OrganizationRepository {
13861390
cacheKey,
13871391
{
13881392
filter,
1393+
search,
13891394
limit,
13901395
offset,
13911396
orderBy,
@@ -1403,6 +1408,7 @@ class OrganizationRepository {
14031408
cacheKey: string,
14041409
{
14051410
filter = {} as any,
1411+
search = undefined as string | undefined,
14061412
limit = 20,
14071413
offset = 0,
14081414
orderBy = undefined,
@@ -1458,13 +1464,19 @@ class OrganizationRepository {
14581464
segmentId = segment.id
14591465
}
14601466

1461-
const params = {
1467+
const params: Record<string, any> = {
14621468
limit,
14631469
offset,
14641470
segmentId,
14651471
tenantId: options.currentTenant.id,
14661472
}
14671473

1474+
let searchWhereClause = ''
1475+
if (search) {
1476+
params.searchTerm = `%${search}%`
1477+
searchWhereClause = `AND o."displayName" ILIKE $(searchTerm)`
1478+
}
1479+
14681480
const filterString = RawQueryParser.parseFilters(
14691481
filter,
14701482
OrganizationRepository.QUERY_FILTER_COLUMN_MAP,
@@ -1498,6 +1510,7 @@ class OrganizationRepository {
14981510
WHERE 1=1
14991511
AND o."tenantId" = $(tenantId)
15001512
${lfxMembershipFilterWhereClause}
1513+
${searchWhereClause}
15011514
AND (${filterString})
15021515
`
15031516
const countQuery = createQuery('COUNT(*)')
@@ -1649,6 +1662,7 @@ class OrganizationRepository {
16491662
params: {
16501663
// TODO: REMOVE this any
16511664
filter?: any
1665+
search?: string
16521666
limit: number
16531667
offset: number
16541668
orderBy?: string
@@ -1671,6 +1685,7 @@ class OrganizationRepository {
16711685
cacheKey: string,
16721686
params: {
16731687
filter?: any
1688+
search?: string
16741689
segmentId?: string
16751690
include: any
16761691
},

backend/src/database/repositories/organizationsQueryCache.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class OrganizationQueryCache {
3838
limit: number
3939
offset: number
4040
orderBy?: string
41+
search?: string
4142
segmentId?: string
4243
}): string {
4344
const cleanParams = Object.fromEntries(
@@ -49,6 +50,7 @@ export class OrganizationQueryCache {
4950
limit: params.limit,
5051
offset: params.offset,
5152
orderBy: params.orderBy,
53+
search: params.search,
5254
segmentId: params.segmentId,
5355
}).filter(([, value]) => value !== null && value !== undefined),
5456
)

backend/src/services/organizationService.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1163,10 +1163,19 @@ export default class OrganizationService extends LoggerBase {
11631163
}
11641164

11651165
async query(data) {
1166-
const { filter, orderBy, limit, offset, segments } = data
1166+
const { filter: rawFilter, orderBy, limit, offset, segments, search: rawSearch } = data
1167+
const searchTerm =
1168+
typeof rawSearch === 'string' && rawSearch.trim() ? rawSearch.trim() : undefined
1169+
1170+
// Strip frontend-state keys that are never valid filter columns or operators.
1171+
// These can appear when the raw Pinia filter state is sent instead of the
1172+
// processed output of buildApiFilter.
1173+
const { search: _s, relation: _r, order: _o, settings: _st, ...filter } = rawFilter ?? {}
1174+
11671175
return OrganizationRepository.findAndCountAll(
11681176
{
11691177
filter,
1178+
search: searchTerm,
11701179
orderBy,
11711180
limit,
11721181
offset,

services/apps/cron_service/src/jobs/inferMemberOrganizationStintChanges.job.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
changeMemberOrganizationAffiliationOverrides,
1111
checkOrganizationAffiliationPolicy,
1212
createMemberOrganization,
13+
deleteUndatedMemberOrganizations,
1314
fetchMemberOrganizationsBySource,
1415
updateMemberOrganization,
1516
} from '@crowd/data-access-layer'
@@ -136,6 +137,10 @@ async function applyStintChanges(qx: QueryExecutor, changes: MemberOrgStintChang
136137
})
137138
}
138139
}
140+
141+
await deleteUndatedMemberOrganizations(qx, changes[0].memberId, [
142+
...new Set(changes.map((c) => c.organizationId)),
143+
])
139144
}
140145

141146
export default job

services/libs/data-access-layer/src/members/organizations.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,47 @@ export async function deleteMemberOrganizations(
482482
})
483483
}
484484

485+
export async function deleteUndatedMemberOrganizations(
486+
qx: QueryExecutor,
487+
memberId: string,
488+
organizationIds: string[],
489+
): Promise<void> {
490+
if (organizationIds.length === 0) {
491+
return
492+
}
493+
494+
const whereClause = `
495+
"memberId" = $(memberId)
496+
AND "organizationId" IN ($(organizationIds:csv))
497+
AND "dateStart" IS NULL
498+
AND "dateEnd" IS NULL
499+
AND "deletedAt" IS NULL
500+
`
501+
502+
const params = { memberId, organizationIds }
503+
504+
await qx.tx(async (tx) => {
505+
await tx.result(
506+
`
507+
DELETE FROM "memberOrganizationAffiliationOverrides"
508+
WHERE "memberOrganizationId" IN (
509+
SELECT "id" FROM "memberOrganizations" WHERE ${whereClause}
510+
)
511+
`,
512+
params,
513+
)
514+
515+
await tx.result(
516+
`
517+
UPDATE "memberOrganizations"
518+
SET "deletedAt" = NOW()
519+
WHERE ${whereClause}
520+
`,
521+
params,
522+
)
523+
})
524+
}
525+
485526
export async function cleanSoftDeletedMemberOrganization(
486527
qx: QueryExecutor,
487528
memberId: string,

0 commit comments

Comments
 (0)