47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { and, desc, eq } from 'drizzle-orm';
|
|
import { db } from '../db/client';
|
|
import { observations } from '../db/schema';
|
|
import { AuditService } from '../audit/audit.service';
|
|
import type { AuthenticatedSession } from '../auth/tenant.guard';
|
|
import type { CreateObservationDto } from './dto';
|
|
|
|
@Injectable()
|
|
export class ObservationsService {
|
|
constructor(private readonly audit: AuditService) {}
|
|
|
|
async list(session: AuthenticatedSession, subjectType?: string, subjectId?: string) {
|
|
return db.query.observations.findMany({
|
|
where: and(
|
|
eq(observations.tenantId, session.tenantId),
|
|
...(subjectType ? [eq(observations.subjectType, subjectType)] : []),
|
|
...(subjectId ? [eq(observations.subjectId, subjectId)] : []),
|
|
),
|
|
orderBy: desc(observations.observedAt),
|
|
});
|
|
}
|
|
|
|
async create(session: AuthenticatedSession, dto: CreateObservationDto) {
|
|
const [row] = await db
|
|
.insert(observations)
|
|
.values({
|
|
tenantId: session.tenantId,
|
|
subjectType: dto.subjectType,
|
|
subjectId: dto.subjectId,
|
|
metric: dto.metric,
|
|
value: dto.value,
|
|
unit: dto.unit,
|
|
source: dto.source,
|
|
observedAt: dto.observedAt ? new Date(dto.observedAt) : new Date(),
|
|
confidence: dto.confidence !== undefined ? String(dto.confidence) : undefined,
|
|
})
|
|
.returning();
|
|
await this.audit.record(null, {
|
|
tenantId: session.tenantId,
|
|
actorId: session.userId,
|
|
action: 'observation.created',
|
|
resource: `observation:${row.id}:${dto.subjectType}/${dto.subjectId}`,
|
|
});
|
|
return row;
|
|
}
|
|
}
|