Feat/s3 storage #2
@@ -25,7 +25,7 @@ function mail(): MailService {
|
|||||||
const ingest = new IngestService(asService, makeFakePorts(), actors);
|
const ingest = new IngestService(asService, makeFakePorts(), actors);
|
||||||
const outbound = new OutboundService(asService, new CapabilityBroker(makeFakePorts(), new CapabilityProviderRegistry()), new IdempotencyService(asService));
|
const outbound = new OutboundService(asService, new CapabilityBroker(makeFakePorts(), new CapabilityProviderRegistry()), new IdempotencyService(asService));
|
||||||
const sender = new TemplatedSender(templates, outbound, makeFakePorts());
|
const sender = new TemplatedSender(templates, outbound, makeFakePorts());
|
||||||
return new MailService(templates, ingest, sender, actors);
|
return new MailService(templates, ingest, sender, actors, asService);
|
||||||
}
|
}
|
||||||
const messages = () => new MessageService(asService, makeFakePorts(), actors);
|
const messages = () => new MessageService(asService, makeFakePorts(), actors);
|
||||||
|
|
||||||
@@ -56,6 +56,7 @@ describe('MailService.postInternal', () => {
|
|||||||
|
|
||||||
const thread = await prisma.iiosThread.findUniqueOrThrow({ where: { id: res.threadId } });
|
const thread = await prisma.iiosThread.findUniqueOrThrow({ where: { id: res.threadId } });
|
||||||
expect(thread.subject).toBe('Welcome Dana');
|
expect(thread.subject).toBe('Welcome Dana');
|
||||||
|
expect((thread.metadata as { source?: string } | null)?.source).toBe('crm-mail'); // lists separately from chat
|
||||||
|
|
||||||
// The load-bearing assertion: the RECIPIENT can see the thread in their inbox.
|
// The load-bearing assertion: the RECIPIENT can see the thread in their inbox.
|
||||||
const bobThreads = await messages().listThreads(bob);
|
const bobThreads = await messages().listThreads(bob);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Prisma } from '@prisma/client';
|
||||||
|
import { PrismaService } from '../prisma/prisma.service';
|
||||||
import { IngestService } from '../interactions/ingest.service';
|
import { IngestService } from '../interactions/ingest.service';
|
||||||
import { ActorResolver, type MessagePrincipal } from '../identity/actor.resolver';
|
import { ActorResolver, type MessagePrincipal } from '../identity/actor.resolver';
|
||||||
import { TemplateService } from '../templates/template.service';
|
import { TemplateService } from '../templates/template.service';
|
||||||
@@ -55,8 +57,12 @@ export class MailService {
|
|||||||
private readonly ingest: IngestService,
|
private readonly ingest: IngestService,
|
||||||
private readonly sender: TemplatedSender,
|
private readonly sender: TemplatedSender,
|
||||||
private readonly actors: ActorResolver,
|
private readonly actors: ActorResolver,
|
||||||
|
private readonly prisma: PrismaService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
/** Marks a thread as CRM mail so it lists separately from chat (Messenger uses source=crm-messenger). */
|
||||||
|
static readonly SOURCE = 'crm-mail';
|
||||||
|
|
||||||
async postInternal(principal: MessagePrincipal, input: PostInternalInput): Promise<{ threadId: string; interactionId: string }> {
|
async postInternal(principal: MessagePrincipal, input: PostInternalInput): Promise<{ threadId: string; interactionId: string }> {
|
||||||
const { content } = await this.templates.render(input.source, input.vars ?? {}, { channel: 'INTERNAL', ...(input.locale ? { locale: input.locale } : {}) });
|
const { content } = await this.templates.render(input.source, input.vars ?? {}, { channel: 'INTERNAL', ...(input.locale ? { locale: input.locale } : {}) });
|
||||||
return this.deposit(principal, input.recipientUserId, content, input.idempotencyKey, 'PORTAL');
|
return this.deposit(principal, input.recipientUserId, content, input.idempotencyKey, 'PORTAL');
|
||||||
@@ -103,6 +109,13 @@ export class MailService {
|
|||||||
await this.actors.ensureParticipant(res.threadId, senderActor.id);
|
await this.actors.ensureParticipant(res.threadId, senderActor.id);
|
||||||
await this.actors.ensureParticipant(res.threadId, recipientActor.id);
|
await this.actors.ensureParticipant(res.threadId, recipientActor.id);
|
||||||
|
|
||||||
|
// Tag the thread as CRM mail (thread metadata) so it lists separately from Messenger chat.
|
||||||
|
// ingest() puts req.metadata on the interaction, not the thread, so we set it here directly.
|
||||||
|
await this.prisma.iiosThread.update({
|
||||||
|
where: { id: res.threadId },
|
||||||
|
data: { metadata: { source: MailService.SOURCE } as Prisma.InputJsonValue },
|
||||||
|
});
|
||||||
|
|
||||||
return { threadId: res.threadId, interactionId: res.interactionId };
|
return { threadId: res.threadId, interactionId: res.interactionId };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user