Skip to content

Commit

Permalink
feat: Instrument assignment to a Proposal, after the Instrument Picke…
Browse files Browse the repository at this point in the history
…r Question has been answered is done.
  • Loading branch information
yoganandaness committed Jun 7, 2023
1 parent 05e86cd commit c03e883
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 13 deletions.
21 changes: 9 additions & 12 deletions apps/user-office-backend/src/datasources/postgres/records.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Datatype } from '@faker-js/faker/modules/datatype';
import { PdfTemplateRecord } from 'knex/types/tables';

import { Page } from '../../models/Admin';
Expand All @@ -13,6 +12,7 @@ import { Feedback } from '../../models/Feedback';
import { FeedbackRequest } from '../../models/FeedbackRequest';
import { GenericTemplate } from '../../models/GenericTemplate';
import { Institution } from '../../models/Institution';
import { Instrument } from '../../models/Instrument';
import { PdfTemplate } from '../../models/PdfTemplate';
import { PredefinedMessage } from '../../models/PredefinedMessage';
import { Proposal, ProposalEndStatus } from '../../models/Proposal';
Expand All @@ -25,7 +25,6 @@ import {
QuestionDataTypeConfigMapping,
} from '../../models/questionTypes/QuestionRegistry';
import { RedeemCode } from '../../models/RedeemCode';
import { Review } from '../../models/Review';
import { Role } from '../../models/Role';
import { Sample } from '../../models/Sample';
import { SampleExperimentSafetyInput } from '../../models/SampleExperimentSafetyInput';
Expand Down Expand Up @@ -709,15 +708,13 @@ export const createProposalObject = (proposal: ProposalRecord) => {
);
};

export const createReviewObject = (review: ReviewRecord) => {
return new Review(
review.review_id,
review.proposal_pk,
review.user_id,
review.comment,
review.grade,
review.status,
review.sep_id
export const createInstrumentObject = (instrument: InstrumentRecord) => {
return new Instrument(
instrument.instrument_id,
instrument.name,
instrument.short_code,
instrument.description,
instrument.manager_user_id
);
};

Expand Down Expand Up @@ -797,7 +794,7 @@ export const createFileMetadata = (record: FileRecord) => {
);
};

export const createQuestionTemplateRelationObject = async <T extends Datatype>(
export const createQuestionTemplateRelationObject = async <T extends DataType>(
record: QuestionRecord &
QuestionTemplateRelRecord & {
config: QuestionDataTypeConfigMapping<T>;
Expand Down
13 changes: 13 additions & 0 deletions apps/user-office-backend/src/models/ProposalModelFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
import { Answer, QuestionaryStep } from './Questionary';
import { getQuestionDefinition } from './questionTypes/QuestionRegistry';
import {
DataType,
FieldDependency,
QuestionTemplateRelation,
TemplateStep,
Expand Down Expand Up @@ -124,3 +125,15 @@ export function transformAnswerValueIfNeeded(

return definition.transform(questionTemplateRelation, value);
}

export async function proposalAnswerAfterSave(
dataType: DataType,
questionaryId: number,
value: any
) {
const definition = getQuestionDefinition(dataType);

if (definition.afterSave) {
await definition.afterSave(questionaryId, value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import { logger } from '@user-office-software/duo-logger';
import { GraphQLError } from 'graphql';

import database from '../../datasources/postgres/database';
import { InstrumentWithAvailabilityTimeRecord } from '../../datasources/postgres/records';
import {
InstrumentRecord,
InstrumentWithAvailabilityTimeRecord,
ProposalRecord,
createInstrumentObject,
createProposalObject,
} from '../../datasources/postgres/records';
import { InstrumentPickerConfig } from '../../resolvers/types/FieldConfig';
import { QuestionFilterCompareOperator } from '../Questionary';
import { DataType, QuestionTemplateRelation } from '../Template';
Expand Down Expand Up @@ -87,4 +93,51 @@ export const instrumentPickerDefinition: Question<DataType.INSTRUMENT_PICKER> =

return fallBackConfig;
},
afterSave: async (questionaryId, value) => {
// Get Proposal
const proposal = await database
.select()
.from('proposals')
.where('questionary_id', questionaryId)
.first()
.then((proposal: ProposalRecord | null) =>
proposal ? createProposalObject(proposal) : null
);
// Get Instrument
const instrument = await database
.select()
.from('instruments')
.where('instrument_id', value)
.first()
.then((instrument: InstrumentRecord | null) =>
instrument ? createInstrumentObject(instrument) : null
);
if (!instrument || !proposal) return;
await database.transaction(async (trx) => {
try {
/**
* NOTE: First delete all connections that should be changed,
* because currently we only support one proposal to be assigned on one instrument.
* So we don't end up in a situation that one proposal is assigned to multiple instruments
* which is not supported scenario by the frontend because it only shows one instrument per proposal.
*/
await database('instrument_has_proposals')
.del()
.where('proposal_pk', proposal.primaryKey)
.transacting(trx);

const result = await database('instrument_has_proposals')
.insert({
instrument_id: value,
proposal_pk: proposal.primaryKey,
})
.returning(['*'])
.transacting(trx);

await trx.commit(result);
} catch (error) {
logger.logException('Could not assign Instrument to Proposal', error);
}
});
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ export interface Question<T extends DataType> {
config: QuestionDataTypeConfigMapping<T>,
callI?: number
) => Promise<QuestionDataTypeConfigMapping<T>>;

/**
* Function to execute after the Question has been answered. Ex., Attach an instrument to a proposal, when the Instrument Proposal Question has been answered.
*/
readonly afterSave?: (questionaryId: number, value: any) => any;
}

// Add new component definitions here
Expand Down
11 changes: 11 additions & 0 deletions apps/user-office-backend/src/mutations/QuestionaryMutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Authorized, EventBus } from '../decorators';
import { Event } from '../events/event.enum';
import {
isMatchingConstraints,
proposalAnswerAfterSave,
transformAnswerValueIfNeeded,
} from '../models/ProposalModelFunctions';
import { rejection } from '../models/Rejection';
Expand Down Expand Up @@ -135,6 +136,16 @@ export default class QuestionaryMutations {
answer.questionId,
answer.value
);

/**
* After Effect hook for an Answer save. Any operation that needs to be done, when a specific Question has been answered will be executed here
* Note: Questionary Component Definition that implements the function afterSave, will only be executed.
*/
await proposalAnswerAfterSave(
questionTemplateRelation.question.dataType,
questionaryId,
value
);
}
}
if (!isPartialSave) {
Expand Down

0 comments on commit c03e883

Please sign in to comment.