Skip to content

Commit

Permalink
feat: release 2022-10-25
Browse files Browse the repository at this point in the history
* feat: new listing type field (#3085)

* 3032/new what to expect core (#3087)

* feat: bring over What to Expect and update Markdown styles

* feat: show dedicated content on the What to Expect form step

* feat: add additional text to terms and confirmation

* feat: update form conditionals to use waitlist enum

* fix: remove stray import

* fix: typos and improved switch statements

* fix: confirmation text and remove lottery date

* fix: add back in eligibility translations (#3134)

* fix: correct the cron jobs

* feat(expandablecontent): remove classname from ExpandableContent

move styling of more/less button to parent component

#3140

* Fix code style issues with Prettier

* feat(expandabletext): add classname to stories

add margin to instances of ExpandableText

#3140

* fix: switch listing to server side props (#3145)

* fix: update activity-log relationship to users for deletion (#3139)

* Allow markup for descriptions and optional classname (#3131)

* feat: display income currency value with commas

* feat: accept only numeric values in currency field

* feat: submit income as a string

* feat: remove redundant step prop from currency field

* feat: add thank you translations to email footer

* fix: change the cron job logging level (#3150)

* fix: what to expect missed changes

* fix: email tests

* chore(release): version

 - @bloom-housing/[email protected]
 - @bloom-housing/[email protected]
 - @bloom-housing/[email protected]
 - @bloom-housing/[email protected]
 - @bloom-housing/[email protected]

Co-authored-by: Jared White <[email protected]>
Co-authored-by: Emily Jablonski <[email protected]>
Co-authored-by: Mark Buckner <[email protected]>
Co-authored-by: Lint Action <[email protected]>
Co-authored-by: christine-sfg <[email protected]>
Co-authored-by: krzysztof ziecina <[email protected]>
  • Loading branch information
7 people authored Oct 27, 2022
1 parent e1b312d commit 2964d79
Show file tree
Hide file tree
Showing 61 changed files with 1,169 additions and 285 deletions.
71 changes: 71 additions & 0 deletions backend/core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,77 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [7.0.1](https://github.com/bloom-housing/bloom/compare/@bloom-housing/[email protected]...@bloom-housing/[email protected]) (2022-10-26)

**Note:** Version bump only for package @bloom-housing/backend-core





## [7.0.1-alpha.5](https://github.com/bloom-housing/bloom/compare/@bloom-housing/[email protected]...@bloom-housing/[email protected]) (2022-10-26)


### Bug Fixes

* change the cron job logging level ([#3150](https://github.com/bloom-housing/bloom/issues/3150)) ([fe43154](https://github.com/bloom-housing/bloom/commit/fe4315423ffd17ee22d16018cc938271592dfcf5))





## [7.0.1-alpha.4](https://github.com/bloom-housing/bloom/compare/@bloom-housing/[email protected]...@bloom-housing/[email protected]) (2022-10-25)


### Features

* add thank you translations to email footer ([5f3c7b1](https://github.com/bloom-housing/bloom/commit/5f3c7b1e81357e1aff5f3f3532dbb7691ac243ce))





## [7.0.1-alpha.3](https://github.com/bloom-housing/bloom/compare/@bloom-housing/[email protected]...@bloom-housing/[email protected]) (2022-10-21)


### Bug Fixes

* update activity-log relationship to users for deletion ([#3139](https://github.com/bloom-housing/bloom/issues/3139)) ([f95532e](https://github.com/bloom-housing/bloom/commit/f95532e4ebe693c128d742399030054d0f735164))





## [7.0.1-alpha.2](https://github.com/bloom-housing/bloom/compare/@bloom-housing/[email protected]...@bloom-housing/[email protected]) (2022-10-19)


### Bug Fixes

* correct the cron jobs ([407c0fb](https://github.com/bloom-housing/bloom/commit/407c0fbe10e3150047dadbb43c5248b768e8dc63))





## [7.0.1-alpha.1](https://github.com/bloom-housing/bloom/compare/@bloom-housing/[email protected]...@bloom-housing/[email protected]) (2022-10-13)


### Bug Fixes

* add back in eligibility translations ([#3134](https://github.com/bloom-housing/bloom/issues/3134)) ([a9ba463](https://github.com/bloom-housing/bloom/commit/a9ba463bfb414ff13820616f7045f43cc997dca2))





## [7.0.1-alpha.0](https://github.com/bloom-housing/bloom/compare/@bloom-housing/[email protected]...@bloom-housing/[email protected]) (2022-10-05)

**Note:** Version bump only for package @bloom-housing/backend-core





# [7.0.0](https://github.com/bloom-housing/bloom/compare/@bloom-housing/[email protected]...@bloom-housing/[email protected]) (2022-09-29)


Expand Down
2 changes: 1 addition & 1 deletion backend/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bloom-housing/backend-core",
"version": "7.0.0",
"version": "7.0.1",
"description": "Listings service reference implementation for the Bloom affordable housing system",
"author": "Sean Albert <[email protected]>",
"private": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class ActivityLog extends AbstractEntity {
@Expose()
action: string

@ManyToOne(() => User, { nullable: true })
@ManyToOne(() => User, { nullable: true, onDelete: "SET NULL" })
@JoinColumn()
@Expose()
@Type(() => User)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { InjectQueue } from "@nestjs/bull"
import { Injectable } from "@nestjs/common"
import { Inject, Injectable, Logger } from "@nestjs/common"
import { Queue } from "bull"
import { AFSProcessingQueueNames } from "./constants/applications-flagged-sets-constants"
import { ConfigService } from "@nestjs/config"
Expand All @@ -8,15 +8,17 @@ import { ConfigService } from "@nestjs/config"
export class ApplicationFlaggedSetsCronjobBoostrapService {
constructor(
@InjectQueue(AFSProcessingQueueNames.afsProcessing) private afsProcessingQueue: Queue,
private readonly config: ConfigService
private readonly config: ConfigService,
@Inject(Logger)
private readonly logger = new Logger(ApplicationFlaggedSetsCronjobBoostrapService.name)
) {
const repeatCron = this.config.get<string>("AFS_PROCESSING_CRON_STRING")
this.logger.warn(`Setting up AFS processing cron to frequency ${repeatCron}`)
void this.afsProcessingQueue.empty()
void this.afsProcessingQueue.add(null, {
repeat: {
cron: config.get<string>("AFS_PROCESSING_CRON_STRING"),
cron: repeatCron,
},
// NOTE: This is not unique on purpose because Bull will not add a job twice with an ID
// which already exists.
id: "afs-process",
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@ 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"
import { Inject, Logger } from "@nestjs/common"

@Processor(AFSProcessingQueueNames.afsProcessing)
export class ApplicationFlaggedSetsCronjobConsumer {
constructor(
@InjectRepository(ListingRepository) private readonly listingRepository: ListingRepository,
@InjectRepository(ApplicationFlaggedSet)
private readonly afsRepository: Repository<ApplicationFlaggedSet>,
@InjectRepository(Application) private readonly applicationRepository: Repository<Application>
@InjectRepository(Application) private readonly applicationRepository: Repository<Application>,
@Inject(Logger) private readonly logger = new Logger(ApplicationFlaggedSetsCronjobConsumer.name)
) {}

@Process({ concurrency: 1 })
async process() {
this.logger.warn("running the Application flagged sets cron job")
const outOfDateListings = await this.listingRepository
.createQueryBuilder("listings")
.select(["listings.id", "listings.afsLastRunAt"])
Expand All @@ -34,6 +37,7 @@ export class ApplicationFlaggedSetsCronjobConsumer {
)
.getMany()

this.logger.warn(`updating the flagged sets for ${outOfDateListings.length} listings`)
for (const outOfDateListing of outOfDateListings) {
try {
await this.generateAFSesForListingRules(outOfDateListing)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Module } from "@nestjs/common"
import { Logger, Module } from "@nestjs/common"
import { ApplicationFlaggedSetsController } from "./application-flagged-sets.controller"
import { ApplicationFlaggedSetsService } from "./application-flagged-sets.service"
import { TypeOrmModule } from "@nestjs/typeorm"
Expand Down Expand Up @@ -40,6 +40,7 @@ import { ListingRepository } from "../listings/db/listing.repository"
ApplicationFlaggedSetsService,
ApplicationFlaggedSetsCronjobBoostrapService,
ApplicationFlaggedSetsCronjobConsumer,
Logger,
],
exports: [
ApplicationFlaggedSetsService,
Expand Down
5 changes: 2 additions & 3 deletions backend/core/src/email/email.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ const translationServiceMock = {
readHowYouCanPrepare: "Read about how you can prepare for next steps",
needToMakeUpdates: "Need to make updates?",
ifYouNeedToUpdateInformation: "",

shouldBeChosen:
"Should your application be chosen, be prepared to fill out a more detailed application and provide required supporting documents.",
subject: "Your Application Confirmation",
Expand Down Expand Up @@ -259,7 +258,7 @@ describe("EmailService", () => {
expect(emailMock.html).toMatch("Your Confirmation Number")
expect(emailMock.html).toMatch("Marisela Baca")
expect(emailMock.html).toMatch(
/If you are contacted for an interview, you will need to fill out a more detailed application and provide supporting documents./
/Eligible applicants will be contacted on a first come first serve basis until vacancies are filled./
)
expect(emailMock.html).toMatch(/http:\/\/localhost:3000\/listing\/Uvbk5qurpB2WI9V6WnNdH/)
// contains application id
Expand All @@ -279,7 +278,7 @@ describe("EmailService", () => {

const emailMock = sendMock.mock.calls[0][0]
expect(emailMock.html).toMatch(
/The lottery will be held on December 31, 2019. Eligible applicants will be placed in order <strong>based on preference and lottery rank<\/strong>./
/Once the application period closes, eligible applicants will be placed in order based on lottery rank order./
)
})

Expand Down
39 changes: 21 additions & 18 deletions backend/core/src/email/email.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import Handlebars from "handlebars"
import path from "path"
import Polyglot from "node-polyglot"
import fs from "fs"
import dayjs from "dayjs"
import { ConfigService } from "@nestjs/config"
import { TranslationsService } from "../translations/services/translations.service"
import { JurisdictionResolverService } from "../jurisdictions/services/jurisdiction-resolver.service"
Expand Down Expand Up @@ -133,7 +132,6 @@ export class EmailService {
public async confirmation(listing: Listing, application: Application, appUrl: string) {
const jurisdiction = await this.getListingJurisdiction(listing)
void (await this.loadTranslations(jurisdiction, application.language || Language.en))
let eligibleApplicantsText
const listingUrl = `${appUrl}/listing/${listing.id}`
const compiledTemplate = this.template("confirmation")

Expand All @@ -143,29 +141,31 @@ export class EmailService {
)
}

let eligibleText
let preferenceText
let contactText = null
if (listing.reviewOrderType === ListingReviewOrder.firstComeFirstServe) {
eligibleText = this.polyglot.t("confirmation.eligible.fcfs")
preferenceText = this.polyglot.t("confirmation.eligible.fcfsPreference")
}
if (listing.reviewOrderType === ListingReviewOrder.lottery) {
const lotteryText = []
if (listing.applicationDueDate) {
lotteryText.push(
this.polyglot.t("confirmation.eligibleApplicants.lotteryDate", {
lotteryDate: dayjs(listing.applicationDueDate).format("MMMM D, YYYY"),
})
)
}
lotteryText.push(this.polyglot.t("confirmation.eligibleApplicants.lottery"))
eligibleApplicantsText = new Handlebars.SafeString(lotteryText.join(" "))
} else {
// for when listing.reviewOrderType === ListingReviewOrder.firstComeFirstServe
eligibleApplicantsText = new Handlebars.SafeString(
this.polyglot.t("confirmation.eligibleApplicants.FCFS")
)
eligibleText = this.polyglot.t("confirmation.eligible.lottery")
preferenceText = this.polyglot.t("confirmation.eligible.lotteryPreference")
}
if (listing.reviewOrderType === ListingReviewOrder.waitlist) {
eligibleText = this.polyglot.t("confirmation.eligible.waitlist")
contactText = this.polyglot.t("confirmation.eligible.waitlistContact")
preferenceText = this.polyglot.t("confirmation.eligible.waitlistPreference")
}

const user = {
firstName: application.applicant.firstName,
middleName: application.applicant.middleName,
lastName: application.applicant.lastName,
}

const nextStepsUrl = this.polyglot.t("confirmation.nextStepsUrl")

await this.send(
application.applicant.emailAddress,
jurisdiction.emailFromAddress,
Expand All @@ -179,7 +179,10 @@ export class EmailService {
listing,
listingUrl,
application,
eligibleApplicantsText,
preferenceText,
interviewText: this.polyglot.t("confirmation.interview"),
eligibleText,
contactText,
nextStepsUrl: nextStepsUrl != "confirmation.nextStepsUrl" ? nextStepsUrl : null,
user,
})
Expand Down
6 changes: 0 additions & 6 deletions backend/core/src/listings/dto/listing-published-create.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { OmitType } from "@nestjs/swagger"
import { UnitCreateDto } from "../../units/dto/unit-create.dto"
import { EnforceLowerCase } from "../../shared/decorators/enforceLowerCase.decorator"
import { ListingImageUpdateDto } from "./listing-image-update.dto"
import { ListingAvailability } from "../types/listing-availability-enum"

export class ListingPublishedCreateDto extends OmitType(ListingCreateDto, [
"assets",
Expand All @@ -39,7 +38,6 @@ export class ListingPublishedCreateDto extends OmitType(ListingCreateDto, [
"rentalAssistance",
"reviewOrderType",
"units",
"listingAvailability",
] as const) {
@Expose()
@ValidateNested({ groups: [ValidationsGroupsEnum.default], each: true })
Expand Down Expand Up @@ -77,10 +75,6 @@ export class ListingPublishedCreateDto extends OmitType(ListingCreateDto, [
@Type(() => ListingImageUpdateDto)
images: ListingImageUpdateDto[]

@Expose()
@IsEnum(ListingAvailability, { groups: [ValidationsGroupsEnum.default] })
listingAvailability: ListingAvailability | null

@Expose()
@IsEmail({}, { groups: [ValidationsGroupsEnum.default] })
@EnforceLowerCase()
Expand Down
6 changes: 0 additions & 6 deletions backend/core/src/listings/dto/listing-published-update.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { AssetUpdateDto } from "../../assets/dto/asset.dto"
import { UnitUpdateDto } from "../../units/dto/unit-update.dto"
import { EnforceLowerCase } from "../../shared/decorators/enforceLowerCase.decorator"
import { ListingImageUpdateDto } from "./listing-image-update.dto"
import { ListingAvailability } from "../types/listing-availability-enum"

export class ListingPublishedUpdateDto extends OmitType(ListingUpdateDto, [
"assets",
Expand All @@ -39,7 +38,6 @@ export class ListingPublishedUpdateDto extends OmitType(ListingUpdateDto, [
"rentalAssistance",
"reviewOrderType",
"units",
"listingAvailability",
] as const) {
@Expose()
@ValidateNested({ groups: [ValidationsGroupsEnum.default], each: true })
Expand Down Expand Up @@ -77,10 +75,6 @@ export class ListingPublishedUpdateDto extends OmitType(ListingUpdateDto, [
@Type(() => ListingImageUpdateDto)
images: ListingImageUpdateDto[]

@Expose()
@IsEnum(ListingAvailability, { groups: [ValidationsGroupsEnum.default] })
listingAvailability: ListingAvailability | null

@Expose()
@IsEmail({}, { groups: [ValidationsGroupsEnum.default] })
@EnforceLowerCase()
Expand Down
11 changes: 0 additions & 11 deletions backend/core/src/listings/entities/listing.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import { ApplicationMethod } from "../../application-methods/entities/applicatio
import { UnitsSummarized } from "../../units/types/units-summarized"
import { UnitsSummary } from "../../units-summary/entities/units-summary.entity"
import { ListingReviewOrder } from "../types/listing-review-order-enum"
import { ListingAvailability } from "../types/listing-availability-enum"
import { ApplicationMethodDto } from "../../application-methods/dto/application-method.dto"
import { ApplicationMethodType } from "../../application-methods/types/application-method-type-enum"
import { ListingFeatures } from "./listing-features.entity"
Expand Down Expand Up @@ -520,16 +519,6 @@ class Listing extends BaseEntity {
})
reviewOrderType?: ListingReviewOrder | null

@Column({ type: "enum", enum: ListingAvailability, nullable: true })
@Expose()
@IsOptional({ groups: [ValidationsGroupsEnum.default] })
@IsEnum(ListingAvailability, { groups: [ValidationsGroupsEnum.default] })
@ApiProperty({
enum: ListingAvailability,
enumName: "ListingAvailability",
})
listingAvailability?: ListingAvailability | null

@Expose()
applicationConfig?: Record<string, unknown>

Expand Down
33 changes: 33 additions & 0 deletions backend/core/src/listings/listings-cron.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Inject, Injectable, Logger } from "@nestjs/common"
import { InjectRepository } from "@nestjs/typeorm"
import { Interval } from "@nestjs/schedule"
import { ListingStatus } from "./types/listing-status-enum"
import { ListingRepository } from "./db/listing.repository"

@Injectable()
export class ListingsCronService {
constructor(
@InjectRepository(ListingRepository) private readonly listingRepository: ListingRepository,
@Inject(Logger) private readonly logger = new Logger(ListingsCronService.name)
) {}

@Interval(1000 * 60 * 60)
public async changeOverdueListingsStatusCron() {
this.logger.warn("changeOverdueListingsStatusCron job running")
const listings = await this.listingRepository
.createQueryBuilder("listings")
.select(["listings.id", "listings.applicationDueDate", "listings.status"])
.where(`listings.status = '${ListingStatus.active}'`)
.andWhere(`listings.applicationDueDate IS NOT NULL`)
.andWhere(`listings.applicationDueDate < NOW()`)
.getMany()

for (const listing of listings) {
listing.status = ListingStatus.closed
listing.closedAt = new Date()
}

await this.listingRepository.save(listings)
this.logger.warn(`Changed the status of ${listings?.length} listings`)
}
}
Loading

0 comments on commit 2964d79

Please sign in to comment.