feat(ADM-018): completed feature
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import type { EmailMessage, EmailTemplate } from '../domain/notification.js';
|
||||
import type { EmailProvider } from '../domain/ports.js';
|
||||
|
||||
const SUBJECTS: Record<EmailTemplate, string> = {
|
||||
order_confirmation: 'Tu pedido ha sido confirmado',
|
||||
payment_failed: 'Hubo un problema con tu pago',
|
||||
order_shipped: 'Tu pedido ha sido enviado',
|
||||
};
|
||||
|
||||
const BODIES: Record<EmailTemplate, string> = {
|
||||
order_confirmation: 'Hemos recibido tu pago y estamos preparando tu pedido.',
|
||||
payment_failed: 'No pudimos procesar tu pago. Por favor, intenta de nuevo.',
|
||||
order_shipped: 'Tu pedido está en camino. Recibirás los datos de seguimiento pronto.',
|
||||
};
|
||||
|
||||
/** Logging email provider for v1: writes to destination stream; swap with real adapter later. */
|
||||
export class LoggingEmailProvider implements EmailProvider {
|
||||
constructor(private readonly log: (line: string) => void = () => undefined) {}
|
||||
|
||||
async send(message: EmailMessage): Promise<void> {
|
||||
const line = JSON.stringify({
|
||||
provider: 'log',
|
||||
template: message.template,
|
||||
recipient: message.recipient,
|
||||
subject: message.subject || SUBJECTS[message.template],
|
||||
body: message.body || BODIES[message.template],
|
||||
eventId: message.eventId,
|
||||
});
|
||||
this.log(line);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import type pg from 'pg';
|
||||
import type { NotificationsRepository } from '../domain/ports.js';
|
||||
import type { EmailMessage } from '../domain/notification.js';
|
||||
|
||||
interface MessageRow {
|
||||
event_id: string;
|
||||
template: string;
|
||||
recipient: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export class PgNotificationsRepository implements NotificationsRepository {
|
||||
constructor(private readonly pool: pg.Pool) {}
|
||||
|
||||
async findByEventId(
|
||||
eventId: string,
|
||||
): Promise<{ template: string; recipient: string; status: string } | undefined> {
|
||||
const result = await this.pool.query<MessageRow>(
|
||||
'SELECT event_id, template, recipient, status FROM notifications_messages WHERE event_id = $1',
|
||||
[eventId],
|
||||
);
|
||||
const row = result.rows[0];
|
||||
return row
|
||||
? { template: row.template, recipient: row.recipient, status: row.status }
|
||||
: undefined;
|
||||
}
|
||||
|
||||
async record(message: EmailMessage): Promise<{ created: boolean }> {
|
||||
const result = await this.pool.query(
|
||||
`INSERT INTO notifications_messages (event_id, template, recipient, subject, body)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
ON CONFLICT (event_id) DO NOTHING
|
||||
RETURNING id`,
|
||||
[message.eventId, message.template, message.recipient, message.subject, message.body],
|
||||
);
|
||||
return { created: (result.rowCount ?? 0) > 0 };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user