feature/IO-3000-messaging-sockets-migration2 - Final fixes around sync / archive / receive

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-11-25 11:38:59 -08:00
parent 239c1502f9
commit 62dd3d7e8e
3 changed files with 77 additions and 47 deletions

View File

@@ -42,10 +42,13 @@ export function* openChatByPhone({ payload }) {
} = yield client.query({ } = yield client.query({
query: CONVERSATION_ID_BY_PHONE, query: CONVERSATION_ID_BY_PHONE,
variables: { phone: p.number }, variables: { phone: p.number },
fetchPolicy: "network-only" // THIS NEEDS TO REMAIN NO CACHE, IT CHECKS FOR NEW MESSAGES FOR SYNC
fetchPolicy: "no-cache"
}); });
if (conversations.length === 0) { const existingConversation = conversations?.find((c) => c.phone_num === phone_num);
if (!existingConversation) {
// No conversation exists, create a new one // No conversation exists, create a new one
const { const {
data: { data: {
@@ -75,18 +78,17 @@ export function* openChatByPhone({ payload }) {
// Set the newly created conversation as selected // Set the newly created conversation as selected
yield put(setSelectedConversation(createdConversation.id)); yield put(setSelectedConversation(createdConversation.id));
} else if (conversations.length === 1) { } else {
const conversation = conversations[0]; let updatedConversation = existingConversation;
let updatedConversation = conversation;
if (conversation.archived) { if (existingConversation.archived) {
// Conversation is archived, unarchive it in the DB // Conversation is archived, unarchive it in the DB
const { const {
data: { update_conversations_by_pk: unarchivedConversation } data: { update_conversations_by_pk: unarchivedConversation }
} = yield client.mutate({ } = yield client.mutate({
mutation: TOGGLE_CONVERSATION_ARCHIVE, mutation: TOGGLE_CONVERSATION_ARCHIVE,
variables: { variables: {
id: conversation.id, id: existingConversation.id,
archived: false archived: false
} }
}); });
@@ -115,10 +117,6 @@ export function* openChatByPhone({ payload }) {
} }
}); });
} }
} else {
// Multiple conversations found
console.error("ERROR: Multiple conversations found.");
yield put(setSelectedConversation(null));
} }
} catch (error) { } catch (error) {
console.error("Error in openChatByPhone saga.", error); console.error("Error in openChatByPhone saga.", error);

View File

@@ -2577,3 +2577,34 @@ exports.MARK_MESSAGES_AS_READ = `mutation MARK_MESSAGES_AS_READ($conversationId:
} }
} }
`; `;
exports.CREATE_CONVERSATION = `mutation CREATE_CONVERSATION($conversation: [conversations_insert_input!]!) {
insert_conversations(objects: $conversation) {
returning {
id
phone_num
archived
label
unreadcnt
job_conversations {
jobid
conversationid
job {
id
ro_number
ownr_fn
ownr_ln
ownr_co_nm
}
}
messages_aggregate(where: { read: { _eq: false }, isoutbound: { _eq: false } }) {
aggregate {
count
}
}
created_at
updated_at
}
}
}
`;

View File

@@ -34,6 +34,7 @@ exports.receive = async (req, res) => {
} }
try { try {
// Step 1: Find the bodyshop and existing conversation
const response = await client.request(queries.FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID, { const response = await client.request(queries.FIND_BODYSHOP_BY_MESSAGING_SERVICE_SID, {
mssid: req.body.MessagingServiceSid, mssid: req.body.MessagingServiceSid,
phone: phone(req.body.From).phoneNumber phone: phone(req.body.From).phoneNumber
@@ -44,53 +45,51 @@ exports.receive = async (req, res) => {
} }
const bodyshop = response.bodyshops[0]; const bodyshop = response.bodyshops[0];
const isNewConversation = bodyshop.conversations.length === 0; const existingConversation = bodyshop.conversations[0]; // Expect only one conversation per phone number per bodyshop
const isDuplicate = bodyshop.conversations.length > 1;
let conversationid;
let newMessage = { let newMessage = {
msid: req.body.SmsMessageSid, msid: req.body.SmsMessageSid,
text: req.body.Body, text: req.body.Body,
image: !!req.body.MediaUrl0, image: !!req.body.MediaUrl0,
image_path: generateMediaArray(req.body) image_path: generateMediaArray(req.body),
isoutbound: false,
userid: null // Add additional fields as necessary
}; };
if (isDuplicate) { if (existingConversation) {
logger.log("sms-inbound-error", "ERROR", "api", null, { // Use the existing conversation
...loggerData, conversationid = existingConversation.id;
messagingServiceSid: req.body.MessagingServiceSid,
type: "duplicate-phone"
});
return res.status(400).json({ success: false, error: "Duplicate phone number" });
}
if (isNewConversation) { // Unarchive the conversation if necessary
newMessage.conversation = { if (existingConversation.archived) {
data: { await client.request(queries.UNARCHIVE_CONVERSATION, {
id: conversationid,
archived: false
});
}
} else {
// Create a new conversation
const newConversationResponse = await client.request(queries.CREATE_CONVERSATION, {
conversation: {
bodyshopid: bodyshop.id, bodyshopid: bodyshop.id,
phone_num: phone(req.body.From).phoneNumber, phone_num: phone(req.body.From).phoneNumber,
archived: false archived: false
} }
}; });
} else { const createdConversation = newConversationResponse.insert_conversations.returning[0];
const existingConversation = bodyshop.conversations[0]; conversationid = createdConversation.id;
// Update the conversation to unarchive it
if (existingConversation.archived) {
await client.request(queries.UNARCHIVE_CONVERSATION, {
id: existingConversation.id,
archived: false
});
}
newMessage.conversationid = existingConversation.id;
} }
const query = isNewConversation ? queries.RECEIVE_MESSAGE : queries.INSERT_MESSAGE; // Ensure `conversationid` is added to the message
const variables = isNewConversation newMessage.conversationid = conversationid;
? { msg: newMessage }
: { msg: newMessage, conversationid: newMessage.conversationid }; // Step 3: Insert the message into the conversation
const insertresp = await client.request(queries.INSERT_MESSAGE, {
msg: newMessage,
conversationid: conversationid
});
const insertresp = await client.request(query, variables);
const message = insertresp?.insert_messages?.returning?.[0]; const message = insertresp?.insert_messages?.returning?.[0];
const conversation = message?.conversation || null; const conversation = message?.conversation || null;
@@ -98,6 +97,7 @@ exports.receive = async (req, res) => {
throw new Error("Conversation data is missing from the response."); throw new Error("Conversation data is missing from the response.");
} }
// Step 4: Notify clients through Redis
const broadcastRoom = getBodyshopRoom(conversation.bodyshop.id); const broadcastRoom = getBodyshopRoom(conversation.bodyshop.id);
const conversationRoom = getBodyshopConversationRoom({ const conversationRoom = getBodyshopConversationRoom({
bodyshopId: conversation.bodyshop.id, bodyshopId: conversation.bodyshop.id,
@@ -113,19 +113,20 @@ exports.receive = async (req, res) => {
ioRedis.to(broadcastRoom).emit("new-message-summary", { ioRedis.to(broadcastRoom).emit("new-message-summary", {
...commonPayload, ...commonPayload,
existingConversation: !isNewConversation, existingConversation: !!existingConversation,
newConversation: isNewConversation ? conversation : null, newConversation: !existingConversation ? conversation : null,
summary: true summary: true
}); });
ioRedis.to(conversationRoom).emit("new-message-detailed", { ioRedis.to(conversationRoom).emit("new-message-detailed", {
newMessage: message, newMessage: message,
...commonPayload, ...commonPayload,
newConversation: isNewConversation ? conversation : null, newConversation: !existingConversation ? conversation : null,
existingConversation: !isNewConversation, existingConversation: !!existingConversation,
summary: false summary: false
}); });
// Step 5: Send FCM notification
const fcmresp = await admin.messaging().send({ const fcmresp = await admin.messaging().send({
topic: `${message.conversation.bodyshop.imexshopid}-messaging`, topic: `${message.conversation.bodyshop.imexshopid}-messaging`,
notification: { notification: {