设计实现了sysAccountMove
This commit is contained in:
parent
ae185dd5a0
commit
bd03f9bd67
|
|
@ -27,13 +27,16 @@ function checkAttributes(data) {
|
|||
}
|
||||
}
|
||||
}
|
||||
const { refundCompensateRatio, refundGapDays } = data;
|
||||
const { refundCompensateRatio, refundGapDays, withdrawTransferLossRatio } = data;
|
||||
if (typeof refundGapDays !== 'number' || refundGapDays < 0) {
|
||||
throw new OakInputIllegalException('offlineAccount', ['refundGapDays'], 'offlineAccount::error.refundGapDaysNotNegative');
|
||||
}
|
||||
if (typeof refundCompensateRatio !== 'number' || refundCompensateRatio < 0 || refundCompensateRatio > 100) {
|
||||
throw new OakInputIllegalException('offlineAccount', ['refundGapDays'], 'offlineAccount::error.refundCompensateIllegal');
|
||||
}
|
||||
if (typeof withdrawTransferLossRatio !== 'number' || withdrawTransferLossRatio < 0) {
|
||||
throw new OakInputIllegalException('offlineAccount', ['withdrawTransferLossRatio'], 'offlineAccount::error.withdrawTransferLossRatioNotNegative');
|
||||
}
|
||||
}
|
||||
const checkers = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ export default function render(props) {
|
|||
update({ allowWithdrawTransfer });
|
||||
}}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t('offlineAccount:attr.withdrawTransferLossRatio')} help={t('placeholder.withdrawTransferLossRatio')}>
|
||||
<Form.Item label={t('offlineAccount:attr.withdrawTransferLossRatio')} help={t('placeholder.withdrawTransferLossRatio')} required>
|
||||
<InputNumber value={offlineAccount.withdrawTransferLossRatio} max={5} min={0.01} addonAfter={"%"} step={0.01} precision={2} onChange={(value) => {
|
||||
const withdrawTransferLossRatio = value;
|
||||
update({ withdrawTransferLossRatio });
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Descriptions, Tag, Modal, Flex, Button, Divider, Alert } from 'antd';
|
||||
import { AlipayOutlined, WechatOutlined } from '@ant-design/icons';
|
||||
import Styles from './web.pc.module.less';
|
||||
import { ThousandCont, ToYuan } from "oak-domain/lib/utils/money";
|
||||
import { OfflineAccount as OADetail } from '../../offlineAccount/config/web.pc';
|
||||
import { WpAccount as WADetail } from '../../wpAccount/config/web.pc';
|
||||
import TransferList from '../transferList';
|
||||
function OfflineAccount(props) {
|
||||
const { data, t } = props;
|
||||
const { type, channel, color, name } = data;
|
||||
|
|
@ -65,6 +66,7 @@ export default function render(props) {
|
|||
const { accounts, total, systemId, accountNum, accountTotalSum, accountAvailSum, refundCnt, refundPriceSum, transferCnt, transferPriceSum, orderCnt, orderPaidSum, orderRefundSum, } = props.data;
|
||||
const { t, setMessage } = props.methods;
|
||||
if (accounts && systemId) {
|
||||
const [showTransferList, setShowTransferList] = useState(false);
|
||||
return (<div className={Styles.container}>
|
||||
<Descriptions title={t('sysAccount')} bordered items={[
|
||||
{
|
||||
|
|
@ -163,9 +165,12 @@ export default function render(props) {
|
|||
<span className={Styles.symbol}>{t('common::pay.symbol')}</span>
|
||||
<span className={Styles.value}>{ThousandCont(ToYuan(transferPriceSum || 0), 2)}</span>
|
||||
</span>
|
||||
<Button>
|
||||
<Button onClick={() => setShowTransferList(true)}>
|
||||
{t('transferList')}
|
||||
</Button>
|
||||
<Modal open={showTransferList} onCancel={() => setShowTransferList(false)} footer={null} closeIcon={null} width={800}>
|
||||
<TransferList oakPath="$opb-sysAccount-survery-transferList"/>
|
||||
</Modal>
|
||||
</div>)
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "withdrawTransfer", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
export default OakComponent({
|
||||
entity: 'withdrawTransfer',
|
||||
isList: true,
|
||||
projection: {
|
||||
id: 1,
|
||||
price: 1,
|
||||
loss: 1,
|
||||
externalId: 1,
|
||||
iState: 1,
|
||||
withdrawAccount: {
|
||||
org: 1,
|
||||
name: 1,
|
||||
code: 1,
|
||||
channel: {
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
offlineAccount: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
}
|
||||
},
|
||||
id: 1,
|
||||
}
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
filter() {
|
||||
const systemId = this.features.application.getApplication().systemId;
|
||||
return {
|
||||
withdrawAccount: {
|
||||
ofSystemId: systemId,
|
||||
},
|
||||
iState: 'transferring',
|
||||
};
|
||||
}
|
||||
}
|
||||
],
|
||||
formData({ data }) {
|
||||
return {
|
||||
transfers: data?.map((ele) => {
|
||||
const { withdrawAccount, ...rest } = ele;
|
||||
const { entity, offlineAccount } = withdrawAccount.channel;
|
||||
const channel = entity === 'offlineAccount' ? this.t(`withdraw::channel.offlineAccount.${offlineAccount?.type}`) : this.t(`withdraw::channel.${entity}`);
|
||||
return {
|
||||
...rest,
|
||||
withdrawAccount,
|
||||
channel,
|
||||
};
|
||||
}),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"label": {
|
||||
"channel": "转账渠道"
|
||||
},
|
||||
"tips": "正在转账的金额不计入任何账户,请到\"提现转账管理\"菜单完成操作"
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'pay', false, {
|
||||
transfers?: (RowWithActions<EntityDict, 'withdrawTransfer'> & {
|
||||
creatorName: string;
|
||||
creatorMobile: string;
|
||||
operatorName: string;
|
||||
operatorMobile: string;
|
||||
channel: string;
|
||||
})[];
|
||||
}, {
|
||||
setUpdateId: (id: string, action: string) => void;
|
||||
}>): React.JSX.Element;
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import React from 'react';
|
||||
import { Result, Alert } from 'antd';
|
||||
import ListPro from 'oak-frontend-base/es/components/listPro';
|
||||
import { ThousandCont, ToYuan } from 'oak-domain/lib/utils/money';
|
||||
export default function Render(props) {
|
||||
const { transfers, oakFullpath, oakExecutable } = props.data;
|
||||
const { t, updateItem, execute, clean, setMessage, setUpdateId } = props.methods;
|
||||
if (transfers?.length) {
|
||||
return (<ListPro entity="withdrawTransfer" data={transfers} title={<Alert type="info" message={t('tips')}/>} attributes={[
|
||||
{
|
||||
path: 'price',
|
||||
label: t('withdrawTransfer:attr.price'),
|
||||
width: 100,
|
||||
render: (row) => {
|
||||
return `${t('common::pay.symbol')} ${ThousandCont(ToYuan(row.price), 2)}`;
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'loss',
|
||||
label: t('withdrawTransfer:attr.loss'),
|
||||
width: 100,
|
||||
render: (row) => {
|
||||
return `${t('common::pay.symbol')} ${ThousandCont(ToYuan(row.loss), 2)}`;
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '$$createAt$$',
|
||||
label: t('common::$$createAt$$'),
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
path: 'channel',
|
||||
label: t('label.channel'),
|
||||
type: 'string',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
path: 'externalId',
|
||||
label: t('withdrawTransfer:attr.externalId'),
|
||||
width: 120,
|
||||
},
|
||||
]} disabledOp={true}/>);
|
||||
}
|
||||
return (<Result status="404" title={t('common::noData')}/>);
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"label": {
|
||||
"channel": "提现渠道",
|
||||
"channel": "转账渠道",
|
||||
"transferActualPrice": "实际转账金额",
|
||||
"sysAccountAmount": "系统账户余额",
|
||||
"cn": "创建者",
|
||||
|
|
|
|||
|
|
@ -409,6 +409,19 @@ const i18ns = [
|
|||
"tips1": "总账户余额+退款总额+转账总额+订单总额应该等于系统账户总余额"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "207fd2189d3697d15672176ae88f4175",
|
||||
namespace: "oak-pay-business-c-sysAccount-transferList",
|
||||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/sysAccount/transferList",
|
||||
data: {
|
||||
"label": {
|
||||
"channel": "转账渠道"
|
||||
},
|
||||
"tips": "正在转账的金额不计入任何账户,请到\"提现转账管理\"菜单完成操作"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "79255be8c093dfef9765b3f367cab553",
|
||||
namespace: "oak-pay-business-c-wechatPay-upsert",
|
||||
|
|
@ -583,7 +596,7 @@ const i18ns = [
|
|||
position: "src/components/withdrawTransfer/list",
|
||||
data: {
|
||||
"label": {
|
||||
"channel": "提现渠道",
|
||||
"channel": "转账渠道",
|
||||
"transferActualPrice": "实际转账金额",
|
||||
"sysAccountAmount": "系统账户余额",
|
||||
"cn": "创建者",
|
||||
|
|
@ -786,7 +799,8 @@ const i18ns = [
|
|||
"error": {
|
||||
"nameQrCodeBothNull": "账号名和二维码不能同时为空",
|
||||
"refundGapDaysNotNegative": "允许退款天数不能为负数或空",
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间"
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间",
|
||||
"withdrawTransferLossRatioNotNegative": "提现转账费率必须在0到100之间"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
"error": {
|
||||
"nameQrCodeBothNull": "账号名和二维码不能同时为空",
|
||||
"refundGapDaysNotNegative": "允许退款天数不能为负数或空",
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间"
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间",
|
||||
"withdrawTransferLossRatioNotNegative": "提现转账费率必须在0到100之间"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,13 +30,16 @@ function checkAttributes(data) {
|
|||
}
|
||||
}
|
||||
}
|
||||
const { refundCompensateRatio, refundGapDays } = data;
|
||||
const { refundCompensateRatio, refundGapDays, withdrawTransferLossRatio } = data;
|
||||
if (typeof refundGapDays !== 'number' || refundGapDays < 0) {
|
||||
throw new types_1.OakInputIllegalException('offlineAccount', ['refundGapDays'], 'offlineAccount::error.refundGapDaysNotNegative');
|
||||
}
|
||||
if (typeof refundCompensateRatio !== 'number' || refundCompensateRatio < 0 || refundCompensateRatio > 100) {
|
||||
throw new types_1.OakInputIllegalException('offlineAccount', ['refundGapDays'], 'offlineAccount::error.refundCompensateIllegal');
|
||||
}
|
||||
if (typeof withdrawTransferLossRatio !== 'number' || withdrawTransferLossRatio < 0) {
|
||||
throw new types_1.OakInputIllegalException('offlineAccount', ['withdrawTransferLossRatio'], 'offlineAccount::error.withdrawTransferLossRatioNotNegative');
|
||||
}
|
||||
}
|
||||
const checkers = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -411,6 +411,19 @@ const i18ns = [
|
|||
"tips1": "总账户余额+退款总额+转账总额+订单总额应该等于系统账户总余额"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "207fd2189d3697d15672176ae88f4175",
|
||||
namespace: "oak-pay-business-c-sysAccount-transferList",
|
||||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/sysAccount/transferList",
|
||||
data: {
|
||||
"label": {
|
||||
"channel": "转账渠道"
|
||||
},
|
||||
"tips": "正在转账的金额不计入任何账户,请到\"提现转账管理\"菜单完成操作"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "79255be8c093dfef9765b3f367cab553",
|
||||
namespace: "oak-pay-business-c-wechatPay-upsert",
|
||||
|
|
@ -585,7 +598,7 @@ const i18ns = [
|
|||
position: "src/components/withdrawTransfer/list",
|
||||
data: {
|
||||
"label": {
|
||||
"channel": "提现渠道",
|
||||
"channel": "转账渠道",
|
||||
"transferActualPrice": "实际转账金额",
|
||||
"sysAccountAmount": "系统账户余额",
|
||||
"cn": "创建者",
|
||||
|
|
@ -788,7 +801,8 @@ const i18ns = [
|
|||
"error": {
|
||||
"nameQrCodeBothNull": "账号名和二维码不能同时为空",
|
||||
"refundGapDaysNotNegative": "允许退款天数不能为负数或空",
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间"
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间",
|
||||
"withdrawTransferLossRatioNotNegative": "提现转账费率必须在0到100之间"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
"error": {
|
||||
"nameQrCodeBothNull": "账号名和二维码不能同时为空",
|
||||
"refundGapDaysNotNegative": "允许退款天数不能为负数或空",
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间"
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间",
|
||||
"withdrawTransferLossRatioNotNegative": "提现转账费率必须在0到100之间"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,13 +33,16 @@ function checkAttributes(data: EntityDict['offlineAccount']['CreateSingle']['dat
|
|||
}
|
||||
}
|
||||
|
||||
const { refundCompensateRatio, refundGapDays } = data;
|
||||
const { refundCompensateRatio, refundGapDays, withdrawTransferLossRatio } = data;
|
||||
if (typeof refundGapDays !== 'number' || refundGapDays < 0) {
|
||||
throw new OakInputIllegalException('offlineAccount', ['refundGapDays'], 'offlineAccount::error.refundGapDaysNotNegative');
|
||||
}
|
||||
if (typeof refundCompensateRatio !== 'number' || refundCompensateRatio < 0 || refundCompensateRatio > 100) {
|
||||
throw new OakInputIllegalException('offlineAccount', ['refundGapDays'], 'offlineAccount::error.refundCompensateIllegal');
|
||||
}
|
||||
if (typeof withdrawTransferLossRatio !== 'number' || withdrawTransferLossRatio < 0) {
|
||||
throw new OakInputIllegalException('offlineAccount', ['withdrawTransferLossRatio'], 'offlineAccount::error.withdrawTransferLossRatioNotNegative');
|
||||
}
|
||||
}
|
||||
|
||||
const checkers: Checker<EntityDict, 'offlineAccount', RuntimeCxt>[] = [
|
||||
|
|
|
|||
|
|
@ -176,6 +176,7 @@ export default function render(props: WebComponentProps<EntityDict, 'offlineAcco
|
|||
<Form.Item
|
||||
label={t('offlineAccount:attr.withdrawTransferLossRatio')}
|
||||
help={t('placeholder.withdrawTransferLossRatio')}
|
||||
required
|
||||
>
|
||||
<InputNumber
|
||||
value={offlineAccount.withdrawTransferLossRatio}
|
||||
|
|
|
|||
|
|
@ -24,5 +24,6 @@
|
|||
"orderPriceSum": "订单总额",
|
||||
"orderManage": "订单管理",
|
||||
"orderList": "订单列表",
|
||||
"tips1": "总账户余额+退款总额+转账总额+订单总额应该等于系统账户总余额"
|
||||
"tips1": "总账户余额+退款总额+转账总额+订单总额应该等于系统账户总余额",
|
||||
"move": "移动资金"
|
||||
}
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
import { EntityDict } from "../../../oak-app-domain";
|
||||
import { RowWithActions, WebComponentProps } from "oak-frontend-base";
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { Descriptions, Tag, Form, Switch, Modal, Input, Select, Flex, Button, Divider, Alert } from 'antd';
|
||||
import { AlipayOutlined, WechatOutlined } from '@ant-design/icons';
|
||||
import Styles from './web.pc.module.less';
|
||||
import { ThousandCont, ToYuan } from "oak-domain/lib/utils/money";
|
||||
import { OfflineAccount as OADetail } from '../../offlineAccount/config/web.pc';
|
||||
import { WpAccount as WADetail } from '../../wpAccount/config/web.pc';
|
||||
import TransferList from '../transferList';
|
||||
import SysAccountMoveCreate from '../../sysAccountMove/create';
|
||||
|
||||
|
||||
function OfflineAccount(props: {
|
||||
data: EntityDict['offlineAccount']['OpSchema'] & { color?: string };
|
||||
|
|
@ -161,6 +164,8 @@ export default function render(props: WebComponentProps<EntityDict, 'offlineAcco
|
|||
const { t, setMessage } = props.methods;
|
||||
|
||||
if (accounts && systemId) {
|
||||
const [showTransferList, setShowTransferList] = useState(false);
|
||||
const [showMoveCreate, setShowMoveCreate] = useState(false);
|
||||
return (
|
||||
<div className={Styles.container}>
|
||||
<Descriptions
|
||||
|
|
@ -180,6 +185,31 @@ export default function render(props: WebComponentProps<EntityDict, 'offlineAcco
|
|||
}
|
||||
]}
|
||||
column={2}
|
||||
extra={
|
||||
<>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => setShowMoveCreate(true)}
|
||||
>
|
||||
{t('move')}
|
||||
</Button>
|
||||
<Modal
|
||||
destroyOnClose
|
||||
open={showMoveCreate}
|
||||
onCancel={() => setShowMoveCreate(false)}
|
||||
closeIcon={null}
|
||||
width={800}
|
||||
title={t('move')}
|
||||
footer={null}
|
||||
>
|
||||
<SysAccountMoveCreate
|
||||
oakPath="$opb-sysAccount-survery-saMoveCreate"
|
||||
systemId={systemId}
|
||||
onSuccess={() => setShowMoveCreate(false)}
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<div className={Styles.sysAccounts}>
|
||||
{
|
||||
|
|
@ -243,7 +273,7 @@ export default function render(props: WebComponentProps<EntityDict, 'offlineAcco
|
|||
{accountNum && <Descriptions
|
||||
title={t('business')}
|
||||
bordered
|
||||
extra={<Alert type="info" message={t('tips1')}/>}
|
||||
extra={<Alert type="info" message={t('tips1')} />}
|
||||
items={[
|
||||
{
|
||||
label: t('accountTotalSum'),
|
||||
|
|
@ -295,9 +325,22 @@ export default function render(props: WebComponentProps<EntityDict, 'offlineAcco
|
|||
<span className={Styles.symbol}>{t('common::pay.symbol')}</span>
|
||||
<span className={Styles.value}>{ThousandCont(ToYuan(transferPriceSum || 0), 2)}</span>
|
||||
</span>
|
||||
<Button>
|
||||
<Button
|
||||
onClick={() => setShowTransferList(true)}
|
||||
>
|
||||
{t('transferList')}
|
||||
</Button>
|
||||
<Modal
|
||||
open={showTransferList}
|
||||
onCancel={() => setShowTransferList(false)}
|
||||
footer={null}
|
||||
closeIcon={null}
|
||||
width={800}
|
||||
>
|
||||
<TransferList
|
||||
oakPath="$opb-sysAccount-survery-transferList"
|
||||
/>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
export default OakComponent({
|
||||
entity: 'withdrawTransfer',
|
||||
isList: true,
|
||||
projection: {
|
||||
id: 1,
|
||||
price: 1,
|
||||
loss: 1,
|
||||
externalId: 1,
|
||||
iState: 1,
|
||||
withdrawAccount: {
|
||||
org: 1,
|
||||
name: 1,
|
||||
code: 1,
|
||||
channel: {
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
offlineAccount: {
|
||||
id: 1,
|
||||
type: 1,
|
||||
}
|
||||
},
|
||||
id: 1,
|
||||
}
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
filter() {
|
||||
const systemId = this.features.application.getApplication()!.systemId;
|
||||
return {
|
||||
withdrawAccount: {
|
||||
ofSystemId: systemId,
|
||||
},
|
||||
iState: 'transferring',
|
||||
};
|
||||
}
|
||||
}
|
||||
],
|
||||
formData({ data }) {
|
||||
return {
|
||||
transfers: data?.map(
|
||||
(ele) => {
|
||||
const { withdrawAccount, ...rest } = ele;
|
||||
const { entity, offlineAccount } = withdrawAccount!.channel!;
|
||||
const channel = entity === 'offlineAccount' ? this.t(`withdraw::channel.offlineAccount.${offlineAccount?.type}`) : this.t(`withdraw::channel.${entity}`);
|
||||
return {
|
||||
...rest,
|
||||
withdrawAccount,
|
||||
channel,
|
||||
};
|
||||
}
|
||||
),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"label": {
|
||||
"channel": "转账渠道"
|
||||
},
|
||||
"tips": "正在转账的金额不计入任何账户,请到\"提现转账管理\"菜单完成操作"
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Result, Alert } from 'antd';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import ListPro from 'oak-frontend-base/es/components/listPro';
|
||||
import { ThousandCont, ToYuan } from 'oak-domain/lib/utils/money';
|
||||
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'pay', false, {
|
||||
transfers?: (RowWithActions<EntityDict, 'withdrawTransfer'> & {
|
||||
creatorName: string;
|
||||
creatorMobile: string;
|
||||
operatorName: string;
|
||||
operatorMobile: string;
|
||||
channel: string;
|
||||
})[];
|
||||
}>) {
|
||||
const { transfers, oakFullpath, oakExecutable } = props.data;
|
||||
const { t } = props.methods;
|
||||
|
||||
if (transfers?.length) {
|
||||
return (
|
||||
<ListPro
|
||||
entity="withdrawTransfer"
|
||||
data={transfers}
|
||||
title={
|
||||
<Alert type="info" message={t('tips')} />
|
||||
}
|
||||
attributes={[
|
||||
{
|
||||
path: 'price',
|
||||
label: t('withdrawTransfer:attr.price'),
|
||||
width: 100,
|
||||
render: (row) => {
|
||||
return `${t('common::pay.symbol')} ${ThousandCont(ToYuan(row!.price), 2)}`
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'loss',
|
||||
label: t('withdrawTransfer:attr.loss'),
|
||||
width: 100,
|
||||
render: (row) => {
|
||||
return `${t('common::pay.symbol')} ${ThousandCont(ToYuan(row!.loss), 2)}`
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '$$createAt$$',
|
||||
label: t('common::$$createAt$$'),
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
path: 'channel',
|
||||
label: t('label.channel'),
|
||||
type: 'string',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
path: 'externalId',
|
||||
label: t('withdrawTransfer:attr.externalId'),
|
||||
width: 120,
|
||||
},
|
||||
]}
|
||||
disabledOp={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Result
|
||||
status="404"
|
||||
title={t('common::noData')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
import { uniq } from "oak-domain/lib/utils/lodash";
|
||||
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
||||
import { ThousandCont, ToCent, ToYuan } from 'oak-domain/lib/utils/money';
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
|
||||
export default OakComponent({
|
||||
properties: {
|
||||
systemId: '',
|
||||
entities: [] as string[],
|
||||
onSuccess: (id: string) => undefined as void,
|
||||
},
|
||||
data: {
|
||||
accounts: [] as Array<{
|
||||
id: string;
|
||||
entity: string;
|
||||
price: number;
|
||||
priceStr: string;
|
||||
label: string;
|
||||
name?: string;
|
||||
}>,
|
||||
fromEntity: '',
|
||||
fromEntityId: '',
|
||||
toEntity: '',
|
||||
toEntityId: '',
|
||||
price: 0,
|
||||
externalId: '',
|
||||
remark: '',
|
||||
max: 0,
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
this.refreshSysAccount();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async refreshSysAccount() {
|
||||
const { entities, systemId } = this.props;
|
||||
|
||||
|
||||
const accounts2 = await Promise.all(
|
||||
uniq(['wpAccount', 'offlineAccount'].concat(entities || [])).map(
|
||||
async (entity) => {
|
||||
const { data: rows } = await this.features.cache.refresh(entity as 'offlineAccount', {
|
||||
data: entity === 'offlineAccount' ? {
|
||||
id: 1,
|
||||
price: 1,
|
||||
name: 1,
|
||||
type: 1,
|
||||
channel: 1,
|
||||
} : {
|
||||
id: 1,
|
||||
price: 1,
|
||||
},
|
||||
filter: {
|
||||
systemId,
|
||||
}
|
||||
});
|
||||
|
||||
const accounts = rows.map(
|
||||
(row) => {
|
||||
const { id, price, name, type, channel } = row;
|
||||
return {
|
||||
id: id!,
|
||||
entity: entity!,
|
||||
priceStr: ThousandCont(ToYuan(price!))!,
|
||||
price: price!,
|
||||
label: entity === 'offlineAccount' ? `${this.t(`${entity}:name`)}-${this.t(`offlineAccount:v.type.${type}`)}` : this.t(`${entity}:name`),
|
||||
name: name || undefined,
|
||||
};
|
||||
}
|
||||
);
|
||||
return accounts;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
this.setState({
|
||||
accounts: accounts2.flat(),
|
||||
});
|
||||
},
|
||||
setFromId(id: string) {
|
||||
const { accounts } = this.state;
|
||||
const account = accounts!.find(
|
||||
ele => ele.id === id
|
||||
);
|
||||
|
||||
this.setState({
|
||||
fromEntity: account!.entity,
|
||||
fromEntityId: account!.id,
|
||||
max: ToYuan(account!.price!),
|
||||
});
|
||||
},
|
||||
setToId(id: string) {
|
||||
const { accounts } = this.state;
|
||||
const account = accounts!.find(
|
||||
ele => ele.id === id
|
||||
);
|
||||
|
||||
this.setState({
|
||||
toEntity: account!.entity,
|
||||
toEntityId: account!.id,
|
||||
});
|
||||
},
|
||||
setPrice(price: number) {
|
||||
this.setState({
|
||||
price,
|
||||
});
|
||||
},
|
||||
setExternalId(externalId: string) {
|
||||
this.setState({
|
||||
externalId,
|
||||
});
|
||||
},
|
||||
setRemark(remark: string) {
|
||||
this.setState({
|
||||
remark,
|
||||
});
|
||||
},
|
||||
async createMove() {
|
||||
const { fromEntity, fromEntityId, toEntity, toEntityId, price, remark, externalId} = this.state;
|
||||
const userId = this.features.token.getUserId();
|
||||
const systemId = this.features.application.getApplication()!.systemId;
|
||||
|
||||
const id = await generateNewIdAsync();
|
||||
const price2 = ToCent(price);
|
||||
const { onSuccess } = this.props;
|
||||
await this.execute(undefined, undefined, undefined, [
|
||||
{
|
||||
entity: 'sysAccountMove',
|
||||
operation: {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id,
|
||||
price: price2,
|
||||
externalId,
|
||||
remark,
|
||||
systemId,
|
||||
operatorId: userId,
|
||||
sysAccountOper$sysAccountMove: [
|
||||
{
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
entity: fromEntity,
|
||||
entityId: fromEntityId,
|
||||
delta: -price2,
|
||||
type: 'moveOut',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
entity: toEntity,
|
||||
entityId: toEntityId,
|
||||
delta: price2,
|
||||
type: 'moveIn',
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
} as EntityDict['sysAccountMove']['CreateSingle'],
|
||||
}
|
||||
]);
|
||||
|
||||
onSuccess && onSuccess(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"label": {
|
||||
"from": "从账户",
|
||||
"to": "到账户"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Button, Alert, Form, Input, InputNumber, Radio, Space, Flex } from 'antd';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import ListPro from 'oak-frontend-base/es/components/listPro';
|
||||
import { ThousandCont, ToYuan } from 'oak-domain/lib/utils/money';
|
||||
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'pay', false, {
|
||||
fromEntityId?: string;
|
||||
toEntityId?: string;
|
||||
price: number;
|
||||
max?: number;
|
||||
externalId: string;
|
||||
remark: string;
|
||||
accounts: Array<{
|
||||
id: string;
|
||||
entity: string;
|
||||
price: number;
|
||||
priceStr: string;
|
||||
label: string;
|
||||
name?: string;
|
||||
}>;
|
||||
}, {
|
||||
setFromId: (id: string) => void;
|
||||
setToId: (id: string) => void;
|
||||
setPrice: (price: number) => void;
|
||||
setExternalId: (externalId: string) => void;
|
||||
setRemark: (remark: string) => void;
|
||||
createMove: () => Promise<void>;
|
||||
}>) {
|
||||
const { price, externalId, max, remark, fromEntityId, toEntityId, accounts } = props.data;
|
||||
const { t, setFromId, setToId, setPrice, setExternalId, setRemark, createMove } = props.methods;
|
||||
|
||||
if (accounts.length) {
|
||||
return (
|
||||
<>
|
||||
<Form
|
||||
labelCol={{ span: 4 }}
|
||||
wrapperCol={{ span: 14 }}
|
||||
layout="horizontal"
|
||||
style={{
|
||||
marginTop: 20,
|
||||
}}
|
||||
>
|
||||
<Form.Item
|
||||
label={t('label.from')}
|
||||
required
|
||||
>
|
||||
<Radio.Group onChange={({ target }) => {
|
||||
setFromId(target.value);
|
||||
}} value={fromEntityId}>
|
||||
<Space
|
||||
direction="vertical"
|
||||
>
|
||||
{
|
||||
accounts.filter(
|
||||
ele => ele.price > 0
|
||||
).map(
|
||||
ele => {
|
||||
const { id, label, price, priceStr } = ele;
|
||||
return (
|
||||
<Radio
|
||||
value={id}
|
||||
key={id}
|
||||
disabled={price <= 0}
|
||||
>
|
||||
{`${label}: ${t('common::pay.symbol')}${priceStr}`}
|
||||
</Radio>
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
{
|
||||
fromEntityId && <Form.Item
|
||||
label={t('label.to')}
|
||||
required
|
||||
>
|
||||
<Radio.Group onChange={({ target }) => {
|
||||
setToId(target.value);
|
||||
}} value={toEntityId}>
|
||||
<Space
|
||||
direction="vertical"
|
||||
>
|
||||
{
|
||||
accounts.filter(
|
||||
ele => ele.id !== fromEntityId
|
||||
).map(
|
||||
ele => {
|
||||
const { id, label, price, priceStr } = ele;
|
||||
return (
|
||||
<Radio
|
||||
value={id}
|
||||
key={id}
|
||||
>
|
||||
{`${label}: ${t('common::pay.symbol')}${priceStr}`}
|
||||
</Radio>
|
||||
);
|
||||
}
|
||||
)
|
||||
}
|
||||
</Space>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
}
|
||||
{
|
||||
fromEntityId && toEntityId && <Form.Item
|
||||
label={t('sysAccountMove:attr.price')}
|
||||
required
|
||||
>
|
||||
<InputNumber
|
||||
value={price}
|
||||
style={{
|
||||
width: 240,
|
||||
}}
|
||||
max={max}
|
||||
precision={2}
|
||||
onChange={(value) => {
|
||||
const price = value as number;
|
||||
setPrice(price)
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
}
|
||||
{
|
||||
fromEntityId && toEntityId && <Form.Item
|
||||
label={t('sysAccountMove:attr.externalId')}
|
||||
required
|
||||
>
|
||||
<Input
|
||||
value={externalId}
|
||||
onChange={({ currentTarget }) => {
|
||||
const externalId = currentTarget.value;
|
||||
setExternalId(externalId);
|
||||
}}
|
||||
maxLength={64}
|
||||
/>
|
||||
</Form.Item>
|
||||
}
|
||||
{
|
||||
fromEntityId && toEntityId && <Form.Item label={t('sysAccountMove:attr.remark')}>
|
||||
<Input.TextArea
|
||||
value={remark || undefined}
|
||||
onChange={({ currentTarget }) => {
|
||||
const remark = currentTarget.value;
|
||||
setRemark(remark);
|
||||
}}
|
||||
rows={4}
|
||||
/>
|
||||
</Form.Item>
|
||||
}
|
||||
</Form>
|
||||
<Flex style={{ width: '100%', padding: 12 }} justify="end">
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={!fromEntityId || !toEntityId || !price || !externalId}
|
||||
onClick={() => createMove()}
|
||||
>
|
||||
{t('common::confirm')}
|
||||
</Button>
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"label": {
|
||||
"channel": "提现渠道",
|
||||
"channel": "转账渠道",
|
||||
"transferActualPrice": "实际转账金额",
|
||||
"sysAccountAmount": "系统账户余额",
|
||||
"cn": "创建者",
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export default function render(props: WebComponentProps<EntityDict, 'wpAccount',
|
|||
systemId={systemId}
|
||||
key="wpCreate"
|
||||
/>}
|
||||
{(wpAccount.wechatPayId && wechatPay?.$$createAt$$ !== 1) && <WechatPayUpsert
|
||||
{(wpAccount.wechatPayId && wpAccount?.$$createAt$$ !== 1) && <WechatPayUpsert
|
||||
oakPath={`${oakFullpath}.wechatPay`}
|
||||
systemId={systemId}
|
||||
key="wpUpdate"
|
||||
|
|
|
|||
|
|
@ -408,7 +408,34 @@ const i18ns: I18n[] = [
|
|||
"orderPriceSum": "订单总额",
|
||||
"orderManage": "订单管理",
|
||||
"orderList": "订单列表",
|
||||
"tips1": "总账户余额+退款总额+转账总额+订单总额应该等于系统账户总余额"
|
||||
"tips1": "总账户余额+退款总额+转账总额+订单总额应该等于系统账户总余额",
|
||||
"move": "移动资金"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "207fd2189d3697d15672176ae88f4175",
|
||||
namespace: "oak-pay-business-c-sysAccount-transferList",
|
||||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/sysAccount/transferList",
|
||||
data: {
|
||||
"label": {
|
||||
"channel": "转账渠道"
|
||||
},
|
||||
"tips": "正在转账的金额不计入任何账户,请到\"提现转账管理\"菜单完成操作"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "17a11f164c9977d8eb5b59fbc78755d5",
|
||||
namespace: "oak-pay-business-c-sysAccountMove-create",
|
||||
language: "zh-CN",
|
||||
module: "oak-pay-business",
|
||||
position: "src/components/sysAccountMove/create",
|
||||
data: {
|
||||
"label": {
|
||||
"from": "从账户",
|
||||
"to": "到账户"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -585,7 +612,7 @@ const i18ns: I18n[] = [
|
|||
position: "src/components/withdrawTransfer/list",
|
||||
data: {
|
||||
"label": {
|
||||
"channel": "提现渠道",
|
||||
"channel": "转账渠道",
|
||||
"transferActualPrice": "实际转账金额",
|
||||
"sysAccountAmount": "系统账户余额",
|
||||
"cn": "创建者",
|
||||
|
|
@ -788,7 +815,8 @@ const i18ns: I18n[] = [
|
|||
"error": {
|
||||
"nameQrCodeBothNull": "账号名和二维码不能同时为空",
|
||||
"refundGapDaysNotNegative": "允许退款天数不能为负数或空",
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间"
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间",
|
||||
"withdrawTransferLossRatioNotNegative": "提现转账费率必须在0到100之间"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
import {
|
||||
String,
|
||||
Text,
|
||||
Price,
|
||||
Boolean,
|
||||
Datetime,
|
||||
} from 'oak-domain/lib/types/DataType';
|
||||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDesc, ActionDef } from 'oak-domain/lib/types';
|
||||
import { Schema as User } from './User';
|
||||
import { Schema as System } from './System';
|
||||
|
||||
export interface Schema extends EntityShape {
|
||||
price: Price;
|
||||
externalId: String<64>;
|
||||
operator: User;
|
||||
remark?: Text;
|
||||
system: System;
|
||||
};
|
||||
|
||||
|
||||
export const entityDesc: EntityDesc<Schema> = {
|
||||
locales: {
|
||||
zh_CN: {
|
||||
name: '系统资金移动',
|
||||
attr: {
|
||||
price: '金额',
|
||||
externalId: '外部流水号',
|
||||
operator: '操作者',
|
||||
remark: '备注',
|
||||
system: '所属系统'
|
||||
},
|
||||
},
|
||||
},
|
||||
configuration: {
|
||||
actionType: 'appendOnly',
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import { EntityDesc, ActionDef } from 'oak-domain/lib/types';
|
|||
import { Schema as Pay } from './Pay';
|
||||
import { Schema as Refund } from './Refund';
|
||||
import { Schema as WithdrawTransfer } from './WithdrawTransfer';
|
||||
import { Schema as SysAccountMove} from './SysAccountMove';
|
||||
|
||||
export interface Schema extends EntityShape {
|
||||
delta: Price;
|
||||
|
|
@ -20,6 +21,7 @@ export interface Schema extends EntityShape {
|
|||
pay?: Pay;
|
||||
refund?: Refund;
|
||||
withdrawTransfer?: WithdrawTransfer;
|
||||
sysAccountMove?: SysAccountMove;
|
||||
};
|
||||
|
||||
export const entityDesc: EntityDesc<Schema, '', '', {
|
||||
|
|
@ -36,6 +38,7 @@ export const entityDesc: EntityDesc<Schema, '', '', {
|
|||
pay: '关联支付',
|
||||
refund: '关联退款',
|
||||
withdrawTransfer: '关联转账提现',
|
||||
sysAccountMove: '系统资金移动'
|
||||
},
|
||||
v: {
|
||||
type: {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
"error": {
|
||||
"nameQrCodeBothNull": "账号名和二维码不能同时为空",
|
||||
"refundGapDaysNotNegative": "允许退款天数不能为负数或空",
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间"
|
||||
"refundCompensateIllegal": "退款补偿百分比必须在0到100之间",
|
||||
"withdrawTransferLossRatioNotNegative": "提现转账费率必须在0到100之间"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue