Compare commits
1
Commits
5e894627f5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be7211ac28 |
@@ -20,7 +20,7 @@ import { getLocationsByQuery } from "../models/Location/operations.js";
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
export const createAccessController = async (req, res) => {
|
export const createAccessController = async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const { user } = res.locals;
|
const { user } = res.locals;
|
||||||
const { employee, designation, department, branch, role } = req.body;
|
const { employee, designation, department, branch, role } = req.body;
|
||||||
@@ -35,7 +35,8 @@ export const createAccessController = async (req, res) => {
|
|||||||
});
|
});
|
||||||
res.status(200).json({ result: access });
|
res.status(200).json({ result: access });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: error.message });
|
console.log("createAccessController Error", error);
|
||||||
|
next(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -203,6 +204,74 @@ export const getAllEmployeeController = async (req, res, next) => {
|
|||||||
preserveNullAndEmptyArrays: true,
|
preserveNullAndEmptyArrays: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: "assignments",
|
||||||
|
localField: "_id",
|
||||||
|
foreignField: "user",
|
||||||
|
as: "assignments",
|
||||||
|
pipeline: [
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$unwind: {
|
||||||
|
path: "$assignments",
|
||||||
|
preserveNullAndEmptyArrays: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: "venues",
|
||||||
|
localField: "assignments.venue",
|
||||||
|
foreignField: "_id",
|
||||||
|
as: "assignments.venue",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$unwind: {
|
||||||
|
path: "$assignments.venue",
|
||||||
|
preserveNullAndEmptyArrays: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: "partners",
|
||||||
|
localField: "assignments.venue.entity",
|
||||||
|
foreignField: "_id",
|
||||||
|
as: "assignments.venue.entity",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$unwind: {
|
||||||
|
path: "$assignments.venue.entity",
|
||||||
|
preserveNullAndEmptyArrays: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// $unwind: {
|
||||||
|
// path: "$assignedVenues",
|
||||||
|
// preserveNullAndEmptyArrays: true,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
$group: {
|
||||||
|
_id: "$_id",
|
||||||
|
name: { $first: "$name" },
|
||||||
|
id: { $first: "$id" },
|
||||||
|
profile: { $first: "$profile" },
|
||||||
|
designation: { $first: "$designation" },
|
||||||
|
department: { $first: "$department" },
|
||||||
|
assignments: {
|
||||||
|
$push: "$assignments",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
$project: {
|
$project: {
|
||||||
_id: 1,
|
_id: 1,
|
||||||
@@ -211,6 +280,7 @@ export const getAllEmployeeController = async (req, res, next) => {
|
|||||||
profile: 1,
|
profile: 1,
|
||||||
designation: "$designation.name",
|
designation: "$designation.name",
|
||||||
department: "$department.name",
|
department: "$department.name",
|
||||||
|
assignments: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import {
|
||||||
|
createEnquiry,
|
||||||
|
updateEnquiry,
|
||||||
|
getAllEnquiries,
|
||||||
|
getEnquiryByQuery,
|
||||||
|
aggregateEnquiry,
|
||||||
|
} from "../models/Enquiry/operations";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
export const createEnquiryController = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { user } = res.locals;
|
||||||
|
const enquiry = await createEnquiry({ ...req.body, createdBy: user.id });
|
||||||
|
return res.json({ result: enquiry });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("createEnquiryController Error", error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getMyEnquiriesController = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const { user } = res.locals;
|
||||||
|
const enquiries = getAllEnquiries({ createdBy: user.id });
|
||||||
|
return res.json({ result: enquiries });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("getMyEnquiriesController Error", error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAllPendingEnquiriesController = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const enquiries = await getAllEnquiries({ status: "CREATED" });
|
||||||
|
return res.json({ result: enquiries });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("getAllPendingEnquiriesController Error", error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAllConfirmedEnquiriesController = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const enquiries = await getAllEnquiries({ status: "CONFIRMED" });
|
||||||
|
return res.json({ result: enquiries });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("getAllConfirmedEnquiriesController Error", error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateEnquiryStatusController = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { status } = req.body;
|
||||||
|
const enquiry = await updateEnquiry(id, { status });
|
||||||
|
return res.json({ result: enquiry });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("updateEnquiryStatusController Error", error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addRemarkToEnquiryController = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const { remark, type, createdBy } = req.body;
|
||||||
|
const enquiry = await updateEnquiry(id, {
|
||||||
|
$push: {
|
||||||
|
remarks: {
|
||||||
|
remark,
|
||||||
|
type,
|
||||||
|
createdBy,
|
||||||
|
createdOn: dayjs().toISOString(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return res.json({ result: enquiry });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("addRemarkToEnquiryController Error", error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getEnquiryByIdController = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const { id } = req.params;
|
||||||
|
const enquiry = await getEnquiryById(id);
|
||||||
|
return res.json({ result: enquiry });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("getEnquiryByIdController Error", error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
getLocationByQuery,
|
getLocationByQuery,
|
||||||
getLocationByRadius,
|
getLocationByRadius,
|
||||||
} from "../models/Location/operations";
|
} from "../models/Location/operations";
|
||||||
|
import { createVisit } from "../models/Visit/operations";
|
||||||
import { aggregateAssignment } from "../models/Assignment/operations";
|
import { aggregateAssignment } from "../models/Assignment/operations";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
@@ -93,13 +94,14 @@ export const createLocationController = async (req, res) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (location.event === "geofence") {
|
if (location.event === "geofence") {
|
||||||
const [assignment, partner, venue] =
|
const { assignment, partner, venue } = location?.geofence?.extras;
|
||||||
location?.geofence?.identifier?.split("-");
|
const visit = await createVisit({ assignment, venue });
|
||||||
const geofencePayload = {
|
const geofencePayload = {
|
||||||
assignment,
|
assignment,
|
||||||
partner,
|
partner,
|
||||||
venue,
|
venue,
|
||||||
action: location?.geofence?.action,
|
action: location?.geofence?.action,
|
||||||
|
visit: visit?._id,
|
||||||
};
|
};
|
||||||
|
|
||||||
dbPayload.geofence = geofencePayload;
|
dbPayload.geofence = geofencePayload;
|
||||||
|
|||||||
@@ -7,17 +7,74 @@ import {
|
|||||||
updatePartner,
|
updatePartner,
|
||||||
aggregatePartner,
|
aggregatePartner,
|
||||||
} from "../models/Partner/operations";
|
} from "../models/Partner/operations";
|
||||||
|
import { aggregateAccess } from "../models/Access/operations";
|
||||||
|
import {
|
||||||
|
createApproval,
|
||||||
|
updateApproval,
|
||||||
|
aggregateApproval,
|
||||||
|
} from "../models/Approval/operations";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { ObjectId } from "mongodb";
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
export const createPartnerController = async (req, res) => {
|
export const createPartnerController = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { user } = res.locals;
|
const { user } = res.locals;
|
||||||
const partner = await createPartner({
|
|
||||||
|
const accessRole = await aggregateAccess([
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
user: ObjectId.createFromHexString(user.id),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: "roles",
|
||||||
|
localField: "role",
|
||||||
|
foreignField: "_id",
|
||||||
|
as: "role",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$unwind: {
|
||||||
|
path: "$role",
|
||||||
|
preserveNullAndEmptyArrays: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
console.log("ACCESS ROLE", accessRole[0]?.role?.modules);
|
||||||
|
|
||||||
|
const isAutoApproved = accessRole[0]?.role?.modules?.some(
|
||||||
|
({ module, permission }) => {
|
||||||
|
return module === "partner" && permission === "authorize";
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const partnerPayload = {
|
||||||
...req.body,
|
...req.body,
|
||||||
createdBy: user.id,
|
createdBy: user.id,
|
||||||
createdOn: dayjs().toISOString(),
|
createdOn: dayjs().toISOString(),
|
||||||
});
|
temp: true,
|
||||||
|
isApproved: isAutoApproved,
|
||||||
|
};
|
||||||
|
|
||||||
|
const approvalPayload = {
|
||||||
|
entity: partner.id,
|
||||||
|
type: "partner",
|
||||||
|
createdBy: user.id,
|
||||||
|
createdOn: dayjs().toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isAutoApproved) {
|
||||||
|
approvalPayload.approvedBy = user.id;
|
||||||
|
approvalPayload.approvedOn = dayjs().toISOString();
|
||||||
|
approvalPayload.isAutoApproved = true;
|
||||||
|
approvalPayload.isApproved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const partner = await createPartner(partnerPayload);
|
||||||
|
|
||||||
|
const approval = await createApproval(approvalPayload);
|
||||||
res.status(200).json({ result: partner });
|
res.status(200).json({ result: partner });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("createPartnerController Error", error);
|
console.log("createPartnerController Error", error);
|
||||||
@@ -39,37 +96,37 @@ export const getPartnerController = async (req, res, next) => {
|
|||||||
// 2. Fetch all invoices for this partner
|
// 2. Fetch all invoices for this partner
|
||||||
{
|
{
|
||||||
$lookup: {
|
$lookup: {
|
||||||
from: "invoices", // Ensure this matches your actual collection name
|
from: "orders", // Ensure this matches your actual collection name
|
||||||
localField: "_id",
|
localField: "_id",
|
||||||
foreignField: "customer",
|
foreignField: "partner",
|
||||||
as: "partnerInvoices",
|
as: "partnerOrders",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// 3. Calculate Invoice Metrics without unwinding (Satisfies Reqs #3, #4, #5)
|
// 3. Calculate Invoice Metrics without unwinding (Satisfies Reqs #3, #4, #5)
|
||||||
{
|
{
|
||||||
$addFields: {
|
$addFields: {
|
||||||
totalInvoicesCount: { $size: "$partnerInvoices" },
|
totalOrdersCount: { $size: "$partnerOrders" },
|
||||||
pendingOrPartialInvoicesCount: {
|
pendingOrPartialOrdersCount: {
|
||||||
$size: {
|
$size: {
|
||||||
$filter: {
|
$filter: {
|
||||||
input: "$partnerInvoices",
|
input: "$partnerOrders",
|
||||||
as: "invoice",
|
as: "order",
|
||||||
cond: {
|
cond: {
|
||||||
$in: ["$$invoice.status", ["PENDING", "PARTIAL"]],
|
$in: ["$$order.status", ["INPROGRESS", "COMPLETED"]],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Note: Your schema uses "PAID", assuming that correlates to "COMPLETED"
|
// Note: Your schema uses "PAID", assuming that correlates to "COMPLETED"
|
||||||
totalInvoicesAmount: { $sum: "$partnerInvoices.total" },
|
totalOrdersAmount: { $sum: "$partnerOrders.total" },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// 4. Remove the heavy invoices array from memory before doing more lookups
|
// 4. Remove the heavy invoices array from memory before doing more lookups
|
||||||
{
|
{
|
||||||
$project: {
|
$project: {
|
||||||
partnerInvoices: 0,
|
partnerOrders: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -163,7 +220,7 @@ export const getPartnerController = async (req, res, next) => {
|
|||||||
|
|
||||||
export const getAllPartnersController = async (req, res) => {
|
export const getAllPartnersController = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const partners = await getAllPartners();
|
const partners = await getPartnersByQuery({ isApproved: true });
|
||||||
res.status(200).json({ result: partners });
|
res.status(200).json({ result: partners });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("getAllPartnersController Error", error);
|
console.log("getAllPartnersController Error", error);
|
||||||
@@ -192,3 +249,59 @@ export const deletePartnerController = async (req, res, next) => {
|
|||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const approvePartnerController = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const { user } = res.locals;
|
||||||
|
const { id } = req.params;
|
||||||
|
|
||||||
|
const approval = await updateApproval(id, {
|
||||||
|
isApproved: true,
|
||||||
|
isAutoApproved: false,
|
||||||
|
approvedBy: user.id,
|
||||||
|
approvedOn: dayjs().toISOString(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const partner = await updatePartner(approval.entity, {
|
||||||
|
isApproved: true,
|
||||||
|
temp: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(200).json({ result: partner });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("approvePartnerController Error", error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getUnapprovedPartnersController = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const pipeline = [
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
isApproved: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: "partners",
|
||||||
|
localField: "entity",
|
||||||
|
foreignField: "_id",
|
||||||
|
as: "partner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$unwind: {
|
||||||
|
path: "$partner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const unapprovedPartners = await aggregateApproval(pipeline);
|
||||||
|
|
||||||
|
res.status(200).json({ result: unapprovedPartners });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("getUnapprovedPartnersController Error", error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createUser, getUserByQuery } from "../models/User/operations.js";
|
import { createUser, getUserByQuery } from "../models/User/operations.js";
|
||||||
|
import { aggregateAccess } from "../models/Access/operations.js";
|
||||||
import bcrypt from "bcrypt";
|
import bcrypt from "bcrypt";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import {
|
import {
|
||||||
@@ -6,6 +7,7 @@ import {
|
|||||||
getRefreshToken,
|
getRefreshToken,
|
||||||
getEncryptedPayload,
|
getEncryptedPayload,
|
||||||
} from "../middlewares/jwt.middleware.js";
|
} from "../middlewares/jwt.middleware.js";
|
||||||
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
export const createUserController = async (req, res, next) => {
|
export const createUserController = async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
@@ -80,3 +82,66 @@ export const renewAccessTokenController = async (req, res, next) => {
|
|||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getAccessibleModulesController = async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const { user } = res.locals;
|
||||||
|
|
||||||
|
const pipeline = [
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
user: ObjectId.createFromHexString(user.id),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: "roles",
|
||||||
|
localField: "role",
|
||||||
|
foreignField: "_id",
|
||||||
|
as: "role",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$unwind: {
|
||||||
|
path: "$role",
|
||||||
|
preserveNullAndEmptyArrays: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: "departments",
|
||||||
|
localField: "department",
|
||||||
|
foreignField: "_id",
|
||||||
|
as: "department",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$unwind: {
|
||||||
|
path: "$department",
|
||||||
|
preserveNullAndEmptyArrays: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: "designations",
|
||||||
|
localField: "designation",
|
||||||
|
foreignField: "_id",
|
||||||
|
as: "designation",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$unwind: {
|
||||||
|
path: "$designation",
|
||||||
|
preserveNullAndEmptyArrays: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const accessibleModules = await aggregateAccess(pipeline)
|
||||||
|
|
||||||
|
res.status(200).json({ result: accessibleModules[0] });
|
||||||
|
} catch (error) {
|
||||||
|
console.log("getAccessibleModulesController Error", error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -11,10 +11,10 @@
|
|||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
"url": "http://localhost:3000/v0/"
|
"url": "http://localhost:3000/v0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://erp-server.triadkube.com/v0/"
|
"url": "https://erp-server.triadkube.com/v0"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"security": [
|
"security": [
|
||||||
@@ -134,6 +134,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/user/accessible-modules": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"User"
|
||||||
|
],
|
||||||
|
"summary": "Get the List of Accessible Modules for a User",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"content": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/profile": {
|
"/profile": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -1029,6 +1043,40 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/partner/{id}/approve": {
|
||||||
|
"tags": [
|
||||||
|
"Partner"
|
||||||
|
],
|
||||||
|
"summary": "Approve a Partner added by an Executive",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"content": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/partner/unapproved": {
|
||||||
|
"tags": [
|
||||||
|
"Partner"
|
||||||
|
],
|
||||||
|
"summary": "Get all Unapproved Partners",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"content": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/venue/": {
|
"/venue/": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ const GENERAL_CONFIG = {
|
|||||||
},
|
},
|
||||||
servers: [
|
servers: [
|
||||||
{
|
{
|
||||||
url: "http://localhost:3000/v0/",
|
url: "http://localhost:3000/v0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: "https://erp-server.triadkube.com/v0/",
|
url: "https://erp-server.triadkube.com/v0",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
security: [
|
security: [
|
||||||
|
|||||||
@@ -213,4 +213,34 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"/partner/{id}/approve": {
|
||||||
|
tags: ["Partner"],
|
||||||
|
summary: "Approve a Partner added by an Executive",
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
in: "path",
|
||||||
|
name: "id",
|
||||||
|
required: true,
|
||||||
|
schema: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: "OK",
|
||||||
|
content: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"/partner/unapproved": {
|
||||||
|
tags: ["Partner"],
|
||||||
|
summary: "Get all Unapproved Partners",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: "OK",
|
||||||
|
content: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -95,4 +95,16 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"/user/accessible-modules": {
|
||||||
|
get: {
|
||||||
|
tags: ["User"],
|
||||||
|
summary: "Get the List of Accessible Modules for a User",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: "OK",
|
||||||
|
content: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -62,30 +62,30 @@ export const authorize = (requiredModule, requiredPermission) => {
|
|||||||
|
|
||||||
// 2. Fetch Access and Populate Role
|
// 2. Fetch Access and Populate Role
|
||||||
// Assuming Access model has a 'user' field and a 'role' field
|
// Assuming Access model has a 'user' field and a 'role' field
|
||||||
const access = await Access.findOne({
|
// const access = await Access.findOne({
|
||||||
user: verifiedPayload.id,
|
// user: verifiedPayload.id,
|
||||||
}).populate("role");
|
// }).populate("role");
|
||||||
|
|
||||||
console.log("access", access?.role?.modules);
|
// console.log("access", access?.role?.modules);
|
||||||
|
|
||||||
if (!access || !access.role) {
|
// if (!access || !access.role) {
|
||||||
throw { code: 403, message: "No role assigned to this user" };
|
// throw { code: 403, message: "No role assigned to this user" };
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 3. Verify Permissions
|
// // 3. Verify Permissions
|
||||||
const hasPermission = access?.role?.modules?.some(
|
// const hasPermission = access?.role?.modules?.some(
|
||||||
(mod) =>
|
// (mod) =>
|
||||||
(mod.module === requiredModule &&
|
// (mod.module === requiredModule &&
|
||||||
mod.permission === requiredPermission) ||
|
// mod.permission === requiredPermission) ||
|
||||||
(requiredModule === "generic" && requiredPermission === "generic"),
|
// (requiredModule === "generic" && requiredPermission === "generic"),
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (!hasPermission) {
|
// if (!hasPermission) {
|
||||||
throw {
|
// throw {
|
||||||
code: 403,
|
// code: 403,
|
||||||
message: `Insufficient permissions for ${requiredModule} (${requiredPermission})`,
|
// message: `Insufficient permissions for ${requiredModule} (${requiredPermission})`,
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
res.locals.user = verifiedPayload;
|
res.locals.user = verifiedPayload;
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ const schema = new Schema({
|
|||||||
},
|
},
|
||||||
city: {
|
city: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: false,
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { model, Schema, Types } from "mongoose";
|
||||||
|
|
||||||
|
const schema = new Schema({
|
||||||
|
entity: {
|
||||||
|
type: Types.ObjectId,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
enum: ["user", "partner", "vendor", "expense"],
|
||||||
|
},
|
||||||
|
createdBy: {
|
||||||
|
type: Types.ObjectId,
|
||||||
|
ref: "user",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
approvedBy: {
|
||||||
|
type: Types.ObjectId,
|
||||||
|
ref: "user",
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
createdOn: {
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
approvedOn: {
|
||||||
|
type: Date,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
isAutoApproved: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
isApproved: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default model("approval", schema);
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import Model from "./model.js";
|
||||||
|
|
||||||
|
// Create
|
||||||
|
export const createApproval = async (data) => {
|
||||||
|
return await Model.create(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read (Get by ID)
|
||||||
|
export const getApprovalById = async (id) => {
|
||||||
|
return await Model.findById(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read (Get by Query)
|
||||||
|
export const getApprovalByQuery = async (query) => {
|
||||||
|
return await Model.findOne(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read (Get all)
|
||||||
|
export const getAllApprovals = async () => {
|
||||||
|
return await Model.find();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update
|
||||||
|
export const updateApproval = async (id, data) => {
|
||||||
|
return await Model.findByIdAndUpdate(id, data, { new: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Aggregate
|
||||||
|
export const aggregateApproval = async (pipeline) => {
|
||||||
|
return await Model.aggregate(pipeline);
|
||||||
|
};
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { model, Schema, Types } from "mongoose";
|
||||||
|
|
||||||
|
const itemSchema = new Schema({
|
||||||
|
product: {
|
||||||
|
type: Types.ObjectId,
|
||||||
|
required: true,
|
||||||
|
ref: "product",
|
||||||
|
},
|
||||||
|
quantity: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
finalRate: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const remarksSchema = new Schema({
|
||||||
|
createdOn: {
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
createdBy: {
|
||||||
|
type: Types.ObjectId,
|
||||||
|
required: true,
|
||||||
|
ref: "user",
|
||||||
|
},
|
||||||
|
remarks: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
enum: ["REJECTION REASON", "CANCELLATION REASON", "OTHER"],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const schema = new Schema({
|
||||||
|
createdBy: {
|
||||||
|
type: Types.ObjectId,
|
||||||
|
required: true,
|
||||||
|
ref: "user",
|
||||||
|
},
|
||||||
|
createdOn: {
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
type: [itemSchema],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
totalValue: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: "CREATED",
|
||||||
|
enum: ["CREATED", "CONFIRMED", "REJECTED", "CANCELLED", "COMPLETED"],
|
||||||
|
},
|
||||||
|
shippingAddress: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
remarks: {
|
||||||
|
type: [remarksSchema],
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default model("enquiry", schema);
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import Model from "./model.js";
|
||||||
|
|
||||||
|
// Create
|
||||||
|
export const createEnquiry = async (data) => {
|
||||||
|
return await Model.create(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read (Get by ID)
|
||||||
|
export const getEnquiryById = async (id) => {
|
||||||
|
return await Model.findById(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read (Get by Query)
|
||||||
|
export const getEnquiryByQuery = async (query) => {
|
||||||
|
return await Model.findOne(query);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read (Get all)
|
||||||
|
export const getAllEnquiries = async (query) => {
|
||||||
|
return await Model.find(query);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update
|
||||||
|
export const updateEnquiry = async (id, data) => {
|
||||||
|
return await Model.findByIdAndUpdate(id, data, { new: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Aggregate
|
||||||
|
export const aggregateEnquiry = async (pipeline) => {
|
||||||
|
return await Model.aggregate(pipeline);
|
||||||
|
};
|
||||||
@@ -16,6 +16,10 @@ const geofenceSchema = new Schema({
|
|||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
visit: {
|
||||||
|
type: Types.ObjectId,
|
||||||
|
ref: "visit",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const schema = new Schema({
|
const schema = new Schema({
|
||||||
|
|||||||
@@ -76,6 +76,14 @@ const schema = new Schema({
|
|||||||
type: [contactPersonSchema],
|
type: [contactPersonSchema],
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
isApproved: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isTemp: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default model("partner", schema);
|
export default model("partner", schema);
|
||||||
|
|||||||
@@ -27,12 +27,13 @@ const schema = new Schema({
|
|||||||
},
|
},
|
||||||
createdBy: {
|
createdBy: {
|
||||||
type: Types.ObjectId,
|
type: Types.ObjectId,
|
||||||
required: true,
|
required: false,
|
||||||
ref: "user",
|
ref: "user",
|
||||||
},
|
},
|
||||||
isActive: {
|
isActive: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true,
|
required: true,
|
||||||
|
default: true
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { model, Schema, Types } from "mongoose";
|
||||||
|
|
||||||
|
const schema = new Schema({
|
||||||
|
createdOn: {
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
type: Types.ObjectId,
|
||||||
|
required: true,
|
||||||
|
ref: "user",
|
||||||
|
},
|
||||||
|
venue: {
|
||||||
|
type: Types.ObjectId,
|
||||||
|
required: true,
|
||||||
|
ref: "venue",
|
||||||
|
},
|
||||||
|
assignment: {
|
||||||
|
type: Types.ObjectId,
|
||||||
|
required: true,
|
||||||
|
ref: "assignment",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default model("visit", schema);
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import Model from "./model.js";
|
||||||
|
|
||||||
|
// Create
|
||||||
|
export const createVisit = async (data) => {
|
||||||
|
return await Model.create(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read (Get by ID)
|
||||||
|
export const getVisitById = async (id) => {
|
||||||
|
return await Model.findById(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read (Get by Query)
|
||||||
|
export const getVisitByQuery = async (query) => {
|
||||||
|
return await Model.findOne(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read (Get all)
|
||||||
|
export const getAllVisits = async () => {
|
||||||
|
return await Model.find();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update
|
||||||
|
export const updateVisit = async (id, data) => {
|
||||||
|
return await Model.findByIdAndUpdate(id, data, { new: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Aggregate
|
||||||
|
export const aggregateVisit = async (pipeline) => {
|
||||||
|
return await Model.aggregate(pipeline);
|
||||||
|
};
|
||||||
@@ -9,7 +9,6 @@ export { default as Salary } from "./Salary/model";
|
|||||||
export { default as Vendor } from "./Vendor/model";
|
export { default as Vendor } from "./Vendor/model";
|
||||||
export { default as Expense } from "./Expense/model";
|
export { default as Expense } from "./Expense/model";
|
||||||
export { default as Product } from "./Product/model";
|
export { default as Product } from "./Product/model";
|
||||||
export { default as Invoice } from "./Invoice/model";
|
|
||||||
export { default as Partner } from "./Partner/model";
|
export { default as Partner } from "./Partner/model";
|
||||||
export { default as Activity } from "./Activity/model";
|
export { default as Activity } from "./Activity/model";
|
||||||
export { default as Location } from "./Location/model";
|
export { default as Location } from "./Location/model";
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import {
|
|||||||
getAllPartnersController,
|
getAllPartnersController,
|
||||||
updatePartnerController,
|
updatePartnerController,
|
||||||
deletePartnerController,
|
deletePartnerController,
|
||||||
|
approvePartnerController,
|
||||||
|
getUnapprovedPartnersController,
|
||||||
} from "../controllers/partner.controller";
|
} from "../controllers/partner.controller";
|
||||||
import { authorize } from "../middlewares/jwt.middleware";
|
import { authorize } from "../middlewares/jwt.middleware";
|
||||||
|
|
||||||
@@ -13,6 +15,16 @@ const router = new Router();
|
|||||||
|
|
||||||
router.post("/", authorize("partner", "write"), createPartnerController);
|
router.post("/", authorize("partner", "write"), createPartnerController);
|
||||||
router.get("/", authorize("partner", "read"), getAllPartnersController);
|
router.get("/", authorize("partner", "read"), getAllPartnersController);
|
||||||
|
router.patch(
|
||||||
|
"/:id/approve",
|
||||||
|
authorize("partner", "authorize"),
|
||||||
|
approvePartnerController,
|
||||||
|
);
|
||||||
|
router.get(
|
||||||
|
"/unapproved",
|
||||||
|
authorize("partner", "authorize"),
|
||||||
|
getUnapprovedPartnersController,
|
||||||
|
);
|
||||||
router.get("/:id", authorize("partner", "read"), getPartnerController);
|
router.get("/:id", authorize("partner", "read"), getPartnerController);
|
||||||
router.patch("/:id", authorize("partner", "write"), updatePartnerController);
|
router.patch("/:id", authorize("partner", "write"), updatePartnerController);
|
||||||
router.delete("/:id", authorize("partner", "write"), deletePartnerController);
|
router.delete("/:id", authorize("partner", "write"), deletePartnerController);
|
||||||
|
|||||||
@@ -3,12 +3,19 @@ import {
|
|||||||
createUserController,
|
createUserController,
|
||||||
loginController,
|
loginController,
|
||||||
renewAccessTokenController,
|
renewAccessTokenController,
|
||||||
|
getAccessibleModulesController,
|
||||||
} from "../controllers/user.controller";
|
} from "../controllers/user.controller";
|
||||||
|
import { authorize } from "../middlewares/jwt.middleware";
|
||||||
|
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
router.post("/create", createUserController);
|
router.post("/create", createUserController);
|
||||||
router.post("/login", loginController);
|
router.post("/login", loginController);
|
||||||
router.post("/token/renew", renewAccessTokenController);
|
router.post("/token/renew", renewAccessTokenController);
|
||||||
|
router.get(
|
||||||
|
"/accessible-modules",
|
||||||
|
authorize("generic", "generic"),
|
||||||
|
getAccessibleModulesController,
|
||||||
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
Reference in New Issue
Block a user