Skip to content

Commit

Permalink
feat: external listing endpoint (#3890)
Browse files Browse the repository at this point in the history
* feat: external listing endpoint

* fix: adding some tests (temp endpoint so quick tests)

* fix: update per morgan
  • Loading branch information
YazeedLoonat authored Feb 20, 2024
1 parent c9b6a06 commit cf398c0
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 3 deletions.
20 changes: 20 additions & 0 deletions api/src/controllers/listing.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,26 @@ export class ListingController {
return await this.listingCsvExportService.exportFile(req, res, queryParams);
}

@Get(`external/:id`)
@ApiOperation({
summary: 'Get listing for external consumption by id',
operationId: 'externalRetrieve',
})
@UseInterceptors(ClassSerializerInterceptor)
@UsePipes(new ValidationPipe(defaultValidationPipeOptions))
@ApiOkResponse({ type: String })
async retrieveForExternalConsumption(
@Headers('language') language: LanguagesEnum,
@Param('id', new ParseUUIDPipe({ version: '4' })) listingId: string,
@Query() queryParams: ListingsRetrieveParams,
) {
return await this.listingService.findOneAndExternalize(
listingId,
language,
queryParams.view,
);
}

@Get(`:id`)
@ApiOperation({ summary: 'Get listing by id', operationId: 'retrieve' })
@UseInterceptors(ClassSerializerInterceptor)
Expand Down
142 changes: 142 additions & 0 deletions api/src/services/listing.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,148 @@ export class ListingService implements OnModuleInit {
return result;
}

/**
*
* @param listingId id for the listing we are querying for
* @param lang language that the translated listing should come back as
* @param view the form the listing should come back as (what data is returned)
* @returns an externalized version of the listing as a json object
*/
async findOneAndExternalize(
listingId: string,
lang: LanguagesEnum = LanguagesEnum.en,
view: ListingViews = ListingViews.full,
): Promise<string> {
const listing: any = await this.findOne(listingId, lang, view);
if (!listing) {
return '';
}

if (listing.applicationMethods) {
listing.applicationMethods.forEach((applicationMethod) => {
if (applicationMethod?.paperApplications) {
applicationMethod.paperApplications.forEach((paperApp) => {
paperApp.file = paperApp.assets;
});
}
});
}
if (listing.referralApplication) {
if (listing?.referralApplication.paperApplications) {
listing?.referralApplication.paperApplications.forEach((paperApp) => {
paperApp.file = paperApp.assets;
});
}
}
if (listing.listingsResult) {
listing.result = listing.listingsResult;
}
if (listing.listingsBuildingSelectionCriteriaFile) {
listing.buildingSelectionCriteriaFile =
listing.listingsBuildingSelectionCriteriaFile;
}
if (listing.listingsBuildingAddress) {
listing.buildingAddress = listing.listingsBuildingAddress;
}
if (listing.listingsApplicationPickUpAddress) {
listing.applicationPickUpAddress =
listing.listingsApplicationPickUpAddress;
}
if (listing.listingsApplicationDropOffAddress) {
listing.applicationDropOffAddress =
listing.listingsApplicationDropOffAddress;
}
if (listing.listingsApplicationMailingAddress) {
listing.applicationMailingAddress =
listing.listingsApplicationMailingAddress;
}
if (listing.listingsLeasingAgentAddress) {
listing.leasingAgentAddress = listing.listingsLeasingAgentAddress;
}
if (listing.listingUtilities) {
listing.utilities = listing.listingUtilities;
}
if (listing.listingFeatures) {
listing.features = listing.listingFeatures;
}
if (listing.jurisdictions) {
listing.jurisdiction = listing.jurisdictions;
}
if (listing.reservedCommunityTypes) {
listing.reservedCommunityType = listing.reservedCommunityTypes;
}
if (listing.listingEvents) {
listing.listingEvents.forEach((event) => {
if (event.assets) {
event.file = event.assets;
}
});
listing.events = listing.listingEvents;
}
if (listing.listingImages) {
listing.listingImages.forEach((image) => {
if (image.assets) {
image.image = image.assets;
}
});
listing.images = listing.listingImages;
}
if (listing.requestedChangesUser) {
delete listing.requestedChangesUser;
}
if (listing.listingMultiselectQuestions) {
listing.listingMultiselectQuestions.forEach(
(listingMultiselectQuestion) => {
listingMultiselectQuestion.multiselectQuestion =
listingMultiselectQuestion.multiselectQuestions;
},
);
}
if (listing.units) {
listing.units.forEach((unit) => {
if (unit.unitTypes) {
unit.unitType = unit.unitTypes;
}
if (unit.unitRentTypes) {
unit.unitRentType = unit.unitRentTypes;
}
if (unit.unitAccessibilityPriorityTypes) {
unit.priorityType = unit.unitAccessibilityPriorityTypes;
}
if (unit.unitAmiChartOverrides) {
unit.amiChartOverride = unit.unitAmiChartOverrides;
}
});
}
if (listing.unitsSummary) {
listing.unitsSummary.forEach((unitsSummary) => {
unitsSummary.unitType = unitsSummary.unitTypes;
});
}
if (listing.unitsSummarized) {
if (listing.unitsSummarized.byUnitTypeAndRent) {
listing.unitsSummarized.byUnitTypeAndRent.forEach((unitsSummary) => {
unitsSummary.unitType = unitsSummary.unitTypes;
});
}
if (listing.unitsSummarized.byUnitType) {
listing.unitsSummarized.byUnitType.forEach((unitsSummary) => {
unitsSummary.unitType = unitsSummary.unitTypes;
});
}
if (listing.unitsSummarized.byAMI) {
listing.unitsSummarized.byAMI.forEach((byAMI) => {
if (byAMI.byUnitType) {
byAMI.byUnitType.forEach((unitSummary) => {
unitSummary.unitType = unitSummary.unitTypes;
});
}
});
}
}
return JSON.stringify(listing);
}

/*
creates a listing
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,20 @@ describe('Testing Permissioning of endpoints as Admin User', () => {
.expect(200);
});

it('should succeed for external listing endpoint', async () => {
const listingA = await listingFactory(jurisdictionAId, prisma);
const listingACreated = await prisma.listings.create({
data: listingA,
include: {
listingMultiselectQuestions: true,
},
});
await request(app.getHttpServer())
.get(`/listings/external/${listingACreated.id}`)
.set('Cookie', cookies)
.expect(200);
});

it('should succeed for delete endpoint & create an activity log entry', async () => {
const jurisdictionA = await generateJurisdiction(
prisma,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,20 @@ describe('Testing Permissioning of endpoints as Jurisdictional Admin in the corr
.expect(200);
});

it('should succeed for external listing endpoint', async () => {
const listingA = await listingFactory(jurisId, prisma);
const listingACreated = await prisma.listings.create({
data: listingA,
include: {
listingMultiselectQuestions: true,
},
});
await request(app.getHttpServer())
.get(`/listings/external/${listingACreated.id}`)
.set('Cookie', cookies)
.expect(200);
});

it('should succeed for delete endpoint & create an activity log entry', async () => {
const listingData = await listingFactory(jurisId, prisma);
const listing = await prisma.listings.create({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,20 @@ describe('Testing Permissioning of endpoints as Jurisdictional Admin in the wron
.expect(200);
});

it('should succeed for external listing endpoint', async () => {
const listingA = await listingFactory(jurisId, prisma);
const listingACreated = await prisma.listings.create({
data: listingA,
include: {
listingMultiselectQuestions: true,
},
});
await request(app.getHttpServer())
.get(`/listings/external/${listingACreated.id}`)
.set('Cookie', cookies)
.expect(200);
});

it('should error as forbidden for delete endpoint', async () => {
const listingData = await listingFactory(jurisId, prisma);
const listing = await prisma.listings.create({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,20 @@ describe('Testing Permissioning of endpoints as logged out user', () => {
.expect(200);
});

it('should succeed for external listing endpoint', async () => {
const listingA = await listingFactory(jurisdictionAId, prisma);
const listingACreated = await prisma.listings.create({
data: listingA,
include: {
listingMultiselectQuestions: true,
},
});
await request(app.getHttpServer())
.get(`/listings/external/${listingACreated.id}`)
.set('Cookie', cookies)
.expect(200);
});

it('should error as forbidden for delete endpoint', async () => {
const jurisdictionA = await generateJurisdiction(
prisma,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { applicationFactory } from '../../../prisma/seed-helpers/application-fac
import { addressFactory } from '../../../prisma/seed-helpers/address-factory';
import { AddressCreate } from '../../../src/dtos/addresses/address-create.dto';
import {
reservedCommunityTypeFactory,
reservedCommunityTypeFactoryAll,
reservedCommunityTypeFactoryGet,
} from '../../../prisma/seed-helpers/reserved-community-type-factory';
Expand Down Expand Up @@ -965,6 +964,13 @@ describe('Testing Permissioning of endpoints as partner with correct listing', (
.expect(200);
});

it('should succeed for external listing endpoint', async () => {
await request(app.getHttpServer())
.get(`/listings/external/${userListingId}`)
.set('Cookie', cookies)
.expect(200);
});

it('should error as forbidden for delete endpoint', async () => {
await request(app.getHttpServer())
.delete(`/listings/`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { applicationFactory } from '../../../prisma/seed-helpers/application-fac
import { addressFactory } from '../../../prisma/seed-helpers/address-factory';
import { AddressCreate } from '../../../src/dtos/addresses/address-create.dto';
import {
reservedCommunityTypeFactory,
reservedCommunityTypeFactoryAll,
reservedCommunityTypeFactoryGet,
} from '../../../prisma/seed-helpers/reserved-community-type-factory';
Expand Down Expand Up @@ -953,6 +952,13 @@ describe('Testing Permissioning of endpoints as partner with wrong listing', ()
.expect(200);
});

it('should succeed for external listing endpoint', async () => {
await request(app.getHttpServer())
.get(`/listings/external/${listingId}`)
.set('Cookie', cookies)
.expect(200);
});

it('should error as forbidden for delete endpoint', async () => {
await request(app.getHttpServer())
.delete(`/listings/`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,20 @@ describe('Testing Permissioning of endpoints as public user', () => {
.expect(200);
});

it('should succeed for retrieveListings endpoint', async () => {
const listingA = await listingFactory(jurisdictionAId, prisma);
const listingACreated = await prisma.listings.create({
data: listingA,
include: {
listingMultiselectQuestions: true,
},
});
await request(app.getHttpServer())
.get(`/listings/external/${listingACreated.id}`)
.set('Cookie', cookies)
.expect(200);
});

it('should error as forbidden for delete endpoint', async () => {
const jurisdictionA = await generateJurisdiction(
prisma,
Expand Down
26 changes: 25 additions & 1 deletion shared-helpers/src/types/backend-swagger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,30 @@ export class ListingsService {
axios(configs, resolve, reject)
})
}
/**
* Get listing for external consumption by id
*/
externalRetrieve(
params: {
/** */
id: string
/** */
view?: ListingViews
} = {} as any,
options: IRequestOptions = {}
): Promise<string> {
return new Promise((resolve, reject) => {
let url = basePath + "/listings/external/{id}"
url = url.replace("{id}", params["id"] + "")

const configs: IRequestConfig = getConfigs("get", "application/json", url, options)
configs.params = { view: params["view"] }

/** 适配ios13,get请求不允许带body */

axios(configs, resolve, reject)
})
}
/**
* Get listing by id
*/
Expand Down Expand Up @@ -4910,7 +4934,7 @@ export interface UserCreate {
email: string

/** */
emailConfirmation: string
emailConfirmation?: string

/** */
jurisdictions?: IdDTO[]
Expand Down

0 comments on commit cf398c0

Please sign in to comment.