12284290cc
- orders: remove name fields from creation, keep dispatchMode logic - chat: remove readonly/senderName/senderAvatar references - reviews: remove fromUserAvatar/toUserId, simplify participant check - disputes: remove initiatorId/initiatorName from creation - posts: remove authorRole/quotedPostId, keep linkedOrderId as number - comments: remove postId from creation - wallet: use string amounts
147 lines
4.1 KiB
TypeScript
147 lines
4.1 KiB
TypeScript
import { calculateOrderIncome } from "@/lib/domain/income"
|
||
import { generateId } from "@/lib/id"
|
||
import type { WalletTransaction } from "@/lib/types"
|
||
import { useShopStore } from "@/store/shops"
|
||
import { create } from "zustand"
|
||
|
||
interface WalletState {
|
||
balance: number
|
||
transactions: WalletTransaction[]
|
||
topUp: (amount: number) => void
|
||
withdraw: (amount: number) => void
|
||
deductBalance: (orderId: string, amount: number) => boolean
|
||
refundPayment: (orderId: string, amount: number) => boolean
|
||
addIncome: (orderId: string, totalPrice: number, shopId?: string) => void
|
||
addTransaction: (transaction: WalletTransaction) => void
|
||
}
|
||
|
||
export const useWalletStore = create<WalletState>((set, get) => ({
|
||
balance: 0,
|
||
transactions: [],
|
||
topUp: (amount) => {
|
||
if (!Number.isFinite(amount) || amount <= 0) return
|
||
const now = new Date().toISOString()
|
||
set((state) => ({
|
||
balance: state.balance + amount,
|
||
transactions: [
|
||
{
|
||
id: generateId("tx"),
|
||
type: "topup",
|
||
amount: String(amount),
|
||
description: "充值",
|
||
createdAt: now,
|
||
},
|
||
...state.transactions,
|
||
],
|
||
}))
|
||
},
|
||
withdraw: (amount) => {
|
||
if (!Number.isFinite(amount) || amount <= 0) return
|
||
const now = new Date().toISOString()
|
||
set((state) => ({
|
||
transactions: [
|
||
{
|
||
id: generateId("tx"),
|
||
type: "withdrawal",
|
||
amount: String(-amount),
|
||
description: "提现到银行卡",
|
||
createdAt: now,
|
||
},
|
||
...state.transactions,
|
||
],
|
||
}))
|
||
},
|
||
deductBalance: (orderId, amount) => {
|
||
if (!Number.isFinite(amount) || amount <= 0) return false
|
||
|
||
const state = get()
|
||
const paid = state.transactions.some(
|
||
(transaction) => transaction.type === "payment" && transaction.description.includes(orderId),
|
||
)
|
||
if (paid || state.balance < amount) {
|
||
return false
|
||
}
|
||
|
||
const now = new Date().toISOString()
|
||
set((prev) => ({
|
||
balance: prev.balance - amount,
|
||
transactions: [
|
||
{
|
||
id: generateId("tx"),
|
||
type: "payment",
|
||
amount: String(-amount),
|
||
description: `支付订单 ${orderId}`,
|
||
createdAt: now,
|
||
},
|
||
...prev.transactions,
|
||
],
|
||
}))
|
||
return true
|
||
},
|
||
refundPayment: (orderId, amount) => {
|
||
if (!Number.isFinite(amount) || amount <= 0) return false
|
||
|
||
const state = get()
|
||
const paid = state.transactions.some(
|
||
(transaction) => transaction.type === "payment" && transaction.description.includes(orderId),
|
||
)
|
||
const refunded = state.transactions.some(
|
||
(transaction) => transaction.type === "refund" && transaction.description.includes(orderId),
|
||
)
|
||
|
||
if (!paid || refunded) {
|
||
return false
|
||
}
|
||
|
||
const now = new Date().toISOString()
|
||
set((prev) => ({
|
||
balance: prev.balance + amount,
|
||
transactions: [
|
||
{
|
||
id: generateId("tx"),
|
||
type: "refund",
|
||
amount: String(amount),
|
||
description: `订单 ${orderId} 退款`,
|
||
createdAt: now,
|
||
},
|
||
...prev.transactions,
|
||
],
|
||
}))
|
||
|
||
return true
|
||
},
|
||
addIncome: (orderId, totalPrice, shopId) => {
|
||
if (!Number.isFinite(totalPrice) || totalPrice <= 0) return
|
||
|
||
const state = get()
|
||
const exists = state.transactions.some(
|
||
(transaction) => transaction.type === "income" && transaction.description.includes(orderId),
|
||
)
|
||
if (exists) return
|
||
|
||
const shop = shopId
|
||
? useShopStore.getState().shops.find((item) => item.id === shopId)
|
||
: undefined
|
||
const { income, commissionLabel } = calculateOrderIncome(totalPrice, shop)
|
||
|
||
const now = new Date().toISOString()
|
||
set((prev) => ({
|
||
transactions: [
|
||
{
|
||
id: generateId("tx"),
|
||
type: "income",
|
||
amount: String(income),
|
||
description: `订单 ${orderId} 收入(${commissionLabel})`,
|
||
createdAt: now,
|
||
},
|
||
...prev.transactions,
|
||
],
|
||
}))
|
||
},
|
||
addTransaction: (transaction) => {
|
||
set((state) => ({
|
||
transactions: [transaction, ...state.transactions],
|
||
}))
|
||
},
|
||
}))
|