feat(frontend): 누락된 메뉴 14개 페이지 일괄 구현
신규 페이지 (모두 ProTable / ProCard 패턴): - org/OrgTree: 조직 트리 + 선택 시 우측에 소속 설계사 ProTable - product/CompanyList: 보험사 목록 - product/ProductList: 상품 목록 (보험종 필터) - rule/CommissionRateList: 수수료율 (보험사 통보) - rule/PayoutRuleList: 지급율 (직급 × 보험종 × 회차) - rule/OverrideRuleList: 오버라이드 규정 (직급 페어) - rule/ChargebackRuleList: 환수 규정 (실효 월수 구간) - rule/ExceptionCodeList: 예외 코드 마스터 - ledger/MaintainLedger: 유지수수료 원장 - receive/ReceiveData: 보험사 raw 수신 데이터 - receive/ReceiveMapping: 보험사 프로파일 + 필드 매핑 규칙 - system/MenuManage: 메뉴 트리 표시 (Tree) - system/SystemConfig: 키-값 설정 (그룹별 필터) - system/SystemLog: 로그인/API/변경 이력 3 탭 신규 API 모듈: - api/org.ts (조직 트리) - api/company.ts, api/product.ts - api/rule.ts (5종 통합) - api/receive.ts (profile/field/raw/error) - api/config.ts, api/log.ts App.tsx: 14 라우트 추가 (org/tree, companies, products, rules/*, receive/*, ledger/maintain, system/menus, system/config, system/logs) 검증: - tsc -b 통과 - 12개 백엔드 엔드포인트 200 OK 확인 - dev 서버 HMR 자동 반영 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import api, { PageResponse, unwrap } from './request';
|
||||
|
||||
export interface CompanyResp {
|
||||
companyId: number;
|
||||
companyCode: string;
|
||||
companyName: string;
|
||||
companyType?: string;
|
||||
bizNo?: string;
|
||||
contactName?: string;
|
||||
contactPhone?: string;
|
||||
contactEmail?: string;
|
||||
isActive: string;
|
||||
}
|
||||
|
||||
export interface CompanySearchParam {
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
searchKeyword?: string;
|
||||
isActive?: string;
|
||||
}
|
||||
|
||||
export const companyApi = {
|
||||
list: (p: CompanySearchParam) =>
|
||||
unwrap<PageResponse<CompanyResp>>(api.get('/api/companies', { params: p })),
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import api, { unwrap } from './request';
|
||||
|
||||
export interface SystemConfigResp {
|
||||
configKey: string;
|
||||
configValue?: string;
|
||||
configDesc?: string;
|
||||
configGroup?: string;
|
||||
valueType?: string;
|
||||
isEncrypted?: string;
|
||||
isEditable?: string;
|
||||
updatedAt?: string;
|
||||
updatedBy?: number;
|
||||
}
|
||||
|
||||
export const configApi = {
|
||||
list: (group?: string) =>
|
||||
unwrap<SystemConfigResp[]>(api.get('/api/system/config', { params: { group } })),
|
||||
update: (key: string, value: string) =>
|
||||
unwrap<void>(api.put(`/api/system/config/${key}`, { value })),
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
import api, { PageResponse, unwrap } from './request';
|
||||
|
||||
export interface LoginLogResp {
|
||||
logId: number;
|
||||
userId?: number;
|
||||
username?: string;
|
||||
loginType: string;
|
||||
ipAddress?: string;
|
||||
userAgent?: string;
|
||||
failReason?: string;
|
||||
loginAt?: string;
|
||||
}
|
||||
|
||||
export interface ApiAccessLogResp {
|
||||
logId: number;
|
||||
userId?: number;
|
||||
username?: string;
|
||||
requestMethod: string;
|
||||
requestUrl: string;
|
||||
responseStatus?: number;
|
||||
responseTime?: number;
|
||||
ipAddress?: string;
|
||||
errorMessage?: string;
|
||||
createdAt?: string;
|
||||
}
|
||||
|
||||
export interface DataChangeLogResp {
|
||||
logId: number;
|
||||
tableName: string;
|
||||
recordId?: string;
|
||||
actionType: string;
|
||||
changeData?: any;
|
||||
changeReason?: string;
|
||||
userId?: number;
|
||||
username?: string;
|
||||
ipAddress?: string;
|
||||
menuCode?: string;
|
||||
createdAt?: string;
|
||||
}
|
||||
|
||||
export const logApi = {
|
||||
login: (p: { pageNum?: number; pageSize?: number; username?: string; startDate?: string; endDate?: string }) =>
|
||||
unwrap<PageResponse<LoginLogResp>>(api.get('/api/system/logs/login', { params: p })),
|
||||
api: (p: { pageNum?: number; pageSize?: number; username?: string; startDate?: string; endDate?: string }) =>
|
||||
unwrap<PageResponse<ApiAccessLogResp>>(api.get('/api/system/logs/api', { params: p })),
|
||||
change: (p: { pageNum?: number; pageSize?: number; tableName?: string; username?: string; startDate?: string; endDate?: string }) =>
|
||||
unwrap<PageResponse<DataChangeLogResp>>(api.get('/api/system/logs/data-change', { params: p })),
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import api, { unwrap } from './request';
|
||||
|
||||
export interface OrgNode {
|
||||
orgId: number;
|
||||
parentOrgId?: number;
|
||||
orgName: string;
|
||||
orgType: string; // HQ / BR / TM
|
||||
orgLevel: number;
|
||||
region?: string;
|
||||
effectiveFrom?: string;
|
||||
effectiveTo?: string;
|
||||
isActive: string;
|
||||
children?: OrgNode[];
|
||||
}
|
||||
|
||||
export const orgApi = {
|
||||
tree: () => unwrap<OrgNode[]>(api.get('/api/orgs/tree')),
|
||||
list: () => unwrap<OrgNode[]>(api.get('/api/orgs')),
|
||||
detail: (id: number) => unwrap<OrgNode>(api.get(`/api/orgs/${id}`)),
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
import api, { PageResponse, unwrap } from './request';
|
||||
|
||||
export interface ProductResp {
|
||||
productId: number;
|
||||
companyId: number;
|
||||
companyName?: string;
|
||||
productCode: string;
|
||||
productName: string;
|
||||
insuranceType: string;
|
||||
productGroup?: string;
|
||||
payPeriodType?: string;
|
||||
isActive: string;
|
||||
launchDate?: string;
|
||||
endDate?: string;
|
||||
}
|
||||
|
||||
export interface ProductSearchParam {
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
searchKeyword?: string;
|
||||
companyId?: number;
|
||||
insuranceType?: string;
|
||||
isActive?: string;
|
||||
}
|
||||
|
||||
export const productApi = {
|
||||
list: (p: ProductSearchParam) =>
|
||||
unwrap<PageResponse<ProductResp>>(api.get('/api/products', { params: p })),
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import api, { unwrap } from './request';
|
||||
|
||||
export interface CompanyProfileResp {
|
||||
companyCode: string;
|
||||
dataFormat?: string;
|
||||
receiveMethod?: string;
|
||||
fileEncoding?: string;
|
||||
delimiter?: string;
|
||||
headerRow?: number;
|
||||
dataStartRow?: number;
|
||||
sheetName?: string;
|
||||
dateFormat?: string;
|
||||
amountFormat?: string;
|
||||
apiUrl?: string;
|
||||
ftpHost?: string;
|
||||
ftpPath?: string;
|
||||
receiveSchedule?: string;
|
||||
isActive: string;
|
||||
}
|
||||
|
||||
export interface FieldMappingResp {
|
||||
mappingId: number;
|
||||
companyCode: string;
|
||||
sourceField: string;
|
||||
sourceColIndex?: number;
|
||||
targetTable: string;
|
||||
targetField: string;
|
||||
dataType?: string;
|
||||
transformRule?: string;
|
||||
defaultValue?: string;
|
||||
isRequired?: string;
|
||||
sortOrder: number;
|
||||
version?: number;
|
||||
effectiveFrom?: string;
|
||||
}
|
||||
|
||||
export interface RawCommissionResp {
|
||||
rawId: number;
|
||||
companyCode: string;
|
||||
batchId?: string;
|
||||
settleMonth: string;
|
||||
dataType: string;
|
||||
parseStatus: string;
|
||||
mappedLedgerId?: number;
|
||||
mappedTable?: string;
|
||||
fileName?: string;
|
||||
rowNumber?: number;
|
||||
receivedAt?: string;
|
||||
parsedAt?: string;
|
||||
}
|
||||
|
||||
export interface ParseErrorResp {
|
||||
errorId: number;
|
||||
rawId?: number;
|
||||
companyCode: string;
|
||||
errorType: string;
|
||||
errorField?: string;
|
||||
errorValue?: string;
|
||||
errorMessage?: string;
|
||||
resolveStatus: string;
|
||||
resolvedBy?: number;
|
||||
resolveNote?: string;
|
||||
resolvedAt?: string;
|
||||
createdAt?: string;
|
||||
}
|
||||
|
||||
export const receiveApi = {
|
||||
profiles: () => unwrap<CompanyProfileResp[]>(api.get('/api/receive/profiles')),
|
||||
fields: (companyCode: string) =>
|
||||
unwrap<FieldMappingResp[]>(api.get(`/api/receive/mapping/${companyCode}/fields`)),
|
||||
raw: (params: { companyCode?: string; settleMonth?: string; parseStatus?: string }) =>
|
||||
unwrap<RawCommissionResp[]>(api.get('/api/receive/raw', { params })),
|
||||
errors: (params: { companyCode?: string; resolveStatus?: string }) =>
|
||||
unwrap<ParseErrorResp[]>(api.get('/api/receive/errors', { params })),
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
import api, { unwrap } from './request';
|
||||
|
||||
export interface CommissionRateResp {
|
||||
rateId: number;
|
||||
productId: number;
|
||||
productName?: string;
|
||||
commissionYear: number;
|
||||
ratePct: number;
|
||||
payMethodCond?: string;
|
||||
minPremium?: number;
|
||||
effectiveFrom?: string;
|
||||
effectiveTo?: string;
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface PayoutRuleResp {
|
||||
ruleId: number;
|
||||
gradeId: number;
|
||||
gradeName?: string;
|
||||
insuranceType: string;
|
||||
commissionYear: number;
|
||||
payoutPct: number;
|
||||
payMethodCond?: string;
|
||||
performanceGrade?: string;
|
||||
effectiveFrom?: string;
|
||||
effectiveTo?: string;
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface OverrideRuleResp {
|
||||
overrideId: number;
|
||||
fromGrade: number;
|
||||
toGrade: number;
|
||||
fromGradeName?: string;
|
||||
toGradeName?: string;
|
||||
overridePct: number;
|
||||
calcType?: string;
|
||||
insuranceTypeCond?: string;
|
||||
capAmount?: number;
|
||||
effectiveFrom?: string;
|
||||
effectiveTo?: string;
|
||||
}
|
||||
|
||||
export interface ChargebackRuleResp {
|
||||
cbRuleId: number;
|
||||
companyCode: string;
|
||||
insuranceType: string;
|
||||
lapseMonthFrom: number;
|
||||
lapseMonthTo: number;
|
||||
cbRate: number;
|
||||
includeOverride: string;
|
||||
installmentAllowed: string;
|
||||
maxInstallments?: number;
|
||||
effectiveFrom?: string;
|
||||
effectiveTo?: string;
|
||||
}
|
||||
|
||||
export interface ExceptionCodeResp {
|
||||
exceptionCode: string;
|
||||
exceptionName: string;
|
||||
category?: string;
|
||||
direction: string;
|
||||
autoCalcYn: string;
|
||||
approvalRequired: string;
|
||||
taxIncluded: string;
|
||||
description?: string;
|
||||
isActive: string;
|
||||
}
|
||||
|
||||
export const ruleApi = {
|
||||
commissionRates: (params?: { productId?: number; year?: number }) =>
|
||||
unwrap<CommissionRateResp[]>(api.get('/api/rules/commission-rates', { params })),
|
||||
payoutRules: (params?: { gradeId?: number; insuranceType?: string }) =>
|
||||
unwrap<PayoutRuleResp[]>(api.get('/api/rules/payout', { params })),
|
||||
overrideRules: () => unwrap<OverrideRuleResp[]>(api.get('/api/rules/override')),
|
||||
chargebackRules: (params?: { companyCode?: string }) =>
|
||||
unwrap<ChargebackRuleResp[]>(api.get('/api/rules/chargeback', { params })),
|
||||
exceptionCodes: () => unwrap<ExceptionCodeResp[]>(api.get('/api/rules/exception-codes')),
|
||||
};
|
||||
Reference in New Issue
Block a user