From 3cf8a65a2c311b93213943a15253f74fa2cf2d21 Mon Sep 17 00:00:00 2001 From: Ingo Sternberg Date: Sun, 14 Jul 2024 23:45:08 +0200 Subject: [PATCH 1/2] feat: add mocked facility names and cases Signed-off-by: Ingo Sternberg #257 --- prisma/seed.ts | 379 +++++++++++++++++++++++++++---------------------- 1 file changed, 213 insertions(+), 166 deletions(-) diff --git a/prisma/seed.ts b/prisma/seed.ts index 85c27369..8e2775a3 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,188 +1,235 @@ import { Prisma, PrismaClient } from '@prisma/client'; -import caseData from './demo_data/CASE-EXAMPLE.json'; +import { faker } from '@faker-js/faker'; + +import { ECasePriority, ECaseStatus, ECaseType } from '../libs/cases/shared/models/src'; import pump2envData from './demo_data/PUMP-002_Environment_20240422-220000000_20240423-220000000.json'; import pump2pumpData from './demo_data/PUMP-002_PumpData_20240422-220000000_20240423-220000000.json'; - import pump10envData from './demo_data/PUMP-010_Environment_20240422-220000000_20240423-220000000.json'; import pump10pumpData from './demo_data/PUMP-010_PumpData_20240422-220000000_20240423-220000000.json'; const prisma = new PrismaClient(); -const facilityNames = [ - { name: 'Facility 1', assetId: 'Facility1', description: 'This is facility 1', typeId: 'pump', indicatorMsg: 'Everything works fine' }, - { name: 'Facility 2', assetId: 'Facility2', description: 'This is facility 2', typeId: 'pump', indicatorMsg: 'Everything works fine' }, - { name: 'Facility 3', assetId: 'Facility3', description: 'This is facility 3', typeId: 'pump', indicatorMsg: 'Everything works fine' }, - { name: 'Facility 4', assetId: 'Facility4', description: 'This is facility 4', typeId: 'pump', indicatorMsg: 'Everything works fine' }, - { name: 'Facility 5', assetId: 'Facility5', description: 'This is facility 5', typeId: 'pump', indicatorMsg: 'Everything works fine' }, - { name: 'Facility 6', assetId: 'Facility6', description: 'This is facility 6', typeId: 'pump', indicatorMsg: 'Everything works fine' }, - { name: 'Facility 7', assetId: 'Facility7', description: 'This is facility 7', typeId: 'pump', indicatorMsg: 'Everything works fine' }, - { name: 'Facility 8', assetId: 'Facility8', description: 'This is facility 8', typeId: 'pump', indicatorMsg: 'Everything works fine' }, - { name: 'Facility 9', assetId: 'Facility9', description: 'This is facility 9', typeId: 'pump', indicatorMsg: 'Everything works fine' }, +const facilityConst = [ + { name: 'totally legal waste disposal', description: 'We ensure environmentally responsible and completely legitimate waste disposal services.' }, + { name: 'Dribble & Drizzle Station', description: 'A captivating large aquarium located in the Computer Science Department building.' }, + { name: 'Waste Water Processing', description: 'Advanced facility dedicated to efficient and eco-friendly waste water treatment.' }, + { name: 'Submarine Solutions', description: 'Cutting-edge submarine testing facility focused on innovation and safety.' }, + { name: 'Gush & Flush' , description: 'Specialized overflow management services in Truth or Consequences, ensuring smooth and safe water flow.' }, + { name: 'Well, Well, Well', description: 'State-of-the-art water pump facility designed to provide sustainable and reliable access to clean water.' }, + { name: 'Drop Zone', description: 'Efficient and reliable water delivery service ensuring residents have access to clean water when they need it most.' }, + { name: 'H2-Whoa Facility', description: ' A high-tech facility known for its impressive and groundbreaking water processing solutions.' }, + { name: 'Bucket Brigade', description: 'Reliable emergency water supply service ensuring access to water during critical situations.' }, ]; +faker.seed(1234); + +const facilities = facilityConst.map((facility, index) => { + return { + name: facility.name, + assetId: faker.string.uuid(), + description: facility.description, + typeId: 'pump', + indicatorMsg: 'Everything works fine', + }; +}); + +const CasesConst = [ + { title: 'Pump Repair Needed', description: 'The pump is damaged and is operating at a fraction of its original capacity' }, + { title: 'Overflow Alarm', description: 'The overflow sensor is malfunctioning and causing false alarms' }, + { title: 'Leak Detection', description: 'A significant leak has been detected in the main pipeline' }, + { title: 'Pressure Drop', description: 'Sudden pressure drop in the system is affecting water distribution' }, + { title: 'Filter Replacement', description: 'The water filters are clogged and need immediate replacement' }, + { title: 'Valve Malfunction', description: 'A critical valve is stuck and preventing proper water flow' }, + { title: 'Contamination Alert', description: 'Water tests have shown signs of contamination in the supply' }, + { title: 'Pump Overheating', description: 'The pump is overheating due to continuous operation and insufficient cooling' }, + { title: 'Sensor Calibration', description: 'Sensors need recalibration to ensure accurate readings' }, + { title: 'Electrical Fault', description: 'An electrical fault has caused a shutdown of the main control panel' }, + { title: 'Water Hammer Issue', description: 'Experiencing water hammer effect causing pipe vibrations and noise' }, + { title: 'System Upgrade', description: 'The system requires an upgrade to handle increased water demand' }, + { title: 'Backup Generator Failure', description: 'The backup generator has failed and needs urgent repair' }, + { title: 'Water Quality Testing', description: 'Routine water quality testing has detected abnormal levels of contaminants' }, + { title: 'Flow Rate Anomaly', description: 'Unexplained fluctuations in water flow rate require investigation' }, +]; + +// still requires the assetId to be added +const cases = CasesConst.map((caseItem, index) => { + return { + handle: 'AA-' + faker.number.int({ min: 1000, max: 9999 }), + dueDate: faker.date.soon({ days: 30}), + status: ECaseStatus.OPEN, + title: caseItem.title, + description: caseItem.description, + type: faker.helpers.enumValue(ECaseType), + source: 'Internal System ' + faker.number.int({min: 1, max: 10}), + priority: faker.helpers.enumValue(ECasePriority), + createdBy: faker.internet.email(), + eTag: faker.string.alphanumeric(10), + }; +}); + async function seedSingleFacility({ - name, - assetId, - description, - typeId, - index, - indicatorMsg, -}: { - name: string; - assetId: string; - description: string; - typeId: string; - index: number; + name, + assetId, + description, + typeId, + index, + indicatorMsg, + }: { + name: string; + assetId: string; + description: string; + typeId: string; + index: number; indicatorMsg: string; }) { - const pumpData = index % 2 === 0 ? pump2pumpData : pump10pumpData; - const envData = index % 2 === 0 ? pump2envData : pump10envData; - - const asset = await prisma.asset.create({ - data: { - assetId, - name, - typeId, - description, + const pumpData = index % 2 === 0 ? pump2pumpData : pump10pumpData; + const envData = index % 2 === 0 ? pump2envData : pump10envData; + + const asset = await prisma.asset.create({ + data: { + assetId, + name, + typeId, + description, indicatorMsg, - location: { - create: { - latitude: 37.7749, - longitude: 122.4194, - country: 'United States', - region: 'California', - streetAddress: '123 Main St', - postalCode: '94105', - locality: 'San Francisco', - }, - }, - variables: {}, - }, - }); - - const tsItemPumpData = await prisma.timeSeriesItem.create({ - data: { - assetId: asset.assetId, - propertySetName: 'PumpData', - variables: [ - { - name: 'Flow', - unit: 'l/s', - }, - { - name: 'MotorCurrent', - unit: 'V', - }, - { - name: 'PressureIn', - unit: 'hPa', - }, - { - name: 'PressureOut', - unit: 'hPa', - }, - { - name: 'StuffingBoxTemperature', - unit: '°C', - }, - ], - }, - }); - - const newPumpData = pumpData.map((data: any) => { - return { - time: new Date(data._time), - - timeSeriesItemAssetId: tsItemPumpData.assetId, - timeSeriesItemPropertySetName: tsItemPumpData.propertySetName, - - data: { - motorCurrent: data.MotorCurrent, - pressureOut: data.PressureOut, - stuffingBoxTemperature: data.StuffingBoxTemperature, - pressureIn: data.PressureIn, - flow: data.Flow, - } as Prisma.JsonObject, - }; - }); - - const tSItemEnv = await prisma.timeSeriesItem.create({ - data: { - assetId: asset.assetId, - propertySetName: 'Environment', - variables: [ - { - name: 'Humidity', - unit: '%', - }, - { - name: 'Pressure', - unit: 'kPa', - }, - { - name: 'Temperature', - unit: '°C', - }, - ], - }, - }); - - const newEnvData = envData.map((data: any) => { - return { - time: new Date(data._time), - - timeSeriesItemAssetId: asset.assetId, - timeSeriesItemPropertySetName: tSItemEnv.propertySetName, - - data: { - pressureQc: data.Pressure_qc, - temperature: data.Temperature, - temperatureQc: data.Temperature_qc, - humidityQc: data.Humidity_qc, - humidity: data.Humidity, - pressure: data.Pressure, - } as Prisma.JsonObject, - }; - }); - - // Seed database with timeseries data - await prisma.timeSeriesDataItem.createMany({ - data: [newPumpData, newEnvData].flat(), - }); - - // create new case data from JSON file - const newCaseData = caseData.map((data: any) => { - return { - handle: data.handle, - dueDate: new Date(data.dueDate), // See https://stackoverflow.com/a/52823241 - title: data.title, - type: data.type, - status: data.status, - indicatorMsg: data.indicatorMsg, - description: data.description, - source: data.source, - priority: data.priority, - createdBy: data.createdBy, - eTag: data.eTag, - assetAssetId: asset.assetId, - }; - }); - - // Seed database with case data - await prisma.case.createMany({ - data: newCaseData, - }); + location: { + create: { + latitude: faker.location.latitude(), + longitude: faker.location.longitude(), + country: faker.location.country(), + region: faker.location.state(), + streetAddress: faker.location.streetAddress(), + postalCode: faker.location.zipCode(), + locality: faker.location.city(), + }, + }, + variables: {}, + }, + }); + + const tsItemPumpData = await prisma.timeSeriesItem.create({ + data: { + assetId: asset.assetId, + propertySetName: 'PumpData', + variables: [ + { + name: 'Flow', + unit: 'l/s', + }, + { + name: 'MotorCurrent', + unit: 'V', + }, + { + name: 'PressureIn', + unit: 'hPa', + }, + { + name: 'PressureOut', + unit: 'hPa', + }, + { + name: 'StuffingBoxTemperature', + unit: '°C', + }, + ], + }, + }); + + const newPumpData = pumpData.map((data: any) => { + return { + time: new Date(data._time), + + timeSeriesItemAssetId: tsItemPumpData.assetId, + timeSeriesItemPropertySetName: tsItemPumpData.propertySetName, + + data: { + MotorCurrent: data.MotorCurrent, + PressureOut: data.PressureOut, + StuffingBoxTemperature: data.StuffingBoxTemperature, + PressureIn: data.PressureIn, + Flow: data.Flow, + } as Prisma.JsonObject, + }; + }); + + const tSItemEnv = await prisma.timeSeriesItem.create({ + data: { + assetId: asset.assetId, + propertySetName: 'Environment', + variables: [ + { + name: 'Humidity', + unit: '%', + }, + { + name: 'Pressure', + unit: 'kPa', + }, + { + name: 'Temperature', + unit: '°C', + }, + ], + }, + }); + + const newEnvData = envData.map((data: any) => { + return { + time: new Date(data._time), + + timeSeriesItemAssetId: asset.assetId, + timeSeriesItemPropertySetName: tSItemEnv.propertySetName, + + data: { + PressureQc: data.Pressure_qc, + Temperature: data.Temperature, + TemperatureQc: data.Temperature_qc, + HumidityQc: data.Humidity_qc, + Humidity: data.Humidity, + Pressure: data.Pressure, + } as Prisma.JsonObject, + }; + }); + + // Seed database with timeseries data + await prisma.timeSeriesDataItem.createMany({ + data: [newPumpData, newEnvData].flat(), + }); + + // create new case data from JSON file + const caseData = faker.helpers.arrayElements(cases, { min: 0, max: 2 }) + const newCaseData = caseData.map((data: any) => { + return { + handle: data.handle, + dueDate: data.dueDate, + title: data.title, + type: data.type, + status: data.status, + description: data.description, + source: data.source, + priority: data.priority, + createdBy: data.createdBy, + eTag: data.eTag, + assetAssetId: asset.assetId, + }; + }); + + // Seed database with case data + await prisma.case.createMany({ + data: newCaseData, + }); } async function main() { - // Seed database with facility data - for (let i = 0; i < facilityNames.length; i++) { - await seedSingleFacility({ ...facilityNames[i], index: i }); - } + // Seed database with facility data + for (let i = 0; i < facilities.length; i++) { + await seedSingleFacility({ ...facilities[i], index: i }); + } } main().catch((e) => { - console.error(e); + console.error(e); - process.exit(1); + process.exit(1); }); From adab3cb6a1f257f778e6cc538801794c231195d1 Mon Sep 17 00:00:00 2001 From: Ingo Sternberg Date: Mon, 15 Jul 2024 18:03:15 +0200 Subject: [PATCH 2/2] feat: mock cases better Signed-off-by: Ingo Sternberg #257 --- prisma/seed.ts | 57 ++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/prisma/seed.ts b/prisma/seed.ts index 8e2775a3..440a5f70 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,7 +1,6 @@ import { Prisma, PrismaClient } from '@prisma/client'; import { faker } from '@faker-js/faker'; -import { ECasePriority, ECaseStatus, ECaseType } from '../libs/cases/shared/models/src'; import pump2envData from './demo_data/PUMP-002_Environment_20240422-220000000_20240423-220000000.json'; import pump2pumpData from './demo_data/PUMP-002_PumpData_20240422-220000000_20240423-220000000.json'; import pump10envData from './demo_data/PUMP-010_Environment_20240422-220000000_20240423-220000000.json'; @@ -10,18 +9,19 @@ import pump10pumpData from './demo_data/PUMP-010_PumpData_20240422-220000000_202 const prisma = new PrismaClient(); const facilityConst = [ - { name: 'totally legal waste disposal', description: 'We ensure environmentally responsible and completely legitimate waste disposal services.' }, { name: 'Dribble & Drizzle Station', description: 'A captivating large aquarium located in the Computer Science Department building.' }, { name: 'Waste Water Processing', description: 'Advanced facility dedicated to efficient and eco-friendly waste water treatment.' }, { name: 'Submarine Solutions', description: 'Cutting-edge submarine testing facility focused on innovation and safety.' }, { name: 'Gush & Flush' , description: 'Specialized overflow management services in Truth or Consequences, ensuring smooth and safe water flow.' }, { name: 'Well, Well, Well', description: 'State-of-the-art water pump facility designed to provide sustainable and reliable access to clean water.' }, + { name: 'totally legal waste disposal', description: 'We ensure environmentally responsible and completely legitimate waste disposal services.' }, { name: 'Drop Zone', description: 'Efficient and reliable water delivery service ensuring residents have access to clean water when they need it most.' }, { name: 'H2-Whoa Facility', description: ' A high-tech facility known for its impressive and groundbreaking water processing solutions.' }, { name: 'Bucket Brigade', description: 'Reliable emergency water supply service ensuring access to water during critical situations.' }, + { name: "Pump It Up Station", description: "A modern facility dedicated to high-efficiency water pumping and distribution to urban and rural areas." } ]; -faker.seed(1234); +faker.seed(123); const facilities = facilityConst.map((facility, index) => { return { @@ -34,34 +34,39 @@ const facilities = facilityConst.map((facility, index) => { }); const CasesConst = [ - { title: 'Pump Repair Needed', description: 'The pump is damaged and is operating at a fraction of its original capacity' }, - { title: 'Overflow Alarm', description: 'The overflow sensor is malfunctioning and causing false alarms' }, - { title: 'Leak Detection', description: 'A significant leak has been detected in the main pipeline' }, - { title: 'Pressure Drop', description: 'Sudden pressure drop in the system is affecting water distribution' }, - { title: 'Filter Replacement', description: 'The water filters are clogged and need immediate replacement' }, - { title: 'Valve Malfunction', description: 'A critical valve is stuck and preventing proper water flow' }, - { title: 'Contamination Alert', description: 'Water tests have shown signs of contamination in the supply' }, - { title: 'Pump Overheating', description: 'The pump is overheating due to continuous operation and insufficient cooling' }, - { title: 'Sensor Calibration', description: 'Sensors need recalibration to ensure accurate readings' }, - { title: 'Electrical Fault', description: 'An electrical fault has caused a shutdown of the main control panel' }, - { title: 'Water Hammer Issue', description: 'Experiencing water hammer effect causing pipe vibrations and noise' }, - { title: 'System Upgrade', description: 'The system requires an upgrade to handle increased water demand' }, - { title: 'Backup Generator Failure', description: 'The backup generator has failed and needs urgent repair' }, - { title: 'Water Quality Testing', description: 'Routine water quality testing has detected abnormal levels of contaminants' }, - { title: 'Flow Rate Anomaly', description: 'Unexplained fluctuations in water flow rate require investigation' }, + { title: 'Pump Repair Needed', description: 'The pump is damaged and is operating at a fraction of its original capacity', type: 'INCIDENT', priority: 'HIGH' }, + { title: 'Overflow Alarm', description: 'The overflow sensor is malfunctioning and causing false alarms', type: 'INCIDENT', priority: 'MEDIUM' }, + { title: 'Leak Detection', description: 'A significant leak has been detected in the main pipeline', type: 'INCIDENT', priority: 'EMERGENCY' }, + { title: 'Pressure Drop', description: 'Sudden pressure drop in the system is affecting water distribution', type: 'INCIDENT', priority: 'HIGH' }, + { title: 'Filter Replacement', description: 'The water filters are clogged and need immediate replacement', type: 'INCIDENT', priority: 'EMERGENCY' }, + { title: 'Valve Malfunction', description: 'A critical valve is stuck and preventing proper water flow', type: 'INCIDENT', priority: 'HIGH' }, + { title: 'Contamination Alert', description: 'Water tests have shown signs of contamination in the supply', type: 'INCIDENT', priority: 'HIGH' }, + { title: 'Pump Overheating', description: 'The pump is overheating due to continuous operation and insufficient cooling', type: 'INCIDENT', priority: 'MEDIUM' }, + { title: 'Sensor Calibration', description: 'Sensors need recalibration to ensure accurate readings', type: 'PLANNED', priority: 'LOW' }, + { title: 'Electrical Fault', description: 'An electrical fault has caused a shutdown of the main control panel', type: 'INCIDENT', priority: 'HIGH' }, + { title: 'Water Hammer Issue', description: 'Experiencing water hammer effect causing pipe vibrations and noise', type: 'INCIDENT', priority: 'MEDIUM' }, + { title: 'System Upgrade', description: 'The system requires an upgrade to handle increased water demand', type: 'ANNOTATION', priority: 'MEDIUM' }, + { title: 'Backup Generator Failure', description: 'The backup generator has failed and needs urgent repair', type: 'INCIDENT', priority: 'EMERGENCY' }, + { title: 'Water Quality Testing', description: 'Routine water quality testing has detected abnormal levels of contaminants', type: 'ANNOTATION', priority: 'MEDIUM' }, + { title: 'Flow Rate Anomaly', description: 'Unexplained fluctuations in water flow rate require investigation', type: 'ANNOTATION', priority: 'LOW' }, + { title: 'Pipe Burst', description: 'A major pipe has burst, causing significant water loss', type: 'INCIDENT', priority: 'EMERGENCY' }, + { title: 'Pump Station Power Outage', description: 'A power outage has halted operations at the pump station', type: 'INCIDENT', priority: 'HIGH' }, + { title: 'Tank Overflow', description: 'A storage tank is overflowing due to faulty level sensors', type: 'INCIDENT', priority: 'HIGH' }, + { title: 'Unauthorized Access', description: 'There has been unauthorized access to the control system', type: 'INCIDENT', priority: 'HIGH' }, + { title: 'Maintenance Schedule', description: 'Regular maintenance is due for several system components', type: 'PLANNED', priority: 'LOW' } ]; // still requires the assetId to be added -const cases = CasesConst.map((caseItem, index) => { +let cases = CasesConst.map((caseItem, index) => { return { handle: 'AA-' + faker.number.int({ min: 1000, max: 9999 }), dueDate: faker.date.soon({ days: 30}), - status: ECaseStatus.OPEN, + status: faker.helpers.arrayElement(['OPEN', 'OPEN', 'INPROGRESS', 'DONE', 'ARCHIVED']), title: caseItem.title, description: caseItem.description, - type: faker.helpers.enumValue(ECaseType), - source: 'Internal System ' + faker.number.int({min: 1, max: 10}), - priority: faker.helpers.enumValue(ECasePriority), + type: caseItem.type, + source: faker.helpers.arrayElement(['Internal', 'External' ]) + ' System ' + faker.number.int({min: 1, max: 10}), + priority: caseItem.priority, createdBy: faker.internet.email(), eTag: faker.string.alphanumeric(10), }; @@ -197,8 +202,10 @@ async function seedSingleFacility({ data: [newPumpData, newEnvData].flat(), }); - // create new case data from JSON file - const caseData = faker.helpers.arrayElements(cases, { min: 0, max: 2 }) + // take 0-2 cases from the cases array and remove them + const caseData = faker.helpers.arrayElements(cases, { min: 0, max: 3 }) + cases = cases.filter((item) => !caseData.includes(item)); + const newCaseData = caseData.map((data: any) => { return { handle: data.handle,