From 56692f7e09ee2aea7b3a93bd84112524be443124 Mon Sep 17 00:00:00 2001 From: martintrajanovski Date: Tue, 3 Dec 2024 08:47:34 +0100 Subject: [PATCH 1/2] feat: migrate dataset principalInvestigator to principalInvestigators --- ...105905-multiple-principal-investigators.js | 31 +++++++++ src/datasets/datasets.controller.ts | 65 +++++++++++++++---- src/datasets/datasets.service.spec.ts | 12 ++-- src/datasets/dto/update-dataset.dto.ts | 7 +- src/datasets/schemas/dataset.schema.ts | 4 +- 5 files changed, 94 insertions(+), 25 deletions(-) create mode 100644 migrations/20241202105905-multiple-principal-investigators.js diff --git a/migrations/20241202105905-multiple-principal-investigators.js b/migrations/20241202105905-multiple-principal-investigators.js new file mode 100644 index 000000000..4ae53f70c --- /dev/null +++ b/migrations/20241202105905-multiple-principal-investigators.js @@ -0,0 +1,31 @@ +module.exports = { + async up(db, client) { + await db.collection("Dataset").updateMany({}, [ + { + $set: { + principalInvestigators: ["$principalInvestigator"], + }, + }, + ]); + + await db + .collection("Dataset") + .updateMany({}, { $unset: { principalInvestigator: "" } }); + }, + + async down(db, client) { + await db.collection("Dataset").updateMany({}, [ + { + $set: { + principalInvestigator: { + $arrayElemAt: ["$principalInvestigators", 0], + }, + }, + }, + ]); + + await db + .collection("Dataset") + .updateMany({}, { $unset: { principalInvestigators: "" } }); + }, +}; diff --git a/src/datasets/datasets.controller.ts b/src/datasets/datasets.controller.ts index 32eb8d34b..085661ad2 100644 --- a/src/datasets/datasets.controller.ts +++ b/src/datasets/datasets.controller.ts @@ -418,10 +418,28 @@ export class DatasetsController { whereFilter.instrumentIds = whereFilter.instrumentId; delete whereFilter.instrumentId; } + if ("investigator" in whereFilter) { + if (typeof whereFilter.investigator === "string") { + whereFilter.principalInvestigators = { + $in: [whereFilter.investigator], + }; + } else { + whereFilter.principalInvestigators = whereFilter.investigator; + } + + delete whereFilter.investigator; + } if ("principalInvestigator" in whereFilter) { - whereFilter.investigator = whereFilter.principalInvestigator; + if (typeof whereFilter.investigator === "string") { + whereFilter.principalInvestigators = { + $in: [whereFilter.principalInvestigator], + }; + } else { + whereFilter.principalInvestigators = whereFilter.principalInvestigator; + } delete whereFilter.principalInvestigator; } + return whereFilter; } convertObsoleteToCurrentSchema( @@ -457,11 +475,18 @@ export class DatasetsController { (inputObsoleteDataset as CreateRawDatasetObsoleteDto).instrumentId, ]; } + if ("principalInvestigator" in inputObsoleteDataset) { + propertiesModifier.principalInvestigators = [ + (inputObsoleteDataset as CreateRawDatasetObsoleteDto) + .principalInvestigator, + ]; + } } else { if ("investigator" in inputObsoleteDataset) { - propertiesModifier.principalInvestigator = ( - inputObsoleteDataset as CreateDerivedDatasetObsoleteDto - ).investigator; + propertiesModifier.principalInvestigators = [ + (inputObsoleteDataset as CreateDerivedDatasetObsoleteDto) + .investigator, + ]; } } @@ -503,18 +528,34 @@ export class DatasetsController { ): OutputDatasetObsoleteDto { const propertiesModifier: Record = {}; if (inputDataset) { - if ("proposalIds" in inputDataset) { - propertiesModifier.proposalId = inputDataset.proposalIds![0]; + if ("proposalIds" in inputDataset && inputDataset.proposalIds?.length) { + propertiesModifier.proposalId = inputDataset.proposalIds[0]; + } + if ("sampleIds" in inputDataset && inputDataset.sampleIds?.length) { + propertiesModifier.sampleId = inputDataset.sampleIds[0]; } - if ("sampleIds" in inputDataset) { - propertiesModifier.sampleId = inputDataset.sampleIds![0]; + if ( + "instrumentIds" in inputDataset && + inputDataset.instrumentIds?.length + ) { + propertiesModifier.instrumentId = inputDataset.instrumentIds[0]; } - if ("instrumentIds" in inputDataset) { - propertiesModifier.instrumentId = inputDataset.instrumentIds![0]; + + if ( + "principalInvestigators" in inputDataset && + inputDataset.principalInvestigators?.length + ) { + propertiesModifier.principalInvestigator = + inputDataset.principalInvestigators[0]; } + if (inputDataset.type == "derived") { - if ("investigator" in inputDataset) { - propertiesModifier.investigator = inputDataset.principalInvestigator; + if ( + "investigator" in inputDataset && + inputDataset.principalInvestigators?.length + ) { + propertiesModifier.investigator = + inputDataset.principalInvestigators[0]; } } } diff --git a/src/datasets/datasets.service.spec.ts b/src/datasets/datasets.service.spec.ts index 9cea8700e..cd14bbd4a 100644 --- a/src/datasets/datasets.service.spec.ts +++ b/src/datasets/datasets.service.spec.ts @@ -19,7 +19,7 @@ const mockDataset: DatasetClass = { pid: "testPid", owner: "testOwner", ownerEmail: "testOwner@email.com", - instrumentId: "testInstrumentId", + instrumentIds: ["testInstrumentId"], orcidOfOwner: "https://0000.0000.0000.0001", contactEmail: "testContact@email.com", sourceFolder: "/nfs/groups/beamlines/test/123456", @@ -59,24 +59,20 @@ const mockDataset: DatasetClass = { createdAt: new Date("2021-11-11T12:29:02.083Z"), updatedAt: new Date("2021-11-11T12:29:02.083Z"), techniques: [], - principalInvestigator: "testInvestigator", + principalInvestigators: ["testInvestigator"], endTime: new Date("2021-12-11T12:29:02.083Z"), creationLocation: "test", dataFormat: "Test Format", scientificMetadata: {}, - proposalId: "ABCDEF", - sampleId: "testSampleId", - attachments: [], + proposalIds: ["ABCDEF"], + sampleIds: ["testSampleId"], accessGroups: [], createdBy: "test user", - datablocks: [], - origdatablocks: [], ownerGroup: "test", relationships: [], sharedWith: [], updatedBy: "test", instrumentGroup: "test", - investigator: "test", inputDatasets: [], usedSoftware: [], jobParameters: {}, diff --git a/src/datasets/dto/update-dataset.dto.ts b/src/datasets/dto/update-dataset.dto.ts index 99c6c3eaf..b2453f56d 100644 --- a/src/datasets/dto/update-dataset.dto.ts +++ b/src/datasets/dto/update-dataset.dto.ts @@ -291,13 +291,14 @@ export class UpdateDatasetDto extends OwnableDto { readonly dataQualityMetrics?: number; @ApiProperty({ - type: String, - required: true, + type: [String], + required: false, description: "First name and last name of principal investigator(s). If multiple PIs are present, use a semicolon separated list. This field is required if the dataset is a Raw dataset.", }) + @IsOptional() @IsString() - readonly principalInvestigator: string; + readonly principalInvestigators?: string[]; @ApiProperty({ type: Date, diff --git a/src/datasets/schemas/dataset.schema.ts b/src/datasets/schemas/dataset.schema.ts index b7e9ca8ef..0dc048ceb 100644 --- a/src/datasets/schemas/dataset.schema.ts +++ b/src/datasets/schemas/dataset.schema.ts @@ -362,8 +362,8 @@ export class DatasetClass extends OwnableClass { description: "First name and last name of principal investigator(s). If multiple PIs are present, use a semicolon separated list. This field is required if the dataset is a Raw dataset.", }) - @Prop({ type: String, required: false }) - principalInvestigator?: string; + @Prop({ type: [String], required: false }) + principalInvestigators?: string[]; @ApiProperty({ type: Date, From fabe5aa31b309360b55c4fa0a8517869293e0e70 Mon Sep 17 00:00:00 2001 From: martintrajanovski Date: Wed, 11 Dec 2024 09:40:25 +0100 Subject: [PATCH 2/2] try to fix some validation and failing tests --- src/datasets/dto/update-dataset.dto.ts | 5 +++-- src/datasets/schemas/dataset.schema.ts | 1 + test/DatasetCustom.js | 2 +- test/TestData.js | 10 +++++----- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/datasets/dto/update-dataset.dto.ts b/src/datasets/dto/update-dataset.dto.ts index 58899a6b6..1dc67f0e7 100644 --- a/src/datasets/dto/update-dataset.dto.ts +++ b/src/datasets/dto/update-dataset.dto.ts @@ -291,13 +291,14 @@ export class UpdateDatasetDto extends OwnableDto { readonly dataQualityMetrics?: number; @ApiProperty({ - type: [String], + type: String, required: false, + isArray: true, description: "First and last name of principal investigator(s). Multiple PIs can be provided as separate strings in the array. This field is required if the dataset is a Raw dataset.", }) @IsOptional() - @IsString() + @IsString({ each: true }) readonly principalInvestigators?: string[]; @ApiProperty({ diff --git a/src/datasets/schemas/dataset.schema.ts b/src/datasets/schemas/dataset.schema.ts index 3a88a154c..723816a56 100644 --- a/src/datasets/schemas/dataset.schema.ts +++ b/src/datasets/schemas/dataset.schema.ts @@ -357,6 +357,7 @@ export class DatasetClass extends OwnableClass { @ApiProperty({ type: String, required: false, + isArray: true, description: "First and last name of principal investigator(s). Multiple PIs can be provided as separate strings in the array. This field is required if the dataset is a Raw dataset.", }) diff --git a/test/DatasetCustom.js b/test/DatasetCustom.js index 9670c1adf..f23c76229 100644 --- a/test/DatasetCustom.js +++ b/test/DatasetCustom.js @@ -17,7 +17,7 @@ describe("2400: CustomDataset: Custom Type Datasets", () => { before(() => { db.collection("Dataset").deleteMany({}); }); - beforeEach(async() => { + beforeEach(async () => { accessTokenAdminIngestor = await utils.getToken(appUrl, { username: "adminIngestor", password: TestData.Accounts["adminIngestor"]["password"], diff --git a/test/TestData.js b/test/TestData.js index afbadf1b1..f16142a96 100644 --- a/test/TestData.js +++ b/test/TestData.js @@ -481,7 +481,7 @@ const TestData = { }, CustomDatasetCorrectMin: { - principalInvestigator: faker.internet.email(), + principalInvestigators: [faker.internet.email()], owner: faker.internet.username(), contactEmail: faker.internet.email(), sourceFolder: faker.system.directoryPath(), @@ -492,7 +492,7 @@ const TestData = { }, CustomDatasetCorrect: { - principalInvestigator: "egon.meier@web.de", + principalInvestigators: ["egon.meier@web.de"], inputDatasets: ["/data/input/file1.dat"], usedSoftware: [ "https://gitlab.psi.ch/ANALYSIS/csaxs/commit/7d5888bfffc440bb613bc7fa50adc0097853446c", @@ -522,7 +522,7 @@ const TestData = { }, CustomDatasetWrongType: { - principalInvestigator: "egon.meier@web.de", + principalInvestigators: ["egon.meier@web.de"], jobParameters: { nscans: 10, }, @@ -540,7 +540,7 @@ const TestData = { }, CustomDatasetWrongData: { - principalInvestigator: "egon.meier@web.de", + principalInvestigators: ["egon.meier@web.de"], jobParameters: { nscans: 10, }, @@ -559,7 +559,7 @@ const TestData = { }, CustomDatasetIncompleteData: { - principalInvestigator: "egon.meier@web.de", + principalInvestigators: ["egon.meier@web.de"], jobParameters: { nscans: 10, },