세금계산서 목록 및 상세 조회 기능 구현

This commit is contained in:
Jay Sheen
2025-09-24 09:53:09 +09:00
parent 9c84991e93
commit 32dec9af25
9 changed files with 150 additions and 40 deletions

View File

@@ -1,5 +1,5 @@
import axios from 'axios'; import axios from 'axios';
import { API_URL } from '@/shared/api/urls'; import { API_URL_TAX } from '@/shared/api/api-url-tax';
import { resultify } from '@/shared/lib/resultify'; import { resultify } from '@/shared/lib/resultify';
import { CBDCAxiosError } from '@/shared/@types/error'; import { CBDCAxiosError } from '@/shared/@types/error';
import { import {
@@ -10,11 +10,10 @@ import {
useMutation, useMutation,
UseMutationOptions UseMutationOptions
} from '@tanstack/react-query'; } from '@tanstack/react-query';
import { API_URL_TRANSACTION } from '@/shared/api/api-url-transaction';
export const invoiceDetail = (params: InvoiceDetailParams) => { export const invoiceDetail = (params: InvoiceDetailParams) => {
return resultify( return resultify(
axios.post<InvoiceDetailResponse>(API_URL_TRANSACTION.allTransactionList(), params), axios.post<InvoiceDetailResponse>(API_URL_TAX.invoiceDetail(), params),
); );
}; };

View File

@@ -0,0 +1,29 @@
import axios from 'axios';
import { API_URL_TAX } from '@/shared/api/api-url-tax';
import { resultify } from '@/shared/lib/resultify';
import { CBDCAxiosError } from '@/shared/@types/error';
import {
InvoiceListResponse,
InvoiceListParams,
} from '../model/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
export const invoiceList = (params: InvoiceListParams) => {
return resultify(
axios.post<InvoiceListResponse>(API_URL_TAX.invoiceList(), params),
);
};
export const useInvoiceListMutation = (options?: UseMutationOptions<InvoiceListResponse, CBDCAxiosError, InvoiceListParams>) => {
const mutation = useMutation<InvoiceListResponse, CBDCAxiosError, InvoiceListParams>({
...options,
mutationFn: (params: InvoiceListParams) => invoiceList(params),
});
return {
...mutation,
};
};

View File

@@ -1,3 +1,6 @@
import { DefaulResponsePagination, DefaultRequestPagination } from '@/entities/common/model/types';
export enum TaxTabKeys { export enum TaxTabKeys {
InvoiceList = 'InvoiceList', InvoiceList = 'InvoiceList',
VatReference = 'VatReference', VatReference = 'VatReference',
@@ -18,22 +21,30 @@ export enum DetailInfoSectionKeys {
}; };
export interface InvoiceListParams { export interface InvoiceListParams {
mid: string;
startDate?: string;
endDate?: string;
receiptType?: string;
targetType?: string;
};
};
export interface invoiceListResponse {
export interface InvoiceListResponse extends DefaulResponsePagination {
content: Array<ListItemProps>;
}
export interface ListItemProps extends InvoiceListItem {
}; };
export interface ListItem {
tid?: string; export interface InvoiceListItem {
pname?: string; id: number
userid?: string; companyName: string;
idate?: string; mid: string;
kind?: string; issueDate: string;
amount?: number; paymentMethod: string;
}; amount: number;
export interface ListItemProps extends ListItem{
}; };
export interface ListDateGroupProps { export interface ListDateGroupProps {
date: string; date: string;
items: Array<ListItemProps> items: Array<ListItemProps>
@@ -45,6 +56,7 @@ export interface InvoiceDetailParams {
svcCd?: string; svcCd?: string;
tid: string; tid: string;
}; };
export interface InvoiceDetailResponse { export interface InvoiceDetailResponse {
}; };

View File

@@ -4,7 +4,17 @@ import { InvoiceFilterProps } from '../model/types';
export const InvoiceFilter = ({ export const InvoiceFilter = ({
filterOn, filterOn,
setFilterOn setFilterOn,
mid,
startDate,
endDate,
receiptType,
targetType,
setMid,
setStartDate,
setEndDate,
setReceiptType,
setTargetType
}: InvoiceFilterProps) => { }: InvoiceFilterProps) => {
const variants = { const variants = {
hidden: { x: '100%' }, hidden: { x: '100%' },

View File

@@ -1,23 +1,45 @@
import moment from 'moment';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { IMAGE_ROOT } from '@/shared/constants/common'; import { IMAGE_ROOT } from '@/shared/constants/common';
import { InvoiceFilter } from './invoice-filter'; import { InvoiceFilter } from './invoice-filter';
import { SortOptionsBox } from '@/entities/common/ui/sort-options-box'; import { SortOptionsBox } from '@/entities/common/ui/sort-options-box';
import { SortByKeys } from '@/entities/common/model/types'; import { SortByKeys } from '@/entities/common/model/types';
import { InvoiceList } from './invoice-list'; import { InvoiceList } from './invoice-list';
import { useInvoiceListMutation } from '../api/use-invoice-list-mutation';
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
export const InvoiceListWrap = () => { export const InvoiceListWrap = () => {
const [filterOn, setFilterOn] = useState<boolean>(false); const [filterOn, setFilterOn] = useState<boolean>(false);
const [sortBy, setSortBy] = useState<SortByKeys>(SortByKeys.New); const [sortBy, setSortBy] = useState<SortByKeys>(SortByKeys.New);
const [listItems, setListItems] = useState({}); const [listItems, setListItems] = useState({});
const [pageParam, setPageParam] = useState(DEFAULT_PAGE_PARAM);
const [mid, setMid] = useState<string>('nictest00m');
const [startDate, setStartDate] = useState(moment().subtract(1, 'month').format('YYYY-MM-DD'));
const [endDate, setEndDate] = useState(moment().format('YYYY-MM-DD'));
const [receiptType, setReceiptType] = useState<string>('');
const [targetType, setTargetType] = useState<string>('');
const { mutateAsync: invoiceList } = useInvoiceListMutation();
const callList = () => { const callList = () => {
setListItems({ let listParams = {
'20250601': [ mid: mid,
{tid: 'a1234567', pname: '와와디디', userid: 'nictest01m', idate: '20250630', kind: 'PG수수료', amount: 48125100}, startDate: startDate,
{tid: 'b34534534', pname: '와와디디', userid: 'wadizcop@m', idate: '20250630', kind: 'PG수수료', amount: 23845000}, endDate: endDate,
] receiptType: receiptType,
}) targetType: targetType,
};
invoiceList(listParams).then((rs) => {
setListItems(assembleData(rs.content));
});
// setListItems({
// '20250601': [
// {tid: 'a1234567', pname: '와와디디', userid: 'nictest01m', idate: '20250630', kind: 'PG수수료', amount: 48125100},
// {tid: 'b34534534', pname: '와와디디', userid: 'wadizcop@m', idate: '20250630', kind: 'PG수수료', amount: 23845000},
// ]
// })
}; };
const onClickToOpenFIlter = () => { const onClickToOpenFIlter = () => {
setFilterOn(true); setFilterOn(true);
}; };
@@ -28,6 +50,23 @@ export const InvoiceListWrap = () => {
useEffect(() => { useEffect(() => {
callList(); callList();
}, []); }, []);
const assembleData = (content: Array<ListItemProps>) => {
let data: any = {};
if(content && content.length > 0){
for(let i=0;i<content?.length;i++){
let groupDate = moment(content[i]?.issueDate).format('YYYYMMDD');
if(!!groupDate && !data.hasOwnProperty(groupDate)){
data[groupDate] = [];
}
if(!!groupDate && data.hasOwnProperty(groupDate)){
data[groupDate].push(content[i]);
}
}
}
console.log('Data : ', data)
return data;
};
return ( return (
<> <>
<div className="summary-section pt-30"> <div className="summary-section pt-30">
@@ -36,7 +75,7 @@ export const InvoiceListWrap = () => {
<input <input
type="text" type="text"
className="credit-period" className="credit-period"
value="2025.06.01 ~ 2025.06.31" value={moment(startDate).format('YYYY.MM.DD') + '-' + moment(endDate).format('YYYY.MM.DD')}
readOnly={ true } readOnly={ true }
/> />
<button <button
@@ -111,6 +150,16 @@ export const InvoiceListWrap = () => {
<InvoiceFilter <InvoiceFilter
filterOn={ filterOn } filterOn={ filterOn }
setFilterOn={ setFilterOn } setFilterOn={ setFilterOn }
mid={ mid }
startDate={ startDate }
endDate={ endDate }
receiptType={ receiptType }
targetType={ targetType }
setMid={ setMid }
setStartDate={ setStartDate }
setEndDate={ setEndDate }
setReceiptType={ setReceiptType }
setTargetType={ setTargetType }
></InvoiceFilter> ></InvoiceFilter>
</> </>
); );

View File

@@ -21,11 +21,11 @@ export const ListDateGroup = ({
rs.push( rs.push(
<ListItem <ListItem
key={ key } key={ key }
tid={ items[i]?.tid } id={ items[i]?.id }
pname={ items[i]?.pname } companyName={ items[i]?.companyName }
userid={ items[i]?.userid } mid={ items[i]?.mid }
idate={ items[i]?.idate } issueDate={ items[i]?.issueDate }
kind={ items[i]?.kind } paymentMethod={ items[i]?.paymentMethod }
amount={ items[i]?.amount } amount={ items[i]?.amount }
></ListItem> ></ListItem>
) )

View File

@@ -5,11 +5,11 @@ import { ListItemProps } from '../model/types';
import moment from 'moment'; import moment from 'moment';
export const ListItem = ({ export const ListItem = ({
tid, id,
pname, companyName,
userid, mid,
idate, issueDate,
kind, paymentMethod,
amount amount
}: ListItemProps) => { }: ListItemProps) => {
const { navigate } = useNavigate(); const { navigate } = useNavigate();
@@ -17,11 +17,10 @@ export const ListItem = ({
const onClickToNavigate = () => { const onClickToNavigate = () => {
navigate(PATHS.tax.invoice.detail, { navigate(PATHS.tax.invoice.detail, {
state: { state: {
tid: tid id: id
} }
}); });
}; };
return ( return (
<> <>
@@ -33,11 +32,11 @@ export const ListItem = ({
<div className="status-dot blue"></div> <div className="status-dot blue"></div>
</div> </div>
<div className="transaction-content"> <div className="transaction-content">
<div className="transaction-title">{ pname } ({ userid })</div> <div className="transaction-title">{ companyName } ({ mid })</div>
<div className="transaction-details"> <div className="transaction-details">
<span>{ moment(idate).format('YYYY.MM.DD') }</span> <span>{ moment(issueDate).format('YYYY.MM.DD') }</span>
<span className="separator">|</span> <span className="separator">|</span>
<span>{ kind }</span> <span>{ paymentMethod }</span>
</div> </div>
</div> </div>
<div className="transaction-amount"> <div className="transaction-amount">

View File

@@ -14,7 +14,6 @@ import {
export const InvoiceListPage = () => { export const InvoiceListPage = () => {
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const [activeTab, setActiveTab] = useState<TaxTabKeys>(TaxTabKeys.InvoiceList); const [activeTab, setActiveTab] = useState<TaxTabKeys>(TaxTabKeys.InvoiceList);
useSetHeaderTitle('부가세 신고 자료'); useSetHeaderTitle('부가세 신고 자료');
useSetHeaderType(HeaderType.LeftArrow); useSetHeaderType(HeaderType.LeftArrow);
@@ -27,7 +26,7 @@ export const InvoiceListPage = () => {
<> <>
<main> <main>
<div className="tab-content"> <div className="tab-content">
<div className="tab-pane sub active"> <div className="tab-pane pt-46 active">
<TaxTab activeTab={ activeTab }></TaxTab> <TaxTab activeTab={ activeTab }></TaxTab>
<InvoiceListWrap></InvoiceListWrap> <InvoiceListWrap></InvoiceListWrap>
</div> </div>

View File

@@ -0,0 +1,13 @@
import {
API_BASE_URL,
API_URL_KEY,
} from './../constants/url';
export const API_URL_TAX = {
invoiceList: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/vat-return/list`;
},
invoiceDetail: () => {
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/vat-return/detail`;
},
};