Skip to content

Commit

Permalink
feat: allow marking status for application flagged sets (#3020)
Browse files Browse the repository at this point in the history
  • Loading branch information
emilyjablonski authored Sep 26, 2022
1 parent 444bbd4 commit 2e1a131
Show file tree
Hide file tree
Showing 45 changed files with 1,183 additions and 314 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ListingRepository } from "../listings/db/listing.repository"
import { Listing } from "../listings/entities/listing.entity"
import { ApplicationFlaggedSet } from "./entities/application-flagged-set.entity"
import { FlaggedSetStatus } from "./types/flagged-set-status-enum"
import { getView } from "../applications/views/view"

@Processor(AFSProcessingQueueNames.afsProcessing)
export class ApplicationFlaggedSetsCronjobConsumer {
Expand All @@ -20,7 +21,6 @@ export class ApplicationFlaggedSetsCronjobConsumer {

@Process({ concurrency: 1 })
async process() {
const rules = [Rule.nameAndDOB, Rule.email]
const outOfDateListings = await this.listingRepository
.createQueryBuilder("listings")
.select(["listings.id", "listings.afsLastRunAt"])
Expand All @@ -36,33 +36,26 @@ export class ApplicationFlaggedSetsCronjobConsumer {

for (const outOfDateListing of outOfDateListings) {
try {
for (const rule of rules) {
await this.generateAFSesForListingRule(outOfDateListing, rule)
}
await this.generateAFSesForListingRules(outOfDateListing)
outOfDateListing.afsLastRunAt = new Date()
await this.listingRepository.save(outOfDateListing)
} catch (e) {
console.error(e)
}

outOfDateListing.afsLastRunAt = new Date()
await this.listingRepository.save(outOfDateListing)
}
}

private async generateAFSesForListingRule(
listing: Pick<Listing, "id" | "afsLastRunAt">,
rule: Rule
) {
const newApplications = await this.applicationRepository.find({
where: {
listing: {
id: listing.id,
},
createdAt: MoreThanOrEqual(listing.afsLastRunAt),
},
private async generateAFSesForListingRules(listing: Pick<Listing, "id" | "afsLastRunAt">) {
const qbView = getView(this.applicationRepository.createQueryBuilder("application"))
const qb = qbView.getViewQb(true)
qb.where("application.listing_id = :id", { id: listing.id })
qb.andWhere("application.updatedAt >= :afsLastRunAt", {
afsLastRunAt: listing.afsLastRunAt,
})
const newApplications = await qb.getMany()

for (const newApplication of newApplications) {
await this.addApplication(newApplication, rule)
await this.addApplication(newApplication)
}

const existingApplications = await this.applicationRepository.find({
Expand All @@ -76,11 +69,11 @@ export class ApplicationFlaggedSetsCronjobConsumer {
})

for (const existingApplication of existingApplications) {
await this.updateApplication(existingApplication, rule)
await this.updateApplication(existingApplication)
}
}

async updateApplication(application: Application, rule: Rule) {
async updateApplication(application: Application) {
application.markedAsDuplicate = false
await this.applicationRepository.save(application)

Expand All @@ -97,7 +90,7 @@ export class ApplicationFlaggedSetsCronjobConsumer {
const afsesToBeRemoved: Array<ApplicationFlaggedSet> = []

for (const afs of afses) {
afs.status = FlaggedSetStatus.flagged
afs.status = FlaggedSetStatus.pending
afs.resolvedTime = null
afs.resolvingUser = null

Expand All @@ -115,49 +108,63 @@ export class ApplicationFlaggedSetsCronjobConsumer {
afsesToBeRemoved.push(afs)
}
}
if (afsesToBeSaved.length) {
await this.afsRepository.save(afsesToBeSaved)
}
if (afsesToBeRemoved.length) {
await this.afsRepository.remove(afsesToBeRemoved)
}

await this.afsRepository.save(afsesToBeSaved)
await this.afsRepository.remove(afsesToBeRemoved)

await this.addApplication(application, rule)
await this.addApplication(application)
}

async addApplication(newApplication: Application, rule: Rule) {
const applicationsMatchingRule = await this.fetchDuplicatesMatchingRule(newApplication, rule)

if (applicationsMatchingRule.length == 0) {
return
}

const afses = await this.afsRepository
.createQueryBuilder("afs")
.leftJoin("afs.applications", "applications")
.select(["afs", "applications.id"])
.where(`afs.ruleKey = :ruleKey`, { ruleKey: this.getRuleKeyForRule(newApplication, rule) })
.getMany()
/**
*
* This method checks if the new application matches others based on the rules.
* If there are applications that match, this application is added to the AFS set (creating a new one or updating an existing set)
*/
async addApplication(newApplication: Application): Promise<void> {
const rules = [Rule.email, Rule.nameAndDOB]

for (const rule of rules) {
const applicationsMatchingRule = await this.fetchDuplicatesMatchingRule(newApplication, rule)
if (applicationsMatchingRule.length === 0) {
// continue to the next rule
continue
}

if (afses.length === 0) {
await this.afsRepository.save({
rule: rule,
ruleKey: this.getRuleKeyForRule(newApplication, rule),
resolvedTime: null,
resolvingUser: null,
status: FlaggedSetStatus.flagged,
applications: [newApplication, ...applicationsMatchingRule],
listing: { id: newApplication.listingId },
})
} else if (afses.length === 1) {
const afs = afses[0]
const afses = await this.afsRepository
.createQueryBuilder("afs")
.leftJoin("afs.applications", "applications")
.select(["afs", "applications.id"])
.where(`afs.ruleKey = :ruleKey`, { ruleKey: this.getRuleKeyForRule(newApplication, rule) })
.getMany()

if (afses.length === 0) {
await this.afsRepository.save({
rule: rule,
ruleKey: this.getRuleKeyForRule(newApplication, rule),
resolvedTime: null,
resolvingUser: null,
status: FlaggedSetStatus.pending,
applications: [newApplication, ...applicationsMatchingRule],
listing: { id: newApplication.listingId },
})
} else if (afses.length === 1) {
const afs = afses[0]

if (!afs.applications.map((app) => app.id).includes(newApplication.id)) {
afs.applications.push(newApplication)
await this.afsRepository.save(afs)
if (!afs.applications.map((app) => app.id).includes(newApplication.id)) {
afs.applications.push(newApplication)
await this.afsRepository.save(afs)
}
} else {
console.error(
"There should be up to one AFS matching a rule for given application, " +
"probably a logic error when creating AFSes"
)
}
} else {
console.error(
"There should be up to one AFS matching a rule for given application, " +
"probably a logic error when creating AFSes"
)
// there was a match so we don't need to check the next rule
break
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Get,
Param,
Post,
Put,
Query,
Request,
UseGuards,
Expand All @@ -17,13 +18,15 @@ import { OptionalAuthGuard } from "../auth/guards/optional-auth.guard"
import { AuthzGuard } from "../auth/guards/authz.guard"
import { defaultValidationPipeOptions } from "../shared/default-validation-pipe-options"
import { mapTo } from "../shared/mapTo"
import { StatusDto } from "../shared/dto/status.dto"
import { ApplicationFlaggedSetsService } from "./application-flagged-sets.service"
import { ApplicationFlaggedSetDto } from "./dto/application-flagged-set.dto"
import { PaginatedApplicationFlaggedSetDto } from "./dto/paginated-application-flagged-set.dto"
import { ApplicationFlaggedSetResolveDto } from "./dto/application-flagged-set-resolve.dto"
import { PaginatedApplicationFlaggedSetQueryParams } from "./paginated-application-flagged-set-query-params"
import { ApplicationFlaggedSetsCronjobConsumer } from "./application-flagged-sets-cronjob-consumer"
import { ApplicationFlaggedSetMeta } from "./dto/application-flagged-set-meta.dto"
import { IdDto } from "../shared/dto/id.dto"

@Controller("/applicationFlaggedSets")
@ApiTags("applicationFlaggedSets")
Expand Down Expand Up @@ -78,6 +81,16 @@ export class ApplicationFlaggedSetsController {
return mapTo(ApplicationFlaggedSetDto, await this.applicationFlaggedSetsService.resolve(dto))
}

@Put(":id")
@ApiOperation({
summary: "Reset flagged set confirmation alert",
operationId: "resetConfirmationAlert",
})
async resetConfirmationAlert(@Body() dto: IdDto): Promise<StatusDto> {
await this.applicationFlaggedSetsService.resetConfirmationAlert(dto.id)
return mapTo(StatusDto, { status: "ok" })
}

@Post("process")
@ApiOperation({ summary: "Trigger the duplicate check process", operationId: "process" })
async process(): Promise<string> {
Expand Down
Loading

0 comments on commit 2e1a131

Please sign in to comment.