Skip to content
1 change: 1 addition & 0 deletions apps/backend/src/config/Tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const Tokens = {
PredefinedMessageDataSource: Symbol('PredefinedMessageDataSource'),
InternalReviewDataSource: Symbol('InternalReviewDataSource'),
FapDataColumns: Symbol('FapDataColumns'),
CallExtraFapDataColumns: Symbol('CallExtraFapDataColumns'),
FapDataRow: Symbol('FapDataRow'),
PopulateRow: Symbol('PopulateRow'),
PopulateCallRow: Symbol('PopulateCallRow'),
Expand Down
22 changes: 13 additions & 9 deletions apps/backend/src/config/dependencyConfigDLS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,15 @@ import {
createPostToRabbitMQHandler,
} from '../eventHandlers/messageBroker';
import { createApplicationEventBus } from '../events';
import { FapDataColumns } from '../factory/xlsx/FapDataColumns';
import {
callFapPopulateRow,
getDataRow,
populateRow,
} from '../factory/xlsx/FapDataRow';
DLSCallExtraFapDataColumns,
DLSFapDataColumns,
} from '../factory/xlsx/dls/DLSFapDataColumns';
import {
callFapDLSPopulateRow,
getDLSDataRow,
populateDLSRow,
} from '../factory/xlsx/dls/DLSFapDataRow';
import BasicUserDetailsLoader from '../loaders/BasicUserDetailsLoader';
import { SkipAssetRegistrar } from '../services/assetRegistrar/skip/SkipAssetRegistrar';

Expand Down Expand Up @@ -127,10 +130,11 @@ mapClass(Tokens.AssetRegistrar, SkipAssetRegistrar);

mapClass(Tokens.MailService, SMTPMailService);

mapValue(Tokens.FapDataColumns, FapDataColumns);
mapValue(Tokens.FapDataRow, getDataRow);
mapValue(Tokens.PopulateRow, populateRow);
mapValue(Tokens.PopulateCallRow, callFapPopulateRow);
mapValue(Tokens.FapDataColumns, DLSFapDataColumns);
mapValue(Tokens.CallExtraFapDataColumns, DLSCallExtraFapDataColumns);
mapValue(Tokens.FapDataRow, getDLSDataRow);
mapValue(Tokens.PopulateRow, populateDLSRow);
mapValue(Tokens.PopulateCallRow, callFapDLSPopulateRow);

mapValue(Tokens.EmailEventHandler, DLSEmailHandler);
mapClass(Tokens.EmailTemplateDataSource, PostgresEmailTemplateDataSource);
Expand Down
48 changes: 35 additions & 13 deletions apps/backend/src/factory/xlsx/FapDataRow.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,41 @@
import { CallRowObj } from './callFaps';
import { RowObj } from './fap';
import { QuestionaryStep } from '../../models/Questionary';
import { Review } from '../../models/Review';

export function getDataRow(
proposalPk: number,
piName: string,
proposalAverageScore: number,
instrumentName: string,
instrumentAvailabilityTime: number,
fapTimeAllocation: number | null,
proposalTitle: string,
proposalId: number | null,
techReviewTimeAllocation: number | null,
technicalReviewComment: string | null,
propFapRankOrder: number | null
): RowObj {
export type FapDataRowInput = {
proposalPk: number;
piName: string;
proposalAverageScore: number;
instrumentName: string;
instrumentAvailabilityTime: number;
fapTimeAllocation: number | null;
proposalTitle: string;
proposalId: number | null;
techReviewTimeAllocation: number | null;
technicalReviewComment: string | null;
propFapRankOrder: number | null;
proposerId: number | null;
proposalAnswers: QuestionaryStep[] | null;
reviews: Review[] | null;
instrumentId: number;
};

export type FapDataRow = (input: FapDataRowInput) => RowObj | Promise<RowObj>;

export function getDataRow({
proposalPk,
piName,
proposalAverageScore,
instrumentName,
instrumentAvailabilityTime,
fapTimeAllocation,
proposalTitle,
proposalId,
techReviewTimeAllocation,
technicalReviewComment,
propFapRankOrder,
}: FapDataRowInput): RowObj {
return {
proposalPk: proposalPk,
propShortCode: proposalId?.toString(),
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/factory/xlsx/callFaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export const collectCallFapXLSXData = async (
return { data: baseData, filename: filename.replace(/\s+/g, '_') };
};

export const CallExtraFapDataColumns = [
export const DefaultCallExtraFapDataColumns = [
'Fap Time allocation',
'Fap Meeting Decision',
'Fap Meeting Comment for User',
Expand Down
20 changes: 20 additions & 0 deletions apps/backend/src/factory/xlsx/dls/DLSFapDataColumns.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const DLSFapDataColumns = [
'Proposal Reference Number',
'Proposal Title',
'Principal Investigator',
'Institution',
'Instrument',
'Instrument available Time',
'TA Recommended Time',
'FAP Recommended Time',
'Average Score',
'Current Rank',
'Is in availability zone',
];

export const DLSCallExtraFapDataColumns = [
'FAP Meeting Recommendation',
'FAP Meeting Comment for User',
'FAP Meeting Internal Comment',
'Instrument Requested Time',
];
72 changes: 72 additions & 0 deletions apps/backend/src/factory/xlsx/dls/DLSFapDataRow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { container } from 'tsyringe';

import { Tokens } from '../../../config/Tokens';
import { ProposalDataSource } from '../../../datasources/ProposalDataSource';
import { UserDataSource } from '../../../datasources/UserDataSource';
import { CallRowObj } from '../callFaps';
import { RowObj } from '../fap';
import { FapDataRowInput, getDataRow } from '../FapDataRow';

type DLSFapRowObj = RowObj & {
instrumentRequestedTime: number | null | undefined;
};

function nullFieldHelper(
data: string | number | null | undefined
): string | number {
return data ?? '<missing>';
}

export async function getDLSDataRow(
input: FapDataRowInput
): Promise<DLSFapRowObj> {
const { proposalPk, proposerId, instrumentId } = input;
const userDataSource = container.resolve<UserDataSource>(
Tokens.UserDataSource
);
const pi = proposerId
? await userDataSource.getBasicUserInfo(proposerId)
: null;

const proposalDataSource = container.resolve<ProposalDataSource>(
Tokens.ProposalDataSource
);
const instrumentRequestedTime = await proposalDataSource.getRequestedTime(
proposalPk,
instrumentId
);

return {
...getDataRow(input),
piOrg: pi?.institution,
instrumentRequestedTime,
};
}

export function populateDLSRow(row: DLSFapRowObj): (string | number)[] {
return [
nullFieldHelper(row.propShortCode),
nullFieldHelper(row.propTitle),
nullFieldHelper(row.principalInv),
nullFieldHelper(row.piOrg),
nullFieldHelper(row.instrName),
nullFieldHelper(row.instrAvailTime),
nullFieldHelper(row.techReviewTimeAllocation),
nullFieldHelper(row.fapTimeAllocation ?? row.techReviewTimeAllocation),
nullFieldHelper(row.propReviewAvgScore),
nullFieldHelper(row.propFapRankOrder),
nullFieldHelper(row.inAvailZone),
];
}

export function callFapDLSPopulateRow(
row: CallRowObj & DLSFapRowObj
): (string | number)[] {
return [
...populateDLSRow(row),
nullFieldHelper(row.fapMeetingDecision),
nullFieldHelper(row.fapMeetingInComment),
nullFieldHelper(row.fapMeetingExComment),
nullFieldHelper(row.instrumentRequestedTime),
].concat(row.reviews ? row.reviews.flatMap((review) => review) : []);
}
40 changes: 20 additions & 20 deletions apps/backend/src/factory/xlsx/fap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import { groupBy } from 'lodash';
import { container } from 'tsyringe';

import { collectCallFapXLSXData } from './callFaps';
import { getDataRow } from './FapDataRow';
import { FapDataRow, FapDataRowInput } from './FapDataRow';
import baseContext from '../../buildContext';
import { getStfcDataRow } from './stfc/StfcFapDataRow';
import { Tokens } from '../../config/Tokens';
import { FapDataSource } from '../../datasources/FapDataSource';
import { UserWithRole } from '../../models/User';
Expand Down Expand Up @@ -36,9 +35,7 @@ export type RowObj = {
accessRoute?: string | null;
};

const fapDataRow = container.resolve<typeof getDataRow | typeof getStfcDataRow>(
Tokens.FapDataRow
);
const fapDataRow = container.resolve<FapDataRow>(Tokens.FapDataRow);

const populateRow = container.resolve<(row: RowObj) => (string | number)[]>(
Tokens.PopulateRow
Expand Down Expand Up @@ -118,22 +115,25 @@ export const collectFapXLSXRowData = async (
{ proposalPk: proposal.proposal_pk, fapId: fapId }
);

return fapDataRow(
proposal.proposal_pk,
piFullName,
proposal.average_grade,
proposal.instrument_name,
proposal.availability_time,
proposal.fap_time_allocation,
proposal.title,
proposal.proposal_id,
proposal.time_allocation,
stripHtml(proposal.comment ?? ''),
proposal.rank_order,
proposal.proposer_id,
const rowInput: FapDataRowInput = {
proposalPk: proposal.proposal_pk,
piName: piFullName,
proposalAverageScore: proposal.average_grade,
instrumentName: proposal.instrument_name,
instrumentAvailabilityTime: proposal.availability_time,
fapTimeAllocation: proposal.fap_time_allocation,
proposalTitle: proposal.title,
proposalId: proposal.proposal_id,
techReviewTimeAllocation: proposal.time_allocation,
technicalReviewComment: stripHtml(proposal.comment ?? ''),
propFapRankOrder: proposal.rank_order,
proposerId: proposal.proposer_id,
proposalAnswers,
reviews
);
reviews,
instrumentId: proposal.instrument_id,
};

return fapDataRow(rowInput);
})
);

Expand Down
44 changes: 8 additions & 36 deletions apps/backend/src/factory/xlsx/stfc/StfcFapDataRow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,13 @@ import { container } from 'tsyringe';

import { Tokens } from '../../../config/Tokens';
import { StfcUserDataSource } from '../../../datasources/stfc/StfcUserDataSource';
import { QuestionaryStep } from '../../../models/Questionary';
import { Review } from '../../../models/Review';
import { stripHtml } from '../../../utils/stringStripHtml';
import { CallRowObj } from '../callFaps';
import { RowObj } from '../fap';
import { getDataRow } from '../FapDataRow';

export async function getStfcDataRow(
proposalPk: number,
piName: string,
proposalAverageScore: number,
instrument: string,
instrumentAvailabilityTime: number,
fapTimeAllocation: number | null,
proposalTitle: string,
proposalId: number | null,
technicalReviewTimeAllocation: number | null,
technicalReviewComment: string | null,
propFapRankOrder: number | null,
proposer_id: number | null,
proposalAnswers: QuestionaryStep[] | null,
reviews: Review[] | null
) {
import { FapDataRowInput, getDataRow } from '../FapDataRow';

export async function getStfcDataRow(input: FapDataRowInput) {
const { proposerId, proposalAnswers, reviews } = input;
const stfcUserDataSource: StfcUserDataSource = container.resolve(
Tokens.UserDataSource
) as StfcUserDataSource;
Expand Down Expand Up @@ -65,31 +49,19 @@ export async function getStfcDataRow(
)?.value;

const piDetails = await stfcUserDataSource.getStfcBasicPeopleByUserNumbers([
proposer_id?.toString() ?? '',
proposerId?.toString() ?? '',
]);

const piCountry = piDetails.find(
(user) => user.userNumber === proposer_id?.toString()
(user) => user.userNumber === proposerId?.toString()
)?.country;

const piOrg = piDetails.find(
(user) => user.userNumber === proposer_id?.toString()
(user) => user.userNumber === proposerId?.toString()
)?.orgName;

return {
...getDataRow(
proposalPk,
piName,
proposalAverageScore,
instrument,
instrumentAvailabilityTime,
fapTimeAllocation,
proposalTitle,
proposalId,
technicalReviewTimeAllocation,
technicalReviewComment,
propFapRankOrder
),
...getDataRow(input),
accessRoute,
timeRequested,
reviews: individualReviews,
Expand Down
9 changes: 7 additions & 2 deletions apps/backend/src/middlewares/factory/xlsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import callFactoryService, {
} from '../../factory/service';
import { getCurrentTimestamp } from '../../factory/util';
import {
CallExtraFapDataColumns,
DefaultCallExtraFapDataColumns,
collectCallFapXLSXData,
} from '../../factory/xlsx/callFaps';
import { collectFapXLSXData } from '../../factory/xlsx/fap';
Expand All @@ -21,6 +21,11 @@ import {
} from '../../factory/xlsx/proposal';

const fapDataColumns = container.resolve<string[]>(Tokens.FapDataColumns);
const callExtraFapDataColumns = container.isRegistered(
Tokens.CallExtraFapDataColumns
)
? container.resolve<string[]>(Tokens.CallExtraFapDataColumns)
: DefaultCallExtraFapDataColumns;

const router = express.Router();

Expand Down Expand Up @@ -147,7 +152,7 @@ router.get(`/${XLSXType.CALL_FAP}/:call_id`, async (req, res, next) => {
const meta: XLSXMetaBase = {
singleFilename: filename,
collectionFilename: filename,
columns: fapDataColumns.concat(CallExtraFapDataColumns),
columns: fapDataColumns.concat(callExtraFapDataColumns),
};

const userRole = req.user.currentRole;
Expand Down
Loading
Loading