Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

슈퍼 어드민에서 정산 내역서 전송 페이지 수정 사항 반영 #262

Merged
merged 1 commit into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,15 @@ const SettlementStatementPreviewContainer = styled.div`
height: 600px;
`;

const PreviewMessage = styled.div`
background-color: #FACBCF;
border-radius: 8px;
padding: 16px 20px;
${({ theme }) => theme.typo.b3};
color: ${({ theme }) => theme.palette.grey.g90};
margin-bottom: 32px;
`;

const TextFieldRow = styled.div`
display: flex;
gap: 8px;
Expand Down Expand Up @@ -267,6 +276,7 @@ export default {
SettlementStatementForm,
SettlementStatementFooter,
SettlementStatementPreviewContainer,
PreviewMessage,
TextFieldRow,
TextField,
Select,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,9 @@ const SettlementStatementFormDialog = ({
)}
{step === 2 && (
<Styled.SettlementStatementPreviewContainer>
<Styled.PreviewMessage>
발송 전 내역서를 다시 한 번 확인해 주세요!
</Styled.PreviewMessage>
<SettlementStatementPreview
data={{
showName: watch('showName'),
Expand Down
1 change: 1 addition & 0 deletions apps/super-admin/src/constants/settlement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const BOOLTI_FEE_RATE = 0.01
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const ProgressItem = styled.li<ProgressItemProps>`
bottom: -36px;
left: 12px;
background-color: ${({ theme, active }) =>
active ? theme.palette.primary.o1 : theme.palette.grey.g20};
active ? theme.palette.primary.o1 : theme.palette.grey.g20};
width: 1px;
height: 30px;
}
Expand Down Expand Up @@ -105,6 +105,20 @@ const ProgressItemDescription = styled.span`
color: ${({ theme }) => theme.palette.grey.g70};
`;

const ProgressItemButton = styled.button`
font-size: 15px;
font-weight: 700;
line-height: 23px;
text-decoration: underline;
color: ${({ theme }) => theme.palette.grey.g70};
cursor: pointer;

&:hover, &:active {
text-decoration: underline;
color: ${({ theme }) => theme.palette.grey.g70};
}
`;

const UserInfo = styled.div`
display: flex;
flex-direction: column;
Expand Down Expand Up @@ -217,6 +231,7 @@ export default {
ProgressItemNumber,
ProgressItemTitle,
ProgressItemDescription,
ProgressItemButton,
UserInfo,
UserInfoItem,
UserInfoTitle,
Expand Down
231 changes: 127 additions & 104 deletions apps/super-admin/src/pages/SettlementPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
useAdminSettlementInfo,
useAdminShowDetail,
useAdminTicketSalesInfo,
useSuperAdminShowSettlementStatement,
} from '@boolti/api';
import { PlusIcon } from '@boolti/icon';
import { Button, useConfirm, useDialog, useToast } from '@boolti/ui';
Expand All @@ -15,6 +16,7 @@ import SettlementStatementFormDialog from '~/components/SettlementStatement/Sett

import Styled from './SettlementPage.styles';
import PageLayout from '~/components/PageLayout/PageLayout';
import { BOOLTI_FEE_RATE } from '~/constants/settlement';

const SettlementPage = () => {
const params = useParams<{ showId: string }>();
Expand All @@ -28,10 +30,82 @@ const SettlementPage = () => {
useAdminSettlementEvent(Number(params!.showId));
const { data: adminSettlementInfo } = useAdminSettlementInfo(Number(params!.showId));
const { data: adminTicketSalesInfo } = useAdminTicketSalesInfo(Number(params!.showId));
const { data: superAdminShowSettlementStatementBlob } = useSuperAdminShowSettlementStatement(Number(params!.showId))

const createSettlementStatementMutation = useAdminCreateSettlementStatement();
const settlementDoneMutation = useAdminSettlementDone();

const dialogContent = (
<SettlementStatementFormDialog
ticketSalesInfo={adminTicketSalesInfo ?? []}
initialValues={{
showName: adminShowDetail?.name ?? '',
hostName: adminShowDetail?.host.name ?? '',
accountHolder: adminSettlementInfo?.bankAccount?.bankAccountHolder ?? '',
bankCode: adminSettlementInfo?.bankAccount?.bankCode ?? '',
accountNumber: adminSettlementInfo?.bankAccount?.bankAccountNumber ?? '',
}}
onSubmit={async (data) => {
try {
if (createSettlementStatementMutation.isLoading) return;

const body = {
showName: data.showName,
hostName: data.hostName,
settlementBankInfo: {
bankCode: data.bankCode,
bankAccountNumber: data.accountNumber,
bankAccountHolder: data.accountHolder,
},
businessLicenseNumber: data.businessNumber,
salesAmount: parseInt(data.salesAmount.replace(/,/g, '')),
salesItems: data.salesItems.reduce<
{
salesTicketTypeId: number;
amount: number;
}[]
>((acc, item) => {
acc.push({
salesTicketTypeId: parseInt(item.salesTicketId.replace(/,/g, '')),
amount: parseInt(item.amount.replace(/,/g, '')),
});

return acc;
}, []),
fee: parseInt(data.fee.replace(/,/g, '')),
feeItems: [
{
feeType: 'BROKERAGE_FEE' as 'BROKERAGE_FEE' | 'PAYMENT_AGENCY_FEE',
amount: parseInt(data.brokerageFee.replace(/,/g, '')),
},
{
feeType: 'PAYMENT_AGENCY_FEE' as
| 'BROKERAGE_FEE'
| 'PAYMENT_AGENCY_FEE',
amount: parseInt(data.paymentAgencyFee.replace(/,/g, '')),
},
],
vat: parseInt(data.vat.replace(/,/g, '')),
roundAmount: parseInt(data.adjustmentAmount.replace(/,/g, '')),
roundReason: data.adjustmentReason,
};

await createSettlementStatementMutation.mutateAsync({
showId: Number(params.showId),
body,
});
await refetchAdminSettlementEvent();

toast.success('정산 내역서를 발송했어요.');
dialog.close();
} catch (error) {
console.error(error);
toast.error('정산 내역서를 생성하지 못했어요. 개발자에게 문의해주세요.');
}
}}
/>
)

return (
<PageLayout
breadscrumb="정산 관리 / 정산 내역서"
Expand All @@ -58,6 +132,22 @@ const SettlementPage = () => {
{format(adminSettlementEvent.SEND, 'yyyy-MM-dd HH:mm')}
</Styled.ProgressItemDescription>
)}
{adminSettlementEvent?.SEND && superAdminShowSettlementStatementBlob && (
<Styled.ProgressItemButton onClick={() => {
if (!adminShowDetail) return;

const downloadUrl = URL.createObjectURL(superAdminShowSettlementStatementBlob);

const anchorElement = document.createElement('a');
anchorElement.href = downloadUrl;
anchorElement.download = `불티 정산 내역서 - ${adminShowDetail.name}.pdf`;
anchorElement.click();

URL.revokeObjectURL(downloadUrl);
}}>
전송한 내역서 보기
</Styled.ProgressItemButton>
)}
</Styled.ProgressItem>
<Styled.ProgressItem active={!!adminSettlementEvent?.REQUEST}>
<Styled.ProgressItemNumber active={!!adminSettlementEvent?.REQUEST}>
Expand All @@ -78,11 +168,11 @@ const SettlementPage = () => {
</Styled.ProgressItemNumber>
<Styled.ProgressItemTitle active={!!adminSettlementEvent?.DONE}>
{adminSettlementEvent?.SEND &&
adminSettlementEvent?.REQUEST &&
!adminSettlementEvent?.DONE ? (
adminSettlementEvent?.REQUEST &&
!adminSettlementEvent?.DONE ? (
<Button
colorTheme="netural"
size="small"
size="x-small"
onClick={async () => {
const confirm = await settlementCompleteConfirm(
<Styled.ConfirmContent>
Expand Down Expand Up @@ -146,36 +236,6 @@ const SettlementPage = () => {
)}
</Styled.UserInfoContent>
</Styled.UserInfoItem>
<Styled.UserInfoItem>
<Styled.UserInfoTitle>정산 계좌</Styled.UserInfoTitle>
<Styled.UserInfoContent>
{adminSettlementInfo?.bankAccount ? (
<>
<Styled.UserInfoText>
{adminSettlementInfo.bankAccount.bankName}{' '}
{adminSettlementInfo.bankAccount.bankAccountNumber}{' '}
{adminSettlementInfo.bankAccount.bankAccountHolder}
</Styled.UserInfoText>
<Button
colorTheme="netural"
size="x-small"
onClick={async () => {
if (!adminSettlementInfo.bankAccount) return;

await navigator.clipboard.writeText(
`${adminSettlementInfo.bankAccount.bankName} ${adminSettlementInfo.bankAccount.bankAccountNumber} ${adminSettlementInfo.bankAccount.bankAccountHolder}`,
);
toast.success('계좌 정보가 복사되었습니다.');
}}
>
복사하기
</Button>
</>
) : (
<Styled.UserInfoText>-</Styled.UserInfoText>
)}
</Styled.UserInfoContent>
</Styled.UserInfoItem>
<Styled.UserInfoItem>
<Styled.UserInfoTitle>통장 사본</Styled.UserInfoTitle>
<Styled.UserInfoContent>
Expand Down Expand Up @@ -248,6 +308,18 @@ const SettlementPage = () => {
</Styled.TableItem>
<Styled.TableItem></Styled.TableItem>
</Styled.TableRow>
<Styled.TableRow>
<Styled.TableItem>불티 수수료</Styled.TableItem>
<Styled.TableItem></Styled.TableItem>
<Styled.TableItem></Styled.TableItem>
<Styled.TableItem></Styled.TableItem>
<Styled.TableItem align="right">
{((adminTicketSalesInfo ?? []).reduce<number>((acc, cur) => acc + cur.amount, 0) * BOOLTI_FEE_RATE)
.toLocaleString()}
</Styled.TableItem>
<Styled.TableItem></Styled.TableItem>
</Styled.TableRow>
</Styled.TableBody>
</Styled.Table>
</Styled.Section>
Expand All @@ -257,81 +329,12 @@ const SettlementPage = () => {
<Styled.Section>
<Button
type="button"
size="medium"
size="bold"
colorTheme="netural"
onClick={() => {
dialog.open({
title: '정산 내역서 생성하기',
content: (
<SettlementStatementFormDialog
ticketSalesInfo={adminTicketSalesInfo ?? []}
initialValues={{
showName: adminShowDetail?.name ?? '',
hostName: adminShowDetail?.host.name ?? '',
accountHolder: adminSettlementInfo?.bankAccount?.bankAccountHolder ?? '',
bankCode: adminSettlementInfo?.bankAccount?.bankCode ?? '',
accountNumber: adminSettlementInfo?.bankAccount?.bankAccountNumber ?? '',
}}
onSubmit={async (data) => {
try {
if (createSettlementStatementMutation.isLoading) return;

const body = {
showName: data.showName,
hostName: data.hostName,
settlementBankInfo: {
bankCode: data.bankCode,
bankAccountNumber: data.accountNumber,
bankAccountHolder: data.accountHolder,
},
businessLicenseNumber: data.businessNumber,
salesAmount: parseInt(data.salesAmount.replace(/,/g, '')),
salesItems: data.salesItems.reduce<
{
salesTicketTypeId: number;
amount: number;
}[]
>((acc, item) => {
acc.push({
salesTicketTypeId: parseInt(item.salesTicketId.replace(/,/g, '')),
amount: parseInt(item.amount.replace(/,/g, '')),
});

return acc;
}, []),
fee: parseInt(data.fee.replace(/,/g, '')),
feeItems: [
{
feeType: 'BROKERAGE_FEE' as 'BROKERAGE_FEE' | 'PAYMENT_AGENCY_FEE',
amount: parseInt(data.brokerageFee.replace(/,/g, '')),
},
{
feeType: 'PAYMENT_AGENCY_FEE' as
| 'BROKERAGE_FEE'
| 'PAYMENT_AGENCY_FEE',
amount: parseInt(data.paymentAgencyFee.replace(/,/g, '')),
},
],
vat: parseInt(data.vat.replace(/,/g, '')),
roundAmount: parseInt(data.adjustmentAmount.replace(/,/g, '')),
roundReason: data.adjustmentReason,
};

await createSettlementStatementMutation.mutateAsync({
showId: Number(params.showId),
body,
});
await refetchAdminSettlementEvent();

toast.success('정산 내역서를 발송했어요.');
dialog.close();
} catch (error) {
console.error(error);
toast.error('정산 내역서를 생성하지 못했어요. 개발자에게 문의해주세요.');
}
}}
/>
),
content: dialogContent,
isAuto: true,
});
}}
Expand All @@ -341,6 +344,26 @@ const SettlementPage = () => {
</Button>
</Styled.Section>
)}
{adminSettlementEvent?.SEND &&
!adminSettlementEvent?.REQUEST &&
!adminSettlementEvent?.DONE && (
<Styled.Section>
<Button
type="button"
size="bold"
colorTheme="line"
onClick={() => {
dialog.open({
title: '정산 내역서 생성하기',
content: dialogContent,
isAuto: true,
});
}}>
<PlusIcon />
내역서 재생성하기
</Button>
</Styled.Section>
)}
</PageLayout>
);
};
Expand Down
2 changes: 2 additions & 0 deletions packages/api/src/queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import useCastTeamList from './useCastTeamList';
import useAdminTicketList from './useAdminTicketList';
import useAdminSalesTicketList from './useAdminSalesTicketList';
import useAdminReservationSummaryV2 from './useAdminReservationSummaryV2';
import useSuperAdminShowSettlementStatement from './useSuperAdminShowSettlementStatement';

export {
useCastTeamList,
Expand Down Expand Up @@ -84,4 +85,5 @@ export {
useSuperAdminSalesTicketList,
useSuperAdminInvitationTicketList,
useSuperAdminInvitationCodeList,
useSuperAdminShowSettlementStatement,
};
Loading
Loading