From d53c66de7702e5ccd0461a866aec6d414e0b5a8d Mon Sep 17 00:00:00 2001 From: Nivetharamesh Date: Thu, 5 Jun 2025 16:40:33 +0530 Subject: [PATCH] Aisle and Simulation Product API and socket Completed --- src/api-server/Routes/productRoutes.ts | 5 +- .../builderController/v1AisleController.ts | 180 ++++++ .../v1productController.ts | 395 +++++++++++++ .../v1Routes/BuilderRoutes/V1-AisleRoutes.ts | 15 + .../v1Routes/BuilderRoutes/v1-ZoneRoutes.ts | 16 +- .../v1Routes/BuilderRoutes/v1-assetRoutes.ts | 12 +- .../v1Routes/BuilderRoutes/v1-cameraRoutes.ts | 10 +- .../BuilderRoutes/v1-environmentRoutes.ts | 8 +- .../v1Routes/BuilderRoutes/v1-linesRoutes.ts | 16 +- .../v1Routes/BuilderRoutes/v1-wallRoutes.ts | 10 +- .../SimulationRoutes/v1-ProductRoutes.ts | 24 + src/api-server/V1/v1Routes/v1-homeRoutes.ts | 10 +- .../V1/v1Routes/v1-projectRoutes.ts | 16 +- src/api-server/V1/v1Routes/v1-trashRoutes.ts | 10 +- .../vizRoutes.ts/v1-FloatWidgetRoutes.ts | 14 +- .../vizRoutes.ts/v1-TemplateRoutes.ts | 12 +- .../v1Routes/vizRoutes.ts/v1-panelRoutes.ts | 10 +- .../vizRoutes.ts/v1-widget3dRoutes.ts | 12 +- .../v1Routes/vizRoutes.ts/v1-widgetRoutes.ts | 12 +- src/api-server/app.ts | 60 +- src/shared/V1Models/Builder/AisleModel.ts | 161 ++++++ .../V1Models/Simulation/eventsDataModel.ts | 8 +- .../V1Models/Simulation/productModel.ts | 10 +- src/shared/services/builder/AisleService.ts | 154 +++++ src/shared/services/builder/assetService.ts | 2 +- src/shared/services/builder/lineService.ts | 1 - .../services/simulation/productService.ts | 298 ++++++---- .../builderController/aisle-Controller.ts | 122 ++++ .../builderController/line-Controller.ts | 1 - .../product-Controller.ts | 528 ++++++++++-------- src/socket-server/manager/manager.ts | 172 ++++-- src/socket-server/socket/events.ts | 17 +- 32 files changed, 1792 insertions(+), 529 deletions(-) create mode 100644 src/api-server/V1/v1Controllers/builderController/v1AisleController.ts create mode 100644 src/api-server/V1/v1Controllers/simulationController/v1productController.ts create mode 100644 src/api-server/V1/v1Routes/BuilderRoutes/V1-AisleRoutes.ts create mode 100644 src/api-server/V1/v1Routes/SimulationRoutes/v1-ProductRoutes.ts create mode 100644 src/shared/V1Models/Builder/AisleModel.ts create mode 100644 src/shared/services/builder/AisleService.ts create mode 100644 src/socket-server/controllers/builderController/aisle-Controller.ts diff --git a/src/api-server/Routes/productRoutes.ts b/src/api-server/Routes/productRoutes.ts index aea6a0c..beee0e0 100644 --- a/src/api-server/Routes/productRoutes.ts +++ b/src/api-server/Routes/productRoutes.ts @@ -5,6 +5,9 @@ productRouter.post("/UpsertProductOrEvent", ProductFlowService.productAdd); productRouter.get("/productData", ProductFlowService.getProductDatas); productRouter.patch("/EventDataDelete", ProductFlowService.EventDataDelete); productRouter.patch("/productDataDelete", ProductFlowService.productDataDelete); -productRouter.get("/AllProducts/:organization", ProductFlowService.AllProductDatas); +productRouter.get( + "/AllProducts/:organization", + ProductFlowService.AllProductDatas +); productRouter.patch("/productRename", ProductFlowService.productRename); export default productRouter; diff --git a/src/api-server/V1/v1Controllers/builderController/v1AisleController.ts b/src/api-server/V1/v1Controllers/builderController/v1AisleController.ts new file mode 100644 index 0000000..63d0758 --- /dev/null +++ b/src/api-server/V1/v1Controllers/builderController/v1AisleController.ts @@ -0,0 +1,180 @@ +import { Response } from "express"; +import { AuthenticatedRequest } from "../../../../shared/utils/token.ts"; +import { + DeleteAisle, + GetProjectAisles, + SetAisle, +} from "../../../../shared/services/builder/AisleService.ts"; + +export const UpsertAisleController = async ( + req: AuthenticatedRequest, + res: Response +): Promise => { + try { + const { organization, userId } = req.user || {}; + const { aisleUuid, points, type, projectId } = req.body; + if (!organization || !userId || !aisleUuid || !projectId) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const data = { + points, + type, + aisleUuid, + projectId, + organization, + userId, + }; + const result = await SetAisle(data); + switch (result.status) { + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "Aisle Not Updated": + res.status(200).json({ + message: "Aisle Not Updated", + }); + break; + case "Aisle Updated Successfully": + res.status(200).json({ + message: "Aisle Updated Successfully", + }); + break; + case "Aisle Not Created": + res.status(200).json({ + message: "Aisle Not Created", + }); + break; + case "Success": + res.status(200).json({ + message: "Aisle Created Successfully", + }); + break; + case "Aisle validation failed": + res.status(200).json({ + message: "Aisle validation failed", + }); + break; + + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + } +}; +export const DeleteAisleController = async ( + req: AuthenticatedRequest, + res: Response +): Promise => { + try { + const { organization, userId } = req.user || {}; + const { aisleUuid, projectId } = req.body; + if (!organization || !userId || !aisleUuid || !projectId) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const data = { + aisleUuid, + projectId, + organization, + userId, + }; + const result = await DeleteAisle(data); + switch (result.status) { + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "Aisle not found": + res.status(200).json({ + message: "Aisle not found", + }); + break; + case "Success": + res.status(200).json({ + message: "Aisle Deleted Successfully", + }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + } +}; +export const AllAisleController = async ( + req: AuthenticatedRequest, + res: Response +): Promise => { + try { + const { organization, userId } = req.user || {}; + const { projectId } = req.params; + if (!organization || !userId || !projectId) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const data = { + projectId, + organization, + userId, + }; + const result = await GetProjectAisles(data); + switch (result.status) { + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "Aisle not found": + res.status(200).json(result.data); + break; + case "Success": + res.status(200).json(result.data); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + } +}; diff --git a/src/api-server/V1/v1Controllers/simulationController/v1productController.ts b/src/api-server/V1/v1Controllers/simulationController/v1productController.ts new file mode 100644 index 0000000..180ad95 --- /dev/null +++ b/src/api-server/V1/v1Controllers/simulationController/v1productController.ts @@ -0,0 +1,395 @@ +import { Response } from "express"; +import { AuthenticatedRequest } from "../../../../shared/utils/token.ts"; +import { + AllProductDatas, + EventDataDelete, + getProductDatas, + productAdd, + productDataDelete, + productRename, +} from "../../../../shared/services/simulation/productService.ts"; + +export const AddProductController = async ( + req: AuthenticatedRequest, + res: Response +): Promise => { + try { + const { userId, organization } = req.user || {}; + const { productUuid, eventDatas, projectId, productName } = req.body; + + if (!req.user?.userId || !req.user?.organization) { + res.status(401).json({ message: "Unauthorized" }); + return; + } + if ( + !productUuid || + !productName || + !projectId || + !userId || + !organization + ) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await productAdd({ + productName, + productUuid, + eventDatas, + projectId, + userId, + organization, + }); + + switch (result.status) { + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "EventData updated successfully": + res.status(200).json({ + message: "EventData updated successfully", + }); + break; + case "EventData add successfully": + res.status(200).json({ + message: "EventData add successfully", + }); + break; + case "Success": + res.status(201).json({ + message: "Product created Successfully", + }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + return; + } +}; +export const GetProductEventDatas = async ( + req: AuthenticatedRequest, + res: Response +): Promise => { + try { + const { userId, organization } = req.user || {}; + const { productUuid, projectId } = req.query as { + productUuid: string; + projectId: string; + }; + + if (!req.user?.userId || !req.user?.organization) { + res.status(401).json({ message: "Unauthorized" }); + return; + } + if (!productUuid || !projectId || !userId || !organization) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await getProductDatas({ + productUuid, + projectId, + userId, + organization, + }); + + switch (result.status) { + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "Product not found": + res.status(404).json({ + message: "Product not found", + }); + break; + case "Events not found": + res.status(200).json(result.data); + break; + case "Success": + res.status(200).json(result.data); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + return; + } +}; +export const DeleteProductController = async ( + req: AuthenticatedRequest, + res: Response +): Promise => { + try { + const { userId, organization } = req.user || {}; + const { productUuid, projectId } = req.body; + + if (!req.user?.userId || !req.user?.organization) { + res.status(401).json({ message: "Unauthorized" }); + return; + } + if (!productUuid || !projectId || !userId || !organization) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await productDataDelete({ + productUuid, + projectId, + userId, + organization, + }); + + switch (result.status) { + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "Product not found": + res.status(404).json({ + message: "Product not found", + }); + break; + case "Success": + res.status(200).json({ + message: "Product Deleted Successfully", + }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + return; + } +}; +export const DeleteEventsController = async ( + req: AuthenticatedRequest, + res: Response +): Promise => { + try { + const { userId, organization } = req.user || {}; + const { productUuid, projectId, modelUuid } = req.body; + + if (!req.user?.userId || !req.user?.organization) { + res.status(401).json({ message: "Unauthorized" }); + return; + } + if (!productUuid || !projectId || !userId || !organization || !modelUuid) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await EventDataDelete({ + productUuid, + modelUuid, + projectId, + userId, + organization, + }); + + switch (result.status) { + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "Product not found": + res.status(404).json({ + message: "Product not found", + }); + break; + case "Event Delete Unsuccessful": + res.status(200).json({ + message: "Event Delete Unsuccessful", + }); + break; + case "Success": + res.status(200).json({ + message: "Events Deleted Successfully", + }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + return; + } +}; +export const ProjectBasedProductsController = async ( + req: AuthenticatedRequest, + res: Response +): Promise => { + try { + const { userId, organization } = req.user || {}; + const { projectId } = req.params; + + if (!req.user?.userId || !req.user?.organization) { + res.status(401).json({ message: "Unauthorized" }); + return; + } + if (!projectId || !userId || !organization) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await AllProductDatas({ + projectId, + userId, + organization, + }); + + switch (result.status) { + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "No products found": + res.status(200).json(result.data); + break; + case "Success": + res.status(200).json(result.data); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + return; + } +}; +export const RenameProductController = async ( + req: AuthenticatedRequest, + res: Response +): Promise => { + try { + const { userId, organization } = req.user || {}; + const { productName, productUuid, projectId } = req.body; + + if (!req.user?.userId || !req.user?.organization) { + res.status(401).json({ message: "Unauthorized" }); + return; + } + if ( + !projectId || + !userId || + !organization || + !productName || + !productUuid + ) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await productRename({ + projectId, + productName, + productUuid, + userId, + organization, + }); + + switch (result.status) { + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "Product not found": + res.status(404).json({ message: "Product not found" }); + break; + case "Rename Unsuccessful": + res.status(200).json({ message: "Product Rename Not Updated" }); + break; + case "Success": + res.status(200).json({ message: "Product Rename Successfull" }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + return; + } +}; diff --git a/src/api-server/V1/v1Routes/BuilderRoutes/V1-AisleRoutes.ts b/src/api-server/V1/v1Routes/BuilderRoutes/V1-AisleRoutes.ts new file mode 100644 index 0000000..16bd1d0 --- /dev/null +++ b/src/api-server/V1/v1Routes/BuilderRoutes/V1-AisleRoutes.ts @@ -0,0 +1,15 @@ +import express from "express"; +import { tokenValidator } from "../../../../shared/utils/token.ts"; +import { + AllAisleController, + DeleteAisleController, + UpsertAisleController, +} from "../../v1Controllers/builderController/v1AisleController.ts"; + +const V1Aisle = express.Router(); + +V1Aisle.post("/UpsertAisle", tokenValidator, UpsertAisleController); +V1Aisle.patch("/DeleteAisle", tokenValidator, DeleteAisleController); +V1Aisle.get("/Aisles/:projectId", tokenValidator, AllAisleController); + +export default V1Aisle; diff --git a/src/api-server/V1/v1Routes/BuilderRoutes/v1-ZoneRoutes.ts b/src/api-server/V1/v1Routes/BuilderRoutes/v1-ZoneRoutes.ts index 510fe16..1068e49 100644 --- a/src/api-server/V1/v1Routes/BuilderRoutes/v1-ZoneRoutes.ts +++ b/src/api-server/V1/v1Routes/BuilderRoutes/v1-ZoneRoutes.ts @@ -9,26 +9,26 @@ import { ZoneDataController, } from "../../v1Controllers/builderController/v1zoneController.ts"; -const v1Zone = express.Router(); +const V1Zone = express.Router(); -v1Zone.post("/zones", tokenValidator, CreateZoneController); -v1Zone.patch("/zones/delete", tokenValidator, DeleteZoneController); +V1Zone.post("/zones", tokenValidator, CreateZoneController); +V1Zone.patch("/zones/delete", tokenValidator, DeleteZoneController); -v1Zone.get( +V1Zone.get( "/zones/visualization/:projectId", tokenValidator, VizZoneController ); -v1Zone.get( +V1Zone.get( "/zones/:projectId/:zoneUuid", tokenValidator, ZoneDataController ); -v1Zone.get( +V1Zone.get( "/zones/panel/:projectId/:zoneUuid", tokenValidator, SingleZonePanelController ); -v1Zone.get("/zones/:projectId", tokenValidator, GetZoneController); -export default v1Zone; +V1Zone.get("/zones/:projectId", tokenValidator, GetZoneController); +export default V1Zone; diff --git a/src/api-server/V1/v1Routes/BuilderRoutes/v1-assetRoutes.ts b/src/api-server/V1/v1Routes/BuilderRoutes/v1-assetRoutes.ts index f01feba..69e5b92 100644 --- a/src/api-server/V1/v1Routes/BuilderRoutes/v1-assetRoutes.ts +++ b/src/api-server/V1/v1Routes/BuilderRoutes/v1-assetRoutes.ts @@ -7,26 +7,26 @@ import { ReplaceEventDataController, } from "../../v1Controllers/builderController/v1assetController.ts"; -const v1Asset = express.Router(); +const V1Asset = express.Router(); -v1Asset.post( +V1Asset.post( "/setAsset", tokenValidator, CreateAssetController ); -v1Asset.patch( +V1Asset.patch( "/updateFloorAssetPositions", tokenValidator, AssetUpdatePosRotController ); -v1Asset.get( +V1Asset.get( "/floorAssets/:projectId", tokenValidator, GetAssetController ); -v1Asset.patch( +V1Asset.patch( "/updateEventData", tokenValidator, ReplaceEventDataController ); -export default v1Asset; +export default V1Asset; diff --git a/src/api-server/V1/v1Routes/BuilderRoutes/v1-cameraRoutes.ts b/src/api-server/V1/v1Routes/BuilderRoutes/v1-cameraRoutes.ts index b1a1e60..3d4228b 100644 --- a/src/api-server/V1/v1Routes/BuilderRoutes/v1-cameraRoutes.ts +++ b/src/api-server/V1/v1Routes/BuilderRoutes/v1-cameraRoutes.ts @@ -6,22 +6,22 @@ import { SetNewCamera, } from "../../v1Controllers/builderController/v1cameraController.ts"; -const v1Camera = express.Router(); +const V1Camera = express.Router(); -v1Camera.post( +V1Camera.post( "/setCamera", tokenValidator, SetNewCamera ); -v1Camera.get( +V1Camera.get( "/activeCameras", tokenValidator, ActiveOnlineController ); -v1Camera.get( +V1Camera.get( "/cameras/:projectId", tokenValidator, CameraList ); -export default v1Camera; +export default V1Camera; diff --git a/src/api-server/V1/v1Routes/BuilderRoutes/v1-environmentRoutes.ts b/src/api-server/V1/v1Routes/BuilderRoutes/v1-environmentRoutes.ts index 94e2fb5..c147cb6 100644 --- a/src/api-server/V1/v1Routes/BuilderRoutes/v1-environmentRoutes.ts +++ b/src/api-server/V1/v1Routes/BuilderRoutes/v1-environmentRoutes.ts @@ -5,14 +5,14 @@ import { SetEnvironmentController, } from "../../v1Controllers/builderController/v1EnvironmentController.ts"; -const v1Environment = express.Router(); +const V1Environment = express.Router(); -v1Environment.post("/SetEnvironments", tokenValidator, SetEnvironmentController); +V1Environment.post("/SetEnvironments", tokenValidator, SetEnvironmentController); -v1Environment.get( +V1Environment.get( "/Environments/:projectId", tokenValidator, GetEnvironmentController ); -export default v1Environment; +export default V1Environment; diff --git a/src/api-server/V1/v1Routes/BuilderRoutes/v1-linesRoutes.ts b/src/api-server/V1/v1Routes/BuilderRoutes/v1-linesRoutes.ts index f3159b8..a40a6c1 100644 --- a/src/api-server/V1/v1Routes/BuilderRoutes/v1-linesRoutes.ts +++ b/src/api-server/V1/v1Routes/BuilderRoutes/v1-linesRoutes.ts @@ -9,36 +9,36 @@ import { UpdateLineController, } from "../../v1Controllers/builderController/v1LineController.ts"; -const v1Line = express.Router(); +const V1Line = express.Router(); -v1Line.post( +V1Line.post( "/lines", tokenValidator, NewLineController ); -v1Line.post( +V1Line.post( "/points", tokenValidator, UpdateLineController ); -v1Line.patch( +V1Line.patch( "/layers/delete", tokenValidator, DeleteLayerController ); -v1Line.patch( +V1Line.patch( "/lines/delete", tokenValidator, DeleteLineController ); -v1Line.patch( +V1Line.patch( "/points/delete", tokenValidator, DeleteLinePointsController ); -v1Line.get( +V1Line.get( "/lines/:projectId", tokenValidator, GetLinesController ); -export default v1Line; +export default V1Line; diff --git a/src/api-server/V1/v1Routes/BuilderRoutes/v1-wallRoutes.ts b/src/api-server/V1/v1Routes/BuilderRoutes/v1-wallRoutes.ts index 9932abf..c221150 100644 --- a/src/api-server/V1/v1Routes/BuilderRoutes/v1-wallRoutes.ts +++ b/src/api-server/V1/v1Routes/BuilderRoutes/v1-wallRoutes.ts @@ -6,21 +6,21 @@ import { WallSetup, } from "../../v1Controllers/builderController/v1wallController.ts"; -const v1Wall = express.Router(); +const V1Wall = express.Router(); -v1Wall.post( +V1Wall.post( "/walls", tokenValidator, WallSetup ); -v1Wall.patch( +V1Wall.patch( "/walls/delete", tokenValidator, WallDelete ); -v1Wall.get( +V1Wall.get( "/walls/:projectId", tokenValidator, WallGet ); -export default v1Wall; +export default V1Wall; diff --git a/src/api-server/V1/v1Routes/SimulationRoutes/v1-ProductRoutes.ts b/src/api-server/V1/v1Routes/SimulationRoutes/v1-ProductRoutes.ts new file mode 100644 index 0000000..3f577de --- /dev/null +++ b/src/api-server/V1/v1Routes/SimulationRoutes/v1-ProductRoutes.ts @@ -0,0 +1,24 @@ +import express from "express"; +import { tokenValidator } from "../../../../shared/utils/token.ts"; +import { + AddProductController, + DeleteEventsController, + DeleteProductController, + GetProductEventDatas, + ProjectBasedProductsController, + RenameProductController, +} from "../../v1Controllers/simulationController/v1productController.ts"; + +const V1Product = express.Router(); + +V1Product.post("/ProductUpsert", tokenValidator, AddProductController); +V1Product.get("/EventsByProduct", tokenValidator, GetProductEventDatas); +V1Product.patch("/DeleteEvent", tokenValidator, DeleteEventsController); +V1Product.patch("/DeleteProduct", tokenValidator, DeleteProductController); +V1Product.get( + "/ProjectProducts/:projectId", + tokenValidator, + ProjectBasedProductsController +); +V1Product.patch("/RenameProduct", tokenValidator, RenameProductController); +export default V1Product; diff --git a/src/api-server/V1/v1Routes/v1-homeRoutes.ts b/src/api-server/V1/v1Routes/v1-homeRoutes.ts index 9067e2c..a1d7538 100644 --- a/src/api-server/V1/v1Routes/v1-homeRoutes.ts +++ b/src/api-server/V1/v1Routes/v1-homeRoutes.ts @@ -6,22 +6,22 @@ import { searchTrashProjectController, } from "../../V1/v1Controllers/homeController/v1homeController.ts"; -const v1homeRoutes = express.Router(); +const V1homeRoutes = express.Router(); -v1homeRoutes.get( +V1homeRoutes.get( "/RecentlyViewed", tokenValidator, recentDataController ); -v1homeRoutes.get( +V1homeRoutes.get( "/search/searchProjects", tokenValidator, searchProjectController ); -v1homeRoutes.get( +V1homeRoutes.get( "/search/searchTrashProjects", tokenValidator, searchTrashProjectController ); -export default v1homeRoutes; +export default V1homeRoutes; diff --git a/src/api-server/V1/v1Routes/v1-projectRoutes.ts b/src/api-server/V1/v1Routes/v1-projectRoutes.ts index 7dbf1bc..e3ba3e5 100644 --- a/src/api-server/V1/v1Routes/v1-projectRoutes.ts +++ b/src/api-server/V1/v1Routes/v1-projectRoutes.ts @@ -9,34 +9,34 @@ import { } from "../../V1/v1Controllers/projectController/v1projectController.ts"; import { tokenValidator } from "../../../shared/utils/token.ts"; -const v1projectRouter = express.Router(); +const V1projectRouter = express.Router(); -v1projectRouter.post("/NewProject", tokenValidator, createProjectController); -v1projectRouter.post( +V1projectRouter.post("/NewProject", tokenValidator, createProjectController); +V1projectRouter.post( "/project/Duplicate", tokenValidator, ProjectDuplicateController ); -v1projectRouter.get( +V1projectRouter.get( "/Projects", tokenValidator, GetProjects ); -v1projectRouter.patch( +V1projectRouter.patch( "/Projects/Archive/:projectId", tokenValidator, RemoveProject ); -v1projectRouter.patch( +V1projectRouter.patch( "/Projects/:projectId", tokenValidator, updateProjectController ); -v1projectRouter.get( +V1projectRouter.get( "/Project/:projectId", tokenValidator, ViewData ); -export default v1projectRouter; +export default V1projectRouter; diff --git a/src/api-server/V1/v1Routes/v1-trashRoutes.ts b/src/api-server/V1/v1Routes/v1-trashRoutes.ts index 9353b7e..925ab66 100644 --- a/src/api-server/V1/v1Routes/v1-trashRoutes.ts +++ b/src/api-server/V1/v1Routes/v1-trashRoutes.ts @@ -6,21 +6,21 @@ import { RestoreTrash, } from "../../V1/v1Controllers/trashController/v1trashController.ts"; -const v1TrashRoutes = express.Router(); -v1TrashRoutes.get( +const V1TrashRoutes = express.Router(); +V1TrashRoutes.get( "/TrashItems", tokenValidator, GetTrashList ); -v1TrashRoutes.patch( +V1TrashRoutes.patch( "/Trash/restore", tokenValidator, RestoreTrash ); -v1TrashRoutes.patch( +V1TrashRoutes.patch( "/Trash/Delete", tokenValidator, DeleteTrashData ); -export default v1TrashRoutes; +export default V1TrashRoutes; diff --git a/src/api-server/V1/v1Routes/vizRoutes.ts/v1-FloatWidgetRoutes.ts b/src/api-server/V1/v1Routes/vizRoutes.ts/v1-FloatWidgetRoutes.ts index fd44751..140afa6 100644 --- a/src/api-server/V1/v1Routes/vizRoutes.ts/v1-FloatWidgetRoutes.ts +++ b/src/api-server/V1/v1Routes/vizRoutes.ts/v1-FloatWidgetRoutes.ts @@ -8,31 +8,31 @@ import { SingleFloatController, } from "../../v1Controllers/vizualizationController/v1floatWidgetController.ts"; -const v1FloatWidget = express.Router(); +const V1FloatWidget = express.Router(); -v1FloatWidget.post( +V1FloatWidget.post( "/floatWidget/save", tokenValidator, FloatAddController ); -v1FloatWidget.patch( +V1FloatWidget.patch( "/floatWidget/delete", tokenValidator, DeleteFloatController ); -v1FloatWidget.get( +V1FloatWidget.get( "/floatWidgets/:zoneUuid/:projectId", tokenValidator, GetFloatController ); -v1FloatWidget.get( +V1FloatWidget.get( "/floatWidget/:floatWidgetId", tokenValidator, SingleFloatController ); -v1FloatWidget.post( +V1FloatWidget.post( "/floatWidget/duplicate", tokenValidator, DuplicateFloatController ); -export default v1FloatWidget; +export default V1FloatWidget; diff --git a/src/api-server/V1/v1Routes/vizRoutes.ts/v1-TemplateRoutes.ts b/src/api-server/V1/v1Routes/vizRoutes.ts/v1-TemplateRoutes.ts index 0789c87..3facb5e 100644 --- a/src/api-server/V1/v1Routes/vizRoutes.ts/v1-TemplateRoutes.ts +++ b/src/api-server/V1/v1Routes/vizRoutes.ts/v1-TemplateRoutes.ts @@ -7,26 +7,26 @@ import { TemplateDeleteController, } from "../../v1Controllers/vizualizationController/v1templateController.ts"; -const v1Template = express.Router(); +const V1Template = express.Router(); -v1Template.post( +V1Template.post( "/template/save", tokenValidator, AddTemplateController ); -v1Template.post( +V1Template.post( "/template/toZone", tokenValidator, AddTemToZoneController ); -v1Template.get( +V1Template.get( "/template/data/:projectId", tokenValidator, GetTemplateController ); -v1Template.patch( +V1Template.patch( "/template/delete", tokenValidator, TemplateDeleteController ); -export default v1Template; +export default V1Template; diff --git a/src/api-server/V1/v1Routes/vizRoutes.ts/v1-panelRoutes.ts b/src/api-server/V1/v1Routes/vizRoutes.ts/v1-panelRoutes.ts index 2d2f95b..478bf94 100644 --- a/src/api-server/V1/v1Routes/vizRoutes.ts/v1-panelRoutes.ts +++ b/src/api-server/V1/v1Routes/vizRoutes.ts/v1-panelRoutes.ts @@ -6,22 +6,22 @@ import { DeletePanelController, } from "../../v1Controllers/vizualizationController/v1panelController.ts"; -const v1PanelRoutes = express.Router(); +const V1PanelRoutes = express.Router(); -v1PanelRoutes.post( +V1PanelRoutes.post( "/panel/save", tokenValidator, AddPanelController ); -v1PanelRoutes.patch( +V1PanelRoutes.patch( "/panel/delete", tokenValidator, DeletePanelController ); -v1PanelRoutes.patch( +V1PanelRoutes.patch( "/panel/clear", tokenValidator, ClearPanelController ); -export default v1PanelRoutes; +export default V1PanelRoutes; diff --git a/src/api-server/V1/v1Routes/vizRoutes.ts/v1-widget3dRoutes.ts b/src/api-server/V1/v1Routes/vizRoutes.ts/v1-widget3dRoutes.ts index 183b075..3a6668d 100644 --- a/src/api-server/V1/v1Routes/vizRoutes.ts/v1-widget3dRoutes.ts +++ b/src/api-server/V1/v1Routes/vizRoutes.ts/v1-widget3dRoutes.ts @@ -8,28 +8,28 @@ import { Update3DwidgetController, } from "../../v1Controllers/vizualizationController/widget3Dcontroller.ts"; -const v1Widget3d = express.Router(); +const V1Widget3d = express.Router(); -v1Widget3d.post( +V1Widget3d.post( "/widget3d/save", tokenValidator, Add3dWidgetController ); -v1Widget3d.patch( +V1Widget3d.patch( "/widget3d/update", tokenValidator, Update3DwidgetController ); -v1Widget3d.get( +V1Widget3d.get( "/widget3d/data/:zoneUuid/:projectId", tokenValidator, Get3DWidgetController ); -v1Widget3d.patch( +V1Widget3d.patch( "/widget3d/delete", tokenValidator, Delete3DwidgetController ); -export default v1Widget3d; +export default V1Widget3d; diff --git a/src/api-server/V1/v1Routes/vizRoutes.ts/v1-widgetRoutes.ts b/src/api-server/V1/v1Routes/vizRoutes.ts/v1-widgetRoutes.ts index 4d07b42..1940879 100644 --- a/src/api-server/V1/v1Routes/vizRoutes.ts/v1-widgetRoutes.ts +++ b/src/api-server/V1/v1Routes/vizRoutes.ts/v1-widgetRoutes.ts @@ -7,26 +7,26 @@ import { WidgetUpdateController, } from "../../v1Controllers/vizualizationController/v1widgetController.ts"; -const v1Widget = express.Router(); +const V1Widget = express.Router(); -v1Widget.post( +V1Widget.post( "/widget/save", tokenValidator, AddWidgetController ); -v1Widget.patch( +V1Widget.patch( "/widget/:widgetID", tokenValidator, WidgetUpdateController ); -v1Widget.get( +V1Widget.get( "/widget/data", tokenValidator, GetWidgetController ); -v1Widget.patch( +V1Widget.patch( "/widget/delete", tokenValidator, WidgetDeleteController ); -export default v1Widget; +export default V1Widget; diff --git a/src/api-server/app.ts b/src/api-server/app.ts index 7603239..927d088 100644 --- a/src/api-server/app.ts +++ b/src/api-server/app.ts @@ -22,20 +22,22 @@ import trashRouter from "./Routes/trashRoutes.ts"; import homePageRouter from "./Routes/homepageRoutes.ts"; import redis from "../shared/redis/redis.ts"; import Authrouter from "./V1/v1Routes/authRoutes.ts"; -import v1TrashRoutes from "./V1/v1Routes/v1-trashRoutes.ts"; -import v1homeRoutes from "./V1/v1Routes/v1-homeRoutes.ts"; -import v1projectRouter from "./V1/v1Routes/v1-projectRoutes.ts"; -import v1Asset from "./V1/v1Routes/BuilderRoutes/v1-assetRoutes.ts"; -import v1Camera from "./V1/v1Routes/BuilderRoutes/v1-cameraRoutes.ts"; -import v1Line from "./V1/v1Routes/BuilderRoutes/v1-linesRoutes.ts"; -import v1Wall from "./V1/v1Routes/BuilderRoutes/v1-wallRoutes.ts"; -import v1Zone from "./V1/v1Routes/BuilderRoutes/v1-ZoneRoutes.ts"; -import v1FloatWidget from "./V1/v1Routes/vizRoutes.ts/v1-FloatWidgetRoutes.ts"; -import v1PanelRoutes from "./V1/v1Routes/vizRoutes.ts/v1-panelRoutes.ts"; -import v1Template from "./V1/v1Routes/vizRoutes.ts/v1-TemplateRoutes.ts"; -import v1Widget from "./V1/v1Routes/vizRoutes.ts/v1-widgetRoutes.ts"; -import v1Widget3d from "./V1/v1Routes/vizRoutes.ts/v1-widget3dRoutes.ts"; -import v1Environment from "./V1/v1Routes/BuilderRoutes/v1-environmentRoutes.ts"; +import V1projectRouter from "./V1/v1Routes/v1-projectRoutes.ts"; +import V1TrashRoutes from "./V1/v1Routes/v1-trashRoutes.ts"; +import V1homeRoutes from "./V1/v1Routes/v1-homeRoutes.ts"; +import V1Asset from "./V1/v1Routes/BuilderRoutes/v1-assetRoutes.ts"; +import V1Camera from "./V1/v1Routes/BuilderRoutes/v1-cameraRoutes.ts"; +import V1Environment from "./V1/v1Routes/BuilderRoutes/v1-environmentRoutes.ts"; +import V1Line from "./V1/v1Routes/BuilderRoutes/v1-linesRoutes.ts"; +import V1Wall from "./V1/v1Routes/BuilderRoutes/v1-wallRoutes.ts"; +import V1Zone from "./V1/v1Routes/BuilderRoutes/v1-ZoneRoutes.ts"; +import V1FloatWidget from "./V1/v1Routes/vizRoutes.ts/v1-FloatWidgetRoutes.ts"; +import V1PanelRoutes from "./V1/v1Routes/vizRoutes.ts/v1-panelRoutes.ts"; +import V1Template from "./V1/v1Routes/vizRoutes.ts/v1-TemplateRoutes.ts"; +import V1Widget from "./V1/v1Routes/vizRoutes.ts/v1-widgetRoutes.ts"; +import V1Widget3d from "./V1/v1Routes/vizRoutes.ts/v1-widget3dRoutes.ts"; +import V1Product from "./V1/v1Routes/SimulationRoutes/v1-ProductRoutes.ts"; +import V1Aisle from "./V1/v1Routes/BuilderRoutes/V1-AisleRoutes.ts"; redis; const app = express(); app.use(cors()); @@ -72,19 +74,21 @@ app.use("/api/v1", trashRouter); app.use("/api/v1", homePageRouter); app.use("/api/V1", Authrouter); -app.use("/api/V1", v1projectRouter); -app.use("/api/V1", v1TrashRoutes); -app.use("/api/V1", v1homeRoutes); -app.use("/api/V1", v1Asset); -app.use("/api/V1", v1Camera); -app.use("/api/V1", v1Environment); -app.use("/api/V1", v1Line); -app.use("/api/V1", v1Wall); -app.use("/api/V1", v1Zone); -app.use("/api/V1", v1FloatWidget); -app.use("/api/V1", v1PanelRoutes); -app.use("/api/V1", v1Template); -app.use("/api/V1", v1Widget); -app.use("/api/V1", v1Widget3d); +app.use("/api/V1", V1projectRouter); +app.use("/api/V1", V1TrashRoutes); +app.use("/api/V1", V1homeRoutes); +app.use("/api/V1", V1Asset); +app.use("/api/V1", V1Camera); +app.use("/api/V1", V1Line); +app.use("/api/V1", V1Environment); +app.use("/api/V1", V1Wall); +app.use("/api/V1", V1Zone); +app.use("/api/V1", V1FloatWidget); +app.use("/api/V1", V1PanelRoutes); +app.use("/api/V1", V1Template); +app.use("/api/V1", V1Widget); +app.use("/api/V1", V1Widget3d); +app.use("/api/V1", V1Product); +app.use("/api/V1", V1Aisle); export default app; diff --git a/src/shared/V1Models/Builder/AisleModel.ts b/src/shared/V1Models/Builder/AisleModel.ts new file mode 100644 index 0000000..f381c37 --- /dev/null +++ b/src/shared/V1Models/Builder/AisleModel.ts @@ -0,0 +1,161 @@ +import { Schema, Document } from "mongoose"; +import MainModel from "../../connect/mongoose.ts"; +import { User } from "../Auth/userAuthModel.ts"; +import { Project } from "../Project/project-model.ts"; + +type PointTypes = "Aisle"; + +export interface Point { + pointUuid: string; + pointType: PointTypes; + position: [number, number, number]; + layer: number; +} + +const ValidAisleTypes = [ + "solid-aisle", + "dashed-aisle", + "stripped-aisle", + "dotted-aisle", + "arrow-aisle", + "arrows-aisle", + "arc-aisle", + "circle-aisle", + "junction-aisle", +] as const; + +const ValidAisleColors = [ + "gray", + "yellow", + "green", + "orange", + "blue", + "purple", + "red", + "#66FF00", + "yellow-black", + "white-black", +] as const; +type AisleTypes = + | "solid-aisle" + | "dashed-aisle" + | "stripped-aisle" + | "dotted-aisle" + | "arrow-aisle" + | "arrows-aisle" + | "arc-aisle" + | "circle-aisle" + | "junction-aisle"; + +type AisleColors = + | "gray" + | "yellow" + | "green" + | "orange" + | "blue" + | "purple" + | "red" + | "#66FF00" + | "yellow-black" + | "white-black"; + +interface ForAisle { + aisleType: AisleTypes; + aisleColor: AisleColors; +} +interface SolidAisle extends ForAisle { + aisleWidth: number; +} + +interface DashedAisle extends ForAisle { + aisleWidth: number; + dashLength: number; + gapLength: number; +} + +interface DottedAisle extends ForAisle { + dotRadius: number; + gapLength: number; +} + +interface ArrowAisle extends ForAisle { + aisleWidth: number; +} + +interface ArrowsAisle extends ForAisle { + aisleWidth: number; + aisleLength: number; + gapLength: number; +} + +interface ArcAisle extends ForAisle { + aisleWidth: number; + isFlipped: boolean; +} + +interface CircleAisle extends ForAisle { + aisleWidth: number; +} + +interface JunctionAisle extends ForAisle { + aisleWidth: number; + isFlipped: boolean; +} + +export type AisleType = + | SolidAisle + | DashedAisle + | DottedAisle + | ArrowAisle + | ArrowsAisle + | ArcAisle + | CircleAisle + | JunctionAisle; + +export interface Aisle extends Document { + aisleUuid: string; + points: [Point, Point]; + projectId: Project["_id"]; + createdBy: User["_id"]; + type: AisleType; + isArchive: boolean; +} +type Aisles = Aisle[]; +const AisleSchema: Schema = new Schema( + { + aisleUuid: { type: String, required: true }, + createdBy: { type: Schema.Types.ObjectId, ref: "User" }, + projectId: { type: Schema.Types.ObjectId, ref: "Project" }, + points: { + type: [ + { + pointUuid: String, + pointType: { type: String, enum: ["Aisle"] }, + position: [Number], + layer: Number, + }, + ], + }, + type: { + type: Object, + validate: { + validator: function (value: any) { + return ( + value && + ValidAisleTypes.includes(value.aisleType) && + ValidAisleColors.includes(value.aisleColor) + ); + }, + message: (props: any) => + `Invalid aisleType or aisleColor: ${JSON.stringify(props.value)}`, + }, + }, + isArchive: { type: Boolean, default: false }, + }, + { timestamps: true } +); + +const AisleModel = (db: any) => { + return MainModel(db, "Aisle", AisleSchema, "Aisle"); +}; +export default AisleModel; diff --git a/src/shared/V1Models/Simulation/eventsDataModel.ts b/src/shared/V1Models/Simulation/eventsDataModel.ts index 24d5739..080235a 100644 --- a/src/shared/V1Models/Simulation/eventsDataModel.ts +++ b/src/shared/V1Models/Simulation/eventsDataModel.ts @@ -1,6 +1,6 @@ import { Schema, Document } from "mongoose"; import MainModel from "../../connect/mongoose.ts"; - +import { Project } from "../Project/project-model.ts"; interface AssetEventSchema { modelUuid: string; modelName: string; @@ -130,7 +130,8 @@ interface IPointModel extends Document { position: [number]; rotation: [number]; state: string; - productId: string; + productUuid: string; + projectId: Project["_id"]; isArchive: boolean; type: "transfer" | "vehicle" | "roboticArm" | "machine" | "storageUnit"; speed: number; @@ -165,7 +166,8 @@ const BaseEventSchema = new Schema( points: { type: Schema.Types.Mixed, }, - productId: { type: String, required: true }, + projectId: { type: Schema.Types.ObjectId, ref: "Project" }, + productUuid: { type: String, required: true }, isArchive: { type: Boolean, default: false }, }, { discriminatorKey: "type", timestamps: true } diff --git a/src/shared/V1Models/Simulation/productModel.ts b/src/shared/V1Models/Simulation/productModel.ts index 4daf732..5aab68b 100644 --- a/src/shared/V1Models/Simulation/productModel.ts +++ b/src/shared/V1Models/Simulation/productModel.ts @@ -2,25 +2,27 @@ import { Schema, Document } from "mongoose"; import MainModel from "../../connect/mongoose.ts"; import { Project } from "../Project/project-model.ts"; import { Version } from "../Version/versionModel.ts"; +import { User } from "../Auth/userAuthModel.ts"; export interface Product extends Document { productName: string; - productId: string; + userId: User["_id"]; + productUuid: string; projectId: Project["_id"]; versionId: Version["_id"]; - eventsData: []; isArchive: boolean; } const ProductSchema = new Schema({ projectId: { type: Schema.Types.ObjectId, ref: "Project" }, + userId: { type: Schema.Types.ObjectId, ref: "User" }, versionId: { type: Schema.Types.ObjectId, ref: "Version" }, productName: { type: String, required: true }, - productId: { type: String, required: true }, + productUuid: { type: String, required: true }, isArchive: { type: Boolean, default: false }, }); const ProductModel = (db: string) => { - return MainModel(db, "Product", ProductSchema, "Product"); + return MainModel(db, "Products", ProductSchema, "Products"); }; export default ProductModel; diff --git a/src/shared/services/builder/AisleService.ts b/src/shared/services/builder/AisleService.ts new file mode 100644 index 0000000..3fb5f41 --- /dev/null +++ b/src/shared/services/builder/AisleService.ts @@ -0,0 +1,154 @@ +import AisleModel, { + AisleType, + Point, +} from "../../V1Models/Builder/AisleModel.ts"; +import { + existingProjectById, + existingUser, +} from "../helpers/v1projecthelperFns.ts"; +interface IAisleDatas { + userId: string; + aisleUuid: string; + points?: [Point, Point]; + type?: AisleType; + organization: string; + projectId: string; +} +interface IAisleDelete { + userId: string; + aisleUuid: string; + organization: string; + projectId: string; +} +interface IProjectAisles { + userId: string; + organization: string; + projectId: string; +} +export const SetAisle = async ( + data: IAisleDatas +): Promise<{ status: string; data?: Object }> => { + try { + const { aisleUuid, points, type, organization, projectId, userId } = data; + const UserExists = await existingUser(userId, organization); + if (!UserExists) return { status: "User not found" }; + const LivingProject = await existingProjectById( + projectId, + organization, + userId + ); + if (!LivingProject) return { status: "Project not found" }; + const ExistingAisle = await AisleModel(organization).findOne({ + aisleUuid: aisleUuid, + projectId: projectId, + isArchive: false, + }); + if (ExistingAisle) { + const UpdateAisle = await AisleModel(organization).findOneAndUpdate( + { aisleUuid: aisleUuid, projectId: projectId, isArchive: false }, + { type: type, points: points }, + { new: true, runValidators: true } + ); + if (!UpdateAisle) return { status: "Aisle Not Updated" }; + return { status: "Aisle Updated Successfully", data: UpdateAisle }; + } else { + const NewAisle = await AisleModel(organization).create({ + aisleUuid, + projectId, + type: type, + points: points, + createdBy: userId, + }); + if (!NewAisle) return { status: "Aisle Not Created" }; + return { status: "Success", data: NewAisle }; + } + } catch (error: unknown) { + if (error instanceof Error) { + if (error.name === "ValidationError") { + return { + status: "Aisle validation failed", + }; + } + return { + status: error.message, + }; + } else { + return { + status: "An unexpected error occurred", + }; + } + } +}; +export const DeleteAisle = async ( + data: IAisleDelete +): Promise<{ status: string; data?: Object }> => { + try { + const { aisleUuid, organization, projectId, userId } = data; + const UserExists = await existingUser(userId, organization); + if (!UserExists) return { status: "User not found" }; + const LivingProject = await existingProjectById( + projectId, + organization, + userId + ); + if (!LivingProject) return { status: "Project not found" }; + const ExistingAisle = await AisleModel(organization).findOne({ + aisleUuid: aisleUuid, + projectId: projectId, + isArchive: false, + }); + if (ExistingAisle) { + await AisleModel(organization).updateOne( + { aisleUuid: aisleUuid, projectId: projectId, isArchive: false }, + { isArchive: true } + ); + return { status: "Success" }; + } + return { status: "Aisle not found" }; + } catch (error: unknown) { + if (error instanceof Error) { + return { + status: error.message, + }; + } else { + return { + status: "An unexpected error occurred", + }; + } + } +}; +export const GetProjectAisles = async ( + data: IProjectAisles +): Promise<{ status: string; data?: Object }> => { + try { + const { organization, projectId, userId } = data; + const UserExists = await existingUser(userId, organization); + if (!UserExists) return { status: "User not found" }; + const LivingProject = await existingProjectById( + projectId, + organization, + userId + ); + if (!LivingProject) return { status: "Project not found" }; + const ExistingAisle = await AisleModel(organization) + .find({ + projectId: projectId, + isArchive: false, + }) + .select("aisleUuid points type"); + if (ExistingAisle) { + return { status: "Success", data: ExistingAisle }; + } + return { status: "Aisle not found", data: [] }; + } catch (error: unknown) { + if (error instanceof Error) { + return { + status: error.message, + }; + } else { + return { + status: "An unexpected error occurred", + }; + } + } +}; diff --git a/src/shared/services/builder/assetService.ts b/src/shared/services/builder/assetService.ts index 2f0145a..6323e41 100644 --- a/src/shared/services/builder/assetService.ts +++ b/src/shared/services/builder/assetService.ts @@ -288,7 +288,7 @@ export const deleteAssetModel = async ( }; } await EventsDataModel(organization).updateMany( - { modelUuid, productId: projectId }, + { modelUuid, projectId: projectId }, { $set: { isArchive: true } } ); diff --git a/src/shared/services/builder/lineService.ts b/src/shared/services/builder/lineService.ts index c3ba76d..6d3be5d 100644 --- a/src/shared/services/builder/lineService.ts +++ b/src/shared/services/builder/lineService.ts @@ -157,7 +157,6 @@ export const DeleteLayer = async ( ): Promise<{ status: string; data?: object }> => { try { const { organization, projectId, layer, userId } = data; - console.log("data: ", data); const UserExists = await existingUser(userId, organization); if (!UserExists) return { status: "User not found" }; const LivingProject = await existingProjectById( diff --git a/src/shared/services/simulation/productService.ts b/src/shared/services/simulation/productService.ts index ed58f7c..a9b36a0 100644 --- a/src/shared/services/simulation/productService.ts +++ b/src/shared/services/simulation/productService.ts @@ -5,10 +5,19 @@ import { existingProjectById, existingUser, } from "../helpers/v1projecthelperFns.ts"; - +interface IEventDatainterface { + modelUuid: string; + modelName: string; + position: [number]; + rotation: [number]; + type: string; + speed: string; + point: Mixed; + points: Mixed; +} interface Iproduct { productName: string; - productId: string; + productUuid: string; eventDatas: { modelUuid: string; modelName: string; @@ -23,22 +32,41 @@ interface Iproduct { organization: string; projectId: string; } -interface IResult { - status: string; - data?: object; +interface IProductEvent { + productUuid: string; + userId: string; + organization: string; + projectId: string; } -interface IEventDataDelete { - productId: string; +interface IDelEvent { + productUuid: string; modelUuid: string; userId: string; organization: string; projectId: string; } +interface IProjectProducts { + userId: string; + organization: string; + projectId: string; +} +interface IProductRename { + userId: string; + organization: string; + projectId: string; + productUuid: string; + productName: string; +} +interface IResult { + status: string; + data?: object; +} + export const productAdd = async (data: Iproduct): Promise => { try { const { productName, - productId, + productUuid, eventDatas, projectId, userId, @@ -52,73 +80,53 @@ export const productAdd = async (data: Iproduct): Promise => { userId ); if (!LivingProject) return { status: "Project not found" }; - const existingProduct = await ProductModel(organization).findOne({ - productId: productId, - projectId: projectId, - isArchive: false, - }); + const existingProduct = await ProductAFind( + productUuid, + projectId, + organization + ); if (existingProduct) { const existingEventData = await EventsDataModel(organization).findOne({ - productId: productId, + productUuid: productUuid, projectId: projectId, modelUuid: eventDatas.modelUuid, isArchive: false, }); if (existingEventData) { - await EventsDataModel(organization).findOneAndUpdate( - { - modelUuid: eventDatas.modelUuid, - productId: productId, - isArchive: false, - }, - { - modelUuid: eventDatas?.modelUuid, - modelName: eventDatas?.modelName, - position: eventDatas?.position, - rotation: eventDatas?.rotation, - type: eventDatas?.type, - speed: eventDatas?.speed, - point: eventDatas?.point, - points: eventDatas?.points, - } + await EventUpdateFunction( + organization, + eventDatas, + productUuid, + projectId ); return { status: "EventData updated successfully", }; } else { - await EventsDataModel(organization).create({ - productId: productId, - modelUuid: eventDatas?.modelUuid, - modelName: eventDatas?.modelName, - position: eventDatas?.position, - rotation: eventDatas?.rotation, - type: eventDatas?.type, - speed: eventDatas?.speed, - point: eventDatas?.point, - points: eventDatas?.points, - }); + await EventCreateFunction( + organization, + eventDatas, + productUuid, + projectId + ); return { status: "EventData add successfully", }; } } else { const newProduct = await ProductModel(organization).create({ - productId: productId, + productUuid: productUuid, + projectId: projectId, productName: productName, }); if (newProduct) { if (eventDatas) { - await EventsDataModel(organization).create({ - productId: productId, - modelUuid: eventDatas?.modelUuid, - modelName: eventDatas?.modelName, - position: eventDatas?.position, - rotation: eventDatas?.rotation, - type: eventDatas?.type, - speed: eventDatas?.speed, - point: eventDatas?.point, - points: eventDatas?.points, - }); + await EventCreateFunction( + organization, + eventDatas, + productUuid, + projectId + ); } } return { @@ -137,9 +145,69 @@ export const productAdd = async (data: Iproduct): Promise => { } } }; -export const getProductDatas = async (data: Iproduct): Promise => { + +async function EventCreateFunction( + organization: string, + eventDatas: IEventDatainterface, + productUuid: string, + projectId: string +) { + await EventsDataModel(organization).create({ + projectId: projectId, + productUuid: productUuid, + modelUuid: eventDatas?.modelUuid as string, + modelName: eventDatas?.modelName, + position: eventDatas?.position, + rotation: eventDatas?.rotation, + type: eventDatas?.type, + speed: eventDatas?.speed, + point: eventDatas?.point, + points: eventDatas?.points, + }); +} +async function EventUpdateFunction( + organization: string, + eventDatas: IEventDatainterface, + productUuid: string, + projectId: string +) { + await EventsDataModel(organization).findOneAndUpdate( + { + projectId: projectId, + modelUuid: eventDatas.modelUuid, + productUuid: productUuid, + isArchive: false, + }, + { + modelUuid: eventDatas?.modelUuid, + modelName: eventDatas?.modelName, + position: eventDatas?.position, + rotation: eventDatas?.rotation, + type: eventDatas?.type, + speed: eventDatas?.speed, + point: eventDatas?.point, + points: eventDatas?.points, + } + ); +} +async function ProductAFind( + productUuid: string, + projectId: string, + organization: string +) { + const existingProduct = await ProductModel(organization).findOne({ + productUuid: productUuid, + projectId: projectId, + isArchive: false, + }); + + return existingProduct; +} +export const getProductDatas = async ( + data: IProductEvent +): Promise => { try { - const { productId, projectId, userId, organization } = data; + const { productUuid, projectId, userId, organization } = data; const UserExists = await existingUser(userId, organization); if (!UserExists) return { status: "User not found" }; const LivingProject = await existingProjectById( @@ -148,17 +216,23 @@ export const getProductDatas = async (data: Iproduct): Promise => { userId ); if (!LivingProject) return { status: "Project not found" }; - const existingProduct = await ProductModel(organization).findOne({ - productId: productId, - projectId: projectId, - isArchive: false, - }); - - if (!existingProduct) return { status: "Product not found" }; + const ExistingProduct = await ProductAFind( + productUuid, + projectId, + organization + ); + if (!ExistingProduct) return { status: "Product not found" }; const existingEventDatas = await EventsDataModel(organization) - .find({ productId: productId, projectId: projectId }) - .select("-productId"); + .find({ + productUuid: productUuid, + projectId: projectId, + isArchive: false, + }) + .select("-productUuid"); + if (!existingEventDatas) { + return { status: "Events not found", data: [] }; + } return { status: "Success", data: existingEventDatas }; } catch (error: unknown) { if (error instanceof Error) { @@ -172,9 +246,11 @@ export const getProductDatas = async (data: Iproduct): Promise => { } } }; -export const productDataDelete = async (data: Iproduct): Promise => { +export const productDataDelete = async ( + data: IProductEvent +): Promise => { try { - const { productId, projectId, userId, organization } = data; + const { productUuid, projectId, userId, organization } = data; const UserExists = await existingUser(userId, organization); if (!UserExists) return { status: "User not found" }; const LivingProject = await existingProjectById( @@ -183,26 +259,28 @@ export const productDataDelete = async (data: Iproduct): Promise => { userId ); if (!LivingProject) return { status: "Project not found" }; - const existingProduct = await ProductModel(organization).findOne({ - productId: productId, - isArchive: false, - }); - - if (!existingProduct) return { status: "Product not found" }; + const ExistingProduct = await ProductAFind( + productUuid, + projectId, + organization + ); + if (!ExistingProduct) return { status: "Product not found" }; await ProductModel(organization).findOneAndUpdate( - { productId: productId, projectId: projectId }, + { productUuid: productUuid, projectId: projectId, isArchive: false }, { isArchive: true, }, { new: true } ); const existingEventDatas = await EventsDataModel(organization).find({ - productId: productId, + productUuid: productUuid, + projectId: projectId, + isArchive: false, }); if (existingEventDatas) { await EventsDataModel(organization).updateMany( - { productId, projectId }, + { productUuid, projectId, isArchive: false }, { $set: { isArchive: true } } ); } @@ -221,11 +299,9 @@ export const productDataDelete = async (data: Iproduct): Promise => { } } }; -export const EventDataDelete = async ( - data: IEventDataDelete -): Promise => { +export const EventDataDelete = async (data: IDelEvent): Promise => { try { - const { modelUuid, productId, projectId, userId, organization } = data; + const { modelUuid, productUuid, projectId, userId, organization } = data; const UserExists = await existingUser(userId, organization); if (!UserExists) return { status: "User not found" }; const LivingProject = await existingProjectById( @@ -234,21 +310,28 @@ export const EventDataDelete = async ( userId ); if (!LivingProject) return { status: "Project not found" }; - const existingProduct = await ProductModel(organization).findOne({ - productId: productId, - projectId: projectId, - isArchive: false, - }); - - if (!existingProduct) return { status: "Product not found" }; - await EventsDataModel(organization).findOneAndUpdate( - { productId: productId, projectId: projectId, modelUuid: modelUuid }, + const ExistingProduct = await ProductAFind( + productUuid, + projectId, + organization + ); + if (!ExistingProduct) return { status: "Product not found" }; + const EventDel = await EventsDataModel(organization).findOneAndUpdate( + { + productUuid: productUuid, + projectId: projectId, + isArchive: false, + modelUuid: modelUuid, + }, { isArchive: true, }, { new: true } ); - + if (!EventDel) + return { + status: "Event Delete Unsuccessful", + }; return { status: "Success", }; @@ -265,7 +348,7 @@ export const EventDataDelete = async ( } }; export const AllProductDatas = async ( - data: IEventDataDelete + data: IProjectProducts ): Promise => { try { const { projectId, userId, organization } = data; @@ -279,10 +362,12 @@ export const AllProductDatas = async ( if (!LivingProject) return { status: "Project not found" }; const existingProduct = await ProductModel(organization).find({ isArchive: false, + projectId: projectId, }); if (!existingProduct) { return { status: "No products found", + data: [], }; } const result = []; @@ -291,15 +376,15 @@ export const AllProductDatas = async ( const eventDatas = await EventsDataModel(organization) .find({ projectId: product.projectId, - productId: product.productId, + productUuid: product.productUuid, isArchive: false, }) - .select("-productId -isArchive -createdAt -updatedAt -__v -_id"); + .select("-productUuid -isArchive -createdAt -updatedAt -__v -_id"); result.push({ projectId: product.projectId, productName: product.productName, - productId: product.productId, + productUuid: product.productUuid, eventDatas, }); } @@ -320,9 +405,9 @@ export const AllProductDatas = async ( } } }; -export const productRename = async (data: Iproduct): Promise => { +export const productRename = async (data: IProductRename): Promise => { try { - const { productName, productId, projectId, userId, organization } = data; + const { productName, productUuid, projectId, userId, organization } = data; const UserExists = await existingUser(userId, organization); if (!UserExists) return { status: "User not found" }; const LivingProject = await existingProjectById( @@ -331,22 +416,25 @@ export const productRename = async (data: Iproduct): Promise => { userId ); if (!LivingProject) return { status: "Project not found" }; - const existingProduct = await ProductModel(organization).findOne({ - productId: productId, - projectId: projectId, - isArchive: false, - }); + const ExistingProduct = await ProductAFind( + productUuid, + projectId, + organization + ); + if (!ExistingProduct) return { status: "Product not found" }; - if (!existingProduct) return { status: "Product not found" }; - - await ProductModel(organization).findOneAndUpdate( - { productId: productId }, + const UpdateName = await ProductModel(organization).findOneAndUpdate( + { productUuid: productUuid, projectId: projectId, isArchive: false }, { productName: productName, }, { new: true } ); - + if (!UpdateName) { + return { + status: "Rename Unsuccessful", + }; + } return { status: "Success", }; diff --git a/src/socket-server/controllers/builderController/aisle-Controller.ts b/src/socket-server/controllers/builderController/aisle-Controller.ts new file mode 100644 index 0000000..4df0750 --- /dev/null +++ b/src/socket-server/controllers/builderController/aisle-Controller.ts @@ -0,0 +1,122 @@ +import { Socket, Server } from "socket.io"; +import { EVENTS } from "../../socket/events.ts"; +import { emitToSenderAndAdmins } from "../../utils/emitEventResponse.ts"; +import { + ErrorResponse, + FinalResponse, + validateFields, +} from "../../utils/socketfunctionHelpers.ts"; +import { + DeleteAisle, + SetAisle, +} from "../../../shared/services/builder/AisleService.ts"; +export const SetAisleHandleEvent = async ( + event: string, + socket: Socket, + io: Server, + data: any, + connectedUsersByOrg: { + [org: string]: { socketId: string; userId: string; role: string }[]; + } +) => { + if (event !== EVENTS.setAisleModel_v1 || !data?.organization) return; + const requiredFields = ["aisleUuid", "projectId", "userId", "organization"]; + const missingFields = validateFields(data, requiredFields); + + if (missingFields.length > 0) { + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.Aisle_v1UpdateResponse, + ErrorResponse(missingFields, socket, data.organization), + connectedUsersByOrg + ); + return; + } + const result = await SetAisle(data); + const status = typeof result?.status === "string" ? result.status : "unknown"; + + const messages: Record = { + Success: { message: "Aisle Created Successfully" }, + "User not found": { message: "User not found" }, + "Project not found": { message: "Project not found" }, + "Aisle Not Updated": { message: "Aisle Not Updated" }, + "Aisle Not Created": { message: "Aisle Not Created" }, + "Aisle Updated Successfully": { message: "Aisle Updated Successfully" }, + }; + + const msg = messages[status] || { message: "Internal server error" }; + const Camera_Datas = status === "Success" && result?.data ? {} : undefined; + + const response = FinalResponse( + status, + socket, + data.organization, + messages, + Camera_Datas + ); + + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.Aisle_v1UpdateResponse, + response, + connectedUsersByOrg + ); +}; +export const DeleteAisleHandleEvent = async ( + event: string, + socket: Socket, + io: Server, + data: any, + connectedUsersByOrg: { + [org: string]: { socketId: string; userId: string; role: string }[]; + } +) => { + if (event !== EVENTS.delete_v1AisleModel || !data?.organization) return; + const requiredFields = ["aisleUuid", "projectId", "userId", "organization"]; + const missingFields = validateFields(data, requiredFields); + + if (missingFields.length > 0) { + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.Aisle_v1DeleteResponse, + ErrorResponse(missingFields, socket, data.organization), + connectedUsersByOrg + ); + return; + } + const result = await DeleteAisle(data); + const status = typeof result?.status === "string" ? result.status : "unknown"; + + const messages: Record = { + Success: { message: "Aisle Deleted Successfully" }, + "User not found": { message: "User not found" }, + "Project not found": { message: "Project not found" }, + "Aisle not found": { message: "Aisle not found" }, + }; + + const msg = messages[status] || { message: "Internal server error" }; + const Camera_Datas = status === "Success" && result?.data ? {} : undefined; + + const response = FinalResponse( + status, + socket, + data.organization, + messages, + Camera_Datas + ); + + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.Aisle_v1DeleteResponse, + response, + connectedUsersByOrg + ); +}; diff --git a/src/socket-server/controllers/builderController/line-Controller.ts b/src/socket-server/controllers/builderController/line-Controller.ts index e74a2b4..39b4901 100644 --- a/src/socket-server/controllers/builderController/line-Controller.ts +++ b/src/socket-server/controllers/builderController/line-Controller.ts @@ -142,7 +142,6 @@ export const DeleteLineHandleEvent = async ( } ) => { if (event !== EVENTS.deleteLine_v1 || !data?.organization) return; - console.log("data: ", data); console.log("event: ", event); const requiredFields = ["line", "projectId", "userId", "organization"]; diff --git a/src/socket-server/controllers/simulationController/product-Controller.ts b/src/socket-server/controllers/simulationController/product-Controller.ts index 1e7b1c2..7444727 100644 --- a/src/socket-server/controllers/simulationController/product-Controller.ts +++ b/src/socket-server/controllers/simulationController/product-Controller.ts @@ -1,272 +1,318 @@ import { Socket, Server } from "socket.io"; import { EVENTS } from "../../socket/events.ts"; import { emitToSenderAndAdmins } from "../../utils/emitEventResponse.ts"; -import { EventDataDelete, productAdd, productDataDelete } from "../../../shared/services/simulation/productService.ts"; +import { + EventDataDelete, + productAdd, + productDataDelete, + productRename, +} from "../../../shared/services/simulation/productService.ts"; export const productAddHandleEvent = async ( - event: string, - socket: Socket, - io: Server, - data: any, - connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, + event: string, + socket: Socket, + io: Server, + data: any, + connectedUsersByOrg: { + [org: string]: { socketId: string; userId: string; role: string }[]; + } ) => { - if (event !== EVENTS.setAssetModel_v1 || !data?.organization) return; - const requiredFields = [ - "productName", "productId", "eventDatas", - "projectId", - "userId", - "organization", - ]; - const missingFields = requiredFields.filter(field => !data?.[field]); - - if (missingFields.length > 0) { - const response = { - success: false, - message: `Missing required field(s): ${missingFields.join(", ")}`, - status: "MissingFields", - socketId: socket.id, - organization: data?.organization ?? "unknown", - }; - - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.asset_v1UpdateResponse, response, connectedUsersByOrg) - return; - } - const result = await productAdd(data); - const status = typeof result?.status === "string" ? result.status : "unknown"; - - const messages: Record = { - Success: { message: "Product created successfully" }, - "User not found": { message: "User not found" }, - "Project not found": { message: "Project not found" }, - "EventData updated successfully": { message: "EventData updated successfully" }, - "EventData add successfully": { message: "EventData add successfully" }, - - - }; - - const msg = messages[status] || { message: "Internal server error" }; - const product_Datas = - status === "Success" && result?.data - - ? { - - } - : undefined; + if (event !== EVENTS.setProductModel_v1 || !data?.organization) return; + const requiredFields = [ + "productName", + "productUuid", + "projectId", + "userId", + "organization", + ]; + const missingFields = requiredFields.filter((field) => !data?.[field]); + if (missingFields.length > 0) { const response = { - success: status === "Success", - message: msg.message, - status, - socketId: socket.id, - organization: data.organization, - ...(product_Datas ? { data: product_Datas } : {}), + success: false, + message: `Missing required field(s): ${missingFields.join(", ")}`, + status: "MissingFields", + socketId: socket.id, + organization: data?.organization ?? "unknown", }; + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.Product_v1UpdateResponse, + response, + connectedUsersByOrg + ); + return; + } + const result = await productAdd(data); + const status = typeof result?.status === "string" ? result.status : "unknown"; - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.asset_v1UpdateResponse, response, connectedUsersByOrg) -} + const messages: Record = { + Success: { message: "Product created successfully" }, + "User not found": { message: "User not found" }, + "Project not found": { message: "Project not found" }, + "EventData updated successfully": { + message: "EventData updated successfully", + }, + "EventData add successfully": { message: "EventData add successfully" }, + }; + + const msg = messages[status] || { message: "Internal server error" }; + const product_Datas = status === "Success" && result?.data ? {} : undefined; + + const response = { + success: status === "Success", + message: msg.message, + status, + socketId: socket.id, + organization: data.organization, + ...(product_Datas ? { data: product_Datas } : {}), + }; + + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.Product_v1UpdateResponse, + response, + connectedUsersByOrg + ); +}; export const productDataDeleteHandleEvent = async ( - event: string, - socket: Socket, - io: Server, - data: any, - connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, + event: string, + socket: Socket, + io: Server, + data: any, + connectedUsersByOrg: { + [org: string]: { socketId: string; userId: string; role: string }[]; + } ) => { - if (event !== EVENTS.setAssetModel_v1 || !data?.organization) return; - const requiredFields = [ - "productId", - "projectId", - "userId", - "organization", - ]; - const missingFields = requiredFields.filter(field => !data?.[field]); - - if (missingFields.length > 0) { - const response = { - success: false, - message: `Missing required field(s): ${missingFields.join(", ")}`, - status: "MissingFields", - socketId: socket.id, - organization: data?.organization ?? "unknown", - }; - - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.asset_v1UpdateResponse, response, connectedUsersByOrg) - return; - } - const result = await productDataDelete(data); - const status = typeof result?.status === "string" ? result.status : "unknown"; - - const messages: Record = { - Success: { message: "Product deleted successfully" }, - "User not found": { message: "User not found" }, - "Project not found": { message: "Project not found" }, - "Product not found": { message: "Product not found" }, - - - - }; - - const msg = messages[status] || { message: "Internal server error" }; - const product_Datas = - status === "Success" && result?.data - - ? { - // widget: { - // id: result.data.widgetID, - // type: result.data.projectName, - // position: result.data.position, - // }, - // Data: result.data.Data, - // zoneId: result.data.zoneId, - } - : undefined; + if (event !== EVENTS.delete_v1ProductModel || !data?.organization) return; + const requiredFields = ["productUuid", "projectId", "userId", "organization"]; + const missingFields = requiredFields.filter((field) => !data?.[field]); + if (missingFields.length > 0) { const response = { - success: status === "Success", - message: msg.message, - status, - socketId: socket.id, - organization: data.organization, - ...(product_Datas ? { data: product_Datas } : {}), + success: false, + message: `Missing required field(s): ${missingFields.join(", ")}`, + status: "MissingFields", + socketId: socket.id, + organization: data?.organization ?? "unknown", }; + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.Product_v1DeleteResponse, + response, + connectedUsersByOrg + ); + return; + } + const result = await productDataDelete(data); + const status = typeof result?.status === "string" ? result.status : "unknown"; - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.asset_v1UpdateResponse, response, connectedUsersByOrg) -} + const messages: Record = { + Success: { message: "Product deleted successfully" }, + "User not found": { message: "User not found" }, + "Project not found": { message: "Project not found" }, + "Product not found": { message: "Product not found" }, + }; + + const msg = messages[status] || { message: "Internal server error" }; + const product_Datas = + status === "Success" && result?.data + ? { + // widget: { + // id: result.data.widgetID, + // type: result.data.projectName, + // position: result.data.position, + // }, + // Data: result.data.Data, + // zoneId: result.data.zoneId, + } + : undefined; + + const response = { + success: status === "Success", + message: msg.message, + status, + socketId: socket.id, + organization: data.organization, + ...(product_Datas ? { data: product_Datas } : {}), + }; + + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.Product_v1DeleteResponse, + response, + connectedUsersByOrg + ); +}; export const EventDataDeleteHandleEvent = async ( - event: string, - socket: Socket, - io: Server, - data: any, - connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, + event: string, + socket: Socket, + io: Server, + data: any, + connectedUsersByOrg: { + [org: string]: { socketId: string; userId: string; role: string }[]; + } ) => { - if (event !== EVENTS.setAssetModel_v1 || !data?.organization) return; - const requiredFields = [ - "modelUuid", - "productId", - "projectId", - "userId", - "organization", - ]; - const missingFields = requiredFields.filter(field => !data?.[field]); - - if (missingFields.length > 0) { - const response = { - success: false, - message: `Missing required field(s): ${missingFields.join(", ")}`, - status: "MissingFields", - socketId: socket.id, - organization: data?.organization ?? "unknown", - }; - - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.asset_v1UpdateResponse, response, connectedUsersByOrg) - return; - } - const result = await EventDataDelete(data); - const status = typeof result?.status === "string" ? result.status : "unknown"; - - const messages: Record = { - Success: { message: "EventData deleted successfully" }, - "User not found": { message: "User not found" }, - "Project not found": { message: "Project not found" }, - "Product not found": { message: "Product not found" }, - - - - }; - - const msg = messages[status] || { message: "Internal server error" }; - const product_Datas = - status === "Success" && result?.data - - ? { - // widget: { - // id: result.data.widgetID, - // type: result.data.projectName, - // position: result.data.position, - // }, - // Data: result.data.Data, - // zoneId: result.data.zoneId, - } - : undefined; + if (event !== EVENTS.deleteEvent_v1ProductModel || !data?.organization) + return; + const requiredFields = [ + "modelUuid", + "productUuid", + "projectId", + "userId", + "organization", + ]; + const missingFields = requiredFields.filter((field) => !data?.[field]); + if (missingFields.length > 0) { const response = { - success: status === "Success", - message: msg.message, - status, - socketId: socket.id, - organization: data.organization, - ...(product_Datas ? { data: product_Datas } : {}), + success: false, + message: `Missing required field(s): ${missingFields.join(", ")}`, + status: "MissingFields", + socketId: socket.id, + organization: data?.organization ?? "unknown", }; + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.ProductEvent_v1DeleteResponse, + response, + connectedUsersByOrg + ); + return; + } + const result = await EventDataDelete(data); + const status = typeof result?.status === "string" ? result.status : "unknown"; - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.asset_v1UpdateResponse, response, connectedUsersByOrg) -} + const messages: Record = { + Success: { message: "EventData deleted successfully" }, + "User not found": { message: "User not found" }, + "Project not found": { message: "Project not found" }, + "Product not found": { message: "Product not found" }, + "Event Delete Unsuccessful": { message: "Event Delete Unsuccessful" }, + }; + + const msg = messages[status] || { message: "Internal server error" }; + const product_Datas = + status === "Success" && result?.data + ? { + // widget: { + // id: result.data.widgetID, + // type: result.data.projectName, + // position: result.data.position, + // }, + // Data: result.data.Data, + // zoneId: result.data.zoneId, + } + : undefined; + + const response = { + success: status === "Success", + message: msg.message, + status, + socketId: socket.id, + organization: data.organization, + ...(product_Datas ? { data: product_Datas } : {}), + }; + + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.ProductEvent_v1DeleteResponse, + response, + connectedUsersByOrg + ); +}; export const productRenameHandleEvent = async ( - event: string, - socket: Socket, - io: Server, - data: any, - connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, + event: string, + socket: Socket, + io: Server, + data: any, + connectedUsersByOrg: { + [org: string]: { socketId: string; userId: string; role: string }[]; + } ) => { - if (event !== EVENTS.setAssetModel_v1 || !data?.organization) return; - const requiredFields = [ - "productName", - "productId", - "projectId", - "userId", - "organization", - ]; - const missingFields = requiredFields.filter(field => !data?.[field]); - - if (missingFields.length > 0) { - const response = { - success: false, - message: `Missing required field(s): ${missingFields.join(", ")}`, - status: "MissingFields", - socketId: socket.id, - organization: data?.organization ?? "unknown", - }; - - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.asset_v1UpdateResponse, response, connectedUsersByOrg) - return; - } - const result = await EventDataDelete(data); - const status = typeof result?.status === "string" ? result.status : "unknown"; - - const messages: Record = { - Success: { message: "product Rename successfully" }, - "User not found": { message: "User not found" }, - "Project not found": { message: "Project not found" }, - "Product not found": { message: "Product not found" }, - - - - }; - - const msg = messages[status] || { message: "Internal server error" }; - const product_Datas = - status === "Success" && result?.data - - ? { - // widget: { - // id: result.data.widgetID, - // type: result.data.projectName, - // position: result.data.position, - // }, - // Data: result.data.Data, - // zoneId: result.data.zoneId, - } - : undefined; + if (event !== EVENTS.ProductRenameModel_v1 || !data?.organization) return; + const requiredFields = [ + "productName", + "productUuid", + "projectId", + "userId", + "organization", + ]; + const missingFields = requiredFields.filter((field) => !data?.[field]); + if (missingFields.length > 0) { const response = { - success: status === "Success", - message: msg.message, - status, - socketId: socket.id, - organization: data.organization, - ...(product_Datas ? { data: product_Datas } : {}), + success: false, + message: `Missing required field(s): ${missingFields.join(", ")}`, + status: "MissingFields", + socketId: socket.id, + organization: data?.organization ?? "unknown", }; + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.ProductRename_v1UpdateResponse, + response, + connectedUsersByOrg + ); + return; + } + const result = await productRename(data); + const status = typeof result?.status === "string" ? result.status : "unknown"; - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.asset_v1UpdateResponse, response, connectedUsersByOrg) -} \ No newline at end of file + const messages: Record = { + Success: { message: "product Rename successfully" }, + "User not found": { message: "User not found" }, + "Project not found": { message: "Project not found" }, + "Product not found": { message: "Product not found" }, + "Rename Unsuccessful": { message: "Rename Unsuccessful" }, + }; + + const msg = messages[status] || { message: "Internal server error" }; + const product_Datas = + status === "Success" && result?.data + ? { + // widget: { + // id: result.data.widgetID, + // type: result.data.projectName, + // position: result.data.position, + // }, + // Data: result.data.Data, + // zoneId: result.data.zoneId, + } + : undefined; + + const response = { + success: status === "Success", + message: msg.message, + status, + socketId: socket.id, + organization: data.organization, + ...(product_Datas ? { data: product_Datas } : {}), + }; + + emitToSenderAndAdmins( + io, + socket, + data.organization, + EVENTS.ProductRename_v1UpdateResponse, + response, + connectedUsersByOrg + ); +}; diff --git a/src/socket-server/manager/manager.ts b/src/socket-server/manager/manager.ts index 9d43218..4314ac5 100644 --- a/src/socket-server/manager/manager.ts +++ b/src/socket-server/manager/manager.ts @@ -1,24 +1,79 @@ -import { Server, Socket } from 'socket.io'; -import jwt from 'jsonwebtoken'; -import dotenv from 'dotenv'; -import AuthModel from '../../shared/V1Models/Auth/userAuthModel.ts'; +import { Server, Socket } from "socket.io"; +import jwt from "jsonwebtoken"; +import dotenv from "dotenv"; +import AuthModel from "../../shared/V1Models/Auth/userAuthModel.ts"; dotenv.config(); -import { addCommentHandleEvent, createThreadHandleEvent, deleteCommentHandleEvent, deleteThreadHandleEvent } from '../controllers/thread/threadController.ts'; -import { DuplicateProjectHandleEvent, projectDeleteHandleEvent, projectHandleEvent, projecUpdateHandleEvent } from '../controllers/projectController/projectController.ts'; -import { setAssetHandleEvent, deleteAssetHandleEvent, replaceEventDatasHandleEvent } from '../controllers/builderController/asset-Controller.ts'; -import { SetCameraHandleEvent } from '../controllers/builderController/camera-Controller.ts'; -import { TrashDeleteHandleEvent } from '../controllers/trashController/trash-Controller.ts'; -import { setEnvironmentHandleEvent } from '../controllers/builderController/environment-Controller.ts'; -import { CreateLineHandleEvent, UpdateLineHandleEvent, DeleteLineHandleEvent, DeleteLayerHandleEvent, DeleteLinePointsHandleEvent } from '../controllers/builderController/line-Controller.ts'; -import { deleteWallItemsHandleEvent, setWallItemsHandleEvent } from '../controllers/builderController/wall-Controller.ts'; -import { DeleteZoneHandleEvent, SetZoneHandleEvent } from '../controllers/builderController/zone-Controller.ts'; -import { add3DwidgetHandleEvent, Delete3DwidgetHandleEvent, update3DHandleEvent } from '../controllers/vizualizationController/3dWidget-Controller.ts'; -import { AddFloatHandleEvent, DeleteFloatHandleEvent, DuplicateFloatHandleEvent } from '../controllers/vizualizationController/floatWidget-Controller.ts'; -import { AddPanelHandleEvent, ClearPanelHandleEvent, DeletePanelHandleEvent, LockedPanelHandleEvent } from '../controllers/vizualizationController/panel-Controller.ts'; -import { AddTemplateHandleEvent, addTemplateZoneHandleEvent, TemplateDeleteHandleEvent } from '../controllers/vizualizationController/template-Controller.ts'; -import { AddWidgetHandleEvent, WidgetDeleteHandleEvent } from '../controllers/vizualizationController/widget-Controller.ts'; -import { getUserRole } from '../utils/getUsers.ts'; - +import { + addCommentHandleEvent, + createThreadHandleEvent, + deleteCommentHandleEvent, + deleteThreadHandleEvent, +} from "../controllers/thread/threadController.ts"; +import { + DuplicateProjectHandleEvent, + projectDeleteHandleEvent, + projectHandleEvent, + projecUpdateHandleEvent, +} from "../controllers/projectController/projectController.ts"; +import { + setAssetHandleEvent, + deleteAssetHandleEvent, + replaceEventDatasHandleEvent, +} from "../controllers/builderController/asset-Controller.ts"; +import { SetCameraHandleEvent } from "../controllers/builderController/camera-Controller.ts"; +import { TrashDeleteHandleEvent } from "../controllers/trashController/trash-Controller.ts"; +import { setEnvironmentHandleEvent } from "../controllers/builderController/environment-Controller.ts"; +import { + CreateLineHandleEvent, + UpdateLineHandleEvent, + DeleteLineHandleEvent, + DeleteLayerHandleEvent, + DeleteLinePointsHandleEvent, +} from "../controllers/builderController/line-Controller.ts"; +import { + deleteWallItemsHandleEvent, + setWallItemsHandleEvent, +} from "../controllers/builderController/wall-Controller.ts"; +import { + DeleteZoneHandleEvent, + SetZoneHandleEvent, +} from "../controllers/builderController/zone-Controller.ts"; +import { + add3DwidgetHandleEvent, + Delete3DwidgetHandleEvent, + update3DHandleEvent, +} from "../controllers/vizualizationController/3dWidget-Controller.ts"; +import { + AddFloatHandleEvent, + DeleteFloatHandleEvent, + DuplicateFloatHandleEvent, +} from "../controllers/vizualizationController/floatWidget-Controller.ts"; +import { + AddPanelHandleEvent, + ClearPanelHandleEvent, + DeletePanelHandleEvent, + LockedPanelHandleEvent, +} from "../controllers/vizualizationController/panel-Controller.ts"; +import { + AddTemplateHandleEvent, + addTemplateZoneHandleEvent, + TemplateDeleteHandleEvent, +} from "../controllers/vizualizationController/template-Controller.ts"; +import { + AddWidgetHandleEvent, + WidgetDeleteHandleEvent, +} from "../controllers/vizualizationController/widget-Controller.ts"; +import { getUserRole } from "../utils/getUsers.ts"; +import { + DeleteAisleHandleEvent, + SetAisleHandleEvent, +} from "../controllers/builderController/aisle-Controller.ts"; +import { + EventDataDeleteHandleEvent, + productAddHandleEvent, + productDataDeleteHandleEvent, + productRenameHandleEvent, +} from "../controllers/simulationController/product-Controller.ts"; interface UserSocketInfo { socketId: string; @@ -28,24 +83,19 @@ interface UserSocketInfo { const connectedUsersByOrg: { [organization: string]: UserSocketInfo[] } = {}; export const SocketServer = (io: Server) => { - - - const namespaces = { - dashboard: io.of('/dashboard'), - project: io.of('/project'), - thread: io.of('/thread'), + dashboard: io.of("/dashboard"), + project: io.of("/project"), + thread: io.of("/thread"), Builder_v1: io.of("/Builder_v1"), visualization_v1: io.of("/Visualization_v1"), + simulation_v1: io.of("/Simulation_v1"), }; - const onlineUsers: { [organization: string]: Set } = {}; - const handleNamespace = (namespace: any, ...eventHandlers: Function[]) => { namespace.use(async (socket: Socket, next: any) => { - const token = socket.handshake.auth.token; const jwt_secret = process.env.JWT_SECRET as string; @@ -59,23 +109,23 @@ export const SocketServer = (io: Server) => { return next(new Error("Server configuration error: Missing secret")); } try { - const decoded = jwt.verify(token, jwt_secret) as { userId: string; Email: string; - organization: string + organization: string; }; - const user = await AuthModel(decoded.organization).findOne({ _id: decoded.userId, Email: decoded.Email, }); + const user = await AuthModel(decoded.organization).findOne({ + _id: decoded.userId, + Email: decoded.Email, + }); if (!user) { console.log(" User not found in DB"); return next(new Error("Authentication error: User not found")); } - (socket as any).user = { - organization: decoded.organization, Email: decoded.Email, userId: decoded.userId, @@ -85,7 +135,6 @@ export const SocketServer = (io: Server) => { } catch (error: any) { console.error("❌ Authentication failed:", error.message); return next(new Error("Authentication error")); - } }); namespace.on("connection", async (socket: Socket) => { @@ -93,8 +142,6 @@ export const SocketServer = (io: Server) => { const organization = user.organization; const userId = user.userId; - - if (organization) { socket.join(organization); } @@ -113,52 +160,49 @@ export const SocketServer = (io: Server) => { userId, role, }); - } else { - console.warn(`❌ Cannot store user. Missing data:`,); + console.warn(`❌ Cannot store user. Missing data:`); } socket.onAny((event: string, data: any, callback: any) => { - eventHandlers.forEach(handler => + eventHandlers.forEach((handler) => handler(event, socket, io, data, connectedUsersByOrg, callback) ); }); socket.on("disconnect", () => { onlineUsers[organization]?.delete(socket.id); - if (onlineUsers[organization]?.size === 0) delete onlineUsers[organization]; - + if (onlineUsers[organization]?.size === 0) + delete onlineUsers[organization]; }); socket.on("reconnect", (attempt: number) => { - if (organization) { socket.join(organization); - } }); }); }; - - handleNamespace(namespaces.dashboard); - handleNamespace(namespaces.thread, + handleNamespace( + namespaces.thread, createThreadHandleEvent, deleteThreadHandleEvent, addCommentHandleEvent, - deleteCommentHandleEvent) + deleteCommentHandleEvent + ); - - - - handleNamespace(namespaces.project, + handleNamespace( + namespaces.project, projectHandleEvent, projectDeleteHandleEvent, projecUpdateHandleEvent, DuplicateProjectHandleEvent, - TrashDeleteHandleEvent) - handleNamespace(namespaces.Builder_v1, + TrashDeleteHandleEvent + ); + handleNamespace( + namespaces.Builder_v1, setAssetHandleEvent, deleteAssetHandleEvent, replaceEventDatasHandleEvent, @@ -172,9 +216,12 @@ export const SocketServer = (io: Server) => { setWallItemsHandleEvent, deleteWallItemsHandleEvent, SetZoneHandleEvent, - DeleteZoneHandleEvent - ) - handleNamespace(namespaces.visualization_v1, + DeleteZoneHandleEvent, + SetAisleHandleEvent, + DeleteAisleHandleEvent + ); + handleNamespace( + namespaces.visualization_v1, add3DwidgetHandleEvent, update3DHandleEvent, Delete3DwidgetHandleEvent, @@ -190,6 +237,13 @@ export const SocketServer = (io: Server) => { TemplateDeleteHandleEvent, AddWidgetHandleEvent, WidgetDeleteHandleEvent - ) + ); + handleNamespace( + namespaces.simulation_v1, + productAddHandleEvent, + productDataDeleteHandleEvent, + EventDataDeleteHandleEvent, + productRenameHandleEvent + ); return io; -}; \ No newline at end of file +}; diff --git a/src/socket-server/socket/events.ts b/src/socket-server/socket/events.ts index 2ca851f..21b6bda 100644 --- a/src/socket-server/socket/events.ts +++ b/src/socket-server/socket/events.ts @@ -108,7 +108,8 @@ export const EVENTS = { addWidget3D: "v1:viz-3D-widget:add", addWidget3DResponse: "v1:viz-widget3D:response:add", updateWidget3DPosition: "v1:viz-3D-widget:modifyPositionRotation", - updateWidget3DPositionResponse:"v1:viz-widget3D:response:modifyPositionRotation", + updateWidget3DPositionResponse: + "v1:viz-widget3D:response:modifyPositionRotation", deleteWidget3D: "v1:viz-3D-widget:delete", deletewidget3DResponse: "v1:viz-widget3D:response:delete", @@ -176,4 +177,18 @@ export const EVENTS = { deleteTrash_v1: "v1:trash:delete", Trash_v1DeleteResponse: "v1:trash:response:delete", + + setAisleModel_v1: "v1:model-aisle:add", + Aisle_v1UpdateResponse: "v1:model-aisle:response:add", + delete_v1AisleModel: "v1:model-aisle:delete", + Aisle_v1DeleteResponse: "v1:model-aisle:response:delete", + + setProductModel_v1: "v1:model-product:add", + Product_v1UpdateResponse: "v1:model-product:response:add", + ProductRenameModel_v1: "v1:model-product:rename", + ProductRename_v1UpdateResponse: "v1:model-product:response:rename", + delete_v1ProductModel: "v1:model-product:delete", + Product_v1DeleteResponse: "v1:model-product:response:delete", + deleteEvent_v1ProductModel: "v1:model-productevent:delete", + ProductEvent_v1DeleteResponse: "v1:model-productevent:response:delete", };