Emit message event with actual message object (#11548)
Events were emitted with the wrong object. We were using messageWithParticipant instead of actual message object
This commit is contained in:
@ -17,7 +17,10 @@ export class MessagingMessageService {
|
|||||||
messages: MessageWithParticipants[],
|
messages: MessageWithParticipants[],
|
||||||
messageChannelId: string,
|
messageChannelId: string,
|
||||||
transactionManager: EntityManager,
|
transactionManager: EntityManager,
|
||||||
): Promise<Map<string, string>> {
|
): Promise<{
|
||||||
|
createdMessages: Partial<MessageWorkspaceEntity>[];
|
||||||
|
messageExternalIdsAndIdsMap: Map<string, string>;
|
||||||
|
}> {
|
||||||
const messageChannelMessageAssociationRepository =
|
const messageChannelMessageAssociationRepository =
|
||||||
await this.twentyORMManager.getRepository<MessageChannelMessageAssociationWorkspaceEntity>(
|
await this.twentyORMManager.getRepository<MessageChannelMessageAssociationWorkspaceEntity>(
|
||||||
'messageChannelMessageAssociation',
|
'messageChannelMessageAssociation',
|
||||||
@ -34,6 +37,7 @@ export class MessagingMessageService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const messageExternalIdsAndIdsMap = new Map<string, string>();
|
const messageExternalIdsAndIdsMap = new Map<string, string>();
|
||||||
|
const createdMessages: Partial<MessageWorkspaceEntity>[] = [];
|
||||||
|
|
||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
const existingMessageChannelMessageAssociation =
|
const existingMessageChannelMessageAssociation =
|
||||||
@ -101,18 +105,18 @@ export class MessagingMessageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const newMessageId = v4();
|
const newMessageId = v4();
|
||||||
|
const messageToCreate = {
|
||||||
|
id: newMessageId,
|
||||||
|
headerMessageId: message.headerMessageId,
|
||||||
|
subject: message.subject,
|
||||||
|
receivedAt: message.receivedAt,
|
||||||
|
text: message.text,
|
||||||
|
messageThreadId: newOrExistingMessageThreadId,
|
||||||
|
};
|
||||||
|
|
||||||
await messageRepository.insert(
|
await messageRepository.insert(messageToCreate, transactionManager);
|
||||||
{
|
|
||||||
id: newMessageId,
|
createdMessages.push(messageToCreate);
|
||||||
headerMessageId: message.headerMessageId,
|
|
||||||
subject: message.subject,
|
|
||||||
receivedAt: message.receivedAt,
|
|
||||||
text: message.text,
|
|
||||||
messageThreadId: newOrExistingMessageThreadId,
|
|
||||||
},
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
messageExternalIdsAndIdsMap.set(message.externalId, newMessageId);
|
messageExternalIdsAndIdsMap.set(message.externalId, newMessageId);
|
||||||
|
|
||||||
@ -128,6 +132,9 @@ export class MessagingMessageService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return messageExternalIdsAndIdsMap;
|
return {
|
||||||
|
createdMessages,
|
||||||
|
messageExternalIdsAndIdsMap,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -119,12 +119,16 @@ describe('MessagingSaveMessagesAndEnqueueContactCreationService', () => {
|
|||||||
{
|
{
|
||||||
provide: MessagingMessageService,
|
provide: MessagingMessageService,
|
||||||
useValue: {
|
useValue: {
|
||||||
saveMessagesWithinTransaction: jest.fn().mockResolvedValue(
|
saveMessagesWithinTransaction: jest.fn().mockResolvedValue({
|
||||||
new Map([
|
messageExternalIdsAndIdsMap: new Map([
|
||||||
['message-1', 'db-message-id-1'],
|
['message-1', 'db-message-id-1'],
|
||||||
['message-2', 'db-message-id-2'],
|
['message-2', 'db-message-id-2'],
|
||||||
]),
|
]),
|
||||||
),
|
createdMessages: [
|
||||||
|
{ id: 'db-message-id-1' },
|
||||||
|
{ id: 'db-message-id-2' },
|
||||||
|
],
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -53,70 +53,76 @@ export class MessagingSaveMessagesAndEnqueueContactCreationService {
|
|||||||
|
|
||||||
const workspaceDataSource = await this.twentyORMManager.getDatasource();
|
const workspaceDataSource = await this.twentyORMManager.getDatasource();
|
||||||
|
|
||||||
const participantsWithMessageId = await workspaceDataSource?.transaction(
|
const createdMessagesWithParticipants =
|
||||||
async (transactionManager: EntityManager) => {
|
await workspaceDataSource?.transaction(
|
||||||
const messageExternalIdsAndIdsMap =
|
async (transactionManager: EntityManager) => {
|
||||||
await this.messageService.saveMessagesWithinTransaction(
|
const { messageExternalIdsAndIdsMap, createdMessages } =
|
||||||
messagesToSave,
|
await this.messageService.saveMessagesWithinTransaction(
|
||||||
messageChannel.id,
|
messagesToSave,
|
||||||
|
messageChannel.id,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
|
||||||
|
const participantsWithMessageId: (ParticipantWithMessageId & {
|
||||||
|
shouldCreateContact: boolean;
|
||||||
|
})[] = messagesToSave.flatMap((message) => {
|
||||||
|
const messageId = messageExternalIdsAndIdsMap.get(
|
||||||
|
message.externalId,
|
||||||
|
);
|
||||||
|
|
||||||
|
return messageId
|
||||||
|
? message.participants.map((participant: Participant) => {
|
||||||
|
const fromHandle =
|
||||||
|
message.participants.find((p) => p.role === 'from')
|
||||||
|
?.handle || '';
|
||||||
|
|
||||||
|
const isMessageSentByConnectedAccount =
|
||||||
|
handleAliases.includes(fromHandle) ||
|
||||||
|
fromHandle === connectedAccount.handle;
|
||||||
|
|
||||||
|
const isParticipantConnectedAccount =
|
||||||
|
handleAliases.includes(participant.handle) ||
|
||||||
|
participant.handle === connectedAccount.handle;
|
||||||
|
|
||||||
|
const isExcludedByNonProfessionalEmails =
|
||||||
|
messageChannel.excludeNonProfessionalEmails &&
|
||||||
|
!isWorkEmail(participant.handle);
|
||||||
|
|
||||||
|
const isExcludedByGroupEmails =
|
||||||
|
messageChannel.excludeGroupEmails &&
|
||||||
|
isGroupEmail(participant.handle);
|
||||||
|
|
||||||
|
const shouldCreateContact =
|
||||||
|
!!participant.handle &&
|
||||||
|
!isParticipantConnectedAccount &&
|
||||||
|
!isExcludedByNonProfessionalEmails &&
|
||||||
|
!isExcludedByGroupEmails &&
|
||||||
|
(messageChannel.contactAutoCreationPolicy ===
|
||||||
|
MessageChannelContactAutoCreationPolicy.SENT_AND_RECEIVED ||
|
||||||
|
(messageChannel.contactAutoCreationPolicy ===
|
||||||
|
MessageChannelContactAutoCreationPolicy.SENT &&
|
||||||
|
isMessageSentByConnectedAccount));
|
||||||
|
|
||||||
|
return {
|
||||||
|
...participant,
|
||||||
|
messageId,
|
||||||
|
shouldCreateContact,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.messageParticipantService.saveMessageParticipants(
|
||||||
|
participantsWithMessageId,
|
||||||
transactionManager,
|
transactionManager,
|
||||||
);
|
);
|
||||||
|
|
||||||
const participantsWithMessageId: (ParticipantWithMessageId & {
|
return { participantsWithMessageId, createdMessages };
|
||||||
shouldCreateContact: boolean;
|
},
|
||||||
})[] = messagesToSave.flatMap((message) => {
|
);
|
||||||
const messageId = messageExternalIdsAndIdsMap.get(message.externalId);
|
|
||||||
|
|
||||||
return messageId
|
const { participantsWithMessageId, createdMessages } =
|
||||||
? message.participants.map((participant: Participant) => {
|
createdMessagesWithParticipants;
|
||||||
const fromHandle =
|
|
||||||
message.participants.find((p) => p.role === 'from')?.handle ||
|
|
||||||
'';
|
|
||||||
|
|
||||||
const isMessageSentByConnectedAccount =
|
|
||||||
handleAliases.includes(fromHandle) ||
|
|
||||||
fromHandle === connectedAccount.handle;
|
|
||||||
|
|
||||||
const isParticipantConnectedAccount =
|
|
||||||
handleAliases.includes(participant.handle) ||
|
|
||||||
participant.handle === connectedAccount.handle;
|
|
||||||
|
|
||||||
const isExcludedByNonProfessionalEmails =
|
|
||||||
messageChannel.excludeNonProfessionalEmails &&
|
|
||||||
!isWorkEmail(participant.handle);
|
|
||||||
|
|
||||||
const isExcludedByGroupEmails =
|
|
||||||
messageChannel.excludeGroupEmails &&
|
|
||||||
isGroupEmail(participant.handle);
|
|
||||||
|
|
||||||
const shouldCreateContact =
|
|
||||||
!!participant.handle &&
|
|
||||||
!isParticipantConnectedAccount &&
|
|
||||||
!isExcludedByNonProfessionalEmails &&
|
|
||||||
!isExcludedByGroupEmails &&
|
|
||||||
(messageChannel.contactAutoCreationPolicy ===
|
|
||||||
MessageChannelContactAutoCreationPolicy.SENT_AND_RECEIVED ||
|
|
||||||
(messageChannel.contactAutoCreationPolicy ===
|
|
||||||
MessageChannelContactAutoCreationPolicy.SENT &&
|
|
||||||
isMessageSentByConnectedAccount));
|
|
||||||
|
|
||||||
return {
|
|
||||||
...participant,
|
|
||||||
messageId,
|
|
||||||
shouldCreateContact,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
: [];
|
|
||||||
});
|
|
||||||
|
|
||||||
await this.messageParticipantService.saveMessageParticipants(
|
|
||||||
participantsWithMessageId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return participantsWithMessageId;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const messageMetadata = await this.objectMetadataRepository.findOneOrFail({
|
const messageMetadata = await this.objectMetadataRepository.findOneOrFail({
|
||||||
where: { nameSingular: 'message', workspaceId },
|
where: { nameSingular: 'message', workspaceId },
|
||||||
@ -125,9 +131,9 @@ export class MessagingSaveMessagesAndEnqueueContactCreationService {
|
|||||||
this.workspaceEventEmitter.emitDatabaseBatchEvent({
|
this.workspaceEventEmitter.emitDatabaseBatchEvent({
|
||||||
objectMetadataNameSingular: 'message',
|
objectMetadataNameSingular: 'message',
|
||||||
action: DatabaseEventAction.CREATED,
|
action: DatabaseEventAction.CREATED,
|
||||||
events: messagesToSave.map((message) => {
|
events: createdMessages.map((message) => {
|
||||||
return {
|
return {
|
||||||
recordId: message.headerMessageId,
|
recordId: message.id ?? '',
|
||||||
objectMetadata: messageMetadata,
|
objectMetadata: messageMetadata,
|
||||||
properties: {
|
properties: {
|
||||||
after: message,
|
after: message,
|
||||||
|
|||||||
Reference in New Issue
Block a user