Skip to content

Commit 1c6fb7a

Browse files
Merge pull request #25 from bloom-housing/release/2-26-26
feat: release 2-26-26
2 parents 1e4e351 + 8fb76bb commit 1c6fb7a

File tree

29 files changed

+548
-94
lines changed

29 files changed

+548
-94
lines changed

api/prisma/seed-helpers/jurisdiction-factory.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import { RaceEthnicityConfiguration } from '../../src/dtos/jurisdictions/race-et
1111
import { SpokenLanguageEnum } from '../../src/enums/applications/spoken-language-enum';
1212

1313
export const jurisdictionFactory = (
14-
jurisdictionName = randomName(),
14+
jurisdictionName = `${randomName()} ${Math.random()
15+
.toString(16)
16+
.substring(2, 8)}`,
1517
optionalFields?: {
1618
listingApprovalPermissions?: UserRoleEnum[];
1719
duplicateListingPermissions?: UserRoleEnum[];

api/prisma/seed-helpers/user-factory.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const userFactory = async (optionalParams?: {
1414
mfaEnabled?: boolean;
1515
middleName?: string;
1616
password?: string;
17+
isApproved?: boolean;
1718
phoneNumber?: string;
1819
phoneNumberVerified?: boolean;
1920
roles?: Prisma.UserRolesUncheckedCreateWithoutUserAccountsInput;
@@ -43,6 +44,8 @@ export const userFactory = async (optionalParams?: {
4344
singleUseCode: optionalParams?.singleUseCode || null,
4445
singleUseCodeUpdatedAt: optionalParams?.mfaEnabled ? new Date() : undefined,
4546
language: optionalParams?.language || undefined,
47+
isAdvocate: optionalParams?.isAdvocate || undefined,
48+
isApproved: optionalParams?.isApproved || undefined,
4649
favoriteListings: optionalParams?.favoriteListings
4750
? {
4851
connect: optionalParams.favoriteListings.map((listing) => {
@@ -80,8 +83,6 @@ export const userFactory = async (optionalParams?: {
8083
},
8184
}
8285
: undefined,
83-
isAdvocate: optionalParams?.isAdvocate,
84-
isApproved: optionalParams?.isAdvocate,
8586
agency: optionalParams?.agencyId
8687
? {
8788
connect: {

api/prisma/seed-staging.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,51 @@ export const stagingSeed = async (
813813
}),
814814
},
815815
);
816+
const mobilityAccessibilityNeedsProgramQuestion =
817+
await prismaClient.multiselectQuestions.create({
818+
data: multiselectQuestionFactory(angelopolisJurisdiction.id, {
819+
multiselectQuestion: {
820+
text: 'Mobility accessibility needs',
821+
description:
822+
'Some units require at least one resident to have a mobility accessibility need',
823+
applicationSection:
824+
MultiselectQuestionsApplicationSectionEnum.programs,
825+
optOutText: 'None of the above',
826+
options: [
827+
{ text: 'Wheelchair', ordinal: 0 },
828+
{ text: 'Walker', ordinal: 1 },
829+
{ text: 'Power chair', ordinal: 2 },
830+
{ text: 'Other mobility device', ordinal: 3 },
831+
],
832+
},
833+
}),
834+
});
835+
const hearingVisionAccessibilityNeedsProgramQuestion =
836+
await prismaClient.multiselectQuestions.create({
837+
data: multiselectQuestionFactory(angelopolisJurisdiction.id, {
838+
multiselectQuestion: {
839+
text: 'Hearing/vision accessibility needs',
840+
description:
841+
'Some units require at least one resident to have a hearing / vision accessibility need',
842+
applicationSection:
843+
MultiselectQuestionsApplicationSectionEnum.programs,
844+
optOutText: 'None of the above',
845+
options: [
846+
{ text: 'Audible and visual doorbells', ordinal: 0 },
847+
{
848+
text: 'Fire and smoke alarms with hard wired strobes',
849+
ordinal: 1,
850+
},
851+
{
852+
text: 'Documents in screen-reader accessible format',
853+
ordinal: 2,
854+
},
855+
{ text: 'Documents in large text or braille', ordinal: 3 },
856+
],
857+
},
858+
}),
859+
});
860+
816861
const multiselectQuestionPrograms =
817862
await prismaClient.multiselectQuestions.create({
818863
data: multiselectQuestionFactory(mainJurisdiction.id, {
@@ -932,6 +977,8 @@ export const stagingSeed = async (
932977
cityEmployeeQuestion,
933978
workInCityQuestion,
934979
multiselectQuestionPrograms,
980+
mobilityAccessibilityNeedsProgramQuestion,
981+
hearingVisionAccessibilityNeedsProgramQuestion,
935982
],
936983
applications: [
937984
await applicationFactory({

api/src/dtos/users/advocate-user-update.dto.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
ValidateNested,
1313
} from 'class-validator';
1414
import { ValidationsGroupsEnum } from '../../enums/shared/validation-groups-enum';
15-
import Agency from '../agency/agency.dto';
1615
import { User } from './user.dto';
1716
import { EnforceLowerCase } from '../../decorators/enforce-lower-case.decorator';
1817
import { passwordRegex } from '../../utilities/password-regex';
Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { Expose } from 'class-transformer';
1+
import { Expose, Transform } from 'class-transformer';
22
import { ApiPropertyOptional } from '@nestjs/swagger';
3-
import { IsString } from 'class-validator';
3+
import { IsBoolean } from 'class-validator';
44
import { ValidationsGroupsEnum } from '../../enums/shared/validation-groups-enum';
55

66
export class UserFilterParams {
@@ -9,6 +9,20 @@ export class UserFilterParams {
99
type: Boolean,
1010
example: true,
1111
})
12-
@IsString({ groups: [ValidationsGroupsEnum.default] })
12+
@Transform(({ value }) =>
13+
typeof value === 'boolean' ? value : value === 'true',
14+
)
15+
@IsBoolean({ groups: [ValidationsGroupsEnum.default] })
1316
isPortalUser?: boolean;
17+
18+
@Expose()
19+
@ApiPropertyOptional({
20+
type: Boolean,
21+
example: false,
22+
})
23+
@Transform(({ value }) =>
24+
typeof value === 'boolean' ? value : value === 'true',
25+
)
26+
@IsBoolean({ groups: [ValidationsGroupsEnum.default] })
27+
isAdvocateUser?: boolean;
1428
}

api/src/dtos/users/user-query-param.dto.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
import { PaginationAllowsAllQueryParams } from '../shared/pagination.dto';
2-
import { Expose, Type } from 'class-transformer';
2+
import { Expose, Transform, Type } from 'class-transformer';
33
import { ApiPropertyOptional, getSchemaPath } from '@nestjs/swagger';
44
import { UserFilterParams } from './user-filter-params.dto';
55
import {
66
ArrayMaxSize,
77
IsArray,
8+
IsEnum,
89
IsString,
910
MinLength,
11+
Validate,
1012
ValidateNested,
1113
} from 'class-validator';
1214
import { ValidationsGroupsEnum } from '../../enums/shared/validation-groups-enum';
15+
import { UserOrderByKeys } from '../../enums/listings/order-by-enum';
16+
import { OrderByEnum } from '../../enums/shared/order-by-enum';
17+
import { OrderQueryParamValidator } from '../../utilities/order-by-validator';
1318

1419
export class UserQueryParams extends PaginationAllowsAllQueryParams {
1520
@Expose()
@@ -38,4 +43,42 @@ export class UserQueryParams extends PaginationAllowsAllQueryParams {
3843
groups: [ValidationsGroupsEnum.default],
3944
})
4045
search?: string;
46+
47+
@Expose()
48+
@ApiPropertyOptional({
49+
enum: UserOrderByKeys,
50+
enumName: 'UserOrderByKeys',
51+
example: ['isApproved'],
52+
default: ['isApproved'],
53+
isArray: true,
54+
})
55+
@IsArray({ groups: [ValidationsGroupsEnum.default] })
56+
@ArrayMaxSize(16, { groups: [ValidationsGroupsEnum.default] })
57+
@IsEnum(UserOrderByKeys, {
58+
groups: [ValidationsGroupsEnum.default],
59+
each: true,
60+
})
61+
@Validate(OrderQueryParamValidator, {
62+
groups: [ValidationsGroupsEnum.default],
63+
})
64+
orderBy?: UserOrderByKeys[];
65+
66+
@Expose()
67+
@ApiPropertyOptional({
68+
enum: OrderByEnum,
69+
enumName: 'OrderByEnum',
70+
example: ['desc'],
71+
default: ['desc'],
72+
isArray: true,
73+
})
74+
@IsArray({ groups: [ValidationsGroupsEnum.default] })
75+
@ArrayMaxSize(16, { groups: [ValidationsGroupsEnum.default] })
76+
@Transform(({ value }) => {
77+
return value ? value.map((val) => val.toLowerCase()) : undefined;
78+
})
79+
@IsEnum(OrderByEnum, { groups: [ValidationsGroupsEnum.default], each: true })
80+
@Validate(OrderQueryParamValidator, {
81+
groups: [ValidationsGroupsEnum.default],
82+
})
83+
orderDir?: OrderByEnum[];
4184
}

api/src/dtos/users/user.dto.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,9 @@ export class User extends AbstractDTO {
193193
@IsString({ groups: [ValidationsGroupsEnum.default] })
194194
@ApiPropertyOptional()
195195
additionalPhoneExtension?: string;
196+
197+
@Expose()
198+
@IsBoolean({ groups: [ValidationsGroupsEnum.default] })
199+
@ApiPropertyOptional()
200+
isApproved?: boolean;
196201
}

api/src/enums/listings/order-by-enum.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,7 @@ export enum ListingOrderByKeys {
1212
marketingSeason = 'marketingSeason',
1313
listingType = 'listingType',
1414
}
15+
16+
export enum UserOrderByKeys {
17+
isApproved = 'isApproved',
18+
}

api/src/services/listing.service.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import {
5959
import {
6060
summarizeUnitsByTypeAndRent,
6161
summarizeUnits,
62+
summarizeByPriorityType,
6263
} from '../utilities/unit-utilities';
6364
import { fillModelStringFields } from '../utilities/model-fields';
6465
import { doJurisdictionHaveFeatureFlagSet } from '../utilities/feature-flag-utilities';
@@ -286,6 +287,7 @@ export class ListingService implements OnModuleInit {
286287
listing.units,
287288
listing,
288289
),
290+
priorityTypes: summarizeByPriorityType(listing),
289291
};
290292
}
291293
});

api/src/services/user.service.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,12 @@ export class UserService {
147147
skip: calculateSkip(params.limit, page),
148148
take: calculateTake(params.limit),
149149
orderBy: buildOrderBy(
150-
['firstName', 'lastName'],
151-
[OrderByEnum.ASC, OrderByEnum.ASC],
150+
['firstName', 'lastName', ...(params.orderBy ? params.orderBy : [])],
151+
[
152+
OrderByEnum.ASC,
153+
OrderByEnum.ASC,
154+
...(params.orderDir ? params.orderDir : []),
155+
],
152156
),
153157
include: views.full,
154158
where: whereClause,

0 commit comments

Comments
 (0)