feat(rfa): complete RFA Approval Refactor - all 9 phases (T001-T080)

Phase 1-2: Setup, SQL schema, enums, queue constants, base entities
Phase 3 (US1): ReviewTeam, ReviewTeamMember, ReviewTask, TaskCreationService
Phase 4 (US2): ResponseCode, ResponseCodeRule, ImplicationsService, NotificationTriggerService
Phase 5 (US3): Delegation entity, CircularDetectionService, DelegationService/Controller/Module
Phase 6 (US4): ReminderRule, SchedulerService, EscalationService, ReminderProcessor, ReminderModule
Phase 7 (US5): DistributionMatrix, DistributionRecipient, ApprovalListenerService (Strangler),
               TransmittalCreatorService, DistributionProcessor, DistributionModule
Phase 8 (US6): MatrixManagementService, InheritanceService (global→project override)
Phase 9 (Polish): AggregateStatusService, ConsensusService, VetoOverrideService,
                  ParallelGatewayHandler, review-validators, optimistic locking in completeReview,
                  test stubs (unit/integration/e2e), jest.config.js updated for tests/ directory

Frontend: ReviewTaskInbox, ParallelProgress, VetoOverrideDialog, DelegationForm,
          DelegatedBadge, MatrixEditor, ProjectOverrideManager, DistributionStatus,
          ReminderHistory, ResponseCodeSelector, CodeImplications, CompleteReviewForm,
          ReviewTeamForm, ReviewTeamSelector, TeamMemberManager

Closes #1
This commit is contained in:
Nattanin
2026-05-12 16:17:27 +07:00
parent 3df8707b7f
commit ef20839f99
82 changed files with 7052 additions and 104 deletions
+100
View File
@@ -0,0 +1,100 @@
// File: types/review-team.ts
// Types สำหรับ Review Team feature
export type ReviewTeamMemberRole = 'REVIEWER' | 'LEAD' | 'MANAGER';
export type DelegationScope = 'ALL' | 'RFA_ONLY' | 'CORRESPONDENCE_ONLY' | 'SPECIFIC_TYPES';
export type ReviewTaskStatus =
| 'PENDING'
| 'IN_PROGRESS'
| 'COMPLETED'
| 'DELEGATED'
| 'EXPIRED'
| 'CANCELLED';
export type ResponseCodeCategory =
| 'ENGINEERING'
| 'MATERIAL'
| 'CONTRACT'
| 'TESTING'
| 'ESG';
export interface ReviewTeam {
publicId: string;
name: string;
description?: string;
projectId?: number;
defaultForRfaTypes?: string[];
isActive: boolean;
createdAt: string;
updatedAt: string;
members?: ReviewTeamMember[];
}
export interface ReviewTeamMember {
publicId: string;
teamId?: number;
userId?: number;
disciplineId?: number;
role: ReviewTeamMemberRole;
priorityOrder: number;
createdAt: string;
user?: {
publicId: string;
fullName?: string;
email?: string;
};
discipline?: {
publicId: string;
disciplineCode: string;
codeNameEn?: string;
codeNameTh?: string;
};
}
export interface ReviewTask {
publicId: string;
rfaRevisionId?: number;
teamId?: number;
disciplineId?: number;
assignedToUserId?: number;
status: ReviewTaskStatus;
dueDate?: string;
responseCodeId?: number;
comments?: string;
attachments?: string[];
completedAt?: string;
version: number;
createdAt: string;
updatedAt: string;
team?: Pick<ReviewTeam, 'publicId' | 'name'>;
responseCode?: ResponseCode;
discipline?: ReviewTeamMember['discipline'];
assignedToUser?: ReviewTeamMember['user'];
}
export interface ResponseCode {
publicId: string;
code: string;
subStatus?: string;
category: ResponseCodeCategory;
descriptionTh: string;
descriptionEn: string;
implications?: {
affectsSchedule?: boolean;
affectsCost?: boolean;
requiresContractReview?: boolean;
requiresEiaAmendment?: boolean;
};
notifyRoles?: string[];
isActive: boolean;
isSystem: boolean;
}
export interface ReviewTaskAggregateStatus {
total: number;
completed: number;
pending: number;
summary: string;
}