수기발행 / 현금영수증 용도변경
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import axios from 'axios';
|
||||
import { API_URL } from '@/shared/api/urls';
|
||||
import { resultify } from '@/shared/lib/resultify';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
import {
|
||||
CashReceiptManualIssueParams,
|
||||
CashReceiptManualIssueResponse
|
||||
} from '../model/types';
|
||||
import {
|
||||
useMutation,
|
||||
UseMutationOptions
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
export const cashReceiptManualIssue = (params: CashReceiptManualIssueParams) => {
|
||||
return resultify(
|
||||
axios.post<CashReceiptManualIssueResponse>(API_URL.cashReceiptManualIssue(), params),
|
||||
);
|
||||
};
|
||||
|
||||
export const useCashReceiptManualIssueMutation = (options?: UseMutationOptions<CashReceiptManualIssueResponse, CBDCAxiosError, CashReceiptManualIssueParams>) => {
|
||||
const mutation = useMutation<CashReceiptManualIssueResponse, CBDCAxiosError, CashReceiptManualIssueParams>({
|
||||
...options,
|
||||
mutationFn: (params: CashReceiptManualIssueParams) => cashReceiptManualIssue(params),
|
||||
});
|
||||
|
||||
return {
|
||||
...mutation,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
import axios from 'axios';
|
||||
import { API_URL } from '@/shared/api/urls';
|
||||
import { resultify } from '@/shared/lib/resultify';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
import {
|
||||
CashReceiptPurposeUpdateParams,
|
||||
CashReceiptPurposeUpdateResponse
|
||||
} from '../model/types';
|
||||
import {
|
||||
useMutation,
|
||||
UseMutationOptions
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
export const cashReceiptPurposeUpdate = (params: CashReceiptPurposeUpdateParams) => {
|
||||
return resultify(
|
||||
axios.post<CashReceiptPurposeUpdateResponse>(API_URL.cashReceiptPurposeUpdate(), params),
|
||||
);
|
||||
};
|
||||
|
||||
export const useCashReceiptPurposeUpdateMutation = (options?: UseMutationOptions<CashReceiptPurposeUpdateResponse, CBDCAxiosError, CashReceiptPurposeUpdateParams>) => {
|
||||
const mutation = useMutation<CashReceiptPurposeUpdateResponse, CBDCAxiosError, CashReceiptPurposeUpdateParams>({
|
||||
...options,
|
||||
mutationFn: (params: CashReceiptPurposeUpdateParams) => cashReceiptPurposeUpdate(params),
|
||||
});
|
||||
|
||||
return {
|
||||
...mutation,
|
||||
};
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DefaulResponsePagination, DefaultRequestPagination } from '@/entities/common/model/types';
|
||||
import { DefaulResponsePagination, DefaultRequestPagination, SuccessResult } from '@/entities/common/model/types';
|
||||
|
||||
export enum CancelTabKeys {
|
||||
All = 'All',
|
||||
@@ -33,6 +33,11 @@ export enum ProcessStep {
|
||||
One = 'One',
|
||||
Two = 'Two',
|
||||
};
|
||||
export enum CashReceiptPurpose {
|
||||
ALL = 'ALL',
|
||||
INCOME_DEDUCTION = 'INCOME_DEDUCTION',
|
||||
EXPENSE_PROOF = 'EXPENSE_PROOF',
|
||||
};
|
||||
export interface SortOptionsBoxProps {
|
||||
sortBy: SortByKeys;
|
||||
onCliCkToSort: (sortBy: SortByKeys) => void;
|
||||
@@ -301,7 +306,7 @@ export interface IssueInfo {
|
||||
approvalNumber?: number;
|
||||
issueNumber?: number;
|
||||
issueDateTime?: string;
|
||||
purpose?: string;
|
||||
purpose?: CashReceiptPurpose;
|
||||
paymentMethod?: string;
|
||||
productName?: string;
|
||||
transmissionStatus?: string;
|
||||
@@ -361,11 +366,11 @@ export interface BillingDetailResponse extends BillingInfo {
|
||||
}
|
||||
|
||||
export interface DetailInfoProps extends DetailResponse {
|
||||
transactionCategory: TransactionCategory;
|
||||
transactionCategory?: TransactionCategory;
|
||||
show?: boolean;
|
||||
tid?: string;
|
||||
serviceCode?: string;
|
||||
issueNumber?: number;
|
||||
purpose?: CashReceiptPurpose;
|
||||
onClickToShowInfo?: (info: InfoWrapKeys) => void;
|
||||
}
|
||||
export interface DetailArrowProps {
|
||||
@@ -415,4 +420,34 @@ export interface AllTransactionCancelInfoResponse {
|
||||
export interface FilterProps {
|
||||
filterOn: boolean;
|
||||
setFilterOn: (filterOn: boolean) => void;
|
||||
}
|
||||
};
|
||||
|
||||
export interface CashReceiptPurposeUpdateParams {
|
||||
issueNumber: number;
|
||||
newPurpose: string;
|
||||
};
|
||||
export interface CashReceiptPurposeUpdateResponse {
|
||||
issueNumber: number;
|
||||
beforePurposeType: CashReceiptPurpose;
|
||||
afterPurposeType: CashReceiptPurpose;
|
||||
updateDateTime: string;
|
||||
};
|
||||
export interface CashReceiptManualIssueParams {
|
||||
businessNumber: string,
|
||||
purpose: CashReceiptPurpose
|
||||
productName: string,
|
||||
buyerName: string,
|
||||
issueNumber: string,
|
||||
email: string,
|
||||
phoneNumber: string,
|
||||
supplyAmount: number,
|
||||
vatAmount: number,
|
||||
taxFreeAmount: number,
|
||||
serviceCharge: number
|
||||
};
|
||||
export interface CashReceiptManualIssueResponse {
|
||||
approvalNumber: number,
|
||||
totalAmount: number,
|
||||
issueDateTime: string,
|
||||
issueResult: SuccessResult
|
||||
};
|
||||
|
||||
@@ -1,11 +1,42 @@
|
||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
export const BottomSheetChangesCashReceitUses = () => {
|
||||
export interface BottomSheetCashReceitPurposeUpdateProps {
|
||||
setBottomSheetOn: (bottomSheetOn: boolean) => void;
|
||||
bottomSheetOn: boolean;
|
||||
callPurposeUpdate: () => void;
|
||||
};
|
||||
|
||||
export const BottomSheetCashReceitPurposeUpdate = ({
|
||||
setBottomSheetOn,
|
||||
bottomSheetOn,
|
||||
callPurposeUpdate
|
||||
}: BottomSheetCashReceitPurposeUpdateProps) => {
|
||||
|
||||
const onClickToClose = () => {
|
||||
setBottomSheetOn(false);
|
||||
};
|
||||
const onCliickToPurposeUpdate = () => {
|
||||
callPurposeUpdate();
|
||||
};
|
||||
|
||||
const variants = {
|
||||
hidden: { y: '100%' },
|
||||
visible: { y: '0%' },
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="bg-dim"></div>
|
||||
<div className="bottomsheet">
|
||||
{ (bottomSheetOn) &&
|
||||
<div className="bg-dim"></div>
|
||||
}
|
||||
<motion.div
|
||||
className="bottomsheet"
|
||||
initial="hidden"
|
||||
animate={ (bottomSheetOn)? 'visible': 'hidden' }
|
||||
variants={ variants }
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
<div className="bottomsheet-header">
|
||||
<div className="bottomsheet-title">
|
||||
<h2>신청 방법을 선택하세요</h2>
|
||||
@@ -13,9 +44,10 @@ export const BottomSheetChangesCashReceitUses = () => {
|
||||
className="close-btn"
|
||||
type="button"
|
||||
>
|
||||
<img
|
||||
<img
|
||||
src={ IMAGE_ROOT + '/ico_close.svg' }
|
||||
alt="닫기"
|
||||
onClick={ () => onClickToClose() }
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
@@ -35,9 +67,10 @@ export const BottomSheetChangesCashReceitUses = () => {
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
type="button"
|
||||
onClick={ () => onCliickToPurposeUpdate() }
|
||||
>신청</button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,10 +1,44 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout';
|
||||
import { CashReceiptPurpose } from '../model/types';
|
||||
|
||||
export const CashReceiptHandWrittenIssuanceStep1 = () => {
|
||||
export interface CashReceiptHandWrittenIssuanceStep1Props {
|
||||
businessNumber?: string;
|
||||
purpose?: CashReceiptPurpose;
|
||||
productName?: string;
|
||||
buyerName?: string;
|
||||
issueNumber?: string;
|
||||
email?: string;
|
||||
phoneNumber?: string;
|
||||
setBusinessNumber: (businessNumber: string) => void;
|
||||
setPurpose: (purpose: CashReceiptPurpose) => void;
|
||||
setProductName: (productName: string) => void;
|
||||
setBuyerName: (buyerName: string) => void;
|
||||
setIssueNumber: (issueNumber: string) => void;
|
||||
setEmail: (email: string) => void;
|
||||
setPhoneNumber: (phoneNumber: string) => void;
|
||||
};
|
||||
|
||||
export const CashReceiptHandWrittenIssuanceStep1 = ({
|
||||
businessNumber,
|
||||
purpose,
|
||||
productName,
|
||||
buyerName,
|
||||
issueNumber,
|
||||
email,
|
||||
phoneNumber,
|
||||
setBusinessNumber,
|
||||
setPurpose,
|
||||
setProductName,
|
||||
setBuyerName,
|
||||
setIssueNumber,
|
||||
setEmail,
|
||||
setPhoneNumber
|
||||
}: CashReceiptHandWrittenIssuanceStep1Props) => {
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
|
||||
useSetOnBack(() => {
|
||||
navigate(PATHS.transaction.cashReceipt.list);
|
||||
});
|
||||
@@ -18,7 +52,7 @@ export const CashReceiptHandWrittenIssuanceStep1 = () => {
|
||||
<input
|
||||
className="error"
|
||||
type="text"
|
||||
value="123456789"
|
||||
value={ businessNumber }
|
||||
disabled={ true }
|
||||
/>
|
||||
</div>
|
||||
@@ -29,12 +63,14 @@ export const CashReceiptHandWrittenIssuanceStep1 = () => {
|
||||
<div className="issue-field">
|
||||
<div className="seg-buttons">
|
||||
<button
|
||||
className="btn-40 btn-blue"
|
||||
className={ `btn-40 ${(purpose === CashReceiptPurpose.INCOME_DEDUCTION)? 'btn-blue': 'btn-white'}` }
|
||||
type="button"
|
||||
onClick={ () => setPurpose(CashReceiptPurpose.INCOME_DEDUCTION) }
|
||||
>소득공제</button>
|
||||
<button
|
||||
className="btn-40 btn-white"
|
||||
className={ `btn-40 ${(purpose === CashReceiptPurpose.EXPENSE_PROOF)? 'btn-blue': 'btn-white'}` }
|
||||
type="button"
|
||||
onClick={ () => setPurpose(CashReceiptPurpose.EXPENSE_PROOF) }
|
||||
>지출증빙</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,6 +81,8 @@ export const CashReceiptHandWrittenIssuanceStep1 = () => {
|
||||
<input
|
||||
type="text"
|
||||
placeholder="상품명"
|
||||
value={ productName }
|
||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setProductName(e.target.value) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -54,6 +92,8 @@ export const CashReceiptHandWrittenIssuanceStep1 = () => {
|
||||
<input
|
||||
type="text"
|
||||
placeholder="구매자명"
|
||||
value={ buyerName }
|
||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setBuyerName(e.target.value) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -63,6 +103,8 @@ export const CashReceiptHandWrittenIssuanceStep1 = () => {
|
||||
<input
|
||||
type="text"
|
||||
placeholder="사업자번호 OR 휴대폰번호"
|
||||
value={ issueNumber }
|
||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setIssueNumber(e.target.value) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,6 +114,8 @@ export const CashReceiptHandWrittenIssuanceStep1 = () => {
|
||||
<input
|
||||
type="email"
|
||||
placeholder="TEST123@nicepay.com"
|
||||
value={ email }
|
||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setEmail(e.target.value) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -81,6 +125,8 @@ export const CashReceiptHandWrittenIssuanceStep1 = () => {
|
||||
<input
|
||||
type="tel"
|
||||
placeholder="01012345678"
|
||||
value={ phoneNumber }
|
||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setPhoneNumber(e.target.value) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,37 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout';
|
||||
import { ProcessStep } from '../model/types';
|
||||
|
||||
export interface CashReceiptHandWrittenIssuanceStep2Props {
|
||||
setProcessStep: ((processStep: ProcessStep) => void);
|
||||
setProcessStep: (processStep: ProcessStep) => void;
|
||||
supplyAmount: number | string;
|
||||
vatAmount: number | string;
|
||||
taxFreeAmount: number | string;
|
||||
serviceCharge: number | string;
|
||||
setSupplyAmount: (supplyAmount: number | string) => void;
|
||||
setVatAmount: (vatAmount: number | string) => void;
|
||||
setTaxFreeAmount: (taxFreeAmount: number | string) => void;
|
||||
setServiceCharge: (serviceCharge: number | string) => void;
|
||||
};
|
||||
export const CashReceiptHandWrittenIssuanceStep2 = ({
|
||||
setProcessStep
|
||||
setProcessStep,
|
||||
supplyAmount,
|
||||
vatAmount,
|
||||
taxFreeAmount,
|
||||
serviceCharge,
|
||||
setSupplyAmount,
|
||||
setVatAmount,
|
||||
setTaxFreeAmount,
|
||||
setServiceCharge
|
||||
}: CashReceiptHandWrittenIssuanceStep2Props) => {
|
||||
useSetOnBack(() => {
|
||||
setProcessStep(ProcessStep.One);
|
||||
});
|
||||
|
||||
const onClickToVatCalculate = () => {
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className="issue-title">발행 금액 입력</h2>
|
||||
@@ -27,6 +49,7 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({
|
||||
<button
|
||||
className="btn-40 btn-white"
|
||||
type="button"
|
||||
onClick={ () => onClickToVatCalculate() }
|
||||
>VAT자동계산</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -39,6 +62,8 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({
|
||||
className="error"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={ supplyAmount }
|
||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setSupplyAmount(e.target.value) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -49,26 +74,32 @@ export const CashReceiptHandWrittenIssuanceStep2 = ({
|
||||
className="error"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={ vatAmount }
|
||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setVatAmount(e.target.value) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="issue-row">
|
||||
<div className="issue-label">발행번호</div>
|
||||
<div className="issue-label">면세금액</div>
|
||||
<div className="issue-field">
|
||||
<input
|
||||
className="error"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={ taxFreeAmount }
|
||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setTaxFreeAmount(e.target.value) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="issue-row">
|
||||
<div className="issue-label">이메일 주소</div>
|
||||
<div className="issue-label">봉사료</div>
|
||||
<div className="issue-field">
|
||||
<input
|
||||
type="email"
|
||||
className="error"
|
||||
type="text"
|
||||
placeholder=""
|
||||
value={ serviceCharge }
|
||||
onChange={ (e: ChangeEvent<HTMLInputElement>) => setServiceCharge(e.target.value) }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,20 +2,35 @@ import moment from 'moment';
|
||||
import { InfoWrapKeys, DetailInfoProps } from '../../model/types';
|
||||
|
||||
export const BillingInfoWrap = ({
|
||||
transactionCategory,
|
||||
billingInfo,
|
||||
show,
|
||||
onClickToShowInfo
|
||||
}: DetailInfoProps) => {
|
||||
|
||||
const onClickToSetShowInfo = () => {
|
||||
if(!!onClickToShowInfo){
|
||||
onClickToShowInfo(InfoWrapKeys.Important);
|
||||
const getInstallmentMonth = () => {
|
||||
let rs = [];
|
||||
if((!!billingInfo?.installmentMonth && parseInt(billingInfo?.installmentMonth) > 1)){
|
||||
rs.push(
|
||||
<li
|
||||
key={ `key-installmentMonth`}
|
||||
className="kv-row"
|
||||
>
|
||||
<span className="k">할부개월</span>
|
||||
<span className="v">{ billingInfo?.installmentMonth }개월 할부</span>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
else{
|
||||
rs.push(
|
||||
<li
|
||||
key={ `key-installmentMonth`}
|
||||
className="kv-row"
|
||||
>
|
||||
<span className="k">할부개월</span>
|
||||
<span className="v">일시불</span>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
return rs;
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="txn-section">
|
||||
@@ -49,12 +64,7 @@ export const BillingInfoWrap = ({
|
||||
<span className="k">처리결과</span>
|
||||
<span className="v">{ billingInfo?.processResult }</span>
|
||||
</li>
|
||||
{ (!!billingInfo?.installmentMonth && parseInt(billingInfo?.installmentMonth) > 1) &&
|
||||
<li className="kv-row">
|
||||
<span className="k">할부개월</span>
|
||||
<span className="v">{ billingInfo?.installmentMonth }개월 할부</span>
|
||||
</li>
|
||||
}
|
||||
{ getInstallmentMonth() }
|
||||
<li className="kv-row">
|
||||
<span className="k">상품명</span>
|
||||
<span className="v">{ billingInfo?.productName }</span>
|
||||
|
||||
@@ -5,26 +5,13 @@ import moment from 'moment';
|
||||
export const IssueInfoWrap = ({
|
||||
transactionCategory,
|
||||
issueInfo,
|
||||
show,
|
||||
onClickToShowInfo
|
||||
purpose,
|
||||
}: DetailInfoProps) => {
|
||||
|
||||
|
||||
const onClickToSetShowInfo = () => {
|
||||
if(!!onClickToShowInfo){
|
||||
onClickToShowInfo(InfoWrapKeys.Issue);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="txn-section">
|
||||
<div
|
||||
className="section-title with-toggle"
|
||||
onClick={ () => onClickToSetShowInfo() }
|
||||
>
|
||||
발급 정보 <DetailArrow show={ show }></DetailArrow>
|
||||
</div>
|
||||
<div className="section-title">발급 정보</div>
|
||||
<ul className="kv-list">
|
||||
<li className="kv-row">
|
||||
<span className="k">승인번호</span>
|
||||
@@ -40,7 +27,7 @@ export const IssueInfoWrap = ({
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">용도</span>
|
||||
<span className="v">{ issueInfo?.purpose }</span>
|
||||
<span className="v">{ purpose }</span>
|
||||
</li>
|
||||
<li className="kv-row">
|
||||
<span className="k">결제수단</span>
|
||||
|
||||
Reference in New Issue
Block a user