shuttlepro-shared 1.3.41 → 1.3.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/common/repositories/customerProfile.repository.js +83 -14
  2. package/common/repositories/userRole.repository.js +5 -2
  3. package/config/redis.js +72 -73
  4. package/middlewares/checkPermission/index.js +36 -23
  5. package/models/Activity.js +28 -0
  6. package/models/ActivityLogs.js +1 -0
  7. package/models/AgentActivity.js +5 -4
  8. package/models/Attribute.js +130 -0
  9. package/models/Automation.js +242 -0
  10. package/models/BusinessRule.js +16 -0
  11. package/models/BusinessRuleHelper.js +13 -0
  12. package/models/Card.js +50 -1
  13. package/models/Catalogue.js +22 -0
  14. package/models/Category.js +129 -0
  15. package/models/ChatMemberSession.js +21 -0
  16. package/models/ChatMessage.js +43 -0
  17. package/models/Chatbot.js +1 -1
  18. package/models/Color.js +10 -0
  19. package/models/Column.js +6 -0
  20. package/models/Conversation.js +40 -0
  21. package/models/Customer.js +2 -1
  22. package/models/CustomerCheckpoint.js +21 -0
  23. package/models/DeviceInfo.js +13 -0
  24. package/models/Email.js +21 -0
  25. package/models/EmailMessage.js +30 -0
  26. package/models/EmailNotification.js +17 -0
  27. package/models/EscalationConfiguration.js +123 -0
  28. package/models/EscalationManager.js +50 -0
  29. package/models/Faq.js +29 -0
  30. package/models/FeedbackResponse.js +72 -0
  31. package/models/FormTemplate.js +27 -0
  32. package/models/Integration.js +6 -0
  33. package/models/InternalComments.js +27 -0
  34. package/models/InternalThreads.js +20 -0
  35. package/models/JobDesign.js +32 -0
  36. package/models/JobQueue.js +17 -0
  37. package/models/LabelsPdf.js +12 -0
  38. package/models/Layout.js +12 -0
  39. package/models/LoadSheet.js +31 -0
  40. package/models/Location.js +148 -0
  41. package/models/Logo.js +11 -0
  42. package/models/MailGroup.js +21 -0
  43. package/models/Notification.js +32 -0
  44. package/models/Order.js +11 -0
  45. package/models/OrderPdf.js +29 -0
  46. package/models/PostsAutomation.js +66 -0
  47. package/models/Product.js +337 -0
  48. package/models/ProductAttachment.js +158 -0
  49. package/models/ProductAttribute.js +140 -0
  50. package/models/ProductCategory.js +128 -0
  51. package/models/ProductLabels.js +11 -0
  52. package/models/ProductShopify.js +13 -0
  53. package/models/ProductTag.js +124 -0
  54. package/models/ProductVariant.js +157 -0
  55. package/models/Profile.js +3 -1
  56. package/models/ServiceUsage.js +26 -0
  57. package/models/ShipperSetting.js +24 -0
  58. package/models/SocialGroup.js +127 -0
  59. package/models/SocialPost.js +40 -0
  60. package/models/SocialProfile.js +56 -0
  61. package/models/Story.js +86 -0
  62. package/models/Tag.js +77 -0
  63. package/models/Template.js +76 -0
  64. package/models/TemplateFrame.js +55 -0
  65. package/models/TemplateTag.js +10 -0
  66. package/models/UserGuide.js +21 -0
  67. package/models/UserSession.js +47 -0
  68. package/models/VariantLocation.js +145 -0
  69. package/models/WhatsappFlow.js +29 -0
  70. package/models/Workflow.js +34 -0
  71. package/models/Workspace.js +78 -4
  72. package/models.js +168 -49
  73. package/package.json +1 -1
@@ -1,42 +1,103 @@
1
+ const { getRedisData, setRedisData } = require("../../config/redis");
1
2
  const CustomerProfile = require("../../models/CustomerProfile");
2
3
 
4
+ const CACHE_KEY_ALL = "customer_profiles_all";
5
+
6
+ const getCachedAllCustomerProfiles = async () => {
7
+ let profiles = await getRedisData(CACHE_KEY_ALL);
8
+ if (!profiles) {
9
+ profiles = await CustomerProfile.find({}).lean().exec();
10
+ await setRedisData(CACHE_KEY_ALL, profiles);
11
+ }
12
+ return profiles;
13
+ };
14
+
15
+ const updateCachedAllCustomerProfiles = async () => {
16
+ const profiles = await CustomerProfile.find({}).lean().exec();
17
+ await setRedisData(CACHE_KEY_ALL, profiles);
18
+ };
19
+
20
+ const getCachedCustomerProfiles = async (workspaceId) => {
21
+ const allProfiles = await getCachedAllCustomerProfiles();
22
+ return allProfiles.filter((profile) => profile.workspaceId === workspaceId);
23
+ };
24
+
3
25
  const createCustomerProfile = async (data) => {
4
26
  const newProfile = new CustomerProfile(data);
5
27
  const savedProfile = await newProfile.save();
28
+
29
+ updateCachedAllCustomerProfiles();
6
30
  return savedProfile;
7
31
  };
8
32
 
9
33
  const findCustomerProfilesByWorkspaceId = async (workspaceId) => {
10
- return await CustomerProfile.find({ workspaceId }).lean().exec();
34
+ return await getCachedCustomerProfiles(workspaceId);
11
35
  };
12
36
 
13
37
  const findCustomerProfilesByWorkspace = async (workspaceId, filter = {}) => {
14
- return await CustomerProfile.find({ workspaceId, ...filter })
15
- .lean()
16
- .exec();
38
+ const profiles = await getCachedCustomerProfiles(workspaceId);
39
+ return profiles.filter((profile) =>
40
+ Object.entries(filter).every(([key, value]) => profile[key] === value)
41
+ );
17
42
  };
18
43
 
19
44
  const findCustomerProfileByFilter = async (
20
45
  filter = {},
21
-
46
+ bodyFilter = {},
22
47
  workspaceId = null
23
48
  ) => {
24
- const query = workspaceId ? { ...filter, workspaceId } : filter;
25
- return await CustomerProfile.findOne(query).lean().exec();
49
+ const allProfiles = await getCachedAllCustomerProfiles();
50
+
51
+ const filtered = workspaceId
52
+ ? allProfiles.filter((p) => p.workspaceId === workspaceId)
53
+ : allProfiles;
54
+
55
+ return (
56
+ filtered.find(
57
+ (profile) =>
58
+ Object.entries(filter).every(
59
+ ([key, value]) => profile[key] === value
60
+ ) &&
61
+ Object.entries(bodyFilter).every(
62
+ ([key, value]) => profile.body?.[key] === value
63
+ )
64
+ ) || null
65
+ );
26
66
  };
27
67
 
28
68
  const findAllCustomerProfilesByFilter = async (
29
69
  filter = {},
70
+ bodyFilter = {},
30
71
  workspaceId = null
31
72
  ) => {
32
- const query = workspaceId ? { ...filter, workspaceId } : filter;
33
- return await CustomerProfile.find(query).lean().exec();
73
+ const allProfiles = await getCachedAllCustomerProfiles();
74
+
75
+ const filtered = workspaceId
76
+ ? allProfiles.filter((p) => p.workspaceId === workspaceId)
77
+ : allProfiles;
78
+
79
+ return (
80
+ filtered.filter(
81
+ (profile) =>
82
+ Object.entries(filter).every(
83
+ ([key, value]) => profile[key] === value
84
+ ) &&
85
+ Object.entries(bodyFilter).every(
86
+ ([key, value]) => profile.body?.[key] === value
87
+ )
88
+ ) || []
89
+ );
34
90
  };
35
91
 
36
92
  const updateCustomerProfile = async (id, data) => {
37
93
  const updated = await CustomerProfile.findByIdAndUpdate(id, data, {
38
94
  new: true,
39
95
  }).exec();
96
+
97
+ if (updated) {
98
+ updateCachedAllCustomerProfiles();
99
+ }
100
+
40
101
  return updated;
41
102
  };
42
103
 
@@ -46,24 +107,33 @@ const updateCustomerProfileByFilter = async (
46
107
  workspaceId = null
47
108
  ) => {
48
109
  const query = workspaceId ? { ...filter, workspaceId } : filter;
110
+
49
111
  const updated = await CustomerProfile.findOneAndUpdate(query, data, {
50
112
  new: true,
51
113
  }).exec();
114
+
115
+ if (updated) {
116
+ updateCachedAllCustomerProfiles();
117
+ }
118
+
52
119
  return updated;
53
120
  };
54
121
 
55
122
  const deleteCustomerProfile = async (id) => {
56
123
  const deleted = await CustomerProfile.findByIdAndDelete(id).exec();
124
+
125
+ if (deleted) {
126
+ updateCachedAllCustomerProfiles();
127
+ }
128
+
57
129
  return deleted;
58
130
  };
59
131
 
60
132
  const deleteAllCustomerProfilesByWorkspace = async (workspaceId) => {
61
133
  await CustomerProfile.deleteMany({ workspaceId }).exec();
134
+ await updateCachedAllCustomerProfiles();
62
135
  };
63
- const findAllCustomerProfilesByFilterFromDb = async (filter = {}) => {
64
- const profiles = await CustomerProfile.find(filter).lean().exec();
65
- return profiles ?? [];
66
- };
136
+
67
137
  module.exports = {
68
138
  createCustomerProfile,
69
139
  findCustomerProfilesByWorkspaceId,
@@ -74,5 +144,4 @@ module.exports = {
74
144
  deleteCustomerProfile,
75
145
  deleteAllCustomerProfilesByWorkspace,
76
146
  findAllCustomerProfilesByFilter,
77
- findAllCustomerProfilesByFilterFromDb,
78
147
  };
@@ -2,7 +2,7 @@ const { UserRole } = require("../../models/UserRole");
2
2
  const { getRedisData, setRedisData } = require("../../config/redis");
3
3
 
4
4
  const defaultSelect =
5
- "iconUrl thumbUrl name productsCount ordersCount contact email address websiteUrl facebookUrl twitterUrl instagramUrl members defaultModule";
5
+ "iconUrl thumbUrl name productsCount ordersCount contact email address websiteUrl facebookUrl twitterUrl instagramUrl members defaultModule allowedModules";
6
6
 
7
7
  // Cache keys
8
8
  const MEMBERS = "members";
@@ -35,6 +35,7 @@ const updateCachedMembers = async (workspaceId) => {
35
35
 
36
36
  const getMembers = async (workspaceId) => {
37
37
  let members = await getRedisData(workspaceId, MEMBERS);
38
+
38
39
  if (!members || members?.length === 0) {
39
40
  members = await UserRole.find({ workspaceId })
40
41
  .select("userId role userShift roleId isOwner workspaceId")
@@ -53,6 +54,7 @@ const getMembers = async (workspaceId) => {
53
54
  .exec();
54
55
  await setRedisData(workspaceId, members, MEMBERS, 3600);
55
56
  }
57
+
56
58
  return members;
57
59
  };
58
60
 
@@ -61,7 +63,8 @@ const getMemberByWorkspaceIdAndUserId = async (workspaceId, userId) => {
61
63
  return (
62
64
  members?.find(
63
65
  (member) =>
64
- member?.workspaceId === workspaceId && member?.userId?._id === userId
66
+ member?.workspaceId?.toString() === workspaceId?.toString() &&
67
+ member?.userId?._id?.toString() === userId?.toString()
65
68
  ) || null
66
69
  );
67
70
  };
package/config/redis.js CHANGED
@@ -8,53 +8,51 @@ const client = createClient({
8
8
  url: REDIS_URL,
9
9
  socket: { reconnectStrategy: (retries) => Math.min(retries * 50, 1000) }, // Exponential backoff
10
10
  });
11
-
12
- // ✅ Create separate Pub/Sub clients
13
11
  const publisher = client.duplicate();
14
12
  const subscriber = client.duplicate();
15
13
 
16
- // ✅ Handle Redis Connection Events
17
- client.on("error", (err) => console.error("Redis Error:", err));
18
- client.on("connect", () => console.log("✅ Redis Connected"));
19
- client.on("ready", () => console.log("🚀 Redis Ready to use"));
20
- client.on("end", () => console.log("❗ Redis Connection Closed"));
14
+ // ✅ Redis Events
15
+ const handleEvents = (client, label = "Redis") => {
16
+ client.on("error", (err) => console.error(`❌ ${label} Error:`, err));
17
+ client.on("connect", () => console.log(`✅ ${label} Connected`));
18
+ client.on("ready", () => console.log(`🚀 ${label} Ready to use`));
19
+ client.on("end", () => console.log(`❗ ${label} Connection Closed`));
20
+ client.on("reconnecting", () => console.warn(`🔄 ${label} Reconnecting...`));
21
+ };
22
+
23
+ handleEvents(client, "Main Redis");
24
+ handleEvents(publisher, "Publisher Redis");
25
+ handleEvents(subscriber, "Subscriber Redis");
21
26
 
22
- // ✅ Ensure Redis is connected before performing operations
27
+ // ✅ Ensure Redis is connected once during app startup
23
28
  const connectRedis = async () => {
24
- if (!client.isOpen) {
25
- try {
26
- await client.connect();
27
- await publisher.connect();
28
- await subscriber.connect();
29
- } catch (err) {
30
- console.error("❌ Failed to connect to Redis:", err);
29
+ try {
30
+ if (!client.isOpen) await client.connect();
31
+ if (!publisher.isOpen) await publisher.connect();
32
+ if (!subscriber.isOpen) await subscriber.connect();
33
+
34
+ // Set keyspace events only once
35
+ const config = await client.configGet("notify-keyspace-events");
36
+ if (!config["notify-keyspace-events"]?.includes("Ex")) {
37
+ await client.configSet("notify-keyspace-events", "Ex");
31
38
  }
39
+ } catch (err) {
40
+ console.error("❌ Failed to connect to Redis:", err);
32
41
  }
33
- await client.configSet("notify-keyspace-events", "Ex");
34
42
  };
35
43
 
36
- /**
37
- * ✅ Publish Data to a Channel
38
- * @param {string} channel - The Redis Pub/Sub channel
39
- * @param {any} message - The message to send
40
- */
44
+ // ✅ Publish Data to a Channel
41
45
  const publishToChannel = async (channel, message) => {
42
46
  try {
43
- await connectRedis();
44
47
  await publisher.publish(channel, JSON.stringify(message));
45
48
  } catch (err) {
46
49
  console.error("❌ Error publishing message:", err);
47
50
  }
48
51
  };
49
52
 
50
- /**
51
- * ✅ Subscribe & Listen for Messages
52
- * @param {string} channel - The Redis Pub/Sub channel
53
- * @param {function} callback - Callback function to handle messages
54
- */
53
+ // ✅ Subscribe & Listen for Messages
55
54
  const subscribeToChannel = async (channel, callback, expiry = false) => {
56
55
  try {
57
- await connectRedis();
58
56
  await subscriber.subscribe(channel, (message) => {
59
57
  if (expiry) callback(message);
60
58
  else callback(JSON.parse(message));
@@ -64,13 +62,7 @@ const subscribeToChannel = async (channel, callback, expiry = false) => {
64
62
  }
65
63
  };
66
64
 
67
- /**
68
- * ✅ Set Data in Redis (Supports String & Hash)
69
- * @param {string} key - The Redis key
70
- * @param {any} value - The value to store
71
- * @param {string|null} field - Optional field for Hash storage
72
- * @param {number} expiryInSeconds - Expiry time in seconds (default: 3600)
73
- */
65
+ // ✅ Set Data in Redis (Supports String & Hash)
74
66
  const setRedisData = async (
75
67
  key,
76
68
  value,
@@ -78,7 +70,6 @@ const setRedisData = async (
78
70
  expiryInSeconds = 3600
79
71
  ) => {
80
72
  try {
81
- await connectRedis();
82
73
  const stringifiedValue = JSON.stringify(value);
83
74
  let result;
84
75
 
@@ -99,43 +90,27 @@ const setRedisData = async (
99
90
  }
100
91
  };
101
92
 
102
- const addDataToRedisSet = async (key, value) => {
103
- try {
104
- await connectRedis();
105
- await client.sAdd(key, value);
106
- return true;
107
- } catch (err) {
108
- return false;
109
- }
110
- };
111
-
112
- const removeDataFromRedisSet = async (key, value) => {
113
- try {
114
- await connectRedis();
115
- await client.sRem(key, value);
116
- return true;
117
- } catch (err) {
118
- return false;
119
- }
120
- };
121
- const isMemberOfRedisSet = async (key, value) => {
93
+ // Get Data from Redis (Supports String & Hash)
94
+ const getRedisData = async (key, field = null) => {
122
95
  try {
123
- await connectRedis();
124
- return await client.sIsMember(key, value);
96
+ const result = field
97
+ ? await client.hGet(key, field)
98
+ : await client.get(key);
99
+ return result ? JSON.parse(result) : null;
125
100
  } catch (err) {
126
- console.log(err, "err");
127
- return false;
101
+ console.error("❌ Error getting Redis data:", err);
102
+ return null;
128
103
  }
129
104
  };
130
105
  /**
131
- * ✅ Get Data from Redis (Supports String & Hash)
106
+ * ✅ Get Expiry Time from Redis
132
107
  * @param {string} key - The Redis key
133
108
  * @param {string|null} field - Optional field for Hash retrieval
134
109
  */
135
- const getRedisData = async (key, field = null) => {
110
+ const getRedisDataTime = async (key) => {
136
111
  try {
137
112
  await connectRedis();
138
- let result = field ? await client.hGet(key, field) : await client.get(key);
113
+ let result = await client.ttl(key);
139
114
  return result ? JSON.parse(result) : null;
140
115
  } catch (err) {
141
116
  console.error("❌ Error getting Redis data:", err);
@@ -143,14 +118,9 @@ const getRedisData = async (key, field = null) => {
143
118
  }
144
119
  };
145
120
 
146
- /**
147
- * ✅ Delete Data from Redis (Supports String & Hash)
148
- * @param {string} key - The Redis key
149
- * @param {string|null} field - Optional field for Hash deletion
150
- */
121
+ // ✅ Delete Data from Redis (Supports String & Hash)
151
122
  const deleteRedisData = async (key, field = null) => {
152
123
  try {
153
- await connectRedis();
154
124
  return field ? await client.hDel(key, field) : await client.del(key);
155
125
  } catch (err) {
156
126
  console.error("❌ Error deleting Redis data:", err);
@@ -158,9 +128,37 @@ const deleteRedisData = async (key, field = null) => {
158
128
  }
159
129
  };
160
130
 
161
- /**
162
- * Graceful Shutdown Handling
163
- */
131
+ // ✅ Redis Set Operations
132
+ const addDataToRedisSet = async (key, value) => {
133
+ try {
134
+ await client.sAdd(key, value);
135
+ return true;
136
+ } catch (err) {
137
+ console.error("❌ Error adding to Redis set:", err);
138
+ return false;
139
+ }
140
+ };
141
+
142
+ const removeDataFromRedisSet = async (key, value) => {
143
+ try {
144
+ await client.sRem(key, value);
145
+ return true;
146
+ } catch (err) {
147
+ console.error("❌ Error removing from Redis set:", err);
148
+ return false;
149
+ }
150
+ };
151
+
152
+ const isMemberOfRedisSet = async (key, value) => {
153
+ try {
154
+ return await client.sIsMember(key, value);
155
+ } catch (err) {
156
+ console.error("❌ Error checking membership in Redis set:", err);
157
+ return false;
158
+ }
159
+ };
160
+
161
+ // ✅ Graceful Shutdown
164
162
  const closeClients = async () => {
165
163
  if (client.isOpen) await client.quit();
166
164
  if (publisher.isOpen) await publisher.quit();
@@ -184,12 +182,13 @@ module.exports = {
184
182
  client,
185
183
  publisher,
186
184
  subscriber,
185
+ connectRedis,
187
186
  setRedisData,
187
+ getRedisDataTime,
188
188
  getRedisData,
189
189
  deleteRedisData,
190
190
  publishToChannel,
191
191
  subscribeToChannel,
192
- connectRedis,
193
192
  addDataToRedisSet,
194
193
  removeDataFromRedisSet,
195
194
  isMemberOfRedisSet,
@@ -31,29 +31,42 @@ exports.checkPermission = async (req, res, next, values) => {
31
31
  const accessToken = token.split(" ")[1];
32
32
  const body = getBodyFromDecodeToken(accessToken);
33
33
  if (body) {
34
- const { module, action } = values;
35
- const moduleObj = getModule(body, module);
36
- if (moduleObj && moduleObj.includes(action)) {
37
- req.user = {
38
- id: body.id,
39
- type: body.type,
40
- email: body.email,
41
- firstName: body.firstName,
42
- lastName: body.lastName,
43
- suspended: body.suspended,
44
- isVerified: body.isVerified,
45
- role: body.role,
46
- isMember: body.isMember,
47
- uuid: body.uuid,
48
- };
49
- req.currentModulePermission = moduleObj;
50
- return next();
51
- } else {
52
- return res.status(HttpStatusCode.UNAUTHORIZED).json({
53
- code: HttpStatusCode.UNAUTHORIZED,
54
- message: GenericMessages.PERMISSION_DENIED,
55
- });
56
- }
34
+ req.user = {
35
+ id: body.id,
36
+ type: body.type,
37
+ email: body.email,
38
+ firstName: body.firstName,
39
+ lastName: body.lastName,
40
+ suspended: body.suspended,
41
+ isVerified: body.isVerified,
42
+ role: body.role,
43
+ isMember: body.isMember,
44
+ uuid: body.uuid,
45
+ };
46
+ return next();
47
+ // const { module, action } = values;
48
+ // const moduleObj = getModule(body, module);
49
+ // if (moduleObj && moduleObj.includes(action)) {
50
+ // req.user = {
51
+ // id: body.id,
52
+ // type: body.type,
53
+ // email: body.email,
54
+ // firstName: body.firstName,
55
+ // lastName: body.lastName,
56
+ // suspended: body.suspended,
57
+ // isVerified: body.isVerified,
58
+ // role: body.role,
59
+ // isMember: body.isMember,
60
+ // uuid: body.uuid,
61
+ // };
62
+ // req.currentModulePermission = moduleObj;
63
+ // return next();
64
+ // } else {
65
+ // return res.status(HttpStatusCode.UNAUTHORIZED).json({
66
+ // code: HttpStatusCode.UNAUTHORIZED,
67
+ // message: GenericMessages.PERMISSION_DENIED,
68
+ // });
69
+ // }
57
70
  }
58
71
  return res.status(HttpStatusCode.UNAUTHORIZED).json({
59
72
  code: HttpStatusCode.UNAUTHORIZED,
@@ -0,0 +1,28 @@
1
+ const mongoose = require("mongoose");
2
+ const { Schema } = mongoose;
3
+
4
+ const ActivitySchema = new Schema(
5
+ {
6
+ trackingId: { type: String, default: "" },
7
+ date: { type: String, default: "" },
8
+ name: { type: String, default: "" },
9
+ type: { type: String, default: "" },
10
+ orderId: { type: String, default: "" },
11
+ emailId: { type: Schema.Types.ObjectId, ref: "Email" },
12
+ mailGroupId: { type: Schema.Types.ObjectId, ref: "MailGroup" },
13
+ templateId: { type: Schema.Types.ObjectId, ref: "DescriptionTemplate" },
14
+ message: { type: String, default: "" },
15
+ status: { type: String, default: "" },
16
+ customerName: { type: String, default: "" },
17
+ contact: { type: String, default: "" },
18
+ notificationTimer: { type: String, default: "" },
19
+ scheduledTime: { type: String, default: "" },
20
+ workspaceId: { type: String, default: "" },
21
+ subject: { type: String, default: "" },
22
+ userName: { type: String, default: "" },
23
+ },
24
+ { timestamps: true, toJSON: { virtuals: true }, toObject: { virtuals: true } }
25
+ );
26
+
27
+ const Activity = mongoose.model("Activity", ActivitySchema);
28
+ module.exports = Activity;
@@ -28,6 +28,7 @@ const ActivityLogsSchema = new Schema(
28
28
  type: String,
29
29
  default: "",
30
30
  },
31
+ body: {},
31
32
  },
32
33
  { timestamps: true, toJSON: { virtuals: true }, toObject: { virtuals: true } }
33
34
  );
@@ -47,8 +47,6 @@ const activitySchema = new mongoose.Schema({
47
47
  remarks: { type: String, required: false },
48
48
  avgAccuracy: { type: Number, required: false, default: 10 },
49
49
  sender: { type: String, required: "" },
50
- members: [],
51
- closedBy: {},
52
50
  });
53
51
 
54
52
  const totalActivitySchema = new mongoose.Schema({
@@ -166,7 +164,9 @@ const findOneAndUpdateAgentActivity = async (
166
164
  );
167
165
 
168
166
  if (bsonSize <= 1000000) {
169
- return await AgentActivity.findOneAndUpdate(findQuery, updateQuery);
167
+ return await AgentActivity.findOneAndUpdate(findQuery, updateQuery, {
168
+ new: true,
169
+ });
170
170
  } else {
171
171
  const { breaks, activities, totalActivities, ...restData } =
172
172
  agentActivityForActivitiesUpdated.toObject();
@@ -177,7 +177,8 @@ const findOneAndUpdateAgentActivity = async (
177
177
 
178
178
  const agentActivityRecord = await AgentActivity.findOneAndUpdate(
179
179
  { ...findQuery, _id: newAgentActivity._id },
180
- updateQuery
180
+ updateQuery,
181
+ { new: true }
181
182
  );
182
183
 
183
184
  return agentActivityRecord;
@@ -0,0 +1,130 @@
1
+ const mongoose = require("mongoose");
2
+ const { Schema } = mongoose;
3
+ const AttributeSchema = new Schema(
4
+ {
5
+ name: { type: String, default: "" },
6
+ webAttributeId: { type: Number, default: null },
7
+ parentId: { type: Schema.Types.ObjectId, ref: "Attribute", default: null },
8
+ workspaceId: {
9
+ type: Schema.Types.ObjectId,
10
+ ref: "Workspace",
11
+ default: null,
12
+ },
13
+ oldId: { type: String, default: "" },
14
+ createdBy: { type: Schema.Types.ObjectId, ref: "User", default: null },
15
+ updatedBy: { type: Schema.Types.ObjectId, ref: "User", default: null },
16
+ isDeleted: { type: Boolean, default: false },
17
+ isDefault: { type: Boolean, default: false },
18
+ },
19
+ { timestamps: true, toJSON: { virtuals: true }, toObject: { virtuals: true } }
20
+ );
21
+ AttributeSchema.virtual("values", {
22
+ ref: "Attribute",
23
+ localField: "_id",
24
+ foreignField: "parentId",
25
+ });
26
+
27
+ const Attribute = mongoose.model("Attribute", AttributeSchema);
28
+
29
+ const createNewAttribute = async (attributeData) => {
30
+ try {
31
+ return await Attribute.create(attributeData);
32
+ } catch (error) {
33
+ console.log(error);
34
+ return null;
35
+ }
36
+ };
37
+
38
+ const attributesInsertMany = async (data) => {
39
+ try {
40
+ return await Attribute.insertMany(data);
41
+ } catch (error) {
42
+ return [];
43
+ }
44
+ };
45
+
46
+ const findAttributeById = async (attributeId) => {
47
+ try {
48
+ return await Attribute.findById(attributeId);
49
+ } catch (error) {
50
+ console.log(error);
51
+ return null;
52
+ }
53
+ };
54
+
55
+ const updateAttributeById = async (criteria, updateData, options = {}) => {
56
+ try {
57
+ return await Attribute.findByIdAndUpdate(criteria, updateData, options);
58
+ } catch (error) {
59
+ console.log(error);
60
+ return null;
61
+ }
62
+ };
63
+
64
+ const deleteAttributeById = async (attributeId) => {
65
+ try {
66
+ return await Attribute.findByIdAndDelete(attributeId);
67
+ } catch (error) {
68
+ console.log(error);
69
+ return null;
70
+ }
71
+ };
72
+
73
+ const findAttribute = async (criteria) => {
74
+ try {
75
+ return await Attribute.findOne(criteria);
76
+ } catch (error) {
77
+ console.log(error);
78
+ return null;
79
+ }
80
+ };
81
+
82
+ const findAttributes = async (criteria) => {
83
+ try {
84
+ return await Attribute.find(criteria);
85
+ } catch (error) {
86
+ console.log(error);
87
+ return null;
88
+ }
89
+ };
90
+
91
+ const attributesByAggregation = async (pipeline) => {
92
+ try {
93
+ return await Attribute.aggregate(pipeline);
94
+ } catch (error) {
95
+ console.log(error);
96
+ return null;
97
+ }
98
+ };
99
+
100
+ const attributesUpdateMany = async (criteria, updateData, options = {}) => {
101
+ try {
102
+ return await Attribute.updateMany(criteria, updateData, options);
103
+ } catch (error) {
104
+ console.log(error);
105
+ return null;
106
+ }
107
+ };
108
+
109
+ const findAttributesWithPopulate = async (criteria, populate) => {
110
+ try {
111
+ return await Attribute.find(criteria).populate(populate);
112
+ } catch (error) {
113
+ console.log(error);
114
+ return null;
115
+ }
116
+ };
117
+
118
+ module.exports = {
119
+ Attribute,
120
+ createNewAttribute,
121
+ findAttributeById,
122
+ updateAttributeById,
123
+ deleteAttributeById,
124
+ findAttribute,
125
+ findAttributes,
126
+ attributesByAggregation,
127
+ attributesInsertMany,
128
+ attributesUpdateMany,
129
+ findAttributesWithPopulate,
130
+ };