import type { ServiceApplicationStatus, ServiceCategory } from './service-applications.js'; export const BENEFICIARY_GENDERS = ['FEMALE', 'MALE', 'OTHER', 'UNDISCLOSED'] as const; export type BeneficiaryGender = (typeof BENEFICIARY_GENDERS)[number]; export const BENEFICIARY_STATUSES = ['ACTIVE', 'INACTIVE', 'ARCHIVED'] as const; export type BeneficiaryStatus = (typeof BENEFICIARY_STATUSES)[number]; export const SERVICE_CASE_PRIORITIES = ['LOW', 'NORMAL', 'HIGH', 'URGENT'] as const; export type ServiceCasePriority = (typeof SERVICE_CASE_PRIORITIES)[number]; export const SERVICE_CASE_STATUSES = [ 'ASSIGNED', 'IN_SERVICE', 'SERVICE_COMPLETED', 'SUSPENDED', 'CANCELLED', ] as const; export type ServiceCaseStatus = (typeof SERVICE_CASE_STATUSES)[number]; export const CASE_ASSIGNEE_TYPES = ['STAFF', 'VOLUNTEER'] as const; export type CaseAssigneeType = (typeof CASE_ASSIGNEE_TYPES)[number]; export const SERVICE_RECORD_TYPES = [ 'HOME_VISIT', 'PHONE_CONTACT', 'ESCORT', 'MATERIAL_SUPPORT', 'ACTIVITY', 'OTHER', ] as const; export type ServiceRecordType = (typeof SERVICE_RECORD_TYPES)[number]; export const BENEFICIARY_CONFIRM_STATUSES = [ 'NOT_REQUESTED', 'CONFIRMED', 'PARTIALLY_CONFIRMED', 'DISPUTED', ] as const; export type BeneficiaryConfirmStatus = (typeof BENEFICIARY_CONFIRM_STATUSES)[number]; export const SERVICE_CASE_STATUS_LABELS: Record = { ASSIGNED: '已指派', IN_SERVICE: '服务中', SERVICE_COMPLETED: '服务已完成', SUSPENDED: '服务暂缓', CANCELLED: '已取消', }; export const SERVICE_CASE_PRIORITY_LABELS: Record = { LOW: '低', NORMAL: '一般', HIGH: '较高', URGENT: '紧急', }; export const SERVICE_RECORD_TYPE_LABELS: Record = { HOME_VISIT: '上门探访', PHONE_CONTACT: '电话关怀', ESCORT: '陪同协助', MATERIAL_SUPPORT: '物资支持', ACTIVITY: '公益活动', OTHER: '其他服务', }; export interface BeneficiaryContactInput { name: string; relation: string; mobile: string; isGuardian: boolean; isEmergencyContact: boolean; } export interface NewBeneficiaryInput { displayName: string; gender?: BeneficiaryGender; birthYear?: number; mobile?: string; regionCode: string; addressDetail?: string; keyCareFlag: boolean; isMinor: boolean; notes?: string; contacts: BeneficiaryContactInput[]; tagCodes: string[]; guardianConsentConfirmed?: true; } export interface AcceptServiceApplicationRequest { clientRequestId: string; beneficiary: | { mode: 'CREATE'; profile: NewBeneficiaryInput } | { mode: 'LINK_EXISTING'; beneficiaryPublicId: string; manualMatchConfirmed: true; }; ownerStaffPublicId: string; collaboratorUserPublicIds: string[]; priority: ServiceCasePriority; plannedStartAt?: string; plannedEndAt?: string; serviceLocation?: string; summary: string; } export interface TransitionServiceApplicationRequest { targetStatus: Extract; reasonCode: string; } export interface BeneficiaryContactDetail { publicId: string; name: string; relation: string; mobile: string; mobileMasked: string; isGuardian: boolean; isEmergencyContact: boolean; hasConsentRecord: boolean; } export interface BeneficiaryTagOption { code: string; name: string; description: string | null; } export interface BeneficiaryListItem { publicId: string; displayName: string; gender: BeneficiaryGender | null; birthYear: number | null; mobileMasked: string | null; regionCode: string; primaryCategory: ServiceCategory; keyCareFlag: boolean; isMinor: boolean; status: BeneficiaryStatus; tags: BeneficiaryTagOption[]; createdAt: string; } export interface BeneficiaryDetail extends BeneficiaryListItem { mobile: string | null; addressDetail: string | null; notes: string | null; contacts: BeneficiaryContactDetail[]; serviceCaseCount: number; } export interface PaginatedBeneficiariesResponse { items: BeneficiaryListItem[]; page: number; pageSize: number; total: number; } export interface BeneficiaryDetailResponse { beneficiary: BeneficiaryDetail; } export interface UpdateBeneficiaryRequest extends NewBeneficiaryInput { status: BeneficiaryStatus; } export interface AssigneeOption { userPublicId: string; displayName: string; type: CaseAssigneeType; department: string | null; } export interface CaseAssigneeItem extends AssigneeOption { role: 'OWNER' | 'COLLABORATOR'; assignedAt: string; } export interface ServiceCaseHistoryItem { status: ServiceCaseStatus; statusLabel: string; reasonLabel: string; createdAt: string; } export interface ServiceRecordAttachment { publicId: string; filename: string; mimeType: string; size: number; } export interface ServiceRecordItem { publicId: string; serviceStartAt: string; serviceEndAt: string | null; serviceType: ServiceRecordType; serviceTypeLabel: string; content: string; result: string; followUpSuggestion: string | null; beneficiaryConfirmStatus: BeneficiaryConfirmStatus; createdByDisplayName: string; revision: number; attachments: ServiceRecordAttachment[]; createdAt: string; updatedAt: string; } export interface ServiceCaseListItem { publicId: string; caseNo: string; applicationPublicId: string; applicationNo: string; beneficiaryPublicId: string; beneficiaryDisplayName: string; category: ServiceCategory; priority: ServiceCasePriority; priorityLabel: string; status: ServiceCaseStatus; statusLabel: string; ownerDisplayName: string; plannedStartAt: string | null; createdAt: string; } export interface ServiceCaseDetail extends ServiceCaseListItem { regionCode: string; beneficiaryMobile: string | null; beneficiaryMobileMasked: string | null; serviceLocation: string | null; summary: string; resultSummary: string | null; followUpPlan: string | null; completedAt: string | null; assignees: CaseAssigneeItem[]; history: ServiceCaseHistoryItem[]; records: ServiceRecordItem[]; } export interface PaginatedServiceCasesResponse { items: ServiceCaseListItem[]; page: number; pageSize: number; total: number; } export interface ServiceCaseDetailResponse { serviceCase: ServiceCaseDetail; } export interface AcceptServiceApplicationResponse { serviceCase: ServiceCaseDetail; idempotentReplay: boolean; } export interface ReplaceCaseAssigneesRequest { collaboratorUserPublicIds: string[]; } export interface CreateServiceRecordRequest { clientRequestId: string; serviceStartAt: string; serviceEndAt?: string; serviceType: ServiceRecordType; content: string; result: string; followUpSuggestion?: string; beneficiaryConfirmStatus: BeneficiaryConfirmStatus; attachmentPublicIds: string[]; } export interface UpdateServiceRecordRequest extends Omit< CreateServiceRecordRequest, 'clientRequestId' > { expectedRevision: number; } export interface ServiceRecordResponse { record: ServiceRecordItem; idempotentReplay?: boolean; } export interface CreateUploadIntentRequest { clientRequestId: string; filename: string; mimeType: 'image/jpeg' | 'image/png' | 'image/webp'; size: number; sha256?: string; } export interface CreateUploadIntentResponse { file: ServiceRecordAttachment; uploadUrl: string; uploadHeaders: Record; expiresAt: string; idempotentReplay: boolean; } export interface ConfirmUploadResponse { file: ServiceRecordAttachment; } export interface DownloadUrlResponse { downloadUrl: string; expiresAt: string; }