Skip to content

Commit

Permalink
Project creation endpoint
Browse files Browse the repository at this point in the history
Create an endpoint through which users may create a new project
Update typescript-eslint to a version that supports decorators

closes #1246

Co-authored-by: horatio <[email protected]>
  • Loading branch information
TangoYankee and horatiorosa committed Nov 12, 2024
1 parent e0965b5 commit ef11f66
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 92 deletions.
6 changes: 3 additions & 3 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@
"@types/superagent-proxy": "^3.0.4",
"@types/supertest": "^6.0.2",
"@types/underscore": "^1.11.15",
"@typescript-eslint/eslint-plugin": "^2.23.0",
"@typescript-eslint/parser": "^2.23.0",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.61.0",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-import": "^2.20.1",
Expand All @@ -85,7 +85,7 @@
"ts-loader": "^6.2.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.2.3"
"typescript": "^4.9.5"
},
"jest": {
"moduleNameMapper": {
Expand Down
4 changes: 2 additions & 2 deletions server/src/config/config.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class ConfigService {

get featureFlag() {
return {
selfService: this.envConfig["FEATURE_FLAG_SELF_SERVICE"] === "ON"
}
selfService: this.envConfig['FEATURE_FLAG_SELF_SERVICE'] === 'ON',
};
}
}
14 changes: 11 additions & 3 deletions server/src/contact/contact.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ export class ContactController {
) {}

@Get('/')
async getContact(@Session() session, @Query('me') me, @Query('email') email, @Query('includeAllStatusCodes') includeAllStatusCodes = 'false') {
async getContact(
@Session() session,
@Query('me') me,
@Query('email') email,
@Query('includeAllStatusCodes') includeAllStatusCodes = 'false',
) {
// if this is a self-check, lookup the contact id from session
if (me) {
const { contactId } = session;
Expand All @@ -56,15 +61,18 @@ export class ContactController {
return this.contactService.findOneById(contactId);
}
} else {
return this.contactService.findOneByEmail(email, includeAllStatusCodes === 'true');
return this.contactService.findOneByEmail(
email,
includeAllStatusCodes === 'true',
);
}
}

@UseGuards(AuthenticateGuard)
@UsePipes(JsonApiDeserializePipe)
@Post('/')
async create(@Body() body) {
return await this.contactService.create(body);
return await this.contactService.create(body);
}

@UseGuards(AuthenticateGuard)
Expand Down
2 changes: 2 additions & 0 deletions server/src/projects/projects.attrs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export const PROJECT_ATTRS = [
'dcp_visibility',
'dcp_publicstatus',
'dcp_projectbrief',
'dcp_applicanttype',
'_dcp_applicant_customer_value',
'_dcp_applicantadministrator_customer_value',
'dcp_dcp_project_dcp_projectapplicant_Project',

'dcp_nonresatleast50000',
Expand Down
24 changes: 16 additions & 8 deletions server/src/projects/projects.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,25 @@ export class ProjectsController {

@Post('/')
async createProject(@Body() body) {
const allowedAttrs = pick(body, PROJECT_ATTRS) as {
dcp_projectname: string;
dcp_borough: string;
dcp_applicanttype: string;
dcp_projectbrief: string;
_dcp_applicant_customer_value: string;
_dcp_applicantadministrator_customer_value: string;
};
if (!this.config.featureFlag.selfService) {
throw new HttpException({
code: "NOT_FOUND",
title: "Not found",
},
HttpStatus.NOT_FOUND)
throw new HttpException(
{
code: 'NOT_FOUND',
title: 'Not found',
},
HttpStatus.NOT_FOUND,
);
}

return {
...body
}
return await this.projectsService.create(allowedAttrs);
}

@Get('/:id')
Expand Down
67 changes: 53 additions & 14 deletions server/src/projects/projects.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class ProjectsService {
any(o:
o/_dcp_applicant_customer_value eq '${contactId}'
and o/statuscode eq ${APPLICANT_ACTIVE_STATUS_CODE}
)
)
and (
dcp_visibility eq ${PROJECT_VISIBILITY_APPLICANT_ONLY}
or dcp_visibility eq ${PROJECT_VISIBILITY_GENERAL_PUBLIC}
Expand Down Expand Up @@ -95,6 +95,45 @@ export class ProjectsService {
}
}

/**
* Create a project, including the contact id for the primary contact and applicant
* Lead planner is automatically assigned by CRM based on the borough
*
* @param body
*/
public async create(attributes: {
dcp_projectname: string;
dcp_borough: string;
dcp_applicanttype: string;
dcp_projectbrief: string;
_dcp_applicant_customer_value: string;
_dcp_applicantadministrator_customer_value: string;
}) {
try {
const data = {
dcp_projectname: attributes.dcp_projectname,
dcp_borough: attributes.dcp_borough,
dcp_applicanttype: attributes.dcp_applicanttype,
dcp_projectbrief: attributes.dcp_projectbrief,
'[email protected]': `/contacts(${attributes._dcp_applicant_customer_value})`,
'[email protected]': `/contacts(${attributes._dcp_applicantadministrator_customer_value})`,
};
const { dcp_projectid } = await this.crmService.create(
'dcp_projects',
data,
);
return {
dcp_projectid,
};
} catch (e) {
console.debug('error creating project', e);
throw new HttpException(
'Unable to create project',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}

/**
* Gets a Project for given dcp_projectid and contactid
*
Expand Down Expand Up @@ -123,19 +162,19 @@ export class ProjectsService {
$filter= statuscode eq ${APPLICANT_ACTIVE_STATUS_CODE}
),
dcp_dcp_project_dcp_dcpprojectteam_project,
dcp_dcp_project_dcp_package_project(
$filter=
(
dcp_visibility eq ${PACKAGE_VISIBILITY.APPLICANT_ONLY}
or dcp_visibility eq ${PACKAGE_VISIBILITY.GENERAL_PUBLIC}
)
and (
statuscode eq ${PACKAGE_STATUSCODE.PACKAGE_PREPARATION}
or statuscode eq ${PACKAGE_STATUSCODE.SUBMITTED}
or statuscode eq ${PACKAGE_STATUSCODE.UNDER_REVIEW}
or statuscode eq ${PACKAGE_STATUSCODE.REVIEWED_NO_REVISIONS_REQUIRED}
or statuscode eq ${PACKAGE_STATUSCODE.REVIEWED_REVISION_REQUIRED}
)
dcp_dcp_project_dcp_package_project(
$filter=
(
dcp_visibility eq ${PACKAGE_VISIBILITY.APPLICANT_ONLY}
or dcp_visibility eq ${PACKAGE_VISIBILITY.GENERAL_PUBLIC}
)
and (
statuscode eq ${PACKAGE_STATUSCODE.PACKAGE_PREPARATION}
or statuscode eq ${PACKAGE_STATUSCODE.SUBMITTED}
or statuscode eq ${PACKAGE_STATUSCODE.UNDER_REVIEW}
or statuscode eq ${PACKAGE_STATUSCODE.REVIEWED_NO_REVISIONS_REQUIRED}
or statuscode eq ${PACKAGE_STATUSCODE.REVIEWED_REVISION_REQUIRED}
)
),
dcp_dcp_project_dcp_projectmilestone_project(
$select=${MILESTONE_ATTRS.join(',')};
Expand Down
8 changes: 4 additions & 4 deletions server/src/provider/msal.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export const MsalProvider: FactoryProvider<MsalProviderType> = {
'SHAREPOINT_CLIENT_SECRET',
);
const siteId: string | undefined = config.get('SHAREPOINT_SITE_ID');
if(tenantId === undefined) throw new Error("Missing tenant id")
if(clientId === undefined) throw new Error("Missing client id")
if(clientSecret === undefined) throw new Error("Missing client secret")
if(siteId === undefined) throw new Error("Missing site id")
if (tenantId === undefined) throw new Error('Missing tenant id');
if (clientId === undefined) throw new Error('Missing client id');
if (clientSecret === undefined) throw new Error('Missing client secret');
if (siteId === undefined) throw new Error('Missing site id');

const cca = new msal.ConfidentialClientApplication({
auth: {
Expand Down
Loading

0 comments on commit ef11f66

Please sign in to comment.