diff --git a/src/app/calculator/partyProfit/_components/AllocationStatusBanner.tsx b/src/app/calculator/partyProfit/_components/AllocationStatusBanner.tsx
index b8bb458..9beaab3 100644
--- a/src/app/calculator/partyProfit/_components/AllocationStatusBanner.tsx
+++ b/src/app/calculator/partyProfit/_components/AllocationStatusBanner.tsx
@@ -1,11 +1,9 @@
-import { formatKoreanNumber } from '@/utils/numberUtils'
import { BiErrorCircle } from 'react-icons/bi'
interface Props {
isVisible: boolean
overRatio: number
remainingRatio: number
- remainder: number
}
const BannerLayout = ({ children }: { children: React.ReactNode }) => {
@@ -21,7 +19,6 @@ const AllocationStatusBanner = ({
isVisible,
overRatio,
remainingRatio,
- remainder,
}: Props) => {
if (!isVisible) {
return
@@ -41,7 +38,6 @@ const AllocationStatusBanner = ({
남은 비율 : {remainingRatio}
- 남은 메소 : {formatKoreanNumber(remainder)}
)
diff --git a/src/app/calculator/partyProfit/_components/PartyMemberCard.tsx b/src/app/calculator/partyProfit/_components/PartyMemberCard.tsx
index 816c985..15c460d 100644
--- a/src/app/calculator/partyProfit/_components/PartyMemberCard.tsx
+++ b/src/app/calculator/partyProfit/_components/PartyMemberCard.tsx
@@ -41,10 +41,17 @@ const PartyMemberCard = ({
%
+
+ 송금할 금액:{' '}
+
+ {formatKoreanNumber(member.transferAmount)}
+ {' '}
+ 메소
+
최종 분배금:{' '}
- {formatKoreanNumber(member.amount)}
+ {formatKoreanNumber(member.finalReceivedAmount)}
{' '}
메소
diff --git a/src/app/calculator/partyProfit/_components/PartyMemberControl.tsx b/src/app/calculator/partyProfit/_components/PartyMemberControl.tsx
index 4c7ecd1..076b2b8 100644
--- a/src/app/calculator/partyProfit/_components/PartyMemberControl.tsx
+++ b/src/app/calculator/partyProfit/_components/PartyMemberControl.tsx
@@ -12,7 +12,6 @@ const PartyMemberControl = ({ netAmount, feeRate }: Props) => {
const {
mode,
members,
- remainder,
overRatio,
remainingRatio,
canAddMember,
@@ -51,7 +50,6 @@ const PartyMemberControl = ({ netAmount, feeRate }: Props) => {
isVisible={isAllocationBannerVisible}
overRatio={overRatio}
remainingRatio={remainingRatio}
- remainder={remainder}
/>
{
return {
mode: state.mode,
- members: distribution.results,
- remainder: distribution.remainder,
+ members: distribution,
canAddMember: canAddMember,
remainingRatio: remainingRatio,
diff --git a/src/app/calculator/partyProfit/_utils/distributeProfitByPercent.ts b/src/app/calculator/partyProfit/_utils/distributeProfitByPercent.ts
index bc5e917..6ea0dac 100644
--- a/src/app/calculator/partyProfit/_utils/distributeProfitByPercent.ts
+++ b/src/app/calculator/partyProfit/_utils/distributeProfitByPercent.ts
@@ -2,33 +2,89 @@ export type DistributionResult = {
id: string
name: string
ratio: number
- amount: number
+ transferAmount: number // 입력 금액 (송금액)
+ finalReceivedAmount: number // 실수령액
}
type Member = { id: string; name: string; ratio: number }
type Mode = 'MANUAL' | 'EQUAL'
+const normalizeMembers = (members: Member[], mode: Mode): Member[] => {
+ if (mode === 'EQUAL') {
+ const equalRatio = 100 / members.length
+ return members.map((m) => ({ ...m, ratio: equalRatio }))
+ }
+ return members
+}
+
+const calculateFairBaseProfit = (
+ totalProfit: number,
+ ownerRatio: number,
+ feeRate: number,
+): number => {
+ const r = feeRate / 100
+ const wOwner = ownerRatio / 100
+
+ const denominator = wOwner + (1 - wOwner) / (1 - r)
+
+ if (denominator <= 0) return 0
+ return totalProfit / denominator
+}
+
+const computeMemberShare = (
+ member: Member,
+ fairBaseProfit: number,
+ feeRate: number,
+ isOwner: boolean,
+): DistributionResult => {
+ const r = feeRate / 100
+ const w = member.ratio / 100
+
+ const targetFinal = Math.floor(fairBaseProfit * w)
+
+ if (isOwner) {
+ return {
+ ...member,
+ transferAmount: 0,
+ finalReceivedAmount: targetFinal,
+ }
+ }
+
+ const transfer = Math.floor(targetFinal / (1 - r))
+ const finalReceived = Math.floor(transfer * (1 - r))
+
+ return {
+ ...member,
+ transferAmount: transfer,
+ finalReceivedAmount: finalReceived,
+ }
+}
+
export const distributeProfitByPercent = (
totalProfit: number,
feeRate: number,
members: Member[],
mode: Mode,
-) => {
- const memberCount = members.length
+): DistributionResult[] => {
+ const normalizedMembers = normalizeMembers(members, mode)
- const fee = memberCount >= 2 ? Math.floor((totalProfit * feeRate) / 100) : 0
- const distributable = totalProfit - fee
+ const activeOwnerIndex = 0
+ const ownerMember = normalizedMembers[activeOwnerIndex]
- const results: DistributionResult[] = members.map((m) => ({
- ...m,
- amount:
- mode === 'MANUAL'
- ? Math.floor((distributable * m.ratio) / 100)
- : Math.floor(distributable / memberCount),
- }))
+ const fairBaseProfit = calculateFairBaseProfit(
+ totalProfit,
+ ownerMember.ratio,
+ feeRate,
+ )
- const distributed = results.reduce((sum, r) => sum + r.amount, 0)
- const remainder = distributable - distributed
+ const results = normalizedMembers.map((member, idx) =>
+ computeMemberShare(
+ member,
+ fairBaseProfit,
+ feeRate,
+ idx === activeOwnerIndex, // isOwner check
+ ),
+ )
- return { results, remainder }
+ return results
}