import { Injectable } from '@nestjs/common'; import { DataSource } from 'typeorm'; import { administrationAuditContext } from '../administration/common/administration-audit'; import { AuditService } from '../audit/audit.service'; import type { AuthPrincipal, RequestWithContext } from '../common/http/request-context'; import { AuditAction } from '../database/entities'; import type { UpdateDeadlinePolicyDto, UpsertBusinessCalendarDayDto } from './dto/update-deadline-policy.dto'; @Injectable() export class InspectionDeadlineAdminService { constructor( private readonly dataSource: DataSource, private readonly audit: AuditService, ) {} async policy() { const [row] = await this.dataSource.query(` SELECT id, urgent_days AS "urgentDays", urgent_day_type AS "urgentDayType", non_urgent_days AS "nonUrgentDays", non_urgent_day_type AS "nonUrgentDayType", updated_by AS "updatedBy", updated_at AS "updatedAt" FROM inspection_deadline_policies ORDER BY created_at LIMIT 1 `); return row ?? { urgentDays: 5, urgentDayType: 'BUSINESS', nonUrgentDays: 10, nonUrgentDayType: 'BUSINESS', }; } async updatePolicy( dto: UpdateDeadlinePolicyDto, principal: AuthPrincipal, request: RequestWithContext, ) { const before = await this.policy(); const [existing] = await this.dataSource.query(` SELECT id FROM inspection_deadline_policies ORDER BY created_at LIMIT 1 `) as Array<{ id: string }>; if (existing) { await this.dataSource.query(` UPDATE inspection_deadline_policies SET urgent_days=$2, urgent_day_type=$3, non_urgent_days=$4, non_urgent_day_type=$5, updated_by=$6, updated_at=CURRENT_TIMESTAMP WHERE id=$1 `, [ existing.id, dto.urgentDays, dto.urgentDayType, dto.nonUrgentDays, dto.nonUrgentDayType, principal.userId, ]); } else { await this.dataSource.query(` INSERT INTO inspection_deadline_policies( urgent_days,urgent_day_type,non_urgent_days,non_urgent_day_type,updated_by ) VALUES($1,$2,$3,$4,$5) `, [ dto.urgentDays, dto.urgentDayType, dto.nonUrgentDays, dto.nonUrgentDayType, principal.userId, ]); } const after = await this.policy(); await this.audit.record({ ...administrationAuditContext(principal, request), action: AuditAction.INSPECTION_DEADLINE_POLICY_UPDATED, entityType: 'inspection_deadline_policy', entityId: String((after as { id?: string }).id ?? 'singleton'), beforeData: before as Record, afterData: after as Record, metadata: { appliesOnlyToFutureLockedActs: true, historicalActsKeepSnapshot: true, }, }); return after; } async calendar() { const data = await this.dataSource.query(` SELECT id,date,is_business_day AS "isBusinessDay",label, updated_by AS "updatedBy",created_at AS "createdAt",updated_at AS "updatedAt" FROM inspection_business_calendar_days ORDER BY date `); return { data }; } async upsertCalendarDay( dto: UpsertBusinessCalendarDayDto, principal: AuthPrincipal, request: RequestWithContext, ) { const [before] = await this.dataSource.query(` SELECT id,date,is_business_day AS "isBusinessDay",label FROM inspection_business_calendar_days WHERE date=$1::date `, [dto.date]); await this.dataSource.query(` INSERT INTO inspection_business_calendar_days(date,is_business_day,label,updated_by) VALUES($1::date,$2,$3,$4) ON CONFLICT(date) DO UPDATE SET is_business_day=EXCLUDED.is_business_day, label=EXCLUDED.label, updated_by=EXCLUDED.updated_by, updated_at=CURRENT_TIMESTAMP `, [dto.date, dto.isBusinessDay, dto.label, principal.userId]); const [after] = await this.dataSource.query(` SELECT id,date,is_business_day AS "isBusinessDay",label, updated_by AS "updatedBy",updated_at AS "updatedAt" FROM inspection_business_calendar_days WHERE date=$1::date `, [dto.date]); await this.audit.record({ ...administrationAuditContext(principal, request), action: AuditAction.INSPECTION_BUSINESS_CALENDAR_UPDATED, entityType: 'inspection_business_calendar_day', entityId: String(after.id), beforeData: before ?? null, afterData: after, }); return after; } async removeCalendarDay( date: string, principal: AuthPrincipal, request: RequestWithContext, ) { const [before] = await this.dataSource.query(` SELECT id,date,is_business_day AS "isBusinessDay",label FROM inspection_business_calendar_days WHERE date=$1::date `, [date]); if (before) { await this.dataSource.query(`DELETE FROM inspection_business_calendar_days WHERE id=$1`, [before.id]); await this.audit.record({ ...administrationAuditContext(principal, request), action: AuditAction.INSPECTION_BUSINESS_CALENDAR_UPDATED, entityType: 'inspection_business_calendar_day', entityId: String(before.id), beforeData: before, afterData: null, metadata: { removed: true }, }); } return { removed: Boolean(before), date }; } }