build
This commit is contained in:
parent
b40c4d8316
commit
fca287127e
|
|
@ -1,2 +1,15 @@
|
|||
const checkers = [];
|
||||
const checkers = [
|
||||
{
|
||||
entity: 'account',
|
||||
type: 'row',
|
||||
filter: {
|
||||
system: {
|
||||
account$entity: {
|
||||
"#sqp": 'not in',
|
||||
},
|
||||
},
|
||||
},
|
||||
action: 'create',
|
||||
}
|
||||
];
|
||||
export default checkers;
|
||||
|
|
|
|||
|
|
@ -81,6 +81,12 @@ const checkers = [
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'tax': {
|
||||
if (totalPlus >= 0 || availPlus >= 0 || totalPlus !== availPlus) {
|
||||
throw new OakInputIllegalException('accountOper', ['totalPlus', 'availPlus'], 'accountOper为tax时,其totalPlus/availPlus必须为负且相等');
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { OakInputIllegalException } from 'oak-domain/lib/types';
|
||||
import { OakAttrNotNullException, OakInputIllegalException } from 'oak-domain/lib/types';
|
||||
import { pipeline } from 'oak-domain/lib/utils/executor';
|
||||
import assert from 'assert';
|
||||
const checkers = [
|
||||
|
|
@ -98,6 +98,18 @@ const checkers = [
|
|||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
entity: 'pay',
|
||||
action: 'succeedPaying',
|
||||
type: 'data',
|
||||
checker(data) {
|
||||
assert(!(data instanceof Array));
|
||||
const { successAt } = data;
|
||||
if (!successAt) {
|
||||
throw new OakAttrNotNullException('pay', ['successAt']);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
// 如果在开始支付或者继续支付过程中,paid达到了price,pay的状态可以改为paid
|
||||
entity: 'pay',
|
||||
|
|
|
|||
|
|
@ -58,14 +58,14 @@ declare const Detail: <T extends keyof EntityDict>(props: ReactComponentProps<En
|
|||
data: Partial<EntityDict[T]["Schema"]>;
|
||||
title?: string | undefined;
|
||||
bordered?: boolean | undefined;
|
||||
layout?: "vertical" | "horizontal" | undefined;
|
||||
layout?: "horizontal" | "vertical" | undefined;
|
||||
}>) => React.ReactElement;
|
||||
declare const Upsert: <T extends keyof EntityDict>(props: ReactComponentProps<EntityDict, T, false, {
|
||||
helps: Record<string, string>;
|
||||
entity: T;
|
||||
attributes: OakAbsAttrUpsertDef<EntityDict, T, string | number>[];
|
||||
data: EntityDict[T]["Schema"];
|
||||
layout: "vertical" | "horizontal";
|
||||
layout: "horizontal" | "vertical";
|
||||
mode: "default" | "card";
|
||||
}>) => React.ReactElement;
|
||||
export { FilterPanel, List, ListPro, Detail, Upsert, ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef, };
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export default function render(props) {
|
|||
return t('notnull', { value: t(`offlineAccount:attr.${attr}`) });
|
||||
};
|
||||
const errMsg = oakExecutable instanceof OakException && (oakExecutable instanceof OakAttrNotNullException ? getNotNullMessage(oakExecutable.getAttributes()[0]) : t(oakExecutable.message));
|
||||
const U = (<Modal destroyOnClose width={680} title={`${t('offlineAccount:name')}${t('common::action.add')}`} open={!!upsertId} onCancel={() => {
|
||||
const U = (<Modal destroyOnClose width={920} title={`${t('offlineAccount:name')}${t('common::action.add')}`} open={!!upsertId} onCancel={() => {
|
||||
clean();
|
||||
setUpsertId('');
|
||||
}} closeIcon={null} onOk={async () => {
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ export default OakComponent({
|
|||
allowPay: 1,
|
||||
systemId: 1,
|
||||
enabled: 1,
|
||||
depositLossRatio: 1,
|
||||
taxlossRatio: 1,
|
||||
refundCompensateRatio: 1,
|
||||
taxLossRatio: 1,
|
||||
refundGapDays: 1,
|
||||
},
|
||||
isList: false,
|
||||
formData({ data }) {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@
|
|||
"shouqianba": "请将二维码解析后的字符串填入",
|
||||
"others": "请将二维码解析后的字符串填入"
|
||||
},
|
||||
"taxlossRatio": "渠道收款时收取的手续费百分比,0.6代表千分之六",
|
||||
"depositLossRatio": "充值时收取的手续费百分比,0.6代表千分之六"
|
||||
"taxLossRatio": "渠道收款时收取的手续费百分比,0.6代表千分之六",
|
||||
"refundGapDays": "超过这个天数后将无法退款",
|
||||
"refundCompensateRatio": "渠道退款时,返回的手续费比例(50代表渠道将返回当时收取的手续费的一半)"
|
||||
},
|
||||
"help": {
|
||||
"allowDeposit": "是否允许用户在系统中主动向此账号发起充值",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export default function render(props) {
|
|||
const { offlineAccount } = props.data;
|
||||
const { t, update } = props.methods;
|
||||
if (offlineAccount) {
|
||||
return (<Form labelCol={{ span: 6 }} wrapperCol={{ span: 16 }} layout="horizontal" style={{ minWidth: 600 }}>
|
||||
return (<Form labelCol={{ span: 8 }} wrapperCol={{ span: 12 }} layout="horizontal" style={{ minWidth: 860 }}>
|
||||
<Form.Item label={t('offlineAccount:attr.type')} required>
|
||||
<Select value={offlineAccount.type} options={['bank', 'alipay', 'wechat', 'shouqianba', 'others'].map(ele => ({
|
||||
label: t(`offlineAccount:v.type.${ele}`),
|
||||
|
|
@ -41,16 +41,22 @@ export default function render(props) {
|
|||
});
|
||||
}} placeholder={t(`placeholder.qrCode.${offlineAccount.type}`)}/>}
|
||||
</Form.Item>}
|
||||
<Form.Item label={t('offlineAccount:attr.taxlossRatio')} help={t('placeholder.taxlossRatio')}>
|
||||
<InputNumber value={offlineAccount.taxlossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const taxlossRatio = value;
|
||||
update({ taxlossRatio });
|
||||
<Form.Item label={t('offlineAccount:attr.taxLossRatio')} help={t('placeholder.taxLossRatio')}>
|
||||
<InputNumber value={offlineAccount.taxLossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const taxLossRatio = value;
|
||||
update({ taxLossRatio });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('offlineAccount:attr.depositLossRatio')} help={t('placeholder.depositLossRatio')}>
|
||||
<InputNumber value={offlineAccount.depositLossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const depositLossRatio = value;
|
||||
update({ depositLossRatio });
|
||||
<Form.Item label={t('offlineAccount:attr.refundGapDays')} help={t('placeholder.refundGapDays')}>
|
||||
<InputNumber value={offlineAccount.refundGapDays} max={365} min={7} addonAfter={"天"} step={1} onChange={(value) => {
|
||||
const refundGapDays = value;
|
||||
update({ refundGapDays });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('offlineAccount:attr.refundCompensateRatio')} help={t('placeholder.refundCompensateRatio')}>
|
||||
<InputNumber value={offlineAccount.refundCompensateRatio} max={100} min={1} addonAfter={"%"} step={1} onChange={(value) => {
|
||||
const refundCompensateRatio = value;
|
||||
update({ refundCompensateRatio });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
{!!offlineAccount.type && <Form.Item label={t('offlineAccount:attr.allowDeposit')} required help={t('help.allowDeposit')}>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { PAY_CHANNEL_ACCOUNT_NAME } from "../../../types/PayConfig";
|
||||
import { generateNewId } from "oak-domain/lib/utils/uuid";
|
||||
import { ToCent, ToYuan } from "oak-domain/lib/utils/money";
|
||||
export default OakComponent({
|
||||
|
|
@ -15,6 +14,8 @@ export default OakComponent({
|
|||
price: 1,
|
||||
paid: 1,
|
||||
iState: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
},
|
||||
filter: {
|
||||
iState: 'paying',
|
||||
|
|
@ -28,9 +29,7 @@ export default OakComponent({
|
|||
onSetPays: (pays) => undefined,
|
||||
},
|
||||
formData({ data }) {
|
||||
const payConfig = this.features.pay.getPayConfigs();
|
||||
const accountConfig = payConfig?.find(ele => ele.channel === PAY_CHANNEL_ACCOUNT_NAME);
|
||||
const payConfig2 = payConfig?.filter(ele => ele !== accountConfig);
|
||||
const payChannels = features.pay.getPayChannels('pay');
|
||||
const activePay = data && data.pay$order?.[0];
|
||||
const { accountPrice } = this.state;
|
||||
const { accountAvailMax } = this.props;
|
||||
|
|
@ -40,11 +39,10 @@ export default OakComponent({
|
|||
accountAvailMaxStr: accountAvailMax && ToYuan(accountAvailMax),
|
||||
order: data,
|
||||
activePay,
|
||||
accountConfig,
|
||||
payConfig: payConfig2,
|
||||
rest,
|
||||
restYuan: ToYuan(rest),
|
||||
legal: !!(data?.['#oakLegalActions']?.includes('startPaying')),
|
||||
payChannels,
|
||||
};
|
||||
},
|
||||
features: ['application'],
|
||||
|
|
@ -52,7 +50,7 @@ export default OakComponent({
|
|||
useAccount: false,
|
||||
accountPrice: 0,
|
||||
accountPriceYuan: 0,
|
||||
channel: '',
|
||||
channel: undefined,
|
||||
restYuan: 0,
|
||||
meta: undefined,
|
||||
onPickMp(channel) {
|
||||
|
|
@ -127,9 +125,9 @@ export default OakComponent({
|
|||
if (useAccount && accountPrice) {
|
||||
pays.push({
|
||||
id: generateNewId(),
|
||||
channel: PAY_CHANNEL_ACCOUNT_NAME,
|
||||
entity: 'account',
|
||||
entityId: accountId,
|
||||
price: accountPrice,
|
||||
accountId,
|
||||
});
|
||||
rest = rest - accountPrice;
|
||||
}
|
||||
|
|
@ -137,7 +135,8 @@ export default OakComponent({
|
|||
payId = generateNewId();
|
||||
pays.push({
|
||||
id: payId,
|
||||
channel,
|
||||
entity: channel.entity,
|
||||
entityId: channel.entityId,
|
||||
meta,
|
||||
price: rest,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@
|
|||
"l-icon": "@oak-frontend-base/miniprogram_npm/lin-ui/icon/index",
|
||||
"l-button": "@oak-frontend-base/miniprogram_npm/lin-ui/button/index",
|
||||
"l-switch": "@oak-frontend-base/miniprogram_npm/lin-ui/switch/index",
|
||||
"channel-picker": "../../pay/channelPicker"
|
||||
"channel-picker": "../../pay/channelPicker2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,24 @@
|
|||
import React from 'react';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { AccountPayConfig, PayConfig } from '../../../types/PayConfig';
|
||||
import { AccountPayConfig } from '../../../types/PayConfig';
|
||||
import { PayChannel, PayChannels } from '../../../types/Pay';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'order', false, {
|
||||
accountId?: string;
|
||||
accountAvailMax: number;
|
||||
order: EntityDict['order']['OpSchema'];
|
||||
activePay?: EntityDict['pay']['OpSchema'];
|
||||
accountConfig?: AccountPayConfig;
|
||||
payConfig?: PayConfig;
|
||||
payChannels?: PayChannels;
|
||||
channel?: PayChannel;
|
||||
accountPrice: number;
|
||||
channel?: string;
|
||||
meta?: object;
|
||||
useAccount: boolean;
|
||||
rest: number;
|
||||
legal: false;
|
||||
}, {
|
||||
setAccountPrice: (price: number) => void;
|
||||
onPickChannel: (channel: string) => void;
|
||||
onPickChannel: (channel: PayChannel) => void;
|
||||
onSetChannelMeta: (meta?: object) => void;
|
||||
switchUseAccount: () => void;
|
||||
}>): React.JSX.Element | null;
|
||||
|
|
|
|||
|
|
@ -1,25 +1,19 @@
|
|||
import React from 'react';
|
||||
import { ToYuan, ToCent } from 'oak-domain/lib/utils/money';
|
||||
import Styles from './web.mobile.module.less';
|
||||
// import PayChannelPicker from '../../pay/channelPicker';
|
||||
import PayChannelPicker from '../../pay/channelPicker2';
|
||||
import { InputNumber } from 'antd';
|
||||
import { Checkbox, Divider, ErrorBlock } from 'antd-mobile';
|
||||
import Info from './info';
|
||||
function RenderPayChannel(props) {
|
||||
const { price, payConfig, t, channel, meta, onPick, onSetMeta } = props;
|
||||
const { price, payChannels, t, channel, meta, onPick, } = props;
|
||||
return (<div className={Styles.pc1}>
|
||||
<div className={Styles.content}>
|
||||
<div>
|
||||
{t('choose', { price: ToYuan(price) })}
|
||||
</div>
|
||||
<Divider />
|
||||
{/* <PayChannelPicker
|
||||
payConfig={payConfig}
|
||||
channel={channel}
|
||||
meta={meta}
|
||||
onPick={onPick}
|
||||
onSetMeta={onSetMeta}
|
||||
/> */}
|
||||
<PayChannelPicker payChannels={payChannels} payChannel={channel} onPick={onPick}/>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
|
|
@ -45,7 +39,7 @@ function RenderAccountPay(props) {
|
|||
</div>);
|
||||
}
|
||||
export default function Render(props) {
|
||||
const { accountId, accountAvailMax, legal, accountPrice, useAccount, order, activePay, payConfig, channel, meta, rest } = props.data;
|
||||
const { accountId, accountAvailMax, legal, accountPrice, useAccount, order, activePay, payChannels, channel, meta, rest } = props.data;
|
||||
const { t, setAccountPrice, onPickChannel, onSetChannelMeta, switchUseAccount } = props.methods;
|
||||
if (order) {
|
||||
if (activePay) {
|
||||
|
|
@ -60,7 +54,7 @@ export default function Render(props) {
|
|||
<RenderAccountPay max={Math.min(accountAvailMax, rest + accountPrice)} t={t} setAccountPrice={setAccountPrice} useAccount={useAccount} switchUseAccount={switchUseAccount} accountPrice={accountPrice} accountAvail={accountAvailMax}/>
|
||||
</div>}
|
||||
{!!(rest && rest > 0) && <div className={Styles.ctrl}>
|
||||
<RenderPayChannel payConfig={payConfig} price={rest} t={t} channel={channel} meta={meta} onPick={onPickChannel} onSetMeta={onSetChannelMeta}/>
|
||||
<RenderPayChannel price={rest} t={t} payChannels={payChannels} channel={channel} meta={meta} onPick={onPickChannel}/>
|
||||
</div>}
|
||||
</div>);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,24 @@
|
|||
import React from 'react';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { AccountPayConfig, PayConfig } from '../../../types/PayConfig';
|
||||
import { AccountPayConfig } from '../../../types/PayConfig';
|
||||
import { PayChannel, PayChannels } from '../../../types/Pay';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'order', false, {
|
||||
accountId?: string;
|
||||
accountAvailMax: number;
|
||||
order: EntityDict['order']['OpSchema'];
|
||||
activePay?: EntityDict['pay']['OpSchema'];
|
||||
accountConfig?: AccountPayConfig;
|
||||
payConfig?: PayConfig;
|
||||
payChannels?: PayChannels;
|
||||
channel?: PayChannel;
|
||||
accountPrice: number;
|
||||
channel?: string;
|
||||
meta?: object;
|
||||
useAccount: boolean;
|
||||
rest: number;
|
||||
legal: false;
|
||||
}, {
|
||||
setAccountPrice: (price: number) => void;
|
||||
onPickChannel: (channel: string) => void;
|
||||
onPickChannel: (channel: PayChannel) => void;
|
||||
onSetChannelMeta: (meta?: object) => void;
|
||||
switchUseAccount: () => void;
|
||||
}>): React.JSX.Element | null;
|
||||
|
|
|
|||
|
|
@ -1,24 +1,18 @@
|
|||
import React from 'react';
|
||||
import { ToYuan, ToCent } from 'oak-domain/lib/utils/money';
|
||||
import Styles from './web.pc.module.less';
|
||||
// import PayChannelPicker from '../../pay/channelPicker';
|
||||
import PayChannelPicker from '../../pay/channelPicker2';
|
||||
import { Divider, Checkbox, InputNumber, Flex, Result } from 'antd';
|
||||
import Info from './info';
|
||||
function RenderPayChannel(props) {
|
||||
const { price, payConfig, t, channel, meta, onPick, onSetMeta } = props;
|
||||
const { price, payChannels, t, channel, meta, onPick, } = props;
|
||||
return (<div className={Styles.pc1}>
|
||||
<div className={Styles.content}>
|
||||
<div>
|
||||
{t('choose', { price: ToYuan(price) })}
|
||||
</div>
|
||||
<Divider />
|
||||
{/* <PayChannelPicker
|
||||
payConfig={payConfig}
|
||||
channel={channel}
|
||||
meta={meta}
|
||||
onPick={onPick}
|
||||
onSetMeta={onSetMeta}
|
||||
/> */}
|
||||
<PayChannelPicker payChannels={payChannels} payChannel={channel} onPick={onPick}/>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
|
|
@ -44,7 +38,7 @@ function RenderAccountPay(props) {
|
|||
</div>);
|
||||
}
|
||||
export default function Render(props) {
|
||||
const { accountId, accountAvailMax, legal, accountPrice, useAccount, order, activePay, payConfig, channel, meta, rest } = props.data;
|
||||
const { accountId, accountAvailMax, legal, accountPrice, useAccount, order, activePay, payChannels, channel, meta, rest } = props.data;
|
||||
const { t, setAccountPrice, onPickChannel, onSetChannelMeta, switchUseAccount } = props.methods;
|
||||
if (order) {
|
||||
if (activePay) {
|
||||
|
|
@ -59,7 +53,7 @@ export default function Render(props) {
|
|||
<RenderAccountPay max={Math.min(accountAvailMax, rest + accountPrice)} t={t} setAccountPrice={setAccountPrice} useAccount={useAccount} switchUseAccount={switchUseAccount} accountPrice={accountPrice} accountAvail={accountAvailMax}/>
|
||||
</div>}
|
||||
{!!(rest && rest > 0) && <div className={Styles.ctrl}>
|
||||
<RenderPayChannel payConfig={payConfig} price={rest} t={t} channel={channel} meta={meta} onPick={onPickChannel} onSetMeta={onSetChannelMeta}/>
|
||||
<RenderPayChannel price={rest} t={t} payChannels={payChannels} channel={channel} meta={meta} onPick={onPickChannel}/>
|
||||
</div>}
|
||||
</div>);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ export default function Render(props) {
|
|||
{t('pay:attr.price')}
|
||||
</List.Item>
|
||||
<List.Item prefix={<GlobalOutline />} extra={t(`payChannel::${entity}`)}>
|
||||
{t('pay:attr.channel')}
|
||||
{t('pay:attr.entity')}
|
||||
</List.Item>
|
||||
</List>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ export default OakComponent({
|
|||
isList: false,
|
||||
projection: {
|
||||
id: 1,
|
||||
payConfig: 1,
|
||||
wpAccount$system: {
|
||||
$entity: 'wpAccount',
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,22 @@
|
|||
{
|
||||
"system": "系统配置",
|
||||
"appsBelow": "以下为application",
|
||||
"mayLossUpdate": "%{name}上的更新可能会丢失,请尽快保存"
|
||||
"system": "系统相关配置",
|
||||
"help": "说明",
|
||||
"payConfig": {
|
||||
"label": {
|
||||
"depositLoss": "充值手续费",
|
||||
"withdrawLoss": "提现手续费",
|
||||
"conservative": "保守策略",
|
||||
"ratio": "按比例",
|
||||
"lowest": "最低(分)",
|
||||
"highest": "最高(分)",
|
||||
"trim": "去尾",
|
||||
"jiao": "角",
|
||||
"yuan": "元",
|
||||
"null": "不去尾"
|
||||
},
|
||||
"help": {
|
||||
"depositLoss": "若不配置手续费,用户充值时渠道的手续费损失将被计算到system关联的账户之中",
|
||||
"withdrawLoss": "若配置为保守策略,系统将自动计算渠道的损耗,在system账户不贴现的前提下让用户可提现的额度最大化"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Tabs } from 'antd';
|
||||
import React from 'react';
|
||||
import { Button, Popover, Tabs, Flex, Card, Form, InputNumber, Switch, Radio } from 'antd';
|
||||
import Styles from './web.pc.module.less';
|
||||
import OfflineConfig from '../../offlineAccount/config';
|
||||
import WpAccountConfig from '../../wpAccount/config';
|
||||
|
|
@ -9,13 +9,144 @@ const PayChannelConfigDict = {
|
|||
export function registerPayChannelComponent(entity, component) {
|
||||
PayChannelConfigDict[entity] = component;
|
||||
}
|
||||
function PayConfig(props) {
|
||||
const { payConfig, update, t } = props;
|
||||
const withdrawLoss = payConfig?.withdrawLoss;
|
||||
const depositLoss = payConfig?.depositLoss;
|
||||
const updateDepositLoss = (data) => {
|
||||
update({
|
||||
depositLoss: {
|
||||
...depositLoss,
|
||||
...data,
|
||||
},
|
||||
withdrawLoss: withdrawLoss || {
|
||||
conservative: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
const updateWithdrawLoss = (data) => {
|
||||
update({
|
||||
depositLoss: depositLoss || {},
|
||||
withdrawLoss: {
|
||||
conservative: !!(withdrawLoss?.conservative),
|
||||
...withdrawLoss,
|
||||
...data,
|
||||
},
|
||||
});
|
||||
};
|
||||
return (<Flex gap="middle">
|
||||
<Card title={t('payConfig.label.depositLoss')} extra={<Popover content={t("payConfig.help.depositLoss")}>
|
||||
<span className={Styles.help}>{t("help")}</span>
|
||||
</Popover>}>
|
||||
<Form labelCol={{ span: 8 }} wrapperCol={{ span: 18 }} layout="horizontal" style={{ width: '100%' }}>
|
||||
<Form.Item label={t('payConfig.label.ratio')}>
|
||||
<InputNumber value={depositLoss?.ratio} max={20} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const ratio = value;
|
||||
updateDepositLoss({
|
||||
ratio: ratio || 0
|
||||
});
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('payConfig.label.highest')}>
|
||||
<InputNumber value={depositLoss?.highest} min={0} step={1} onChange={(value) => {
|
||||
const highest = value;
|
||||
updateDepositLoss({
|
||||
highest: highest || undefined
|
||||
});
|
||||
return;
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('payConfig.label.lowest')}>
|
||||
<InputNumber value={depositLoss?.lowest} min={0} step={1} onChange={(value) => {
|
||||
const lowest = value;
|
||||
updateDepositLoss({
|
||||
lowest: lowest || undefined
|
||||
});
|
||||
return;
|
||||
}}/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
<Card title={t('payConfig.label.withdrawLoss')} extra={<Popover content={t('payConfig.help.withdrawLoss')}>
|
||||
<span className={Styles.help}>{t("help")}</span>
|
||||
</Popover>}>
|
||||
<Form labelCol={{ span: 8 }} wrapperCol={{ span: 18 }} layout="horizontal" style={{ width: '100%' }}>
|
||||
<Form.Item label={t('payConfig.label.conservative')}>
|
||||
<Switch value={withdrawLoss?.conservative} onChange={(conservative) => {
|
||||
updateWithdrawLoss({ conservative });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('payConfig.label.ratio')}>
|
||||
<InputNumber disabled={!!withdrawLoss?.conservative} value={withdrawLoss?.ratio} max={20} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const ratio = value;
|
||||
updateWithdrawLoss({
|
||||
ratio: ratio || 0
|
||||
});
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('payConfig.label.highest')}>
|
||||
<InputNumber disabled={!!withdrawLoss?.conservative} value={withdrawLoss?.highest} min={0} step={1} onChange={(value) => {
|
||||
const highest = value;
|
||||
updateWithdrawLoss({
|
||||
highest: highest || undefined
|
||||
});
|
||||
return;
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('payConfig.label.lowest')}>
|
||||
<InputNumber disabled={!!withdrawLoss?.conservative} value={withdrawLoss?.lowest} min={0} step={1} onChange={(value) => {
|
||||
const lowest = value;
|
||||
updateWithdrawLoss({
|
||||
lowest: lowest || undefined
|
||||
});
|
||||
return;
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('payConfig.label.trim')}>
|
||||
<Radio.Group disabled={!!withdrawLoss?.conservative} options={[
|
||||
{
|
||||
label: t('payConfig.label.jiao'),
|
||||
value: 'jiao',
|
||||
},
|
||||
{
|
||||
label: t('payConfig.label.yuan'),
|
||||
value: 'yuan',
|
||||
},
|
||||
{
|
||||
label: t('payConfig.label.null'),
|
||||
value: '',
|
||||
}
|
||||
]} value={withdrawLoss?.trim} onChange={({ target }) => updateWithdrawLoss({
|
||||
trim: target.value,
|
||||
})}/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
</Flex>);
|
||||
}
|
||||
export default function render(props) {
|
||||
const { system, oakFullpath, operation, oakDirty, serverUrl, oakExecutable } = props.data;
|
||||
const { t, update, setMessage, execute } = props.methods;
|
||||
const [key, setKey] = useState('');
|
||||
const { t, update, clean, execute } = props.methods;
|
||||
if (system && oakFullpath) {
|
||||
return (<div className={Styles.container}>
|
||||
<Tabs className={Styles.tabs} tabPosition="left" items={[
|
||||
{
|
||||
label: (<div className={Styles.systemLabel}>
|
||||
{t('system')}
|
||||
</div>),
|
||||
key: 'system',
|
||||
children: (<Flex vertical>
|
||||
<PayConfig payConfig={system.payConfig} update={(payConfig) => update({ payConfig })} t={t}/>
|
||||
<Flex gap="middle" justify='end'>
|
||||
<Button type="primary" disabled={oakExecutable !== true} onClick={() => execute()}>
|
||||
{t('common::confirm')}
|
||||
</Button>
|
||||
<Button disabled={!oakDirty} onClick={() => clean()}>
|
||||
{t('common::reset')}
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>),
|
||||
},
|
||||
{
|
||||
label: (<div className={Styles.systemLabel}>
|
||||
{t('offlineAccount:name')}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ export default OakComponent({
|
|||
price: 1,
|
||||
mchId: 1,
|
||||
refundGapDays: 1,
|
||||
refundLossRatio: 1,
|
||||
refundLossFloor: 1,
|
||||
taxlossRatio: 1,
|
||||
taxLossRatio: 1,
|
||||
enabled: 1,
|
||||
},
|
||||
formData({ data, legalActions }) {
|
||||
|
|
|
|||
|
|
@ -12,11 +12,10 @@ export default OakComponent({
|
|||
payNotifyUrl: 1,
|
||||
refundNotifyUrl: 1,
|
||||
},
|
||||
taxlossRatio: 1,
|
||||
taxLossRatio: 1,
|
||||
publicKeyFilePath: 1,
|
||||
privateKeyFilePath: 1,
|
||||
refundLossFloor: 1,
|
||||
refundLossRatio: 1,
|
||||
refundCompensateRatio: 1,
|
||||
apiV3Key: 1,
|
||||
systemId: 1,
|
||||
},
|
||||
|
|
@ -46,7 +45,7 @@ export default OakComponent({
|
|||
this.update({
|
||||
price: 0,
|
||||
enabled: true,
|
||||
taxlossRatio: 0.6,
|
||||
taxLossRatio: 0.6,
|
||||
});
|
||||
const { systemId } = this.props;
|
||||
const { data: [wechatPay] } = await this.features.cache.refresh('wechatPay', {
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@
|
|||
"placeholder": {
|
||||
"privateKeyFilePath": "服务器上存放apiclient_key.pem的路径,注意访问权限",
|
||||
"publicKeyFilePath": "服务器上存放apiclient_cert.pem的路径,注意访问权限",
|
||||
"taxlossRatio": "微信支付收取的手续费百分比,一般为0.6(代表千分之六)",
|
||||
"taxLossRatio": "微信支付收取的手续费百分比,一般为0.6(代表千分之六)",
|
||||
"refundCompensateRatio": "渠道退款时,返回的手续费比例(50代表渠道将返回当时收取的手续费的一半)",
|
||||
"depositLossRatio": "充值收取的手续费百分比,一般为0.6(代表千分之六)",
|
||||
"payNotifyUrl": "endpoint",
|
||||
"refundNotifyUrl": "endpoint",
|
||||
"apiV3Key": "需要登录商户后台获取",
|
||||
"refundGapDays": "超过这个天数后无法退款",
|
||||
"refundLossRatio": "退款时将按这个百分比扣除损耗(0.6就代表千分之六)",
|
||||
"refundLossFloor": "退款时按位向下取整(如按元取整,则忽略角位和分位)"
|
||||
"refundGapDays": "超过这个天数后无法退款"
|
||||
},
|
||||
"wechatPayIsShared": "以上配置是全局的,请谨慎修改"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Form, Switch, InputNumber, Input, Radio, Divider } from 'antd';
|
||||
import { Form, Switch, InputNumber, Input, Divider } from 'antd';
|
||||
import Styles from './web.pc.module.less';
|
||||
import WechatPayUpsert from '../../wechatPay/upsert';
|
||||
export default function render(props) {
|
||||
|
|
@ -39,16 +39,16 @@ export default function render(props) {
|
|||
update({ apiV3Key });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.taxlossRatio')} help={t('placeholder.taxlossRatio')}>
|
||||
<InputNumber value={wpAccount.taxlossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const taxlossRatio = value;
|
||||
update({ taxlossRatio });
|
||||
<Form.Item label={t('wpAccount:attr.taxLossRatio')} help={t('placeholder.taxLossRatio')}>
|
||||
<InputNumber value={wpAccount.taxLossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const taxLossRatio = value;
|
||||
update({ taxLossRatio });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.depositLossRatio')} help={t('placeholder.depositLossRatio')}>
|
||||
<InputNumber value={wpAccount.depositLossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const depositLossRatio = value;
|
||||
update({ depositLossRatio });
|
||||
<Form.Item label={t('wpAccount:attr.refundCompensateRatio')} help={t('placeholder.refundCompensateRatio')}>
|
||||
<InputNumber value={wpAccount.refundCompensateRatio} max={100} min={1} addonAfter={"%"} step={1} onChange={(value) => {
|
||||
const refundCompensateRatio = value;
|
||||
update({ refundCompensateRatio });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.refundGapDays')} help={t('placeholder.refundGapDays')}>
|
||||
|
|
@ -57,22 +57,6 @@ export default function render(props) {
|
|||
update({ refundGapDays });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.refundLossRatio')} help={t('placeholder.refundLossRatio')}>
|
||||
<InputNumber value={wpAccount.refundLossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const refundLossRatio = value;
|
||||
update({ refundLossRatio });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.refundLossFloor')} help={t('placeholder.refundLossFloor')}>
|
||||
<Radio.Group onChange={({ target }) => {
|
||||
const { value } = target;
|
||||
const refundLossFloor = value;
|
||||
update({ refundLossFloor });
|
||||
}} value={wpAccount.refundLossFloor}>
|
||||
<Radio value={"jiao"}>角</Radio>
|
||||
<Radio value={"yuan"}>元</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.enabled')} required>
|
||||
<Switch value={wpAccount.enabled} onChange={(enabled) => {
|
||||
update({ enabled });
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"placeholder": {
|
||||
"taxlossRatio": "如果配置了产品的手续费,则覆盖微信支付账号上配置的手续费"
|
||||
"taxLossRatio": "如果配置了产品的手续费,则覆盖微信支付账号上配置的手续费"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ export default function render(props) {
|
|||
update({ enabled });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('wpAccount:attr.taxlossRatio')} help={t('placeholder.taxlossRatio')}>
|
||||
<InputNumber value={wpProduct.taxlossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const taxlossRatio = value;
|
||||
update({ taxlossRatio });
|
||||
<Form.Item label={t('wpAccount:attr.taxLossRatio')} help={t('placeholder.taxLossRatio')}>
|
||||
<InputNumber value={wpProduct.taxLossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const taxLossRatio = value;
|
||||
update({ taxLossRatio });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
</Form>);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ const attrUpdateMatrix = {
|
|||
forbidRefundAt: {
|
||||
actions: ['succeedPaying'],
|
||||
},
|
||||
successAt: {
|
||||
actions: ['succeedPaying'],
|
||||
},
|
||||
entity: {
|
||||
actions: ['update', 'succeedPaying'],
|
||||
filter: {
|
||||
|
|
@ -108,12 +111,18 @@ const attrUpdateMatrix = {
|
|||
enabled: {
|
||||
actions: ['update'],
|
||||
},
|
||||
taxlossRatio: {
|
||||
taxLossRatio: {
|
||||
actions: ['update'],
|
||||
},
|
||||
depositLossRatio: {
|
||||
actions: ['update'],
|
||||
},
|
||||
refundCompensateRatio: {
|
||||
actions: ['update'],
|
||||
},
|
||||
refundGapDays: {
|
||||
actions: ['update'],
|
||||
},
|
||||
price: {
|
||||
actions: ['pay', 'refund', 'deposit', 'withdraw', 'tax'],
|
||||
},
|
||||
|
|
@ -134,7 +143,7 @@ const attrUpdateMatrix = {
|
|||
wechatPay: {
|
||||
actions: ['update'],
|
||||
},
|
||||
taxlossRatio: {
|
||||
taxLossRatio: {
|
||||
actions: ['update'],
|
||||
},
|
||||
depositLossRatio: {
|
||||
|
|
|
|||
|
|
@ -115,8 +115,9 @@ const i18ns = [
|
|||
"shouqianba": "请将二维码解析后的字符串填入",
|
||||
"others": "请将二维码解析后的字符串填入"
|
||||
},
|
||||
"taxlossRatio": "渠道收款时收取的手续费百分比,0.6代表千分之六",
|
||||
"depositLossRatio": "充值时收取的手续费百分比,0.6代表千分之六"
|
||||
"taxLossRatio": "渠道收款时收取的手续费百分比,0.6代表千分之六",
|
||||
"refundGapDays": "超过这个天数后将无法退款",
|
||||
"refundCompensateRatio": "渠道退款时,返回的手续费比例(50代表渠道将返回当时收取的手续费的一半)"
|
||||
},
|
||||
"help": {
|
||||
"allowDeposit": "是否允许用户在系统中主动向此账号发起充值",
|
||||
|
|
@ -229,9 +230,26 @@ const i18ns = [
|
|||
module: "oak-pay-business",
|
||||
position: "src/components/payConfig/system",
|
||||
data: {
|
||||
"system": "系统配置",
|
||||
"appsBelow": "以下为application",
|
||||
"mayLossUpdate": "%{name}上的更新可能会丢失,请尽快保存"
|
||||
"system": "系统相关配置",
|
||||
"help": "说明",
|
||||
"payConfig": {
|
||||
"label": {
|
||||
"depositLoss": "充值手续费",
|
||||
"withdrawLoss": "提现手续费",
|
||||
"conservative": "保守策略",
|
||||
"ratio": "按比例",
|
||||
"lowest": "最低(分)",
|
||||
"highest": "最高(分)",
|
||||
"trim": "去尾",
|
||||
"jiao": "角",
|
||||
"yuan": "元",
|
||||
"null": "不去尾"
|
||||
},
|
||||
"help": {
|
||||
"depositLoss": "若不配置手续费,用户充值时渠道的手续费损失将被计算到system关联的账户之中",
|
||||
"withdrawLoss": "若配置为保守策略,系统将自动计算渠道的损耗,在system账户不贴现的前提下让用户可提现的额度最大化"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -472,14 +490,13 @@ const i18ns = [
|
|||
"placeholder": {
|
||||
"privateKeyFilePath": "服务器上存放apiclient_key.pem的路径,注意访问权限",
|
||||
"publicKeyFilePath": "服务器上存放apiclient_cert.pem的路径,注意访问权限",
|
||||
"taxlossRatio": "微信支付收取的手续费百分比,一般为0.6(代表千分之六)",
|
||||
"taxLossRatio": "微信支付收取的手续费百分比,一般为0.6(代表千分之六)",
|
||||
"refundCompensateRatio": "渠道退款时,返回的手续费比例(50代表渠道将返回当时收取的手续费的一半)",
|
||||
"depositLossRatio": "充值收取的手续费百分比,一般为0.6(代表千分之六)",
|
||||
"payNotifyUrl": "endpoint",
|
||||
"refundNotifyUrl": "endpoint",
|
||||
"apiV3Key": "需要登录商户后台获取",
|
||||
"refundGapDays": "超过这个天数后无法退款",
|
||||
"refundLossRatio": "退款时将按这个百分比扣除损耗(0.6就代表千分之六)",
|
||||
"refundLossFloor": "退款时按位向下取整(如按元取整,则忽略角位和分位)"
|
||||
"refundGapDays": "超过这个天数后无法退款"
|
||||
},
|
||||
"wechatPayIsShared": "以上配置是全局的,请谨慎修改"
|
||||
}
|
||||
|
|
@ -506,7 +523,7 @@ const i18ns = [
|
|||
position: "src/components/wpProduct/upsert",
|
||||
data: {
|
||||
"placeholder": {
|
||||
"taxlossRatio": "如果配置了产品的手续费,则覆盖微信支付账号上配置的手续费"
|
||||
"taxLossRatio": "如果配置了产品的手续费,则覆盖微信支付账号上配置的手续费"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -576,7 +593,9 @@ const i18ns = [
|
|||
},
|
||||
"deposit": {
|
||||
"lossReason": {
|
||||
"ratio": "按百分比%{value}%扣除"
|
||||
"ratio": "按百分比%{value}%扣除",
|
||||
"highest": "按单笔充值最高手续费%{value}扣除",
|
||||
"lowest": "按单笔充值最低手续费%{value}扣除"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,9 @@ import { Int, Decimal } from 'oak-domain/lib/types/DataType';
|
|||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDesc } from 'oak-domain/lib/types';
|
||||
export interface Schema extends EntityShape {
|
||||
taxlossRatio: Decimal<4, 2>;
|
||||
depositLossRatio?: Decimal<4, 2>;
|
||||
taxLossRatio: Decimal<4, 2>;
|
||||
refundGapDays?: Int<4>;
|
||||
refundLossRatio?: Decimal<4, 2>;
|
||||
refundLossFloor?: 'yuan' | 'jiao';
|
||||
refundCompensateRatio?: Int<4>;
|
||||
}
|
||||
export type Action = 'pay' | 'refund' | 'deposit' | 'withdraw' | 'tax';
|
||||
export declare const entityDesc: EntityDesc<Schema, Action, '', {
|
||||
refundLossFloor: NonNullable<Schema['refundLossFloor']>;
|
||||
}>;
|
||||
export declare const entityDesc: EntityDesc<Schema, Action>;
|
||||
|
|
|
|||
|
|
@ -4,17 +4,9 @@ export const entityDesc = {
|
|||
zh_CN: {
|
||||
name: '抽象支付帐号',
|
||||
attr: {
|
||||
taxlossRatio: '渠道手续费(百分比)',
|
||||
depositLossRatio: '充值损耗百分比',
|
||||
taxLossRatio: '渠道手续费(百分比)',
|
||||
refundGapDays: '(支付后)允许退款的天数',
|
||||
refundLossRatio: '退款损耗百分比',
|
||||
refundLossFloor: '退款向下取整位数',
|
||||
},
|
||||
v: {
|
||||
refundLossFloor: {
|
||||
yuan: '元',
|
||||
jiao: '角'
|
||||
},
|
||||
refundCompensateRatio: '退款补偿百分比',
|
||||
},
|
||||
action: {
|
||||
pay: '支付',
|
||||
|
|
@ -26,12 +18,6 @@ export const entityDesc = {
|
|||
},
|
||||
},
|
||||
style: {
|
||||
color: {
|
||||
refundLossFloor: {
|
||||
yuan: '#FFFF00',
|
||||
jiao: '#00FF00'
|
||||
}
|
||||
},
|
||||
icon: {
|
||||
pay: '',
|
||||
refund: '',
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { String, Price } from 'oak-domain/lib/types/DataType';
|
|||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDesc } from 'oak-domain/lib/types';
|
||||
import { Schema as Account } from './Account';
|
||||
type Type = 'deposit' | 'withdraw' | 'consume' | 'loan' | 'repay' | 'withdrawBack' | 'earn' | 'encash' | 'cutoffRefundable';
|
||||
type Type = 'deposit' | 'withdraw' | 'consume' | 'loan' | 'repay' | 'withdrawBack' | 'earn' | 'encash' | 'cutoffRefundable' | 'tax';
|
||||
export interface Schema extends EntityShape {
|
||||
account: Account;
|
||||
type: Type;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export const entityDesc = {
|
|||
withdrawBack: '提现失败',
|
||||
earn: '赚取',
|
||||
encash: '兑现',
|
||||
tax: '渠道费',
|
||||
cutoffRefundable: '削减可自由退额度'
|
||||
},
|
||||
},
|
||||
|
|
@ -38,6 +39,7 @@ export const entityDesc = {
|
|||
repay: '#82E0AA',
|
||||
earn: '#FF3333',
|
||||
encash: '#FF3399',
|
||||
tax: '#A569BD',
|
||||
cutoffRefundable: '#2E4053',
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,4 @@
|
|||
<<<<<<< HEAD
|
||||
import { String, Text, Price, Boolean } from 'oak-domain/lib/types/DataType';
|
||||
=======
|
||||
import { String, Text, Price, Boolean, Decimal } from 'oak-domain/lib/types/DataType';
|
||||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
>>>>>>> 99d2876ae88266ffcff6aa944c537941daeab7ce
|
||||
import { EntityDesc } from 'oak-domain/lib/types';
|
||||
import { Schema as System } from './System';
|
||||
import { Schema as Pay } from './Pay';
|
||||
|
|
@ -12,8 +7,6 @@ import { Schema as AbstractAccount } from './AbstractAccount';
|
|||
export interface Schema extends AbstractAccount {
|
||||
type: 'bank' | 'alipay' | 'wechat' | 'shouqianba' | 'others';
|
||||
channel?: String<32>;
|
||||
taxlossRatio?: Decimal<4, 2>;
|
||||
depositLossRatio?: Decimal<4, 2>;
|
||||
name?: String<64>;
|
||||
qrCode?: Text;
|
||||
allowDeposit: Boolean;
|
||||
|
|
|
|||
|
|
@ -8,14 +8,9 @@ export const entityDesc = {
|
|||
channel: '通道',
|
||||
name: '用户/帐号',
|
||||
qrCode: '收款二维码',
|
||||
taxlossRatio: '商户号手续费(百分比)',
|
||||
depositLossRatio: '充值损耗百分比',
|
||||
<<<<<<< HEAD
|
||||
taxLossRatio: '商户号手续费(百分比)',
|
||||
refundCompensateRatio: '退款补偿百分比',
|
||||
refundGapDays: '(支付后)允许退款的天数',
|
||||
refundLossRatio: '退款损耗百分比',
|
||||
refundLossFloor: '退款向下取整位数',
|
||||
=======
|
||||
>>>>>>> 99d2876ae88266ffcff6aa944c537941daeab7ce
|
||||
allowDeposit: '允许主动充值',
|
||||
allowPay: '允许主动支付',
|
||||
system: '所属系统',
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export interface Schema extends EntityShape {
|
|||
entity: String<32>;
|
||||
entityId: String<64>;
|
||||
timeoutAt?: Datetime;
|
||||
successAt?: Datetime;
|
||||
forbidRefundAt?: Datetime;
|
||||
refundable: Boolean;
|
||||
deposit?: Deposit;
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ export const entityDesc = {
|
|||
order: '所属订单',
|
||||
deposit: '充值',
|
||||
timeoutAt: '过期时间',
|
||||
successAt: '完成时间',
|
||||
forbidRefundAt: '停止退款时间',
|
||||
refundable: '是否可退款',
|
||||
meta: '支付metadata',
|
||||
|
|
|
|||
|
|
@ -2,8 +2,24 @@ import { EntityDesc } from 'oak-domain/lib/types/EntityDesc';
|
|||
import { Schema as System } from 'oak-general-business/lib/entities/System';
|
||||
import { Schema as Account } from './Account';
|
||||
import { Schema as WithdrawAccount } from './WithdrawAccount';
|
||||
type PayConfig = {
|
||||
withdrawLoss: {
|
||||
conservative: boolean;
|
||||
ratio?: number;
|
||||
lowest?: number;
|
||||
highest?: number;
|
||||
trim?: "jiao" | "yuan";
|
||||
};
|
||||
depositLoss: {
|
||||
ratio?: number;
|
||||
lowest?: number;
|
||||
highest?: number;
|
||||
};
|
||||
};
|
||||
export interface Schema extends System {
|
||||
accounts: Account[];
|
||||
withdrawAccounts: WithdrawAccount[];
|
||||
payConfig?: PayConfig;
|
||||
}
|
||||
export declare const entityDesc: EntityDesc<Schema>;
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export const entityDesc = {
|
|||
name: '名称',
|
||||
description: '描述',
|
||||
config: '设置',
|
||||
payConfig: '支付相关设置',
|
||||
platform: '平台',
|
||||
super: '超级系统',
|
||||
folder: '代码目录名',
|
||||
|
|
|
|||
|
|
@ -16,6 +16,4 @@ export interface Schema extends AbstractAccount {
|
|||
enabled: Boolean;
|
||||
}
|
||||
export type Action = 'pay' | 'refund' | 'deposit' | 'withdraw' | 'tax';
|
||||
export declare const entityDesc: EntityDesc<Schema, Action, '', {
|
||||
refundLossFloor: NonNullable<Schema['refundLossFloor']>;
|
||||
}>;
|
||||
export declare const entityDesc: EntityDesc<Schema, Action>;
|
||||
|
|
|
|||
|
|
@ -5,11 +5,9 @@ export const entityDesc = {
|
|||
name: '微信支付帐号',
|
||||
attr: {
|
||||
wechatPay: '微信支付',
|
||||
taxlossRatio: '商户号手续费(百分比)',
|
||||
depositLossRatio: '充值损耗百分比',
|
||||
taxLossRatio: '商户号手续费(百分比)',
|
||||
refundCompensateRatio: '退款补偿百分比',
|
||||
refundGapDays: '(支付后)允许退款的天数',
|
||||
refundLossRatio: '退款损耗百分比',
|
||||
refundLossFloor: '退款向下取整位数',
|
||||
mchId: '商户号',
|
||||
publicKeyFilePath: '公钥文件路径',
|
||||
privateKeyFilePath: '私钥文件路径',
|
||||
|
|
@ -19,12 +17,6 @@ export const entityDesc = {
|
|||
opers: '操作记录',
|
||||
enabled: '是否启用',
|
||||
},
|
||||
v: {
|
||||
refundLossFloor: {
|
||||
yuan: '元',
|
||||
jiao: '角'
|
||||
},
|
||||
},
|
||||
action: {
|
||||
pay: '支付',
|
||||
refund: '退款',
|
||||
|
|
@ -35,12 +27,6 @@ export const entityDesc = {
|
|||
},
|
||||
},
|
||||
style: {
|
||||
color: {
|
||||
refundLossFloor: {
|
||||
yuan: '#FFFF00',
|
||||
jiao: '#00FF00'
|
||||
}
|
||||
},
|
||||
icon: {
|
||||
pay: '',
|
||||
refund: '',
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Schema as Pay } from './Pay';
|
|||
export interface Schema extends EntityShape {
|
||||
wpAccount: WpAccount;
|
||||
type: 'native' | 'mp' | 'jsapi' | 'h5' | 'app';
|
||||
taxlossRatio?: Decimal<4, 2>;
|
||||
taxLossRatio?: Decimal<4, 2>;
|
||||
application: Application;
|
||||
enabled: Boolean;
|
||||
pays: Pay[];
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export const entityDesc = {
|
|||
type: '类型',
|
||||
application: '关联应用',
|
||||
enabled: '有效中',
|
||||
taxlossRatio: '产品手续费(百分比)',
|
||||
taxLossRatio: '产品手续费(百分比)',
|
||||
pays: '支付',
|
||||
},
|
||||
v: {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export default class Pay extends Feature {
|
|||
}
|
||||
calcDepositLoss(price, channel) {
|
||||
const { entity, entityId } = channel;
|
||||
return getDepositLoss(price, entity, entityId, this.application.getApplication());
|
||||
return getDepositLoss(price, this.application.getApplication());
|
||||
}
|
||||
getDepositRatio(channel) {
|
||||
throw new Error('method not implemented');
|
||||
|
|
|
|||
|
|
@ -58,7 +58,9 @@
|
|||
},
|
||||
"deposit": {
|
||||
"lossReason": {
|
||||
"ratio": "按百分比%{value}%扣除"
|
||||
"ratio": "按百分比%{value}%扣除",
|
||||
"highest": "按单笔充值最高手续费%{value}扣除",
|
||||
"lowest": "按单笔充值最低手续费%{value}扣除"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,18 @@
|
|||
import { Q_DateValue, Q_NumberValue, Q_StringValue, Q_EnumValue, NodeId, MakeFilter, ExprOp, ExpressionKey } from "oak-domain/lib/types/Demand";
|
||||
import { Q_DateValue, Q_NumberValue, Q_StringValue, NodeId, MakeFilter, ExprOp, ExpressionKey } from "oak-domain/lib/types/Demand";
|
||||
import { OneOf } from "oak-domain/lib/types/Polyfill";
|
||||
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/Entity";
|
||||
import { Action, ParticularAction } from "./Action";
|
||||
import { Decimal, Int } from "oak-domain/lib/types/DataType";
|
||||
export type OpSchema = EntityShape & {
|
||||
taxlossRatio: Decimal<4, 2>;
|
||||
depositLossRatio?: Decimal<4, 2> | null;
|
||||
taxLossRatio: Decimal<4, 2>;
|
||||
refundGapDays?: Int<4> | null;
|
||||
refundLossRatio?: Decimal<4, 2> | null;
|
||||
refundLossFloor?: ("yuan" | "jiao") | null;
|
||||
refundCompensateRatio?: Int<4> | null;
|
||||
};
|
||||
export type OpAttr = keyof OpSchema;
|
||||
export type Schema = EntityShape & {
|
||||
taxlossRatio: Decimal<4, 2>;
|
||||
depositLossRatio?: Decimal<4, 2> | null;
|
||||
taxLossRatio: Decimal<4, 2>;
|
||||
refundGapDays?: Int<4> | null;
|
||||
refundLossRatio?: Decimal<4, 2> | null;
|
||||
refundLossFloor?: ("yuan" | "jiao") | null;
|
||||
refundCompensateRatio?: Int<4> | null;
|
||||
} & {
|
||||
[A in ExpressionKey]?: any;
|
||||
};
|
||||
|
|
@ -25,11 +21,9 @@ type AttrFilter = {
|
|||
$$createAt$$: Q_DateValue;
|
||||
$$seq$$: Q_NumberValue;
|
||||
$$updateAt$$: Q_DateValue;
|
||||
taxlossRatio: Q_NumberValue;
|
||||
depositLossRatio: Q_NumberValue;
|
||||
taxLossRatio: Q_NumberValue;
|
||||
refundGapDays: Q_NumberValue;
|
||||
refundLossRatio: Q_NumberValue;
|
||||
refundLossFloor: Q_EnumValue<"yuan" | "jiao">;
|
||||
refundCompensateRatio: Q_NumberValue;
|
||||
};
|
||||
export type Filter = MakeFilter<AttrFilter & ExprOp<OpAttr | string>>;
|
||||
export type Projection = {
|
||||
|
|
@ -39,11 +33,9 @@ export type Projection = {
|
|||
$$createAt$$?: number;
|
||||
$$updateAt$$?: number;
|
||||
$$seq$$?: number;
|
||||
taxlossRatio?: number;
|
||||
depositLossRatio?: number;
|
||||
taxLossRatio?: number;
|
||||
refundGapDays?: number;
|
||||
refundLossRatio?: number;
|
||||
refundLossFloor?: number;
|
||||
refundCompensateRatio?: number;
|
||||
} & Partial<ExprOp<OpAttr | string>>;
|
||||
type AbstractAccountIdProjection = OneOf<{
|
||||
id: number;
|
||||
|
|
@ -57,15 +49,11 @@ export type SortAttr = {
|
|||
} | {
|
||||
$$updateAt$$: number;
|
||||
} | {
|
||||
taxlossRatio: number;
|
||||
} | {
|
||||
depositLossRatio: number;
|
||||
taxLossRatio: number;
|
||||
} | {
|
||||
refundGapDays: number;
|
||||
} | {
|
||||
refundLossRatio: number;
|
||||
} | {
|
||||
refundLossFloor: number;
|
||||
refundCompensateRatio: number;
|
||||
} | {
|
||||
[k: string]: any;
|
||||
} | OneOf<ExprOp<OpAttr | string>>;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { actions } from "./Action";
|
||||
export const desc = {
|
||||
attributes: {
|
||||
taxlossRatio: {
|
||||
taxLossRatio: {
|
||||
notNull: true,
|
||||
type: "decimal",
|
||||
params: {
|
||||
|
|
@ -9,13 +9,6 @@ export const desc = {
|
|||
scale: 2
|
||||
}
|
||||
},
|
||||
depositLossRatio: {
|
||||
type: "decimal",
|
||||
params: {
|
||||
precision: 4,
|
||||
scale: 2
|
||||
}
|
||||
},
|
||||
refundGapDays: {
|
||||
type: "int",
|
||||
params: {
|
||||
|
|
@ -23,16 +16,12 @@ export const desc = {
|
|||
signed: true
|
||||
}
|
||||
},
|
||||
refundLossRatio: {
|
||||
type: "decimal",
|
||||
refundCompensateRatio: {
|
||||
type: "int",
|
||||
params: {
|
||||
precision: 4,
|
||||
scale: 2
|
||||
width: 4,
|
||||
signed: true
|
||||
}
|
||||
},
|
||||
refundLossFloor: {
|
||||
type: "enum",
|
||||
enumeration: ["yuan", "jiao"]
|
||||
}
|
||||
},
|
||||
actionType: "crud",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
export const style = {
|
||||
color: {
|
||||
refundLossFloor: {
|
||||
yuan: '#FFFF00',
|
||||
jiao: '#00FF00'
|
||||
}
|
||||
},
|
||||
icon: {
|
||||
pay: '',
|
||||
refund: '',
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{ "name": "抽象支付帐号", "attr": { "taxlossRatio": "渠道手续费(百分比)", "depositLossRatio": "充值损耗百分比", "refundGapDays": "(支付后)允许退款的天数", "refundLossRatio": "退款损耗百分比", "refundLossFloor": "退款向下取整位数" }, "v": { "refundLossFloor": { "yuan": "元", "jiao": "角" } }, "action": { "pay": "支付", "refund": "退款", "deposit": "充值", "withdraw": "提现", "tax": "渠道费" } }
|
||||
{ "name": "抽象支付帐号", "attr": { "taxLossRatio": "渠道手续费(百分比)", "refundGapDays": "(支付后)允许退款的天数", "refundCompensateRatio": "退款补偿百分比" }, "action": { "pay": "支付", "refund": "退款", "deposit": "充值", "withdraw": "提现", "tax": "渠道费" } }
|
||||
|
|
|
|||
|
|
@ -155,7 +155,6 @@ export type Sorter = SortNode[];
|
|||
export type SelectOperation<P extends Object = Projection> = OakSelection<"select", P, Filter, Sorter>;
|
||||
export type Selection<P extends Object = Projection> = SelectOperation<P>;
|
||||
export type Aggregation = DeduceAggregation<Projection, Filter, Sorter>;
|
||||
<<<<<<< HEAD
|
||||
export type CreateOperationData = FormCreateData<Omit<OpSchema, "entity" | "entityId" | "ofSystemId">> & (({
|
||||
ofSystemId?: never;
|
||||
ofSystem: System.CreateSingleOperation;
|
||||
|
|
@ -166,9 +165,6 @@ export type CreateOperationData = FormCreateData<Omit<OpSchema, "entity" | "enti
|
|||
ofSystem?: never;
|
||||
ofSystemId: ForeignKey<"ofSystem">;
|
||||
})) & ({
|
||||
=======
|
||||
export type CreateOperationData = FormCreateData<Omit<OpSchema, "entity" | "entityId" | "ofSystemId">> & ({
|
||||
>>>>>>> 99d2876ae88266ffcff6aa944c537941daeab7ce
|
||||
entity?: never;
|
||||
entityId?: never;
|
||||
system: System.CreateSingleOperation;
|
||||
|
|
@ -205,7 +201,6 @@ export type CreateOperationData = FormCreateData<Omit<OpSchema, "entity" | "enti
|
|||
export type CreateSingleOperation = OakOperation<"create", CreateOperationData>;
|
||||
export type CreateMultipleOperation = OakOperation<"create", Array<CreateOperationData>>;
|
||||
export type CreateOperation = CreateSingleOperation | CreateMultipleOperation;
|
||||
<<<<<<< HEAD
|
||||
export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity" | "entityId" | "ofSystemId">> & (({
|
||||
ofSystem?: System.CreateSingleOperation;
|
||||
ofSystemId?: never;
|
||||
|
|
@ -223,13 +218,6 @@ export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity" | "enti
|
|||
entityId?: never;
|
||||
entity?: never;
|
||||
} | {
|
||||
=======
|
||||
export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity" | "entityId" | "ofSystemId">> & ({
|
||||
system?: System.CreateSingleOperation | System.UpdateOperation | System.RemoveOperation;
|
||||
entityId?: never;
|
||||
entity?: never;
|
||||
} | {
|
||||
>>>>>>> 99d2876ae88266ffcff6aa944c537941daeab7ce
|
||||
user?: User.CreateSingleOperation | User.UpdateOperation | User.RemoveOperation;
|
||||
entityId?: never;
|
||||
entity?: never;
|
||||
|
|
@ -246,13 +234,9 @@ export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity" | "enti
|
|||
pay$entity?: OakOperation<Pay.UpdateOperation["action"], Omit<Pay.UpdateOperationData, "entity" | "entityId">, Omit<Pay.Filter, "entity" | "entityId">> | OakOperation<Pay.RemoveOperation["action"], Omit<Pay.RemoveOperationData, "entity" | "entityId">, Omit<Pay.Filter, "entity" | "entityId">> | OakOperation<"create", Omit<Pay.CreateOperationData, "entity" | "entityId">[]> | Array<OakOperation<"create", Omit<Pay.CreateOperationData, "entity" | "entityId">> | OakOperation<Pay.UpdateOperation["action"], Omit<Pay.UpdateOperationData, "entity" | "entityId">, Omit<Pay.Filter, "entity" | "entityId">> | OakOperation<Pay.RemoveOperation["action"], Omit<Pay.RemoveOperationData, "entity" | "entityId">, Omit<Pay.Filter, "entity" | "entityId">>>;
|
||||
};
|
||||
export type UpdateOperation = OakOperation<"update" | ParticularAction | string, UpdateOperationData, Filter, Sorter>;
|
||||
<<<<<<< HEAD
|
||||
export type RemoveOperationData = {} & (({
|
||||
ofSystem?: System.UpdateOperation | System.RemoveOperation;
|
||||
})) & ({
|
||||
=======
|
||||
export type RemoveOperationData = {} & ({
|
||||
>>>>>>> 99d2876ae88266ffcff6aa944c537941daeab7ce
|
||||
system?: System.UpdateOperation | System.RemoveOperation;
|
||||
} | {
|
||||
user?: User.UpdateOperation | User.RemoveOperation;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import * as Account from "../Account/Schema";
|
|||
import * as Deposit from "../Deposit/Schema";
|
||||
import * as Pay from "../Pay/Schema";
|
||||
import * as Withdraw from "../Withdraw/Schema";
|
||||
type Type = "deposit" | "withdraw" | "consume" | "loan" | "repay" | "withdrawBack" | "earn" | "encash" | "cutoffRefundable";
|
||||
type Type = "deposit" | "withdraw" | "consume" | "loan" | "repay" | "withdrawBack" | "earn" | "encash" | "cutoffRefundable" | "tax";
|
||||
export type OpSchema = EntityShape & {
|
||||
accountId: ForeignKey<"account">;
|
||||
type: Type;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const desc = {
|
|||
type: {
|
||||
notNull: true,
|
||||
type: "enum",
|
||||
enumeration: ["deposit", "withdraw", "consume", "loan", "repay", "withdrawBack", "earn", "encash", "cutoffRefundable"]
|
||||
enumeration: ["deposit", "withdraw", "consume", "loan", "repay", "withdrawBack", "earn", "encash", "cutoffRefundable", "tax"]
|
||||
},
|
||||
totalPlus: {
|
||||
notNull: true,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ export const style = {
|
|||
repay: '#82E0AA',
|
||||
earn: '#FF3333',
|
||||
encash: '#FF3399',
|
||||
tax: '#A569BD',
|
||||
cutoffRefundable: '#2E4053',
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{ "name": "帐号操作", "attr": { "account": "帐号", "type": "类型", "totalPlus": "余额变化", "availPlus": "可用余额变化", "refundablePlus": "可退款余额变化", "entity": "关联对象", "entityId": "关联对象Id" }, "v": { "type": { "deposit": "充值", "withdraw": "提现", "consume": "消费", "loan": "抵押", "repay": "偿还", "withdrawBack": "提现失败", "earn": "赚取", "encash": "兑现", "cutoffRefundable": "削减可自由退额度" } } }
|
||||
{ "name": "帐号操作", "attr": { "account": "帐号", "type": "类型", "totalPlus": "余额变化", "availPlus": "可用余额变化", "refundablePlus": "可退款余额变化", "entity": "关联对象", "entityId": "关联对象Id" }, "v": { "type": { "deposit": "充值", "withdraw": "提现", "consume": "消费", "loan": "抵押", "repay": "偿还", "withdrawBack": "提现失败", "earn": "赚取", "encash": "兑现", "tax": "渠道费", "cutoffRefundable": "削减可自由退额度" } } }
|
||||
|
|
|
|||
|
|
@ -3,24 +3,16 @@ import { Q_DateValue, Q_BooleanValue, Q_NumberValue, Q_StringValue, Q_EnumValue,
|
|||
import { OneOf } from "oak-domain/lib/types/Polyfill";
|
||||
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, AggregationResult, EntityShape } from "oak-domain/lib/types/Entity";
|
||||
import { Action, ParticularAction } from "./Action";
|
||||
<<<<<<< HEAD
|
||||
import { Decimal, Int, String, Text, Boolean, Price } from "oak-domain/lib/types/DataType";
|
||||
=======
|
||||
import { String, Decimal, Text, Boolean, Price } from "oak-domain/lib/types/DataType";
|
||||
>>>>>>> 99d2876ae88266ffcff6aa944c537941daeab7ce
|
||||
import * as System from "../System/Schema";
|
||||
import * as Pay from "../Pay/Schema";
|
||||
import * as SysAccountOper from "../SysAccountOper/Schema";
|
||||
export type OpSchema = EntityShape & {
|
||||
taxlossRatio: Decimal<4, 2>;
|
||||
depositLossRatio?: Decimal<4, 2> | null;
|
||||
taxLossRatio: Decimal<4, 2>;
|
||||
refundGapDays?: Int<4> | null;
|
||||
refundLossRatio?: Decimal<4, 2> | null;
|
||||
refundLossFloor?: ("yuan" | "jiao") | null;
|
||||
refundCompensateRatio?: Int<4> | null;
|
||||
type: "bank" | "alipay" | "wechat" | "shouqianba" | "others";
|
||||
channel?: String<32> | null;
|
||||
taxlossRatio?: Decimal<4, 2> | null;
|
||||
depositLossRatio?: Decimal<4, 2> | null;
|
||||
name?: String<64> | null;
|
||||
qrCode?: Text | null;
|
||||
allowDeposit: Boolean;
|
||||
|
|
@ -31,15 +23,11 @@ export type OpSchema = EntityShape & {
|
|||
};
|
||||
export type OpAttr = keyof OpSchema;
|
||||
export type Schema = EntityShape & {
|
||||
taxlossRatio: Decimal<4, 2>;
|
||||
depositLossRatio?: Decimal<4, 2> | null;
|
||||
taxLossRatio: Decimal<4, 2>;
|
||||
refundGapDays?: Int<4> | null;
|
||||
refundLossRatio?: Decimal<4, 2> | null;
|
||||
refundLossFloor?: ("yuan" | "jiao") | null;
|
||||
refundCompensateRatio?: Int<4> | null;
|
||||
type: "bank" | "alipay" | "wechat" | "shouqianba" | "others";
|
||||
channel?: String<32> | null;
|
||||
taxlossRatio?: Decimal<4, 2> | null;
|
||||
depositLossRatio?: Decimal<4, 2> | null;
|
||||
name?: String<64> | null;
|
||||
qrCode?: Text | null;
|
||||
allowDeposit: Boolean;
|
||||
|
|
@ -60,15 +48,11 @@ type AttrFilter = {
|
|||
$$createAt$$: Q_DateValue;
|
||||
$$seq$$: Q_NumberValue;
|
||||
$$updateAt$$: Q_DateValue;
|
||||
taxlossRatio: Q_NumberValue;
|
||||
depositLossRatio: Q_NumberValue;
|
||||
taxLossRatio: Q_NumberValue;
|
||||
refundGapDays: Q_NumberValue;
|
||||
refundLossRatio: Q_NumberValue;
|
||||
refundLossFloor: Q_EnumValue<"yuan" | "jiao">;
|
||||
refundCompensateRatio: Q_NumberValue;
|
||||
type: Q_EnumValue<"bank" | "alipay" | "wechat" | "shouqianba" | "others">;
|
||||
channel: Q_StringValue;
|
||||
taxlossRatio: Q_NumberValue;
|
||||
depositLossRatio: Q_NumberValue;
|
||||
name: Q_StringValue;
|
||||
qrCode: Q_StringValue;
|
||||
allowDeposit: Q_BooleanValue;
|
||||
|
|
@ -88,15 +72,11 @@ export type Projection = {
|
|||
$$createAt$$?: number;
|
||||
$$updateAt$$?: number;
|
||||
$$seq$$?: number;
|
||||
taxlossRatio?: number;
|
||||
depositLossRatio?: number;
|
||||
taxLossRatio?: number;
|
||||
refundGapDays?: number;
|
||||
refundLossRatio?: number;
|
||||
refundLossFloor?: number;
|
||||
refundCompensateRatio?: number;
|
||||
type?: number;
|
||||
channel?: number;
|
||||
taxlossRatio?: number;
|
||||
depositLossRatio?: number;
|
||||
name?: number;
|
||||
qrCode?: number;
|
||||
allowDeposit?: number;
|
||||
|
|
@ -133,23 +113,15 @@ export type SortAttr = {
|
|||
} | {
|
||||
$$updateAt$$: number;
|
||||
} | {
|
||||
taxlossRatio: number;
|
||||
} | {
|
||||
depositLossRatio: number;
|
||||
taxLossRatio: number;
|
||||
} | {
|
||||
refundGapDays: number;
|
||||
} | {
|
||||
refundLossRatio: number;
|
||||
} | {
|
||||
refundLossFloor: number;
|
||||
refundCompensateRatio: number;
|
||||
} | {
|
||||
type: number;
|
||||
} | {
|
||||
channel: number;
|
||||
} | {
|
||||
taxlossRatio: number;
|
||||
} | {
|
||||
depositLossRatio: number;
|
||||
} | {
|
||||
name: number;
|
||||
} | {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { actions } from "./Action";
|
||||
export const desc = {
|
||||
attributes: {
|
||||
taxlossRatio: {
|
||||
taxLossRatio: {
|
||||
notNull: true,
|
||||
type: "decimal",
|
||||
params: {
|
||||
|
|
@ -9,13 +9,6 @@ export const desc = {
|
|||
scale: 2
|
||||
}
|
||||
},
|
||||
depositLossRatio: {
|
||||
type: "decimal",
|
||||
params: {
|
||||
precision: 4,
|
||||
scale: 2
|
||||
}
|
||||
},
|
||||
refundGapDays: {
|
||||
type: "int",
|
||||
params: {
|
||||
|
|
@ -23,17 +16,13 @@ export const desc = {
|
|||
signed: true
|
||||
}
|
||||
},
|
||||
refundLossRatio: {
|
||||
type: "decimal",
|
||||
refundCompensateRatio: {
|
||||
type: "int",
|
||||
params: {
|
||||
precision: 4,
|
||||
scale: 2
|
||||
width: 4,
|
||||
signed: true
|
||||
}
|
||||
},
|
||||
refundLossFloor: {
|
||||
type: "enum",
|
||||
enumeration: ["yuan", "jiao"]
|
||||
},
|
||||
type: {
|
||||
notNull: true,
|
||||
type: "enum",
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{ "name": "线下账户", "attr": { "type": "类型", "channel": "通道", "name": "用户/帐号", "qrCode": "收款二维码", "taxlossRatio": "商户号手续费(百分比)", "depositLossRatio": "充值损耗百分比", "refundGapDays": "(支付后)允许退款的天数", "refundLossRatio": "退款损耗百分比", "refundLossFloor": "退款向下取整位数", "allowDeposit": "允许主动充值", "allowPay": "允许主动支付", "system": "所属系统", "price": "余额", "pays": "支付", "opers": "操作记录", "enabled": "是否启用" }, "v": { "type": { "bank": "银行", "alipay": "支付宝", "wechat": "微信", "shouqianba": "收钱吧", "others": "其它" } }, "action": { "pay": "支付", "refund": "退款", "deposit": "充值", "withdraw": "提现", "tax": "渠道费" } }
|
||||
{ "name": "线下账户", "attr": { "type": "类型", "channel": "通道", "name": "用户/帐号", "qrCode": "收款二维码", "taxLossRatio": "商户号手续费(百分比)", "refundCompensateRatio": "退款补偿百分比", "refundGapDays": "(支付后)允许退款的天数", "allowDeposit": "允许主动充值", "allowPay": "允许主动支付", "system": "所属系统", "price": "余额", "pays": "支付", "opers": "操作记录", "enabled": "是否启用" }, "v": { "type": { "bank": "银行", "alipay": "支付宝", "wechat": "微信", "shouqianba": "收钱吧", "others": "其它" } }, "action": { "pay": "支付", "refund": "退款", "deposit": "充值", "withdraw": "提现", "tax": "渠道费" } }
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export type OpSchema = EntityShape & {
|
|||
entity: "account" | "offlineAccount" | "wpProduct" | string;
|
||||
entityId: String<64>;
|
||||
timeoutAt?: Datetime | null;
|
||||
successAt?: Datetime | null;
|
||||
forbidRefundAt?: Datetime | null;
|
||||
refundable: Boolean;
|
||||
depositId?: ForeignKey<"deposit"> | null;
|
||||
|
|
@ -43,6 +44,7 @@ export type Schema = EntityShape & {
|
|||
entity: "account" | "offlineAccount" | "wpProduct" | string;
|
||||
entityId: String<64>;
|
||||
timeoutAt?: Datetime | null;
|
||||
successAt?: Datetime | null;
|
||||
forbidRefundAt?: Datetime | null;
|
||||
refundable: Boolean;
|
||||
depositId?: ForeignKey<"deposit"> | null;
|
||||
|
|
@ -83,6 +85,7 @@ type AttrFilter = {
|
|||
entity: Q_EnumValue<"account" | "offlineAccount" | "wpProduct" | string>;
|
||||
entityId: Q_StringValue;
|
||||
timeoutAt: Q_DateValue;
|
||||
successAt: Q_DateValue;
|
||||
forbidRefundAt: Q_DateValue;
|
||||
refundable: Q_BooleanValue;
|
||||
depositId: Q_StringValue;
|
||||
|
|
@ -121,6 +124,7 @@ export type Projection = {
|
|||
entity?: number;
|
||||
entityId?: number;
|
||||
timeoutAt?: number;
|
||||
successAt?: number;
|
||||
forbidRefundAt?: number;
|
||||
refundable?: number;
|
||||
depositId?: number;
|
||||
|
|
@ -204,6 +208,8 @@ export type SortAttr = {
|
|||
entityId: number;
|
||||
} | {
|
||||
timeoutAt: number;
|
||||
} | {
|
||||
successAt: number;
|
||||
} | {
|
||||
forbidRefundAt: number;
|
||||
} | {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ export const desc = {
|
|||
timeoutAt: {
|
||||
type: "datetime"
|
||||
},
|
||||
successAt: {
|
||||
type: "datetime"
|
||||
},
|
||||
forbidRefundAt: {
|
||||
type: "datetime"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{ "name": "订单", "attr": { "price": "应支付金额", "paid": "已支付金额", "refunded": "已退款金额", "iState": "支付状态", "entity": "支付渠道", "entityId": "支付渠道id", "order": "所属订单", "deposit": "充值", "timeoutAt": "过期时间", "forbidRefundAt": "停止退款时间", "refundable": "是否可退款", "meta": "支付metadata", "externalId": "外部订单Id", "opers": "被关联帐户操作", "application": "关联应用", "creator": "创建者", "phantom1": "索引项一", "phantom2": "索引项二", "phantom3": "索引项三", "phantom4": "索引项四" }, "action": { "startPaying": "开始支付", "continuePaying": "继续支付", "succeedPaying": "支付成功", "close": "关闭", "startRefunding": "开始退款", "refundAll": "完全退款", "refundPartially": "部分退款", "closeRefund": "禁止退款", "stopRefunding": "停止退款" }, "v": { "iState": { "unpaid": "待付款", "paying": "支付中", "paid": "已付款", "closed": "已关闭", "refunding": "退款中", "refunded": "已退款", "partiallyRefunded": "已部分退款" } } }
|
||||
{ "name": "订单", "attr": { "price": "应支付金额", "paid": "已支付金额", "refunded": "已退款金额", "iState": "支付状态", "entity": "支付渠道", "entityId": "支付渠道id", "order": "所属订单", "deposit": "充值", "timeoutAt": "过期时间", "successAt": "完成时间", "forbidRefundAt": "停止退款时间", "refundable": "是否可退款", "meta": "支付metadata", "externalId": "外部订单Id", "opers": "被关联帐户操作", "application": "关联应用", "creator": "创建者", "phantom1": "索引项一", "phantom2": "索引项二", "phantom3": "索引项三", "phantom4": "索引项四" }, "action": { "startPaying": "开始支付", "continuePaying": "继续支付", "succeedPaying": "支付成功", "close": "关闭", "startRefunding": "开始退款", "refundAll": "完全退款", "refundPartially": "部分退款", "closeRefund": "禁止退款", "stopRefunding": "停止退款" }, "v": { "iState": { "unpaid": "待付款", "paying": "支付中", "paid": "已付款", "closed": "已关闭", "refunding": "退款中", "refunded": "已退款", "partiallyRefunded": "已部分退款" } } }
|
||||
|
|
|
|||
|
|
@ -18,6 +18,20 @@ import * as WechatPay from "../WechatPay/Schema";
|
|||
import * as WithdrawAccount from "../WithdrawAccount/Schema";
|
||||
import * as WithdrawChannel from "../WithdrawChannel/Schema";
|
||||
import * as WpAccount from "../WpAccount/Schema";
|
||||
type PayConfig = {
|
||||
withdrawLoss: {
|
||||
conservative: boolean;
|
||||
ratio?: number;
|
||||
lowest?: number;
|
||||
highest?: number;
|
||||
trim?: "jiao" | "yuan";
|
||||
};
|
||||
depositLoss: {
|
||||
ratio?: number;
|
||||
lowest?: number;
|
||||
highest?: number;
|
||||
};
|
||||
};
|
||||
export type OpSchema = EntityShape & {
|
||||
name: String<32>;
|
||||
description: Text;
|
||||
|
|
@ -28,6 +42,7 @@ export type OpSchema = EntityShape & {
|
|||
style?: Style | null;
|
||||
entity?: String<32> | null;
|
||||
entityId?: String<64> | null;
|
||||
payConfig?: PayConfig | null;
|
||||
};
|
||||
export type OpAttr = keyof OpSchema;
|
||||
export type Schema = EntityShape & {
|
||||
|
|
@ -40,6 +55,7 @@ export type Schema = EntityShape & {
|
|||
style?: Style | null;
|
||||
entity?: String<32> | null;
|
||||
entityId?: String<64> | null;
|
||||
payConfig?: PayConfig | null;
|
||||
platform?: Platform.Schema | null;
|
||||
application$system?: Array<Application.Schema>;
|
||||
application$system$$aggr?: AggregationResult<Application.Schema>;
|
||||
|
|
@ -85,6 +101,7 @@ type AttrFilter = {
|
|||
style: JsonFilter<Style>;
|
||||
entity: Q_StringValue;
|
||||
entityId: Q_StringValue;
|
||||
payConfig: JsonFilter<PayConfig>;
|
||||
application$system: Application.Filter & SubQueryPredicateMetadata;
|
||||
domain$system: Domain.Filter & SubQueryPredicateMetadata;
|
||||
messageSystem$system: MessageSystem.Filter & SubQueryPredicateMetadata;
|
||||
|
|
@ -117,6 +134,7 @@ export type Projection = {
|
|||
style?: number | JsonProjection<Style>;
|
||||
entity?: number;
|
||||
entityId?: number;
|
||||
payConfig?: number | JsonProjection<PayConfig>;
|
||||
application$system?: Application.Selection & {
|
||||
$entity: "application";
|
||||
};
|
||||
|
|
@ -230,6 +248,8 @@ export type SortAttr = {
|
|||
entity: number;
|
||||
} | {
|
||||
entityId: number;
|
||||
} | {
|
||||
payConfig: number;
|
||||
} | {
|
||||
[k: string]: any;
|
||||
} | OneOf<ExprOp<OpAttr | string>>;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ export const desc = {
|
|||
super: {
|
||||
type: "boolean"
|
||||
},
|
||||
style: {
|
||||
style // 如果为true,则按照渠道taxLossRatio和refundCompensateRatio进行扣取(如果因为depositLossRatio已经大于taxLossRatio,则全额退款)
|
||||
: {
|
||||
type: "object"
|
||||
},
|
||||
entity: {
|
||||
|
|
@ -44,6 +45,9 @@ export const desc = {
|
|||
params: {
|
||||
length: 64
|
||||
}
|
||||
},
|
||||
payConfig: {
|
||||
type: "object"
|
||||
}
|
||||
},
|
||||
actionType: "crud",
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{ "name": "系统", "attr": { "name": "名称", "description": "描述", "config": "设置", "platform": "平台", "super": "超级系统", "folder": "代码目录名", "style": "样式", "entity": "关联对象", "entityId": "关联对象id", "accounts": "关联账户", "withdrawAccounts": "关联提现账户" } }
|
||||
{ "name": "系统", "attr": { "name": "名称", "description": "描述", "config": "设置", "payConfig": "支付相关设置", "platform": "平台", "super": "超级系统", "folder": "代码目录名", "style": "样式", "entity": "关联对象", "entityId": "关联对象id", "accounts": "关联账户", "withdrawAccounts": "关联提现账户" } }
|
||||
|
|
|
|||
|
|
@ -164,7 +164,6 @@ export type SelectOperation<P extends Object = Projection> = OakSelection<"selec
|
|||
export type Selection<P extends Object = Projection> = SelectOperation<P>;
|
||||
export type Aggregation = DeduceAggregation<Projection, Filter, Sorter>;
|
||||
export type CreateOperationData = FormCreateData<Omit<OpSchema, "entity" | "entityId" | "ofSystemId" | "channelId">> & (({
|
||||
<<<<<<< HEAD
|
||||
ofSystemId?: never;
|
||||
ofSystem: System.CreateSingleOperation;
|
||||
} | {
|
||||
|
|
@ -174,8 +173,6 @@ export type CreateOperationData = FormCreateData<Omit<OpSchema, "entity" | "enti
|
|||
ofSystem?: never;
|
||||
ofSystemId: ForeignKey<"ofSystem">;
|
||||
}) & ({
|
||||
=======
|
||||
>>>>>>> 99d2876ae88266ffcff6aa944c537941daeab7ce
|
||||
channelId?: never;
|
||||
channel: WithdrawChannel.CreateSingleOperation;
|
||||
} | {
|
||||
|
|
@ -221,7 +218,6 @@ export type CreateSingleOperation = OakOperation<"create", CreateOperationData>;
|
|||
export type CreateMultipleOperation = OakOperation<"create", Array<CreateOperationData>>;
|
||||
export type CreateOperation = CreateSingleOperation | CreateMultipleOperation;
|
||||
export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity" | "entityId" | "ofSystemId" | "channelId">> & (({
|
||||
<<<<<<< HEAD
|
||||
ofSystem?: System.CreateSingleOperation;
|
||||
ofSystemId?: never;
|
||||
} | {
|
||||
|
|
@ -234,8 +230,6 @@ export type UpdateOperationData = FormUpdateData<Omit<OpSchema, "entity" | "enti
|
|||
ofSystem?: never;
|
||||
ofSystemId?: ForeignKey<"ofSystem">;
|
||||
}) & ({
|
||||
=======
|
||||
>>>>>>> 99d2876ae88266ffcff6aa944c537941daeab7ce
|
||||
channel?: WithdrawChannel.CreateSingleOperation;
|
||||
channelId?: never;
|
||||
} | {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { ForeignKey } from "oak-domain/lib/types/DataType";
|
||||
import { Q_DateValue, Q_BooleanValue, Q_NumberValue, Q_StringValue, Q_EnumValue, NodeId, MakeFilter, ExprOp, ExpressionKey, SubQueryPredicateMetadata } from "oak-domain/lib/types/Demand";
|
||||
import { Q_DateValue, Q_BooleanValue, Q_NumberValue, Q_StringValue, NodeId, MakeFilter, ExprOp, ExpressionKey, SubQueryPredicateMetadata } from "oak-domain/lib/types/Demand";
|
||||
import { OneOf } from "oak-domain/lib/types/Polyfill";
|
||||
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, AggregationResult, EntityShape } from "oak-domain/lib/types/Entity";
|
||||
import { Action, ParticularAction } from "./Action";
|
||||
|
|
@ -11,11 +11,9 @@ import * as ModiEntity from "../ModiEntity/Schema";
|
|||
import * as OperEntity from "../OperEntity/Schema";
|
||||
import * as SysAccountOper from "../SysAccountOper/Schema";
|
||||
export type OpSchema = EntityShape & {
|
||||
taxlossRatio: Decimal<4, 2>;
|
||||
depositLossRatio?: Decimal<4, 2> | null;
|
||||
taxLossRatio: Decimal<4, 2>;
|
||||
refundGapDays?: Int<4> | null;
|
||||
refundLossRatio?: Decimal<4, 2> | null;
|
||||
refundLossFloor?: ("yuan" | "jiao") | null;
|
||||
refundCompensateRatio?: Int<4> | null;
|
||||
wechatPayId: ForeignKey<"wechatPay">;
|
||||
mchId: String<128>;
|
||||
publicKeyFilePath: Text;
|
||||
|
|
@ -27,11 +25,9 @@ export type OpSchema = EntityShape & {
|
|||
};
|
||||
export type OpAttr = keyof OpSchema;
|
||||
export type Schema = EntityShape & {
|
||||
taxlossRatio: Decimal<4, 2>;
|
||||
depositLossRatio?: Decimal<4, 2> | null;
|
||||
taxLossRatio: Decimal<4, 2>;
|
||||
refundGapDays?: Int<4> | null;
|
||||
refundLossRatio?: Decimal<4, 2> | null;
|
||||
refundLossFloor?: ("yuan" | "jiao") | null;
|
||||
refundCompensateRatio?: Int<4> | null;
|
||||
wechatPayId: ForeignKey<"wechatPay">;
|
||||
mchId: String<128>;
|
||||
publicKeyFilePath: Text;
|
||||
|
|
@ -58,11 +54,9 @@ type AttrFilter = {
|
|||
$$createAt$$: Q_DateValue;
|
||||
$$seq$$: Q_NumberValue;
|
||||
$$updateAt$$: Q_DateValue;
|
||||
taxlossRatio: Q_NumberValue;
|
||||
depositLossRatio: Q_NumberValue;
|
||||
taxLossRatio: Q_NumberValue;
|
||||
refundGapDays: Q_NumberValue;
|
||||
refundLossRatio: Q_NumberValue;
|
||||
refundLossFloor: Q_EnumValue<"yuan" | "jiao">;
|
||||
refundCompensateRatio: Q_NumberValue;
|
||||
wechatPayId: Q_StringValue;
|
||||
wechatPay: WechatPay.Filter;
|
||||
mchId: Q_StringValue;
|
||||
|
|
@ -86,11 +80,9 @@ export type Projection = {
|
|||
$$createAt$$?: number;
|
||||
$$updateAt$$?: number;
|
||||
$$seq$$?: number;
|
||||
taxlossRatio?: number;
|
||||
depositLossRatio?: number;
|
||||
taxLossRatio?: number;
|
||||
refundGapDays?: number;
|
||||
refundLossRatio?: number;
|
||||
refundLossFloor?: number;
|
||||
refundCompensateRatio?: number;
|
||||
wechatPayId?: number;
|
||||
wechatPay?: WechatPay.Projection;
|
||||
mchId?: number;
|
||||
|
|
@ -144,15 +136,11 @@ export type SortAttr = {
|
|||
} | {
|
||||
$$updateAt$$: number;
|
||||
} | {
|
||||
taxlossRatio: number;
|
||||
} | {
|
||||
depositLossRatio: number;
|
||||
taxLossRatio: number;
|
||||
} | {
|
||||
refundGapDays: number;
|
||||
} | {
|
||||
refundLossRatio: number;
|
||||
} | {
|
||||
refundLossFloor: number;
|
||||
refundCompensateRatio: number;
|
||||
} | {
|
||||
wechatPayId: number;
|
||||
} | {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { actions } from "./Action";
|
||||
export const desc = {
|
||||
attributes: {
|
||||
taxlossRatio: {
|
||||
taxLossRatio: {
|
||||
notNull: true,
|
||||
type: "decimal",
|
||||
params: {
|
||||
|
|
@ -9,13 +9,6 @@ export const desc = {
|
|||
scale: 2
|
||||
}
|
||||
},
|
||||
depositLossRatio: {
|
||||
type: "decimal",
|
||||
params: {
|
||||
precision: 4,
|
||||
scale: 2
|
||||
}
|
||||
},
|
||||
refundGapDays: {
|
||||
type: "int",
|
||||
params: {
|
||||
|
|
@ -23,17 +16,13 @@ export const desc = {
|
|||
signed: true
|
||||
}
|
||||
},
|
||||
refundLossRatio: {
|
||||
type: "decimal",
|
||||
refundCompensateRatio: {
|
||||
type: "int",
|
||||
params: {
|
||||
precision: 4,
|
||||
scale: 2
|
||||
width: 4,
|
||||
signed: true
|
||||
}
|
||||
},
|
||||
refundLossFloor: {
|
||||
type: "enum",
|
||||
enumeration: ["yuan", "jiao"]
|
||||
},
|
||||
wechatPayId: {
|
||||
notNull: true,
|
||||
type: "ref",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
export const style = {
|
||||
color: {
|
||||
refundLossFloor: {
|
||||
yuan: '#FFFF00',
|
||||
jiao: '#00FF00'
|
||||
}
|
||||
},
|
||||
icon: {
|
||||
pay: '',
|
||||
refund: '',
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{ "name": "微信支付帐号", "attr": { "wechatPay": "微信支付", "taxlossRatio": "商户号手续费(百分比)", "depositLossRatio": "充值损耗百分比", "refundGapDays": "(支付后)允许退款的天数", "refundLossRatio": "退款损耗百分比", "refundLossFloor": "退款向下取整位数", "mchId": "商户号", "publicKeyFilePath": "公钥文件路径", "privateKeyFilePath": "私钥文件路径", "apiV3Key": "apiV3Key", "price": "余额", "system": "关联系统", "opers": "操作记录", "enabled": "是否启用" }, "v": { "refundLossFloor": { "yuan": "元", "jiao": "角" } }, "action": { "pay": "支付", "refund": "退款", "deposit": "充值", "withdraw": "提现", "tax": "渠道费" } }
|
||||
{ "name": "微信支付帐号", "attr": { "wechatPay": "微信支付", "taxLossRatio": "商户号手续费(百分比)", "refundCompensateRatio": "退款补偿百分比", "refundGapDays": "(支付后)允许退款的天数", "mchId": "商户号", "publicKeyFilePath": "公钥文件路径", "privateKeyFilePath": "私钥文件路径", "apiV3Key": "apiV3Key", "price": "余额", "system": "关联系统", "opers": "操作记录", "enabled": "是否启用" }, "action": { "pay": "支付", "refund": "退款", "deposit": "充值", "withdraw": "提现", "tax": "渠道费" } }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import * as Pay from "../Pay/Schema";
|
|||
export type OpSchema = EntityShape & {
|
||||
wpAccountId: ForeignKey<"wpAccount">;
|
||||
type: "native" | "mp" | "jsapi" | "h5" | "app";
|
||||
taxlossRatio?: Decimal<4, 2> | null;
|
||||
taxLossRatio?: Decimal<4, 2> | null;
|
||||
applicationId: ForeignKey<"application">;
|
||||
enabled: Boolean;
|
||||
};
|
||||
|
|
@ -20,7 +20,7 @@ export type OpAttr = keyof OpSchema;
|
|||
export type Schema = EntityShape & {
|
||||
wpAccountId: ForeignKey<"wpAccount">;
|
||||
type: "native" | "mp" | "jsapi" | "h5" | "app";
|
||||
taxlossRatio?: Decimal<4, 2> | null;
|
||||
taxLossRatio?: Decimal<4, 2> | null;
|
||||
applicationId: ForeignKey<"application">;
|
||||
enabled: Boolean;
|
||||
wpAccount: WpAccount.Schema;
|
||||
|
|
@ -42,7 +42,7 @@ type AttrFilter = {
|
|||
wpAccountId: Q_StringValue;
|
||||
wpAccount: WpAccount.Filter;
|
||||
type: Q_EnumValue<"native" | "mp" | "jsapi" | "h5" | "app">;
|
||||
taxlossRatio: Q_NumberValue;
|
||||
taxLossRatio: Q_NumberValue;
|
||||
applicationId: Q_StringValue;
|
||||
application: Application.Filter;
|
||||
enabled: Q_BooleanValue;
|
||||
|
|
@ -61,7 +61,7 @@ export type Projection = {
|
|||
wpAccountId?: number;
|
||||
wpAccount?: WpAccount.Projection;
|
||||
type?: number;
|
||||
taxlossRatio?: number;
|
||||
taxLossRatio?: number;
|
||||
applicationId?: number;
|
||||
application?: Application.Projection;
|
||||
enabled?: number;
|
||||
|
|
@ -108,7 +108,7 @@ export type SortAttr = {
|
|||
} | {
|
||||
type: number;
|
||||
} | {
|
||||
taxlossRatio: number;
|
||||
taxLossRatio: number;
|
||||
} | {
|
||||
applicationId: number;
|
||||
} | {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export const desc = {
|
|||
type: "enum",
|
||||
enumeration: ["native", "mp", "jsapi", "h5", "app"]
|
||||
},
|
||||
taxlossRatio: {
|
||||
taxLossRatio: {
|
||||
type: "decimal",
|
||||
params: {
|
||||
precision: 4,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{ "name": "微信支付产品", "attr": { "wpAccount": "微信支付帐号", "type": "类型", "application": "关联应用", "enabled": "有效中", "taxlossRatio": "产品手续费(百分比)", "pays": "支付" }, "v": { "type": { "native": "扫码", "mp": "小程序", "jsapi": "jsApi", "h5": "H5唤起微信", "app": "App" } } }
|
||||
{ "name": "微信支付产品", "attr": { "wpAccount": "微信支付帐号", "type": "类型", "application": "关联应用", "enabled": "有效中", "taxLossRatio": "产品手续费(百分比)", "pays": "支付" }, "v": { "type": { "native": "扫码", "mp": "小程序", "jsapi": "jsApi", "h5": "H5唤起微信", "app": "App" } } }
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import { Trigger } from 'oak-domain/lib/types/Trigger';
|
|||
import { EntityDict } from '../oak-app-domain';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { BRC } from '../types/RuntimeCxt';
|
||||
type CalcPaySysAccountChangeOption<ED extends EntityDict & BaseEntityDict> = {
|
||||
type CalcPayChannelTaxOption<ED extends EntityDict & BaseEntityDict> = {
|
||||
projection: ED['pay']['Selection']['data'];
|
||||
fn: (pay: ED['pay']['Schema']) => [number, string, string];
|
||||
};
|
||||
export declare function registerCalcPaySysAccountChangeOption<ED extends EntityDict & BaseEntityDict>(entity: keyof ED, option: CalcPaySysAccountChangeOption<ED>): void;
|
||||
export declare function registerCalcPayChannelTaxOption<ED extends EntityDict & BaseEntityDict>(entity: keyof ED, option: CalcPayChannelTaxOption<ED>): void;
|
||||
declare const triggers: Trigger<EntityDict, 'pay', BRC>[];
|
||||
export default triggers;
|
||||
|
|
|
|||
|
|
@ -4,44 +4,42 @@ import { getPayClazz } from '../utils/payClazz';
|
|||
import { fullPayProjection } from '../utils/pay';
|
||||
import { DATA_SUBSCRIBER_KEYS } from '../config/constants';
|
||||
import { merge } from 'oak-domain/lib/utils/lodash';
|
||||
const CalcPaySysAccountChangeDict = {
|
||||
const CalcPayChannelTaxDict = {
|
||||
wpProduct: {
|
||||
projection: {
|
||||
wpProduct: {
|
||||
id: 1,
|
||||
taxlossRatio: 1,
|
||||
taxLossRatio: 1,
|
||||
wpAccountId: 1,
|
||||
wpAccount: {
|
||||
id: 1,
|
||||
taxlossRatio: 1,
|
||||
taxLossRatio: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
fn: (pay) => {
|
||||
const { paid, wpProduct } = pay;
|
||||
const taxlossRatio = wpProduct.taxlossRatio || wpProduct.wpAccount.taxlossRatio;
|
||||
assert(typeof taxlossRatio === 'number');
|
||||
const tax = Math.round(paid * taxlossRatio / 100);
|
||||
return [paid - tax, 'wpAccount', wpProduct.wpAccountId];
|
||||
const taxLossRatio = wpProduct.taxLossRatio || wpProduct.wpAccount.taxLossRatio;
|
||||
assert(typeof taxLossRatio === 'number', '微信渠道的手续费率未配置');
|
||||
return [Math.round(paid * taxLossRatio / 100), 'wpAccount', wpProduct.wpAccountId];
|
||||
},
|
||||
},
|
||||
offlineAccount: {
|
||||
projection: {
|
||||
offlineAccount: {
|
||||
id: 1,
|
||||
taxlossRatio: 1,
|
||||
taxLossRatio: 1,
|
||||
},
|
||||
},
|
||||
fn: (pay) => {
|
||||
const { offlineAccount, paid } = pay;
|
||||
const { taxlossRatio } = offlineAccount;
|
||||
const tax = taxlossRatio ? Math.round(paid * taxlossRatio / 100) : 0;
|
||||
return [paid - tax, pay.entity, pay.entityId];
|
||||
const { taxLossRatio } = offlineAccount;
|
||||
return [taxLossRatio ? Math.round(paid * taxLossRatio / 100) : 0, pay.entity, pay.entityId];
|
||||
},
|
||||
},
|
||||
};
|
||||
export function registerCalcPaySysAccountChangeOption(entity, option) {
|
||||
CalcPaySysAccountChangeDict[entity] = option;
|
||||
export function registerCalcPayChannelTaxOption(entity, option) {
|
||||
CalcPayChannelTaxDict[entity] = option;
|
||||
}
|
||||
async function changeOrderStateByPay(filter, context, option) {
|
||||
const orders = await context.select('order', {
|
||||
|
|
@ -227,11 +225,14 @@ const triggers = [
|
|||
price: 1,
|
||||
loss: 1,
|
||||
},
|
||||
application: {
|
||||
systemId: 1,
|
||||
},
|
||||
iState: 1,
|
||||
},
|
||||
filter,
|
||||
}, { dontCollect: true });
|
||||
const { orderId, depositId, iState, deposit } = pay;
|
||||
const { orderId, depositId, iState, deposit, application } = pay;
|
||||
context.saveOperationToEvent(id, `${DATA_SUBSCRIBER_KEYS.payStateChanged}-${filter.id}`);
|
||||
if (orderId) {
|
||||
return await changeOrderStateByPay({ id: orderId }, context, option);
|
||||
|
|
@ -243,24 +244,48 @@ const triggers = [
|
|||
const payPrice = pay.price;
|
||||
const { price, loss } = deposit;
|
||||
assert(price === payPrice);
|
||||
const accountOpers = [
|
||||
{
|
||||
id: await generateNewIdAsync(),
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
totalPlus: price - loss,
|
||||
availPlus: price - loss,
|
||||
refundablePlus: pay.refundable ? price : 0,
|
||||
accountId: deposit.accountId,
|
||||
type: 'deposit',
|
||||
},
|
||||
action: 'create',
|
||||
}
|
||||
];
|
||||
if (loss > 0) {
|
||||
// 如果有loss就充入system的account账户
|
||||
const [account] = await context.select('account', {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: {
|
||||
entity: 'system',
|
||||
entityId: application?.systemId,
|
||||
},
|
||||
}, { dontCollect: true });
|
||||
accountOpers.push({
|
||||
id: await generateNewIdAsync(),
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
totalPlus: loss,
|
||||
availPlus: loss,
|
||||
accountId: account.id,
|
||||
type: 'earn',
|
||||
},
|
||||
action: 'create',
|
||||
});
|
||||
}
|
||||
await context.operate('deposit', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'succeed',
|
||||
data: {
|
||||
accountOper$entity: [
|
||||
{
|
||||
id: await generateNewIdAsync(),
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
totalPlus: price - loss,
|
||||
availPlus: price - loss,
|
||||
refundablePlus: pay.refundable ? price : 0,
|
||||
accountId: deposit.accountId,
|
||||
type: 'deposit',
|
||||
},
|
||||
action: 'create',
|
||||
}
|
||||
]
|
||||
accountOper$entity: accountOpers,
|
||||
},
|
||||
filter: {
|
||||
id: depositId,
|
||||
|
|
@ -381,7 +406,7 @@ const triggers = [
|
|||
},
|
||||
},
|
||||
{
|
||||
name: '当pay完成支付时,修改相应的sys account中的余额',
|
||||
name: '当pay完成支付时,计算相应的account以及syste account中的余额变化',
|
||||
entity: 'pay',
|
||||
action: 'succeedPaying',
|
||||
when: 'after',
|
||||
|
|
@ -395,9 +420,13 @@ const triggers = [
|
|||
entityId: 1,
|
||||
iState: 1,
|
||||
depositId: 1,
|
||||
orderId: 1,
|
||||
application: {
|
||||
systemId: 1,
|
||||
}
|
||||
};
|
||||
for (const key in CalcPaySysAccountChangeDict) {
|
||||
merge(projection, CalcPaySysAccountChangeDict[key].projection);
|
||||
for (const key in CalcPayChannelTaxDict) {
|
||||
merge(projection, CalcPayChannelTaxDict[key].projection);
|
||||
}
|
||||
const pays = await context.select('pay', {
|
||||
data: projection,
|
||||
|
|
@ -405,33 +434,56 @@ const triggers = [
|
|||
}, {});
|
||||
assert(pays.length === 1);
|
||||
const [pay] = pays;
|
||||
const { price, paid, entity, entityId, iState, depositId } = pay;
|
||||
const { price, paid, entity, entityId, iState, application } = pay;
|
||||
assert(iState === 'paid');
|
||||
const option = CalcPaySysAccountChangeDict[entity];
|
||||
let cnt = 0;
|
||||
const option = CalcPayChannelTaxDict[entity];
|
||||
if (option) {
|
||||
const [delta, sysAccountEntity, sysAccountEntityId] = option.fn(pay);
|
||||
if (delta !== 0) {
|
||||
assert(delta > 0);
|
||||
await context.operate('sysAccountOper', {
|
||||
const [tax, sysAccountEntity, sysAccountEntityId] = option.fn(pay);
|
||||
await context.operate('sysAccountOper', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
delta: paid - tax,
|
||||
entity: sysAccountEntity,
|
||||
entityId: sysAccountEntityId,
|
||||
payId: pay.id,
|
||||
type: 'pay',
|
||||
}
|
||||
}, {});
|
||||
if (tax !== 0) {
|
||||
// tax产生的损失由sys account来承担
|
||||
const [account] = await context.select('account', {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: {
|
||||
entity: 'system',
|
||||
entityId: application.systemId,
|
||||
}
|
||||
}, { dontCollect: true });
|
||||
await context.operate('accountOper', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
delta,
|
||||
entity: sysAccountEntity,
|
||||
entityId: sysAccountEntityId,
|
||||
payId: pay.id,
|
||||
type: 'pay',
|
||||
}
|
||||
accountId: account.id,
|
||||
type: 'tax',
|
||||
totalPlus: -tax,
|
||||
availPlus: -tax,
|
||||
entity: 'pay',
|
||||
entityId: pay.id,
|
||||
},
|
||||
}, {});
|
||||
return 1;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
return 0;
|
||||
return cnt;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '当pay的paid达到price,支付成功',
|
||||
name: '当account类型的pay的paid达到price,改为支付成功',
|
||||
entity: 'pay',
|
||||
action: ['startPaying', 'continuePaying'],
|
||||
check(operation) {
|
||||
|
|
@ -461,7 +513,9 @@ const triggers = [
|
|||
await context.operate('pay', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'succeedPaying',
|
||||
data: {},
|
||||
data: {
|
||||
successAt: Date.now(),
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
}
|
||||
|
|
@ -471,5 +525,32 @@ const triggers = [
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '当pay完成支付时,计算其refundable和forbidRefundAt',
|
||||
entity: 'pay',
|
||||
action: 'succeedPaying',
|
||||
when: 'before',
|
||||
fn: async ({ operation }, context) => {
|
||||
const { data, filter } = operation;
|
||||
assert(data.successAt);
|
||||
const pays = await context.select('pay', {
|
||||
data: {
|
||||
id: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
applicationId: 1,
|
||||
},
|
||||
filter
|
||||
}, { dontCollect: true, forUpdate: true });
|
||||
assert(pays.length === 1);
|
||||
const [pay] = pays;
|
||||
const { applicationId, entity, entityId } = pay;
|
||||
const payClazz = await getPayClazz(applicationId, entity, entityId, context);
|
||||
const forbidRefundAt = payClazz.getRefundableAt(data.successAt);
|
||||
data.forbidRefundAt = forbidRefundAt;
|
||||
data.refundable = forbidRefundAt > Date.now();
|
||||
return 1;
|
||||
},
|
||||
},
|
||||
];
|
||||
export default triggers;
|
||||
|
|
|
|||
|
|
@ -7,22 +7,22 @@ const CalcRefundSysAccountChangeDict = {
|
|||
projection: {
|
||||
wpProduct: {
|
||||
id: 1,
|
||||
taxlossRatio: 1,
|
||||
taxLossRatio: 1,
|
||||
wpAccountId: 1,
|
||||
wpAccount: {
|
||||
id: 1,
|
||||
taxlossRatio: 1,
|
||||
taxLossRatio: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
fn: (refund) => {
|
||||
const { price, pay, loss } = refund;
|
||||
const { wpProduct } = pay;
|
||||
const taxlossRatio = wpProduct.taxlossRatio || wpProduct.wpAccount.taxlossRatio;
|
||||
assert(typeof taxlossRatio === 'number');
|
||||
const taxLossRatio = wpProduct.taxLossRatio || wpProduct.wpAccount.taxLossRatio;
|
||||
assert(typeof taxLossRatio === 'number');
|
||||
// 微信支付的退款部分不计手续费(这里计算的不够精细,直接四舍五入可能会产生误差积累)
|
||||
const toRefund = price - loss;
|
||||
const tax = Math.round(toRefund * taxlossRatio / 100);
|
||||
const tax = Math.round(toRefund * taxLossRatio / 100);
|
||||
const price2 = toRefund - tax;
|
||||
return [-price2, 'wpAccount', wpProduct.wpAccountId];
|
||||
},
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export default interface PayClazz {
|
|||
}>;
|
||||
refund(refund: EntityDict['refund']['OpSchema']): Promise<EntityDict['refund']['Update']['data'] | undefined>;
|
||||
closeRefund(refund: EntityDict['refund']['OpSchema']): Promise<void>;
|
||||
getRefundableAt(successAt: number): number;
|
||||
getRefundState(refund: EntityDict['refund']['OpSchema']): Promise<[EntityDict['refund']['OpSchema']['iState'], EntityDict['refund']['Update']['data'] | undefined]>;
|
||||
}
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -11,15 +11,13 @@ export const applicationProjection = {
|
|||
type: 1,
|
||||
wpAccount: {
|
||||
id: 1,
|
||||
depositLossRatio: 1,
|
||||
refundGapDays: 1,
|
||||
refundLossFloor: 1,
|
||||
refundLossRatio: 1,
|
||||
mchId: 1,
|
||||
}
|
||||
},
|
||||
},
|
||||
system: {
|
||||
payConfig: 1,
|
||||
offlineAccount$system: {
|
||||
$entity: 'offlineAccount',
|
||||
data: {
|
||||
|
|
@ -28,13 +26,16 @@ export const applicationProjection = {
|
|||
name: 1,
|
||||
type: 1,
|
||||
allowDeposit: 1,
|
||||
depositLossRatio: 1,
|
||||
refundGapDays: 1,
|
||||
refundLossFloor: 1,
|
||||
refundLossRatio: 1,
|
||||
allowPay: 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
account$entity: {
|
||||
$entity: 'account',
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
export const mergedProjection = merge({}, ogbAppProjection, applicationProjection);
|
||||
|
|
|
|||
|
|
@ -6,15 +6,13 @@ import { IncomingHttpHeaders } from 'http';
|
|||
export declare const fullPayProjection: EntityDict['pay']['Selection']['data'];
|
||||
export declare function payNotify<ED extends EntityDict & BaseEntityDict>(context: BackendRuntimeContext<ED>, body: any, payId: string, headers: IncomingHttpHeaders): Promise<void>;
|
||||
type CalcLoss = <ED extends EntityDict & BaseEntityDict>(entityId: string, application: ED['application']['Schema'], price: number) => [number, string, any];
|
||||
export declare function registerCalcRefundLoss<ED extends EntityDict & BaseEntityDict>(entity: string, projection: ED['application']['Selection']['data'], fn: CalcLoss): void;
|
||||
export declare function registerCalcDepositLoss<ED extends EntityDict & BaseEntityDict>(entity: string, projection: ED['application']['Selection']['data'], fn: CalcLoss): void;
|
||||
/**
|
||||
* 计算充值的损耗比例
|
||||
* attention: 这个函数目前是在前端调用的,所以要确保对应的offlineAccount的信息前端能取的到
|
||||
* attention: 这个函数目前是在前端调用的
|
||||
* @param context
|
||||
* @param channel
|
||||
* @param application
|
||||
*/
|
||||
export declare function getDepositLoss<ED extends EntityDict & BaseEntityDict>(price: number, entity: keyof ED, entityId: string, application: ED['application']['Schema']): ReturnType<CalcLoss>;
|
||||
export declare function getDepositLoss<ED extends EntityDict & BaseEntityDict>(price: number, application: ED['application']['Schema']): ReturnType<CalcLoss>;
|
||||
export declare function getAccountPayRefunds<ED extends EntityDict & BaseEntityDict>(context: BackendRuntimeContext<ED>, accountId: string, totalPrice?: number): Promise<Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "entity" | "entityId">[]>;
|
||||
export {};
|
||||
|
|
|
|||
113
es/utils/pay.js
113
es/utils/pay.js
|
|
@ -1,8 +1,6 @@
|
|||
import { getPayClazz } from './payClazz';
|
||||
import assert from 'assert';
|
||||
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
||||
import { RefundExceedMax } from '../types/Exception';
|
||||
import { merge } from 'oak-domain/lib/utils/lodash';
|
||||
export const fullPayProjection = {
|
||||
id: 1,
|
||||
applicationId: 1,
|
||||
|
|
@ -85,7 +83,10 @@ export async function payNotify(context, body, payId, headers) {
|
|||
}
|
||||
return;
|
||||
}
|
||||
const CalcRefundLossDict = {
|
||||
/* const CalcRefundLossDict: Record<string, {
|
||||
projection: EntityDict['application']['Selection']['data'],
|
||||
fn: CalcLoss,
|
||||
}> = {
|
||||
'wpProduct': {
|
||||
projection: {
|
||||
wpProduct$application: {
|
||||
|
|
@ -102,8 +103,8 @@ const CalcRefundLossDict = {
|
|||
},
|
||||
fn: (entityId, application, price) => {
|
||||
const { wpProduct$application: wpProducts } = application;
|
||||
const wpProduct = wpProducts.find(ele => ele.id === entityId);
|
||||
const { refundLossFloor, refundLossRatio } = wpProduct.wpAccount;
|
||||
const wpProduct = wpProducts!.find(ele => ele.id === entityId);
|
||||
const { refundLossFloor, refundLossRatio } = wpProduct!.wpAccount!;
|
||||
if (refundLossRatio) {
|
||||
return [
|
||||
Math.ceil(price * refundLossRatio / 100),
|
||||
|
|
@ -129,83 +130,45 @@ const CalcRefundLossDict = {
|
|||
}
|
||||
}
|
||||
};
|
||||
const CalcDepositLossDict = {
|
||||
wpProduct: {
|
||||
projection: {
|
||||
wpProduct$application: {
|
||||
$entity: 'wpProduct',
|
||||
data: {
|
||||
wpAccount: {
|
||||
id: 1,
|
||||
depositLossRatio: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
fn: (entityId, application, price) => {
|
||||
const { wpProduct$application: wpProducts } = application;
|
||||
const wpProduct = wpProducts.find(ele => ele.id === entityId);
|
||||
const { depositLossRatio } = wpProduct.wpAccount;
|
||||
if (depositLossRatio) {
|
||||
return [Math.ceil(price * depositLossRatio / 100), 'common::deposit.lossReason.ratio', { value: depositLossRatio }];
|
||||
}
|
||||
return [0, '', undefined];
|
||||
},
|
||||
},
|
||||
offlineAccount: {
|
||||
projection: {
|
||||
system: {
|
||||
offlineAccount$system: {
|
||||
$entity: 'offlineAccount',
|
||||
data: {
|
||||
id: 1,
|
||||
depositLossRatio: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fn: (entityId, application, price) => {
|
||||
const { system } = application;
|
||||
const { offlineAccount$system: offlineAccounts } = system;
|
||||
const offlineAccount = offlineAccounts.find(ele => ele.id === entityId);
|
||||
const { depositLossRatio } = offlineAccount;
|
||||
if (depositLossRatio) {
|
||||
return [Math.ceil(price * depositLossRatio / 100), 'common::deposit.lossReason.ratio', { value: depositLossRatio }];
|
||||
}
|
||||
return [0, '', undefined];
|
||||
}
|
||||
}
|
||||
};
|
||||
export function registerCalcRefundLoss(entity, projection, fn) {
|
||||
|
||||
|
||||
export function registerCalcRefundLoss<ED extends EntityDict & BaseEntityDict>(entity: string, projection: ED['application']['Selection']['data'], fn: CalcLoss) {
|
||||
assert(!CalcRefundLossDict[entity], `${entity}上已经定义了CalcLoss`);
|
||||
CalcRefundLossDict[entity] = {
|
||||
projection,
|
||||
fn,
|
||||
};
|
||||
}
|
||||
export function registerCalcDepositLoss(entity, projection, fn) {
|
||||
assert(!CalcDepositLossDict[entity], `${entity}上已经定义了CalcLoss`);
|
||||
CalcDepositLossDict[entity] = {
|
||||
projection,
|
||||
fn,
|
||||
};
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* 计算充值的损耗比例
|
||||
* attention: 这个函数目前是在前端调用的,所以要确保对应的offlineAccount的信息前端能取的到
|
||||
* attention: 这个函数目前是在前端调用的
|
||||
* @param context
|
||||
* @param channel
|
||||
* @param application
|
||||
*/
|
||||
export function getDepositLoss(price, entity, entityId, application) {
|
||||
const option = CalcDepositLossDict[entity];
|
||||
if (option) {
|
||||
return option.fn(entityId, application, price);
|
||||
export function getDepositLoss(price, application) {
|
||||
const { system } = application;
|
||||
const { payConfig } = system;
|
||||
const depositLoss = payConfig?.depositLoss;
|
||||
if (depositLoss) {
|
||||
const { ratio, highest, lowest } = depositLoss;
|
||||
let loss = ratio && Math.round(price * ratio / 100) || 0;
|
||||
if (highest && loss > highest) {
|
||||
return [highest, 'common::deposit.lossReason.highest', { value: (highest / 100).toFixed(2) }];
|
||||
}
|
||||
if (lowest && loss < lowest) {
|
||||
return [lowest, 'common::deposit.lossReason.lowest', { value: (lowest / 100).toFixed(2) }];
|
||||
}
|
||||
if (loss > 0) {
|
||||
return [loss, 'common::deposit.lossReason.ratio', { value: ratio }];
|
||||
}
|
||||
}
|
||||
return [0, '', undefined];
|
||||
}
|
||||
export async function getAccountPayRefunds(context, accountId, totalPrice) {
|
||||
const appProj = {
|
||||
const refundData = [];
|
||||
/* const appProj: EntityDict['application']['Selection']['data'] = {
|
||||
id: 1,
|
||||
};
|
||||
for (const k in CalcRefundLossDict) {
|
||||
|
|
@ -240,25 +203,28 @@ export async function getAccountPayRefunds(context, accountId, totalPrice) {
|
|||
}
|
||||
],
|
||||
}, { dontCollect: true, forUpdate: true });
|
||||
|
||||
let price2 = 0;
|
||||
const refundData = [];
|
||||
|
||||
for (const pay of pays) {
|
||||
const { price, paid, refunded, refundable, entity, entityId, application } = pay;
|
||||
assert(price === paid && refundable);
|
||||
assert(!['account', 'offlineAccount'].includes(entity));
|
||||
const rest = paid - refunded;
|
||||
assert(!['account', 'offlineAccount'].includes(entity!));
|
||||
|
||||
const rest = paid! - refunded!;
|
||||
assert(rest > 0);
|
||||
let refundPrice = rest;
|
||||
if (totalPrice && totalPrice - price2 < rest) {
|
||||
refundPrice = totalPrice - price2;
|
||||
}
|
||||
const [loss, lossExplanation, lossExplanationParams] = CalcRefundLossDict[entity].fn(entityId, application, price);
|
||||
const [loss, lossExplanation, lossExplanationParams] = CalcRefundLossDict[entity!]!.fn(entityId!, application as EntityDict['application']['Schema'], price!);
|
||||
|
||||
refundData.push({
|
||||
id: await generateNewIdAsync(),
|
||||
price: refundPrice,
|
||||
loss,
|
||||
creatorId: context.getCurrentUserId(),
|
||||
payId: pay.id,
|
||||
payId: pay.id!,
|
||||
iState: 'refunding',
|
||||
meta: {
|
||||
channel: entity,
|
||||
|
|
@ -266,13 +232,16 @@ export async function getAccountPayRefunds(context, accountId, totalPrice) {
|
|||
lossExplanationParams,
|
||||
}
|
||||
});
|
||||
|
||||
price2 += refundPrice;
|
||||
|
||||
if (totalPrice && price2 === totalPrice) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalPrice && price2 < totalPrice) {
|
||||
throw new RefundExceedMax();
|
||||
}
|
||||
} */
|
||||
return refundData;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Schema, OpSchema as Pay, UpdateOperationData as PayUpdateData } from ".
|
|||
import PayClazz from "../../types/PayClazz";
|
||||
import { BRC } from "../../types/RuntimeCxt";
|
||||
export default class Account implements PayClazz {
|
||||
getRefundableAt(successAt: number): number;
|
||||
refund(refund: Refund): Promise<undefined>;
|
||||
closeRefund(refund: Refund): Promise<void>;
|
||||
getRefundState(refund: Refund): Promise<[Refund['iState'], undefined]>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import assert from 'assert';
|
||||
import dayJs from 'dayjs';
|
||||
import { generateNewIdAsync } from "oak-domain/lib/utils/uuid";
|
||||
export default class Account {
|
||||
getRefundableAt(successAt) {
|
||||
return dayJs(successAt).add(1000, 'y').valueOf();
|
||||
}
|
||||
async refund(refund) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ import { OpSchema, UpdateOperationData } from "../../oak-app-domain/Refund/Schem
|
|||
import { OpSchema as Pay, UpdateOperationData as PayUpdateData } from "../../oak-app-domain/Pay/Schema";
|
||||
import PayClazz from "../../types/PayClazz";
|
||||
import { BRC } from "../../types/RuntimeCxt";
|
||||
import { EntityDict } from "../../oak-app-domain";
|
||||
export default class Offline implements PayClazz {
|
||||
offlineAccount: EntityDict['offlineAccount']['OpSchema'];
|
||||
constructor(offlineAccount: EntityDict['offlineAccount']['OpSchema']);
|
||||
getRefundableAt(successTime: number): number;
|
||||
refund(refund: OpSchema): Promise<UpdateOperationData | undefined>;
|
||||
closeRefund(refund: OpSchema): Promise<void>;
|
||||
getRefundState(refund: OpSchema): Promise<[Pay['iState'], PayUpdateData | undefined]>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
import assert from "assert";
|
||||
import dayJs from 'dayjs';
|
||||
export default class Offline {
|
||||
offlineAccount;
|
||||
constructor(offlineAccount) {
|
||||
this.offlineAccount = offlineAccount;
|
||||
}
|
||||
getRefundableAt(successTime) {
|
||||
const { refundGapDays } = this.offlineAccount;
|
||||
return refundGapDays ? dayJs(successTime).add(refundGapDays, 'day').subtract(12, 'hour').valueOf() : 0;
|
||||
}
|
||||
async refund(refund) {
|
||||
// 啥也不做
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -32,4 +32,5 @@ export default class WechatPay implements PayClazz {
|
|||
iState: EntityDict['pay']['OpSchema']['iState'];
|
||||
extra?: PayUpdateData;
|
||||
}>;
|
||||
getRefundableAt(successAt: number): number;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,5 +24,6 @@ export default class WechatPay implements PayClazz {
|
|||
*/
|
||||
prepay(pay: Pay, data: PayUpdateData, context: BRC): Promise<void>;
|
||||
getState(pay: Pay): Promise<[string, PayUpdateData]>;
|
||||
getRefundableAt(successAt: number): number;
|
||||
close(pay: Pay): Promise<void>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,10 +78,12 @@ export default class WechatPay {
|
|||
return ['closed', {}];
|
||||
}
|
||||
return ['paid', {
|
||||
forbidRefundAt: Date.now() + 24 * 3600 * 1000,
|
||||
refundable: true,
|
||||
successAt: Date.now(),
|
||||
}];
|
||||
}
|
||||
getRefundableAt(successAt) {
|
||||
return successAt + 24 * 3600 * 1000;
|
||||
}
|
||||
async close(pay) {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export default class WechatPay {
|
|||
if (gapDays < WechatPay.MIN_REFUND_DAYS_GAP) {
|
||||
gapDays = WechatPay.MIN_REFUND_DAYS_GAP;
|
||||
}
|
||||
return dayJs(successTime).add(gapDays, 'day').subtract(12, 'hour').millisecond();
|
||||
return dayJs(successTime).add(gapDays, 'day').subtract(12, 'hour').valueOf();
|
||||
}
|
||||
async prepay(pay, data, context) {
|
||||
const applicationId = context.getApplicationId();
|
||||
|
|
@ -159,8 +159,7 @@ export default class WechatPay {
|
|||
}
|
||||
};
|
||||
if (iState === 'paid') {
|
||||
updateData.forbidRefundAt = this.caclRefundDeadline(success_time);
|
||||
updateData.refundable = true;
|
||||
updateData.forbidRefundAt = dayJs(success_time).millisecond();
|
||||
}
|
||||
return [iState, updateData];
|
||||
}
|
||||
|
|
@ -276,8 +275,7 @@ export default class WechatPay {
|
|||
meta: omit(result, ['mchid',]),
|
||||
};
|
||||
if (iState === 'paid') {
|
||||
extra.forbidRefundAt = this.caclRefundDeadline(success_time);
|
||||
extra.refundable = true;
|
||||
extra.successAt = success_time;
|
||||
}
|
||||
return {
|
||||
payId,
|
||||
|
|
@ -285,4 +283,7 @@ export default class WechatPay {
|
|||
extra,
|
||||
};
|
||||
}
|
||||
getRefundableAt(successAt) {
|
||||
return this.caclRefundDeadline(successAt);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,30 @@ import WechatPay from './WechatPay';
|
|||
const PayChannelDict = {};
|
||||
const PayClazzConstructorDict = {
|
||||
'account': async () => new Account(),
|
||||
'offlineAccount': async () => new Offline(),
|
||||
'offlineAccount': async (applicationId, entityId, context) => {
|
||||
const [offlineAccount] = await context.select('offlineAccount', {
|
||||
data: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
channel: 1,
|
||||
name: 1,
|
||||
qrCode: 1,
|
||||
taxLossRatio: 1,
|
||||
refundCompensateRatio: 1,
|
||||
refundGapDays: 1,
|
||||
allowDeposit: 1,
|
||||
allowPay: 1,
|
||||
systemId: 1,
|
||||
price: 1,
|
||||
enabled: 1,
|
||||
},
|
||||
filter: {
|
||||
id: entityId,
|
||||
},
|
||||
}, { dontCollect: true });
|
||||
assert(offlineAccount.enabled);
|
||||
return new Offline(offlineAccount);
|
||||
},
|
||||
'wpProduct': async (applicationId, entityId, context) => {
|
||||
const [[wpProduct], [application]] = await Promise.all([
|
||||
context.select('wpProduct', {
|
||||
|
|
@ -24,6 +47,9 @@ const PayClazzConstructorDict = {
|
|||
refundNotifyUrl: 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
id: entityId,
|
||||
}
|
||||
}, { dontCollect: true }),
|
||||
context.select('application', {
|
||||
|
|
|
|||
|
|
@ -101,6 +101,18 @@ const checkers = [
|
|||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
entity: 'pay',
|
||||
action: 'succeedPaying',
|
||||
type: 'data',
|
||||
checker(data) {
|
||||
(0, assert_1.default)(!(data instanceof Array));
|
||||
const { successAt } = data;
|
||||
if (!successAt) {
|
||||
throw new types_1.OakAttrNotNullException('pay', ['successAt']);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
// 如果在开始支付或者继续支付过程中,paid达到了price,pay的状态可以改为paid
|
||||
entity: 'pay',
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ function PayConfig(props) {
|
|||
...data,
|
||||
},
|
||||
withdrawLoss: withdrawLoss || {
|
||||
conservative: !!(withdrawLoss?.conservative),
|
||||
conservative: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ const attrUpdateMatrix = {
|
|||
forbidRefundAt: {
|
||||
actions: ['succeedPaying'],
|
||||
},
|
||||
successAt: {
|
||||
actions: ['succeedPaying'],
|
||||
},
|
||||
entity: {
|
||||
actions: ['update', 'succeedPaying'],
|
||||
filter: {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export interface Schema extends EntityShape {
|
|||
entity: String<32>;
|
||||
entityId: String<64>;
|
||||
timeoutAt?: Datetime;
|
||||
successAt?: Datetime;
|
||||
forbidRefundAt?: Datetime;
|
||||
refundable: Boolean;
|
||||
deposit?: Deposit;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ exports.entityDesc = {
|
|||
order: '所属订单',
|
||||
deposit: '充值',
|
||||
timeoutAt: '过期时间',
|
||||
successAt: '完成时间',
|
||||
forbidRefundAt: '停止退款时间',
|
||||
refundable: '是否可退款',
|
||||
meta: '支付metadata',
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export type OpSchema = EntityShape & {
|
|||
entity: "account" | "offlineAccount" | "wpProduct" | string;
|
||||
entityId: String<64>;
|
||||
timeoutAt?: Datetime | null;
|
||||
successAt?: Datetime | null;
|
||||
forbidRefundAt?: Datetime | null;
|
||||
refundable: Boolean;
|
||||
depositId?: ForeignKey<"deposit"> | null;
|
||||
|
|
@ -43,6 +44,7 @@ export type Schema = EntityShape & {
|
|||
entity: "account" | "offlineAccount" | "wpProduct" | string;
|
||||
entityId: String<64>;
|
||||
timeoutAt?: Datetime | null;
|
||||
successAt?: Datetime | null;
|
||||
forbidRefundAt?: Datetime | null;
|
||||
refundable: Boolean;
|
||||
depositId?: ForeignKey<"deposit"> | null;
|
||||
|
|
@ -83,6 +85,7 @@ type AttrFilter = {
|
|||
entity: Q_EnumValue<"account" | "offlineAccount" | "wpProduct" | string>;
|
||||
entityId: Q_StringValue;
|
||||
timeoutAt: Q_DateValue;
|
||||
successAt: Q_DateValue;
|
||||
forbidRefundAt: Q_DateValue;
|
||||
refundable: Q_BooleanValue;
|
||||
depositId: Q_StringValue;
|
||||
|
|
@ -121,6 +124,7 @@ export type Projection = {
|
|||
entity?: number;
|
||||
entityId?: number;
|
||||
timeoutAt?: number;
|
||||
successAt?: number;
|
||||
forbidRefundAt?: number;
|
||||
refundable?: number;
|
||||
depositId?: number;
|
||||
|
|
@ -204,6 +208,8 @@ export type SortAttr = {
|
|||
entityId: number;
|
||||
} | {
|
||||
timeoutAt: number;
|
||||
} | {
|
||||
successAt: number;
|
||||
} | {
|
||||
forbidRefundAt: number;
|
||||
} | {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ exports.desc = {
|
|||
timeoutAt: {
|
||||
type: "datetime"
|
||||
},
|
||||
successAt: {
|
||||
type: "datetime"
|
||||
},
|
||||
forbidRefundAt: {
|
||||
type: "datetime"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{ "name": "订单", "attr": { "price": "应支付金额", "paid": "已支付金额", "refunded": "已退款金额", "iState": "支付状态", "entity": "支付渠道", "entityId": "支付渠道id", "order": "所属订单", "deposit": "充值", "timeoutAt": "过期时间", "forbidRefundAt": "停止退款时间", "refundable": "是否可退款", "meta": "支付metadata", "externalId": "外部订单Id", "opers": "被关联帐户操作", "application": "关联应用", "creator": "创建者", "phantom1": "索引项一", "phantom2": "索引项二", "phantom3": "索引项三", "phantom4": "索引项四" }, "action": { "startPaying": "开始支付", "continuePaying": "继续支付", "succeedPaying": "支付成功", "close": "关闭", "startRefunding": "开始退款", "refundAll": "完全退款", "refundPartially": "部分退款", "closeRefund": "禁止退款", "stopRefunding": "停止退款" }, "v": { "iState": { "unpaid": "待付款", "paying": "支付中", "paid": "已付款", "closed": "已关闭", "refunding": "退款中", "refunded": "已退款", "partiallyRefunded": "已部分退款" } } }
|
||||
{ "name": "订单", "attr": { "price": "应支付金额", "paid": "已支付金额", "refunded": "已退款金额", "iState": "支付状态", "entity": "支付渠道", "entityId": "支付渠道id", "order": "所属订单", "deposit": "充值", "timeoutAt": "过期时间", "successAt": "完成时间", "forbidRefundAt": "停止退款时间", "refundable": "是否可退款", "meta": "支付metadata", "externalId": "外部订单Id", "opers": "被关联帐户操作", "application": "关联应用", "creator": "创建者", "phantom1": "索引项一", "phantom2": "索引项二", "phantom3": "索引项三", "phantom4": "索引项四" }, "action": { "startPaying": "开始支付", "continuePaying": "继续支付", "succeedPaying": "支付成功", "close": "关闭", "startRefunding": "开始退款", "refundAll": "完全退款", "refundPartially": "部分退款", "closeRefund": "禁止退款", "stopRefunding": "停止退款" }, "v": { "iState": { "unpaid": "待付款", "paying": "支付中", "paid": "已付款", "closed": "已关闭", "refunding": "退款中", "refunded": "已退款", "partiallyRefunded": "已部分退款" } } }
|
||||
|
|
|
|||
|
|
@ -23,8 +23,7 @@ exports.desc = {
|
|||
type: "ref",
|
||||
ref: "platform"
|
||||
},
|
||||
folder // 提现的loss在用户提现时计算
|
||||
: {
|
||||
folder: {
|
||||
notNull: true,
|
||||
type: "varchar",
|
||||
params: {
|
||||
|
|
@ -34,11 +33,11 @@ exports.desc = {
|
|||
super: {
|
||||
type: "boolean"
|
||||
},
|
||||
style: {
|
||||
style // 如果为true,则按照渠道taxLossRatio和refundCompensateRatio进行扣取(如果因为depositLossRatio已经大于taxLossRatio,则全额退款)
|
||||
: {
|
||||
type: "object"
|
||||
},
|
||||
entity // 如果为true,则按照渠道taxLossRatio和refundCompensateRatio进行扣取(如果因为depositLossRatio已经大于taxLossRatio,则全额退款)
|
||||
: {
|
||||
entity: {
|
||||
type: "varchar",
|
||||
params: {
|
||||
length: 32
|
||||
|
|
|
|||
|
|
@ -2,12 +2,6 @@
|
|||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.style = void 0;
|
||||
exports.style = {
|
||||
color: {
|
||||
refundLossFloor: {
|
||||
yuan: '#FFFF00',
|
||||
jiao: '#00FF00'
|
||||
}
|
||||
},
|
||||
icon: {
|
||||
pay: '',
|
||||
refund: '',
|
||||
|
|
|
|||
|
|
@ -518,7 +518,9 @@ const triggers = [
|
|||
await context.operate('pay', {
|
||||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||||
action: 'succeedPaying',
|
||||
data: {},
|
||||
data: {
|
||||
successAt: Date.now(),
|
||||
},
|
||||
filter: {
|
||||
id,
|
||||
}
|
||||
|
|
@ -528,5 +530,32 @@ const triggers = [
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '当pay完成支付时,计算其refundable和forbidRefundAt',
|
||||
entity: 'pay',
|
||||
action: 'succeedPaying',
|
||||
when: 'before',
|
||||
fn: async ({ operation }, context) => {
|
||||
const { data, filter } = operation;
|
||||
(0, assert_1.default)(data.successAt);
|
||||
const pays = await context.select('pay', {
|
||||
data: {
|
||||
id: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
applicationId: 1,
|
||||
},
|
||||
filter
|
||||
}, { dontCollect: true, forUpdate: true });
|
||||
(0, assert_1.default)(pays.length === 1);
|
||||
const [pay] = pays;
|
||||
const { applicationId, entity, entityId } = pay;
|
||||
const payClazz = await (0, payClazz_1.getPayClazz)(applicationId, entity, entityId, context);
|
||||
const forbidRefundAt = payClazz.getRefundableAt(data.successAt);
|
||||
data.forbidRefundAt = forbidRefundAt;
|
||||
data.refundable = forbidRefundAt > Date.now();
|
||||
return 1;
|
||||
},
|
||||
},
|
||||
];
|
||||
exports.default = triggers;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export default interface PayClazz {
|
|||
}>;
|
||||
refund(refund: EntityDict['refund']['OpSchema']): Promise<EntityDict['refund']['Update']['data'] | undefined>;
|
||||
closeRefund(refund: EntityDict['refund']['OpSchema']): Promise<void>;
|
||||
getRefundableAt(successAt: number): number;
|
||||
getRefundState(refund: EntityDict['refund']['OpSchema']): Promise<[EntityDict['refund']['OpSchema']['iState'], EntityDict['refund']['Update']['data'] | undefined]>;
|
||||
}
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Schema, OpSchema as Pay, UpdateOperationData as PayUpdateData } from ".
|
|||
import PayClazz from "../../types/PayClazz";
|
||||
import { BRC } from "../../types/RuntimeCxt";
|
||||
export default class Account implements PayClazz {
|
||||
getRefundableAt(successAt: number): number;
|
||||
refund(refund: Refund): Promise<undefined>;
|
||||
closeRefund(refund: Refund): Promise<void>;
|
||||
getRefundState(refund: Refund): Promise<[Refund['iState'], undefined]>;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@
|
|||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
const assert_1 = tslib_1.__importDefault(require("assert"));
|
||||
const dayjs_1 = tslib_1.__importDefault(require("dayjs"));
|
||||
const uuid_1 = require("oak-domain/lib/utils/uuid");
|
||||
class Account {
|
||||
getRefundableAt(successAt) {
|
||||
return (0, dayjs_1.default)(successAt).add(1000, 'y').valueOf();
|
||||
}
|
||||
async refund(refund) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ import { OpSchema, UpdateOperationData } from "../../oak-app-domain/Refund/Schem
|
|||
import { OpSchema as Pay, UpdateOperationData as PayUpdateData } from "../../oak-app-domain/Pay/Schema";
|
||||
import PayClazz from "../../types/PayClazz";
|
||||
import { BRC } from "../../types/RuntimeCxt";
|
||||
import { EntityDict } from "../../oak-app-domain";
|
||||
export default class Offline implements PayClazz {
|
||||
offlineAccount: EntityDict['offlineAccount']['OpSchema'];
|
||||
constructor(offlineAccount: EntityDict['offlineAccount']['OpSchema']);
|
||||
getRefundableAt(successTime: number): number;
|
||||
refund(refund: OpSchema): Promise<UpdateOperationData | undefined>;
|
||||
closeRefund(refund: OpSchema): Promise<void>;
|
||||
getRefundState(refund: OpSchema): Promise<[Pay['iState'], PayUpdateData | undefined]>;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,16 @@
|
|||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
const assert_1 = tslib_1.__importDefault(require("assert"));
|
||||
const dayjs_1 = tslib_1.__importDefault(require("dayjs"));
|
||||
class Offline {
|
||||
offlineAccount;
|
||||
constructor(offlineAccount) {
|
||||
this.offlineAccount = offlineAccount;
|
||||
}
|
||||
getRefundableAt(successTime) {
|
||||
const { refundGapDays } = this.offlineAccount;
|
||||
return refundGapDays ? (0, dayjs_1.default)(successTime).add(refundGapDays, 'day').subtract(12, 'hour').valueOf() : 0;
|
||||
}
|
||||
async refund(refund) {
|
||||
// 啥也不做
|
||||
return;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue