import { useState } from 'react'; import { Alert, Form, Input, InputNumber, Modal, Space, Tabs, message } from 'antd'; import { ProCard } from '@ant-design/pro-components'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import type { ColDef } from '@ag-grid-community/core'; import dayjs from 'dayjs'; import PageContainer from '@/components/common/PageContainer'; import SearchForm from '@/components/common/SearchForm'; import DataGrid from '@/components/common/DataGrid'; import PermissionButton from '@/components/common/PermissionButton'; import { commissionApi, BranchAllowanceRuleRow, BranchAllowanceLedgerRow, CommissionSearchParam, } from '@/api/commission'; import { GRAY, RADIUS, SHADOW } from '@/theme/tokens'; const fmt = (v: unknown) => (v as number)?.toLocaleString() ?? '-'; const fmtRate = (v: unknown) => v != null ? `${((v as number) * 100).toFixed(2)}%` : '-'; const RULE_COLS: ColDef[] = [ { field: 'positionCode', headerName: '직책코드', width: 130 }, { field: 'allowanceRate', headerName: '수당율', width: 110, type: 'numericColumn', valueFormatter: (p) => fmtRate(p.value) }, { field: 'capAmount', headerName: '상한', flex: 1, type: 'numericColumn', valueFormatter: (p) => fmt(p.value) }, { field: 'effectiveFrom', headerName: '적용시작', width: 120 }, { field: 'effectiveTo', headerName: '적용종료', width: 120 }, ]; const LEDGER_COLS: ColDef[] = [ { field: 'settleMonth', headerName: '정산월', width: 110, pinned: 'left' }, { field: 'managerAgentName',headerName: '지점장', width: 130 }, { field: 'orgName', headerName: '조직명', width: 130 }, { field: 'baseAmount', headerName: '조직실적', flex: 1, type: 'numericColumn', valueFormatter: (p) => fmt(p.value) }, { field: 'allowanceRate', headerName: '수당율', width: 110, type: 'numericColumn', valueFormatter: (p) => fmtRate(p.value) }, { field: 'allowanceAmount', headerName: '수당금액', flex: 1, type: 'numericColumn', valueFormatter: (p) => fmt(p.value) }, { field: 'clawbackAmount', headerName: '환수액', flex: 1, type: 'numericColumn', valueFormatter: (p) => fmt(p.value) }, { field: 'status', headerName: '상태', width: 100 }, ]; export default function BranchAllowance() { const qc = useQueryClient(); const [ledgerParams, setLedgerParams] = useState({ settleMonth: dayjs().format('YYYYMM'), pageSize: 200, }); const [ruleModalOpen, setRuleModalOpen] = useState(false); const [editingRule, setEditingRule] = useState(null); const [form] = Form.useForm(); const { data: rulesData, isLoading: rulesLoading, isError: rulesError } = useQuery({ queryKey: ['branchAllowance', 'rules'], queryFn: () => commissionApi.branchAllowanceRules(), retry: false, }); const { data: ledgersData, isLoading: ledgersLoading } = useQuery({ queryKey: ['branchAllowance', 'ledgers', ledgerParams], queryFn: () => commissionApi.branchAllowanceLedgers(ledgerParams), retry: false, }); const rules = rulesData?.list ?? []; const ledgers = ledgersData?.list ?? []; const openCreate = () => { setEditingRule(null); form.resetFields(); setRuleModalOpen(true); }; const openEdit = (row: BranchAllowanceRuleRow) => { setEditingRule(row); form.setFieldsValue(row); setRuleModalOpen(true); }; const handleSave = async () => { const values = await form.validateFields(); try { if (editingRule) { await commissionApi.branchAllowanceRuleUpdate(editingRule.ruleId, values); message.success('수정 완료'); } else { await commissionApi.branchAllowanceRuleCreate(values); message.success('등록 완료'); } qc.invalidateQueries({ queryKey: ['branchAllowance', 'rules'] }); setRuleModalOpen(false); } catch { /* request.ts 처리 */ } }; const handleDelete = (id: number) => Modal.confirm({ title: '룰 삭제', content: '삭제하시겠습니까?', onOk: async () => { await commissionApi.branchAllowanceRuleDelete(id); message.success('삭제 완료'); qc.invalidateQueries({ queryKey: ['branchAllowance', 'rules'] }); }, }); const pinnedLedger = ledgers.length > 0 ? { managerAgentName: '합계', baseAmount: ledgers.reduce((s, r) => s + (r.baseAmount ?? 0), 0), allowanceAmount: ledgers.reduce((s, r) => s + (r.allowanceAmount ?? 0), 0), clawbackAmount: ledgers.reduce((s, r) => s + (r.clawbackAmount ?? 0), 0), } as Partial : undefined; const cardStyle = { background: '#fff', borderRadius: RADIUS.lg, border: `1px solid ${GRAY[100]}`, boxShadow: SHADOW.sm }; return ( {rulesError && ( )}
+ 룰 등록
rows={rules} columns={[ ...RULE_COLS, { headerName: '액션', width: 160, pinned: 'right', cellRenderer: (p: { data: BranchAllowanceRuleRow }) => ( openEdit(p.data)}>수정 handleDelete(p.data.ruleId)}>삭제 ), }, ]} loading={rulesLoading} height={520} rowKey="ruleId" /> ), }, { key: 'ledgers', label: '원장', children: ( <> setLedgerParams({ ...v as CommissionSearchParam, pageSize: 200 })} onReset={() => setLedgerParams({ settleMonth: dayjs().format('YYYYMM'), pageSize: 200 })} /> rows={ledgers} columns={LEDGER_COLS} loading={ledgersLoading} height={520} rowKey="ledgerId" pinnedBottomRow={pinnedLedger} /> ), }, ]} /> setRuleModalOpen(false)} okText="저장" cancelText="취소" >
); }