feat(f4): implement JEFE deadline policy and calendar administration
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
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<string, unknown>,
|
||||
afterData: after as Record<string, unknown>,
|
||||
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 };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user