diff --git a/CHANGELOG.md b/CHANGELOG.md index d1e8a7a345..47508f2134 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,11 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - DEPENDENCIES_FRONTEND, SECURITY.md, NOTICE.md, LICENSE file to frontend docker image - Added a step-by-step guide to register a server in pgAdmin in the database dump README - Documentation about technical users +- new filtering capabilities ( receivedQualityAlertIdsInStatusActive, sentQualityAlertIdsInStatusActive, receivedQualityInvestigationIdsInStatusActive, sentQualityInvestigationIdsInStatusActive ) ### Changed - Fixed helm repository path for backend & frontend (wrong prefix) +- Filter configuration for tables to be resuable and easy to adapt - Updated user manual - Autocomplete endpoints changed owner String type param to Owner for input validation and sql injection prevention - Autocomplete endpoints repository uses now criteria api rather than native query @@ -20,6 +22,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Removed - apk upgrade in docker image built as requested by TRG 4.02 +- removed asset filters ( qualityInvestigationIdsInStatusActive, qualityInvestigationIdsInStatusActive ) ## [9.0.0-rc2 - 15.11.2023] ### Added diff --git a/frontend/src/app/mocks/services/investigations-mock/investigations.model.ts b/frontend/src/app/mocks/services/investigations-mock/investigations.model.ts index 93e98945da..0cc82b64cd 100644 --- a/frontend/src/app/mocks/services/investigations-mock/investigations.model.ts +++ b/frontend/src/app/mocks/services/investigations-mock/investigations.model.ts @@ -19,12 +19,12 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -import type { NotificationResponse } from '@shared/model/notification.model'; -import { NotificationStatus, NotificationType } from '@shared/model/notification.model'; -import { Severity } from '@shared/model/severity.model'; -import { getRandomAsset } from '../parts-mock/partsAsPlanned/partsAsPlanned.model'; -import { MOCK_part_1 } from '../parts-mock/partsAsPlanned/partsAsPlanned.test.model'; -import { getRandomIntFromInterval, getRandomText } from '../text-generator.helper'; +import type {NotificationResponse} from '@shared/model/notification.model'; +import {NotificationStatus, NotificationType} from '@shared/model/notification.model'; +import {Severity} from '@shared/model/severity.model'; +import {getRandomAsset} from '../parts-mock/partsAsPlanned/partsAsPlanned.model'; +import {MOCK_part_1} from '../parts-mock/partsAsPlanned/partsAsPlanned.test.model'; +import {getRandomIntFromInterval, getRandomText} from '../text-generator.helper'; export const InvestigationIdPrefix = 'id-'; @@ -32,67 +32,71 @@ export const InvestigationIdPrefix = 'id-'; const severities = [Severity.MINOR, Severity.MAJOR, Severity.CRITICAL, Severity.LIFE_THREATENING]; export const buildMockInvestigations = ( - statuses: NotificationStatus[], - channel: 'SENDER' | 'RECEIVER', + statuses: NotificationStatus[], + channel: 'SENDER' | 'RECEIVER', ): NotificationResponse[] => - new Array(101).fill(null).map((_, index) => { - const status = statuses[index % statuses.length]; - const severity = severities[index % severities.length]; - // every 10th alert should have an error - const errorInvestigation = (index+1) % 10 === 0 ? "The Services returned an Error while processing this Investigation" : undefined; + new Array(101).fill(null).map((_, index) => { + const status = statuses[index % statuses.length]; + const severity = severities[index % severities.length]; + // every 10th alert should have an error + const errorInvestigation = (index + 1) % 10 === 0 ? "The Services returned an Error while processing this Investigation" : undefined; - const close = status === NotificationStatus.CLOSED ? getRandomText(getRandomIntFromInterval(15, 500)) : ''; - const isDeclined = Math.random() >= 0.5; + const close = status === NotificationStatus.CLOSED ? getRandomText(getRandomIntFromInterval(15, 500)) : ''; + const isDeclined = Math.random() >= 0.5; - const decline = - status === NotificationStatus.DECLINED || (!!close && isDeclined) - ? getRandomText(getRandomIntFromInterval(15, 500)) - : ''; + const decline = + status === NotificationStatus.DECLINED || (!!close && isDeclined) + ? getRandomText(getRandomIntFromInterval(15, 500)) + : ''; - const accept = - status === NotificationStatus.ACCEPTED || (!!close && !isDeclined) - ? getRandomText(getRandomIntFromInterval(15, 500)) - : ''; + const accept = + status === NotificationStatus.ACCEPTED || (!!close && !isDeclined) + ? getRandomText(getRandomIntFromInterval(15, 500)) + : ''; - const numberToString = (i: number) => i.toString().padStart(2, '0'); - const month = getRandomIntFromInterval(1, 12); - const day = getRandomIntFromInterval(1, 27); + const numberToString = (i: number) => i.toString().padStart(2, '0'); + const month = getRandomIntFromInterval(1, 12); + const day = getRandomIntFromInterval(1, 27); - return { - id: `${InvestigationIdPrefix}${index + 1}`, - description: `Investigation No ${index + 1} ${getRandomText(getRandomIntFromInterval(15, 500))}`, - status, - severity, - channel, - createdBy: 'BPN10000000OEM0A', - createdByName: 'OEM xxxxxxxxxxxxxxx A', - sendTo: 'BPN20000000OEM0B', - sendToName: 'OEM xxxxxxxxxxxxxxx B', - reason: { close, decline, accept }, - createdDate: `2022-${numberToString(month)}-${numberToString(day)}T12:34:12`, - targetDate: `2022-${numberToString(month)}-${numberToString(day + 1)}T11:34:12Z`, - assetIds: [MOCK_part_1.id, getRandomAsset().id, getRandomAsset().id, getRandomAsset().id], - errorMessage: errorInvestigation, - notificationType: NotificationType.INVESTIGATION, - }; - }); + return { + id: `${InvestigationIdPrefix}${index + 1}`, + description: `Investigation No ${index + 1} ${getRandomText(getRandomIntFromInterval(15, 500))}`, + status, + severity, + channel, + createdBy: 'BPN10000000OEM0A', + createdByName: 'OEM xxxxxxxxxxxxxxx A', + sendTo: 'BPN20000000OEM0B', + sendToName: 'OEM xxxxxxxxxxxxxxx B', + reason: {close, decline, accept}, + createdDate: `2022-${numberToString(month)}-${numberToString(day)}T12:34:12`, + targetDate: `2022-${numberToString(month)}-${numberToString(day + 1)}T11:34:12Z`, + assetIds: [MOCK_part_1.id, getRandomAsset().id, getRandomAsset().id, getRandomAsset().id], + errorMessage: errorInvestigation, + notificationType: NotificationType.INVESTIGATION, + }; + }); const MockEmptyInvestigation: NotificationResponse = { - id: `${InvestigationIdPrefix}000`, - description: `Investigation No 000`, - status: NotificationStatus.CREATED, - severity: Severity.MINOR, - createdBy: 'BPN10000000OEM0A', - createdByName: 'OEM xxxxxxxxxxxxxxx A', - sendTo: 'BPN20000000OEM0B', - sendToName: 'OEM xxxxxxxxxxxxxxx B', - reason: { close: '', decline: '', accept: '' }, - createdDate: `2022-05-01T12:34:12`, - targetDate: `2022-02-01T12:34:12`, - assetIds: [getRandomAsset().id], - channel: 'SENDER', + id: `${InvestigationIdPrefix}000`, + description: `Investigation No 000`, + status: NotificationStatus.CREATED, + severity: Severity.MINOR, + createdBy: 'BPN10000000OEM0A', + createdByName: 'OEM xxxxxxxxxxxxxxx A', + sendTo: 'BPN20000000OEM0B', + sendToName: 'OEM xxxxxxxxxxxxxxx B', + reason: {close: '', decline: '', accept: ''}, + createdDate: `2022-05-01T12:34:12`, + targetDate: `2022-02-01T12:34:12`, + assetIds: [getRandomAsset().id], + channel: 'SENDER', }; +export interface NotificationFilter { + notificationIds: string[] +} + export const getInvestigationById = (id: string) => { - return [].find(investigation => investigation.id === id) || { ...MockEmptyInvestigation, id }; + return [].find(investigation => investigation.id === id) || {...MockEmptyInvestigation, id}; }; diff --git a/frontend/src/app/mocks/services/parts-mock/partsAsBuilt/partsAsBuilt.model.ts b/frontend/src/app/mocks/services/parts-mock/partsAsBuilt/partsAsBuilt.model.ts index 7c7a7af6a5..b650a9133c 100644 --- a/frontend/src/app/mocks/services/parts-mock/partsAsBuilt/partsAsBuilt.model.ts +++ b/frontend/src/app/mocks/services/parts-mock/partsAsBuilt/partsAsBuilt.model.ts @@ -31,8 +31,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-613963493493659233961306", "businessPartner": "BPNL00000003CML1", "manufacturerName": "BMW AG", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [ { @@ -64,8 +64,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e43842", @@ -73,8 +75,8 @@ export const mockBmwAssets = [ "semanticModelId": "12345678ABC", "businessPartner": "BPNL00000003CML1", "manufacturerName": "BMW AG", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [], "parentRelations": [], @@ -96,8 +98,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive:[], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:4a5e9ff6-2d5c-4510-a90e-d55af3ba502f", @@ -105,8 +109,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-246880451848384868750731", "businessPartner": "BPNL00000003CML1", "manufacturerName": "BMW AG", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [{ "id": "urn:uuid:c47b9f8b-48d0-4ef4-8f0b-e965a225cb8d", @@ -136,8 +140,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive:[], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fa03", @@ -145,8 +151,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-341449848714937445621543", "businessPartner": "BPNL00000003CML1", "manufacturerName": "BMW AG", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [], "parentRelations": [ @@ -173,8 +179,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fa01", @@ -182,8 +190,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-341449848714937445621543", "businessPartner": "BPNL00000003CML1", "manufacturerName": "BMW AG", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [], "parentRelations": [], @@ -205,8 +213,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccad12", @@ -214,8 +224,8 @@ export const mockBmwAssets = [ "semanticModelId": "OMAYSKEITUGNVHKKX", "businessPartner": "BPNL00000003CML1", "manufacturerName": "BMW AG", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [ { @@ -242,8 +252,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", @@ -251,8 +263,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-989134870198932317923938", "businessPartner": "BPNL00000003CNKC", "manufacturerName": "BMW AG", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [], "parentRelations": [], @@ -274,8 +286,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fa02", @@ -283,8 +297,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-341449848714937445621543", "businessPartner": "BPNL00000003CML1", "manufacturerName": "BMW AG", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [ { @@ -311,8 +325,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive:[], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fb01", @@ -320,8 +336,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-341449848714937445621543", "businessPartner": "BPNL00000003CNKC", "manufacturerName": "TEST_BPN_IRS_1", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [], "parentRelations": [], @@ -343,8 +359,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:6b2296cc-26c0-4f38-8a22-092338c36e22", @@ -352,8 +370,8 @@ export const mockBmwAssets = [ "semanticModelId": "OMAOYGBDTSRCMYSCX", "businessPartner": "BPNL00000003CML1", "manufacturerName": "MyAsBuiltPart", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [ { @@ -380,8 +398,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:c47b9f8b-48d0-4ef4-8f0b-e965a225cb8d", @@ -389,8 +409,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-477013846751358222215326", "businessPartner": "BPNL00000003CNKC", "manufacturerName": "TEST_BPN_IRS_1", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [], "parentRelations": [], @@ -412,8 +432,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:f11ddc62-3bd5-468f-b7b0-110fe13ed0cd", @@ -421,8 +443,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-004314332935115065980115", "businessPartner": "BPNL00000003CNKC", "manufacturerName": "TEST_BPN_IRS_1", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [], "parentRelations": [], @@ -444,8 +466,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fb02", @@ -453,8 +477,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-341449848714937445621543", "businessPartner": "BPNL00000003CNKC", "manufacturerName": "TEST_BPN_IRS_1", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [], "parentRelations": [], @@ -476,8 +500,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive:[], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, { "id": "urn:uuid:7eeeac86-7b69-444d-81e6-655d0f1513bd", @@ -485,8 +511,8 @@ export const mockBmwAssets = [ "semanticModelId": "NO-313869652971440618042264", "businessPartner": "BPNL00000003CNKC", "manufacturerName": "TEST_BPN_IRS_1", - nameAtManufacturer: "MyAsBuiltPartName", - manufacturerPartId: "ManuPartID", + "nameAtManufacturer": "MyAsBuiltPartName", + "manufacturerPartId": "ManuPartID", "owner": "OWN", "childRelations": [], "parentRelations": [], @@ -508,8 +534,10 @@ export const mockBmwAssets = [ } } ], - qualityAlertIdsInStatusActive:[], - qualityInvestigationIdsInStatusActive: [], + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }, ] as PartResponse[]; @@ -541,8 +569,10 @@ const MockEmptyPart: PartResponse = { qualityType: QualityType.Ok, van: null, semanticDataModel: SemanticDataModel.SERIALPART, - qualityAlertIdsInStatusActive: [], - qualityInvestigationIdsInStatusActive: [], + sentQualityAlertIdsInStatusActive: [], + receivedQualityAlertIdsInStatusActive: [], + sentQualityInvestigationIdsInStatusActive: [], + receivedQualityInvestigationIdsInStatusActive: [] }; diff --git a/frontend/src/app/mocks/services/parts-mock/partsAsBuilt/partsAsBuilt.test.model.ts b/frontend/src/app/mocks/services/parts-mock/partsAsBuilt/partsAsBuilt.test.model.ts index 08a9303ac9..315405622c 100644 --- a/frontend/src/app/mocks/services/parts-mock/partsAsBuilt/partsAsBuilt.test.model.ts +++ b/frontend/src/app/mocks/services/parts-mock/partsAsBuilt/partsAsBuilt.test.model.ts @@ -52,8 +52,10 @@ export const MOCK_part_5 = { } } ], - 'qualityAlertsInStatusActive': 0, - 'qualityInvestigationsInStatusActive': 0, + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }; export const MOCK_part_4 = { @@ -90,8 +92,10 @@ export const MOCK_part_4 = { } } ], - 'qualityAlertsInStatusActive': 0, - 'qualityInvestigationsInStatusActive': 0, + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }; export const MOCK_part_3 = { @@ -129,8 +133,10 @@ export const MOCK_part_3 = { } } ], - 'qualityAlertsInStatusActive': 0, - 'qualityInvestigationsInStatusActive': 0, + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }; export const MOCK_part_2 = { @@ -172,8 +178,10 @@ export const MOCK_part_2 = { } } ], - 'qualityAlertsInStatusActive': 0, - 'qualityInvestigationsInStatusActive': 0, + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }; export const MOCK_part_1 = { @@ -212,8 +220,10 @@ export const MOCK_part_1 = { } } ], - 'qualityAlertsInStatusActive': 0, - 'qualityInvestigationsInStatusActive': 0, + 'sentQualityAlertIdsInStatusActive': [], + 'receivedQualityAlertIdsInStatusActive': [], + 'sentQualityInvestigationIdsInStatusActive': [], + 'receivedQualityInvestigationIdsInStatusActive': [], }; export const mockAssets: PartsResponse = { diff --git a/frontend/src/app/mocks/services/parts-mock/partsAsPlanned/partsAsPlanned.model.ts b/frontend/src/app/mocks/services/parts-mock/partsAsPlanned/partsAsPlanned.model.ts index 37b3ecbc96..530acda114 100644 --- a/frontend/src/app/mocks/services/parts-mock/partsAsPlanned/partsAsPlanned.model.ts +++ b/frontend/src/app/mocks/services/parts-mock/partsAsPlanned/partsAsPlanned.model.ts @@ -19,499 +19,502 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -import { DetailAspectType } from '@page/parts/model/detailAspectModel.model'; -import { Owner } from '@page/parts/model/owner.enum'; -import { PartResponse, QualityType, SemanticDataModel } from '@page/parts/model/parts.model'; -import { otherPartsAssets } from '../../otherParts-mock/otherParts.model'; +import {DetailAspectType} from '@page/parts/model/detailAspectModel.model'; +import {Owner} from '@page/parts/model/owner.enum'; +import {PartResponse, QualityType, SemanticDataModel} from '@page/parts/model/parts.model'; +import {otherPartsAssets} from '../../otherParts-mock/otherParts.model'; export const mockBmwAsPlannedAssets = [ - { - "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fa01", - "idShort": "--", - "semanticModelId": "NO-341449848714937445621543", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [], - "parentRelations": [], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "--", - "semanticDataModel": "BATCH", - "classification": "component", - "detailAspectModels": [ - { - "type": "AS_PLANNED", - "data": { - validityPeriodFrom: "01.01.2020", - functionValidUntil: "01.02.2020" - } - }, - { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] - }, - { - "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fa03", - "idShort": "--", - "semanticModelId": "NO-341449848714937445621543", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [], - "parentRelations": [ - { - "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fb02", - "idShort": null - } - ], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "--", - "semanticDataModel": "BATCH", - "classification": "component", - "detailAspectModels": [ - { - "type": "AS_PLANNED", - "data": { - validityPeriodFrom: "01.01.2020", - functionValidUntil: "01.02.2020" - } - }, - { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] - }, - { - "id": "urn:uuid:4a5e9ff6-2d5c-4510-a90e-d55af3ba502f", - "idShort": "--", - "semanticModelId": "NO-246880451848384868750731", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [], - "parentRelations": [ - { - "id": "urn:uuid:f11ddc62-3bd5-468f-b7b0-110fe13ed0cd", - "idShort": null - } - ], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "--", - "semanticDataModel": "SERIALPART", - "classification": "component", - "detailAspectModels": [ - { - "type": "AS_PLANNED", - "data": { - validityPeriodFrom: "01.01.2020", - functionValidUntil: "01.02.2020" - } - }, - { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] - }, - { - "id": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e43842", - "idShort": "--", - "semanticModelId": "12345678ABC", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [], - "parentRelations": [], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "--", - "semanticDataModel": "JUSTINSEQUENCE", - "classification": "product", - "detailAspectModels": [ - { - "type": "AS_PLANNED", - "data": { - validityPeriodFrom: "01.01.2023", - validityPeriodTo: "01.02.2023", - } - }, - { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] - }, - { - "id": "urn:uuid:6ec3f1db-2798-454b-a73f-0d21a8966c74", - "idShort": "--", - "semanticModelId": "NO-613963493493659233961306", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [{ - "id": "urn:uuid:c47b9f8b-48d0-4ef4-8f0b-e965a225cb8d", - "idShort": null - }], - "parentRelations": [ - { - "id": "urn:uuid:c47b9f8b-48d0-4ef4-8f0b-e965a225cb8d", - "idShort": null - } - ], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "--", - "semanticDataModel": "SERIALPART", - "classification": "component", - "detailAspectModels": [ - { - "type": "AS_PLANNED", - "data": { - "validityPeriodFrom": "01.01.2023", - "validityPeriodTo": "01.02.2023", - } - }, - { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] - }, - -{ - "id": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e43842", - "idShort": "--", - "semanticModelId": "12345678ABC", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [], - "parentRelations": [], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "--", - "semanticDataModel": "JUSTINSEQUENCE", - "classification": "product", - "detailAspectModels": [ { - "type": "AS_PLANNED", - "data": { - validityPeriodFrom: "01.01.2023", - validityPeriodTo: "01.02.2023", - } + "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fa01", + "idShort": "--", + "semanticModelId": "NO-341449848714937445621543", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [], + "parentRelations": [], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "--", + "semanticDataModel": "BATCH", + "classification": "component", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + validityPeriodFrom: "01.01.2020", + functionValidUntil: "01.02.2020" + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] }, { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] -}, + "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fa03", + "idShort": "--", + "semanticModelId": "NO-341449848714937445621543", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [], + "parentRelations": [ + { + "id": "urn:uuid:1be6ec59-40fb-4993-9836-acb0e284fb02", + "idShort": null + } + ], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "--", + "semanticDataModel": "BATCH", + "classification": "component", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + validityPeriodFrom: "01.01.2020", + functionValidUntil: "01.02.2020" + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] + }, + { + "id": "urn:uuid:4a5e9ff6-2d5c-4510-a90e-d55af3ba502f", + "idShort": "--", + "semanticModelId": "NO-246880451848384868750731", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [], + "parentRelations": [ + { + "id": "urn:uuid:f11ddc62-3bd5-468f-b7b0-110fe13ed0cd", + "idShort": null + } + ], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "--", + "semanticDataModel": "SERIALPART", + "classification": "component", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + validityPeriodFrom: "01.01.2020", + functionValidUntil: "01.02.2020" + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] + }, + { + "id": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e43842", + "idShort": "--", + "semanticModelId": "12345678ABC", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [], + "parentRelations": [], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "--", + "semanticDataModel": "JUSTINSEQUENCE", + "classification": "product", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + validityPeriodFrom: "01.01.2023", + validityPeriodTo: "01.02.2023", + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] + }, + { + "id": "urn:uuid:6ec3f1db-2798-454b-a73f-0d21a8966c74", + "idShort": "--", + "semanticModelId": "NO-613963493493659233961306", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [{ + "id": "urn:uuid:c47b9f8b-48d0-4ef4-8f0b-e965a225cb8d", + "idShort": null + }], + "parentRelations": [ + { + "id": "urn:uuid:c47b9f8b-48d0-4ef4-8f0b-e965a225cb8d", + "idShort": null + } + ], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "--", + "semanticDataModel": "SERIALPART", + "classification": "component", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + "validityPeriodFrom": "01.01.2023", + "validityPeriodTo": "01.02.2023", + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] + }, - { - "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccad12", - "idShort": "--", - "semanticModelId": "OMAYSKEITUGNVHKKX", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [ - { - "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", - "idShort": null - } - ], - "parentRelations": [], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "OMAYSKEITUGNVHKKX", - "semanticDataModel": "SERIALPART", - "classification": "product", - "detailAspectModels": [ - { - "type": "AS_PLANNED", - "data": { - validityPeriodFrom: "01.01.2023", - validityPeriodTo: "01.02.2023", - } - }, - { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] - }, + { + "id": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e43842", + "idShort": "--", + "semanticModelId": "12345678ABC", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [], + "parentRelations": [], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "--", + "semanticDataModel": "JUSTINSEQUENCE", + "classification": "product", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + validityPeriodFrom: "01.01.2023", + validityPeriodTo: "01.02.2023", + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] + }, - { - "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccvf54", - "idShort": "--", - "semanticModelId": "OMAYSKEITUGNVHKKX", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [ - { - "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", - "idShort": null - } - ], - "parentRelations": [], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "OMAYSKEITUGNVHKKX", - "semanticDataModel": "SERIALPART", - "classification": "product", - "detailAspectModels": [ - { - "type": "AS_PLANNED", - "data": { - validityPeriodFrom: "01.01.2023", - validityPeriodTo: "01.02.2023", - } - }, - { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] - }, - { - "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccaf88", - "idShort": "--", - "semanticModelId": "OMAYSKEITUGNVHKKX", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [ - { - "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", - "idShort": null - } - ], - "parentRelations": [], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "OMAYSKEITUGNVHKKX", - "semanticDataModel": "SERIALPART", - "classification": "product", - "detailAspectModels": [ - { - "type": "AS_PLANNED", - "data": { - validityPeriodFrom: "01.01.2023", - validityPeriodTo: "01.02.2023", - } - }, - { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] - }, - { - "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccav85", - "idShort": "myShortId", - "semanticModelId": "OMAYSKEITUGNVHKKX", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [ - { - "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", - "idShort": null - } - ], - "parentRelations": [], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "OMAYSKEITUGNVHKKX", - "semanticDataModel": "SERIALPART", - "classification": "product", - "detailAspectModels": [ - { - "type": "AS_PLANNED", - "data": { - validityPeriodFrom: "01.01.2023", - validityPeriodTo: "01.02.2023", - } - }, - { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] - }, - { - "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccag25", - "idShort": "--", - "semanticModelId": "OMAYSKEITUGNVHKKX", - "businessPartner": "BPNL00000003CML1", - "manufacturerName": "MyManufacturerName", - nameAtManufacturer: "MyAsPlannedPartName", - manufacturerPartId: "ManuPartID", - "owner": "OWN", - "childRelations": [ - { - "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", - "idShort": null - } - ], - "parentRelations": [], - "activeAlert": false, - "underInvestigation": false, - "qualityType": "Ok", - "van": "OMAYSKEITUGNVHKKX", - "semanticDataModel": "SERIALPART", - "classification": "product", - "detailAspectModels": [ - { - "type": "AS_PLANNED", - "data": { - validityPeriodFrom: "01.01.2023", - validityPeriodTo: "01.02.2023", - } - }, - { - "type": "PART_SITE_INFORMATION_AS_PLANNED", - "data": { - "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", - "function": "production", - "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", - "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - } - ] - }, + { + "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccad12", + "idShort": "--", + "semanticModelId": "OMAYSKEITUGNVHKKX", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [ + { + "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", + "idShort": null + } + ], + "parentRelations": [], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "OMAYSKEITUGNVHKKX", + "semanticDataModel": "SERIALPART", + "classification": "product", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + validityPeriodFrom: "01.01.2023", + validityPeriodTo: "01.02.2023", + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] + }, + + { + "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccvf54", + "idShort": "--", + "semanticModelId": "OMAYSKEITUGNVHKKX", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [ + { + "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", + "idShort": null + } + ], + "parentRelations": [], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "OMAYSKEITUGNVHKKX", + "semanticDataModel": "SERIALPART", + "classification": "product", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + validityPeriodFrom: "01.01.2023", + validityPeriodTo: "01.02.2023", + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] + }, + { + "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccaf88", + "idShort": "--", + "semanticModelId": "OMAYSKEITUGNVHKKX", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [ + { + "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", + "idShort": null + } + ], + "parentRelations": [], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "OMAYSKEITUGNVHKKX", + "semanticDataModel": "SERIALPART", + "classification": "product", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + validityPeriodFrom: "01.01.2023", + validityPeriodTo: "01.02.2023", + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] + }, + { + "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccav85", + "idShort": "myShortId", + "semanticModelId": "OMAYSKEITUGNVHKKX", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [ + { + "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", + "idShort": null + } + ], + "parentRelations": [], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "OMAYSKEITUGNVHKKX", + "semanticDataModel": "SERIALPART", + "classification": "product", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + validityPeriodFrom: "01.01.2023", + validityPeriodTo: "01.02.2023", + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] + }, + { + "id": "urn:uuid:d8030bbf-a874-49fb-b2e1-7610f0ccag25", + "idShort": "--", + "semanticModelId": "OMAYSKEITUGNVHKKX", + "businessPartner": "BPNL00000003CML1", + "manufacturerName": "MyManufacturerName", + nameAtManufacturer: "MyAsPlannedPartName", + manufacturerPartId: "ManuPartID", + "owner": "OWN", + "childRelations": [ + { + "id": "urn:uuid:5205f736-8fc2-4585-b869-6bf36842369a", + "idShort": null + } + ], + "parentRelations": [], + "activeAlert": false, + "underInvestigation": false, + "qualityType": "Ok", + "van": "OMAYSKEITUGNVHKKX", + "semanticDataModel": "SERIALPART", + "classification": "product", + "detailAspectModels": [ + { + "type": "AS_PLANNED", + "data": { + validityPeriodFrom: "01.01.2023", + validityPeriodTo: "01.02.2023", + } + }, + { + "type": "PART_SITE_INFORMATION_AS_PLANNED", + "data": { + "functionValidUntil": "Sat Feb 08 03:30:48 GMT 2025", + "function": "production", + "functionValidFrom": "Wed Aug 21 00:10:36 GMT 2019", + "catenaXSiteId": "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + } + ] + }, ] as PartResponse[]; const MockEmptyPart: PartResponse = { - id: 'urn:uuid:a000a0aa-00a0-0000-000a-0a0000a0a000', - idShort: '--', - businessPartner: 'OEM A', - semanticModelId: "emptySematicModelId", - "manufacturerName": "MyDefaultManufacturerName", - nameAtManufacturer: "MyDefaultAsPlannedPartName", - manufacturerPartId: "ManuDefaultPartID", - classification: "B-Level", - detailAspectModels: [{ - type: DetailAspectType.AS_PLANNED, - data: { - validityPeriodFrom: "01.01.2023", - validityPeriodTo: "01.02.2023", - } + id: 'urn:uuid:a000a0aa-00a0-0000-000a-0a0000a0a000', + idShort: '--', + businessPartner: 'OEM A', + semanticModelId: "emptySematicModelId", + manufacturerName: "MyDefaultManufacturerName", + nameAtManufacturer: "MyDefaultAsPlannedPartName", + manufacturerPartId: "ManuDefaultPartID", + classification: "B-Level", + detailAspectModels: [{ + type: DetailAspectType.AS_PLANNED, + data: { + validityPeriodFrom: "01.01.2023", + validityPeriodTo: "01.02.2023", + } }, - { - type: DetailAspectType.PART_SITE_INFORMATION_AS_PLANNED, - data: { - functionValidUntil: "Sat Feb 08 03:30:48 GMT 2025", - function: "production", - functionValidFrom: "Wed Aug 21 00:10:36 GMT 2019", - catenaXSiteId: "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" - } - }] , - owner: Owner.OWN, - childRelations: [], - parentRelations: [], - activeAlert: false, - underInvestigation: false, - qualityType: QualityType.Ok, - van: null, - semanticDataModel: SemanticDataModel.PARTASPLANNED + { + type: DetailAspectType.PART_SITE_INFORMATION_AS_PLANNED, + data: { + functionValidUntil: "Sat Feb 08 03:30:48 GMT 2025", + function: "production", + functionValidFrom: "Wed Aug 21 00:10:36 GMT 2019", + catenaXSiteId: "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01" + } + }], + owner: Owner.OWN, + childRelations: [], + parentRelations: [], + activeAlert: false, + underInvestigation: false, + qualityType: QualityType.Ok, + van: null, + semanticDataModel: SemanticDataModel.PARTASPLANNED, + sentQualityAlertIdsInStatusActive: [], + receivedQualityAlertIdsInStatusActive: [], + sentQualityInvestigationIdsInStatusActive: [], + receivedQualityInvestigationIdsInStatusActive: [] }; - export const getAssetAsPlannedById = (id: string) => { - return [...mockBmwAsPlannedAssets, ...otherPartsAssets].find(asset => asset.id === id) || { ...MockEmptyPart, id }; + return [...mockBmwAsPlannedAssets, ...otherPartsAssets].find(asset => asset.id === id) || {...MockEmptyPart, id}; }; export const getRandomAsset = () => { - const parts = [...mockBmwAsPlannedAssets, ...otherPartsAssets]; - return parts[Math.floor(Math.random() * parts.length)]; + const parts = [...mockBmwAsPlannedAssets, ...otherPartsAssets]; + return parts[Math.floor(Math.random() * parts.length)]; }; diff --git a/frontend/src/app/mocks/services/parts-mock/partsAsPlanned/partsAsPlanned.test.model.ts b/frontend/src/app/mocks/services/parts-mock/partsAsPlanned/partsAsPlanned.test.model.ts index a0613ae5dc..7393dcb575 100644 --- a/frontend/src/app/mocks/services/parts-mock/partsAsPlanned/partsAsPlanned.test.model.ts +++ b/frontend/src/app/mocks/services/parts-mock/partsAsPlanned/partsAsPlanned.test.model.ts @@ -57,6 +57,10 @@ export const MOCK_part_5 = { qualityType: QualityType.LifeThreatening, van: 'myvan5', semanticDataModel: SemanticDataModel.SERIALPART, + sentQualityAlertIdsInStatusActive: [], + receivedQualityAlertIdsInStatusActive: [], + sentQualityInvestigationIdsInStatusActive: [], + receivedQualityInvestigationIdsInStatusActive: [] }; export const MOCK_part_4 = { @@ -93,6 +97,10 @@ export const MOCK_part_4 = { qualityType: QualityType.Critical, van: 'myvan4', semanticDataModel: SemanticDataModel.SERIALPART, + sentQualityAlertIdsInStatusActive: [], + receivedQualityAlertIdsInStatusActive: [], + sentQualityInvestigationIdsInStatusActive: [], + receivedQualityInvestigationIdsInStatusActive: [] }; export const MOCK_part_3 = { @@ -129,6 +137,10 @@ export const MOCK_part_3 = { qualityType: QualityType.Major, van: 'myvan3', semanticDataModel: SemanticDataModel.PARTASPLANNED, + sentQualityAlertIdsInStatusActive: [], + receivedQualityAlertIdsInStatusActive: [], + sentQualityInvestigationIdsInStatusActive: [], + receivedQualityInvestigationIdsInStatusActive: [] }; export const MOCK_part_2 = { @@ -165,6 +177,10 @@ export const MOCK_part_2 = { qualityType: QualityType.Minor, van: 'myvan2', semanticDataModel: SemanticDataModel.SERIALPART, + sentQualityAlertIdsInStatusActive: [], + receivedQualityAlertIdsInStatusActive: [], + sentQualityInvestigationIdsInStatusActive: [], + receivedQualityInvestigationIdsInStatusActive: [] }; export const MOCK_part_1 = { @@ -203,7 +219,11 @@ export const MOCK_part_1 = { underInvestigation: false, qualityType: QualityType.Ok, van: 'myvan1', - semanticDataModel: SemanticDataModel.SERIALPART + semanticDataModel: SemanticDataModel.SERIALPART, + sentQualityAlertIdsInStatusActive: [], + receivedQualityAlertIdsInStatusActive: [], + sentQualityInvestigationIdsInStatusActive: [], + receivedQualityInvestigationIdsInStatusActive: [] }; export const mockAssets: PartsResponse = { diff --git a/frontend/src/app/modules/core/user/table-settings.service.ts b/frontend/src/app/modules/core/user/table-settings.service.ts index e2f93d02b2..74dd9e1b27 100644 --- a/frontend/src/app/modules/core/user/table-settings.service.ts +++ b/frontend/src/app/modules/core/user/table-settings.service.ts @@ -17,45 +17,79 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -import { Injectable } from '@angular/core'; -import { PartTableType } from '@shared/components/table/table.model'; -import { Subject } from 'rxjs'; +import {Injectable} from '@angular/core'; +import {PartTableType} from '@shared/components/table/table.model'; +import {Subject} from 'rxjs'; +import {TableViewConfig} from "@shared/components/parts-table/table-view-config.model"; @Injectable({ - providedIn: 'root', + providedIn: 'root', }) export class TableSettingsService { - private settingsKey = 'TableViewSettings'; - private changeEvent = new Subject(); - - storeTableSettings(partTableType: PartTableType, tableSettingsList: any ): void { - // before setting anything, all maps in new tableSettingList should be stringified - Object.keys(tableSettingsList).forEach(tableSetting => { - const newMap = tableSettingsList[tableSetting].columnSettingsOptions; - tableSettingsList[tableSetting].columnSettingsOptions = JSON.stringify(Array.from(newMap.entries())); - }) - localStorage.setItem(this.settingsKey, JSON.stringify(tableSettingsList)); - } - - // this returns whole settings whether empty / not for part / etc. - getStoredTableSettings(): any { - const settingsJson = localStorage.getItem(this.settingsKey); - let settingsObject = settingsJson ? JSON.parse(settingsJson) : null; - if(!settingsObject) return; - - // iterate through all tabletypes and parse columnSettingsOption to a map - Object.keys(settingsObject).forEach(tableSetting => { - settingsObject[tableSetting].columnSettingsOptions = new Map(JSON.parse(settingsObject[tableSetting].columnSettingsOptions)); - - }); - return settingsObject; - } - - emitChangeEvent() { - this.changeEvent.next(); - } - - getEvent() { - return this.changeEvent.asObservable(); - } + private settingsKey = 'TableViewSettings'; + private changeEvent = new Subject(); + + storeTableSettings(tableSettingsList: any): void { + // before setting anything, all maps in new tableSettingList should be stringified + Object.keys(tableSettingsList).forEach(tableSetting => { + const newMap = tableSettingsList[tableSetting].columnSettingsOptions; + tableSettingsList[tableSetting].columnSettingsOptions = JSON.stringify(Array.from(newMap.entries())); + }) + localStorage.setItem(this.settingsKey, JSON.stringify(tableSettingsList)); + } + + // this returns whole settings whether empty / not for part / etc. + getStoredTableSettings(): any { + const settingsJson = localStorage.getItem(this.settingsKey); + let settingsObject = settingsJson ? JSON.parse(settingsJson) : null; + if (!settingsObject) return; + + // iterate through all tabletypes and parse columnSettingsOption to a map + Object.keys(settingsObject).forEach(tableSetting => { + settingsObject[tableSetting].columnSettingsOptions = new Map(JSON.parse(settingsObject[tableSetting].columnSettingsOptions)); + + }); + + return settingsObject; + } + + storedTableSettingsInvalid(tableViewConfig: TableViewConfig, tableType: PartTableType): boolean { + let isInvalid = false; + + const storage = this.getStoredTableSettings(); + if (!storage || !storage[tableType]){ + return false; + } + const storageElement = storage[tableType]; + + if (!storageElement || !storageElement.columnsForDialog) { + return false; + } + + if (tableViewConfig.displayedColumns.length !== storageElement.columnsForDialog.length) { + isInvalid = true; + } + for (const col of tableViewConfig.displayedColumns.values()) { + if (!storageElement.columnsForDialog.includes(col)) { + isInvalid = true; + } + } + for (const col of storage[tableType]?.columnsForDialog) { + if (!tableViewConfig.displayedColumns.includes(col)) { + isInvalid = true; + } + } + if (isInvalid) { + localStorage.removeItem(this.settingsKey); + } + return isInvalid; + } + + emitChangeEvent() { + this.changeEvent.next(); + } + + getEvent() { + return this.changeEvent.asObservable(); + } } diff --git a/frontend/src/app/modules/page/alerts/core/alerts.facade.ts b/frontend/src/app/modules/page/alerts/core/alerts.facade.ts index 6595100e6b..16f5a69fa1 100644 --- a/frontend/src/app/modules/page/alerts/core/alerts.facade.ts +++ b/frontend/src/app/modules/page/alerts/core/alerts.facade.ts @@ -24,6 +24,7 @@ import { Notification, Notifications, NotificationStatus } from '@shared/model/n import { View } from '@shared/model/view.model'; import { AlertsService } from '@shared/service/alerts.service'; import { Observable, Subscription } from 'rxjs'; +import {NotificationFilter} from "../../../../mocks/services/investigations-mock/investigations.model"; @Injectable() export class AlertsFacade { @@ -47,20 +48,20 @@ export class AlertsFacade { return this.alertsService.getAlert(id); } - public setReceivedAlerts(page = 0, pageSize = 50, sorting: TableHeaderSort[] = []): void { + public setReceivedAlerts(page = 0, pageSize = 50, sorting: TableHeaderSort[] = [], filter?: NotificationFilter): void { this.alertReceivedSubscription?.unsubscribe(); this.alertReceivedSubscription = this.alertsService - .getReceivedAlerts(page, pageSize, sorting) + .getReceivedAlerts(page, pageSize, sorting, filter) .subscribe({ next: data => (this.alertsState.alertsReceived = { data }), error: (error: Error) => (this.alertsState.alertsReceived = { error }), }); } - public setQueuedAndRequestedAlerts(page = 0, pageSize = 50, sorting: TableHeaderSort[] = []): void { + public setQueuedAndRequestedAlerts(page = 0, pageSize = 50, sorting: TableHeaderSort[] = [], filter?: NotificationFilter): void { this.alertQueuedAndRequestedSubscription?.unsubscribe(); this.alertQueuedAndRequestedSubscription = this.alertsService - .getCreatedAlerts(page, pageSize, sorting) + .getCreatedAlerts(page, pageSize, sorting,filter) .subscribe({ next: data => (this.alertsState.alertsQueuedAndRequested = { data }), error: (error: Error) => (this.alertsState.alertsQueuedAndRequested = { error }), diff --git a/frontend/src/app/modules/page/alerts/presentation/alerts.component.ts b/frontend/src/app/modules/page/alerts/presentation/alerts.component.ts index 6cdde6cb81..df87bfc6f5 100644 --- a/frontend/src/app/modules/page/alerts/presentation/alerts.component.ts +++ b/frontend/src/app/modules/page/alerts/presentation/alerts.component.ts @@ -73,10 +73,28 @@ export class AlertsComponent { } public ngOnInit(): void { + this.paramSubscription = this.route.queryParams.subscribe(params => { - this.pagination.page = params?.pageNumber; - this.alertsFacade.setReceivedAlerts(this.pagination.page, this.pagination.pageSize, this.alertReceivedSortList); - this.alertsFacade.setQueuedAndRequestedAlerts(this.pagination.page, this.pagination.pageSize, this.alertQueuedAndRequestedSortList); + if (params.deeplink){ + this.pagination.page = 0; + if (params.received === 'true' && params?.notificationIds?.length > 0) { + console.log("Received"); + const filter = {notificationIds: params.notificationIds}; + this.alertsFacade.setReceivedAlerts(this.pagination.page, this.pagination.pageSize, this.alertReceivedSortList, filter); + this.alertsFacade.setQueuedAndRequestedAlerts(this.pagination.page, this.pagination.pageSize, this.alertQueuedAndRequestedSortList); + } + if (params.received === 'false' && params?.notificationIds?.length > 0) { + console.log("Sent"); + const filter = {notificationIds: params.notificationIds}; + this.alertsFacade.setQueuedAndRequestedAlerts(this.pagination.page, this.pagination.pageSize, this.alertQueuedAndRequestedSortList, filter); + this.alertsFacade.setReceivedAlerts(this.pagination.page, this.pagination.pageSize, this.alertReceivedSortList); + } + } else { + this.pagination.page = params?.pageNumber; + this.alertsFacade.setReceivedAlerts(this.pagination.page, this.pagination.pageSize, this.alertReceivedSortList); + this.alertsFacade.setQueuedAndRequestedAlerts(this.pagination.page, this.pagination.pageSize, this.alertQueuedAndRequestedSortList); + } + }) } diff --git a/frontend/src/app/modules/page/investigations/core/investigations.facade.ts b/frontend/src/app/modules/page/investigations/core/investigations.facade.ts index 405fc11489..18b784d32b 100644 --- a/frontend/src/app/modules/page/investigations/core/investigations.facade.ts +++ b/frontend/src/app/modules/page/investigations/core/investigations.facade.ts @@ -26,6 +26,9 @@ import { View } from '@shared/model/view.model'; import { InvestigationsService } from '@shared/service/investigations.service'; import { Observable, Subscription } from 'rxjs'; import { InvestigationsState } from './investigations.state'; +import { + NotificationFilter +} from "../../../../mocks/services/investigations-mock/investigations.model"; @Injectable() export class InvestigationsFacade { @@ -49,20 +52,20 @@ export class InvestigationsFacade { return this.investigationsService.getInvestigation(id); } - public setReceivedInvestigation(page = 0, pageSize = 50, sorting: TableHeaderSort[] = []): void { + public setReceivedInvestigation(page = 0, pageSize = 50, sorting: TableHeaderSort[] = [], filter?: NotificationFilter): void { this.investigationReceivedSubscription?.unsubscribe(); this.investigationReceivedSubscription = this.investigationsService - .getReceivedInvestigations(page, pageSize, sorting) + .getReceivedInvestigations(page, pageSize, sorting, filter) .subscribe({ next: data => (this.investigationsState.investigationsReceived = { data }), error: (error: Error) => (this.investigationsState.investigationsReceived = { error }), }); } - public setQueuedAndRequestedInvestigations(page = 0, pageSize = 50, sorting: TableHeaderSort[] = []): void { + public setQueuedAndRequestedInvestigations(page = 0, pageSize = 50, sorting: TableHeaderSort[] = [], filter?: NotificationFilter): void { this.investigationQueuedAndRequestedSubscription?.unsubscribe(); this.investigationQueuedAndRequestedSubscription = this.investigationsService - .getCreatedInvestigations(page, pageSize, sorting, ) + .getCreatedInvestigations(page, pageSize, sorting, filter) .subscribe({ next: data => (this.investigationsState.investigationsQueuedAndRequested = { data }), error: (error: Error) => (this.investigationsState.investigationsQueuedAndRequested = { error }), diff --git a/frontend/src/app/modules/page/investigations/presentation/investigations.component.ts b/frontend/src/app/modules/page/investigations/presentation/investigations.component.ts index fd4af6a9b1..74a1bd112e 100644 --- a/frontend/src/app/modules/page/investigations/presentation/investigations.component.ts +++ b/frontend/src/app/modules/page/investigations/presentation/investigations.component.ts @@ -19,109 +19,126 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -import { ChangeDetectorRef, Component, ViewChild } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { getRoute, INVESTIGATION_BASE_ROUTE } from '@core/known-route'; -import { InvestigationDetailFacade } from '@page/investigations/core/investigation-detail.facade'; -import { InvestigationHelperService } from '@page/investigations/core/investigation-helper.service'; -import { NotificationMenuActionsAssembler } from '@shared/assembler/notificationMenuActions.assembler'; -import { NotificationCommonModalComponent } from '@shared/components/notification-common-modal/notification-common-modal.component'; -import { TableSortingUtil } from '@shared/components/table/table-sorting.util'; -import { MenuActionConfig, TableEventConfig, TableHeaderSort } from '@shared/components/table/table.model'; -import { NotificationTabInformation } from '@shared/model/notification-tab-information'; -import { Notification, NotificationStatusGroup, NotificationType } from '@shared/model/notification.model'; -import { TranslationContext } from '@shared/model/translation-context.model'; -import { Subscription } from 'rxjs'; -import { InvestigationsFacade } from '../core/investigations.facade'; +import {ChangeDetectorRef, Component, ViewChild} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; +import {getRoute, INVESTIGATION_BASE_ROUTE} from '@core/known-route'; +import {InvestigationDetailFacade} from '@page/investigations/core/investigation-detail.facade'; +import {InvestigationHelperService} from '@page/investigations/core/investigation-helper.service'; +import {NotificationMenuActionsAssembler} from '@shared/assembler/notificationMenuActions.assembler'; +import { + NotificationCommonModalComponent +} from '@shared/components/notification-common-modal/notification-common-modal.component'; +import {TableSortingUtil} from '@shared/components/table/table-sorting.util'; +import {MenuActionConfig, TableEventConfig, TableHeaderSort} from '@shared/components/table/table.model'; +import {NotificationTabInformation} from '@shared/model/notification-tab-information'; +import {Notification, NotificationStatusGroup, NotificationType} from '@shared/model/notification.model'; +import {TranslationContext} from '@shared/model/translation-context.model'; +import {Subscription} from 'rxjs'; +import {InvestigationsFacade} from '../core/investigations.facade'; @Component({ - selector: 'app-investigations', - templateUrl: './investigations.component.html', + selector: 'app-investigations', + templateUrl: './investigations.component.html', }) export class InvestigationsComponent { - @ViewChild(NotificationCommonModalComponent) notificationCommonModalComponent: NotificationCommonModalComponent; - - public readonly investigationsReceived$; - public readonly investigationsQueuedAndRequested$; - - public menuActionsConfig: MenuActionConfig[]; - - public investigationReceivedSortList: TableHeaderSort[] = []; - public investigationQueuedAndRequestedSortList: TableHeaderSort[] = []; - private ctrlKeyState: boolean = false; - - private paramSubscription: Subscription; - - private pagination: TableEventConfig = { page: 0, pageSize: 50, sorting: [ 'createdDate', 'desc' ] }; - - constructor( - public readonly helperService: InvestigationHelperService, - public readonly investigationsFacade: InvestigationsFacade, - private readonly investigationDetailFacade: InvestigationDetailFacade, - private readonly router: Router, - private readonly route: ActivatedRoute, - private readonly cd: ChangeDetectorRef, - ) { - this.investigationsReceived$ = this.investigationsFacade.investigationsReceived$; - this.investigationsQueuedAndRequested$ = this.investigationsFacade.investigationsQueuedAndRequested$; - - window.addEventListener('keydown', (event) => { - this.ctrlKeyState = event.ctrlKey; - }); - window.addEventListener('keyup', (event) => { - this.ctrlKeyState = event.ctrlKey; - }); - - } - - public ngOnInit(): void { - this.paramSubscription = this.route.queryParams.subscribe(params => { - this.pagination.page = params?.pageNumber; - this.investigationsFacade.setReceivedInvestigation(this.pagination.page, this.pagination.pageSize, this.investigationReceivedSortList); - this.investigationsFacade.setQueuedAndRequestedInvestigations(this.pagination.page, this.pagination.pageSize, this.investigationQueuedAndRequestedSortList); - }); - } - - public ngAfterViewInit(): void { - this.menuActionsConfig = NotificationMenuActionsAssembler.getMenuActions(this.helperService, this.notificationCommonModalComponent); - this.cd.detectChanges(); - } - - public ngOnDestroy(): void { - this.investigationsFacade.stopInvestigations(); - this.paramSubscription?.unsubscribe(); - } - - public onReceivedTableConfigChanged(pagination: TableEventConfig) { - this.pagination = pagination; - this.setTableSortingList(pagination.sorting, NotificationStatusGroup.RECEIVED); - this.investigationsFacade.setReceivedInvestigation(this.pagination.page, this.pagination.pageSize, this.investigationReceivedSortList); - } - - public onQueuedAndRequestedTableConfigChanged(pagination: TableEventConfig) { - this.pagination = pagination; - this.setTableSortingList(pagination.sorting, NotificationStatusGroup.QUEUED_AND_REQUESTED); - this.investigationsFacade.setQueuedAndRequestedInvestigations(this.pagination.page, this.pagination.pageSize, this.investigationQueuedAndRequestedSortList); - } - - public openDetailPage(notification: Notification): void { - this.investigationDetailFacade.selected = { data: notification }; - const { link } = getRoute(INVESTIGATION_BASE_ROUTE); - const tabIndex = this.route.snapshot.queryParamMap.get('tabIndex'); - const tabInformation: NotificationTabInformation = { tabIndex: tabIndex, pageNumber: this.pagination.page }; - this.router.navigate([ `/${ link }/${ notification.id }` ], { queryParams: tabInformation }); - } - - public handleConfirmActionCompletedEvent() { - this.ngOnInit(); - } - - private setTableSortingList(sorting: TableHeaderSort, notificationTable: NotificationStatusGroup): void { - const tableSortList = notificationTable === NotificationStatusGroup.RECEIVED ? - this.investigationReceivedSortList : this.investigationQueuedAndRequestedSortList; - TableSortingUtil.setTableSortingList(sorting, tableSortList, this.ctrlKeyState); - } - - protected readonly TranslationContext = TranslationContext; - protected readonly NotificationType = NotificationType; + @ViewChild(NotificationCommonModalComponent) notificationCommonModalComponent: NotificationCommonModalComponent; + + public readonly investigationsReceived$; + public readonly investigationsQueuedAndRequested$; + + public menuActionsConfig: MenuActionConfig[]; + + public investigationReceivedSortList: TableHeaderSort[] = []; + public investigationQueuedAndRequestedSortList: TableHeaderSort[] = []; + private ctrlKeyState: boolean = false; + + private paramSubscription: Subscription; + + private pagination: TableEventConfig = {page: 0, pageSize: 50, sorting: ['createdDate', 'desc']}; + + constructor( + public readonly helperService: InvestigationHelperService, + public readonly investigationsFacade: InvestigationsFacade, + private readonly investigationDetailFacade: InvestigationDetailFacade, + private readonly router: Router, + private readonly route: ActivatedRoute, + private readonly cd: ChangeDetectorRef, + ) { + this.investigationsReceived$ = this.investigationsFacade.investigationsReceived$; + this.investigationsQueuedAndRequested$ = this.investigationsFacade.investigationsQueuedAndRequested$; + + window.addEventListener('keydown', (event) => { + this.ctrlKeyState = event.ctrlKey; + }); + window.addEventListener('keyup', (event) => { + this.ctrlKeyState = event.ctrlKey; + }); + + } + + public ngOnInit(): void { + + this.paramSubscription = this.route.queryParams.subscribe(params => { + if (params.deeplink) { + this.pagination.page = 0; + if (params.received === 'true' && params?.notificationIds?.length > 0) { + const filter = {notificationIds: params.notificationIds}; + this.investigationsFacade.setReceivedInvestigation(this.pagination.page, this.pagination.pageSize, this.investigationReceivedSortList, filter); + this.investigationsFacade.setQueuedAndRequestedInvestigations(this.pagination.page, this.pagination.pageSize, this.investigationReceivedSortList,); + } + if (params.received === 'false' && params?.notificationIds?.length > 0) { + const filter = {notificationIds: params.notificationIds}; + this.investigationsFacade.setQueuedAndRequestedInvestigations(this.pagination.page, this.pagination.pageSize, this.investigationReceivedSortList, filter); + this.investigationsFacade.setReceivedInvestigation(this.pagination.page, this.pagination.pageSize, this.investigationReceivedSortList); + } + } else { + this.pagination.page = params?.pageNumber; + this.investigationsFacade.setReceivedInvestigation(this.pagination.page, this.pagination.pageSize, this.investigationReceivedSortList); + this.investigationsFacade.setQueuedAndRequestedInvestigations(this.pagination.page, this.pagination.pageSize, this.investigationQueuedAndRequestedSortList); + } + }) + } + + public ngAfterViewInit(): void { + this.menuActionsConfig = NotificationMenuActionsAssembler.getMenuActions(this.helperService, this.notificationCommonModalComponent); + this.cd.detectChanges(); + } + + public ngOnDestroy(): void { + this.investigationsFacade.stopInvestigations(); + this.paramSubscription?.unsubscribe(); + } + + public onReceivedTableConfigChanged(pagination: TableEventConfig) { + this.pagination = pagination; + this.setTableSortingList(pagination.sorting, NotificationStatusGroup.RECEIVED); + this.investigationsFacade.setReceivedInvestigation(this.pagination.page, this.pagination.pageSize, this.investigationReceivedSortList); + } + + public onQueuedAndRequestedTableConfigChanged(pagination: TableEventConfig) { + this.pagination = pagination; + this.setTableSortingList(pagination.sorting, NotificationStatusGroup.QUEUED_AND_REQUESTED); + this.investigationsFacade.setQueuedAndRequestedInvestigations(this.pagination.page, this.pagination.pageSize, this.investigationQueuedAndRequestedSortList); + } + + public openDetailPage(notification: Notification): void { + this.investigationDetailFacade.selected = {data: notification}; + const {link} = getRoute(INVESTIGATION_BASE_ROUTE); + const tabIndex = this.route.snapshot.queryParamMap.get('tabIndex'); + const tabInformation: NotificationTabInformation = {tabIndex: tabIndex, pageNumber: this.pagination.page}; + this.router.navigate([`/${link}/${notification.id}`], {queryParams: tabInformation}); + } + + public handleConfirmActionCompletedEvent() { + this.ngOnInit(); + } + + private setTableSortingList(sorting: TableHeaderSort, notificationTable: NotificationStatusGroup): void { + const tableSortList = notificationTable === NotificationStatusGroup.RECEIVED ? + this.investigationReceivedSortList : this.investigationQueuedAndRequestedSortList; + TableSortingUtil.setTableSortingList(sorting, tableSortList, this.ctrlKeyState); + } + + protected readonly TranslationContext = TranslationContext; + protected readonly NotificationType = NotificationType; } diff --git a/frontend/src/app/modules/page/other-parts/presentation/customer-parts/customer-parts.component.spec.ts b/frontend/src/app/modules/page/other-parts/presentation/customer-parts/customer-parts.component.spec.ts index 6d0973ab15..cf3ebe8bb2 100644 --- a/frontend/src/app/modules/page/other-parts/presentation/customer-parts/customer-parts.component.spec.ts +++ b/frontend/src/app/modules/page/other-parts/presentation/customer-parts/customer-parts.component.spec.ts @@ -58,10 +58,10 @@ describe('CustomerPartsComponent', () => { const { fixture } = await renderCustomerParts(); const customerPartsComponent = fixture.componentInstance; - let nameHeader = await screen.findByText('table.column.name'); + let nameHeader = await screen.findByText('table.column.nameAtManufacturer'); fireEvent.click(nameHeader); - expect(customerPartsComponent['tableCustomerAsBuiltSortList']).toEqual([ [ 'name', 'asc' ] ]); + expect(customerPartsComponent['tableCustomerAsBuiltSortList']).toEqual([ [ 'nameAtManufacturer', 'asc' ] ]); }); @@ -69,7 +69,7 @@ describe('CustomerPartsComponent', () => { const { fixture } = await renderCustomerParts(); const customerPartsComponent = fixture.componentInstance; - let nameHeader = await screen.findByText('table.column.name'); + let nameHeader = await screen.findByText('table.column.nameAtManufacturer'); fireEvent.click(nameHeader); let semanticModelIdHeader = await screen.findByText('table.column.semanticModelId'); @@ -94,7 +94,7 @@ describe('CustomerPartsComponent', () => { await waitFor(() => { fireEvent.click(semanticModelIdHeader); }); - expect(customerPartsComponent['tableCustomerAsBuiltSortList']).toEqual([ [ 'name', 'asc' ], [ 'semanticModelId', 'desc' ] ]); + expect(customerPartsComponent['tableCustomerAsBuiltSortList']).toEqual([ [ 'nameAtManufacturer', 'asc' ], [ 'semanticModelId', 'desc' ] ]); }); it('should reset sorting on third click', async () => { @@ -103,7 +103,7 @@ describe('CustomerPartsComponent', () => { customerPartsComponent.bomLifecycle = MainAspectType.AS_BUILT; fixture.detectChanges(); - let nameHeader = await screen.findByText('table.column.name'); + let nameHeader = await screen.findByText('table.column.nameAtManufacturer'); fireEvent.click(nameHeader); let semanticModelIdHeader = await screen.findByText('table.column.semanticModelId'); diff --git a/frontend/src/app/modules/page/other-parts/presentation/other-parts.component.spec.ts b/frontend/src/app/modules/page/other-parts/presentation/other-parts.component.spec.ts index 614bb3b3f0..9509a35640 100644 --- a/frontend/src/app/modules/page/other-parts/presentation/other-parts.component.spec.ts +++ b/frontend/src/app/modules/page/other-parts/presentation/other-parts.component.spec.ts @@ -114,8 +114,8 @@ describe('Other Parts', () => { await renderOtherParts({ roles: [ 'user' ] }); fireEvent.click(screen.getAllByText('pageOtherParts.tab.supplier')[0]); - await waitFor(() => expect(screen.getByText('table.column.manufacturer')).toBeInTheDocument()); - fireEvent.click(screen.getByText('table.column.manufacturer')); + await waitFor(() => expect(screen.getByText('table.column.manufacturerName')).toBeInTheDocument()); + fireEvent.click(screen.getByText('table.column.manufacturerName')); const supplierParts = await firstValueFrom(otherPartsState.supplierPartsAsBuilt$); await waitFor(() => @@ -143,8 +143,8 @@ describe('Other Parts', () => { let tabs = screen.getAllByText('pageOtherParts.tab.customer'); fireEvent.click(tabs[0]); - await waitFor(() => expect(screen.getByText('table.column.manufacturer')).toBeInTheDocument()); - fireEvent.click(screen.getByText('table.column.manufacturer')); + await waitFor(() => expect(screen.getByText('table.column.manufacturerName')).toBeInTheDocument()); + fireEvent.click(screen.getByText('table.column.manufacturerName')); const customerParts = await firstValueFrom(otherPartsState.customerPartsAsBuilt$); await waitFor(() => diff --git a/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.html b/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.html index f115caa7ef..68f27f5a9d 100644 --- a/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.html +++ b/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.html @@ -46,7 +46,7 @@ [multiSortList]="tableSupplierAsBuiltSortList" (filterActivated)="filterActivated(true, $event )" [tableType]="PartTableType.AS_BUILT_SUPPLIER" - [mainAspectType]="MainAspectType.AS_BUILT" + [mainAspectType]="MainAspectType.AS_BUILT" > diff --git a/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.spec.ts b/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.spec.ts index 8134f71ad7..157d509768 100644 --- a/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.spec.ts +++ b/frontend/src/app/modules/page/other-parts/presentation/supplier-parts/supplier-parts.component.spec.ts @@ -77,10 +77,10 @@ describe('SupplierPartsComponent', () => { const { fixture } = await renderSupplierParts({ roles: [ 'admin' ] }); const supplierPartsComponent = fixture.componentInstance; - let nameHeader = await screen.findByText('table.column.name'); + let nameHeader = await screen.findByText('table.column.nameAtManufacturer'); fireEvent.click(nameHeader); - expect(supplierPartsComponent['tableSupplierAsBuiltSortList']).toEqual([ [ 'name', 'asc' ] ]); + expect(supplierPartsComponent['tableSupplierAsBuiltSortList']).toEqual([ [ 'nameAtManufacturer', 'asc' ] ]); }); @@ -88,7 +88,7 @@ describe('SupplierPartsComponent', () => { const { fixture } = await renderSupplierParts({ roles: [ 'admin' ] }); const supplierPartsComponent = fixture.componentInstance; - let nameHeader = await screen.findByText('table.column.name'); + let nameHeader = await screen.findByText('table.column.nameAtManufacturer'); fireEvent.click(nameHeader); let semanticModelIdHeader = await screen.findByText('table.column.semanticModelId'); @@ -113,14 +113,14 @@ describe('SupplierPartsComponent', () => { await waitFor(() => { fireEvent.click(semanticModelIdHeader); }); - expect(supplierPartsComponent['tableSupplierAsBuiltSortList']).toEqual([ [ 'name', 'asc' ], [ 'semanticModelId', 'desc' ] ]); + expect(supplierPartsComponent['tableSupplierAsBuiltSortList']).toEqual([ [ 'nameAtManufacturer', 'asc' ], [ 'semanticModelId', 'desc' ] ]); }); it('should reset sorting on third click', async () => { const { fixture } = await renderSupplierParts({ roles: [ 'admin' ] }); const supplierPartsComponent = fixture.componentInstance; - let nameHeader = await screen.findByText('table.column.name'); + let nameHeader = await screen.findByText('table.column.nameAtManufacturer'); fireEvent.click(nameHeader); let semanticModelIdHeader = await screen.findByText('table.column.semanticModelId'); diff --git a/frontend/src/app/modules/page/parts/model/parts.model.ts b/frontend/src/app/modules/page/parts/model/parts.model.ts index e9f775c89f..7d918a23f0 100644 --- a/frontend/src/app/modules/page/parts/model/parts.model.ts +++ b/frontend/src/app/modules/page/parts/model/parts.model.ts @@ -19,161 +19,162 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -import type { PaginationResponse } from '@core/model/pagination.model'; -import { SemanticModel, TractionBatteryCode } from '@page/parts/model/aspectModels.model'; -import { DetailAspectModel } from '@page/parts/model/detailAspectModel.model'; -import { MainAspectType } from '@page/parts/model/mainAspectType.enum'; -import { Owner } from '@page/parts/model/owner.enum'; +import type {PaginationResponse} from '@core/model/pagination.model'; +import {SemanticModel, TractionBatteryCode} from '@page/parts/model/aspectModels.model'; +import {DetailAspectModel} from '@page/parts/model/detailAspectModel.model'; +import {MainAspectType} from '@page/parts/model/mainAspectType.enum'; +import {Owner} from '@page/parts/model/owner.enum'; export interface Part { - id: string; - idShort: string; - name: string; - manufacturer: string; - manufacturerPartId: string; - nameAtManufacturer: string; - businessPartner: string; - semanticModel?: SemanticModel; - semanticModelId: string; - qualityType: QualityType; - children: string[]; - parents?: string[]; - error?: boolean; - activeInvestigation?: boolean; - activeAlert: boolean; - van: string; - semanticDataModel: SemanticDataModel; - classification: string; - - mainAspectType: MainAspectType; - - // aspectmodel props are temporarely hardcoded here because Tables and Views only accept root level prop array - // as built - partId?: string; - customerPartId?: string; - nameAtCustomer?: string; - manufacturingDate?: string; - manufacturingCountry?: string; - - productType?: string; - tractionBatteryCode?: string; - subcomponents: TractionBatteryCode[]; - - // as planned - validityPeriodFrom?: string; - validityPeriodTo?: string; - //partSiteInformationAsPlanned - catenaXSiteId: string; - psFunction: string; - functionValidFrom?: string; - functionValidUntil?: string; - - // count of notifications - activeAlerts: string []; - activeInvestigations: string []; + id: string; + idShort: string; + manufacturerName: string; + manufacturerPartId: string; + nameAtManufacturer: string; + businessPartner: string; + semanticModel?: SemanticModel; + semanticModelId: string; + qualityType: QualityType; + children: string[]; + parents?: string[]; + error?: boolean; + activeInvestigation?: boolean; + activeAlert: boolean; + van: string; + semanticDataModel: SemanticDataModel; + classification: string; + + mainAspectType: MainAspectType; + + // aspectmodel props are temporarely hardcoded here because Tables and Views only accept root level prop array + // as built + partId?: string; + customerPartId?: string; + nameAtCustomer?: string; + manufacturingDate?: string; + manufacturingCountry?: string; + + productType?: string; + tractionBatteryCode?: string; + subcomponents: TractionBatteryCode[]; + + // as planned + validityPeriodFrom?: string; + validityPeriodTo?: string; + //partSiteInformationAsPlanned + catenaXSiteId: string; + psFunction: string; + functionValidFrom?: string; + functionValidUntil?: string; + + // count of notifications + sentActiveAlerts: string []; + sentActiveInvestigations: string []; + receivedActiveAlerts: string []; + receivedActiveInvestigations: string []; } export interface PartResponse { - id: string; - idShort: string; - semanticModelId: string; - manufacturerPartId: string; - businessPartner: string; - manufacturerName: string; - nameAtManufacturer: string; - owner: Owner; - childRelations: Relation[]; - parentRelations: Relation[]; - activeAlert: boolean; - underInvestigation: boolean; - qualityType: QualityType; - van: string; - semanticDataModel: SemanticDataModel; - classification: string; - detailAspectModels: DetailAspectModel[]; - - // TODO: Delete ? flag when AsPlanned Parts do not return the props anymore - qualityAlertIdsInStatusActive?: string[]; - qualityInvestigationIdsInStatusActive?: string[]; - + id: string; + idShort: string; + semanticModelId: string; + manufacturerPartId: string; + businessPartner: string; + manufacturerName: string; + nameAtManufacturer: string; + owner: Owner; + childRelations: Relation[]; + parentRelations: Relation[]; + activeAlert: boolean; + underInvestigation: boolean; + qualityType: QualityType; + van: string; + semanticDataModel: SemanticDataModel; + classification: string; + detailAspectModels: DetailAspectModel[]; + // TODO: Delete ? flag when AsPlanned Parts do not return the props anymore + sentQualityAlertIdsInStatusActive: string[], + receivedQualityAlertIdsInStatusActive: string[], + sentQualityInvestigationIdsInStatusActive: string[], + receivedQualityInvestigationIdsInStatusActive: string[] } export type PartsResponse = PaginationResponse; // TODO: needs to be aligned with Severity in the future in terms of coding standards and use export enum QualityType { - Ok = 'Ok', - Minor = 'Minor', - Major = 'Major', - Critical = 'Critical', - LifeThreatening = 'LifeThreatening', + Ok = 'Ok', + Minor = 'Minor', + Major = 'Major', + Critical = 'Critical', + LifeThreatening = 'LifeThreatening', } export enum SemanticDataModel { - BATCH = 'BATCH', - SERIALPART = 'SERIALPART', - PARTASPLANNED = 'PARTASPLANNED', - JUSTINSEQUENCE = 'JUSTINSEQUENCE', - TRACTIONBATTERYCODE = 'TRACTIONBATTERYCODE', - UNKNOWN = 'UNKNOWN' + BATCH = 'BATCH', + SERIALPART = 'SERIALPART', + PARTASPLANNED = 'PARTASPLANNED', + JUSTINSEQUENCE = 'JUSTINSEQUENCE', + TRACTIONBATTERYCODE = 'TRACTIONBATTERYCODE', + UNKNOWN = 'UNKNOWN' } export enum SemanticDataModelInCamelCase { - BATCH = 'Batch', - SERIALPART = 'SerialPart', - PARTASPLANNED = 'PartAsPlanned', - JUSTINSEQUENCE = 'JustInSequence', - TRACTIONBATTERYCODE = 'TractionBatteryCode', - UNKNOWN = 'Unknown' + BATCH = 'Batch', + SERIALPART = 'SerialPart', + PARTASPLANNED = 'PartAsPlanned', + JUSTINSEQUENCE = 'JustInSequence', + TRACTIONBATTERYCODE = 'TractionBatteryCode', + UNKNOWN = 'Unknown' } export interface Relation { - id: string; - idShort: string; + id: string; + idShort: string; } export interface AssetAsBuiltFilter { - id?: string, - idShort?: string, - name?: string, - manufacturer?: string, - partId?: string, - manufacturerPartId?: string, - customerPartId?: string, - classification?: string, - nameAtCustomer?: string, - semanticModelId?: string, - semanticDataModel?: string[], - manufacturingDate?: string, - manufacturingCountry?: string + id?: string, + idShort?: string, + name?: string, + manufacturerName?: string, + partId?: string, + manufacturerPartId?: string, + customerPartId?: string, + classification?: string, + nameAtCustomer?: string, + semanticModelId?: string, + semanticDataModel?: string[], + manufacturingDate?: string, + manufacturingCountry?: string } export interface AssetAsPlannedFilter { - id?: string, - idShort?: string, - name?: string, - manufacturer?: string, - manufacturerPartId?: string, - classification?: string, - semanticDataModel?: string[], - semanticModelId?: string, - validityPeriodFrom?: string, - validityPeriodTo?: string, - psFunction?: string, - catenaXSiteId?: string, - functionValidFrom?: string, - functionValidUntil?: string, + id?: string, + idShort?: string, + name?: string, + manufacturer?: string, + manufacturerPartId?: string, + classification?: string, + semanticDataModel?: string[], + semanticModelId?: string, + validityPeriodFrom?: string, + validityPeriodTo?: string, + psFunction?: string, + catenaXSiteId?: string, + functionValidFrom?: string, + functionValidUntil?: string, } export enum FilterOperator { - EQUAL = 'EQUAL', - AT_LOCAL_DATE = 'AT_LOCAL_DATE', - STARTS_WITH = 'STARTS_WITH', - BEFORE_LOCAL_DATE = 'BEFORE_LOCAL_DATE', - AFTER_LOCAL_DATE = 'AFTER_LOCAL_DATE', - NOTIFICATION_COUNT_EQUAL = 'NOTIFICATION_COUNT_EQUAL' + EQUAL = 'EQUAL', + AT_LOCAL_DATE = 'AT_LOCAL_DATE', + STARTS_WITH = 'STARTS_WITH', + BEFORE_LOCAL_DATE = 'BEFORE_LOCAL_DATE', + AFTER_LOCAL_DATE = 'AFTER_LOCAL_DATE', + NOTIFICATION_COUNT_EQUAL = 'NOTIFICATION_COUNT_EQUAL' } export function getFilterOperatorValue(operator: FilterOperator) { - return operator as string; + return operator as string; } diff --git a/frontend/src/app/modules/page/parts/presentation/parts.component.html b/frontend/src/app/modules/page/parts/presentation/parts.component.html index bceceb610d..77746c5d88 100644 --- a/frontend/src/app/modules/page/parts/presentation/parts.component.html +++ b/frontend/src/app/modules/page/parts/presentation/parts.component.html @@ -53,7 +53,7 @@ *viewContainer="partsAsBuilt$ | async; main: mainTmp; error: errorTmp; loading: loaderTmp"> - { id, idShort: idShort, semanticModelId: semanticModelId, - - manufacturer: manufacturerName, + manufacturerName: manufacturerName, manufacturerPartId: manufacturerPartId, nameAtManufacturer: nameAtManufacturer, businessPartner: businessPartner, - name: nameAtManufacturer, children: [], parents: [], activeAlert: false, @@ -130,11 +128,8 @@ describe('PartsAssembler', () => { van: 'van', semanticDataModel: SemanticDataModel.BATCH, classification: classification, - semanticModel: semanticModel, - mainAspectType: mainAspectType, - partId: partId, // is partInstance, BatchId, jisNumber customerPartId: customerPartId, nameAtCustomer: nameAtCustomer, @@ -154,10 +149,11 @@ describe('PartsAssembler', () => { const manufacturingCountry = 'manufacturingCountry'; const classification = 'classification'; + it('should clean up data for part view', () => { const data = { semanticDataModel, semanticModelId, manufacturingDate, manufacturingCountry, classification, test: '' } as unknown as Part; expect(PartsAssembler.filterPartForView({ data })).toEqual({ - data: { name: undefined, manufacturingDate, semanticModelId, semanticDataModel, manufacturingCountry, classification } as unknown as Part, + data: { manufacturingDate, semanticModelId, semanticDataModel, manufacturingCountry, classification } as unknown as Part, }); }); @@ -169,19 +165,19 @@ describe('PartsAssembler', () => { }); describe('mapPartForManufacturerView', () => { - const manufacturer = 'manufacturer'; + const manufacturerName = 'manufacturerName'; const manufacturerPartId = 'manufacturerPartId'; const nameAtManufacturer = 'nameAtManufacturer'; const van = 'van'; const mainAspectType = MainAspectType.AS_BUILT it('should clean up data for manufacturer view', done => { - const data = { manufacturer, manufacturerPartId, nameAtManufacturer, test: '', van, mainAspectType } as unknown as Part; + const data = { manufacturerName, manufacturerPartId, nameAtManufacturer, test: '', van, mainAspectType } as unknown as Part; of({ data }) .pipe(PartsAssembler.mapPartForManufacturerView()) .subscribe(result => { expect(result).toEqual({ - data: { manufacturer, manufacturerPartId, nameAtManufacturer, van } as unknown as Part, + data: { manufacturerName, manufacturerPartId, nameAtManufacturer, van } as unknown as Part, }); done(); }); diff --git a/frontend/src/app/modules/shared/assembler/parts.assembler.ts b/frontend/src/app/modules/shared/assembler/parts.assembler.ts index 492236a043..8c2fb2526d 100644 --- a/frontend/src/app/modules/shared/assembler/parts.assembler.ts +++ b/frontend/src/app/modules/shared/assembler/parts.assembler.ts @@ -22,11 +22,11 @@ import {Pagination, PaginationResponse} from '@core/model/pagination.model'; import {PaginationAssembler} from '@core/pagination/pagination.assembler'; import { - AsBuiltAspectModel, - AsPlannedAspectModel, - PartSiteInformationAsPlanned, - SemanticModel, - TractionBatteryCode, + AsBuiltAspectModel, + AsPlannedAspectModel, + PartSiteInformationAsPlanned, + SemanticModel, + TractionBatteryCode, } from '@page/parts/model/aspectModels.model'; import {MainAspectType} from '@page/parts/model/mainAspectType.enum'; import {Part, PartResponse, QualityType} from '@page/parts/model/parts.model'; @@ -37,245 +37,243 @@ import {map} from 'rxjs/operators'; export class PartsAssembler { - public static createSemanticModelFromPartResponse(partResponse: PartResponse): SemanticModel { - let proplist= {}; - partResponse.detailAspectModels.forEach((detailAspectModel) => { - proplist = {...proplist, ...detailAspectModel.data}; - }) + public static createSemanticModelFromPartResponse(partResponse: PartResponse): SemanticModel { + let proplist = {}; + partResponse.detailAspectModels.forEach((detailAspectModel) => { + proplist = {...proplist, ...detailAspectModel.data}; + }) - return proplist; - } + return proplist; + } + + public static assemblePart(partResponse: PartResponse, mainAspectType: MainAspectType): Part { + if (!partResponse) { + return null; + } - public static assemblePart(partResponse: PartResponse, mainAspectType: MainAspectType): Part { - if (!partResponse) { - return null; + let createdSemanticModel = PartsAssembler.createSemanticModelFromPartResponse(partResponse); + + // Access the partId property + + const partId = (partResponse.detailAspectModels[0].data as AsBuiltAspectModel)?.partId; + const customerPartId = (partResponse.detailAspectModels[0].data as AsBuiltAspectModel)?.customerPartId; + const nameAtCustomer = (partResponse.detailAspectModels[0].data as AsBuiltAspectModel)?.nameAtCustomer; + const manufacturingDate = (partResponse.detailAspectModels[0].data as AsBuiltAspectModel)?.manufacturingDate; + const manufacturingCountry = (partResponse.detailAspectModels[0].data as AsBuiltAspectModel)?.manufacturingCountry; + + const validityPeriodFrom = (partResponse.detailAspectModels[0].data as AsPlannedAspectModel)?.validityPeriodFrom; + const validityPeriodTo = (partResponse.detailAspectModels[0].data as AsPlannedAspectModel)?.validityPeriodTo; + const catenaXSiteId = (partResponse.detailAspectModels[1]?.data as PartSiteInformationAsPlanned)?.catenaXSiteId; + const psFunction = (partResponse.detailAspectModels[1]?.data as PartSiteInformationAsPlanned)?.function; + const functionValidFrom = (partResponse.detailAspectModels[1]?.data as PartSiteInformationAsPlanned)?.functionValidFrom; + const functionValidUntil = (partResponse.detailAspectModels[1]?.data as PartSiteInformationAsPlanned)?.functionValidUntil; + + // traction battery code + const productType = (partResponse.detailAspectModels[1]?.data as TractionBatteryCode)?.productType; + const tractionBatteryCode = (partResponse.detailAspectModels[1]?.data as TractionBatteryCode)?.tractionBatteryCode; + const subcomponents = (partResponse.detailAspectModels[1]?.data as TractionBatteryCode)?.subcomponents; + + return { + id: partResponse.id, + idShort: partResponse.idShort, + semanticModelId: partResponse.semanticModelId, + manufacturerName: partResponse.manufacturerName, + manufacturerPartId: partResponse.manufacturerPartId, + nameAtManufacturer: partResponse.nameAtManufacturer, + businessPartner: partResponse.businessPartner, + children: partResponse.childRelations.map(child => child.id) || [], + parents: partResponse.parentRelations?.map(parent => parent.id) || [], + activeAlert: partResponse.activeAlert || false, + activeInvestigation: partResponse.underInvestigation || false, + qualityType: partResponse.qualityType || QualityType.Ok, + van: partResponse.van || '--', + semanticDataModel: partResponse.semanticDataModel, + classification: partResponse.classification, + semanticModel: createdSemanticModel, + + mainAspectType: mainAspectType, + + // as built + partId: partId, // is partInstance, BatchId, jisNumber + customerPartId: customerPartId, + nameAtCustomer: nameAtCustomer, + manufacturingDate: manufacturingDate === "null" ? null : manufacturingDate, + manufacturingCountry: manufacturingCountry, + + // tractionBatteryCode + productType: productType, + tractionBatteryCode: tractionBatteryCode, + subcomponents: subcomponents, + + // as planned + validityPeriodFrom: validityPeriodFrom === "null" ? null : validityPeriodFrom, + validityPeriodTo: validityPeriodTo === "null" ? null : validityPeriodTo, + + //partSiteInformationAsPlanned + catenaXSiteId: catenaXSiteId, + psFunction: psFunction, + functionValidFrom: functionValidFrom === "null" ? null : functionValidFrom, + functionValidUntil: functionValidUntil === "null" ? null : functionValidUntil, + + // count of notifications + sentActiveAlerts: partResponse.sentQualityAlertIdsInStatusActive, + receivedActiveAlerts: partResponse.receivedQualityAlertIdsInStatusActive, + sentActiveInvestigations: partResponse.sentQualityInvestigationIdsInStatusActive, + receivedActiveInvestigations: partResponse.receivedQualityInvestigationIdsInStatusActive + + + }; } - let createdSemanticModel = PartsAssembler.createSemanticModelFromPartResponse(partResponse); - - // Access the partId property - - const partId = (partResponse.detailAspectModels[0].data as AsBuiltAspectModel)?.partId; - const customerPartId = (partResponse.detailAspectModels[0].data as AsBuiltAspectModel)?.customerPartId; - const nameAtCustomer = (partResponse.detailAspectModels[0].data as AsBuiltAspectModel)?.nameAtCustomer; - const manufacturingDate = (partResponse.detailAspectModels[0].data as AsBuiltAspectModel)?.manufacturingDate; - const manufacturingCountry = (partResponse.detailAspectModels[0].data as AsBuiltAspectModel)?.manufacturingCountry; - - const validityPeriodFrom = (partResponse.detailAspectModels[0].data as AsPlannedAspectModel)?.validityPeriodFrom; - const validityPeriodTo = (partResponse.detailAspectModels[0].data as AsPlannedAspectModel)?.validityPeriodTo; - const catenaXSiteId = (partResponse.detailAspectModels[1]?.data as PartSiteInformationAsPlanned)?.catenaXSiteId; - const psFunction = (partResponse.detailAspectModels[1]?.data as PartSiteInformationAsPlanned)?.function; - const functionValidFrom = (partResponse.detailAspectModels[1]?.data as PartSiteInformationAsPlanned)?.functionValidFrom; - const functionValidUntil = (partResponse.detailAspectModels[1]?.data as PartSiteInformationAsPlanned)?.functionValidUntil; - - // traction battery code - const productType = (partResponse.detailAspectModels[1]?.data as TractionBatteryCode)?.productType; - const tractionBatteryCode = (partResponse.detailAspectModels[1]?.data as TractionBatteryCode)?.tractionBatteryCode; - const subcomponents = (partResponse.detailAspectModels[1]?.data as TractionBatteryCode)?.subcomponents; - - let mappedPart = { - id: partResponse.id, - idShort: partResponse.idShort, - semanticModelId: partResponse.semanticModelId, - manufacturer: partResponse.manufacturerName, - manufacturerPartId: partResponse.manufacturerPartId, - nameAtManufacturer: partResponse.nameAtManufacturer, - businessPartner: partResponse.businessPartner, - name: partResponse.nameAtManufacturer, - children: partResponse.childRelations.map(child => child.id) || [], - parents: partResponse.parentRelations?.map(parent => parent.id) || [], - activeAlert: partResponse.activeAlert || false, - activeInvestigation: partResponse.underInvestigation || false, - qualityType: partResponse.qualityType || QualityType.Ok, - van: partResponse.van || '--', - semanticDataModel: partResponse.semanticDataModel, - classification: partResponse.classification, - semanticModel: createdSemanticModel, - - mainAspectType: mainAspectType, - - // as built - partId: partId, // is partInstance, BatchId, jisNumber - customerPartId: customerPartId, - nameAtCustomer: nameAtCustomer, - manufacturingDate: manufacturingDate === "null" ? null : manufacturingDate , - manufacturingCountry: manufacturingCountry, - - // tractionBatteryCode - productType: productType, - tractionBatteryCode: tractionBatteryCode, - subcomponents: subcomponents, - - // as planned - validityPeriodFrom: validityPeriodFrom === "null" ? null : validityPeriodFrom, - validityPeriodTo: validityPeriodTo === "null" ? null : validityPeriodTo, - - //partSiteInformationAsPlanned - catenaXSiteId: catenaXSiteId, - psFunction: psFunction, - functionValidFrom: functionValidFrom=== "null" ? null : functionValidFrom, - functionValidUntil: functionValidUntil=== "null" ? null : functionValidUntil, - - // count of notifications - activeAlerts: partResponse.qualityAlertIdsInStatusActive, - activeInvestigations: partResponse.qualityInvestigationIdsInStatusActive, + public static assembleOtherPart(partResponse: PartResponse, mainAspectType: MainAspectType): Part { + if (!partResponse) { + return null; + } + return {...PartsAssembler.assemblePart(partResponse, mainAspectType), qualityType: partResponse.qualityType}; } - return mappedPart; - } - public static assembleOtherPart(partResponse: PartResponse, mainAspectType: MainAspectType): Part { - if (!partResponse) { - return null; + + public static assembleParts(parts: PaginationResponse, mainAspectType: MainAspectType): Pagination { + return PaginationAssembler.assemblePagination(PartsAssembler.assemblePart, parts, mainAspectType); } - return { ...PartsAssembler.assemblePart(partResponse, mainAspectType), qualityType: partResponse.qualityType }; - } + public static assemblePartList(parts: PartResponse[], mainAspectType: MainAspectType): Part[] { + const partCopy = [...parts]; + return partCopy.map(part => PartsAssembler.assemblePart(part, mainAspectType)); + } - public static assembleParts(parts: PaginationResponse, mainAspectType: MainAspectType): Pagination { - return PaginationAssembler.assemblePagination(PartsAssembler.assemblePart, parts, mainAspectType); - } + public static assembleOtherParts(parts: PaginationResponse, mainAspectType: MainAspectType): Pagination { + return PaginationAssembler.assemblePagination(PartsAssembler.assembleOtherPart, parts, mainAspectType); + } - public static assemblePartList(parts: PartResponse[], mainAspectType: MainAspectType): Part[] { - const partCopy = [...parts]; - return partCopy.map(part => PartsAssembler.assemblePart(part, mainAspectType)); - } + public static filterPartForView(viewData: View): View { + if (!viewData?.data) { + return viewData; + } - public static assembleOtherParts(parts: PaginationResponse, mainAspectType: MainAspectType): Pagination { - return PaginationAssembler.assemblePagination(PartsAssembler.assembleOtherPart, parts, mainAspectType); - } + const { + semanticDataModel, + semanticModelId, + manufacturingDate, + manufacturingCountry, + classification, + + } = viewData.data; + return { + data: { + semanticDataModel, + semanticModelId, + manufacturingDate, + manufacturingCountry, + classification + } as Part + }; + } - public static filterPartForView(viewData: View): View { - if (!viewData?.data) { - return viewData; + public static mapPartForView(): OperatorFunction, View> { + return map(PartsAssembler.filterPartForView); } - const { - name, - semanticDataModel, - semanticModelId, - manufacturingDate, - manufacturingCountry, - classification , - - } = viewData.data; - return { data: { - name, - semanticDataModel, - semanticModelId, - manufacturingDate, - manufacturingCountry, - classification , - - - } as Part }; - } - - public static mapPartForView(): OperatorFunction, View> { - return map(PartsAssembler.filterPartForView); - } - - public static mapPartForManufacturerView(): OperatorFunction, View> { - return map(viewData => { - if (!viewData.data) { - return viewData; - } - - // exclude 'van' if is a partAsPlanned - if(viewData.data?.mainAspectType === MainAspectType.AS_BUILT) { - const { - manufacturer, - manufacturerPartId, - nameAtManufacturer, - van, - } = viewData.data; - return { data: { manufacturer, manufacturerPartId, nameAtManufacturer, van } as Part }; - } else { - const { - manufacturer, - manufacturerPartId, - nameAtManufacturer, - } = viewData.data; - return { data: { manufacturer, manufacturerPartId, nameAtManufacturer } as Part }; - } - }); - } - - public static mapPartForCustomerOrPartSiteView(): OperatorFunction, View> { - return map(viewData => { - if (!viewData.data) { - return; - } - // if no customer data is available then return partSiteInformation - if(!viewData.data?.nameAtCustomer && !viewData.data?.customerPartId && viewData.data?.functionValidFrom) { - const { catenaXSiteId, psFunction, functionValidFrom, functionValidUntil } = viewData.data; - return { data: { catenaXSiteId, psFunction, functionValidFrom, functionValidUntil } as Part }; - } - - const { nameAtCustomer, customerPartId } = viewData.data; - return { data: { nameAtCustomer, customerPartId } as Part }; - }); - } - - public static mapPartForTractionBatteryCodeDetailsView(): OperatorFunction, View> { - return map(viewData => { - if (!viewData?.data?.tractionBatteryCode) { - return; - } - - const { productType, tractionBatteryCode } = viewData.data; - return { data: { productType, tractionBatteryCode } as Part }; - }); - } - - public static mapPartForTractionBatteryCodeSubComponentsView(): OperatorFunction, View> { - return map(viewData => { - if (!viewData?.data?.tractionBatteryCode || !viewData?.data?.subcomponents?.length) { - return; - } - - const { productType, tractionBatteryCode, subcomponents } = viewData.data; - return { data: { productType, tractionBatteryCode, subcomponents } as Part }; - }); - } - - public static mapSortToApiSort(sorting: TableHeaderSort): string { - if (!sorting) { - return ''; + public static mapPartForManufacturerView(): OperatorFunction, View> { + return map(viewData => { + if (!viewData.data) { + return viewData; + } + + // exclude 'van' if is a partAsPlanned + if (viewData.data?.mainAspectType === MainAspectType.AS_BUILT) { + const { + manufacturerName, + manufacturerPartId, + nameAtManufacturer, + van, + } = viewData.data; + return {data: {manufacturerName, manufacturerPartId, nameAtManufacturer, van} as Part}; + } else { + const { + manufacturerName, + manufacturerPartId, + nameAtManufacturer, + } = viewData.data; + return {data: {manufacturerName, manufacturerPartId, nameAtManufacturer} as Part}; + } + }); } + public static mapPartForCustomerOrPartSiteView(): OperatorFunction, View> { + return map(viewData => { + if (!viewData.data) { + return; + } + // if no customer data is available then return partSiteInformation + if (!viewData.data?.nameAtCustomer && !viewData.data?.customerPartId && viewData.data?.functionValidFrom) { + const {catenaXSiteId, psFunction, functionValidFrom, functionValidUntil} = viewData.data; + return {data: {catenaXSiteId, psFunction, functionValidFrom, functionValidUntil} as Part}; + } + + const {nameAtCustomer, customerPartId} = viewData.data; + return {data: {nameAtCustomer, customerPartId} as Part}; + }); + } + + public static mapPartForTractionBatteryCodeDetailsView(): OperatorFunction, View> { + return map(viewData => { + if (!viewData?.data?.tractionBatteryCode) { + return; + } + + const {productType, tractionBatteryCode} = viewData.data; + return {data: {productType, tractionBatteryCode} as Part}; + }); + } + + public static mapPartForTractionBatteryCodeSubComponentsView(): OperatorFunction, View> { + return map(viewData => { + if (!viewData?.data?.tractionBatteryCode || !viewData?.data?.subcomponents?.length) { + return; + } + const {productType, tractionBatteryCode, subcomponents} = viewData.data; + return {data: {productType, tractionBatteryCode, subcomponents} as Part}; + }); + } + + public static mapSortToApiSort(sorting: TableHeaderSort): string { + if (!sorting) { + return ''; + } - const localToApiMapping = new Map([ - ['id', 'id'], - ['idShort', 'idShort'], - ['semanticModelId', 'semanticModelId'], - ['manufacturer', 'manufacturerName'], - ['manufacturerPartId', 'manufacturerPartId'], - ['partId', "manufacturerPartId"], - ['nameAtManufacturer', 'nameAtManufacturer'], - ['businessPartner', 'businessPartner'], - ['name', 'nameAtManufacturer'], - ['qualityType', 'qualityType'], - ['van', 'van'], - ['semanticDataModel', 'semanticDataModel'], - ['classification', 'classification'], - ['customerPartId', 'customerPartId'], - ['nameAtCustomer', 'nameAtCustomer'], - ['manufacturingDate', 'manufacturingDate'], - ['manufacturingCountry', 'manufacturingCountry'], - ['validityPeriodFrom', 'validityPeriodFrom'], - ['validityPeriodTo', 'validityPeriodTo'], - ['catenaXSiteId', 'catenaXSiteId'], - ['psFunction', 'function'], - ['functionValidFrom', 'functionValidFrom'], - ['functionValidUntil', 'functionValidUntil'], - [ 'activeAlerts', 'qualityAlertIdsInStatusActive' ], - [ 'activeInvestigations', 'qualityInvestigationIdsInStatusActive' ], - - ]); - - - - return `${localToApiMapping.get(sorting[0]) || sorting},${sorting[1]}`; - } + + const localToApiMapping = new Map([ + ['id', 'id'], + ['idShort', 'idShort'], + ['semanticModelId', 'semanticModelId'], + ['manufacturer', 'manufacturerName'], + ['manufacturerPartId', 'manufacturerPartId'], + ['partId', "manufacturerPartId"], + ['nameAtManufacturer', 'nameAtManufacturer'], + ['businessPartner', 'businessPartner'], + ['name', 'nameAtManufacturer'], + ['qualityType', 'qualityType'], + ['van', 'van'], + ['semanticDataModel', 'semanticDataModel'], + ['classification', 'classification'], + ['customerPartId', 'customerPartId'], + ['nameAtCustomer', 'nameAtCustomer'], + ['manufacturingDate', 'manufacturingDate'], + ['manufacturingCountry', 'manufacturingCountry'], + ['validityPeriodFrom', 'validityPeriodFrom'], + ['validityPeriodTo', 'validityPeriodTo'], + ['catenaXSiteId', 'catenaXSiteId'], + ['psFunction', 'function'], + ['functionValidFrom', 'functionValidFrom'], + ['functionValidUntil', 'functionValidUntil'], + ['sentActiveAlerts', 'sentQualityAlertIdsInStatusActive'], + ['receivedActiveAlerts', 'receivedQualityAlertIdsInStatusActive'], + ['sentActiveInvestigations', 'receivedQualityAlertIdsInStatusActive'], + ['receivedActiveInvestigations', 'receivedQualityAlertIdsInStatusActive'] + ]); + + return `${localToApiMapping.get(sorting[0]) || sorting},${sorting[1]}`; + } } diff --git a/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.ts b/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.ts index b98f26d425..70f0b32722 100644 --- a/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.ts +++ b/frontend/src/app/modules/shared/components/multi-select-autocomplete/multi-select-autocomplete.component.ts @@ -240,7 +240,7 @@ export class MultiSelectAutocompleteComponent implements OnChanges { this.delayTimeoutId = setTimeout(timeoutCallback, 500); } - +// This is used by parent component isUnsupportedAutoCompleteField(fieldName: string) { return fieldName === 'activeAlerts' || fieldName === 'activeInvestigations'; } diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-as-built-configuration.model.ts b/frontend/src/app/modules/shared/components/parts-table/parts-as-built-configuration.model.ts new file mode 100644 index 0000000000..f62d29cfee --- /dev/null +++ b/frontend/src/app/modules/shared/components/parts-table/parts-as-built-configuration.model.ts @@ -0,0 +1,50 @@ +/******************************************************************************** + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +import {TableFilterConfiguration} from "@shared/components/parts-table/parts-config.model"; + +export class PartsAsBuiltConfigurationModel extends TableFilterConfiguration { + constructor() { + const sortableColumns = { + select: false, + id: true, + idShort: true, + nameAtManufacturer: true, + manufacturerName: true, + partId: true, + manufacturerPartId: true, + customerPartId: true, + classification: true, + nameAtCustomer: true, + semanticModelId: true, + semanticDataModel: true, + manufacturingDate: true, + manufacturingCountry: true, + receivedActiveAlerts: true, + receivedActiveInvestigations: true, + sentActiveAlerts: true, + sentActiveInvestigations: true, + // menu: false + }; + + const dateFields = ['manufacturingDate']; + const singleSearchFields = ['receivedActiveAlerts', 'sentActiveAlerts', 'receivedActiveInvestigations', 'sentActiveInvestigations']; + super(sortableColumns, dateFields, singleSearchFields); + } + +} diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-as-built-customer-configuration.model.ts b/frontend/src/app/modules/shared/components/parts-table/parts-as-built-customer-configuration.model.ts new file mode 100644 index 0000000000..ba48c6bb14 --- /dev/null +++ b/frontend/src/app/modules/shared/components/parts-table/parts-as-built-customer-configuration.model.ts @@ -0,0 +1,43 @@ +/******************************************************************************** + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +import {TableFilterConfiguration} from "@shared/components/parts-table/parts-config.model"; + +export class PartsAsBuiltCustomerConfigurationModel extends TableFilterConfiguration { + + constructor() { + const sortableColumns = { + select: false, + semanticDataModel: true, + nameAtManufacturer: true, + manufacturerName: true, + manufacturerPartId: true, + semanticModelId: true, + manufacturingDate: true, + receivedActiveAlerts: true, + receivedActiveInvestigations: true, + sentActiveAlerts: true, + sentActiveInvestigations: true, + //menu: false + }; + const dateFields = ['manufacturingDate']; + const singleSearchFields = ['receivedActiveAlerts', 'sentActiveAlerts', 'receivedActiveInvestigations', 'sentActiveInvestigations']; + super(sortableColumns, dateFields, singleSearchFields); + } +} + diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-as-built-supplier-configuration.model.ts b/frontend/src/app/modules/shared/components/parts-table/parts-as-built-supplier-configuration.model.ts new file mode 100644 index 0000000000..082a9089d7 --- /dev/null +++ b/frontend/src/app/modules/shared/components/parts-table/parts-as-built-supplier-configuration.model.ts @@ -0,0 +1,44 @@ +/******************************************************************************** + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +import {TableFilterConfiguration} from "@shared/components/parts-table/parts-config.model"; + +export class PartsAsBuiltSupplierConfigurationModel extends TableFilterConfiguration { + constructor() { + const sortableColumns = { + select: false, + semanticDataModel: true, + nameAtManufacturer: true, + manufacturerName: true, + manufacturerPartId: true, + semanticModelId: true, + manufacturingDate: true, + receivedActiveAlerts: true, + receivedActiveInvestigations: true, + sentActiveAlerts: true, + sentActiveInvestigations: true, + //menu: false + }; + const dateFields = ['manufacturingDate']; + const singleSearchFields = ['receivedActiveAlerts', 'sentActiveAlerts', 'receivedActiveInvestigations', 'sentActiveInvestigations']; + super(sortableColumns, dateFields, singleSearchFields); + } + + +} + diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-as-planned-configuration.model.ts b/frontend/src/app/modules/shared/components/parts-table/parts-as-planned-configuration.model.ts new file mode 100644 index 0000000000..5ed4fd3e05 --- /dev/null +++ b/frontend/src/app/modules/shared/components/parts-table/parts-as-planned-configuration.model.ts @@ -0,0 +1,47 @@ +/******************************************************************************** + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +import {TableFilterConfiguration} from "@shared/components/parts-table/parts-config.model"; + +export class PartsAsPlannedConfigurationModel extends TableFilterConfiguration { + + constructor() { + const sortableColumns = { + select: false, + id: true, + idShort: true, + nameAtManufacturer: true, + manufacturerName: true, + manufacturerPartId: true, + classification: true, + semanticDataModel: true, + semanticModelId: true, + validityPeriodFrom: true, + validityPeriodTo: true, + psFunction: true, + catenaXSiteId: true, + functionValidFrom: true, + functionValidUntil: true, + // menu: false + }; + + const dateFields = ['validityPeriodFrom', 'validityPeriodTo', 'functionValidFrom', 'functionValidUntil']; + super(sortableColumns, dateFields); + } +} + diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-as-planned-customer-configuration.model.ts b/frontend/src/app/modules/shared/components/parts-table/parts-as-planned-customer-configuration.model.ts new file mode 100644 index 0000000000..3529e0465b --- /dev/null +++ b/frontend/src/app/modules/shared/components/parts-table/parts-as-planned-customer-configuration.model.ts @@ -0,0 +1,36 @@ +/******************************************************************************** + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +import {TableFilterConfiguration} from "@shared/components/parts-table/parts-config.model"; + +export class PartsAsPlannedCustomerConfigurationModel extends TableFilterConfiguration { + + constructor() { + const sortableColumns = { + select: false, + semanticDataModel: true, + nameAtManufacturer: true, + manufacturerName: true, + manufacturerPartId: true, + semanticModelId: true, + // menu: false + }; + super(sortableColumns); + } +} + diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-as-planned-supplier-configuration.model.ts b/frontend/src/app/modules/shared/components/parts-table/parts-as-planned-supplier-configuration.model.ts new file mode 100644 index 0000000000..81c65511f4 --- /dev/null +++ b/frontend/src/app/modules/shared/components/parts-table/parts-as-planned-supplier-configuration.model.ts @@ -0,0 +1,36 @@ +/******************************************************************************** + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +import {TableFilterConfiguration} from "@shared/components/parts-table/parts-config.model"; + +export class PartsAsPlannedSupplierConfigurationModel extends TableFilterConfiguration { + + constructor() { + const sortableColumns = { + select: false, + semanticDataModel: true, + nameAtManufacturer: true, + manufacturerName: true, + manufacturerPartId: true, + semanticModelId: true, + //menu: false + }; + super(sortableColumns); + } +} + diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-config.model.ts b/frontend/src/app/modules/shared/components/parts-table/parts-config.model.ts new file mode 100644 index 0000000000..27d8b4ff33 --- /dev/null +++ b/frontend/src/app/modules/shared/components/parts-table/parts-config.model.ts @@ -0,0 +1,54 @@ +/******************************************************************************** + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + + +import {TableViewConfig} from "@shared/components/parts-table/table-view-config.model"; + + +import {PartsTableConfigUtils} from "@shared/components/parts-table/parts-table-config.utils"; + + +export class TableFilterConfiguration implements TableViewConfig { + filterColumns: any; + displayedColumns: any; + displayFilterColumnMappings: any; + filterFormGroup: any; + sortableColumns: any; + + constructor(sortableColumns: any, dateFields?: any, singleSearchFields?: any) { + this.displayedColumns = Object.keys(sortableColumns); + this.filterFormGroup = PartsTableConfigUtils.createFormGroup(this.displayedColumns); + this.filterColumns = PartsTableConfigUtils.createFilterColumns(this.displayedColumns); + this.sortableColumns = sortableColumns; + this.displayFilterColumnMappings = PartsTableConfigUtils.generateFilterColumnsMapping(sortableColumns, dateFields, singleSearchFields); + + } + + public filterConfiguration(): TableViewConfig { + return { + filterColumns: this.filterColumns, + displayedColumns: this.displayedColumns, + displayFilterColumnMappings: this.displayFilterColumnMappings, + filterFormGroup: this.filterFormGroup, + sortableColumns: this.sortableColumns + } + } + +} + diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-table-config.utils.ts b/frontend/src/app/modules/shared/components/parts-table/parts-table-config.utils.ts new file mode 100644 index 0000000000..c74c2cc185 --- /dev/null +++ b/frontend/src/app/modules/shared/components/parts-table/parts-table-config.utils.ts @@ -0,0 +1,52 @@ +import {FormControl} from "@angular/forms"; + +export class PartsTableConfigUtils { + + public static createFormGroup(displayedColumns: any): Record { + const formGroup: Record = {}; + + for (const column of displayedColumns) { + if (column !== 'select' && column !== 'menu') { + formGroup[column] = new FormControl([]); + } + + } + return formGroup; + } + + public static createFilterColumns(displayedColumns: string[]): string[] { + const array = displayedColumns.filter((column: string) => 'select' !== column && 'menu' !== column).map((column: string) => 'filter' + column); + + return ["Filter", ...array]; + + + } + + public static generateFilterColumnsMapping(sortableColumns: any, dateFields?: string[], singleSearchFields?: string[]): any[] { + const filterColumnsMapping: any[] = []; + const firstElement = {filterKey: 'Filter', headerKey: 'Filter'}; + + const excludedFields = ['select', 'menu']; + for (const key in sortableColumns) { + if (sortableColumns.hasOwnProperty(key) && !excludedFields.includes(key)) { + // This key goes to the backend rest api + const filterKey = key; + const headerKey = 'filter' + key; + + let columnMapping: { filterKey: string; headerKey: string; isDate?: boolean; singleSearch?: boolean; }; + if (dateFields?.includes(filterKey)) { + columnMapping = {filterKey, headerKey, isDate: true}; + } else if (singleSearchFields?.includes(filterKey)) { + columnMapping = {filterKey, headerKey, singleSearch: true}; + } else { + columnMapping = {filterKey, headerKey}; + } + + filterColumnsMapping.push(columnMapping); + } + } + + return [firstElement, ...filterColumnsMapping]; + + } +} diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-table.component.html b/frontend/src/app/modules/shared/components/parts-table/parts-table.component.html index 444b55bb46..f52296f091 100644 --- a/frontend/src/app/modules/shared/components/parts-table/parts-table.component.html +++ b/frontend/src/app/modules/shared/components/parts-table/parts-table.component.html @@ -18,28 +18,29 @@ --> -
-
-
{{tableHeader}} - settings -
-
-

{{ selectedPartsInfoLabel | i18n : {count: selection?.selected?.length || 0} }}

- -
- announcement - {{ selectedPartsActionLabel | i18n }} +
+
{{tableHeader}} + + settings +
- +
+

{{ selectedPartsInfoLabel | i18n : {count: selection?.selected?.length || 0} }}

+ +
+ announcement + {{ selectedPartsActionLabel | i18n }} +
+
+
-
@@ -58,32 +59,33 @@ data-testid="table-component--head-row" class="table--header--row"> - + - - - - {{ ''}} - - + + + + {{ ''}} + + {{ 'table.noResultFound' | i18n }} mat-header-cell class="table--cell table--header--normal--cell" > + {{ tableConfig?.header?.[column] | i18n }} + + + notification_important + + + + + + inbox + + + + @@ -195,10 +220,17 @@

{{ 'table.noResultFound' | i18n }}

- - - {{isDateElement(column) ? (element[column] | date:'yyyy-MM-dd') : element[column]?.length }} - + + + {{(element[column] | date:'yyyy-MM-dd')}} + + + + + + {{element[column]?.length}} + + {{ 'table.noResultFound' | i18n }} - + - notification_important + notification_important - + + + notification_important + + + + + inbox + + + - inbox + inbox diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-table.component.spec.ts b/frontend/src/app/modules/shared/components/parts-table/parts-table.component.spec.ts index 9ed6822e5b..ec7bb144c8 100644 --- a/frontend/src/app/modules/shared/components/parts-table/parts-table.component.spec.ts +++ b/frontend/src/app/modules/shared/components/parts-table/parts-table.component.spec.ts @@ -73,22 +73,24 @@ describe('PartsTableComponent', () => { // Expect that the event was emitted with the correct data expect(componentInstance.displayedColumns).toEqual([ 'Filter', - 'filterId', - 'filterIdShort', - 'filterName', // nameAtManufacturer - 'filterManufacturer', - 'filterPartId', // Part number / Batch Number / JIS Number - 'filterManufacturerPartId', - 'filterCustomerPartId', // --> semanticModel.customerPartId - 'filterClassification', + 'filterid', + 'filteridShort', + 'filternameAtManufacturer', // nameAtManufacturer + 'filtermanufacturerName', + 'filterpartId', // Part number / Batch Number / JIS Number + 'filtermanufacturerPartId', + 'filtercustomerPartId', // --> semanticModel.customerPartId + 'filterclassification', //'nameAtManufacturer', --> already in name - 'filterNameAtCustomer', // --> semanticModel.nameAtCustomer - 'filterSemanticModelId', - 'filterSemanticDataModel', - 'filterManufacturingDate', - 'filterManufacturingCountry', - 'filterActiveAlerts', - 'filterActiveInvestigations', + 'filternameAtCustomer', // --> semanticModel.nameAtCustomer + 'filtersemanticModelId', + 'filtersemanticDataModel', + 'filtermanufacturingDate', + 'filtermanufacturingCountry', + 'filterreceivedActiveAlerts', + 'filterreceivedActiveInvestigations', + 'filtersentActiveAlerts', + 'filtersentActiveInvestigations', ]); }); @@ -100,20 +102,20 @@ describe('PartsTableComponent', () => { expect(componentInstance.displayedColumns).toEqual([ 'Filter', - 'filterId', - 'filterIdShort', - 'filterName', - 'filterManufacturer', - 'filterManufacturerPartId', - 'filterClassification', - 'filterSemanticDataModel', - 'filterSemanticModelId', - 'filterValidityPeriodFrom', - 'filterValidityPeriodTo', - 'filterPsFunction', - 'filterCatenaXSiteId', - 'filterFunctionValidFrom', - 'filterFunctionValidUntil', + 'filterid', + 'filteridShort', + 'filternameAtManufacturer', + 'filtermanufacturerName', + 'filtermanufacturerPartId', + 'filterclassification', + 'filtersemanticDataModel', + 'filtersemanticModelId', + 'filtervalidityPeriodFrom', + 'filtervalidityPeriodTo', + 'filterpsFunction', + 'filtercatenaXSiteId', + 'filterfunctionValidFrom', + 'filterfunctionValidUntil', ]); }); diff --git a/frontend/src/app/modules/shared/components/parts-table/parts-table.component.ts b/frontend/src/app/modules/shared/components/parts-table/parts-table.component.ts index 4269889653..0aad0633b6 100644 --- a/frontend/src/app/modules/shared/components/parts-table/parts-table.component.ts +++ b/frontend/src/app/modules/shared/components/parts-table/parts-table.component.ts @@ -17,40 +17,58 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -import { SelectionModel } from '@angular/cdk/collections'; -import { MenuStack } from '@angular/cdk/menu'; +import {SelectionModel} from '@angular/cdk/collections'; +import {MenuStack} from '@angular/cdk/menu'; import { - Component, - ElementRef, - EventEmitter, - Input, - OnInit, - Output, - QueryList, - ViewChild, - ViewChildren, + Component, + ElementRef, + EventEmitter, + Input, + OnInit, + Output, + QueryList, + ViewChild, + ViewChildren, } from '@angular/core'; -import { FormControl, FormGroup } from '@angular/forms'; -import { MatDialog, MatDialogConfig } from '@angular/material/dialog'; -import { MatPaginator, PageEvent } from '@angular/material/paginator'; -import { MatSort, Sort } from '@angular/material/sort'; -import { MatTableDataSource } from '@angular/material/table'; -import { Pagination } from '@core/model/pagination.model'; -import { TableSettingsService } from '@core/user/table-settings.service'; -import { MainAspectType } from '@page/parts/model/mainAspectType.enum'; -import { SemanticDataModel } from '@page/parts/model/parts.model'; -import { MultiSelectAutocompleteComponent } from '@shared/components/multi-select-autocomplete/multi-select-autocomplete.component'; -import { TableViewConfig } from '@shared/components/parts-table/table-view-config.model'; -import { TableSettingsComponent } from '@shared/components/table-settings/table-settings.component'; +import {FormGroup} from '@angular/forms'; +import {MatDialog, MatDialogConfig} from '@angular/material/dialog'; +import {MatPaginator, PageEvent} from '@angular/material/paginator'; +import {MatSort, Sort} from '@angular/material/sort'; +import {MatTableDataSource} from '@angular/material/table'; +import {Pagination} from '@core/model/pagination.model'; +import {TableSettingsService} from '@core/user/table-settings.service'; +import {MainAspectType} from '@page/parts/model/mainAspectType.enum'; import { - CreateHeaderFromColumns, - PartTableType, - TableConfig, - TableEventConfig, - TableHeaderSort, + MultiSelectAutocompleteComponent +} from '@shared/components/multi-select-autocomplete/multi-select-autocomplete.component'; +import {TableViewConfig} from '@shared/components/parts-table/table-view-config.model'; +import {TableSettingsComponent} from '@shared/components/table-settings/table-settings.component'; +import { + CreateHeaderFromColumns, + PartTableType, + TableConfig, + TableEventConfig, + TableHeaderSort, } from '@shared/components/table/table.model'; -import { isDateFilter } from '@shared/helper/filter-helper'; -import { addSelectedValues, removeSelectedValues } from '@shared/helper/table-helper'; +import {isDateFilter} from '@shared/helper/filter-helper'; +import {addSelectedValues, removeSelectedValues} from '@shared/helper/table-helper'; +import {PartsAsBuiltConfigurationModel} from "@shared/components/parts-table/parts-as-built-configuration.model"; +import { + PartsAsBuiltSupplierConfigurationModel +} from "@shared/components/parts-table/parts-as-built-supplier-configuration.model"; +import { + PartsAsBuiltCustomerConfigurationModel +} from "@shared/components/parts-table/parts-as-built-customer-configuration.model"; +import {PartsAsPlannedConfigurationModel} from "@shared/components/parts-table/parts-as-planned-configuration.model"; +import { + PartsAsPlannedSupplierConfigurationModel +} from "@shared/components/parts-table/parts-as-planned-supplier-configuration.model"; +import { + PartsAsPlannedCustomerConfigurationModel +} from "@shared/components/parts-table/parts-as-planned-customer-configuration.model"; +import {Router} from "@angular/router"; +import {ALERT_BASE_ROUTE, INVESTIGATION_BASE_ROUTE} from "@core/known-route"; +import {ToastService} from "@shared/components/toasts/toast.service"; @Component({ @@ -121,7 +139,12 @@ export class PartsTableComponent implements OnInit { @Output() clickSelectAction = new EventEmitter(); @Output() filterActivated = new EventEmitter(); - constructor(private readonly tableSettingsService: TableSettingsService, private dialog: MatDialog) {} + constructor( + private readonly tableSettingsService: TableSettingsService, + private dialog: MatDialog, + private router: Router, + private toastService: ToastService) { + } public readonly dataSource = new MatTableDataSource(); @@ -134,569 +157,162 @@ export class PartsTableComponent implements OnInit { public isMenuOpen: boolean; public displayedFilter: boolean; + // TODO remove it and set only in tableViewConfig public filterConfiguration: any[]; + // TODO remove it and set only in tableViewConfig public displayedColumns: string[]; + // TODO remove it and set only in tableViewConfig public defaultColumns: string[]; + // TODO remove it and set only in tableViewConfig + filterFormGroup = new FormGroup({}); - private tableViewConfig: TableViewConfig; + public tableViewConfig: TableViewConfig; + + + public deeplinkToNotification(column: any, notificationId: string[]) { + let route; + let received; + let tabIndex; + switch (column) { + case "receivedActiveAlerts": { + received = true; + route = ALERT_BASE_ROUTE; + tabIndex = 0; + break; + } + case "sentActiveAlerts": { + received = false; + route = ALERT_BASE_ROUTE; + tabIndex = 1; + break; + } + case "receivedActiveInvestigations": { + received = true; + route = INVESTIGATION_BASE_ROUTE; + tabIndex = 0; + break; + } + case "sentActiveInvestigations": { + received = false; + route = INVESTIGATION_BASE_ROUTE; + tabIndex = 1; + break; + } + } + this.router.navigate([route], {queryParams: {tabIndex: tabIndex, deeplink: true, received: received, notificationIds: notificationId}}) + } - filterFormGroup = new FormGroup({}); + public isNotificationCountColumn(column: any) { + return column === 'receivedActiveAlerts' || column === 'sentActiveAlerts' || column === 'receivedActiveInvestigations' || column === 'sentActiveInvestigations'; + } - public isDateElement(key: string){ + public isDateElement(key: string) { return isDateFilter(key); } - private readonly displayedColumnsAsBuilt: string[] = [ - 'Filter', - 'filterId', - 'filterIdShort', - 'filterName', // nameAtManufacturer - 'filterManufacturer', - 'filterPartId', // Part number / Batch Number / JIS Number - 'filterManufacturerPartId', - 'filterCustomerPartId', // --> semanticModel.customerPartId - 'filterClassification', - 'filterNameAtCustomer', // --> semanticModel.nameAtCustomer - 'filterSemanticModelId', - 'filterSemanticDataModel', - 'filterManufacturingDate', - 'filterManufacturingCountry', - 'filterActiveAlerts', - 'filterActiveInvestigations', - ]; - - private readonly displayedColumnsAsPlanned: string[] = [ - 'Filter', - 'filterId', - 'filterIdShort', - 'filterName', - 'filterManufacturer', - 'filterManufacturerPartId', - 'filterClassification', - 'filterSemanticDataModel', - 'filterSemanticModelId', - 'filterValidityPeriodFrom', - 'filterValidityPeriodTo', - 'filterPsFunction', - 'filterCatenaXSiteId', - 'filterFunctionValidFrom', - 'filterFunctionValidUntil', - ]; - - private readonly displayedColumnsAsBuiltForTable: string[] = [ - 'select', - 'id', - 'idShort', - 'name', - 'manufacturer', - 'partId', - 'manufacturerPartId', - 'customerPartId', - 'classification', - 'nameAtCustomer', - 'semanticModelId', - 'semanticDataModel', - 'manufacturingDate', - 'manufacturingCountry', - 'activeAlerts', - 'activeInvestigations', - ]; - - - private readonly displayedColumnsAsPlannedForTable: string[] = [ - 'select', - 'id', - 'idShort', - 'name', - 'manufacturer', - 'manufacturerPartId', - 'classification', - 'semanticDataModel', - 'semanticModelId', - 'validityPeriodFrom', - 'validityPeriodTo', - 'psFunction', - 'catenaXSiteId', - 'functionValidFrom', - 'functionValidUntil', - 'menu' - ]; - - private readonly sortableColumnsAsBuilt: Record = { - id: true, - idShort: true, - name: true, - manufacturer: true, - partId: true, - manufacturerPartId: true, - customerPartId: true, - classification: true, - nameAtCustomer: true, - semanticModelId: true, - semanticDataModel: true, - manufacturingDate: true, - manufacturingCountry: true, - activeAlerts: true, - activeInvestigations: true, - - }; - - private readonly sortableColumnsAsPlanned: Record = { - id: true, - idShort: true, - name: true, - manufacturer: true, - manufacturerPartId: true, - classification: true, - semanticDataModel: true, - semanticModelId: true, - validityPeriodFrom: true, - validityPeriodTo: true, - psFunction: true, - catenaXSiteId: true, - functionValidFrom: true, - functionValidUntil: true, - }; - - private readonly displayedColumnsAsPlannedCustomer: string[] = [ - 'filterSemanticDataModel', - 'filterName', - 'filterManufacturer', - 'filterManufacturerPartId', - 'filterSemanticModelId', - ]; - - - private readonly displayedColumnsAsPlannedSupplier: string[] = [ - 'Filter', - 'filterSemanticDataModel', - 'filterName', - 'filterManufacturer', - 'filterManufacturerPartId', - 'filterSemanticModelId', - ]; - - - private readonly displayedColumnsAsBuiltCustomer: string[] = [ - 'filterSemanticDataModel', - 'filterName', - 'filterManufacturer', - 'filterPartId', - 'filterSemanticModelId', - 'filterManufacturingDate', - 'filterActiveAlerts', - 'filterActiveInvestigations', - ]; - - - private readonly displayedColumnsAsBuiltSupplier: string[] = [ - 'Filter', - 'filterSemanticDataModel', - 'filterName', - 'filterManufacturer', - 'filterPartId', - 'filterSemanticModelId', - 'filterManufacturingDate', - 'filterActiveAlerts', - 'filterActiveInvestigations', - ]; - - private readonly displayedColumnsAsBuiltCustomerForTable: string[] = [ - 'semanticDataModel', - 'name', - 'manufacturer', - 'partId', - 'semanticModelId', - 'manufacturingDate', - 'activeAlerts', - 'activeInvestigations', - ]; - - - private readonly sortableColumnsAsBuiltCustomer: Record = { - semanticDataModel: true, - name: true, - manufacturer: true, - partId: true, - semanticModelId: true, - manufacturingDate: true, - activeAlerts: true, - activeInvestigations: true, - }; - - private readonly displayedColumnsAsPlannedCustomerForTable: string[] = [ - 'semanticDataModel', - 'name', - 'manufacturer', - 'manufacturerPartId', - 'semanticModelId', - ]; - - private readonly sortableColumnsAsPlannedCustomer: Record = { - semanticDataModel: true, - name: true, - manufacturer: true, - manufacturerPartId: true, - semanticModelId: true, - manufacturingDate: true, - }; - - private readonly displayedColumnsAsBuiltSupplierForTable: string[] = [ - 'select', - 'semanticDataModel', - 'name', - 'manufacturer', - 'partId', - 'semanticModelId', - 'manufacturingDate', - 'activeAlerts', - 'activeInvestigations', - 'menu' - ]; - - private readonly sortableColumnsAsBuiltSupplier: Record = { - semanticDataModel: true, - name: true, - manufacturer: true, - partId: true, - semanticModelId: true, - manufacturingDate: true, - activeAlerts: true, - activeInvestigations: true, - }; - - private readonly displayedColumnsAsPlannedSupplierForTable: string[] = [ - 'select', - 'semanticDataModel', - 'name', - 'manufacturer', - 'manufacturerPartId', - 'semanticModelId', - 'menu' - ]; - - private readonly sortableColumnsAsPlannedSupplier: Record = { - semanticDataModel: true, - name: true, - manufacturer: true, - manufacturerPartId: true, - semanticModelId: true, - }; + private initializeTableViewSettings(): void { + + switch (this.tableType) { + case PartTableType.AS_PLANNED_CUSTOMER: + this.tableViewConfig = new PartsAsPlannedCustomerConfigurationModel().filterConfiguration(); + break; + case PartTableType.AS_PLANNED_OWN: + this.tableViewConfig = new PartsAsPlannedConfigurationModel().filterConfiguration(); + break; + case PartTableType.AS_PLANNED_SUPPLIER: + this.tableViewConfig = new PartsAsPlannedSupplierConfigurationModel().filterConfiguration(); + break; + case PartTableType.AS_BUILT_OWN: + this.tableViewConfig = new PartsAsBuiltConfigurationModel().filterConfiguration(); + break; + case PartTableType.AS_BUILT_CUSTOMER: + this.tableViewConfig = new PartsAsBuiltCustomerConfigurationModel().filterConfiguration(); + break; + case PartTableType.AS_BUILT_SUPPLIER: + this.tableViewConfig = new PartsAsBuiltSupplierConfigurationModel().filterConfiguration(); + break; + } + } private pageSize: number; private sorting: TableHeaderSort; ngOnInit() { - this.initializeTableViewSettings(); - this.tableSettingsService.getEvent().subscribe(() => { + this.initializeTableViewSettings(); + this.tableSettingsService.getEvent().subscribe(() => { + this.setupTableViewSettings(); + }) this.setupTableViewSettings(); - }) - this.setupTableViewSettings(); this.filterFormGroup.valueChanges.subscribe((formValues) => { this.filterActivated.emit(formValues); }); } - private initializeTableViewSettings(): void { - switch (this.tableType) { - case PartTableType.AS_PLANNED_CUSTOMER: - this.tableViewConfig = { - displayedColumns: this.displayedColumnsAsPlannedCustomer, - displayedColumnsForTable: this.displayedColumnsAsPlannedCustomerForTable, - filterConfiguration: this.assetAsPlannedCustomerFilterConfiguration, - filterFormGroup: this.assetAsPlannedCustomerFilterFormGroup, - sortableColumns: this.sortableColumnsAsPlannedCustomer - } - break; - case PartTableType.AS_PLANNED_OWN: - this.tableViewConfig = { - displayedColumns: this.displayedColumnsAsPlanned, - displayedColumnsForTable: this.displayedColumnsAsPlannedForTable, - filterConfiguration: this.assetAsPlannedFilterConfiguration, - filterFormGroup: this.assetAsPlannedFilterFormGroup, - sortableColumns: this.sortableColumnsAsPlanned - } - break; - case PartTableType.AS_PLANNED_SUPPLIER: - this.tableViewConfig = { - displayedColumns: this.displayedColumnsAsPlannedSupplier, - displayedColumnsForTable: this.displayedColumnsAsPlannedSupplierForTable, - filterConfiguration: this.assetAsPlannedSupplierFilterConfiguration, - filterFormGroup: this.assetAsPlannedSupplierFilterFormGroup, - sortableColumns: this.sortableColumnsAsPlannedSupplier - } - break; - case PartTableType.AS_BUILT_OWN: - this.tableViewConfig = { - displayedColumns: this.displayedColumnsAsBuilt, - displayedColumnsForTable: this.displayedColumnsAsBuiltForTable, - filterConfiguration: this.assetAsBuiltFilterConfiguration, - filterFormGroup: this.assetAsBuiltFilterFormGroup, - sortableColumns: this.sortableColumnsAsBuilt - } - break; - case PartTableType.AS_BUILT_CUSTOMER: - this.tableViewConfig = { - displayedColumns: this.displayedColumnsAsBuiltCustomer, - displayedColumnsForTable: this.displayedColumnsAsBuiltCustomerForTable, - filterConfiguration: this.assetAsBuiltCustomerFilterConfiguration, - filterFormGroup: this.assetAsBuiltCustomerFilterFormGroup, - sortableColumns: this.sortableColumnsAsBuiltCustomer - } - break; - case PartTableType.AS_BUILT_SUPPLIER: - this.tableViewConfig = { - displayedColumns: this.displayedColumnsAsBuiltSupplier, - displayedColumnsForTable: this.displayedColumnsAsBuiltSupplierForTable, - filterConfiguration: this.assetAsBuiltSupplierFilterConfiguration, - filterFormGroup: this.assetAsBuiltSupplierFilterFormGroup, - sortableColumns: this.sortableColumnsAsBuiltSupplier - } - break; - } - } private setupTableViewSettings() { - const tableSettingsList = this.tableSettingsService.getStoredTableSettings(); - // check if there are table settings list - if(tableSettingsList) { - // if yes, check if there is a table-setting for this table type - if(tableSettingsList[this.tableType]) { - // if yes, get the effective displayedcolumns from the settings and set the tableconfig after it. - this.setupTableConfigurations(tableSettingsList[this.tableType].columnsForTable, tableSettingsList[this.tableType].filterColumnsForTable, this.tableViewConfig.sortableColumns, this.tableViewConfig.filterConfiguration, this.tableViewConfig.filterFormGroup); - } else { - // if no, create new a table setting for this.tabletype and put it into the list. Additionally, intitialize default table configuration - tableSettingsList[this.tableType] = { - columnsForDialog: this.tableViewConfig.displayedColumnsForTable, - columnSettingsOptions: this.getDefaultColumnVisibilityMap(), - columnsForTable: this.tableViewConfig.displayedColumnsForTable, - filterColumnsForTable: this.tableViewConfig.displayedColumns - }; - this.tableSettingsService.storeTableSettings(this.tableType, tableSettingsList); - this.setupTableConfigurations(this.tableViewConfig.displayedColumnsForTable, this.tableViewConfig.displayedColumns, this.tableViewConfig.sortableColumns, this.tableViewConfig.filterConfiguration, this.tableViewConfig.filterFormGroup); + + if (this.tableSettingsService.storedTableSettingsInvalid(this.tableViewConfig, this.tableType)) { + this.toastService.warning("table.tableSettings.invalid", 10000); } - } else { - // if no, create new list and a settings entry for this.tabletype with default values and set correspondingly the tableconfig - const newTableSettingsList = { - [this.tableType]: { - columnsForDialog: this.tableViewConfig.displayedColumnsForTable, - columnSettingsOptions: this.getDefaultColumnVisibilityMap(), - columnsForTable: this.tableViewConfig.displayedColumnsForTable, - filterColumnsForTable: this.tableViewConfig.displayedColumns - } + const tableSettingsList = this.tableSettingsService.getStoredTableSettings(); + // check if there are table settings list + if (tableSettingsList) { + // if yes, check if there is a table-setting for this table type + if (tableSettingsList[this.tableType]) { + // if yes, get the effective displayedcolumns from the settings and set the tableconfig after it. + this.setupTableConfigurations(tableSettingsList[this.tableType].columnsForTable, tableSettingsList[this.tableType].filterColumnsForTable, this.tableViewConfig.sortableColumns, this.tableViewConfig.displayFilterColumnMappings, this.tableViewConfig.filterFormGroup); + } else { + // if no, create new a table setting for this.tabletype and put it into the list. Additionally, intitialize default table configuration + tableSettingsList[this.tableType] = { + columnsForDialog: this.tableViewConfig.displayedColumns, + columnSettingsOptions: this.getDefaultColumnVisibilityMap(), + columnsForTable: this.tableViewConfig.displayedColumns, + filterColumnsForTable: this.tableViewConfig.filterColumns + }; + this.tableSettingsService.storeTableSettings(tableSettingsList); + this.setupTableConfigurations(this.tableViewConfig.displayedColumns, this.tableViewConfig.filterColumns, this.tableViewConfig.sortableColumns, this.tableViewConfig.displayFilterColumnMappings, this.tableViewConfig.filterFormGroup); + } + } else { + // if no, create new list and a settings entry for this.tabletype with default values and set correspondingly the tableconfig + const newTableSettingsList = { + [this.tableType]: { + columnsForDialog: this.tableViewConfig.displayedColumns, + columnSettingsOptions: this.getDefaultColumnVisibilityMap(), + columnsForTable: this.tableViewConfig.displayedColumns, + filterColumnsForTable: this.tableViewConfig.filterColumns + } + } + this.tableSettingsService.storeTableSettings(newTableSettingsList); + this.setupTableConfigurations(this.tableViewConfig.displayedColumns, this.tableViewConfig.filterColumns, this.tableViewConfig.sortableColumns, this.tableViewConfig.displayFilterColumnMappings, this.tableViewConfig.filterFormGroup); } - this.tableSettingsService.storeTableSettings(this.tableType, newTableSettingsList); - this.setupTableConfigurations(this.tableViewConfig.displayedColumnsForTable, this.tableViewConfig.displayedColumns, this.tableViewConfig.sortableColumns, this.tableViewConfig.filterConfiguration, this.tableViewConfig.filterFormGroup); - } } - private getDefaultColumnVisibilityMap(): Map { - const initialColumnMap = new Map(); - for(const column of this.tableViewConfig.displayedColumnsForTable) { - initialColumnMap.set(column,true); - } - return initialColumnMap; + private getDefaultColumnVisibilityMap(): Map { + const initialColumnMap = new Map(); + for (const column of this.tableViewConfig.displayedColumns) { + initialColumnMap.set(column, true); + } + return initialColumnMap; } - private setupTableConfigurations(displayedColumnsForTable: string[], displayedColumns: string[], sortableColumns: Record, filterConfiguration: any[], filterFormGroup: any): any { - const headerKey = 'table.column'; - this.tableConfig = { - displayedColumns: displayedColumnsForTable, - header: CreateHeaderFromColumns(displayedColumnsForTable, headerKey), - sortableColumns: sortableColumns, - }; - this.filterConfiguration = filterConfiguration; - this.displayedColumns = displayedColumns; - for (const controlName in filterFormGroup) { - if (filterFormGroup.hasOwnProperty(controlName)) { - this.filterFormGroup.addControl(controlName, filterFormGroup[controlName]); - } - } - - } - - - semanticDataModelOptions = [ - { - display: 'Batch', - value: SemanticDataModel.BATCH, - }, { - display: 'JustInSequence', - value: SemanticDataModel.JUSTINSEQUENCE, - }, { - display: 'SerialPart', - value: SemanticDataModel.SERIALPART, - }, { - display: 'Unknown', - value: SemanticDataModel.UNKNOWN, - }, { - display: 'PartAsPlanned', - value: SemanticDataModel.PARTASPLANNED, - }, - ]; - - // TODO: create a type for the filterconfig - public readonly assetAsBuiltFilterConfiguration: any[] = [ - {filterKey: 'Filter', headerKey: 'Filter'}, - {filterKey: 'id', headerKey: 'filterId'}, - {filterKey: 'idShort', headerKey: 'filterIdShort'}, - {filterKey: 'nameAtManufacturer', headerKey: 'filterName'}, // nameAtManufacturer - {filterKey: 'manufacturerName', headerKey: 'filterManufacturer'}, - {filterKey: 'manufacturerPartId', headerKey: 'filterPartId'}, // Part number / Batch Number / JIS Number - {filterKey: 'manufacturerPartId', headerKey: 'filterManufacturerPartId'}, - {filterKey: 'customerPartId', headerKey: 'filterCustomerPartId'}, // --> semanticModel.customerPartId - {filterKey: 'classification', headerKey: 'filterClassification'}, - {filterKey: 'nameAtCustomer', headerKey: 'filterNameAtCustomer'}, // --> semanticModel.nameAtCustomer - {filterKey: 'semanticModelId', headerKey: 'filterSemanticModelId'}, - {filterKey: 'semanticDataModel', headerKey: 'filterSemanticDataModel'}, - {filterKey: 'manufacturingDate', headerKey: 'filterManufacturingDate', isDate: true}, - {filterKey: 'manufacturingCountry', headerKey: 'filterManufacturingCountry'}, - {filterKey: 'activeAlerts', headerKey: 'filterActiveAlerts', singleSearch: true}, - {filterKey: 'activeInvestigations', headerKey: 'filterActiveInvestigations', singleSearch: true}, - ]; - - - assetAsBuiltFilterFormGroup = { - id: new FormControl([]), - idShort: new FormControl([]), - nameAtManufacturer: new FormControl([]), - manufacturerName: new FormControl([]), - partId: new FormControl([]), - manufacturerPartId: new FormControl([]), - customerPartId: new FormControl([]), - classification: new FormControl([]), - nameAtCustomer: new FormControl([]), - semanticModelId: new FormControl([]), - semanticDataModel: new FormControl([]), - manufacturingDate: new FormControl([]), - manufacturingCountry: new FormControl([]), - activeAlerts: new FormControl([]), - activeInvestigations: new FormControl([]), - }; - - assetAsPlannedFilterFormGroup = { - id: new FormControl([]), - idShort: new FormControl([]), - nameAtManufacturer: new FormControl([]), - manufacturerName: new FormControl([]), - manufacturerPartId: new FormControl([]), - classification: new FormControl([]), - semanticDataModel: new FormControl([]), - semanticModelId: new FormControl([]), - validityPeriodFrom: new FormControl([]), - validityPeriodTo: new FormControl([]), - function: new FormControl([]), - catenaxSiteId: new FormControl([]), - functionValidFrom: new FormControl([]), - functionValidUntil: new FormControl([]) - }; - - - assetAsPlannedSupplierFilterFormGroup = { - select: new FormControl([]), - semanticDataModel: new FormControl([]), - nameAtManufacturer: new FormControl([]), - manufacturerName: new FormControl([]), - manufacturerPartId: new FormControl([]), - semanticModelId: new FormControl([]), - menu: new FormControl([]) - }; - - assetAsPlannedCustomerFilterFormGroup = { - semanticDataModel: new FormControl([]), - nameAtManufacturer: new FormControl([]), - manufacturerName: new FormControl([]), - semanticModelId: new FormControl([]), - manufacturerPartId: new FormControl([]) - }; - - - assetAsBuiltSupplierFilterFormGroup = { - select: new FormControl([]), - semanticDataModel: new FormControl([]), - nameAtManufacturer: new FormControl([]), - manufacturerName: new FormControl([]), - manufacturerPartId: new FormControl([]), - semanticModelId: new FormControl([]), - manufacturingDate: new FormControl([]), - activeAlerts: new FormControl([]), - activeInvestigations: new FormControl([]), - menu: new FormControl([]) - }; - - assetAsBuiltCustomerFilterFormGroup = { - semanticDataModel: new FormControl([]), - nameAtManufacturer: new FormControl([]), - manufacturerName: new FormControl([]), - manufacturerPartId: new FormControl([]), - semanticModelId: new FormControl([]), - manufacturingDate: new FormControl([]), - activeAlerts: new FormControl([]), - activeInvestigations: new FormControl([]), - }; - - private readonly assetAsPlannedCustomerFilterConfiguration: any[] = [ - {filterKey: 'semanticDataModel', headerKey: 'filterSemanticDataModel'}, - {filterKey: 'nameAtManufacturer', headerKey: 'filterName'}, - {filterKey: 'manufacturerName', headerKey: 'filterManufacturer'}, - {filterKey: 'manufacturerPartId', headerKey: 'filterManufacturerPartId'}, - {filterKey: 'semanticModelId', headerKey: 'filterSemanticModelId'} - ]; - - private readonly assetAsPlannedSupplierFilterConfiguration: any[] = [ - {filterKey: 'Filter', headerKey: 'Filter'}, - {filterKey: 'semanticDataModel', headerKey: 'filterSemanticDataModel'}, - {filterKey: 'nameAtManufacturer', headerKey: 'filterName'}, - {filterKey: 'manufacturerName', headerKey: 'filterManufacturer'}, - {filterKey: 'manufacturerPartId', headerKey: 'filterManufacturerPartId'}, - {filterKey: 'semanticModelId', headerKey: 'filterSemanticModelId'} - ]; - - - private readonly assetAsBuiltCustomerFilterConfiguration: any[] = [ - {filterKey: 'semanticDataModel', headerKey: 'filterSemanticDataModel'}, - {filterKey: 'nameAtManufacturer', headerKey: 'filterName'}, - {filterKey: 'manufacturerName', headerKey: 'filterManufacturer'}, - {filterKey: 'manufacturerPartId', headerKey: 'filterPartId'}, - {filterKey: 'semanticModelId', headerKey: 'filterSemanticModelId'}, - {filterKey: 'manufacturingDate', headerKey: 'filterManufacturingDate', isDate: true}, - {filterKey: 'activeAlerts', headerKey: 'filterActiveAlerts', singleSearch: true}, - {filterKey: 'activeInvestigations', headerKey: 'filterActiveInvestigations', singleSearch: true}, - ]; - - - private readonly assetAsBuiltSupplierFilterConfiguration: any[] = [ - {filterKey: 'Filter', headerKey: 'Filter'}, - {filterKey: 'semanticDataModel', headerKey: 'filterSemanticDataModel'}, - {filterKey: 'nameAtManufacturer', headerKey: 'filterName'}, - {filterKey: 'manufacturerName', headerKey: 'filterManufacturer'}, - {filterKey: 'manufacturerPartId', headerKey: 'filterPartId'}, - {filterKey: 'semanticModelId', headerKey: 'filterSemanticModelId'}, - {filterKey: 'manufacturingDate', headerKey: 'filterManufacturingDate', isDate: true}, - {filterKey: 'activeAlerts', headerKey: 'filterActiveAlerts', singleSearch: true}, - {filterKey: 'activeInvestigations', headerKey: 'filterActiveInvestigations', singleSearch: true}, - ]; - - - private readonly assetAsPlannedFilterConfiguration: any[] = [ - {filterKey: 'Filter', headerKey: 'Filter'}, - {filterKey: 'id', headerKey: 'filterId'}, - {filterKey: 'idShort', headerKey: 'filterIdShort'}, - {filterKey: 'nameAtManufacturer', headerKey: 'filterName'}, // nameAtManufacturer - {filterKey: 'manufacturerName', headerKey: 'filterManufacturer'}, - {filterKey: 'manufacturerPartId', headerKey: 'filterManufacturerPartId'}, // Part number / Batch Number / JIS Number - {filterKey: 'classification', headerKey: 'filterClassification'}, - {filterKey: 'semanticDataModel', headerKey: 'filterSemanticDataModel'}, - {filterKey: 'semanticModelId', headerKey: 'filterSemanticModelId'}, - {filterKey: 'validityPeriodFrom', headerKey: 'filterValidityPeriodFrom', isDate: true}, - {filterKey: 'validityPeriodTo', headerKey: 'filterValidityPeriodTo', isDate: true}, - {filterKey: 'function', headerKey: 'filterPsFunction'}, - {filterKey: 'catenaxSiteId', headerKey: 'filterCatenaXSiteId'}, - {filterKey: 'functionValidFrom', headerKey: 'filterFunctionValidFrom', isDate: true}, - {filterKey: 'functionValidUntil', headerKey: 'filterFunctionValidUntil', isDate: true} - ]; + private setupTableConfigurations(displayedColumnsForTable: string[], displayedColumns: string[], sortableColumns: Record, filterConfiguration: any[], filterFormGroup: any): any { + const headerKey = 'table.column'; + this.tableConfig = { + displayedColumns: displayedColumnsForTable, + header: CreateHeaderFromColumns(displayedColumnsForTable, headerKey), + sortableColumns: sortableColumns, + }; + + console.log(this.tableConfig, "tableconfig"); + this.displayedColumns = displayedColumns; + for (const controlName in filterFormGroup) { + if (filterFormGroup.hasOwnProperty(controlName)) { + this.filterFormGroup.addControl(controlName, filterFormGroup[controlName]); + } + } + } public areAllRowsSelected(): boolean { return this.dataSource.data.every(data => this.isSelected(data)); @@ -765,18 +381,19 @@ export class PartsTableComponent implements OnInit { } openDialog(): void { - const config = new MatDialogConfig(); - config.data = { - title: "table.tableSettings.title", - panelClass: "custom", - tableType: this.tableType, - defaultColumns: this.tableViewConfig.displayedColumnsForTable, - defaultFilterColumns: this.tableViewConfig.displayedColumns - }; - this.dialog.open(TableSettingsComponent, config ) + const config = new MatDialogConfig(); + config.data = { + title: "table.tableSettings.title", + panelClass: "custom", + tableType: this.tableType, + defaultColumns: this.tableViewConfig.displayedColumns, + defaultFilterColumns: this.tableViewConfig.filterColumns + }; + this.dialog.open(TableSettingsComponent, config) } - protected readonly MenuStack = MenuStack; - protected readonly MainAspectType = MainAspectType; + protected readonly MenuStack = MenuStack; + protected readonly MainAspectType = MainAspectType; + protected readonly PartTableType = PartTableType; } diff --git a/frontend/src/app/modules/shared/components/parts-table/table-view-config.model.ts b/frontend/src/app/modules/shared/components/parts-table/table-view-config.model.ts index d2b0600e15..b3acca0e34 100644 --- a/frontend/src/app/modules/shared/components/parts-table/table-view-config.model.ts +++ b/frontend/src/app/modules/shared/components/parts-table/table-view-config.model.ts @@ -17,9 +17,9 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ export interface TableViewConfig { - displayedColumnsForTable: string[], displayedColumns: string[], + filterColumns: string[], sortableColumns: Record, - filterConfiguration: any[], + displayFilterColumnMappings: any[], filterFormGroup: any } diff --git a/frontend/src/app/modules/shared/components/request-notification/request-notification.base.html b/frontend/src/app/modules/shared/components/request-notification/request-notification.base.html index 0f834850ed..31fb4503d4 100644 --- a/frontend/src/app/modules/shared/components/request-notification/request-notification.base.html +++ b/frontend/src/app/modules/shared/components/request-notification/request-notification.base.html @@ -26,12 +26,12 @@

{{ this.context + '.headline' close - - {{ part.name || part.id }} + + {{ part.nameAtManufacturer || part.id }} @@ -42,13 +42,13 @@

{{ this.context + '.headline'

{{ 'requestNotification.restoreItem' | i18n }}

restore - {{ removedItemsHistory[0].name || removedItemsHistory[0].id }} + {{ removedItemsHistory[0].nameAtManufacturer || removedItemsHistory[0].id }}

diff --git a/frontend/src/app/modules/shared/components/request-notification/request-notification.base.spec.ts b/frontend/src/app/modules/shared/components/request-notification/request-notification.base.spec.ts index b7f2780d8d..8959e9546f 100644 --- a/frontend/src/app/modules/shared/components/request-notification/request-notification.base.spec.ts +++ b/frontend/src/app/modules/shared/components/request-notification/request-notification.base.spec.ts @@ -33,7 +33,7 @@ describe('requestInvestigationComponent', () => { let deselectPartMock: jasmine.Spy; let clearSelectedMock: jasmine.Spy; let submittedMock: jasmine.Spy; - const currentSelectedItems = [{ name: 'part_1' }, { name: 'part_2' }, { name: 'part_3' }]; + const currentSelectedItems = [{ nameAtManufacturer: 'part_1' }, { nameAtManufacturer: 'part_2' }, { nameAtManufacturer: 'part_3' }]; const renderRequestInvestigationComponent = async () => { return renderComponent( diff --git a/frontend/src/app/modules/shared/components/table-settings/table-settings.component.html b/frontend/src/app/modules/shared/components/table-settings/table-settings.component.html index dc2097d368..a0d7c53d86 100644 --- a/frontend/src/app/modules/shared/components/table-settings/table-settings.component.html +++ b/frontend/src/app/modules/shared/components/table-settings/table-settings.component.html @@ -63,6 +63,26 @@ class="dialog--columns--columns--list" > {{'table.column.' + item | i18n}} + + + notification_important + + + + + inbox + + + +
diff --git a/frontend/src/app/modules/shared/components/table-settings/table-settings.component.scss b/frontend/src/app/modules/shared/components/table-settings/table-settings.component.scss index fdd42215f2..15bcdd3e68 100644 --- a/frontend/src/app/modules/shared/components/table-settings/table-settings.component.scss +++ b/frontend/src/app/modules/shared/components/table-settings/table-settings.component.scss @@ -44,6 +44,7 @@ padding-bottom: 24px; } + .mat-icon { width: 32px; height: 32px; diff --git a/frontend/src/app/modules/shared/components/table-settings/table-settings.component.spec.ts b/frontend/src/app/modules/shared/components/table-settings/table-settings.component.spec.ts index 7a3f065136..707091423d 100644 --- a/frontend/src/app/modules/shared/components/table-settings/table-settings.component.spec.ts +++ b/frontend/src/app/modules/shared/components/table-settings/table-settings.component.spec.ts @@ -43,7 +43,7 @@ describe('TableSettingsComponent', () => { columnSettingsOptions: new Map(), columnsForDialog: ['column1', 'column2'], columnsForTable: ['column1'], - filterColumnsForTable: ['filterColumn1'], + filterColumnsForTable: ['filtercolumn1'], }, }; }); @@ -72,7 +72,7 @@ describe('TableSettingsComponent', () => { panelClass: 'test-dialog', tableType: PartTableType.AS_BUILT_OWN, defaultColumns: ['column1', 'column2'], - defaultFilterColumns: ['filterColumn1', 'filterColumn2'], + defaultFilterColumns: ['filtercolumn1', 'filtercolumn2'], }, }, { @@ -111,7 +111,7 @@ describe('TableSettingsComponent', () => { expect(component.panelClass).toEqual('test-dialog'); expect(component.tableType).toEqual(PartTableType.AS_BUILT_OWN); expect(component.defaultColumns).toEqual(['column1', 'column2']); - expect(component.defaultFilterColumns).toEqual(['filterColumn1', 'filterColumn2']); + expect(component.defaultFilterColumns).toEqual(['filtercolumn1', 'filtercolumn2']); expect(component.isCustomerTable).toEqual(false); }); @@ -123,12 +123,12 @@ describe('TableSettingsComponent', () => { component.save(); // Check that setColumnVisibilitySettings was called with the updated settings - expect(tableSettingsService.storeTableSettings).toHaveBeenCalledWith(PartTableType.AS_BUILT_OWN, { + expect(tableSettingsService.storeTableSettings).toHaveBeenCalledWith({ [PartTableType.AS_BUILT_OWN]: { columnSettingsOptions: columnOptions, columnsForDialog: ['column1', 'column2'], columnsForTable: ['column1'], - filterColumnsForTable: ['filterColumn1'], + filterColumnsForTable: ['filtercolumn1'], }, }); }); diff --git a/frontend/src/app/modules/shared/components/table-settings/table-settings.component.ts b/frontend/src/app/modules/shared/components/table-settings/table-settings.component.ts index 7c27ad6232..2870512f33 100644 --- a/frontend/src/app/modules/shared/components/table-settings/table-settings.component.ts +++ b/frontend/src/app/modules/shared/components/table-settings/table-settings.component.ts @@ -56,14 +56,14 @@ export class TableSettingsComponent { this.isCustomerTable = data.tableType === PartTableType.AS_BUILT_CUSTOMER || data.tableType === PartTableType.AS_PLANNED_CUSTOMER // Passed Data this.tableType = data.tableType; - this.defaultColumns = data.defaultColumns; - this.defaultFilterColumns = data.defaultFilterColumns; + this.defaultColumns = data.defaultColumns.filter((column: string) => column !== 'menu'); + this.defaultFilterColumns = data.defaultFilterColumns.filter((column: string) => column !== 'menu'); // Storage Data this.columnOptions = tableSettingsService.getStoredTableSettings()[this.tableType].columnSettingsOptions; - this.dialogColumns = tableSettingsService.getStoredTableSettings()[this.tableType].columnsForDialog; - this.tableColumns = tableSettingsService.getStoredTableSettings()[this.tableType].columnsForTable; - this.filterColumns = tableSettingsService.getStoredTableSettings()[this.tableType].filterColumnsForTable; + this.dialogColumns = tableSettingsService.getStoredTableSettings()[this.tableType].columnsForDialog.filter((column: string) => column !== 'menu');; + this.tableColumns = tableSettingsService.getStoredTableSettings()[this.tableType].columnsForTable.filter((column: string) => column !== 'menu');; + this.filterColumns = tableSettingsService.getStoredTableSettings()[this.tableType].filterColumnsForTable.filter((column: string) => column !== 'menu');; this.selectAllSelected = this.dialogColumns.length === this.tableColumns.length; @@ -79,10 +79,13 @@ export class TableSettingsComponent { if(this.columnOptions.get(column)) { newTableColumns.push(column); // ignore select column in customertable - if(column === 'select' && !this.isCustomerTable) { + if(column === 'select') { newTableFilterColumns.push('Filter'); - } else { - newTableFilterColumns.push('filter'+ column.charAt(0).toUpperCase() + column.slice(1)) + } else if(column === 'menu'){ + + } + else { + newTableFilterColumns.push('filter'+ column) } } } @@ -99,7 +102,7 @@ export class TableSettingsComponent { } as TableViewSettings; // save all values back to localstorage - this.tableSettingsService.storeTableSettings(this.tableType, tableSettingsList); + this.tableSettingsService.storeTableSettings(tableSettingsList); // trigger action that table will refresh this.tableSettingsService.emitChangeEvent(); @@ -140,7 +143,7 @@ export class TableSettingsComponent { selectAll(isChecked: boolean) { for(let column of this.dialogColumns) { - if(column === 'select'){ + if(column === 'select' || column === 'menu'){ continue; } this.columnOptions.set(column,isChecked); @@ -149,6 +152,7 @@ export class TableSettingsComponent { } resetColumns() { + this.dialogColumns = [...this.defaultColumns.filter(value => value!=='menu')]; this.selectAll(true); } diff --git a/frontend/src/app/modules/shared/helper/filter-helper.ts b/frontend/src/app/modules/shared/helper/filter-helper.ts index faac1d5f9a..ee6009f790 100644 --- a/frontend/src/app/modules/shared/helper/filter-helper.ts +++ b/frontend/src/app/modules/shared/helper/filter-helper.ts @@ -18,139 +18,160 @@ ********************************************************************************/ import {HttpParams} from '@angular/common/http'; import { - AssetAsBuiltFilter, - AssetAsPlannedFilter, - FilterOperator, - getFilterOperatorValue, + AssetAsBuiltFilter, + AssetAsPlannedFilter, + FilterOperator, + getFilterOperatorValue, } from '@page/parts/model/parts.model'; -export const DATE_FILTER_KEYS = [ 'manufacturingDate', 'functionValidFrom', 'functionValidUntil', 'validityPeriodFrom', 'validityPeriodTo' ]; +export const DATE_FILTER_KEYS = ['manufacturingDate', 'functionValidFrom', 'functionValidUntil', 'validityPeriodFrom', 'validityPeriodTo']; // TODO: Refactor function export function enrichFilterAndGetUpdatedParams(filter: AssetAsBuiltFilter, params: HttpParams, filterOperator: string): HttpParams { - for (const key in filter) { - let operator: string; - const filterValues: string = filter[key]; - if (!filterValues){ - continue; - } - // has date - if (isDateFilter(key)) { - if (isDateRangeFilter(filterValues)) { - const [ startDate, endDate ] = filterValues.split(','); - if (isSameDate(startDate, endDate)) { - operator = getFilterOperatorValue(FilterOperator.AT_LOCAL_DATE); - params = params.append('filter', `${ key },${ operator },${ startDate },${ filterOperator }`); - continue; + for (const key in filter) { + let operator: string; + const filterValues: string = filter[key]; + if (!filterValues) { + continue; + } + // has date + if (isDateFilter(key)) { + if (isDateRangeFilter(filterValues)) { + const [startDate, endDate] = filterValues.split(','); + if (isSameDate(startDate, endDate)) { + operator = getFilterOperatorValue(FilterOperator.AT_LOCAL_DATE); + params = params.append('filter', `${key},${operator},${startDate},${filterOperator}`); + continue; + } + let endDateOperator = getFilterOperatorValue(FilterOperator.BEFORE_LOCAL_DATE); + operator = getFilterOperatorValue((FilterOperator.AFTER_LOCAL_DATE)); + params = params.append('filter', `${key},${operator},${startDate},${filterOperator}`); + params = params.append('filter', `${key},${endDateOperator},${endDate},${filterOperator}`); + continue; + } else if (filterValues && filterValues.length != 0) { + console.log(filterValues, "filtervalues"); + operator = getFilterOperatorValue(FilterOperator.AT_LOCAL_DATE); + params = params.append('filter', `${key},${operator},${filterValues},${filterOperator}`); + } } - let endDateOperator = getFilterOperatorValue(FilterOperator.BEFORE_LOCAL_DATE); - operator = getFilterOperatorValue((FilterOperator.AFTER_LOCAL_DATE)); - params = params.append('filter', `${ key },${ operator },${ startDate },${ filterOperator }`); - params = params.append('filter', `${ key },${ endDateOperator },${ endDate },${ filterOperator }`); - continue; - } else if (filterValues && filterValues.length != 0) { - console.log(filterValues, "filtervalues"); - operator = getFilterOperatorValue(FilterOperator.AT_LOCAL_DATE); - params = params.append('filter', `${ key },${ operator },${ filterValues },${ filterOperator }`); - } - } - // has multiple values - if (isStartsWithFilter(key) && Array.isArray(filter[key])) { - operator = getFilterOperatorValue(FilterOperator.EQUAL); + // has multiple values + if (isStartsWithFilter(key) && Array.isArray(filter[key])) { + operator = getFilterOperatorValue(FilterOperator.EQUAL); - for (const value of filter[key]) { - params = params.append('filter', `${ key },${ operator },${ value },${ filterOperator }`); - } - } + for (const value of filter[key]) { + params = params.append('filter', `${key},${operator},${value},${filterOperator}`); + } + } - // has single value - if (isStartsWithFilter(key) && !Array.isArray(filter[key])) { - operator = getFilterOperatorValue(FilterOperator.STARTS_WITH); - params = params.append('filter', `${ key },${ operator },${ filterValues },${ filterOperator }`); - } + // has single value + if (isStartsWithFilter(key) && !Array.isArray(filter[key])) { + operator = getFilterOperatorValue(FilterOperator.STARTS_WITH); + params = params.append('filter', `${key},${operator},${filterValues},${filterOperator}`); + } - if (isNotificationCountFilter(key) && filterValues && filterValues.length != 0) { - operator = getFilterOperatorValue(FilterOperator.NOTIFICATION_COUNT_EQUAL); - params = params.append('filter', `${ key },${ operator },${ filterValues },${ filterOperator }`); - } + if (isNotificationCountFilter(key) && filterValues && filterValues.length != 0) { + operator = getFilterOperatorValue(FilterOperator.NOTIFICATION_COUNT_EQUAL); + params = params.append('filter', `${key},${operator},${filterValues},${filterOperator}`); + } - } + } - return params; + return params; } export function isStartsWithFilter(key: string): boolean { - return !isDateFilter(key) && !isNotificationCountFilter(key); + return !isDateFilter(key) && !isNotificationCountFilter(key); } export function isNotificationCountFilter(key: string): boolean { - return 'qualityAlertIdsInStatusActive' === key || 'qualityInvestigationIdsInStatusActive' === key; + return 'receivedQualityAlertIdsInStatusActive' === key || 'sentQualityAlertIdsInStatusActive' === key || 'receivedQualityInvestigationIdsInStatusActive' === key || 'sentQualityInvestigationIdsInStatusActive' === key; } export function isDateFilter(key: string): boolean { - return DATE_FILTER_KEYS.includes(key); + return DATE_FILTER_KEYS.includes(key); } export function isDateRangeFilter(filterValues: string): boolean { - return filterValues.includes(','); + return filterValues.includes(','); } export function isSameDate(startDate: string, endDate: string): boolean { - return startDate === endDate; + return startDate === endDate; } export function toAssetFilter(formValues: any, isAsBuilt: boolean): AssetAsPlannedFilter | AssetAsBuiltFilter { - const transformedFilter: any = {}; - - // Loop through each form control and add it to the transformedFilter if it has a non-null and non-undefined value - for (const key in formValues) { - if (formValues[key] !== null && formValues[key] !== undefined) { - if ('activeAlerts' === key) { - transformedFilter['qualityAlertIdsInStatusActive'] = formValues[key]; - continue; - } - if ('activeInvestigations' === key) { - transformedFilter['qualityInvestigationIdsInStatusActive'] = formValues[key]; - continue; - } - transformedFilter[key] = formValues[key]; + const transformedFilter: any = {}; + + // Loop through each form control and add it to the transformedFilter if it has a non-null and non-undefined value + for (const key in formValues) { + if (formValues[key] !== null && formValues[key] !== undefined) { + if ('receivedActiveAlerts' === key) { + transformedFilter['receivedQualityAlertIdsInStatusActive'] = formValues[key]; + continue; + } + if ('sentActiveAlerts' === key) { + transformedFilter['sentQualityAlertIdsInStatusActive'] = formValues[key]; + continue; + } + if ('receivedActiveInvestigations' === key) { + transformedFilter['receivedQualityInvestigationIdsInStatusActive'] = formValues[key]; + continue; + } + if ('sentActiveInvestigations' === key) { + transformedFilter['sentQualityInvestigationIdsInStatusActive'] = formValues[key]; + continue; + } + transformedFilter[key] = formValues[key]; + } } - } - const filterIsSet = Object.values(transformedFilter).some(value => value !== undefined && value !== null); - if (filterIsSet) { - if (isAsBuilt) { - return transformedFilter as AssetAsBuiltFilter; + const filterIsSet = Object.values(transformedFilter).some(value => value !== undefined && value !== null); + if (filterIsSet) { + if (isAsBuilt) { + return transformedFilter as AssetAsBuiltFilter; + } else { + return transformedFilter as AssetAsPlannedFilter; + } } else { - return transformedFilter as AssetAsPlannedFilter; + return null; + } + +} + +export function enrichDeeplinkFilterAndGetUpdatedParams(filter: any, httpParams: HttpParams): HttpParams { + + if (filter?.notificationIds) { + filter.notificationIds.forEach(notificationId => { + httpParams = httpParams.append('filter', 'id,EQUAL,' + notificationId + ',OR') + }) } - } else { - return null; - } + console.log(httpParams, "params"); + return httpParams; } + export function toGlobalSearchAssetFilter(formValues: string, isAsBuilt: boolean) { - let filter; - if (isAsBuilt) { - filter = { - id: formValues, - semanticModelId: formValues, - idShort: formValues, - customerPartId: formValues, - manufacturerPartId: formValues, - } as AssetAsBuiltFilter; - } else { - filter = { - id: formValues, - idShort: formValues, - semanticModelId: formValues, - manufacturerPartId: formValues, - } as AssetAsPlannedFilter; - } - - return filter; + let filter; + if (isAsBuilt) { + filter = { + id: formValues, + semanticModelId: formValues, + idShort: formValues, + customerPartId: formValues, + manufacturerPartId: formValues, + } as AssetAsBuiltFilter; + } else { + filter = { + id: formValues, + idShort: formValues, + semanticModelId: formValues, + manufacturerPartId: formValues, + } as AssetAsPlannedFilter; + } + + return filter; } diff --git a/frontend/src/app/modules/shared/modules/relations/core/relations.assembler.spec.ts b/frontend/src/app/modules/shared/modules/relations/core/relations.assembler.spec.ts index 075e9c1e2e..e11667be06 100644 --- a/frontend/src/app/modules/shared/modules/relations/core/relations.assembler.spec.ts +++ b/frontend/src/app/modules/shared/modules/relations/core/relations.assembler.spec.ts @@ -26,7 +26,7 @@ import { TreeElement, TreeStructure } from '@shared/modules/relations/model/rela describe('Relations assembler', () => { describe('assemblePartForRelation', () => { it('should assemble loading part', () => { - const part = { id: 'id', name: 'name', semanticModelId: 'semanticModelId', children: null, parents: null } as Part; + const part = { id: 'id', nameAtManufacturer: 'name', semanticModelId: 'semanticModelId', children: null, parents: null } as Part; const expected = { children: null, parents: null, @@ -38,7 +38,7 @@ describe('Relations assembler', () => { expect(RelationsAssembler.assemblePartForRelation(part)).toEqual(expected); }); it('should assemble finished loading part', () => { - const part = { id: 'id', name: 'name', semanticModelId: 'semanticModelId', children: [], parents: [] } as Part; + const part = { id: 'id', nameAtManufacturer: 'name', semanticModelId: 'semanticModelId', children: [], parents: [] } as Part; const expected = { children: [], parents: [], diff --git a/frontend/src/app/modules/shared/modules/relations/core/relations.assembler.ts b/frontend/src/app/modules/shared/modules/relations/core/relations.assembler.ts index 0d142d356c..5eadc211d6 100644 --- a/frontend/src/app/modules/shared/modules/relations/core/relations.assembler.ts +++ b/frontend/src/app/modules/shared/modules/relations/core/relations.assembler.ts @@ -25,7 +25,7 @@ import _deepClone from 'lodash-es/cloneDeep'; export class RelationsAssembler { public static assemblePartForRelation(part: Part, idFallback?: string): TreeElement { - const { id, name: text = idFallback, semanticDataModel, children, parents } = part || {}; + const { id, nameAtManufacturer: text = idFallback, semanticDataModel, children, parents } = part || {}; const mapBatchToState = (type: SemanticDataModel): SemanticDataModel | string => { if(type && type.toUpperCase() in SemanticDataModel) { diff --git a/frontend/src/app/modules/shared/service/alerts.service.ts b/frontend/src/app/modules/shared/service/alerts.service.ts index 6bc4c2a55b..18dbdd3e55 100644 --- a/frontend/src/app/modules/shared/service/alerts.service.ts +++ b/frontend/src/app/modules/shared/service/alerts.service.ts @@ -37,6 +37,8 @@ import { NotificationStatus, NotificationType, } from '../model/notification.model'; +import {NotificationFilter} from "../../../mocks/services/investigations-mock/investigations.model"; +import {enrichDeeplinkFilterAndGetUpdatedParams} from "@shared/helper/filter-helper"; @Injectable({ providedIn: 'root', @@ -46,7 +48,7 @@ export class AlertsService { constructor(private readonly apiService: ApiService) {} - public getCreatedAlerts(page: number, pageSize: number, sorting: TableHeaderSort[]): Observable { + public getCreatedAlerts(page: number, pageSize: number, sorting: TableHeaderSort[], filter?: NotificationFilter): Observable { let sort = sorting.length ? sorting : ['createdDate,desc']; let params = new HttpParams() .set('page', page) @@ -57,12 +59,14 @@ export class AlertsService { params = params.append('sort', sortingItem); }) + params = enrichDeeplinkFilterAndGetUpdatedParams(filter, params); + return this.apiService .getBy(`${this.url}/alerts`, params) .pipe(map(alerts => NotificationAssembler.assembleNotifications(alerts, NotificationType.ALERT))); } - public getReceivedAlerts(page: number, pageSize: number, sorting: TableHeaderSort[]): Observable { + public getReceivedAlerts(page: number, pageSize: number, sorting: TableHeaderSort[], filter?: NotificationFilter): Observable { let sort = sorting.length ? sorting : ['createdDate,desc']; let params = new HttpParams() .set('page', page) @@ -73,6 +77,8 @@ export class AlertsService { params = params.append('sort', sortingItem); }) + params = enrichDeeplinkFilterAndGetUpdatedParams(filter, params); + return this.apiService .getBy(`${this.url}/alerts`, params) .pipe(map(alerts => NotificationAssembler.assembleNotifications(alerts, NotificationType.ALERT))); diff --git a/frontend/src/app/modules/shared/service/investigations.service.ts b/frontend/src/app/modules/shared/service/investigations.service.ts index 8729fe73b4..5a020daaa0 100644 --- a/frontend/src/app/modules/shared/service/investigations.service.ts +++ b/frontend/src/app/modules/shared/service/investigations.service.ts @@ -30,96 +30,103 @@ import type {Observable} from 'rxjs'; import {map} from 'rxjs/operators'; import {NotificationAssembler} from '../assembler/notification.assembler'; import { - Notification, - NotificationCreateResponse, - NotificationResponse, - Notifications, - NotificationsResponse, - NotificationStatus, - NotificationType, + Notification, + NotificationCreateResponse, + NotificationResponse, + Notifications, + NotificationsResponse, + NotificationStatus, + NotificationType, } from '../model/notification.model'; +import {NotificationFilter} from "../../../mocks/services/investigations-mock/investigations.model"; +import {enrichDeeplinkFilterAndGetUpdatedParams} from "@shared/helper/filter-helper"; @Injectable({ - providedIn: 'root', + providedIn: 'root', }) export class InvestigationsService { - private readonly url = environment.apiUrl; - - constructor(private readonly apiService: ApiService) {} - - public getCreatedInvestigations(page: number, pageSize: number, sorting: TableHeaderSort[]): Observable { - let sort = sorting.length ? sorting : ['createdDate,desc']; - let params = new HttpParams() - .set('page', page) - .set('size', pageSize) - .set('filter', 'channel,EQUAL,SENDER,AND') - - sort.forEach(sortingItem => { - params = params.append('sort', sortingItem); - }) - - return this.apiService - .getBy(`${this.url}/investigations`, params) - .pipe(map(investigations => NotificationAssembler.assembleNotifications(investigations, NotificationType.INVESTIGATION))); - } - - public getReceivedInvestigations(page: number, pageSize: number, sorting: TableHeaderSort[]): Observable { - let sort = sorting.length ? sorting : ['createdDate,desc']; - let params = new HttpParams() - .set('page', page) - .set('size', pageSize) - .set('filter', 'channel,EQUAL,RECEIVER,AND') - - sort.forEach(sortingItem => { - params = params.append('sort', sortingItem); - }) - - return this.apiService - .getBy(`${this.url}/investigations`, params) - .pipe(map(investigations => NotificationAssembler.assembleNotifications(investigations, NotificationType.INVESTIGATION))); - } - - public getInvestigation(id: string): Observable { - return this.apiService - .get(`${this.url}/investigations/${id}`) - .pipe(map(notification => NotificationAssembler.assembleNotification(notification, NotificationType.INVESTIGATION))); - } - - public postInvestigation( - partIds: string[], - description: string, - severity: Severity, - dateString: DateTimeString, - ): Observable { - // targetDate is an optional field - const targetDate = null === dateString ? null : new Date(dateString).toISOString(); - const body = { partIds, description, severity, targetDate }; - - return this.apiService - .post(`${this.url}/investigations`, body) - .pipe(map(({ id }) => id)); - } - - public closeInvestigation(id: string, reason: string): Observable { - const body = { reason }; - - return this.apiService.post(`${this.url}/investigations/${id}/close`, body); - } - - public approveInvestigation(id: string): Observable { - return this.apiService.post(`${this.url}/investigations/${id}/approve`); - } - - public cancelInvestigation(id: string): Observable { - return this.apiService.post(`${this.url}/investigations/${id}/cancel`); - } - - public updateInvestigation( - id: string, - status: NotificationStatus.ACKNOWLEDGED | NotificationStatus.ACCEPTED | NotificationStatus.DECLINED, - reason = '', - ): Observable { - const body = { reason, status }; - return this.apiService.post(`${this.url}/investigations/${id}/update`, body); - } + private readonly url = environment.apiUrl; + + constructor(private readonly apiService: ApiService) { + } + + public getCreatedInvestigations(page: number, pageSize: number, sorting: TableHeaderSort[], filter?: NotificationFilter): Observable { + let sort = sorting.length ? sorting : ['createdDate,desc']; + let params = new HttpParams() + .set('page', page) + .set('size', pageSize) + .set('filter', 'channel,EQUAL,SENDER,AND') + + sort.forEach(sortingItem => { + params = params.append('sort', sortingItem); + }) + + params = enrichDeeplinkFilterAndGetUpdatedParams(filter, params); + + return this.apiService + .getBy(`${this.url}/investigations`, params) + .pipe(map(investigations => NotificationAssembler.assembleNotifications(investigations, NotificationType.INVESTIGATION))); + } + + public getReceivedInvestigations(page: number, pageSize: number, sorting: TableHeaderSort[], filter?: NotificationFilter): Observable { + let sort = sorting.length ? sorting : ['createdDate,desc']; + + let params = new HttpParams() + .set('page', page) + .set('size', pageSize) + .set('filter', 'channel,EQUAL,RECEIVER,AND') + + sort.forEach(sortingItem => { + params = params.append('sort', sortingItem); + }) + params = enrichDeeplinkFilterAndGetUpdatedParams(filter, params); + + return this.apiService + .getBy(`${this.url}/investigations`, params) + .pipe(map(investigations => NotificationAssembler.assembleNotifications(investigations, NotificationType.INVESTIGATION))); + } + + public getInvestigation(id: string): Observable { + return this.apiService + .get(`${this.url}/investigations/${id}`) + .pipe(map(notification => NotificationAssembler.assembleNotification(notification, NotificationType.INVESTIGATION))); + } + + public postInvestigation( + partIds: string[], + description: string, + severity: Severity, + dateString: DateTimeString, + ): Observable { + // targetDate is an optional field + const targetDate = null === dateString ? null : new Date(dateString).toISOString(); + const body = {partIds, description, severity, targetDate}; + + return this.apiService + .post(`${this.url}/investigations`, body) + .pipe(map(({id}) => id)); + } + + public closeInvestigation(id: string, reason: string): Observable { + const body = {reason}; + + return this.apiService.post(`${this.url}/investigations/${id}/close`, body); + } + + public approveInvestigation(id: string): Observable { + return this.apiService.post(`${this.url}/investigations/${id}/approve`); + } + + public cancelInvestigation(id: string): Observable { + return this.apiService.post(`${this.url}/investigations/${id}/cancel`); + } + + public updateInvestigation( + id: string, + status: NotificationStatus.ACKNOWLEDGED | NotificationStatus.ACCEPTED | NotificationStatus.DECLINED, + reason = '', + ): Observable { + const body = {reason, status}; + return this.apiService.post(`${this.url}/investigations/${id}/update`, body); + } } diff --git a/frontend/src/assets/locales/de/common.json b/frontend/src/assets/locales/de/common.json index b2219e5fc0..f5b6511c26 100644 --- a/frontend/src/assets/locales/de/common.json +++ b/frontend/src/assets/locales/de/common.json @@ -60,11 +60,14 @@ "multiSortingTooltip": "Erster Klick: aufsteigend sortieren ↑ Zweiter Klick: absteigend sortieren ↓ Dritter Klick: Sortierung zurücksetzen", "filterTitle" : "Filter", "tableSettings": { + "invalid": "Auf Grund eines Fehlers werden die Tabelleneinstellungen zurückgesetzt", "title": "Tabellenspalten Einstellungen", "selectAll": "Alle", "orderTooltip": "Die Anordnung der Tabellenspalten kann über die Auswahl einer Spalte und einem Klick auf die Pfeilsymbole angepasst werden. ↑ (hoch) oder ↓ (runter)", "refreshTooltip": "Zurücksetzen der individuellen Einstellung der Tabellenspalten auf die Standardeinstellung", - "saveAction": "Speichern" + "saveAction": "Speichern", + "alert": "Qualitätswarnung", + "investigation": "Qualitätsuntersuchung" }, "adminColumn": { "startDate": "Startdatum", @@ -78,7 +81,7 @@ "id": "ID", "idShort": "Kurz-ID", "name": "Name", - "manufacturer": "Hersteller", + "manufacturerName": "Hersteller", "partId": "Produktnummer", "manufacturerPartId": "Hersteller Produktnummer", "customerPartId": "Kunden Produktnummer", @@ -104,8 +107,10 @@ "psFunction": "Funktion", "functionValidFrom": "Funktion gültig von", "functionValidUntil" : "Funktion gültig bis", - "activeAlerts" : "Aktive Qualitätswarnungen", - "activeInvestigations" : "Aktive Qualitätsuntersuchungen" + "sentActiveAlerts" : "Erstellte", + "receivedActiveInvestigations" : "Empfangene", + "receivedActiveAlerts" : "Empfangene", + "sentActiveInvestigations" : "Erstellte" } }, "dataLoading": { diff --git a/frontend/src/assets/locales/de/page.otherParts.json b/frontend/src/assets/locales/de/page.otherParts.json index 651242e793..fcf10f1899 100644 --- a/frontend/src/assets/locales/de/page.otherParts.json +++ b/frontend/src/assets/locales/de/page.otherParts.json @@ -14,7 +14,7 @@ "partId": "Produktnummer", "semanticModelId": "Semantische Modellnummer", "manufacturingDate": "Produktionsdatum", - "manufacturer": "Hersteller", + "manufacturerName": "Hersteller", "nameAtCustomer": "Name beim Kunden", "customerPartId": "Kunden Produktnummer", "semanticDataModel": "Semantisches Datenmodell" diff --git a/frontend/src/assets/locales/de/partDetail.json b/frontend/src/assets/locales/de/partDetail.json index 87be49bda4..61fba07fb5 100644 --- a/frontend/src/assets/locales/de/partDetail.json +++ b/frontend/src/assets/locales/de/partDetail.json @@ -12,7 +12,7 @@ "semanticModelId": "Semantische Modellnummer", "qualityType": "Qualitätsstufe", "productionDate": "Produktionsdatum", - "manufacturer": "Hersteller", + "manufacturerName": "Hersteller", "manufacturerPartId": "Hersteller Produktnummer", "nameAtManufacturer": "Hersteller Produktname", "nameAtCustomer": "Name beim Kunden", diff --git a/frontend/src/assets/locales/en/common.json b/frontend/src/assets/locales/en/common.json index b60eb73e16..ed8d1812f5 100644 --- a/frontend/src/assets/locales/en/common.json +++ b/frontend/src/assets/locales/en/common.json @@ -60,11 +60,14 @@ "multiSortingTooltip": "First click: sort in ascending order ↑ Second click: sort in descending order ↓ Third click: reset sorting", "filterTitle": "Filter", "tableSettings": { + "invalid": "Due to an error table settings have been reset", "title": "Table column settings", "selectAll": "All", "orderTooltip": "Table column order can be changed by selecting a column and move it up or down by clicking on the icon ↑ (up) or ↓ (down)", "refreshTooltip": "Reset individual table column settings to default", - "saveAction": "Save" + "saveAction": "Save", + "alert": "Quality Alert", + "investigation": "Quality Investigation" }, "adminColumn": { "startDate": "Start date", @@ -78,7 +81,7 @@ "id": "ID", "idShort": "ID Short", "name": "Name", - "manufacturer": "Manufacturer", + "manufacturerName": "Manufacturer", "partId": "Part number", "manufacturerPartId": "Manufacturer part ID", "customerPartId": "Customer part ID", @@ -103,8 +106,10 @@ "psFunction": "Function", "functionValidFrom": "Function valid from", "functionValidUntil" : "Function valid until", - "activeAlerts" : "Active Quality alerts", - "activeInvestigations" : "Active Quality investigations" + "sentActiveAlerts" : "Created", + "receivedActiveInvestigations" : "Received", + "receivedActiveAlerts" : "Received", + "sentActiveInvestigations" : "Created" } }, "dataLoading": { diff --git a/frontend/src/assets/locales/en/page.otherParts.json b/frontend/src/assets/locales/en/page.otherParts.json index ecdc572afe..9f411c78aa 100644 --- a/frontend/src/assets/locales/en/page.otherParts.json +++ b/frontend/src/assets/locales/en/page.otherParts.json @@ -14,7 +14,7 @@ "partId": "Part number", "semanticModelId": "Semantic Model ID", "manufacturingDate": "Production date", - "manufacturer": "Manufacturer", + "manufacturerName": "Manufacturer", "nameAtCustomer": "Name at customer", "customerPartId": "Customer part ID", "semanticDataModel": "Semantic Data Model" diff --git a/frontend/src/assets/locales/en/partDetail.json b/frontend/src/assets/locales/en/partDetail.json index 7e1f707f8e..a5b9531cb7 100644 --- a/frontend/src/assets/locales/en/partDetail.json +++ b/frontend/src/assets/locales/en/partDetail.json @@ -12,7 +12,7 @@ "semanticModelId": "Semantic Model ID", "qualityType": "Quality type", "productionDate": "Production date", - "manufacturer": "Manufacturer", + "manufacturerName": "Manufacturer", "manufacturerPartId": "Manufacturer part ID", "nameAtManufacturer": "Name at manufacturer", "nameAtCustomer": "Name at customer", diff --git a/frontend/src/theme/base.scss b/frontend/src/theme/base.scss index 3b8f1a06a7..9d987ed6bb 100644 --- a/frontend/src/theme/base.scss +++ b/frontend/src/theme/base.scss @@ -161,6 +161,12 @@ as-split-area { } app-parts-table { + + th{ + white-space: normal!important; + word-wrap: break-word!important; + } + /* Avoid sticky head to be over sidenav component*/ th { z-index: 1 !important; @@ -217,7 +223,6 @@ app-parts, app-other-parts, app-notifications-tab { border-radius: 24px 24px 0 0; background-color: rgba(0, 0, 0, 0.02); box-shadow: 0 3px 5px #888; - // box-shadow: 0 2px 2px -3px rgba(0, 0, 0, 0.2), 0px 4px 6px -1px rgba(0, 0, 0, 0.14), 0px 1px 8px -2px rgba(0, 0, 0, 0.12); .table-header-container { justify-content: center; @@ -259,6 +264,26 @@ app-parts, app-other-parts, app-notifications-tab { } +/* Align icon with text centered*/ +app-table-settings{ + .mat-mdc-checkbox label{ + display:flex; + align-items:center; + } +} + +/* Make sure multi-select text field does fit with other content and does not extend the column width */ +app-multiselect{ + .mat-mdc-form-field{ + width:100%; + } +} + +/* Make sure multi-select text field does fit with other content and does not extend the column width */ +app-multiselect .mdc-text-field--no-label:not(.mdc-text-field--outlined):not(.mdc-text-field--textarea) .mat-mdc-form-field-infix{ + width:100%; +} + /* Apply correct padding for text value inside of textarea*/ app-textarea { .mat-mdc-form-field-infix { diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asbuilt/mapper/AssetAsBuiltFieldMapper.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asbuilt/mapper/AssetAsBuiltFieldMapper.java index 550c9e007a..0db5c4b341 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asbuilt/mapper/AssetAsBuiltFieldMapper.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asbuilt/mapper/AssetAsBuiltFieldMapper.java @@ -50,8 +50,10 @@ public class AssetAsBuiltFieldMapper extends BaseRequestFieldMapper { Map.entry("van", "van"), Map.entry("businessPartner", "manufacturerId"), Map.entry("alerts", "alerts"), - Map.entry("qualityAlertIdsInStatusActive", "activeAlertsCount"), - Map.entry("qualityInvestigationIdsInStatusActive", "activeInvestigationsCount") + Map.entry("sentQualityAlertIdsInStatusActive", "sentActiveAlertsCount"), + Map.entry("sentQualityInvestigationIdsInStatusActive", "sentActiveInvestigationsCount"), + Map.entry("receivedQualityAlertIdsInStatusActive", "receivedActiveAlertsCount"), + Map.entry("receivedQualityInvestigationIdsInStatusActive", "receivedActiveInvestigationsCount") ); @Override diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asbuilt/mapper/AssetAsBuiltResponseMapper.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asbuilt/mapper/AssetAsBuiltResponseMapper.java index ba2ab1a0cb..1e898bfdb4 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asbuilt/mapper/AssetAsBuiltResponseMapper.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asbuilt/mapper/AssetAsBuiltResponseMapper.java @@ -54,8 +54,10 @@ public static AssetAsBuiltResponse from(final AssetBase asset) { .van(asset.getVan()) .semanticDataModel(from(asset.getSemanticDataModel())) .detailAspectModels(fromList(asset.getDetailAspectModels())) - .qualityAlertIdsInStatusActive(getNotificationIdsInActiveState(asset.getQualityAlerts())) - .qualityInvestigationIdsInStatusActive(getNotificationIdsInActiveState(asset.getQualityInvestigations())) + .sentQualityAlertIdsInStatusActive(getNotificationIdsInActiveState(asset.getSentQualityAlerts())) + .receivedQualityAlertIdsInStatusActive(getNotificationIdsInActiveState(asset.getReceivedQualityAlerts())) + .sentQualityInvestigationIdsInStatusActive(getNotificationIdsInActiveState(asset.getSentQualityInvestigations())) + .receivedQualityInvestigationIdsInStatusActive(getNotificationIdsInActiveState(asset.getReceivedQualityInvestigations())) .build(); } diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asplanned/mapper/AssetAsPlannedResponseMapper.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asplanned/mapper/AssetAsPlannedResponseMapper.java index f87420fbdc..50e872c1c1 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asplanned/mapper/AssetAsPlannedResponseMapper.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/application/asplanned/mapper/AssetAsPlannedResponseMapper.java @@ -54,8 +54,10 @@ public static AssetAsPlannedResponse from(final AssetBase asset) { .van(asset.getVan()) .semanticDataModel(from(asset.getSemanticDataModel())) .detailAspectModels(fromList(asset.getDetailAspectModels())) - .qualityAlertIdsInStatusActive(getNotificationIdsInActiveState(asset.getQualityAlerts())) - .qualityInvestigationIdsInStatusActive(getNotificationIdsInActiveState(asset.getQualityInvestigations())) + .sentQualityAlertIdsInStatusActive(getNotificationIdsInActiveState(asset.getSentQualityAlerts())) + .receivedQualityAlertIdsInStatusActive(getNotificationIdsInActiveState(asset.getReceivedQualityAlerts())) + .sentQualityInvestigationIdsInStatusActive(getNotificationIdsInActiveState(asset.getSentQualityInvestigations())) + .receivedQualityInvestigationIdsInStatusActive(getNotificationIdsInActiveState(asset.getReceivedQualityInvestigations())) .build(); } diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/domain/base/model/AssetBase.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/domain/base/model/AssetBase.java index f70d799b38..c955b6ea79 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/domain/base/model/AssetBase.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/domain/base/model/AssetBase.java @@ -55,6 +55,8 @@ public class AssetBase { private SemanticDataModel semanticDataModel; private String classification; private List detailAspectModels; - private List qualityAlerts; - private List qualityInvestigations; + private List sentQualityAlerts; + private List receivedQualityAlerts; + private List sentQualityInvestigations; + private List receivedQualityInvestigations; } diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/model/AssetAsBuiltEntity.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/model/AssetAsBuiltEntity.java index 094607b922..bc25756d9b 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/model/AssetAsBuiltEntity.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/model/AssetAsBuiltEntity.java @@ -42,6 +42,7 @@ import org.eclipse.tractusx.traceability.assets.infrastructure.base.model.SemanticDataModelEntity; import org.eclipse.tractusx.traceability.qualitynotification.infrastructure.alert.model.AlertEntity; import org.eclipse.tractusx.traceability.qualitynotification.infrastructure.investigation.model.InvestigationEntity; +import org.eclipse.tractusx.traceability.qualitynotification.infrastructure.model.NotificationSideBaseEntity; import java.time.Instant; import java.util.ArrayList; @@ -143,8 +144,10 @@ public static AssetBase toDomain(AssetAsBuiltEntity entity) { .van(entity.getVan()) .classification(entity.getClassification()) .detailAspectModels(DetailAspectModel.from(entity)) - .qualityAlerts(emptyIfNull(entity.alerts).stream().map(AlertEntity::toDomain).toList()) - .qualityInvestigations(emptyIfNull(entity.investigations).stream().map(InvestigationEntity::toDomain).toList()) + .sentQualityAlerts(emptyIfNull(entity.alerts).stream().filter(alert -> NotificationSideBaseEntity.SENDER.equals(alert.getSide())).map(AlertEntity::toDomain).toList()) + .receivedQualityAlerts(emptyIfNull(entity.alerts).stream().filter(alert -> NotificationSideBaseEntity.RECEIVER.equals(alert.getSide())).map(AlertEntity::toDomain).toList()) + .sentQualityInvestigations(emptyIfNull(entity.investigations).stream().filter(alert -> NotificationSideBaseEntity.SENDER.equals(alert.getSide())).map(InvestigationEntity::toDomain).toList()) + .receivedQualityInvestigations(emptyIfNull(entity.investigations).stream().filter(alert -> NotificationSideBaseEntity.RECEIVER.equals(alert.getSide())).map(InvestigationEntity::toDomain).toList()) .build(); } diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/repository/AssetAsBuildSpecification.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/repository/AssetAsBuildSpecification.java index d7aeff40ca..dd6b4b2676 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/repository/AssetAsBuildSpecification.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/repository/AssetAsBuildSpecification.java @@ -33,6 +33,7 @@ import org.eclipse.tractusx.traceability.qualitynotification.domain.base.model.QualityNotificationStatus; import org.eclipse.tractusx.traceability.qualitynotification.infrastructure.alert.model.AlertEntity; import org.eclipse.tractusx.traceability.qualitynotification.infrastructure.investigation.model.InvestigationEntity; +import org.eclipse.tractusx.traceability.qualitynotification.infrastructure.model.NotificationSideBaseEntity; import org.jetbrains.annotations.NotNull; import org.springframework.data.jpa.domain.Specification; @@ -57,14 +58,28 @@ public Predicate toPredicate(@NotNull Root root, @NotNull Cr private static Predicate activeNotificationCountEqualPredicate(SearchCriteriaFilter criteria, Root root, CriteriaBuilder builder, String expectedFieldValue) { String joinTableName; Class notificationClass; + NotificationSideBaseEntity side; switch (criteria.getKey()) { - case "activeAlertsCount" -> { + case "sentActiveAlertsCount" -> { notificationClass = AlertEntity.class; joinTableName = "alerts"; + side = NotificationSideBaseEntity.SENDER; } - case "activeInvestigationsCount" -> { + case "sentActiveInvestigationsCount" -> { notificationClass = InvestigationEntity.class; joinTableName = "investigations"; + side = NotificationSideBaseEntity.SENDER; + } + case "receivedActiveAlertsCount" -> { + notificationClass = AlertEntity.class; + joinTableName = "alerts"; + side = NotificationSideBaseEntity.RECEIVER; + + } + case "receivedActiveInvestigationsCount" -> { + notificationClass = InvestigationEntity.class; + joinTableName = "investigations"; + side = NotificationSideBaseEntity.RECEIVER; } default -> throw new UnsupportedOperationException(); } @@ -81,6 +96,7 @@ private static Predicate activeNotificationCountEqualPredicate(SearchCriteriaFil builder.or( activeNotificationPredicates(builder, subRoot) ), + notificationSidePredicate(builder, subRoot, side), builder.equal(assetJoin.get("id"), root.get("id"))) ); @@ -94,4 +110,8 @@ private static Predicate[] activeNotificationPredicates(CriteriaBuilder builder, return predicates.toArray(new Predicate[0]); } + + private static Predicate notificationSidePredicate(CriteriaBuilder builder, Root root, NotificationSideBaseEntity side) { + return builder.equal(root.get("side").as(String.class), side.name()); + } } diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asplanned/model/AssetAsPlannedEntity.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asplanned/model/AssetAsPlannedEntity.java index bf5c927d5a..fdadaa1fb1 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asplanned/model/AssetAsPlannedEntity.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asplanned/model/AssetAsPlannedEntity.java @@ -38,6 +38,7 @@ import org.eclipse.tractusx.traceability.assets.infrastructure.base.model.SemanticDataModelEntity; import org.eclipse.tractusx.traceability.qualitynotification.infrastructure.alert.model.AlertEntity; import org.eclipse.tractusx.traceability.qualitynotification.infrastructure.investigation.model.InvestigationEntity; +import org.eclipse.tractusx.traceability.qualitynotification.infrastructure.model.NotificationSideBaseEntity; import java.time.Instant; import java.util.ArrayList; @@ -130,8 +131,11 @@ public static AssetBase toDomain(AssetAsPlannedEntity entity) { .activeAlert(entity.isActiveAlert()) .qualityType(entity.getQualityType()) .detailAspectModels(DetailAspectModel.from(entity)) - .qualityAlerts(emptyIfNull(entity.alerts).stream().map(AlertEntity::toDomain).toList()) - .qualityInvestigations(emptyIfNull(entity.investigations).stream().map(InvestigationEntity::toDomain).toList()) + .sentQualityAlerts(emptyIfNull(entity.alerts).stream().filter(alert -> NotificationSideBaseEntity.SENDER.equals(alert.getSide())).map(AlertEntity::toDomain).toList()) + .receivedQualityAlerts(emptyIfNull(entity.alerts).stream().filter(alert -> NotificationSideBaseEntity.RECEIVER.equals(alert.getSide())).map(AlertEntity::toDomain).toList()) + .sentQualityInvestigations(emptyIfNull(entity.investigations).stream().filter(alert -> NotificationSideBaseEntity.SENDER.equals(alert.getSide())).map(InvestigationEntity::toDomain).toList()) + .receivedQualityInvestigations(emptyIfNull(entity.investigations).stream().filter(alert -> NotificationSideBaseEntity.RECEIVER.equals(alert.getSide())).map(InvestigationEntity::toDomain).toList()) + .build(); } diff --git a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsBuiltControllerByIdIT.java b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsBuiltControllerByIdIT.java index d2788093ab..d126c6c675 100644 --- a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsBuiltControllerByIdIT.java +++ b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsBuiltControllerByIdIT.java @@ -101,7 +101,7 @@ void givenAlertsForAsset_whenCallAssetById_thenReturnProperCount() throws JoseEx .log().all() .statusCode(200) .assertThat() - .body("qualityAlertIdsInStatusActive", hasSize(6)); + .body("receivedQualityAlertIdsInStatusActive", hasSize(6)); } @Test @@ -127,7 +127,7 @@ void givenInvestigationsForAsset_whenCallAssetById_thenReturnProperCount() throw .then() .statusCode(200) .assertThat() - .body("qualityInvestigationIdsInStatusActive", hasSize(6)); + .body("receivedQualityInvestigationIdsInStatusActive", hasSize(6)); } @Test diff --git a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsBuiltControllerFilteringIT.java b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsBuiltControllerFilteringIT.java index f1a90cae8c..951fe3cec9 100644 --- a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsBuiltControllerFilteringIT.java +++ b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsBuiltControllerFilteringIT.java @@ -26,6 +26,7 @@ import org.eclipse.tractusx.traceability.integration.common.support.AlertsSupport; import org.eclipse.tractusx.traceability.integration.common.support.AssetsSupport; import org.eclipse.tractusx.traceability.integration.common.support.InvestigationsSupport; +import org.eclipse.tractusx.traceability.qualitynotification.infrastructure.model.NotificationSideBaseEntity; import org.jose4j.lang.JoseException; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -34,6 +35,8 @@ import static io.restassured.RestAssured.given; import static org.eclipse.tractusx.traceability.common.security.JwtRole.ADMIN; +import static org.eclipse.tractusx.traceability.qualitynotification.infrastructure.model.NotificationSideBaseEntity.RECEIVER; +import static org.eclipse.tractusx.traceability.qualitynotification.infrastructure.model.NotificationSideBaseEntity.SENDER; import static org.eclipse.tractusx.traceability.qualitynotification.infrastructure.model.NotificationStatusBaseEntity.ACCEPTED; import static org.eclipse.tractusx.traceability.qualitynotification.infrastructure.model.NotificationStatusBaseEntity.ACKNOWLEDGED; import static org.eclipse.tractusx.traceability.qualitynotification.infrastructure.model.NotificationStatusBaseEntity.CANCELED; @@ -353,7 +356,7 @@ void givenAssetsWithAlerts_whenGetAssetsWithActiveAlertCountFilter_thenReturnPro alertsSupport.storeAlertWithStatusAndAssets(CANCELED, List.of(assetAsBuilt), null); alertsSupport.storeAlertWithStatusAndAssets(CLOSED, List.of(assetAsBuilt), null); - final String filter = "qualityAlertIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,6,AND"; + final String filter = "receivedQualityAlertIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,6,AND"; // When given() @@ -385,7 +388,7 @@ void givenAssetsWithAlerts_whenGetAssetsWithActiveAlertCountFilter2_thenReturnPr alertsSupport.storeAlertWithStatusAndAssets(CANCELED, List.of(assetAsBuilt), null); alertsSupport.storeAlertWithStatusAndAssets(CLOSED, List.of(assetAsBuilt), null); - final String filter = "qualityAlertIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,2,AND"; + final String filter = "receivedQualityAlertIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,2,AND"; // When given() @@ -402,20 +405,60 @@ void givenAssetsWithAlerts_whenGetAssetsWithActiveAlertCountFilter2_thenReturnPr } @Test - void givenAssetsWithInvestigations_whenGetAssetsWithActiveInvestigationCountFilter_thenReturnProperAssets() throws JoseException { + void givenAssetsWithInvestigations_whenGetAssetsWithActiveSentInvestigationCountFilter_thenReturnProperAssets() throws JoseException { // Given assetsSupport.defaultAssetsStored(); AssetAsBuiltEntity assetAsBuilt = jpaAssetAsBuiltRepository.findById("urn:uuid:d387fa8e-603c-42bd-98c3-4d87fef8d2bb").orElseThrow(); - investigationsSupport.storeInvestigationWithStatusAndAssets(CREATED, List.of(assetAsBuilt), null); - investigationsSupport.storeInvestigationWithStatusAndAssets(SENT, List.of(assetAsBuilt), null); - investigationsSupport.storeInvestigationWithStatusAndAssets(RECEIVED, List.of(assetAsBuilt), null); - investigationsSupport.storeInvestigationWithStatusAndAssets(ACKNOWLEDGED, List.of(assetAsBuilt), null); - investigationsSupport.storeInvestigationWithStatusAndAssets(ACCEPTED, List.of(assetAsBuilt), null); - investigationsSupport.storeInvestigationWithStatusAndAssets(DECLINED, List.of(assetAsBuilt), null); - investigationsSupport.storeInvestigationWithStatusAndAssets(CANCELED, List.of(assetAsBuilt), null); - investigationsSupport.storeInvestigationWithStatusAndAssets(CLOSED, List.of(assetAsBuilt), null); + investigationsSupport.storeInvestigationWithStatusAndAssets(CREATED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(SENT, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(RECEIVED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(ACKNOWLEDGED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(ACCEPTED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(DECLINED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(CANCELED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(CLOSED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(CREATED, List.of(assetAsBuilt), null, RECEIVER); + + final String filter = "sentQualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,6,AND"; + + + // When + given() + .header(oAuth2Support.jwtAuthorization(ADMIN)) + .contentType(ContentType.JSON) + .when() + .param("filter", filter) + .get("/api/assets/as-built") + .then() + .statusCode(200) + .assertThat() + .body("totalItems", equalTo(1)); + } - final String filter = "qualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,6,AND"; + @Test + void givenAssetsWithInvestigations_whenGetAssetsWithActiveReceivedInvestigationCountFilter_thenReturnProperAssets() throws JoseException { + // Given + assetsSupport.defaultAssetsStored(); + AssetAsBuiltEntity assetAsBuilt = jpaAssetAsBuiltRepository.findById("urn:uuid:d387fa8e-603c-42bd-98c3-4d87fef8d2bb").orElseThrow(); + investigationsSupport.storeInvestigationWithStatusAndAssets(CREATED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(SENT, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(RECEIVED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(ACKNOWLEDGED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(ACCEPTED, List.of(assetAsBuilt), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(DECLINED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(CANCELED, List.of(assetAsBuilt), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(CLOSED, List.of(assetAsBuilt), null, SENDER); + + investigationsSupport.storeInvestigationWithStatusAndAssets(CREATED, List.of(assetAsBuilt), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(SENT, List.of(assetAsBuilt), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(RECEIVED, List.of(assetAsBuilt), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(ACKNOWLEDGED, List.of(assetAsBuilt), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(ACCEPTED, List.of(assetAsBuilt), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(DECLINED, List.of(assetAsBuilt), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(CANCELED, List.of(assetAsBuilt), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(CLOSED, List.of(assetAsBuilt), null, RECEIVER); + + final String filter = "receivedQualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,7,AND"; // When @@ -447,7 +490,7 @@ void givenAssetsWithInvestigations_whenGetAssetsWithActiveInvestigationCountFilt investigationsSupport.storeInvestigationWithStatusAndAssets(CANCELED, List.of(assetAsBuilt), null); investigationsSupport.storeInvestigationWithStatusAndAssets(CLOSED, List.of(assetAsBuilt), null); - final String filter = "qualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,2,AND"; + final String filter = "receivedQualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,2,AND"; // When @@ -479,7 +522,7 @@ void givenAssetsWithInvestigations_whenGetAssetsWithActiveInvestigationCountFilt investigationsSupport.storeInvestigationWithStatusAndAssets(CANCELED, List.of(assetAsBuilt), null); investigationsSupport.storeInvestigationWithStatusAndAssets(CLOSED, List.of(assetAsBuilt), null); - final String filter = "qualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,0,AND"; + final String filter = "receivedQualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,0,AND"; // When @@ -511,7 +554,7 @@ void givenAssetsWithInvestigations_whenGetAssetsWithActiveInvestigationCountFilt investigationsSupport.storeInvestigationWithStatusAndAssets(CANCELED, List.of(assetAsBuilt), null); investigationsSupport.storeInvestigationWithStatusAndAssets(CLOSED, List.of(assetAsBuilt), null); - final String filter = "qualityAlertIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,0,AND"; + final String filter = "receivedQualityAlertIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,0,AND"; // When @@ -543,9 +586,52 @@ void givenAssetsWithInvestigations_whenGetAssetsWithActiveInvestigationCountFilt investigationsSupport.storeInvestigationWithStatusAndAssets(CANCELED, List.of(assetAsBuilt), null); investigationsSupport.storeInvestigationWithStatusAndAssets(CLOSED, List.of(assetAsBuilt), null); - final String filter1 = "qualityAlertIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,0,AND"; - final String filter2 = "qualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,2,AND"; + final String filter1 = "receivedQualityAlertIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,0,AND"; + final String filter2 = "receivedQualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,2,AND"; + + + // When + given() + .header(oAuth2Support.jwtAuthorization(ADMIN)) + .contentType(ContentType.JSON) + .when() + .param("filter", filter1) + .param("filter", filter2) + .get("/api/assets/as-built") + .then() + .statusCode(200) + .assertThat() + .body("totalItems", equalTo(1)); + } + + @Test + void givenAssetsWithInvestigations_whenGetAssetsWithActiveInvestigationCountFilter6_thenReturnProperAssets() throws JoseException { + // Given + assetsSupport.defaultAssetsStored(); + AssetAsBuiltEntity assetAsBuilt = jpaAssetAsBuiltRepository.findById("urn:uuid:d387fa8e-603c-42bd-98c3-4d87fef8d2bb").orElseThrow(); + AssetAsBuiltEntity assetAsBuilt1 = jpaAssetAsBuiltRepository.findById("urn:uuid:7fa65f10-9dc1-49fe-818a-09c7313a4562").orElseThrow(); + + alertsSupport.storeAlertWithStatusAndAssets(CREATED, List.of(assetAsBuilt, assetAsBuilt1), null, SENDER); + alertsSupport.storeAlertWithStatusAndAssets(SENT, List.of(assetAsBuilt1), null, SENDER); + + investigationsSupport.storeInvestigationWithStatusAndAssets(CREATED, List.of(assetAsBuilt, assetAsBuilt1), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(CREATED, List.of(assetAsBuilt, assetAsBuilt1), null, SENDER); + investigationsSupport.storeInvestigationWithStatusAndAssets(SENT, List.of(assetAsBuilt1), null, SENDER); + + alertsSupport.storeAlertWithStatusAndAssets(CREATED, List.of(assetAsBuilt, assetAsBuilt1), null, RECEIVER); + alertsSupport.storeAlertWithStatusAndAssets(SENT, List.of(assetAsBuilt), null, RECEIVER); + alertsSupport.storeAlertWithStatusAndAssets(SENT, List.of(assetAsBuilt), null, RECEIVER); + + investigationsSupport.storeInvestigationWithStatusAndAssets(CREATED, List.of(assetAsBuilt, assetAsBuilt1), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(CREATED, List.of(assetAsBuilt, assetAsBuilt1), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(SENT, List.of(assetAsBuilt), null, RECEIVER); + investigationsSupport.storeInvestigationWithStatusAndAssets(SENT, List.of(assetAsBuilt), null, RECEIVER); + + final String filter1 = "receivedQualityAlertIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,3,AND"; + final String filter2 = "receivedQualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,4,AND"; + final String filter3 = "sentQualityAlertIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,1,AND"; + final String filter4 = "sentQualityInvestigationIdsInStatusActive,NOTIFICATION_COUNT_EQUAL,2,AND"; // When given() @@ -554,6 +640,8 @@ void givenAssetsWithInvestigations_whenGetAssetsWithActiveInvestigationCountFilt .when() .param("filter", filter1) .param("filter", filter2) + .param("filter", filter3) + .param("filter", filter4) .get("/api/assets/as-built") .then() .statusCode(200) diff --git a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsPlannedControllerByIdIT.java b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsPlannedControllerByIdIT.java index 9fb9bc8e15..00e53ece94 100644 --- a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsPlannedControllerByIdIT.java +++ b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/assets/AssetAsPlannedControllerByIdIT.java @@ -49,7 +49,6 @@ import static org.eclipse.tractusx.traceability.qualitynotification.infrastructure.model.NotificationStatusBaseEntity.SENT; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; import static org.junit.jupiter.params.provider.Arguments.arguments; class AssetAsPlannedControllerByIdIT extends IntegrationTestSpecification { @@ -99,7 +98,7 @@ void givenAlertsForAsset_whenCallAssetById_thenReturnProperCount() throws JoseEx .log().all() .statusCode(200) .assertThat() - .body("qualityAlertIdsInStatusActive", hasSize(6)); + .body("receivedQualityAlertIdsInStatusActive", hasSize(6)); } @Test @@ -125,7 +124,7 @@ void givenInvestigationsForAsset_whenCallAssetById_thenReturnProperCount() throw .then() .statusCode(200) .assertThat() - .body("qualityInvestigationIdsInStatusActive", hasSize(6)); + .body("receivedQualityInvestigationIdsInStatusActive", hasSize(6)); } @Test diff --git a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/common/support/AlertsSupport.java b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/common/support/AlertsSupport.java index a19cf40f2d..10a2f2b20a 100644 --- a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/common/support/AlertsSupport.java +++ b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/common/support/AlertsSupport.java @@ -60,11 +60,15 @@ public Long defaultReceivedAlertStored() { } public Long storeAlertWithStatusAndAssets(NotificationStatusBaseEntity status, List assetsAsBuilt, List assetsAsPlanned) { + return storeAlertWithStatusAndAssets(status, assetsAsBuilt, assetsAsPlanned, NotificationSideBaseEntity.RECEIVER); + } + + public Long storeAlertWithStatusAndAssets(NotificationStatusBaseEntity status, List assetsAsBuilt, List assetsAsPlanned, NotificationSideBaseEntity side) { AlertEntity entity = AlertEntity.builder() .assets(Collections.emptyList()) .bpn("BPNL00000003AXS3") .status(status) - .side(NotificationSideBaseEntity.RECEIVER) + .side(side) .createdDate(Instant.now()) .build(); Long alertId = storedAlert(entity); diff --git a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/common/support/InvestigationsSupport.java b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/common/support/InvestigationsSupport.java index e1fb906b3c..55c18e7a36 100644 --- a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/common/support/InvestigationsSupport.java +++ b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/common/support/InvestigationsSupport.java @@ -56,11 +56,15 @@ public Long defaultReceivedInvestigationStored() { } public Long storeInvestigationWithStatusAndAssets(NotificationStatusBaseEntity status, List assetsAsBuilt, List assetsAsPlanned) { + return storeInvestigationWithStatusAndAssets(status, assetsAsBuilt, assetsAsPlanned, NotificationSideBaseEntity.RECEIVER); + } + + public Long storeInvestigationWithStatusAndAssets(NotificationStatusBaseEntity status, List assetsAsBuilt, List assetsAsPlanned, NotificationSideBaseEntity side) { InvestigationEntity entity = InvestigationEntity.builder() .assets(Collections.emptyList()) .bpn("BPNL00000003AXS3") .status(status) - .side(NotificationSideBaseEntity.RECEIVER) + .side(side) .createdDate(Instant.now()) .build(); Long alertId = storedInvestigation(entity); diff --git a/tx-models/src/main/java/assets/response/base/AssetBaseResponse.java b/tx-models/src/main/java/assets/response/base/AssetBaseResponse.java index 7e6b1d5dc4..7c1f8b8821 100644 --- a/tx-models/src/main/java/assets/response/base/AssetBaseResponse.java +++ b/tx-models/src/main/java/assets/response/base/AssetBaseResponse.java @@ -76,7 +76,11 @@ public class AssetBaseResponse { private String classification; private List detailAspectModels; @ApiModelProperty(dataType = "List", example = "1") - private List qualityAlertIdsInStatusActive; + private List sentQualityAlertIdsInStatusActive; + @ApiModelProperty(dataType = "List", example = "1") + private List receivedQualityAlertIdsInStatusActive; + @ApiModelProperty(dataType = "List", example = "2") + private List sentQualityInvestigationIdsInStatusActive; @ApiModelProperty(dataType = "List", example = "2") - private List qualityInvestigationIdsInStatusActive; + private List receivedQualityInvestigationIdsInStatusActive; }