feat: 품목기준관리 Zustand 리팩토링 및 422 에러 팝업
- Zustand store 도입 (useItemMasterStore) - 훅 분리 및 구조 개선 (hooks/, contexts/) - 422 ValidationException 에러 AlertDialog 팝업 추가 - API 함수 분리 (src/lib/api/item-master.ts) - 타입 정의 정리 (item-master.types.ts, item-master-api.ts) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -617,12 +617,14 @@ export interface TabColumnResponse {
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* 단위 옵션 생성 요청
|
||||
* 단위 옵션 생성/수정 요청
|
||||
* POST /v1/item-master/units
|
||||
*/
|
||||
export interface UnitOptionRequest {
|
||||
label: string;
|
||||
value: string;
|
||||
unit_code: string;
|
||||
unit_name: string;
|
||||
description?: string;
|
||||
is_active?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -631,8 +633,78 @@ export interface UnitOptionRequest {
|
||||
export interface UnitOptionResponse {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
label: string;
|
||||
value: string;
|
||||
unit_code: string;
|
||||
unit_name: string;
|
||||
description?: string;
|
||||
is_active: boolean;
|
||||
created_by: number | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 재질 옵션
|
||||
// ============================================
|
||||
|
||||
export type MaterialType = 'STEEL' | 'ALUMINUM' | 'PLASTIC' | 'OTHER';
|
||||
|
||||
/**
|
||||
* 재질 옵션 생성/수정 요청
|
||||
*/
|
||||
export interface MaterialOptionRequest {
|
||||
material_code: string;
|
||||
material_name: string;
|
||||
material_type: MaterialType;
|
||||
thickness?: string;
|
||||
description?: string;
|
||||
is_active?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 재질 옵션 응답
|
||||
*/
|
||||
export interface MaterialOptionResponse {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
material_code: string;
|
||||
material_name: string;
|
||||
material_type: MaterialType;
|
||||
thickness?: string;
|
||||
description?: string;
|
||||
is_active: boolean;
|
||||
created_by: number | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 표면처리 옵션
|
||||
// ============================================
|
||||
|
||||
export type TreatmentType = 'PAINTING' | 'COATING' | 'PLATING' | 'NONE';
|
||||
|
||||
/**
|
||||
* 표면처리 옵션 생성/수정 요청
|
||||
*/
|
||||
export interface TreatmentOptionRequest {
|
||||
treatment_code: string;
|
||||
treatment_name: string;
|
||||
treatment_type: TreatmentType;
|
||||
description?: string;
|
||||
is_active?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 표면처리 옵션 응답
|
||||
*/
|
||||
export interface TreatmentOptionResponse {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
treatment_code: string;
|
||||
treatment_name: string;
|
||||
treatment_type: TreatmentType;
|
||||
description?: string;
|
||||
is_active: boolean;
|
||||
created_by: number | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
|
||||
392
src/types/item-master.types.ts
Normal file
392
src/types/item-master.types.ts
Normal file
@@ -0,0 +1,392 @@
|
||||
/**
|
||||
* 품목기준관리 타입 정의
|
||||
* ItemMasterContext에서 분리됨 (2026-01-06)
|
||||
*/
|
||||
|
||||
// ===== 기본 타입 =====
|
||||
|
||||
// 전개도 상세 정보
|
||||
export interface BendingDetail {
|
||||
id: string;
|
||||
no: number; // 번호
|
||||
input: number; // 입력
|
||||
elongation: number; // 연신율 (기본값 -1)
|
||||
calculated: number; // 연신율 계산 후
|
||||
sum: number; // 합계
|
||||
shaded: boolean; // 음영 여부
|
||||
aAngle?: number; // A각
|
||||
}
|
||||
|
||||
// 부품구성표(BOM, Bill of Materials) - 자재 명세서
|
||||
export interface BOMLine {
|
||||
id: string;
|
||||
childItemCode: string; // 구성 품목 코드
|
||||
childItemName: string; // 구성 품목명
|
||||
quantity: number; // 기준 수량
|
||||
unit: string; // 단위
|
||||
unitPrice?: number; // 단가
|
||||
quantityFormula?: string; // 수량 계산식 (예: "W * 2", "H + 100")
|
||||
note?: string; // 비고
|
||||
// 절곡품 관련 (하위 절곡 부품용)
|
||||
isBending?: boolean;
|
||||
bendingDiagram?: string; // 전개도 이미지 URL
|
||||
bendingDetails?: BendingDetail[]; // 전개도 상세 데이터
|
||||
}
|
||||
|
||||
// 규격 마스터 (원자재/부자재용)
|
||||
export interface SpecificationMaster {
|
||||
id: string;
|
||||
specificationCode: string; // 규격 코드 (예: 1.6T x 1219 x 2438)
|
||||
itemType: 'RM' | 'SM'; // 원자재 | 부자재
|
||||
itemName?: string; // 품목명 (예: SPHC-SD, SPCC-SD) - 품목명별 규격 필터링용
|
||||
fieldCount: '1' | '2' | '3'; // 너비 입력 개수
|
||||
thickness: string; // 두께
|
||||
widthA: string; // 너비A
|
||||
widthB?: string; // 너비B
|
||||
widthC?: string; // 너비C
|
||||
length: string; // 길이
|
||||
description?: string; // 설명
|
||||
isActive: boolean; // 활성 여부
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
// 원자재/부자재 품목명 마스터
|
||||
export interface MaterialItemName {
|
||||
id: string;
|
||||
itemType: 'RM' | 'SM'; // 원자재 | 부자재
|
||||
itemName: string; // 품목명 (예: "SPHC-SD", "STS430")
|
||||
category?: string; // 분류 (예: "냉연", "열연", "스테인리스")
|
||||
description?: string; // 설명
|
||||
isActive: boolean; // 활성 여부
|
||||
createdAt: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
// 품목 수정 이력
|
||||
export interface ItemRevision {
|
||||
revisionNumber: number; // 수정 차수 (1차, 2차, 3차...)
|
||||
revisionDate: string; // 수정일
|
||||
revisionBy: string; // 수정자
|
||||
revisionReason?: string; // 수정 사유
|
||||
previousData: any; // 이전 버전의 전체 데이터
|
||||
}
|
||||
|
||||
// 품목 마스터
|
||||
export interface ItemMaster {
|
||||
id: string;
|
||||
itemCode: string;
|
||||
itemName: string;
|
||||
itemType: 'FG' | 'PT' | 'SM' | 'RM' | 'CS'; // 제품, 부품, 부자재, 원자재, 소모품
|
||||
productCategory?: 'SCREEN' | 'STEEL'; // 제품 카테고리 (스크린/철재)
|
||||
partType?: 'ASSEMBLY' | 'BENDING' | 'PURCHASED'; // 부품 유형 (조립/절곡/구매)
|
||||
partUsage?: 'GUIDE_RAIL' | 'BOTTOM_FINISH' | 'CASE' | 'DOOR' | 'BRACKET' | 'GENERAL'; // 부품 용도
|
||||
unit: string;
|
||||
category1?: string;
|
||||
category2?: string;
|
||||
category3?: string;
|
||||
specification?: string;
|
||||
isVariableSize?: boolean;
|
||||
isActive?: boolean; // 품목 활성/비활성 (제품/부품/원자재/부자재만 사용)
|
||||
lotAbbreviation?: string; // 로트 약자 (제품만 사용)
|
||||
purchasePrice?: number;
|
||||
marginRate?: number;
|
||||
processingCost?: number;
|
||||
laborCost?: number;
|
||||
installCost?: number;
|
||||
salesPrice?: number;
|
||||
safetyStock?: number;
|
||||
leadTime?: number;
|
||||
bom?: BOMLine[]; // 부품구성표(BOM) - 자재 명세서
|
||||
bomCategories?: string[]; // 견적산출용 샘플 제품의 BOM 카테고리 (예: ['motor', 'guide-rail'])
|
||||
|
||||
// 인정 정보
|
||||
certificationNumber?: string; // 인정번호
|
||||
certificationStartDate?: string; // 인정 유효기간 시작일
|
||||
certificationEndDate?: string; // 인정 유효기간 종료일
|
||||
specificationFile?: string; // 시방서 파일 (Base64 또는 URL)
|
||||
specificationFileName?: string; // 시방서 파일명
|
||||
certificationFile?: string; // 인정서 파일 (Base64 또는 URL)
|
||||
certificationFileName?: string; // 인정서 파일명
|
||||
note?: string; // 비고 (제품만 사용)
|
||||
|
||||
// 조립 부품 관련 필드
|
||||
installationType?: string; // 설치 유형 (wall: 벽면형, side: 측면형, steel: 스틸, iron: 철재)
|
||||
assemblyType?: string; // 종류 (M, T, C, D, S, U 등)
|
||||
sideSpecWidth?: string; // 측면 규격 가로 (mm)
|
||||
sideSpecHeight?: string; // 측면 규격 세로 (mm)
|
||||
assemblyLength?: string; // 길이 (2438, 3000, 3500, 4000, 4300 등)
|
||||
|
||||
// 가이드레일 관련 필드
|
||||
guideRailModelType?: string; // 가이드레일 모델 유형
|
||||
guideRailModel?: string; // 가이드레일 모델
|
||||
|
||||
// 절곡품 관련 (부품 유형이 BENDING인 경우)
|
||||
bendingDiagram?: string; // 전개도 이미지 URL
|
||||
bendingDetails?: BendingDetail[]; // 전개도 상세 데이터
|
||||
material?: string; // 재질 (EGI 1.55T, SUS 1.2T 등)
|
||||
length?: string; // 길이/목함 (mm)
|
||||
|
||||
// 버전 관리
|
||||
currentRevision: number; // 현재 차수 (0 = 최초, 1 = 1차 수정...)
|
||||
revisions?: ItemRevision[]; // 수정 이력
|
||||
isFinal: boolean; // 최종 확정 여부
|
||||
finalizedDate?: string; // 최종 확정일
|
||||
finalizedBy?: string; // 최종 확정자
|
||||
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
// ===== 품목 기준정보 관리 (Master Data) =====
|
||||
|
||||
export interface ItemCategory {
|
||||
id: string;
|
||||
categoryType: 'PRODUCT' | 'PART' | 'MATERIAL' | 'SUB_MATERIAL'; // 품목 구분
|
||||
category1: string; // 대분류
|
||||
category2?: string; // 중분류
|
||||
category3?: string; // 소분류
|
||||
code?: string; // 코드 (자동생성 또는 수동입력)
|
||||
description?: string;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface ItemUnit {
|
||||
id: string;
|
||||
unitCode: string; // 단위 코드 (EA, SET, M, KG, L 등)
|
||||
unitName: string; // 단위명
|
||||
description?: string;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface ItemMaterial {
|
||||
id: string;
|
||||
materialCode: string; // 재질 코드
|
||||
materialName: string; // 재질명 (EGI 1.55T, SUS 1.2T 등)
|
||||
materialType: 'STEEL' | 'ALUMINUM' | 'PLASTIC' | 'OTHER'; // 재질 유형
|
||||
thickness?: string; // 두께 (1.2T, 1.6T 등)
|
||||
description?: string;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface SurfaceTreatment {
|
||||
id: string;
|
||||
treatmentCode: string; // 처리 코드
|
||||
treatmentName: string; // 처리명 (무도장, 파우더도장, 아노다이징 등)
|
||||
treatmentType: 'PAINTING' | 'COATING' | 'PLATING' | 'NONE'; // 처리 유형
|
||||
description?: string;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface PartTypeOption {
|
||||
id: string;
|
||||
partType: 'ASSEMBLY' | 'BENDING' | 'PURCHASED'; // 부품 유형
|
||||
optionCode: string; // 옵션 코드
|
||||
optionName: string; // 옵션명
|
||||
description?: string;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface PartUsageOption {
|
||||
id: string;
|
||||
usageCode: string; // 용도 코드
|
||||
usageName: string; // 용도명 (가이드레일, 하단마감재, 케이스 등)
|
||||
description?: string;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface GuideRailOption {
|
||||
id: string;
|
||||
optionType: 'MODEL_TYPE' | 'MODEL' | 'CERTIFICATION' | 'SHAPE' | 'FINISH' | 'LENGTH'; // 옵션 유형
|
||||
optionCode: string; // 옵션 코드
|
||||
optionName: string; // 옵션명
|
||||
parentOption?: string; // 상위 옵션 (종속 관계)
|
||||
description?: string;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
// ===== 품목기준관리 계층구조 =====
|
||||
|
||||
// 항목 속성
|
||||
export interface ItemFieldProperty {
|
||||
id?: string; // 속성 ID (properties 배열에서 사용)
|
||||
key?: string; // 속성 키 (properties 배열에서 사용)
|
||||
label?: string; // 속성 라벨 (properties 배열에서 사용)
|
||||
type?: 'textbox' | 'dropdown' | 'checkbox' | 'number' | 'date' | 'textarea'; // 속성 타입 (properties 배열에서 사용)
|
||||
inputType: 'textbox' | 'dropdown' | 'checkbox' | 'number' | 'date' | 'textarea' | 'section'; // 입력방식
|
||||
required: boolean; // 필수 여부
|
||||
row: number; // 행 위치
|
||||
col: number; // 열 위치
|
||||
options?: string[]; // 드롭다운 옵션 (입력방식이 dropdown일 경우)
|
||||
defaultValue?: string; // 기본값
|
||||
placeholder?: string; // 플레이스홀더
|
||||
multiColumn?: boolean; // 다중 컬럼 사용 여부
|
||||
columnCount?: number; // 컬럼 개수
|
||||
columnNames?: string[]; // 각 컬럼의 이름
|
||||
}
|
||||
|
||||
// 항목 마스터 (재사용 가능한 항목 템플릿) - MasterFieldResponse와 정확히 일치
|
||||
export interface ItemMasterField {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
field_name: string;
|
||||
field_key?: string | null; // 2025-11-28: field_key 추가 (형식: {ID}_{사용자입력})
|
||||
field_type: 'textbox' | 'number' | 'dropdown' | 'checkbox' | 'date' | 'textarea'; // API와 동일
|
||||
category: string | null;
|
||||
description: string | null;
|
||||
is_common: boolean; // 공통 필드 여부
|
||||
is_required?: boolean; // 필수 여부 (API에서 반환)
|
||||
default_value: string | null; // 기본값
|
||||
options: Array<{ label: string; value: string }> | null; // dropdown 옵션
|
||||
validation_rules: Record<string, any> | null; // 검증 규칙
|
||||
properties: Record<string, any> | null; // 추가 속성
|
||||
created_by: number | null;
|
||||
updated_by: number | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
// 조건부 표시 설정
|
||||
export interface FieldDisplayCondition {
|
||||
targetType: 'field' | 'section'; // 조건 대상 타입
|
||||
// 일반항목 조건 (여러 개 가능)
|
||||
fieldConditions?: Array<{
|
||||
fieldKey: string; // 조건이 되는 필드의 키
|
||||
expectedValue: string; // 예상되는 값
|
||||
}>;
|
||||
// 섹션 조건 (여러 개 가능)
|
||||
sectionIds?: string[]; // 표시할 섹션 ID 배열
|
||||
}
|
||||
|
||||
// 항목 (Field) - API 응답 구조에 맞춰 수정
|
||||
export interface ItemField {
|
||||
id: number; // 서버 생성 ID (string → number)
|
||||
tenant_id?: number; // 백엔드에서 자동 추가
|
||||
group_id?: number | null; // 그룹 ID (독립 필드용)
|
||||
section_id: number | null; // 외래키 - 섹션 ID (독립 필드는 null)
|
||||
master_field_id?: number | null; // 마스터 항목 ID (마스터에서 가져온 경우)
|
||||
field_name: string; // 항목명 (name → field_name)
|
||||
field_key?: string | null; // 2025-11-28: 필드 키 (형식: {ID}_{사용자입력}, 백엔드에서 생성)
|
||||
field_type: 'textbox' | 'number' | 'dropdown' | 'checkbox' | 'date' | 'textarea'; // 필드 타입
|
||||
order_no: number; // 항목 순서 (order → order_no, required)
|
||||
is_required: boolean; // 필수 여부
|
||||
placeholder?: string | null; // 플레이스홀더
|
||||
default_value?: string | null; // 기본값
|
||||
display_condition?: Record<string, any> | null; // 조건부 표시 설정 (displayCondition → display_condition)
|
||||
validation_rules?: Record<string, any> | null; // 검증 규칙
|
||||
options?: Array<{ label: string; value: string }> | null; // dropdown 옵션
|
||||
properties?: Record<string, any> | null; // 추가 속성
|
||||
// 2025-11-28 추가: 잠금 기능
|
||||
is_locked?: boolean; // 잠금 여부
|
||||
locked_by?: number | null; // 잠금 설정자
|
||||
locked_at?: string | null; // 잠금 시간
|
||||
created_by?: number | null; // 생성자 ID 추가
|
||||
updated_by?: number | null; // 수정자 ID 추가
|
||||
created_at: string; // 생성일 (camelCase → snake_case)
|
||||
updated_at: string; // 수정일 추가
|
||||
}
|
||||
|
||||
// BOM 아이템 타입 - API 응답 구조에 맞춰 수정
|
||||
export interface BOMItem {
|
||||
id: number; // 서버 생성 ID (string → number)
|
||||
tenant_id?: number; // 백엔드에서 자동 추가
|
||||
group_id?: number | null; // 그룹 ID (독립 BOM용)
|
||||
section_id: number | null; // 외래키 - 섹션 ID (독립 BOM은 null)
|
||||
item_code?: string | null; // 품목 코드 (itemCode → item_code, optional)
|
||||
item_name: string; // 품목명 (itemName → item_name)
|
||||
quantity: number; // 수량
|
||||
unit?: string | null; // 단위 (optional)
|
||||
unit_price?: number | null; // 단가 추가
|
||||
total_price?: number | null; // 총액 추가
|
||||
spec?: string | null; // 규격/사양 추가
|
||||
note?: string | null; // 비고 (optional)
|
||||
created_by?: number | null; // 생성자 ID 추가
|
||||
updated_by?: number | null; // 수정자 ID 추가
|
||||
created_at: string; // 생성일 (createdAt → created_at)
|
||||
updated_at: string; // 수정일 추가
|
||||
}
|
||||
|
||||
// 섹션 (Section) - API 응답 구조에 맞춰 수정
|
||||
export interface ItemSection {
|
||||
id: number; // 서버 생성 ID (string → number)
|
||||
tenant_id?: number; // 백엔드에서 자동 추가
|
||||
group_id?: number | null; // 그룹 ID (독립 섹션 그룹화용) - 2025-11-26 추가
|
||||
page_id: number | null; // 외래키 - 페이지 ID (null이면 독립 섹션) - 2025-11-26 수정
|
||||
title: string; // 섹션 제목 (API 필드명과 일치하도록 section_name → title)
|
||||
section_type: 'BASIC' | 'BOM' | 'CUSTOM'; // 섹션 타입 (type → section_type, 값 변경)
|
||||
description?: string | null; // 설명
|
||||
order_no: number; // 섹션 순서 (order → order_no)
|
||||
is_template: boolean; // 템플릿 여부 (section_templates 통합) - 2025-11-26 추가
|
||||
is_default: boolean; // 기본 템플릿 여부 - 2025-11-26 추가
|
||||
is_collapsible?: boolean; // 접기/펼치기 가능 여부 (프론트엔드 전용, optional)
|
||||
is_default_open?: boolean; // 기본 열림 상태 (프론트엔드 전용, optional)
|
||||
created_by?: number | null; // 생성자 ID 추가
|
||||
updated_by?: number | null; // 수정자 ID 추가
|
||||
created_at: string; // 생성일 (camelCase → snake_case)
|
||||
updated_at: string; // 수정일 추가
|
||||
fields?: ItemField[]; // 섹션에 포함된 항목들 (optional로 변경)
|
||||
bom_items?: BOMItem[]; // BOM 타입일 경우 BOM 품목 목록 (bomItems → bom_items)
|
||||
}
|
||||
|
||||
// 페이지 (Page) - API 응답 구조에 맞춰 수정
|
||||
export interface ItemPage {
|
||||
id: number; // 서버 생성 ID (string → number)
|
||||
tenant_id?: number; // 백엔드에서 자동 추가
|
||||
page_name: string; // 페이지명 (camelCase → snake_case)
|
||||
item_type: 'FG' | 'PT' | 'SM' | 'RM' | 'CS'; // 품목유형
|
||||
description?: string | null; // 설명 추가
|
||||
absolute_path: string; // 절대경로 (camelCase → snake_case)
|
||||
is_active: boolean; // 사용 여부 (camelCase → snake_case)
|
||||
order_no: number; // 순서 번호 추가
|
||||
created_by?: number | null; // 생성자 ID 추가
|
||||
updated_by?: number | null; // 수정자 ID 추가
|
||||
created_at: string; // 생성일 (camelCase → snake_case)
|
||||
updated_at: string; // 수정일 (camelCase → snake_case)
|
||||
sections: ItemSection[]; // 페이지에 포함된 섹션들 (Nested)
|
||||
}
|
||||
|
||||
// 템플릿 필드 (로컬 관리용 - API에서 제공하지 않음)
|
||||
export interface TemplateField {
|
||||
id: string;
|
||||
name: string;
|
||||
fieldKey: string;
|
||||
property: {
|
||||
inputType: 'textbox' | 'number' | 'dropdown' | 'checkbox' | 'date' | 'textarea';
|
||||
required: boolean;
|
||||
options?: string[];
|
||||
multiColumn?: boolean;
|
||||
columnCount?: number;
|
||||
columnNames?: string[];
|
||||
};
|
||||
description?: string;
|
||||
}
|
||||
|
||||
// 섹션 템플릿 (재사용 가능한 섹션) - Transformer 출력과 UI 요구사항에 맞춤
|
||||
export interface SectionTemplate {
|
||||
id: number;
|
||||
tenant_id: number;
|
||||
template_name: string; // transformer가 title → template_name으로 변환
|
||||
section_type: 'BASIC' | 'BOM' | 'CUSTOM'; // transformer가 type → section_type으로 변환
|
||||
description: string | null;
|
||||
default_fields: TemplateField[] | null; // 기본 필드 (로컬 관리)
|
||||
category?: string[]; // 적용 카테고리 (로컬 관리)
|
||||
fields?: TemplateField[]; // 템플릿에 포함된 필드 (로컬 관리)
|
||||
bomItems?: BOMItem[]; // BOM 타입일 경우 BOM 품목 (로컬 관리)
|
||||
created_by: number | null;
|
||||
updated_by: number | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
Reference in New Issue
Block a user