Abhises commited on
Commit
0ccfbbc
·
1 Parent(s): 5134e36
prisma/schema.prisma CHANGED
@@ -54,6 +54,8 @@ model ExchangeThread {
54
  receiverWorkspaceId String
55
  stage String @default("NEW") // NEW | CHAT | PLACED
56
  status String @default("PENDING") // PENDING | ACCEPTED | REJECTED
 
 
57
  createdAt DateTime @default(now())
58
  updatedAt DateTime @updatedAt
59
 
 
54
  receiverWorkspaceId String
55
  stage String @default("NEW") // NEW | CHAT | PLACED
56
  status String @default("PENDING") // PENDING | ACCEPTED | REJECTED
57
+ giverAccepted Boolean @default(false)
58
+ receiverAccepted Boolean @default(false)
59
  createdAt DateTime @default(now())
60
  updatedAt DateTime @updatedAt
61
 
src/controllers/threads.js CHANGED
@@ -141,36 +141,71 @@ const updateThreadStatus = async (req, res) => {
141
  const thread = await prisma.exchangeThread.findUnique({ where: { id: req.params.id } });
142
  if (!thread) return res.status(404).json({ error: 'Thread not found' });
143
 
144
- // Only receiver can approve/reject
145
- if (thread.receiverWorkspaceId !== member.workspaceId) {
146
- return res.status(403).json({ error: 'Only the receiver can approve or reject' });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  }
148
 
149
  const updated = await prisma.exchangeThread.update({
150
  where: { id: req.params.id },
151
- data: {
152
- status,
153
- stage: status === 'ACCEPTED' ? 'CHAT' : 'NEW',
154
- },
155
  include: {
156
  giverWorkspace: true,
157
  receiverWorkspace: true,
158
  },
159
  });
160
 
161
- if (status === 'ACCEPTED') {
162
- wsManager.sendNotification(updated.giverWorkspaceId, {
 
 
 
 
 
 
 
 
 
 
 
163
  type: 'connection_accepted',
164
  threadId: updated.id,
165
- receiverWorkspaceName: updated.receiverWorkspace.websiteName,
166
- receiverWorkspaceDomain: updated.receiverWorkspace.domain,
167
  });
168
- } else if (status === 'REJECTED') {
169
- wsManager.sendNotification(updated.giverWorkspaceId, {
170
  type: 'connection_rejected',
171
  threadId: updated.id,
172
- receiverWorkspaceName: updated.receiverWorkspace.websiteName,
173
- receiverWorkspaceDomain: updated.receiverWorkspace.domain,
174
  });
175
  }
176
 
 
141
  const thread = await prisma.exchangeThread.findUnique({ where: { id: req.params.id } });
142
  if (!thread) return res.status(404).json({ error: 'Thread not found' });
143
 
144
+ const isGiver = thread.giverWorkspaceId === member.workspaceId;
145
+ const isReceiver = thread.receiverWorkspaceId === member.workspaceId;
146
+
147
+ if (!isGiver && !isReceiver) {
148
+ return res.status(403).json({ error: 'Access denied' });
149
+ }
150
+
151
+ let updateData = {};
152
+ let newStatus = thread.status;
153
+ let newStage = thread.stage;
154
+
155
+ let giverAccepted = thread.giverAccepted;
156
+ let receiverAccepted = thread.receiverAccepted;
157
+
158
+ if (status === 'REJECTED') {
159
+ newStatus = 'REJECTED';
160
+ newStage = 'NEW';
161
+ updateData = { status: newStatus, stage: newStage };
162
+ } else if (status === 'ACCEPTED') {
163
+ if (isGiver) giverAccepted = true;
164
+ if (isReceiver) receiverAccepted = true;
165
+
166
+ updateData = { giverAccepted, receiverAccepted };
167
+
168
+ if (giverAccepted && receiverAccepted) {
169
+ newStatus = 'ACCEPTED';
170
+ newStage = 'CHAT';
171
+ updateData.status = newStatus;
172
+ updateData.stage = newStage;
173
+ }
174
  }
175
 
176
  const updated = await prisma.exchangeThread.update({
177
  where: { id: req.params.id },
178
+ data: updateData,
 
 
 
179
  include: {
180
  giverWorkspace: true,
181
  receiverWorkspace: true,
182
  },
183
  });
184
 
185
+ // Determine who to notify
186
+ const otherId = isGiver ? thread.receiverWorkspaceId : thread.giverWorkspaceId;
187
+ const selfWorkspace = isGiver ? updated.giverWorkspace : updated.receiverWorkspace;
188
+
189
+ if (newStatus === 'ACCEPTED' && newStage === 'CHAT') {
190
+ wsManager.sendNotification(otherId, {
191
+ type: 'connection_accepted',
192
+ threadId: updated.id,
193
+ receiverWorkspaceName: selfWorkspace.websiteName,
194
+ receiverWorkspaceDomain: selfWorkspace.domain,
195
+ });
196
+ // also notify self just in case
197
+ wsManager.sendNotification(member.workspaceId, {
198
  type: 'connection_accepted',
199
  threadId: updated.id,
200
+ receiverWorkspaceName: selfWorkspace.websiteName,
201
+ receiverWorkspaceDomain: selfWorkspace.domain,
202
  });
203
+ } else if (newStatus === 'REJECTED') {
204
+ wsManager.sendNotification(otherId, {
205
  type: 'connection_rejected',
206
  threadId: updated.id,
207
+ receiverWorkspaceName: selfWorkspace.websiteName,
208
+ receiverWorkspaceDomain: selfWorkspace.domain,
209
  });
210
  }
211
 
src/jobs/matcher.js CHANGED
@@ -3,7 +3,7 @@ const cron = require('node-cron');
3
  const wsManager = require('../lib/ws');
4
 
5
  const runWeeklyMatching = async () => {
6
- console.log('Running automated connection matching algorithm...');
7
  try {
8
  // Fetch workspaces that belong ONLY to non-admin users
9
  // A workspace has teamMembers, we check if they are owned by an ADMIN
@@ -19,7 +19,7 @@ const runWeeklyMatching = async () => {
19
  }
20
  });
21
  if (workspaces.length < 2) {
22
- console.log('Not enough workspaces for matching.');
23
  return { success: false, message: 'Not enough workspaces to perform matching.' };
24
  }
25
 
@@ -137,10 +137,10 @@ const runWeeklyMatching = async () => {
137
  }
138
  }
139
 
140
- console.log(`Matching completed successfully. Created ${createdCount} new connections.`);
141
  return { success: true, count: createdCount };
142
  } catch (error) {
143
- console.error('Error in matching algorithm:', error);
144
  return { success: false, error: error.message };
145
  }
146
  };
@@ -158,9 +158,9 @@ const initCron = async () => {
158
  activeJob = cron.schedule(expr, () => {
159
  runWeeklyMatching();
160
  });
161
- console.log(`Initialized matchmaking cron job with expression: ${expr}`);
162
  } catch (err) {
163
- console.error('Failed to init cron:', err);
164
  }
165
  };
166
 
 
3
  const wsManager = require('../lib/ws');
4
 
5
  const runWeeklyMatching = async () => {
6
+ console.log(`[${new Date().toISOString()}] Running automated connection matching algorithm...`);
7
  try {
8
  // Fetch workspaces that belong ONLY to non-admin users
9
  // A workspace has teamMembers, we check if they are owned by an ADMIN
 
19
  }
20
  });
21
  if (workspaces.length < 2) {
22
+ console.log(`[${new Date().toISOString()}] Not enough workspaces for matching.`);
23
  return { success: false, message: 'Not enough workspaces to perform matching.' };
24
  }
25
 
 
137
  }
138
  }
139
 
140
+ console.log(`[${new Date().toISOString()}] Matching completed successfully. Created ${createdCount} new connections.`);
141
  return { success: true, count: createdCount };
142
  } catch (error) {
143
+ console.error(`[${new Date().toISOString()}] Error in matching algorithm:`, error);
144
  return { success: false, error: error.message };
145
  }
146
  };
 
158
  activeJob = cron.schedule(expr, () => {
159
  runWeeklyMatching();
160
  });
161
+ console.log(`[${new Date().toISOString()}] Initialized matchmaking cron job with expression: ${expr}`);
162
  } catch (err) {
163
+ console.error(`[${new Date().toISOString()}] Failed to init cron:`, err);
164
  }
165
  };
166