All files / apps/work-orders-service/src/messaging work-order-events.outbox.ts

100% Statements 9/9
100% Branches 10/10
100% Functions 1/1
100% Lines 7/7

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 555x 5x     5x   5x               5x           6x                                                     6x              
import { randomUUID } from 'node:crypto';
import { Injectable } from '@nestjs/common';
import { EntityManager } from 'typeorm';
import { WorkOrderEvent, WorkOrderEventType } from '@app/contracts';
import { currentRequestId, currentUserId } from '@app/observability';
import { WorkOrder } from '../work-orders/work-order.entity';
import { OutboxEvent } from './outbox-event.entity';
 
/**
 * Builds the event envelope at write time (so the ambient correlation id and
 * domain timestamp are captured in the request context) and stages it in the
 * outbox using the caller's transaction. Publishing is the relay's job.
 */
@Injectable()
export class WorkOrderEventsOutbox {
  async stage(
    manager: EntityManager,
    type: WorkOrderEventType,
    workOrder: WorkOrder,
  ): Promise<void> {
    const event: WorkOrderEvent = {
      eventId: randomUUID(),
      type,
      occurredAt: new Date().toISOString(),
      correlationId: currentRequestId() ?? null,
      // Null for system-initiated events (the triage consumer runs outside
      // any HTTP request) — the audit log records "who", or that no one did.
      actorId: currentUserId() ?? null,
      data: {
        workOrderId: workOrder.id,
        propertyId: workOrder.propertyId,
        title: workOrder.title,
        description: workOrder.description,
        priority: workOrder.priority,
        status: workOrder.status,
        assigneeId: workOrder.assigneeId,
        triage:
          workOrder.triageCategory && workOrder.triageUrgency
            ? {
                category: workOrder.triageCategory,
                urgency: workOrder.triageUrgency,
                reasoning: workOrder.triageReasoning ?? '',
              }
            : null,
      },
    };
 
    await manager.insert(OutboxEvent, {
      eventId: event.eventId,
      type,
      payload: event,
    });
  }
}