From 36e1bf664f08615f5c097cf26e56da326fa78eb4 Mon Sep 17 00:00:00 2001 From: Shibi Chakkaravarthy Date: Sun, 14 Jun 2026 08:04:31 +0530 Subject: [PATCH] Operational Endpoints for Admin, Products, Assignments, Location, Vendor, Venue completed. Geofence Testing PEnding --- controllers/admin.controller.js | 16 +- controllers/assignment.controller.js | 39 ++- controllers/location.controller.js | 47 +++ controllers/product.controller.js | 70 +++++ controllers/vendor.controller.js | 79 +++++ controllers/venue.controller.js | 105 +++++++ documentation/admin.js | 34 ++ documentation/documentation.json | 454 +++++++++++++++++++++++++++ documentation/index.js | 4 + documentation/location.js | 17 +- documentation/product.js | 176 +++++++++++ documentation/vendor.js | 222 +++++++++++++ index.js | 21 +- models/.DS_Store | Bin 12292 -> 12292 bytes models/Access/model.js | 8 + models/Product/model.js | 4 + models/Product/operations.js | 11 +- models/Role/model.js | 8 + models/User/model.js | 4 + models/Vendor/operations.js | 9 +- routes/admin.route.js | 15 +- routes/index.js | 2 + routes/location.route.js | 16 +- routes/product.route.js | 17 + routes/vendor.route.js | 25 ++ routes/venue.route.js | 14 +- 26 files changed, 1392 insertions(+), 25 deletions(-) create mode 100644 controllers/product.controller.js create mode 100644 controllers/vendor.controller.js create mode 100644 documentation/product.js create mode 100644 documentation/vendor.js create mode 100644 routes/product.route.js create mode 100644 routes/vendor.route.js diff --git a/controllers/admin.controller.js b/controllers/admin.controller.js index 0c726c6..ea9b24e 100644 --- a/controllers/admin.controller.js +++ b/controllers/admin.controller.js @@ -1,5 +1,9 @@ import { createAccess } from "../models/Access/operations.js"; -import { createRole, getAllRoles } from "../models/Role/operations.js"; +import { + createRole, + getAllRoles, + updateRole, +} from "../models/Role/operations.js"; import { createDesignation, updateDesignation, @@ -60,6 +64,7 @@ export const updateDepartmentController = async (req, res, next) => { export const updateRoleController = async (req, res, next) => { try { const { id } = req.params; + console.log("REQ BODY", req.body, id); const role = await updateRole(id, req.body); res.status(200).json({ result: role }); } catch (error) { @@ -78,6 +83,7 @@ export const createRoleController = async (req, res) => { }); res.status(200).json({ result: role }); } catch (error) { + console.log("createRoleController Error", error); res.status(500).json({ error: error.message }); } }; @@ -251,7 +257,7 @@ export const getEmployeeDetailsController = async (req, res, next) => { const pipeline = [ { $match: { - _id: new ObjectId.createFromHexString(id), + _id: ObjectId.createFromHexString(id), }, }, { @@ -336,9 +342,9 @@ export const getEmployeeDetailsController = async (req, res, next) => { $project: { _id: 1, name: 1, - department: "$department.name", - designation: "$designation.name", - role: "$role.name", + department: 1, + designation: 1, + role: 1, profile: 1, branches: 1, }, diff --git a/controllers/assignment.controller.js b/controllers/assignment.controller.js index 18893b4..bfe03de 100644 --- a/controllers/assignment.controller.js +++ b/controllers/assignment.controller.js @@ -2,8 +2,10 @@ import { createAssignment, updateAssignment, getAssignmentsByQuery, + aggregateAssignment, } from "../models/Assignment/operations.js"; import dayjs from "dayjs"; +import { ObjectId } from "mongodb"; export const createAssignmentHandler = async (req, res) => { try { @@ -13,6 +15,7 @@ export const createAssignmentHandler = async (req, res) => { }); const assignment = await createAssignment({ ...req.body, + isActive: true, createdOn: dayjs().toISOString(), createdBy: user.id, }); @@ -35,7 +38,41 @@ export const updateAssignmentHandler = async (req, res) => { export const getAssignmentsByUserHandler = async (req, res) => { try { const { id } = req.params; - const assignment = await getAssignmentsByQuery({ user: id }); + const pipeline = [ + { + $match: { + user: ObjectId?.createFromHexString(id), + isActive: true, + }, + }, + { + $lookup: { + from: "venues", + localField: "venue", + foreignField: "_id", + as: "venue", + }, + }, + { + $unwind: { + path: "$venue", + }, + }, + { + $lookup: { + from: "partners", + localField: "venue.entity", + foreignField: "_id", + as: "partner", + }, + }, + { + $unwind: { + path: "$partner", + }, + }, + ]; + const assignment = await aggregateAssignment(pipeline); res.status(200).json({ result: assignment }); } catch (error) { res.status(500).json({ message: "Error getting assignment", error }); diff --git a/controllers/location.controller.js b/controllers/location.controller.js index 7e0bb12..8c5e973 100644 --- a/controllers/location.controller.js +++ b/controllers/location.controller.js @@ -3,6 +3,8 @@ import { getLocationByQuery, getLocationByRadius, } from "../models/Location/operations"; +import { aggregateAssignment } from "../models/Assignment/operations"; +import { ObjectId } from "mongodb"; /* Sample Location Payload @@ -69,3 +71,48 @@ export const getLocationController = async (req, res) => { res.status(500).json({ error: error.message }); } }; + +export const getMyAssignedVenuesHandler = async (req, res, next) => { + try { + const { user } = res.locals; + const pipeline = [ + { + $match: { + user: ObjectId?.createFromHexString(user.id), + isActive: true, + }, + }, + { + $lookup: { + from: "venues", + localField: "venue", + foreignField: "_id", + as: "venue", + }, + }, + { + $unwind: { + path: "$venue", + }, + }, + { + $lookup: { + from: "partners", + localField: "venue.entity", + foreignField: "_id", + as: "partner", + }, + }, + { + $unwind: { + path: "$partner", + }, + }, + ]; + const assignment = await aggregateAssignment(pipeline); + res.status(200).json({ result: assignment }); + } catch (error) { + console.log("getMyAssignedVenuesHandler Error", error); + next(error); + } +}; diff --git a/controllers/product.controller.js b/controllers/product.controller.js new file mode 100644 index 0000000..b58c2ce --- /dev/null +++ b/controllers/product.controller.js @@ -0,0 +1,70 @@ +import { + createProduct, + updateProduct, + getAllProducts, + getProductByQuery, + getProductById, + deleteProduct, +} from "../models/Product/operations"; +import dayjs from "dayjs"; + +export const createProductController = async (req, res, next) => { + try { + const { user } = res.locals; + + const product = await createProduct({ + ...req.body, + createdBy: user.id, + createdOn: dayjs().toISOString(), + }); + + res.status(200).json({ + result: product, + }); + } catch (error) { + console.log("createProductController Error", error); + next(error); + } +}; + +export const updateProductController = async (req, res, next) => { + try { + const { id } = req.params; + const product = await updateProduct(id, { + ...req.body, + }); + + res.status(200).json({ + result: product, + }); + } catch (error) { + console.log("updateProductController Error", error); + next(error); + } +}; + +export const getAllProductsController = async (req, res, next) => { + try { + const products = await getAllProducts(); + + res.status(200).json({ + result: products, + }); + } catch (error) { + console.log("getAllProductsController Error", error); + next(error); + } +}; + +export const deleteProductController = async (req, res, next) => { + try { + const { id } = req.params; + const product = await deleteProduct(id); + res.status(200).json({ + result: product, + }); + } catch (error) { + console.log("deleteProductController Error", error); + next(error); + } +}; \ No newline at end of file diff --git a/controllers/vendor.controller.js b/controllers/vendor.controller.js new file mode 100644 index 0000000..8ac75a5 --- /dev/null +++ b/controllers/vendor.controller.js @@ -0,0 +1,79 @@ +import dayjs from "dayjs"; +import { + createVendor, + updateVendor, + deleteVendor, + getVendorsByQuery, + getVendorById, + getAllVendors, +} from "../models/Vendor/operations"; + +export const createVendorController = async (req, res, next) => { + try { + const { user } = res.locals; + const vendor = await createVendor({ + ...req.body, + createdBy: user?.id, + createdOn: dayjs().toISOString(), + }); + res.status(201).json({ result: vendor }); + } catch (error) { + console.log("createVendorController Error", error); + next(error); + } +}; + +export const updateVendorController = async (req, res, next) => { + try { + const { id } = req.params; + const vendor = await updateVendor(id, req.body); + res.status(200).json({ result: vendor }); + } catch (error) { + console.log("updateVendorController Error", error); + next(error); + } +}; + +export const getActiveVendorsController = async (req, res, next) => { + try { + const vendors = await getVendorsByQuery({ isActive: true }); + res.status(200).json({ result: vendors }); + } catch (error) { + console.log("getActiveVendorsController Error", error); + next(error); + } +}; + +export const getAllVendorsController = async (req, res, next) => { + try { + const vendors = await getAllVendors(); + res.status(200).json({ result: vendors }); + } catch (error) { + console.log("getAllVendorsController Error", error); + next(error); + } +}; + +export const deactivateVendorController = async (req, res, next) => { + try { + const { id } = req.params; + const deactivatedVendor = await updateVendor(id, { isActive: false }); + res.status(200).json({ result: deactivatedVendor }); + } catch (error) { + console.log("deactivateVendorController Error", error); + next(error); + } +}; + +export const getVendorByIdController = async (req, res, next) => { + try { + const { id } = req.params; + + const vendor = await getVendorById(id); + + res.status(200).json({ result: vendor }); + } catch (error) { + console.log("getVendorByIdController Error", error); + next(error); + } +}; diff --git a/controllers/venue.controller.js b/controllers/venue.controller.js index 6950dbe..003f346 100644 --- a/controllers/venue.controller.js +++ b/controllers/venue.controller.js @@ -6,6 +6,8 @@ import { updateVenue, aggregateVenue, } from "../models/Venue/operations.js"; +import { ObjectId } from "mongodb"; +import { aggregateAssignment } from "../models/Assignment/operations.js"; import { coordinatesToGeoJson } from "../helpers/geoJson.helper.js"; import dayjs from "dayjs"; @@ -69,3 +71,106 @@ export const getVenueController = async (req, res, next) => { next(error); } }; + +export const getAssignedVenuesController = async (req, res, next) => { + try { + const { userId } = req.params; + // const { user } = res.locals; + + const assignedVenues = await aggregateAssignment([ + { + $match: { + user: ObjectId.createFromHexString(userId), + isActive: true, + }, + }, + { + $lookup: { + from: "venues", + localField: "venue", + foreignField: "_id", + as: "venue", + }, + }, + { + $unwind: { + path: "$venue", + preserveNullAndEmptyArrays: true, + }, + }, + { + $lookup: { + from: "partners", + localField: "venue.entity", + foreignField: "_id", + as: "partner", + }, + }, + { + $unwind: { + path: "$partner", + preserveNullAndEmptyArrays: true, + }, + }, + ]); + + res.status(200).json({ result: assignedVenues }); + } catch (error) { + console.log("getAssignedVenues Error", error); + next(error); + } +}; + +export const getUnassignedVenuesController = async (req, res, next) => { + try { + const unassignedVenues = await aggregateVenue([ + { + $match: { + category: "PARTNER" + }, + }, + { + $lookup: { + from: "assignments", + localField: "_id", + foreignField: "venue", + pipeline: [ + { + $match: { + isActive: true, + }, + }, + ], + as: "activeAssignments", + }, + }, + { + $match: { + $or: [ + { activeAssignments: { $size: 0 } }, + { activeAssignments: { $exists: false } }, + ], + }, + }, + { + $lookup: { + from: "partners", + localField: "entity", + foreignField: "_id", + as: "partner", + }, + }, + { + $unwind: { + path: "$partner", + preserveNullAndEmptyArrays: true, + }, + }, + ]); + + res.status(200).json({ result: unassignedVenues }); + } catch (error) { + console.log("getUnassignedVenuesController Error", error); + next(error); + } +}; diff --git a/documentation/admin.js b/documentation/admin.js index 9d916e0..1645b22 100644 --- a/documentation/admin.js +++ b/documentation/admin.js @@ -226,6 +226,40 @@ export default { }, }, }, + "/admin/role/{id}": { + patch: { + tags: ["Admin"], + summary: "Edit New Role", + parameters: [ + { + in: "path", + name: "id", + }, + ], + requestBody: { + required: true, + content: { + "application/json": { + schema: { + type: "object", + properties: { + name: { + type: "string", + required: true, + }, + }, + }, + }, + }, + }, + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + }, "/admin/employee/{id}": { get: { tags: ["Admin"], diff --git a/documentation/documentation.json b/documentation/documentation.json index adb4471..e0ee0dc 100644 --- a/documentation/documentation.json +++ b/documentation/documentation.json @@ -244,6 +244,20 @@ } } }, + "/location/venues/assigned/me": { + "get": { + "tags": [ + "Location" + ], + "summary": "Get Assigned Venues for creating Geofence", + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + } + }, "/uploads/single/{folder}": { "post": { "tags": [ @@ -521,6 +535,42 @@ } } }, + "/admin/role/{id}": { + "patch": { + "tags": [ + "Admin" + ], + "summary": "Edit New Role", + "parameters": [ + { + "in": "path", + "name": "id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "required": true + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + } + }, "/admin/employee/{id}": { "get": { "tags": [ @@ -1116,6 +1166,410 @@ } } } + }, + "/product": { + "post": { + "summary": "Create a New Product", + "tags": [ + "Product" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "sku": { + "type": "string", + "required": true + }, + "name": { + "type": "string", + "required": true + }, + "stock": { + "type": "number", + "required": true + }, + "buyingPrice": { + "type": "number", + "required": true + }, + "sellingPrice": { + "type": "number", + "required": true + }, + "description": { + "type": "string", + "required": true + }, + "gst": { + "type": "number", + "required": true + }, + "hsn": { + "type": "string", + "required": true + }, + "vendors": { + "type": "array", + "items": { + "type": "string" + }, + "required": true + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + }, + "get": { + "summary": "Get All Products", + "tags": [ + "Product" + ], + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + } + }, + "/product/{id}": { + "patch": { + "summary": "Update a Product", + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "Product ID", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "sku": { + "type": "string", + "required": true + }, + "name": { + "type": "string", + "required": true + }, + "stock": { + "type": "number", + "required": true + }, + "buyingPrice": { + "type": "number", + "required": true + }, + "sellingPrice": { + "type": "number", + "required": true + }, + "description": { + "type": "string", + "required": true + }, + "gst": { + "type": "number", + "required": true + }, + "hsn": { + "type": "string", + "required": true + }, + "vendors": { + "type": "array", + "items": { + "type": "string" + }, + "required": true + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + }, + "delete": { + "summary": "Delete a Product", + "tags": [ + "Product" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "Product ID", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + } + }, + "/vendor/all": { + "get": { + "summary": "Get All Vendors", + "tags": [ + "Vendor" + ], + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + } + }, + "/vendor/{id}": { + "get": { + "summary": "Get Vendor Details", + "tags": [ + "Vendor" + ], + "parameters": [ + { + "in": "path", + "required": true, + "description": "Vendor ID", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + }, + "patch": { + "summary": "Get Vendor Details", + "tags": [ + "Vendor" + ], + "parameters": [ + { + "in": "path", + "required": true, + "description": "Vendor ID", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "required": true + }, + "email": { + "type": "string", + "required": true + }, + "mobile": { + "type": "string", + "required": true + }, + "address": { + "type": "string", + "required": true + }, + "city": { + "type": "string", + "required": true + }, + "state": { + "type": "string", + "required": true + }, + "picode": { + "type": "string", + "required": true + }, + "isActive": { + "type": "boolean", + "required": true + }, + "contactPersons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "required": true + }, + "email": { + "type": "string", + "required": true + }, + "mobile": { + "type": "string", + "required": true + }, + "designation": { + "type": "string", + "required": true + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + }, + "delete": { + "summary": "Deactivate Vendor", + "tags": [ + "Vendor" + ], + "parameters": [ + { + "in": "path", + "required": true, + "description": "Vendor ID", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + } + }, + "/vendor": { + "post": { + "summary": "Create New Vendor", + "tags": [ + "Vendor" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "required": true + }, + "email": { + "type": "string", + "required": true + }, + "mobile": { + "type": "string", + "required": true + }, + "address": { + "type": "string", + "required": true + }, + "city": { + "type": "string", + "required": true + }, + "state": { + "type": "string", + "required": true + }, + "picode": { + "type": "string", + "required": true + }, + "isActive": { + "type": "boolean", + "required": true + }, + "contactPersons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "required": true + }, + "email": { + "type": "string", + "required": true + }, + "mobile": { + "type": "string", + "required": true + }, + "designation": { + "type": "string", + "required": true + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": {} + } + } + } } } } \ No newline at end of file diff --git a/documentation/index.js b/documentation/index.js index 282aed6..4a002f4 100644 --- a/documentation/index.js +++ b/documentation/index.js @@ -8,6 +8,8 @@ import location from "./location.js"; import assignment from "./assignment.js"; import partner from "./partner.js"; import venue from "./venue.js"; +import product from "./product.js"; +import vendor from "./vendor.js"; const GENERAL_CONFIG = { openapi: "3.0.1", @@ -53,6 +55,8 @@ let paths = { ...assignment, ...partner, ...venue, + ...product, + ...vendor, }; const getSwaggerDocument = () => { diff --git a/documentation/location.js b/documentation/location.js index 89112e5..86f6dbb 100644 --- a/documentation/location.js +++ b/documentation/location.js @@ -27,12 +27,11 @@ export default { coordinates: { type: "array", required: true, - }, + }, venue: { type: "string", required: false, - }, - + }, }, }, }, @@ -46,4 +45,16 @@ export default { }, }, }, + "/location/venues/assigned/me": { + get: { + tags: ["Location"], + summary: "Get Assigned Venues for creating Geofence", + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + }, }; diff --git a/documentation/product.js b/documentation/product.js new file mode 100644 index 0000000..663f0e7 --- /dev/null +++ b/documentation/product.js @@ -0,0 +1,176 @@ +export default { + "/product": { + post: { + summary: "Create a New Product", + tags: ["Product"], + requestBody: { + content: { + "application/json": { + schema: { + type: "object", + properties: { + sku: { + type: "string", + required: true, + }, + name: { + type: "string", + required: true, + }, + stock: { + type: "number", + required: true, + }, + buyingPrice: { + type: "number", + required: true, + }, + sellingPrice: { + type: "number", + required: true, + }, + description: { + type: "string", + required: true, + }, + gst: { + type: "number", + required: true, + }, + hsn: { + type: "string", + required: true, + }, + stock: { + type: "number", + required: true, + }, + vendors: { + type: "array", + items: { + type: "string", + }, + required: true, + }, + }, + }, + }, + }, + }, + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + get: { + summary: "Get All Products", + tags: ["Product"], + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + }, + "/product/{id}": { + patch: { + summary: "Update a Product", + tags: ["Product"], + parameters: [ + { + name: "id", + in: "path", + required: true, + description: "Product ID", + schema: { + type: "string", + }, + }, + ], + requestBody: { + content: { + "application/json": { + schema: { + type: "object", + properties: { + sku: { + type: "string", + required: true, + }, + name: { + type: "string", + required: true, + }, + stock: { + type: "number", + required: true, + }, + buyingPrice: { + type: "number", + required: true, + }, + sellingPrice: { + type: "number", + required: true, + }, + description: { + type: "string", + required: true, + }, + gst: { + type: "number", + required: true, + }, + hsn: { + type: "string", + required: true, + }, + stock: { + type: "number", + required: true, + }, + vendors: { + type: "array", + items: { + type: "string", + }, + required: true, + }, + }, + }, + }, + }, + }, + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + delete: { + summary: "Delete a Product", + tags: ["Product"], + parameters: [ + { + name: "id", + in: "path", + required: true, + description: "Product ID", + schema: { + type: "string", + }, + }, + ], + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + }, +}; \ No newline at end of file diff --git a/documentation/vendor.js b/documentation/vendor.js new file mode 100644 index 0000000..6087c2a --- /dev/null +++ b/documentation/vendor.js @@ -0,0 +1,222 @@ +export default { + "/vendor/all": { + get: { + summary: "Get All Vendors", + tags: ["Vendor"], + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + }, + "/vendor/{id}": { + get: { + summary: "Get Vendor Details", + tags: ["Vendor"], + parameters: [ + { + in: "path", + required: true, + description: "Vendor ID", + schema: { + type: "string", + }, + }, + ], + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + patch: { + summary: "Get Vendor Details", + tags: ["Vendor"], + parameters: [ + { + in: "path", + required: true, + description: "Vendor ID", + schema: { + type: "string", + }, + }, + ], + requestBody: { + content: { + "application/json": { + schema: { + type: "object", + properties: { + name: { + type: "string", + required: true, + }, + email: { + type: "string", + required: true, + }, + mobile: { + type: "string", + required: true, + }, + address: { + type: "string", + required: true, + }, + city: { + type: "string", + required: true, + }, + state: { + type: "string", + required: true, + }, + picode: { + type: "string", + required: true, + }, + isActive: { + type: "boolean", + required: true, + }, + contactPersons: { + type: "array", + items: { + type: "object", + properties: { + name: { + type: "string", + required: true, + }, + email: { + type: "string", + required: true, + }, + mobile: { + type: "string", + required: true, + }, + designation: { + type: "string", + required: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + delete: { + summary: "Deactivate Vendor", + tags: ["Vendor"], + parameters: [ + { + in: "path", + required: true, + description: "Vendor ID", + schema: { + type: "string", + }, + }, + ], + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + }, + "/vendor": { + post: { + summary: "Create New Vendor", + tags: ["Vendor"], + requestBody: { + content: { + "application/json": { + schema: { + type: "object", + properties: { + name: { + type: "string", + required: true, + }, + email: { + type: "string", + required: true, + }, + mobile: { + type: "string", + required: true, + }, + address: { + type: "string", + required: true, + }, + city: { + type: "string", + required: true, + }, + state: { + type: "string", + required: true, + }, + picode: { + type: "string", + required: true, + }, + isActive: { + type: "boolean", + required: true, + }, + contactPersons: { + type: "array", + items: { + type: "object", + properties: { + name: { + type: "string", + required: true, + }, + email: { + type: "string", + required: true, + }, + mobile: { + type: "string", + required: true, + }, + designation: { + type: "string", + required: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + responses: { + 200: { + description: "OK", + content: {}, + }, + }, + }, + }, +}; diff --git a/index.js b/index.js index f319c27..499762a 100644 --- a/index.js +++ b/index.js @@ -17,7 +17,9 @@ import { LocationRoutes, AssignmentRoutes, PartnerRoutes, - VenueRoutes + VenueRoutes, + ProductRoutes, + VendorRoutes, } from "./routes"; dotenv.config(); @@ -44,9 +46,22 @@ db.once("open", () => const app = express(); -app.use(cors()); +app.use( + cors({ + origin: [ + "http://localhost:1420", + "tauri://localhost", + "https://tauri.localhost", + "http://tauri.localhost", + ], + }), +); app.use(express.json()); +app.get("/test", (req, res, next) => { + res.json({status: "success"}) +}) + app.use("/v0/docs", swaggerUi.serve, swaggerUi.setup(swaggerDoc)); app.use("/v0/user", UserRoutes); app.use("/v0/admin", AdminRoutes); @@ -54,6 +69,8 @@ app.use("/v0/location", LocationRoutes); app.use("/v0/assignment", AssignmentRoutes); app.use("/v0/partner", PartnerRoutes); app.use("/v0/venue", VenueRoutes); +app.use("/v0/product", ProductRoutes); +app.use("/v0/vendor", VendorRoutes); app.use((err, req, res, next) => { const statusCode = err.status || 500; diff --git a/models/.DS_Store b/models/.DS_Store index 6dc4a543601bddee79e2b9350917cb56733e9d15..d40b6cc02113e53f88397f40d4ab9dda732df522 100644 GIT binary patch delta 241 zcmZokXi1ph&secBU^hRb=fnweleGkTm^kex?+`e^#6D|smEa*J_C1sBg!VA8C2am9 zq{zhhce0%51}65r%@;)7nHfJ$mXKV=#5Qa40myBD^Icq$a`Kaaq8$7UKV)wlKkkUGB87m8f(&FE6oA?{Ye^-tPUcqdW@2O7 d9HG#~$i$jESwKl@@;}85Osuk-Hz%<9ileGkTn3y#u?+`e^#B4CRO7IYfXD76WiFMNEKSGL3 zjN2y5iEdzGySe#-s5>)b@?;6gWlYRUlMhH{Z(c2xz&i0k!(?s+Zzk61n { // Read (Get all) export const getAllProducts = async () => { - return await Model.find(); + return await Model.aggregate([ + { + $lookup: { + from: "vendors", + localField: "vendors", + foreignField: "_id", + as: "vendors" + } + } + ]); }; // Update diff --git a/models/Role/model.js b/models/Role/model.js index 76a1195..89f725b 100644 --- a/models/Role/model.js +++ b/models/Role/model.js @@ -18,6 +18,8 @@ const moduleSchema = new Schema({ "salary", "vendor", "expense", + "venue", + "metadata", "product", "invoice", "partner", @@ -28,6 +30,12 @@ const moduleSchema = new Schema({ "inventoryLog", ], }, + region: { + type: String, + required: true, + default: "CITY", + enum: ["CITY", "STATE", "COUNTRY"], + }, permission: { type: String, required: true, diff --git a/models/User/model.js b/models/User/model.js index 8017d5f..7a9ec66 100644 --- a/models/User/model.js +++ b/models/User/model.js @@ -30,6 +30,10 @@ const schema = new Schema({ required: true, ref: "user", }, + isActive: { + type: Boolean, + required: true, + }, }); export default model("user", schema); diff --git a/models/Vendor/operations.js b/models/Vendor/operations.js index 35d4dc3..2e72cf7 100644 --- a/models/Vendor/operations.js +++ b/models/Vendor/operations.js @@ -10,10 +10,15 @@ export const getVendorById = async (id) => { return await Model.findById(id); }; -// Read (Get by Query) +// Read (Get One by Query) export const getVendorByQuery = async (query) => { return await Model.findOne(query); -} +}; + +// Read (Get All by Query) +export const getVendorsByQuery = async (query) => { + return await Model.find(query); +}; // Read (Get all) export const getAllVendors = async () => { diff --git a/routes/admin.route.js b/routes/admin.route.js index 240e582..ebc63d0 100644 --- a/routes/admin.route.js +++ b/routes/admin.route.js @@ -8,6 +8,7 @@ import { createDepartmentController, createDesignationController, createRoleController, + updateRoleController, getAllEmployeeController, getEmployeeDetailsController, getEmployeeLocationHistoryController, @@ -29,20 +30,16 @@ router.post( authorize("department", "write"), createDepartmentController, ); -router.get( - "/employees", - authorize("employee", "read"), - getAllEmployeeController, -); -router.post("/employee", authorize("employee", "write"), createEmployee); +router.get("/employees", authorize("user", "read"), getAllEmployeeController); +router.post("/employee", authorize("user", "write"), createEmployee); router.get( "/employee/:id", - authorize("employee", "read"), + authorize("user", "read"), getEmployeeDetailsController, ); router.get( "/employee/:user/locations", - authorize("employee", "read"), + authorize("user", "read"), getEmployeeLocationHistoryController, ); router.post( @@ -52,4 +49,6 @@ router.post( ); router.post("/role", authorize("role", "write"), createRoleController); +router.patch("/role/:id", authorize("role", "write"), updateRoleController); + export default router; diff --git a/routes/index.js b/routes/index.js index 9f2165f..1111807 100644 --- a/routes/index.js +++ b/routes/index.js @@ -5,3 +5,5 @@ export { default as LocationRoutes } from "./location.route"; export { default as AssignmentRoutes } from "./assignment.route"; export { default as VenueRoutes } from "./venue.route"; export { default as PartnerRoutes } from "./partner.route"; +export { default as ProductRoutes } from "./product.route"; +export { default as VendorRoutes } from "./vendor.route"; diff --git a/routes/location.route.js b/routes/location.route.js index 593dfff..f55d4f9 100644 --- a/routes/location.route.js +++ b/routes/location.route.js @@ -1,6 +1,12 @@ import { Router } from "express"; -import { authorizeWithEncryptedKey } from "../middlewares/jwt.middleware"; -import { createLocationController } from "../controllers/location.controller"; +import { + authorize, + authorizeWithEncryptedKey, +} from "../middlewares/jwt.middleware"; +import { + createLocationController, + getMyAssignedVenuesHandler, +} from "../controllers/location.controller"; const router = new Router(); @@ -10,4 +16,10 @@ router.post( createLocationController, ); +router.get( + "/venues/assigned/me", + authorize("generic", "generic"), + getMyAssignedVenuesHandler, +); + export default router; diff --git a/routes/product.route.js b/routes/product.route.js new file mode 100644 index 0000000..c1ffb97 --- /dev/null +++ b/routes/product.route.js @@ -0,0 +1,17 @@ +import { Router } from "express"; +import { authorize } from "../middlewares/jwt.middleware"; +import { + createProductController, + deleteProductController, + getAllProductsController, + updateProductController, +} from "../controllers/product.controller"; + +const router = Router(); + +router.post("/", authorize("product", "write"), createProductController); +router.get("/", authorize("product", "read"), getAllProductsController); +router.patch("/:id", authorize("product", "write"), updateProductController); +router.delete("/:id", authorize("product", "delete"), deleteProductController); + +export default router; diff --git a/routes/vendor.route.js b/routes/vendor.route.js new file mode 100644 index 0000000..b85870a --- /dev/null +++ b/routes/vendor.route.js @@ -0,0 +1,25 @@ +import { Router } from "express"; +import { + createVendorController, + updateVendorController, + getActiveVendorsController, + getAllVendorsController, + deactivateVendorController, + getVendorByIdController, +} from "../controllers/vendor.controller"; +import { authorize } from "../middlewares/jwt.middleware"; + +const router = Router(); + +router.post("/", authorize("vendor", "write"), createVendorController); +router.patch("/:id", authorize("vendor", "write"), updateVendorController); +router.get("/active", authorize("vendor", "read"), getActiveVendorsController); +router.get("/all", authorize("vendor", "read"), getAllVendorsController); +router.delete( + "/:id", + authorize("vendor", "delete"), + deactivateVendorController, +); +router.get("/:id", authorize("vendor", "read"), getVendorByIdController); + +export default router; diff --git a/routes/venue.route.js b/routes/venue.route.js index 22bee36..9d7e1c4 100644 --- a/routes/venue.route.js +++ b/routes/venue.route.js @@ -4,6 +4,8 @@ import { deleteVenueController, getVenuesByEntityController, getVenueController, + getAssignedVenuesController, + getUnassignedVenuesController, } from "../controllers/venue.controller"; import { authorize } from "../middlewares/jwt.middleware"; @@ -15,7 +17,17 @@ router.get( authorize("venue", "read"), getVenuesByEntityController, ); -router.get("/:id", authorize("venue", "read"), getVenueController); +router.get("/details/:id", authorize("venue", "read"), getVenueController); +router.get( + "/assigned/:userId", + authorize("venue", "read"), + getAssignedVenuesController, +); +router.get( + "/unassigned", + authorize("venue", "read"), + getUnassignedVenuesController, +); router.delete("/:id", authorize("venue", "write"), deleteVenueController); export default router;