diff --git a/api-v3/src/asset-master/inventory-function.service.ts b/api-v3/src/asset-master/inventory-function.service.ts index 1a2e315..f0a1e39 100644 --- a/api-v3/src/asset-master/inventory-function.service.ts +++ b/api-v3/src/asset-master/inventory-function.service.ts @@ -16,12 +16,12 @@ import type { } from './dto/inventory-function.dto'; import { AssetHistoryService } from './asset-history.service'; -interface InventoryFunctionRow { +export interface InventoryFunctionRow { id: string; code: string; name: string; description: string | null; isActive: boolean; sortOrder: number; createdAt: Date; updatedAt: Date; } -interface FunctionAssignmentRow { +export interface FunctionAssignmentRow { id: string; assetId: string; functionId: string; functionCode: string; functionName: string; validFrom: Date; validUntil: Date | null; reason: string | null; changedBy: string | null; changedByUsername: string | null; createdAt: Date; diff --git a/api-v3/src/inspection-findings/finding-recurrence.controller.ts b/api-v3/src/inspection-findings/finding-recurrence.controller.ts index c06e773..369ce91 100644 --- a/api-v3/src/inspection-findings/finding-recurrence.controller.ts +++ b/api-v3/src/inspection-findings/finding-recurrence.controller.ts @@ -18,6 +18,12 @@ import { FindingRecurrenceService } from './finding-recurrence.service'; export class FindingRecurrenceController { constructor(private readonly recurrence: FindingRecurrenceService) {} + @Get(':id/recurrence') + @RequirePermissions('inspection_findings.read') + state(@Param('id', new ParseUUIDPipe({ version: '4' })) id: string) { + return this.recurrence.state(id); + } + @Get(':id/recurrence-candidates') @RequirePermissions('inspection_findings.read') candidates(@Param('id', new ParseUUIDPipe({ version: '4' })) id: string) { diff --git a/api-v3/src/inspection-findings/finding-recurrence.service.ts b/api-v3/src/inspection-findings/finding-recurrence.service.ts index c20f384..a06e304 100644 --- a/api-v3/src/inspection-findings/finding-recurrence.service.ts +++ b/api-v3/src/inspection-findings/finding-recurrence.service.ts @@ -26,6 +26,12 @@ interface FindingRecurrenceContext { visitStatus: string; } +export interface FindingRecurrenceState { + isRecurrence: boolean; + recurrenceOfFindingId: string | null; + recurrenceOfFindingCode: string | null; +} + function comparable(value: string): string { return value .normalize('NFD') @@ -44,6 +50,25 @@ export class FindingRecurrenceService { private readonly findings: InspectionFindingsService, ) {} + async state(id: string): Promise { + const [row] = await this.dataSource.query(` + SELECT + finding.is_recurrence AS "isRecurrence", + finding.recurrence_of_finding_id AS "recurrenceOfFindingId", + antecedent.code AS "recurrenceOfFindingCode" + FROM inspection_findings finding + LEFT JOIN inspection_findings antecedent ON antecedent.id = finding.recurrence_of_finding_id + WHERE finding.id = $1 + `, [id]) as FindingRecurrenceState[]; + if (!row) { + throw new NotFoundException({ + code: 'INSPECTION_FINDING_NOT_FOUND', + message: 'Hallazgo no encontrado', + }); + } + return row; + } + async candidates(id: string) { const current = await this.requireFinding(this.dataSource.manager, id, false); const rows = await this.dataSource.query(` @@ -138,7 +163,11 @@ export class FindingRecurrenceService { metadata: { actId: current.actId, visitId: current.visitId, recurrenceAction: 'LINKED' }, }, manager); }); - return this.findings.getById(id); + const [finding, recurrence] = await Promise.all([ + this.findings.getById(id), + this.state(id), + ]); + return { ...finding, ...recurrence }; } async clear( @@ -171,7 +200,11 @@ export class FindingRecurrenceService { metadata: { actId: current.actId, visitId: current.visitId, recurrenceAction: 'CLEARED' }, }, manager); }); - return this.findings.getById(id); + const [finding, recurrence] = await Promise.all([ + this.findings.getById(id), + this.state(id), + ]); + return { ...finding, ...recurrence }; } private async requireFinding( diff --git a/api-v3/src/inspection-findings/inspection-findings.controller.ts b/api-v3/src/inspection-findings/inspection-findings.controller.ts index 6e1d522..20ad646 100644 --- a/api-v3/src/inspection-findings/inspection-findings.controller.ts +++ b/api-v3/src/inspection-findings/inspection-findings.controller.ts @@ -16,6 +16,7 @@ import { CloseInspectionFindingDto } from './dto/close-inspection-finding.dto'; import { CreateInspectionFindingDto } from './dto/create-inspection-finding.dto'; import { ListInspectionFindingsQueryDto } from './dto/list-inspection-findings-query.dto'; import { UpdateInspectionFindingDto } from './dto/update-inspection-finding.dto'; +import { FindingRecurrenceService } from './finding-recurrence.service'; import { InspectionFindingWorklistService } from './inspection-finding-worklist.service'; import { InspectionFindingsService } from './inspection-findings.service'; @@ -46,6 +47,7 @@ export class InspectionFindingsController { constructor( private readonly findings: InspectionFindingsService, private readonly worklist: InspectionFindingWorklistService, + private readonly recurrence: FindingRecurrenceService, ) {} @Get() @@ -56,8 +58,12 @@ export class InspectionFindingsController { @Get(':id') @RequirePermissions('inspection_findings.read') - get(@Param('id', new ParseUUIDPipe({ version: '4' })) id: string) { - return this.findings.getById(id); + async get(@Param('id', new ParseUUIDPipe({ version: '4' })) id: string) { + const [finding, recurrence] = await Promise.all([ + this.findings.getById(id), + this.recurrence.state(id), + ]); + return { ...finding, ...recurrence }; } @Get(':id/verification-history') diff --git a/web-v2/src/components/Icon.tsx b/web-v2/src/components/Icon.tsx index bcc1fc3..cb66ed2 100644 --- a/web-v2/src/components/Icon.tsx +++ b/web-v2/src/components/Icon.tsx @@ -1,7 +1,7 @@ export type IconName = | 'home' | 'map' | 'layers' | 'calendar' | 'clipboard' | 'alert' | 'history' | 'users' | 'shield' | 'audit' | 'logout' | 'menu' - | 'plus' | 'search' | 'edit' | 'chevron' | 'check' | 'key' | 'upload' | 'mail'; + | 'plus' | 'search' | 'edit' | 'chevron' | 'check' | 'key' | 'upload' | 'mail' | 'lock'; export function Icon({ name, size = 18 }: { name: IconName; size?: number }) { const paths: Record = { @@ -25,6 +25,7 @@ export function Icon({ name, size = 18 }: { name: IconName; size?: number }) { key: <>, upload: <>, mail: <>, + lock: <>, }; return (