Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save an Activity Report #102

Merged
merged 23 commits into from
Jan 15, 2021
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4b4333a
begin ar
SarahJaine Dec 3, 2020
fa7b032
add ar validation checkRequiredForSubmission
SarahJaine Dec 3, 2020
05b1d98
first pass at secondary tables
SarahJaine Dec 4, 2020
e550671
remove multiselects
SarahJaine Dec 8, 2020
fddb56b
stash
jasalisbury Dec 23, 2020
cab758e
merge main
SarahJaine Dec 23, 2020
7d4965d
nongrantee extends
SarahJaine Dec 30, 2020
521661d
Merge branch 'main' into sj-activity-report
jasalisbury Jan 6, 2021
2d5378e
Merge branch 'main' into stash--saving-pt-2
jasalisbury Jan 6, 2021
c93c902
Merge branch 'main' into sj-activity-report
jasalisbury Jan 6, 2021
7234e1b
Merge branch 'stash--saving-pt-2' into sj-activity-report
jasalisbury Jan 7, 2021
5df666a
Add activity report endpoints
jasalisbury Jan 13, 2021
6879d12
Merge branch 'main' into sj-activity-report
jasalisbury Jan 13, 2021
432110d
Moving around seeders
jasalisbury Jan 13, 2021
fa1f120
Fix test
jasalisbury Jan 13, 2021
7affa8f
Fix axe/cucumber/backend tests
jasalisbury Jan 14, 2021
5b7043c
Merge branch 'main' into sj-activity-report
jasalisbury Jan 14, 2021
293ef60
Revert "stash"
jasalisbury Jan 14, 2021
36b176b
Continuing to revert frontend changes
jasalisbury Jan 14, 2021
471a66d
Merge branch 'sj-activity-report' of github.com:adhocteam/Head-Start-…
jasalisbury Jan 14, 2021
59c2547
Revert last of the frontend changes
jasalisbury Jan 14, 2021
203feae
Add grant fields that had been removed
jasalisbury Jan 14, 2021
ef0cfba
Move DB access layer to `services`. fix typo
jasalisbury Jan 15, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 80 additions & 9 deletions docs/openapi/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,93 @@ paths:
$ref: "./paths/index.yaml"
components:
schemas:
activityReport:
type: object
properties:
id:
type: number
userId:
type: number
lastUpdatedById:
type: number
resourcesUsed:
type: string
additionalNotes:
type: string
numberOfParticipants:
type: number
deliveryMethod:
type: string
duration:
type: number
endDate:
type: string
startDate:
type: string
participantType:
type: string
requester:
type: string
programTypes:
type: array
items:
type: string
targetPopulations:
type: array
items:
type: string
reason:
type: array
items:
type: string
participants:
type: array
items:
type: string
topics:
type: array
items:
type: string
pageState:
type: object
properties:
1:
type: string
2:
type: string
3:
type: string
4:
type: string
status:
type: string
ttaType:
type: array
items:
type: string
approvingUser:
type: object
properties:
id:
type: number
name:
type: string
participant:
type: object
properties:
participantId:
type: number
name:
type: string
permission:
type: object
properties:
userId:
type: number
scopeId:
type: number
regionId:
type: number
user:
type: object
properties:
Expand All @@ -44,12 +124,3 @@ components:
type: array
items:
$ref: '#/components/schemas/permission'
permission:
type: object
properties:
userId:
type: number
scopeId:
type: number
regionId:
type: number
41 changes: 41 additions & 0 deletions docs/openapi/paths/activity-reports/activity-reports-id.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
get:
tags:
- activity-reports
summary: Retrieve an activity report
parameters:
- in: path
name: activityReportId
required: true
schema:
type: number
responses:
200:
description: The activity report with an Id of {activityReportId}
content:
application/json:
schema:
$ref: '../../index.yaml#/components/schemas/activityReport'
put:
tags:
- activity-reports
summary: Update an activity report
requestBody:
description: A new activity report
required: true
content:
application/json:
schema:
$ref: '../../index.yaml#/components/schemas/activityReport'
parameters:
- in: path
name: activityReportId
required: true
schema:
type: number
responses:
200:
description: The updated activity report
content:
application/json:
schema:
$ref: '../../index.yaml#/components/schemas/activityReport'
18 changes: 18 additions & 0 deletions docs/openapi/paths/activity-reports/activity-reports.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
post:
tags:
- activity-reports
summary: Create a new activity report
requestBody:
description: A new activity report
required: true
content:
application/json:
schema:
$ref: '../../index.yaml#/components/schemas/activityReport'
responses:
200:
description: Successfully created activity report
content:
application/json:
schema:
$ref: '../../index.yaml#/components/schemas/activityReport'
23 changes: 23 additions & 0 deletions docs/openapi/paths/activity-reports/participants.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
get:
tags:
- activity-reports
summary: >
Get possible participants for an activity report
description: >
A participant is either a grant or nonGrantee.
responses:
200:
description: The possible participants
content:
application/json:
schema:
type: object
properties:
grants:
type: array
items:
$ref: '../../index.yaml#/components/schemas/participant'
nonGrantees:
type: array
items:
$ref: '../../index.yaml#/components/schemas/participant'
8 changes: 7 additions & 1 deletion docs/openapi/paths/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@
$ref: './admin.yaml'
'/admin/users':
$ref: './adminAllUsers.yaml'
'/activity-reports':
$ref: './activity-reports/activity-reports.yaml'
'/activity-reports/approvers':
$ref: './activity-reports/approvers.yaml'
$ref: './activity-reports/approvers.yaml'
'/activity-reports/participants':
$ref: './activity-reports/participants.yaml'
'/activity-reports/{activityReportId}':
$ref: './activity-reports/activity-reports-id.yaml'
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"server:debug": "nodemon src/index.js --exec babel-node --inspect",
"client": "yarn --cwd frontend start",
"test": "jest src",
"test:ci": "cross-env JEST_JUNIT_OUTPUT_DIR=reports JEST_JUNIT_OUTPUT_NAME=unit.xml POSTGRES_USERNAME=postgres POSTGRES_DB=ttasmarthub CURRENT_USER_ID=5 CI=true jest src tools --coverage --reporters=default --reporters=jest-junit",
"test:ci": "cross-env JEST_JUNIT_OUTPUT_DIR=reports JEST_JUNIT_OUTPUT_NAME=unit.xml POSTGRES_USERNAME=postgres POSTGRES_DB=ttasmarthub CURRENT_USER_ID=5 CI=true jest src tools --runInBand --coverage --reporters=default --reporters=jest-junit",
"test:all": "yarn test:ci && yarn --cwd frontend test:ci",
"lint": "eslint src",
"lint:ci": "eslint -f eslint-formatter-multiple src",
Expand Down Expand Up @@ -148,6 +148,7 @@
"http-codes": "^1.0.0",
"lodash": "^4.17.20",
"memorystore": "^1.6.2",
"moment": "^2.29.1",
"mz": "^2.7.0",
"newrelic": "^7.0.1",
"pg": "^8.3.3",
Expand Down
140 changes: 140 additions & 0 deletions src/lib/activityReports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import _ from 'lodash';
import { Op } from 'sequelize';

import {
ActivityReport,
sequelize,
ActivityParticipant,
Grant,
Grantee,
NonGrantee,
} from '../models';

async function saveReportParticipants(
activityReportId,
participantIds,
participantType,
transaction,
) {
await ActivityParticipant.destroy({
where: {
activityReportId: {
[Op.eq]: activityReportId,
},
},
transaction,
});

await Promise.all(participantIds.map(async (participantId) => {
const activityParticipant = {
activityReportId,
};

if (participantType === 'grantee') {
activityParticipant.grantId = participantId;
} else if (participantType === 'non-grantee') {
activityParticipant.nonGranteeId = participantId;
}

return ActivityParticipant.create(activityParticipant, { transaction });
}));
}

async function update(newReport, activityReportId, transaction) {
const result = await ActivityReport.update(newReport, {
where: {
id: {
[Op.eq]: activityReportId,
},
},
returning: true,
plain: true,
transaction,
fields: _.keys(newReport),
});
return result[1];
}

async function create(report, transaction) {
return ActivityReport.create(report, { transaction });
}

export function activityReportById(activityReportId) {
return ActivityReport.findOne({
where: {
id: {
[Op.eq]: activityReportId,
},
},
include: [
{
model: ActivityParticipant,
attributes: ['id', 'name', 'participantId'],
as: 'activityParticipants',
required: false,
include: [
{
model: Grant,
attributes: ['id', 'number'],
as: 'grant',
required: false,
include: [{
model: Grantee,
as: 'grantee',
attributes: ['name'],
}],
},
{
model: NonGrantee,
as: 'nonGrantee',
required: false,
},
],
},
],
});
}

export async function createOrUpdate(newActivityReport, activityReportId) {
let savedReport;
await sequelize.transaction(async (transaction) => {
if (activityReportId) {
savedReport = await update(newActivityReport, activityReportId, transaction);
} else {
savedReport = await create(newActivityReport, transaction);
}

if (newActivityReport.activityParticipants) {
const { participantType, id } = savedReport;
const participantIds = newActivityReport.activityParticipants.map((g) => g.participantId);
await saveReportParticipants(id, participantIds, participantType, transaction);
}
});
return activityReportById(savedReport.id);
}

export async function reportParticipants() {
const rawGrants = await Grant.findAll({
attributes: ['id', 'name', 'number'],
include: [{
model: Grantee,
as: 'grantee',
}],
});

const grants = rawGrants.map((g) => ({
participantId: g.id,
name: g.name,
}));

const nonGrantees = await NonGrantee.findAll({
raw: true,
attributes: [['id', 'participantId'], 'name'],
});
return { grants, nonGrantees };
}

export async function reportExists(activityReportId) {
const report = await ActivityReport.findOne({ where: { id: activityReportId } });
return !_.isNull(report);
}
4 changes: 2 additions & 2 deletions src/lib/apiErrorHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ async function handleSequelizeError(req, res, error, logContext) {
responseBody: { ...error, errorStack: error.stack },
responseCode: INTERNAL_SERVER_ERROR,
});
logger.error(`${logContext.namespace} id: ${requestErrorId} Sequelize error`);
logger.error(`${logContext.namespace} id: ${requestErrorId} Sequelize error ${error.stack}`);
} catch (err) {
logger.error(`${logContext.namespace} - Sequelize error - unable to save to db - ${error}`);
}
Expand All @@ -35,7 +35,7 @@ export const handleError = async (req, res, error, logContext) => {
if (error instanceof Sequelize.Error) {
await handleSequelizeError(req, res, error, logContext);
} else {
logger.error(`${logContext.namespace} - UNEXPECTED ERROR - ${error}`);
logger.error(`${logContext.namespace} - UNEXPECTED ERROR - ${error.stack}`);
res.status(INTERNAL_SERVER_ERROR).end();
}
};
Expand Down
Loading