거래내역상세 거래확인서 기능 추가

This commit is contained in:
focp212@naver.com
2025-11-21 11:46:49 +09:00
parent e22fb91708
commit e07e5c5629
12 changed files with 175 additions and 34 deletions

View File

@@ -1,6 +1,4 @@
VITE_APP_ENV=development VITE_APP_ENV=development
# VITE_APP_AUTH_PROXY_HOST='http://3.35.79.250:8090'
# VITE_APP_API_PROXY_HOST='http://3.35.79.250:8080'
VITE_APP_AUTH_PROXY_HOST='https://auth.nicepay.co.kr' VITE_APP_AUTH_PROXY_HOST='https://auth.nicepay.co.kr'
VITE_APP_API_PROXY_HOST='https://rest.nicepay.co.kr' VITE_APP_API_PROXY_HOST='https://rest.nicepay.co.kr'
GENERATE_SOURCEMAP=false GENERATE_SOURCEMAP=false

View File

@@ -4,7 +4,7 @@
"version": "1.0.3", "version": "1.0.3",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "env-cmd -f .env.local vite --host --open", "dev": "env-cmd -f .env.development vite --host --open",
"build:development": "env-cmd -f .env.development vite build", "build:development": "env-cmd -f .env.development vite build",
"build": "env-cmd -f .env.production vite build", "build": "env-cmd -f .env.production vite build",
"lint": "eslint . --ext js,jsx,ts,tsx --report-unused-disable-directives --max-warnings 0", "lint": "eslint . --ext js,jsx,ts,tsx --report-unused-disable-directives --max-warnings 0",

View File

@@ -84,6 +84,9 @@ export const NoticeDetail = ({
className="notice-detail__body" className="notice-detail__body"
dangerouslySetInnerHTML={{ __html: result.contents || '' }} dangerouslySetInnerHTML={{ __html: result.contents || '' }}
></div> ></div>
{/*
<div className="notice-detail__body">{ result.contents }</div>
*/}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,39 @@
import axios from 'axios';
import { API_URL_TRANSACTION } from '@/shared/api/api-url-transaction';
import { resultify } from '@/shared/lib/resultify';
import { NiceAxiosError } from '@/shared/@types/error';
import {
AllTransactionIssueSendParams,
AllTransactionIssueSendResponse
} from '../model/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
import { getHeaderUserAgent } from '@/shared/constants/url';
export const allTransactionIssueSend = (params: AllTransactionIssueSendParams) => {
let headerOptions = {
menuId: 31,
apiType: 'SEND'
};
let options = {
headers: {
'X-User-Agent': getHeaderUserAgent(headerOptions)
}
};
return resultify(
axios.post<AllTransactionIssueSendResponse>(API_URL_TRANSACTION.transactionIssueSend(), params, options),
);
};
export const useAllTransactionIssueSendMutation = (options?: UseMutationOptions<AllTransactionIssueSendResponse, NiceAxiosError, AllTransactionIssueSendParams>) => {
const mutation = useMutation<AllTransactionIssueSendResponse, NiceAxiosError, AllTransactionIssueSendParams>({
...options,
mutationFn: (params: AllTransactionIssueSendParams) => allTransactionIssueSend(params),
});
return {
...mutation,
};
};

View File

@@ -454,8 +454,10 @@ export interface ImportantInfo {
approvalDate?: string; approvalDate?: string;
approvalTime?: string; approvalTime?: string;
transactionDate?: string; transactionDate?: string;
transactionTime?: string;
requestDate?: string; requestDate?: string;
cancelDate?: string; cancelDate?: string;
cancelTime?: string;
goodsName?: string; goodsName?: string;
orderNumber?: string; orderNumber?: string;
@@ -483,6 +485,7 @@ export interface PaymentInfo {
depositorName?: string; depositorName?: string;
depositDeadline?: string; depositDeadline?: string;
depositDate?: string; depositDate?: string;
depositTime?: string;
refundScheduleDate?: string; refundScheduleDate?: string;
refundBankName?: string; refundBankName?: string;
refundAccountNumber?: string; refundAccountNumber?: string;
@@ -906,4 +909,35 @@ export interface EscrowMailResendParams {
}; };
export interface EscrowMailResendResponse { export interface EscrowMailResendResponse {
};
export interface AllTransactionIssueSendParams {
sendEmail: string;
mid?: string;
tid: string;
buyerName?: string;
approvalDate?: string;
depositDate?: string;
transactionDate?: string;
approvalTime?: string;
depositTime?: string;
transactionTime?: string;
transactionAmount?: number;
goodsName?: string;
buyerTel?: string;
approvalNo?: string;
installmentMonth?: string;
moid?: string;
bankName?: string;
accountNo?: string;
purchaseCompany?: string;
cancelDate?: string;
cancelTime?: string;
serviceCode?: string;
transactionStatus?: string;
};
export interface AllTransactionIssueSendResponse {
code: string;
message: string;
ordNm: string;
}; };

View File

@@ -191,6 +191,9 @@ export const AllTransactionDetail = ({
<AmountInfoSection <AmountInfoSection
transactionCategory={ TransactionCategory.AllTransaction } transactionCategory={ TransactionCategory.AllTransaction }
amountInfo={ amountInfo } amountInfo={ amountInfo }
importantInfo={ importantInfo }
paymentInfo={ paymentInfo }
transactionInfo={ transactionInfo }
isOpen={ showAmountInfo } isOpen={ showAmountInfo }
tid={ tid } tid={ tid }
serviceCode={ serviceCode } serviceCode={ serviceCode }

View File

@@ -234,7 +234,7 @@ export const AllTransactionFilter = ({
<div className="option-list pt-16 pb-86"> <div className="option-list pt-16 pb-86">
<FilterSelectMid <FilterSelectMid
title={t('filter.merchant')} title={t('filter.merchant')}
selectSetter={ setMid } selectSetter={ setFilterMid }
showType={ 'GID' } showType={ 'GID' }
></FilterSelectMid> ></FilterSelectMid>
<FilterSelectInput <FilterSelectInput

View File

@@ -1,7 +1,7 @@
import moment from 'moment'; import moment from 'moment';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { SectionTitleArrow } from '@/entities/common/ui/section-title-arrow'; import { SectionTitleArrow } from '@/entities/common/ui/section-title-arrow';
import { AmountInfo, CashReceiptReceiptDownloadParams, CashReceiptReceiptDownloadResponse, CashReceiptReceiptSendEmailParams, CashReceiptReceiptSendEmailResponse, CustomerInfo, InfoSectionKeys, InfoSectionProps, IssueInfo, MerchantInfo, ProductInfo, TransactionCategory, TransactionInfo } from '../../model/types'; import { AllTransactionIssueSendParams, AllTransactionIssueSendResponse, AmountInfo, CashReceiptReceiptDownloadParams, CashReceiptReceiptDownloadResponse, CashReceiptReceiptSendEmailParams, CashReceiptReceiptSendEmailResponse, CustomerInfo, InfoSectionKeys, InfoSectionProps, IssueInfo, MerchantInfo, ProductInfo, TransactionCategory, TransactionInfo } from '../../model/types';
import { SlideDown } from 'react-slidedown'; import { SlideDown } from 'react-slidedown';
import 'react-slidedown/lib/slidedown.css'; import 'react-slidedown/lib/slidedown.css';
import { snackBar } from '@/shared/lib'; import { snackBar } from '@/shared/lib';
@@ -10,11 +10,15 @@ import { useState } from 'react';
import { DownloadBottomSheet, DownloadSelectedMode } from '@/entities/common/ui/download-bottom-sheet'; import { DownloadBottomSheet, DownloadSelectedMode } from '@/entities/common/ui/download-bottom-sheet';
import { CashReceiptSample } from '@/entities/common/ui/cash-receipt-sample'; import { CashReceiptSample } from '@/entities/common/ui/cash-receipt-sample';
import { useCashReceiptReceiptSendEmailMutation } from '../../api/use-cash-receipt-receipt-send-email-mutation'; import { useCashReceiptReceiptSendEmailMutation } from '../../api/use-cash-receipt-receipt-send-email-mutation';
import { useDownloadBottomSheetOnStore } from '@/shared/model/store'; import { useDownloadBottomSheetOn2Store } from '@/shared/model/store';
import { useAllTransactionIssueSendMutation } from '../../api/use-all-transaction-issue-send-mutation';
export const AmountInfoSection = ({ export const AmountInfoSection = ({
transactionCategory, transactionCategory,
amountInfo, amountInfo,
importantInfo,
paymentInfo,
transactionInfo,
isOpen, isOpen,
tid, tid,
serviceCode, serviceCode,
@@ -23,10 +27,11 @@ export const AmountInfoSection = ({
}: InfoSectionProps) => { }: InfoSectionProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { mutateAsync: allTransactionIssueSend } = useAllTransactionIssueSendMutation();
const { mutateAsync: cashReceiptReceiptDownload } = useCashReceiptReceiptDownloadMutation(); const { mutateAsync: cashReceiptReceiptDownload } = useCashReceiptReceiptDownloadMutation();
const { mutateAsync: cashReceiptReceiptSendEamil } = useCashReceiptReceiptSendEmailMutation(); const { mutateAsync: cashReceiptReceiptSendEamil } = useCashReceiptReceiptSendEmailMutation();
const { downloadBottomSheetOn, setDownloadBottomSheetOn } = useDownloadBottomSheetOnStore(); const { downloadBottomSheetOn2, setDownloadBottomSheetOn2 } = useDownloadBottomSheetOn2Store();
const [cashReceiptSampleOn, setCashReceiptSampleOn] = useState<boolean>(false); const [cashReceiptSampleOn, setCashReceiptSampleOn] = useState<boolean>(false);
const [receiptIssueInfo, setReceiptIssueInfo] = useState<IssueInfo>({}); const [receiptIssueInfo, setReceiptIssueInfo] = useState<IssueInfo>({});
@@ -35,7 +40,7 @@ export const AmountInfoSection = ({
const [receiptAmountInfo, setReceiptAmountInfo] = useState<AmountInfo>({}); const [receiptAmountInfo, setReceiptAmountInfo] = useState<AmountInfo>({});
const [receiptCustomerInfo, setReceiptCustomerInfo] = useState<CustomerInfo>(); const [receiptCustomerInfo, setReceiptCustomerInfo] = useState<CustomerInfo>();
const [receiptProductInfo, setReceiptProductInfo] = useState<ProductInfo>(); const [receiptProductInfo, setReceiptProductInfo] = useState<ProductInfo>();
let newAmountInfo: Record<string, any> | undefined = amountInfo; let newAmountInfo: Record<string, any> | undefined = amountInfo;
const subItems: Record<string, Record<string, string>> = { const subItems: Record<string, Record<string, string>> = {
transactionRequestAmount: {name: t('transaction.fields.transactionRequestAmount'), type: 'number'}, transactionRequestAmount: {name: t('transaction.fields.transactionRequestAmount'), type: 'number'},
@@ -199,7 +204,7 @@ export const AmountInfoSection = ({
}; };
const onClickToOpenDownloadBottomSheet = () => { const onClickToOpenDownloadBottomSheet = () => {
setDownloadBottomSheetOn(true); setDownloadBottomSheetOn2(true);
}; };
const onRequestDownload = ( const onRequestDownload = (
@@ -210,21 +215,63 @@ export const AmountInfoSection = ({
if(selectedMode === DownloadSelectedMode.EMAIL if(selectedMode === DownloadSelectedMode.EMAIL
&& !!userEmail && !!userEmail
){ ){
let params: CashReceiptReceiptSendEmailParams = { if(transactionCategory === TransactionCategory.AllTransaction){
tid: tid, let params: AllTransactionIssueSendParams = {
email: userEmail sendEmail: userEmail,
}; mid: amountInfo?.mid,
cashReceiptReceiptSendEamil(params).then((rs: CashReceiptReceiptSendEmailResponse) => { tid: tid,
console.log(rs); buyerName: transactionInfo?.buyerName,
if(rs.message){ approvalDate: importantInfo?.approvalDate,
snackBar(rs.message); depositDate: paymentInfo?.depositDate,
} transactionDate: importantInfo?.transactionDate,
}).catch((e: any) => { approvalTime: importantInfo?.approvalTime,
if(e.response?.data?.error?.message){ depositTime: paymentInfo?.depositTime,
snackBar(e.response?.data?.error?.message); transactionTime: importantInfo?.transactionTime,
return; transactionAmount: amountInfo?.transactionAmount,
} goodsName: importantInfo?.goodsName,
}); buyerTel: transactionInfo?.buyerTel,
approvalNo: paymentInfo?.approvalNo,
installmentMonth: paymentInfo?.approvalNo,
moid: importantInfo?.moid,
bankName: paymentInfo?.bankName || paymentInfo?.refundBankName,
accountNo: paymentInfo?.accountNo || paymentInfo?.refundAccountNo,
purchaseCompany: paymentInfo?.purchaseCompany,
cancelDate: importantInfo?.cancelDate,
cancelTime: importantInfo?.cancelTime,
serviceCode: serviceCode,
transactionStatus: importantInfo?.transactionStatus
};
allTransactionIssueSend(params).then((rs: AllTransactionIssueSendResponse) => {
if(rs.message){
snackBar(rs.message);
}
else{
snackBar('메일이 전송 되었습니다.');
}
}).catch((e: any) => {
if(e.response?.data?.error?.message){
snackBar(e.response?.data?.error?.message);
return;
}
});
}
else if(transactionCategory === TransactionCategory.CashReceipt){
let params: CashReceiptReceiptSendEmailParams = {
tid: tid,
email: userEmail
};
cashReceiptReceiptSendEamil(params).then((rs: CashReceiptReceiptSendEmailResponse) => {
console.log(rs);
if(rs.message){
snackBar(rs.message);
}
}).catch((e: any) => {
if(e.response?.data?.error?.message){
snackBar(e.response?.data?.error?.message);
return;
}
});
}
} }
else if(selectedMode === DownloadSelectedMode.IMAGE){ else if(selectedMode === DownloadSelectedMode.IMAGE){
let params: CashReceiptReceiptDownloadParams = { let params: CashReceiptReceiptDownloadParams = {
@@ -460,8 +507,9 @@ export const AmountInfoSection = ({
</div> </div>
} }
<div className="txn-doc"> <div className="txn-doc">
{ (transactionCategory === TransactionCategory.CashReceipt) && { ((transactionCategory === TransactionCategory.AllTransaction) ||
!!canDownloadReceipt && ((transactionCategory === TransactionCategory.CashReceipt) &&
!!canDownloadReceipt)) &&
<button <button
className="doc-btn" className="doc-btn"
type="button" type="button"
@@ -470,11 +518,11 @@ export const AmountInfoSection = ({
} }
</div> </div>
</div> </div>
{ !!downloadBottomSheetOn && { !!downloadBottomSheetOn2 &&
<DownloadBottomSheet <DownloadBottomSheet
bottomSheetOn={ downloadBottomSheetOn } bottomSheetOn={ downloadBottomSheetOn2 }
setBottomSheetOn={ setDownloadBottomSheetOn } setBottomSheetOn={ setDownloadBottomSheetOn2 }
imageMode={ true } imageMode={ (transactionCategory === TransactionCategory.CashReceipt) }
emailMode={ true } emailMode={ true }
sendRequest={ onRequestDownload } sendRequest={ onRequestDownload }
></DownloadBottomSheet> ></DownloadBottomSheet>

View File

@@ -31,6 +31,10 @@ export const API_URL_TRANSACTION = {
// POST: 거래취소 정보 조회 // POST: 거래취소 정보 조회
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/transaction/cancel-info`; return `${API_BASE_URL}/api/v1/${API_URL_KEY}/transaction/cancel-info`;
}, },
transactionIssueSend: () => {
// POST: 거래확인서 메일 발송
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/transaction/issue/send`;
},
/* Cash Receipt Management - 현금영수증 API */ /* Cash Receipt Management - 현금영수증 API */
cashReceiptList: () => { cashReceiptList: () => {

View File

@@ -10,6 +10,10 @@ export interface DownloadBottomSheetOnStore {
downloadBottomSheetOn: boolean; downloadBottomSheetOn: boolean;
setDownloadBottomSheetOn: (downloadBottomSheetOn: boolean) => void; setDownloadBottomSheetOn: (downloadBottomSheetOn: boolean) => void;
}; };
export interface DownloadBottomSheetOn2Store {
downloadBottomSheetOn2: boolean;
setDownloadBottomSheetOn2: (downloadBottomSheetOn2: boolean) => void;
};
export interface FilterOnStore { export interface FilterOnStore {
filterOn: boolean; filterOn: boolean;
setFilterOn: (filterOn: boolean) => void; setFilterOn: (filterOn: boolean) => void;
@@ -50,6 +54,14 @@ export const useDownloadBottomSheetOnStore = create<DownloadBottomSheetOnStore>(
})); }));
} }
})); }));
export const useDownloadBottomSheetOn2Store = create<DownloadBottomSheetOn2Store>((set) => ({
downloadBottomSheetOn2: false,
setDownloadBottomSheetOn2: (downloadBottomSheetOn2: boolean) => {
set((state: {downloadBottomSheetOn2: boolean}) => ({
downloadBottomSheetOn2: (state.downloadBottomSheetOn2 = downloadBottomSheetOn2)
}));
}
}));
export const useFilterlOnStore = create<FilterOnStore>((set) => ({ export const useFilterlOnStore = create<FilterOnStore>((set) => ({
filterOn: false, filterOn: false,

View File

@@ -54,11 +54,11 @@ export const MaskedNameInput = ({
onChange(valueWithoutSpace); onChange(valueWithoutSpace);
}} }}
onChange={(e: ChangeEvent<HTMLInputElement>) => { onChange={(e: ChangeEvent<HTMLInputElement>) => {
if(isComposing){
// composition 중에는 스페이스 제거 // composition 중에는 스페이스 제거
const valueWithoutSpace = e.target.value.replace(/\s/g, ''); const valueWithoutSpace = e.target.value.replace(/\s/g, '');
onChange(valueWithoutSpace); onChange(valueWithoutSpace);
}
}} }}
onFocus={onFocus} onFocus={onFocus}
/> />

View File

@@ -260,8 +260,8 @@ export const SubLayout = () => {
let userParmas; let userParmas;
if(!isNativeEnvironment){ if(!isNativeEnvironment){
userParmas = { userParmas = {
//id: 'nictest00', id: 'nictest00',
id: 'reptest22m', //id: 'reptest22m',
password: 'nictest00' password: 'nictest00'
}; };
// userParmas = { // userParmas = {