This commit is contained in:
lxy 2025-07-18 17:21:18 +08:00
parent 5c0508cb33
commit c4021ff42c
168 changed files with 2352 additions and 626 deletions

View File

@ -99,22 +99,22 @@ const checkers = [
} }
break; break;
} }
case 'preSettle': { // case 'preSettle': {
//预分账时账户total增加avail不变refundable不变 // //预分账时账户total增加avail不变refundable不变
if (totalPlus < 0 || availPlus !== 0 || (refundablePlus && refundablePlus !== 0)) { // if (totalPlus < 0 || availPlus !== 0 || (refundablePlus && refundablePlus !== 0)) {
throw new OakInputIllegalException('accountOper', ['totalPlus', 'availPlus', 'refundablePlus'], 'accountOper为preSettle时其totalPlus必须为非负数、availPlus必须为0refundable必须为空或者0'); // throw new OakInputIllegalException('accountOper', ['totalPlus', 'availPlus', 'refundablePlus'], 'accountOper为preSettle时其totalPlus必须为非负数、availPlus必须为0refundable必须为空或者0');
} // }
break; // break;
} // }
case 'settle': { case 'settle': {
//分账时账户total不变refundable不变 //分账时账户total增加avail增加refundable不变
if (totalPlus !== 0 || (refundablePlus && refundablePlus !== 0)) { if (totalPlus < 0 || availPlus < 0 || (refundablePlus && refundablePlus !== 0)) {
throw new OakInputIllegalException('accountOper', ['totalPlus', 'refundablePlus'], 'accountOper为settle时其totalPlus必须为0refundable必须为空或者0'); throw new OakInputIllegalException('accountOper', ['totalPlus', 'refundablePlus'], 'accountOper为settle时其totalPlus、availPlus必须为非负数refundable必须为空或者0');
} }
break; break;
} }
default: { default: {
assert(false); // assert(false);
break; break;
} }
} }

View File

@ -9,6 +9,7 @@ import withdrawAccounts from './withdrawAccount';
import refundCheckers from './refund'; import refundCheckers from './refund';
import withdrawTransferCheckers from './withdrawTransfer'; import withdrawTransferCheckers from './withdrawTransfer';
import shipCheckers from './ship'; import shipCheckers from './ship';
import settlePlanCheckers from './settlePlan';
const checkers = [ const checkers = [
...refundCheckers, ...refundCheckers,
...withdrawAccounts, ...withdrawAccounts,
@ -21,5 +22,6 @@ const checkers = [
...wpProductCheckers, ...wpProductCheckers,
...withdrawTransferCheckers, ...withdrawTransferCheckers,
...shipCheckers, ...shipCheckers,
...settlePlanCheckers,
]; ];
export default checkers; export default checkers;

View File

@ -13,7 +13,8 @@ const checkers = [
} }
data.paid = 0; data.paid = 0;
data.refunded = 0; data.refunded = 0;
data.settled = false; data.settled = 0;
data.settlePlanned = 0;
if (!data.systemId) { if (!data.systemId) {
const contextSystemId = context.getApplication()?.systemId; const contextSystemId = context.getApplication()?.systemId;
assert(contextSystemId); assert(contextSystemId);
@ -105,51 +106,59 @@ const checkers = [
}); });
} }
}, },
/**todo settlePlan settle
{ {
// 订单结算检查存在关联的未结算的settlement其price之和等于订单的已支付与已退款的差值 // 订单结算检查存在关联的未结算的settlement其price之和等于订单的已支付与已退款的差值
type: 'logicalData', type: 'logicalData',
entity: 'order', entity: 'order',
action: 'settle', action: 'settle',
checker: (operation, context) => { checker: (operation, context) => {
const { data, filter } = operation; const { data, filter } = operation as EntityDict['order']['Update'];
assert(typeof filter.id === 'string');
assert(typeof filter!.id === 'string');
data.settled = true; data.settled = true;
return pipeline(() => context.select('order', { return pipeline(
data: { () => context.select('order', {
id: 1, data: {
price: 1, id: 1,
paid: 1, price: 1,
refunded: 1, paid: 1,
iState: 1, refunded: 1,
settlement$order: { iState: 1,
$entity: 'settlement', settlement$order: {
data: { $entity: 'settlement',
id: 1, data: {
accountId: 1, id: 1,
price: 1, accountId: 1,
iState: 1, price: 1,
}, iState: 1,
filter: { },
iState: 'unsettled' filter: {
iState: 'unsettled'
}
} }
} },
}, filter: {
filter: { id: filter!.id!,
id: filter.id, },
}, }, {}),
}, {}), (orders) => { (orders: EntityDict['order']['Schema'][]) => {
const [order] = orders; const [order] = orders;
const { price, paid, refunded, iState, settlement$order: settlements } = order; const { price, paid, refunded, iState, settlement$order: settlements } = order;
assert(['paid'].includes(iState) && refunded === 0 && paid === price); assert(['paid'].includes(iState!) && refunded === 0 && paid === price);
assert(settlements && settlements.length > 0, '该结算订单需添加结算明细'); assert(settlements && settlements.length > 0, '该结算订单需添加结算明细');
let amount = 0;
settlements.forEach((settlement) => { let amount = 0;
amount += settlement.price; settlements.forEach((settlement) => {
assert(settlement.iState === 'unsettled', '订单结算前settlement必须处于未分账状态'); amount += settlement.price;
}); assert(settlement.iState === 'unsettled', '订单结算前settlement必须处于未分账状态');
assert(amount === paid); })
}); assert(amount === paid);
}
);
} }
}, },
*/
]; ];
export default checkers; export default checkers;

5
es/checkers/settlePlan.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import { Checker } from 'oak-domain/lib/types/Auth';
import { EntityDict } from '../oak-app-domain';
import { RuntimeCxt } from '../types/RuntimeCxt';
declare const checkers: Checker<EntityDict, 'settlePlan', RuntimeCxt>[];
export default checkers;

105
es/checkers/settlePlan.js Normal file
View File

@ -0,0 +1,105 @@
import { pipeline } from 'oak-domain/lib/utils/executor';
import { assert } from 'oak-domain/lib/utils/assert';
const checkers = [
{
/**
* 1settlement.price总和等于settlePlan.price
* 2settlePlan.price <= order.paid - order.refunded - order.settlePlanned
*/
entity: 'settlePlan',
action: 'create',
type: 'logicalData',
priority: 1,
checker: (operation, context) => {
const { data } = operation;
const checkfn = (settlePlan) => {
return pipeline(() => context.select('order', {
data: {
id: 1,
paid: 1,
refunded: 1,
settlePlanned: 1,
},
filter: {
id: settlePlan.orderId,
},
}, { dontCollect: true }), (orders) => {
const [order] = orders;
const { paid, refunded, settlePlanned } = order;
const orderPrice = paid - refunded - settlePlanned;
assert(settlePlan.price <= orderPrice, '结算计划金额不大于订单可结算金额');
return context.select('settlement', {
data: {
id: 1,
price: 1,
iState: 1,
planId: 1,
},
filter: {
planId: settlePlan.id,
iState: 'unsettled',
},
}, { dontCollect: true });
}, (settlements) => {
let amount = 0;
settlements.forEach((settlement) => amount += settlement.price);
if (settlePlan.settlement$plan && settlePlan.settlement$plan.length > 0) {
for (const settlementOper of settlePlan.settlement$plan) {
const settlementData = settlementOper.data;
if (settlementData instanceof Array) {
settlementData.forEach((s) => amount += s.price ?? 0);
}
else {
amount += settlementData?.price ?? 0;
}
}
}
assert(amount === settlePlan.price, '结算计划金额需等于关联的结算明细金额总和');
});
};
if (data instanceof Array) {
for (const d of data) {
checkfn(d);
}
}
else {
checkfn(data);
}
}
},
{
entity: 'settlePlan',
action: 'close',
type: 'logicalData',
checker: (operation, context) => {
const { filter } = operation;
return pipeline(() => context.select('settlePlan', {
data: {
id: 1,
price: 1,
iState: 1,
settlement$plan: {
$entity: 'settlement',
data: {
id: 1,
price: 1,
iState: 1,
},
filter: {
iState: 'unsettled',
}
}
},
filter,
}, { dontCollect: true }), (settlePlans) => {
for (const settlePlan of settlePlans) {
const { price: planPrice, settlement$plan: settlements } = settlePlan;
let amount = 0;
settlements.forEach((settlement) => amount += settlement.price);
assert(amount === planPrice, '结算计划金额需等于未结算的结算明细金额总和');
}
});
}
}
];
export default checkers;

View File

@ -4,15 +4,71 @@
*/ */
import React from 'react'; import React from 'react';
import { EntityDict } from '../oak-app-domain'; import { EntityDict } from '../oak-app-domain';
import { ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef } from 'oak-frontend-base'; import { ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef, ListButtonProps, OakAbsAttrUpsertDef } from 'oak-frontend-base';
import AbsFilterPanel from 'oak-frontend-base/es/components/filterPanel'; declare const FilterPanel: <T extends keyof EntityDict>(props: ReactComponentProps<EntityDict, T, false, {
import AbsList from 'oak-frontend-base/es/components/list'; entity: T;
import AbsListPro from 'oak-frontend-base/es/components/listPro'; columns: ColumnProps<EntityDict, T>[];
import AbsDetail from 'oak-frontend-base/es/components/detail'; }>) => React.ReactElement;
import AbsUpsert from 'oak-frontend-base/es/components/upsert'; declare const List: <T extends keyof EntityDict>(props: ReactComponentProps<EntityDict, T, false, {
declare const FilterPanel: <T extends keyof EntityDict>(...props: Parameters<typeof AbsFilterPanel<EntityDict, T>>) => React.ReactElement; entity: T;
declare const List: <T extends keyof EntityDict>(...props: Parameters<typeof AbsList<EntityDict, T>>) => React.ReactElement; extraActions: OakExtraActionProps[] | ((row: RowWithActions<EntityDict, T>) => OakExtraActionProps[]);
declare const ListPro: <T extends keyof EntityDict>(...props: Parameters<typeof AbsListPro<EntityDict, T>>) => React.ReactElement; onAction: onActionFnDef;
declare const Detail: <T extends keyof EntityDict>(...props: Parameters<typeof AbsDetail<EntityDict, T>>) => React.ReactElement; disabledOp: boolean;
declare const Upsert: <T extends keyof EntityDict>(...props: Parameters<typeof AbsUpsert<EntityDict, T>>) => React.ReactElement; attributes: OakAbsAttrDef[];
data: RowWithActions<EntityDict, T>[];
loading: boolean;
tablePagination?: React.ReactNode;
rowSelection?: any;
hideHeader?: boolean | undefined;
disableSerialNumber?: boolean | undefined;
size?: "small" | "middle" | "large" | undefined;
scroll?: ({
x?: string | number | true | undefined;
y?: string | number | undefined;
} & {
scrollToFirstRowOnChange?: boolean | undefined;
}) | undefined;
empty?: React.ReactNode;
opWidth?: number | undefined;
ellipsis?: boolean | undefined;
}>) => React.ReactElement;
declare const ListPro: <T extends keyof EntityDict>(props: {
title?: any;
extraContent?: any;
hideDefaultButtons?: boolean | undefined;
buttonGroup?: ListButtonProps[] | undefined;
onReload?: (() => void) | undefined;
entity: T;
extraActions?: OakExtraActionProps[] | ((row: RowWithActions<EntityDict, T>) => OakExtraActionProps[]) | undefined;
onAction?: onActionFnDef | undefined;
disabledOp?: boolean | undefined;
attributes: OakAbsAttrDef[];
data: RowWithActions<EntityDict, T>[];
loading?: boolean | undefined;
tablePagination?: any;
rowSelection?: any;
disableSerialNumber?: boolean | undefined;
size?: "small" | "middle" | "large" | undefined;
scroll?: any;
empty?: any;
opWidth?: number | undefined;
oakPath?: string | undefined;
}) => React.ReactElement;
declare const Detail: <T extends keyof EntityDict>(props: ReactComponentProps<EntityDict, T, false, {
column?: number | Record<Breakpoint, number> | undefined;
entity: T;
attributes: OakAbsAttrDef[];
data: Partial<EntityDict[T]["Schema"]>;
title?: string | undefined;
bordered?: boolean | 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: "horizontal" | "vertical";
mode: "default" | "card";
}>) => React.ReactElement;
export { FilterPanel, List, ListPro, Detail, Upsert, ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef, }; export { FilterPanel, List, ListPro, Detail, Upsert, ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef, };

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { EntityDict } from "../../../oak-app-domain"; import { EntityDict } from "../../../oak-app-domain";
export default function Render(props: { export default function Render(props: {
accountOpers: EntityDict['accountOper']['OpSchema'][]; accountOpers: EntityDict['accountOper']['OpSchema'][];

View File

@ -1,2 +1,3 @@
/// <reference types="wechat-miniprogram" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "offlineAccount", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement; declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "offlineAccount", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
export default _default; export default _default;

View File

@ -1,2 +1,3 @@
/// <reference types="wechat-miniprogram" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "order", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement; declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "order", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
export default _default; export default _default;

View File

@ -2,7 +2,7 @@ import { EntityDict } from "../../../oak-app-domain";
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "order", false, { declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "order", false, {
accountId: string; accountId: string;
accountAvailMax: number; accountAvailMax: number;
onSetPays: (pays: Partial<EntityDict["pay"]["CreateOperationData"]>[]) => void; onSetPays: (pays: Partial<EntityDict['pay']['CreateOperationData']>[]) => void;
accountTips: string; accountTips: string;
autoStartPay: boolean; autoStartPay: boolean;
}>) => React.ReactElement; }>) => React.ReactElement;

View File

@ -24,10 +24,10 @@ export default OakComponent({
}, },
isList: false, isList: false,
properties: { properties: {
accountId: '', // 是否可以使用帐户中的余额抵扣 accountId: '',
accountAvailMax: 0, // 本次交易可以使用的帐户中的Avail max值调用者自己保证此数值的一致性不要扣成负数 accountAvailMax: 0,
onSetPays: (pays) => undefined, onSetPays: (pays) => undefined,
accountTips: '', // 使用余额支付的提示说明 accountTips: '',
autoStartPay: false, autoStartPay: false,
}, },
formData({ data }) { formData({ data }) {

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
export default function Info(props: { export default function Info(props: {
price: number; price: number;
t: (k: string) => string; t: (k: string) => string;

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { PayChannelOption } from "../../../types/Pay"; import { PayChannelOption } from "../../../types/Pay";
export default function Render(props: { export default function Render(props: {
data: { data: {

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { PayChannelOption } from "../../../types/Pay"; import { PayChannelOption } from "../../../types/Pay";
export default function Render(props: { export default function Render(props: {
data: { data: {

View File

@ -1,2 +1,3 @@
/// <reference types="wechat-miniprogram" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "pay", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement; declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "pay", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
export default _default; export default _default;

View File

@ -1,2 +1,3 @@
/// <reference types="wechat-miniprogram" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "system", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement; declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "system", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
export default _default; export default _default;

View File

@ -1,2 +1,3 @@
/// <reference types="wechat-miniprogram" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "refund", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement; declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "refund", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
export default _default; export default _default;

View File

@ -1,2 +1,3 @@
/// <reference types="wechat-miniprogram" />
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "system", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement; declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "system", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
export default _default; export default _default;

View File

@ -1,3 +1,4 @@
/// <reference types="wechat-miniprogram" />
import { EntityDict } from "../../../../oak-app-domain"; import { EntityDict } from "../../../../oak-app-domain";
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "wechatMpShip", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement; declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "wechatMpShip", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
export default _default; export default _default;

View File

@ -156,7 +156,7 @@ export default OakComponent({
}, },
}, },
filter: { filter: {
settled: false, settled: 0,
price: { price: {
$gt: 0, $gt: 0,
}, },

View File

@ -1,2 +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; declare const _default: (props: import("oak-frontend-base").ReactComponentProps<import("../../../oak-app-domain").EntityDict, "withdrawTransfer", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
export default _default; export default _default;

View File

@ -1,3 +1,4 @@
/// <reference types="wechat-miniprogram" />
import { EntityDict } from "../../../oak-app-domain"; import { EntityDict } from "../../../oak-app-domain";
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "withdraw", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement; declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "withdraw", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
export default _default; export default _default;

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { EntityDict } from '../../../oak-app-domain'; import { EntityDict } from '../../../oak-app-domain';
export default function render(props: { export default function render(props: {
data: { data: {

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { EntityDict } from '../../../oak-app-domain'; import { EntityDict } from '../../../oak-app-domain';
export default function render(props: { export default function render(props: {
data: { data: {

View File

@ -1,3 +1,4 @@
/// <reference types="wechat-miniprogram" />
import { EntityDict } from '../../../oak-app-domain'; import { EntityDict } from '../../../oak-app-domain';
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "withdrawTransfer", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement; declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "withdrawTransfer", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
export default _default; export default _default;

View File

@ -924,7 +924,9 @@ const i18ns = [
"create": { "create": {
"hasAnotherRefunding": "您有一笔退款正在进行中", "hasAnotherRefunding": "您有一笔退款正在进行中",
"exceedMax": "退款额度大于可用值", "exceedMax": "退款额度大于可用值",
"payUnrefundable": "支付已经不可退款" "payUnrefundable": "支付已经不可退款",
"opersNotEnough": "指定退款帐户的操作金额总和不足",
"opersExceed": "指定退款帐户的操作金额总和超过订单已结算金额"
} }
}, },
"pay": { "pay": {
@ -932,7 +934,11 @@ const i18ns = [
"priceOverflow": "支付金额总和大于订单金额" "priceOverflow": "支付金额总和大于订单金额"
}, },
"ship": { "ship": {
"noClazz": "当前物流未关联外部接口" "noClazz": "当前物流未关联外部接口",
"uploadShipException": "小程序上传发货信息异常"
},
"settlePlan": {
"exceed": "结算计划总金额超过订单可结算金额上限"
} }
} }
}, },

View File

@ -2,7 +2,7 @@ import { String, Price } from 'oak-domain/lib/types/DataType';
import { EntityShape } from 'oak-domain/lib/types/Entity'; import { EntityShape } from 'oak-domain/lib/types/Entity';
import { EntityDesc } from 'oak-domain/lib/types'; import { EntityDesc } from 'oak-domain/lib/types';
import { Schema as Account } from './Account'; import { Schema as Account } from './Account';
type Type = 'deposit' | 'withdraw' | 'consume' | 'consumeBack' | 'loan' | 'repay' | 'withdrawBack' | 'earn' | 'cutoffRefundable' | 'tax' | 'taxRefund' | 'refund' | 'refundFailure' | 'preSettle' | 'settle'; type Type = 'deposit' | 'withdraw' | 'consume' | 'consumeBack' | 'loan' | 'repay' | 'withdrawBack' | 'earn' | 'cutoffRefundable' | 'tax' | 'taxRefund' | 'refund' | 'refundFailure' | 'settle';
export interface Schema extends EntityShape { export interface Schema extends EntityShape {
account: Account; account: Account;
type: Type; type: Type;

View File

@ -30,7 +30,6 @@ export const entityDesc = {
cutoffRefundable: '削减可自由退额度', cutoffRefundable: '削减可自由退额度',
refund: '退款', refund: '退款',
refundFailure: '退款失败', refundFailure: '退款失败',
preSettle: '预分账',
settle: '分账', settle: '分账',
}, },
}, },
@ -52,7 +51,6 @@ export const entityDesc = {
cutoffRefundable: '#2E4053', cutoffRefundable: '#2E4053',
refund: '#CC3333', refund: '#CC3333',
refundFailure: '#009933', refundFailure: '#009933',
preSettle: '#8A631D',
settle: '#157d5a', settle: '#157d5a',
} }
} }

View File

@ -30,7 +30,7 @@ export const entityDesc = {
keyType: '指定应用私钥类型', keyType: '指定应用私钥类型',
gateway: "支付宝网关地址", gateway: "支付宝网关地址",
wsServiceUrl: 'websocket服务地址', wsServiceUrl: 'websocket服务地址',
timeout: "网关超时时间", //(单位毫秒),默认值是 5000 timeout: "网关超时时间",
needEncrypt: "是否需要AES加解密", needEncrypt: "是否需要AES加解密",
encryptKey: 'AES密钥', //调用AES加解密相关接口时需要 encryptKey: 'AES密钥', //调用AES加解密相关接口时需要
}, },

View File

@ -9,13 +9,14 @@ export interface Schema extends EntityShape {
price: Price; price: Price;
paid: Price; paid: Price;
refunded: Price; refunded: Price;
settled: Price;
settlePlanned: Price;
title: String<32>; title: String<32>;
desc: Text; desc: Text;
timeoutAt?: Datetime; timeoutAt?: Datetime;
creator: User; creator: User;
entity: String<32>; entity: String<32>;
entityId: String<64>; entityId: String<64>;
settled: Boolean;
allowPartialPay?: Boolean; allowPartialPay?: Boolean;
system: System; system: System;
address?: Address; address?: Address;
@ -25,7 +26,7 @@ export interface Schema extends EntityShape {
export type IAction = 'startPaying' | 'payAll' | 'payPartially' | 'payNone' | 'timeout' | 'cancel' | 'startRefunding' | 'refundAll' | 'refundPartially' | 'refundNone'; export type IAction = 'startPaying' | 'payAll' | 'payPartially' | 'payNone' | 'timeout' | 'cancel' | 'startRefunding' | 'refundAll' | 'refundPartially' | 'refundNone';
export type IState = 'unpaid' | 'timeout' | 'cancelled' | 'paying' | 'partiallyPaid' | 'paid' | 'refunding' | 'partiallyRefunded' | 'refunded'; export type IState = 'unpaid' | 'timeout' | 'cancelled' | 'paying' | 'partiallyPaid' | 'paid' | 'refunding' | 'partiallyRefunded' | 'refunded';
export declare const IActionDef: ActionDef<IAction, IState>; export declare const IActionDef: ActionDef<IAction, IState>;
export type Action = IAction | 'settle'; export type Action = IAction;
export declare const entityDesc: EntityDesc<Schema, Action, '', { export declare const entityDesc: EntityDesc<Schema, Action, '', {
iState: IState; iState: IState;
}>; }>;

View File

@ -51,6 +51,8 @@ export const entityDesc = {
price: '订单金额', price: '订单金额',
paid: '已支付金额', paid: '已支付金额',
refunded: '已退款金额', refunded: '已退款金额',
settled: '已结算金额',
settlePlanned: '已计划结算金额',
iState: '订单状态', iState: '订单状态',
title: '订单标题', title: '订单标题',
desc: "订单描述", desc: "订单描述",
@ -59,7 +61,6 @@ export const entityDesc = {
creator: '创建者', creator: '创建者',
entity: '关联对象', entity: '关联对象',
entityId: '关联对象Id', entityId: '关联对象Id',
settled: '是否结算',
opers: '相关帐户操作', opers: '相关帐户操作',
system: '所属系统', system: '所属系统',
address: '收货地址', address: '收货地址',
@ -76,7 +77,6 @@ export const entityDesc = {
refundAll: '完全退款', refundAll: '完全退款',
refundNone: '退款失败', refundNone: '退款失败',
refundPartially: '部分退款', refundPartially: '部分退款',
settle: '结算',
}, },
v: { v: {
iState: { iState: {
@ -105,7 +105,6 @@ export const entityDesc = {
refundAll: '', refundAll: '',
refundNone: '', refundNone: '',
refundPartially: '', refundPartially: '',
settle: '',
}, },
color: { color: {
iState: { iState: {

17
es/entities/SettlePlan.d.ts vendored Normal file
View File

@ -0,0 +1,17 @@
import { Price, 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 Order } from './Order';
export interface Schema extends EntityShape {
when?: Datetime;
order: Order;
price: Price;
}
type IState = 'unsettled' | 'settled' | 'closed';
type IAction = 'settle' | 'close';
export declare const IActionDef: ActionDef<IAction, IState>;
type Action = IAction;
export declare const entityDesc: EntityDesc<Schema, Action, '', {
iState: IState;
}>;
export {};

45
es/entities/SettlePlan.js Normal file
View File

@ -0,0 +1,45 @@
;
export const IActionDef = {
stm: {
settle: ['unsettled', 'settled'],
close: ['unsettled', 'closed'],
},
is: 'unsettled',
};
export const entityDesc = {
locales: {
zh_CN: {
name: '结算计划',
attr: {
when: '结算时间',
order: '订单',
price: '结算金额',
iState: '结算计划状态',
},
action: {
settle: '结算',
close: '关闭',
},
v: {
iState: {
unsettled: '未结算',
settled: '已结算',
closed: '已关闭',
},
},
},
},
style: {
icon: {
settle: '',
close: '',
},
color: {
iState: {
unsettled: '#52BE80',
settled: '#2E86C1',
closed: '#8C949C'
},
}
},
};

View File

@ -2,18 +2,18 @@ import { Price } from 'oak-domain/lib/types/DataType';
import { EntityShape } from 'oak-domain/lib/types/Entity'; import { EntityShape } from 'oak-domain/lib/types/Entity';
import { EntityDesc, ActionDef } from 'oak-domain/lib/types'; import { EntityDesc, ActionDef } from 'oak-domain/lib/types';
import { Schema as Account } from './Account'; import { Schema as Account } from './Account';
import { Schema as Order } from './Order'; import { Schema as SettlePlan } from './SettlePlan';
import { Schema as AccountOper } from './AccountOper'; import { Schema as AccountOper } from './AccountOper';
export interface Schema extends EntityShape { export interface Schema extends EntityShape {
account: Account; account: Account;
plan: SettlePlan;
price: Price; price: Price;
order: Order;
opers?: AccountOper[]; opers?: AccountOper[];
} }
type IState = 'unsettled' | 'settled'; type IState = 'unsettled' | 'settled' | 'closed';
type IAction = 'settle'; type IAction = 'settle' | 'close';
export declare const IActionDef: ActionDef<IAction, IState>; export declare const IActionDef: ActionDef<IAction, IState>;
type Action = IAction | 'preSettle' | 'refund' | 'refundFailure'; type Action = IAction | 'refund' | 'refundFailure';
export declare const entityDesc: EntityDesc<Schema, Action, '', { export declare const entityDesc: EntityDesc<Schema, Action, '', {
iState: IState; iState: IState;
}>; }>;

View File

@ -2,6 +2,7 @@
export const IActionDef = { export const IActionDef = {
stm: { stm: {
settle: ['unsettled', 'settled'], settle: ['unsettled', 'settled'],
close: ['unsettled', 'closed'],
}, },
is: 'unsettled', is: 'unsettled',
}; };
@ -11,14 +12,14 @@ export const entityDesc = {
name: '结算明细', name: '结算明细',
attr: { attr: {
account: '帐号', account: '帐号',
plan: '结算计划',
price: '变化金额', price: '变化金额',
order: '订单',
iState: '结算状态', iState: '结算状态',
opers: '相关帐户操作', opers: '相关帐户操作',
}, },
action: { action: {
preSettle: '预结算',
settle: '结算', settle: '结算',
close: '关闭',
refund: '退款', refund: '退款',
refundFailure: '退款失败', refundFailure: '退款失败',
}, },
@ -26,6 +27,7 @@ export const entityDesc = {
iState: { iState: {
unsettled: '未结算', unsettled: '未结算',
settled: '已结算', settled: '已结算',
closed: '已关闭',
}, },
}, },
}, },
@ -40,6 +42,7 @@ export const entityDesc = {
iState: { iState: {
unsettled: '#52BE80', unsettled: '#52BE80',
settled: '#2E86C1', settled: '#2E86C1',
closed: '#8C949C'
}, },
} }
}, },

View File

@ -21,7 +21,9 @@
"create": { "create": {
"hasAnotherRefunding": "您有一笔退款正在进行中", "hasAnotherRefunding": "您有一笔退款正在进行中",
"exceedMax": "退款额度大于可用值", "exceedMax": "退款额度大于可用值",
"payUnrefundable": "支付已经不可退款" "payUnrefundable": "支付已经不可退款",
"opersNotEnough": "指定退款帐户的操作金额总和不足",
"opersExceed": "指定退款帐户的操作金额总和超过订单已结算金额"
} }
}, },
"pay": { "pay": {
@ -29,6 +31,10 @@
"priceOverflow": "支付金额总和大于订单金额" "priceOverflow": "支付金额总和大于订单金额"
}, },
"ship": { "ship": {
"noClazz": "当前物流未关联外部接口" "noClazz": "当前物流未关联外部接口",
"uploadShipException": "小程序上传发货信息异常"
},
"settlePlan": {
"exceed": "结算计划总金额超过订单可结算金额上限"
} }
} }

View File

@ -9,7 +9,7 @@ export const desc = {
type: { type: {
notNull: true, notNull: true,
type: "enum", type: "enum",
enumeration: ["deposit", "withdraw", "consume", "consumeBack", "loan", "repay", "withdrawBack", "earn", "cutoffRefundable", "tax", "taxRefund", "refund", "refundFailure", "preSettle", "settle"] enumeration: ["deposit", "withdraw", "consume", "consumeBack", "loan", "repay", "withdrawBack", "earn", "cutoffRefundable", "tax", "taxRefund", "refund", "refundFailure", "settle"]
}, },
totalPlus: { totalPlus: {
notNull: true, notNull: true,

View File

@ -14,7 +14,6 @@ export const style = {
cutoffRefundable: '#2E4053', cutoffRefundable: '#2E4053',
refund: '#CC3333', refund: '#CC3333',
refundFailure: '#009933', refundFailure: '#009933',
preSettle: '#8A631D',
settle: '#157d5a', settle: '#157d5a',
} }
} }

View File

@ -3,7 +3,7 @@ import { Q_DateValue, Q_NumberValue, Q_StringValue, Q_EnumValue, NodeId, ExprOp,
import { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/Entity"; import { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/Entity";
import { AppendOnlyAction } from "oak-domain/lib/actions/action"; import { AppendOnlyAction } from "oak-domain/lib/actions/action";
import { Price, String } from "oak-domain/lib/types/DataType"; import { Price, String } from "oak-domain/lib/types/DataType";
type Type = "deposit" | "withdraw" | "consume" | "consumeBack" | "loan" | "repay" | "withdrawBack" | "earn" | "cutoffRefundable" | "tax" | "taxRefund" | "refund" | "refundFailure" | "preSettle" | "settle"; type Type = "deposit" | "withdraw" | "consume" | "consumeBack" | "loan" | "repay" | "withdrawBack" | "earn" | "cutoffRefundable" | "tax" | "taxRefund" | "refund" | "refundFailure" | "settle";
export type OpSchema = EntityShape & { export type OpSchema = EntityShape & {
accountId: ForeignKey<"account">; accountId: ForeignKey<"account">;
type: Type; type: Type;

View File

@ -27,7 +27,6 @@
"cutoffRefundable": "削减可自由退额度", "cutoffRefundable": "削减可自由退额度",
"refund": "退款", "refund": "退款",
"refundFailure": "退款失败", "refundFailure": "退款失败",
"preSettle": "预分账",
"settle": "分账" "settle": "分账"
} }
} }

View File

@ -64,6 +64,9 @@ export declare const actionDefDict: {
settlement: { settlement: {
iState: import("oak-domain/lib/types").ActionDef<string, string>; iState: import("oak-domain/lib/types").ActionDef<string, string>;
}; };
settlePlan: {
iState: import("oak-domain/lib/types").ActionDef<string, string>;
};
ship: { ship: {
iState: import("oak-domain/lib/types").ActionDef<string, string>; iState: import("oak-domain/lib/types").ActionDef<string, string>;
}; };

View File

@ -24,6 +24,7 @@ import { actionDefDict as order } from "./Order/Action";
import { actionDefDict as pay } from "./Pay/Action"; import { actionDefDict as pay } from "./Pay/Action";
import { actionDefDict as refund } from "./Refund/Action"; import { actionDefDict as refund } from "./Refund/Action";
import { actionDefDict as settlement } from "./Settlement/Action"; import { actionDefDict as settlement } from "./Settlement/Action";
import { actionDefDict as settlePlan } from "./SettlePlan/Action";
import { actionDefDict as ship } from "./Ship/Action"; import { actionDefDict as ship } from "./Ship/Action";
import { actionDefDict as user } from "./User/Action"; import { actionDefDict as user } from "./User/Action";
import { actionDefDict as withdraw } from "./Withdraw/Action"; import { actionDefDict as withdraw } from "./Withdraw/Action";
@ -58,6 +59,7 @@ export const actionDefDict = {
pay, pay,
refund, refund,
settlement, settlement,
settlePlan,
ship, ship,
user, user,
withdraw, withdraw,

View File

@ -72,6 +72,7 @@ import * as BaseOrder from "./Order/_baseSchema";
import * as BasePay from "./Pay/_baseSchema"; import * as BasePay from "./Pay/_baseSchema";
import * as BaseRefund from "./Refund/_baseSchema"; import * as BaseRefund from "./Refund/_baseSchema";
import * as BaseSettlement from "./Settlement/_baseSchema"; import * as BaseSettlement from "./Settlement/_baseSchema";
import * as BaseSettlePlan from "./SettlePlan/_baseSchema";
import * as BaseShip from "./Ship/_baseSchema"; import * as BaseShip from "./Ship/_baseSchema";
import * as BaseShipCompany from "./ShipCompany/_baseSchema"; import * as BaseShipCompany from "./ShipCompany/_baseSchema";
import * as BaseShipOrder from "./ShipOrder/_baseSchema"; import * as BaseShipOrder from "./ShipOrder/_baseSchema";
@ -4411,11 +4412,11 @@ export type Order = {
system: System["Schema"]; system: System["Schema"];
address?: Address["Schema"]; address?: Address["Schema"];
pay$order?: Array<Omit<Pay["Schema"], "order">>; pay$order?: Array<Omit<Pay["Schema"], "order">>;
settlement$order?: Array<Omit<Settlement["Schema"], "order">>; settlePlan$order?: Array<Omit<SettlePlan["Schema"], "order">>;
shipOrder$order?: Array<Omit<ShipOrder["Schema"], "order">>; shipOrder$order?: Array<Omit<ShipOrder["Schema"], "order">>;
accountOper$entity?: Array<Omit<AccountOper["Schema"], "entity">>; accountOper$entity?: Array<Omit<AccountOper["Schema"], "entity">>;
pay$order$$aggr?: AggregationResult<Omit<Pay["Schema"], "order">>; pay$order$$aggr?: AggregationResult<Omit<Pay["Schema"], "order">>;
settlement$order$$aggr?: AggregationResult<Omit<Settlement["Schema"], "order">>; settlePlan$order$$aggr?: AggregationResult<Omit<SettlePlan["Schema"], "order">>;
shipOrder$order$$aggr?: AggregationResult<Omit<ShipOrder["Schema"], "order">>; shipOrder$order$$aggr?: AggregationResult<Omit<ShipOrder["Schema"], "order">>;
accountOper$entity$$aggr?: AggregationResult<Omit<AccountOper["Schema"], "entity">>; accountOper$entity$$aggr?: AggregationResult<Omit<AccountOper["Schema"], "entity">>;
}; };
@ -4429,11 +4430,11 @@ export type Order = {
pay$order$$aggr?: DeduceAggregation<Omit<Pay["Projection"], "order">, Omit<Pay["Filter"], "order">, Pay["Sorter"]> & { pay$order$$aggr?: DeduceAggregation<Omit<Pay["Projection"], "order">, Omit<Pay["Filter"], "order">, Pay["Sorter"]> & {
$entity: "pay"; $entity: "pay";
}; };
settlement$order?: OakSelection<"select", Omit<Settlement["Projection"], "order">, Omit<Settlement["Filter"], "order">, Settlement["Sorter"]> & { settlePlan$order?: OakSelection<"select", Omit<SettlePlan["Projection"], "order">, Omit<SettlePlan["Filter"], "order">, SettlePlan["Sorter"]> & {
$entity: "settlement"; $entity: "settlePlan";
}; };
settlement$order$$aggr?: DeduceAggregation<Omit<Settlement["Projection"], "order">, Omit<Settlement["Filter"], "order">, Settlement["Sorter"]> & { settlePlan$order$$aggr?: DeduceAggregation<Omit<SettlePlan["Projection"], "order">, Omit<SettlePlan["Filter"], "order">, SettlePlan["Sorter"]> & {
$entity: "settlement"; $entity: "settlePlan";
}; };
shipOrder$order?: OakSelection<"select", Omit<ShipOrder["Projection"], "order">, Omit<ShipOrder["Filter"], "order">, ShipOrder["Sorter"]> & { shipOrder$order?: OakSelection<"select", Omit<ShipOrder["Projection"], "order">, Omit<ShipOrder["Filter"], "order">, ShipOrder["Sorter"]> & {
$entity: "shipOrder"; $entity: "shipOrder";
@ -4453,7 +4454,7 @@ export type Order = {
system: MakeFilter<System["FilterUnit"]>; system: MakeFilter<System["FilterUnit"]>;
address: MakeFilter<Address["FilterUnit"]>; address: MakeFilter<Address["FilterUnit"]>;
pay$order: MakeFilter<Omit<Pay["FilterUnit"], "order">> & SubQueryPredicateMetadata; pay$order: MakeFilter<Omit<Pay["FilterUnit"], "order">> & SubQueryPredicateMetadata;
settlement$order: MakeFilter<Omit<Settlement["FilterUnit"], "order">> & SubQueryPredicateMetadata; settlePlan$order: MakeFilter<Omit<SettlePlan["FilterUnit"], "order">> & SubQueryPredicateMetadata;
shipOrder$order: MakeFilter<Omit<ShipOrder["FilterUnit"], "order">> & SubQueryPredicateMetadata; shipOrder$order: MakeFilter<Omit<ShipOrder["FilterUnit"], "order">> & SubQueryPredicateMetadata;
accountOper$entity: MakeFilter<Omit<AccountOper["FilterUnit"], "entity">> & SubQueryPredicateMetadata; accountOper$entity: MakeFilter<Omit<AccountOper["FilterUnit"], "entity">> & SubQueryPredicateMetadata;
}; };
@ -4475,7 +4476,7 @@ export type Order = {
system?: OakOperation<"create", System["CreateOperationData"]> | OakOperation<BaseSystem.OpUpdateAction, System["UpdateOperationData"], System["Filter"]>; system?: OakOperation<"create", System["CreateOperationData"]> | OakOperation<BaseSystem.OpUpdateAction, System["UpdateOperationData"], System["Filter"]>;
address?: OakOperation<"create", Address["CreateOperationData"]> | OakOperation<BaseAddress.OpUpdateAction, Address["UpdateOperationData"], Address["Filter"]>; address?: OakOperation<"create", Address["CreateOperationData"]> | OakOperation<BaseAddress.OpUpdateAction, Address["UpdateOperationData"], Address["Filter"]>;
pay$order?: (OakOperation<"create", Omit<Pay["CreateOperationData"], "order"> | Omit<Pay["CreateOperationData"], "order">[]> | OakOperation<BasePay.OpUpdateAction, Omit<Pay["UpdateOperationData"], "order">, Pay["Filter"]>)[]; pay$order?: (OakOperation<"create", Omit<Pay["CreateOperationData"], "order"> | Omit<Pay["CreateOperationData"], "order">[]> | OakOperation<BasePay.OpUpdateAction, Omit<Pay["UpdateOperationData"], "order">, Pay["Filter"]>)[];
settlement$order?: (OakOperation<"create", Omit<Settlement["CreateOperationData"], "order"> | Omit<Settlement["CreateOperationData"], "order">[]> | OakOperation<BaseSettlement.OpUpdateAction, Omit<Settlement["UpdateOperationData"], "order">, Settlement["Filter"]>)[]; settlePlan$order?: (OakOperation<"create", Omit<SettlePlan["CreateOperationData"], "order"> | Omit<SettlePlan["CreateOperationData"], "order">[]> | OakOperation<BaseSettlePlan.OpUpdateAction, Omit<SettlePlan["UpdateOperationData"], "order">, SettlePlan["Filter"]>)[];
shipOrder$order?: (OakOperation<"create", Omit<ShipOrder["CreateOperationData"], "order"> | Omit<ShipOrder["CreateOperationData"], "order">[]> | OakOperation<BaseShipOrder.OpUpdateAction, Omit<ShipOrder["UpdateOperationData"], "order">, ShipOrder["Filter"]>)[]; shipOrder$order?: (OakOperation<"create", Omit<ShipOrder["CreateOperationData"], "order"> | Omit<ShipOrder["CreateOperationData"], "order">[]> | OakOperation<BaseShipOrder.OpUpdateAction, Omit<ShipOrder["UpdateOperationData"], "order">, ShipOrder["Filter"]>)[];
accountOper$entity?: OakOperation<"create", Omit<AccountOper["CreateOperationData"], "order"> | Omit<AccountOper["CreateOperationData"], "order">[]>[]; accountOper$entity?: OakOperation<"create", Omit<AccountOper["CreateOperationData"], "order"> | Omit<AccountOper["CreateOperationData"], "order">[]>[];
}>; }>;
@ -4487,7 +4488,7 @@ export type Order = {
system?: OakOperation<"create", System["CreateOperationData"]> | OakOperation<BaseSystem.OpUpdateAction, System["UpdateOperationData"], System["Filter"]> | OakOperation<"remove", System["RemoveOperationData"], System["Filter"]>; system?: OakOperation<"create", System["CreateOperationData"]> | OakOperation<BaseSystem.OpUpdateAction, System["UpdateOperationData"], System["Filter"]> | OakOperation<"remove", System["RemoveOperationData"], System["Filter"]>;
address?: OakOperation<"create", Address["CreateOperationData"]> | OakOperation<BaseAddress.OpUpdateAction, Address["UpdateOperationData"], Address["Filter"]> | OakOperation<"remove", Address["RemoveOperationData"], Address["Filter"]>; address?: OakOperation<"create", Address["CreateOperationData"]> | OakOperation<BaseAddress.OpUpdateAction, Address["UpdateOperationData"], Address["Filter"]> | OakOperation<"remove", Address["RemoveOperationData"], Address["Filter"]>;
pay$order?: (OakOperation<"create", Omit<Pay["CreateOperationData"], "order"> | Omit<Pay["CreateOperationData"], "order">[]> | OakOperation<BasePay.OpUpdateAction, Omit<Pay["UpdateOperationData"], "order">, Pay["Filter"]> | OakOperation<"remove", Pay["RemoveOperationData"], Pay["Filter"]>)[]; pay$order?: (OakOperation<"create", Omit<Pay["CreateOperationData"], "order"> | Omit<Pay["CreateOperationData"], "order">[]> | OakOperation<BasePay.OpUpdateAction, Omit<Pay["UpdateOperationData"], "order">, Pay["Filter"]> | OakOperation<"remove", Pay["RemoveOperationData"], Pay["Filter"]>)[];
settlement$order?: (OakOperation<"create", Omit<Settlement["CreateOperationData"], "order"> | Omit<Settlement["CreateOperationData"], "order">[]> | OakOperation<BaseSettlement.OpUpdateAction, Omit<Settlement["UpdateOperationData"], "order">, Settlement["Filter"]> | OakOperation<"remove", Settlement["RemoveOperationData"], Settlement["Filter"]>)[]; settlePlan$order?: (OakOperation<"create", Omit<SettlePlan["CreateOperationData"], "order"> | Omit<SettlePlan["CreateOperationData"], "order">[]> | OakOperation<BaseSettlePlan.OpUpdateAction, Omit<SettlePlan["UpdateOperationData"], "order">, SettlePlan["Filter"]> | OakOperation<"remove", SettlePlan["RemoveOperationData"], SettlePlan["Filter"]>)[];
shipOrder$order?: (OakOperation<"create", Omit<ShipOrder["CreateOperationData"], "order"> | Omit<ShipOrder["CreateOperationData"], "order">[]> | OakOperation<BaseShipOrder.OpUpdateAction, Omit<ShipOrder["UpdateOperationData"], "order">, ShipOrder["Filter"]> | OakOperation<"remove", ShipOrder["RemoveOperationData"], ShipOrder["Filter"]>)[]; shipOrder$order?: (OakOperation<"create", Omit<ShipOrder["CreateOperationData"], "order"> | Omit<ShipOrder["CreateOperationData"], "order">[]> | OakOperation<BaseShipOrder.OpUpdateAction, Omit<ShipOrder["UpdateOperationData"], "order">, ShipOrder["Filter"]> | OakOperation<"remove", ShipOrder["RemoveOperationData"], ShipOrder["Filter"]>)[];
accountOper$entity?: OakOperation<"create", Omit<AccountOper["CreateOperationData"], "order"> | Omit<AccountOper["CreateOperationData"], "order">[]>[]; accountOper$entity?: OakOperation<"create", Omit<AccountOper["CreateOperationData"], "order"> | Omit<AccountOper["CreateOperationData"], "order">[]>[];
}>; }>;
@ -4684,13 +4685,13 @@ export type Settlement = {
Action: BaseSettlement.OpAction; Action: BaseSettlement.OpAction;
Schema: BaseSettlement.OpSchema & { Schema: BaseSettlement.OpSchema & {
account: Account["Schema"]; account: Account["Schema"];
order: Order["Schema"]; plan: SettlePlan["Schema"];
accountOper$entity?: Array<Omit<AccountOper["Schema"], "entity">>; accountOper$entity?: Array<Omit<AccountOper["Schema"], "entity">>;
accountOper$entity$$aggr?: AggregationResult<Omit<AccountOper["Schema"], "entity">>; accountOper$entity$$aggr?: AggregationResult<Omit<AccountOper["Schema"], "entity">>;
}; };
Projection: BaseSettlement.OpProjection & { Projection: BaseSettlement.OpProjection & {
account?: Account["Projection"]; account?: Account["Projection"];
order?: Order["Projection"]; plan?: SettlePlan["Projection"];
accountOper$entity?: OakSelection<"select", Omit<AccountOper["Projection"], "settlement">, Omit<AccountOper["Filter"], "settlement">, AccountOper["Sorter"]> & { accountOper$entity?: OakSelection<"select", Omit<AccountOper["Projection"], "settlement">, Omit<AccountOper["Filter"], "settlement">, AccountOper["Sorter"]> & {
$entity: "accountOper"; $entity: "accountOper";
}; };
@ -4700,13 +4701,13 @@ export type Settlement = {
}; };
FilterUnit: BaseSettlement.OpFilter & { FilterUnit: BaseSettlement.OpFilter & {
account: MakeFilter<Account["FilterUnit"]>; account: MakeFilter<Account["FilterUnit"]>;
order: MakeFilter<Order["FilterUnit"]>; plan: MakeFilter<SettlePlan["FilterUnit"]>;
accountOper$entity: MakeFilter<Omit<AccountOper["FilterUnit"], "entity">> & SubQueryPredicateMetadata; accountOper$entity: MakeFilter<Omit<AccountOper["FilterUnit"], "entity">> & SubQueryPredicateMetadata;
}; };
Filter: MakeFilter<Settlement["FilterUnit"]>; Filter: MakeFilter<Settlement["FilterUnit"]>;
SortAttr: Partial<BaseSettlement.OpSortAttr | { SortAttr: Partial<BaseSettlement.OpSortAttr | {
account: Account["SortAttr"]; account: Account["SortAttr"];
order: Order["SortAttr"]; plan: SettlePlan["SortAttr"];
}>; }>;
SortNode: { SortNode: {
$attr: Settlement["SortAttr"]; $attr: Settlement["SortAttr"];
@ -4717,7 +4718,7 @@ export type Settlement = {
Aggregation: DeduceAggregation<Settlement["Projection"], Settlement["Filter"], Settlement["Sorter"]>; Aggregation: DeduceAggregation<Settlement["Projection"], Settlement["Filter"], Settlement["Sorter"]>;
CreateOperationData: FormCreateData<BaseSettlement.OpSchema & { CreateOperationData: FormCreateData<BaseSettlement.OpSchema & {
account?: OakOperation<"create", Account["CreateOperationData"]> | OakOperation<BaseAccount.OpUpdateAction, Account["UpdateOperationData"], Account["Filter"]>; account?: OakOperation<"create", Account["CreateOperationData"]> | OakOperation<BaseAccount.OpUpdateAction, Account["UpdateOperationData"], Account["Filter"]>;
order?: OakOperation<"create", Order["CreateOperationData"]> | OakOperation<BaseOrder.OpUpdateAction, Order["UpdateOperationData"], Order["Filter"]>; plan?: OakOperation<"create", SettlePlan["CreateOperationData"]> | OakOperation<BaseSettlePlan.OpUpdateAction, SettlePlan["UpdateOperationData"], SettlePlan["Filter"]>;
accountOper$entity?: OakOperation<"create", Omit<AccountOper["CreateOperationData"], "settlement"> | Omit<AccountOper["CreateOperationData"], "settlement">[]>[]; accountOper$entity?: OakOperation<"create", Omit<AccountOper["CreateOperationData"], "settlement"> | Omit<AccountOper["CreateOperationData"], "settlement">[]>[];
}>; }>;
CreateSingle: OakOperation<"create", Settlement["CreateOperationData"]>; CreateSingle: OakOperation<"create", Settlement["CreateOperationData"]>;
@ -4725,7 +4726,7 @@ export type Settlement = {
Create: Settlement["CreateSingle"] | Settlement["CreateMulti"]; Create: Settlement["CreateSingle"] | Settlement["CreateMulti"];
UpdateOperationData: FormUpdateData<BaseSettlement.OpSchema & { UpdateOperationData: FormUpdateData<BaseSettlement.OpSchema & {
account?: OakOperation<"create", Account["CreateOperationData"]> | OakOperation<BaseAccount.OpUpdateAction, Account["UpdateOperationData"], Account["Filter"]> | OakOperation<"remove", Account["RemoveOperationData"], Account["Filter"]>; account?: OakOperation<"create", Account["CreateOperationData"]> | OakOperation<BaseAccount.OpUpdateAction, Account["UpdateOperationData"], Account["Filter"]> | OakOperation<"remove", Account["RemoveOperationData"], Account["Filter"]>;
order?: OakOperation<"create", Order["CreateOperationData"]> | OakOperation<BaseOrder.OpUpdateAction, Order["UpdateOperationData"], Order["Filter"]> | OakOperation<"remove", Order["RemoveOperationData"], Order["Filter"]>; plan?: OakOperation<"create", SettlePlan["CreateOperationData"]> | OakOperation<BaseSettlePlan.OpUpdateAction, SettlePlan["UpdateOperationData"], SettlePlan["Filter"]> | OakOperation<"remove", SettlePlan["RemoveOperationData"], SettlePlan["Filter"]>;
accountOper$entity?: OakOperation<"create", Omit<AccountOper["CreateOperationData"], "settlement"> | Omit<AccountOper["CreateOperationData"], "settlement">[]>[]; accountOper$entity?: OakOperation<"create", Omit<AccountOper["CreateOperationData"], "settlement"> | Omit<AccountOper["CreateOperationData"], "settlement">[]>[];
}>; }>;
Update: OakOperation<BaseSettlement.OpUpdateAction, Settlement["UpdateOperationData"], Settlement["Filter"], Settlement["Sorter"]>; Update: OakOperation<BaseSettlement.OpUpdateAction, Settlement["UpdateOperationData"], Settlement["Filter"], Settlement["Sorter"]>;
@ -4733,6 +4734,54 @@ export type Settlement = {
Remove: OakOperation<"remove", Settlement["RemoveOperationData"], Settlement["Filter"], Settlement["Sorter"]>; Remove: OakOperation<"remove", Settlement["RemoveOperationData"], Settlement["Filter"], Settlement["Sorter"]>;
Operation: Settlement["Create"] | Settlement["Update"] | Settlement["Remove"]; Operation: Settlement["Create"] | Settlement["Update"] | Settlement["Remove"];
}; };
export type SettlePlan = {
OpSchema: BaseSettlePlan.OpSchema;
Action: BaseSettlePlan.OpAction;
Schema: BaseSettlePlan.OpSchema & {
order: Order["Schema"];
settlement$plan?: Array<Omit<Settlement["Schema"], "plan">>;
settlement$plan$$aggr?: AggregationResult<Omit<Settlement["Schema"], "plan">>;
};
Projection: BaseSettlePlan.OpProjection & {
order?: Order["Projection"];
settlement$plan?: OakSelection<"select", Omit<Settlement["Projection"], "settlePlan">, Omit<Settlement["Filter"], "settlePlan">, Settlement["Sorter"]> & {
$entity: "settlement";
};
settlement$plan$$aggr?: DeduceAggregation<Omit<Settlement["Projection"], "settlePlan">, Omit<Settlement["Filter"], "settlePlan">, Settlement["Sorter"]> & {
$entity: "settlement";
};
};
FilterUnit: BaseSettlePlan.OpFilter & {
order: MakeFilter<Order["FilterUnit"]>;
settlement$plan: MakeFilter<Omit<Settlement["FilterUnit"], "plan">> & SubQueryPredicateMetadata;
};
Filter: MakeFilter<SettlePlan["FilterUnit"]>;
SortAttr: Partial<BaseSettlePlan.OpSortAttr | {
order: Order["SortAttr"];
}>;
SortNode: {
$attr: SettlePlan["SortAttr"];
$direction?: "asc" | "desc";
};
Sorter: SettlePlan["SortNode"][];
Selection: OakSelection<"select", SettlePlan["Projection"], SettlePlan["Filter"], SettlePlan["Sorter"]>;
Aggregation: DeduceAggregation<SettlePlan["Projection"], SettlePlan["Filter"], SettlePlan["Sorter"]>;
CreateOperationData: FormCreateData<BaseSettlePlan.OpSchema & {
order?: OakOperation<"create", Order["CreateOperationData"]> | OakOperation<BaseOrder.OpUpdateAction, Order["UpdateOperationData"], Order["Filter"]>;
settlement$plan?: (OakOperation<"create", Omit<Settlement["CreateOperationData"], "plan"> | Omit<Settlement["CreateOperationData"], "plan">[]> | OakOperation<BaseSettlement.OpUpdateAction, Omit<Settlement["UpdateOperationData"], "plan">, Settlement["Filter"]>)[];
}>;
CreateSingle: OakOperation<"create", SettlePlan["CreateOperationData"]>;
CreateMulti: OakOperation<"create", Array<SettlePlan["CreateOperationData"]>>;
Create: SettlePlan["CreateSingle"] | SettlePlan["CreateMulti"];
UpdateOperationData: FormUpdateData<BaseSettlePlan.OpSchema & {
order?: OakOperation<"create", Order["CreateOperationData"]> | OakOperation<BaseOrder.OpUpdateAction, Order["UpdateOperationData"], Order["Filter"]> | OakOperation<"remove", Order["RemoveOperationData"], Order["Filter"]>;
settlement$plan?: (OakOperation<"create", Omit<Settlement["CreateOperationData"], "plan"> | Omit<Settlement["CreateOperationData"], "plan">[]> | OakOperation<BaseSettlement.OpUpdateAction, Omit<Settlement["UpdateOperationData"], "plan">, Settlement["Filter"]> | OakOperation<"remove", Settlement["RemoveOperationData"], Settlement["Filter"]>)[];
}>;
Update: OakOperation<BaseSettlePlan.OpUpdateAction, SettlePlan["UpdateOperationData"], SettlePlan["Filter"], SettlePlan["Sorter"]>;
RemoveOperationData: {};
Remove: OakOperation<"remove", SettlePlan["RemoveOperationData"], SettlePlan["Filter"], SettlePlan["Sorter"]>;
Operation: SettlePlan["Create"] | SettlePlan["Update"] | SettlePlan["Remove"];
};
export type Ship = { export type Ship = {
OpSchema: BaseShip.OpSchema; OpSchema: BaseShip.OpSchema;
Action: BaseShip.OpAction; Action: BaseShip.OpAction;
@ -5719,6 +5768,7 @@ export type EntityDict = {
pay: Pay; pay: Pay;
refund: Refund; refund: Refund;
settlement: Settlement; settlement: Settlement;
settlePlan: SettlePlan;
ship: Ship; ship: Ship;
shipCompany: ShipCompany; shipCompany: ShipCompany;
shipOrder: ShipOrder; shipOrder: ShipOrder;

View File

@ -3,7 +3,7 @@ import { GenericAction } from "oak-domain/lib/actions/action";
export type IAction = 'startPaying' | 'payAll' | 'payPartially' | 'payNone' | 'timeout' | 'cancel' | 'startRefunding' | 'refundAll' | 'refundPartially' | 'refundNone' | string; export type IAction = 'startPaying' | 'payAll' | 'payPartially' | 'payNone' | 'timeout' | 'cancel' | 'startRefunding' | 'refundAll' | 'refundPartially' | 'refundNone' | string;
export type IState = 'unpaid' | 'timeout' | 'cancelled' | 'paying' | 'partiallyPaid' | 'paid' | 'refunding' | 'partiallyRefunded' | 'refunded' | string; export type IState = 'unpaid' | 'timeout' | 'cancelled' | 'paying' | 'partiallyPaid' | 'paid' | 'refunding' | 'partiallyRefunded' | 'refunded' | string;
export declare const IActionDef: ActionDef<IAction, IState>; export declare const IActionDef: ActionDef<IAction, IState>;
export type ParticularAction = IAction | 'settle'; export type ParticularAction = IAction;
export declare const actions: string[]; export declare const actions: string[];
export type Action = GenericAction | ParticularAction | string; export type Action = GenericAction | ParticularAction | string;
export declare const actionDefDict: { export declare const actionDefDict: {

View File

@ -13,7 +13,7 @@ export const IActionDef = {
}, },
is: 'unpaid', is: 'unpaid',
}; };
export const actions = ["count", "stat", "download", "select", "aggregate", "create", "remove", "update", "startPaying", "payAll", "payPartially", "payNone", "timeout", "cancel", "startRefunding", "refundAll", "refundPartially", "refundNone", "settle"]; export const actions = ["count", "stat", "download", "select", "aggregate", "create", "remove", "update", "startPaying", "payAll", "payPartially", "payNone", "timeout", "cancel", "startRefunding", "refundAll", "refundPartially", "refundNone"];
export const actionDefDict = { export const actionDefDict = {
iState: IActionDef iState: IActionDef
}; };

View File

@ -13,6 +13,14 @@ export const desc = {
notNull: true, notNull: true,
type: "money" type: "money"
}, },
settled: {
notNull: true,
type: "money"
},
settlePlanned: {
notNull: true,
type: "money"
},
title: { title: {
notNull: true, notNull: true,
type: "varchar", type: "varchar",
@ -46,10 +54,6 @@ export const desc = {
length: 64 length: 64
} }
}, },
settled: {
notNull: true,
type: "boolean"
},
allowPartialPay: { allowPartialPay: {
type: "boolean" type: "boolean"
}, },

View File

@ -10,7 +10,6 @@ export const style = {
refundAll: '', refundAll: '',
refundNone: '', refundNone: '',
refundPartially: '', refundPartially: '',
settle: '',
}, },
color: { color: {
iState: { iState: {

View File

@ -7,13 +7,14 @@ export type OpSchema = EntityShape & {
price: Price; price: Price;
paid: Price; paid: Price;
refunded: Price; refunded: Price;
settled: Price;
settlePlanned: Price;
title: String<32>; title: String<32>;
desc: Text; desc: Text;
timeoutAt?: Datetime | null; timeoutAt?: Datetime | null;
creatorId: ForeignKey<"user">; creatorId: ForeignKey<"user">;
entity: String<32>; entity: String<32>;
entityId: String<64>; entityId: String<64>;
settled: Boolean;
allowPartialPay?: Boolean | null; allowPartialPay?: Boolean | null;
systemId: ForeignKey<"system">; systemId: ForeignKey<"system">;
addressId?: ForeignKey<"address"> | null; addressId?: ForeignKey<"address"> | null;
@ -31,13 +32,14 @@ export type OpFilter = {
price: Q_NumberValue; price: Q_NumberValue;
paid: Q_NumberValue; paid: Q_NumberValue;
refunded: Q_NumberValue; refunded: Q_NumberValue;
settled: Q_NumberValue;
settlePlanned: Q_NumberValue;
title: Q_StringValue; title: Q_StringValue;
desc: Q_StringValue; desc: Q_StringValue;
timeoutAt: Q_DateValue; timeoutAt: Q_DateValue;
creatorId: Q_StringValue; creatorId: Q_StringValue;
entity: Q_StringValue; entity: Q_StringValue;
entityId: Q_StringValue; entityId: Q_StringValue;
settled: Q_BooleanValue;
allowPartialPay: Q_BooleanValue; allowPartialPay: Q_BooleanValue;
systemId: Q_StringValue; systemId: Q_StringValue;
addressId: Q_StringValue; addressId: Q_StringValue;
@ -54,13 +56,14 @@ export type OpProjection = {
price?: number; price?: number;
paid?: number; paid?: number;
refunded?: number; refunded?: number;
settled?: number;
settlePlanned?: number;
title?: number; title?: number;
desc?: number; desc?: number;
timeoutAt?: number; timeoutAt?: number;
creatorId?: number; creatorId?: number;
entity?: number; entity?: number;
entityId?: number; entityId?: number;
settled?: number;
allowPartialPay?: number; allowPartialPay?: number;
systemId?: number; systemId?: number;
addressId?: number; addressId?: number;
@ -75,13 +78,14 @@ export type OpSortAttr = Partial<{
price: number; price: number;
paid: number; paid: number;
refunded: number; refunded: number;
settled: number;
settlePlanned: number;
title: number; title: number;
desc: number; desc: number;
timeoutAt: number; timeoutAt: number;
creatorId: number; creatorId: number;
entity: number; entity: number;
entityId: number; entityId: number;
settled: number;
allowPartialPay: number; allowPartialPay: number;
systemId: number; systemId: number;
addressId: number; addressId: number;

View File

@ -4,6 +4,8 @@
"price": "订单金额", "price": "订单金额",
"paid": "已支付金额", "paid": "已支付金额",
"refunded": "已退款金额", "refunded": "已退款金额",
"settled": "已结算金额",
"settlePlanned": "已计划结算金额",
"iState": "订单状态", "iState": "订单状态",
"title": "订单标题", "title": "订单标题",
"desc": "订单描述", "desc": "订单描述",
@ -12,7 +14,6 @@
"creator": "创建者", "creator": "创建者",
"entity": "关联对象", "entity": "关联对象",
"entityId": "关联对象Id", "entityId": "关联对象Id",
"settled": "是否结算",
"opers": "相关帐户操作", "opers": "相关帐户操作",
"system": "所属系统", "system": "所属系统",
"address": "收货地址", "address": "收货地址",
@ -28,8 +29,7 @@
"startRefunding": "开始退款", "startRefunding": "开始退款",
"refundAll": "完全退款", "refundAll": "完全退款",
"refundNone": "退款失败", "refundNone": "退款失败",
"refundPartially": "部分退款", "refundPartially": "部分退款"
"settle": "结算"
}, },
"v": { "v": {
"iState": { "iState": {

View File

@ -0,0 +1,11 @@
import { ActionDef } from "oak-domain/lib/types/Action";
import { GenericAction } from "oak-domain/lib/actions/action";
export type IState = 'unsettled' | 'settled' | 'closed' | string;
export type IAction = 'settle' | 'close' | string;
export declare const IActionDef: ActionDef<IAction, IState>;
export type ParticularAction = IAction;
export declare const actions: string[];
export type Action = GenericAction | ParticularAction | string;
export declare const actionDefDict: {
iState: ActionDef<string, string>;
};

View File

@ -0,0 +1,11 @@
export const IActionDef = {
stm: {
settle: ['unsettled', 'settled'],
close: ['unsettled', 'closed'],
},
is: 'unsettled',
};
export const actions = ["count", "stat", "download", "select", "aggregate", "create", "remove", "update", "settle", "close"];
export const actionDefDict = {
iState: IActionDef
};

View File

@ -0,0 +1,19 @@
export * from "./_baseSchema";
import { SettlePlan } from "../EntityDict";
export type Schema = SettlePlan["Schema"];
export type Action = SettlePlan["Action"];
export type Projection = SettlePlan["Projection"];
export type Filter = SettlePlan["Filter"];
export type SortNode = SettlePlan["SortNode"];
export type Sorter = SettlePlan["Sorter"];
export type Selection = SettlePlan["Selection"];
export type Aggregation = SettlePlan["Aggregation"];
export type CreateOperationData = SettlePlan["CreateOperationData"];
export type CreateSingle = SettlePlan["CreateSingle"];
export type CreateMulti = SettlePlan["CreateMulti"];
export type Create = SettlePlan["Create"];
export type UpdateOperationData = SettlePlan["UpdateOperationData"];
export type Update = SettlePlan["Update"];
export type RemoveOperationData = SettlePlan["RemoveOperationData"];
export type Remove = SettlePlan["Remove"];
export type Operation = SettlePlan["Operation"];

View File

@ -0,0 +1 @@
export * from "./_baseSchema";

View File

@ -0,0 +1,3 @@
import { StorageDesc } from "oak-domain/lib/types/Storage";
import { OpSchema } from "./Schema";
export declare const desc: StorageDesc<OpSchema>;

View File

@ -0,0 +1,23 @@
import { actions } from "./Action";
export const desc = {
attributes: {
when: {
type: "datetime"
},
orderId: {
notNull: true,
type: "ref",
ref: "order"
},
price: {
notNull: true,
type: "money"
},
iState: {
type: "enum",
enumeration: ["unsettled", "settled", "closed"]
}
},
actionType: "crud",
actions
};

View File

@ -0,0 +1,3 @@
import { Action, OpSchema } from "./Schema";
import { StyleDef } from "oak-domain/lib/types/Style";
export declare const style: StyleDef<OpSchema, Action>;

View File

@ -0,0 +1,13 @@
export const style = {
icon: {
settle: '',
close: '',
},
color: {
iState: {
unsettled: '#52BE80',
settled: '#2E86C1',
closed: '#8C949C'
},
}
};

View File

@ -0,0 +1,49 @@
import { ForeignKey } from "oak-domain/lib/types/DataType";
import { Q_DateValue, Q_NumberValue, Q_StringValue, Q_EnumValue, NodeId, ExprOp, ExpressionKey } from "oak-domain/lib/types/Demand";
import { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/Entity";
import { Action, ParticularAction, IState } from "./Action";
import { Datetime, Price } from "oak-domain/lib/types/DataType";
export type OpSchema = EntityShape & {
when?: Datetime | null;
orderId: ForeignKey<"order">;
price: Price;
iState?: IState | null;
} & {
[A in ExpressionKey]?: any;
};
export type OpAttr = keyof OpSchema;
export type OpFilter = {
id: Q_StringValue;
$$createAt$$: Q_DateValue;
$$seq$$: Q_NumberValue;
$$updateAt$$: Q_DateValue;
when: Q_DateValue;
orderId: Q_StringValue;
price: Q_NumberValue;
iState: Q_EnumValue<IState>;
} & ExprOp<OpAttr | string>;
export type OpProjection = {
"#id"?: NodeId;
[k: string]: any;
id?: number;
$$createAt$$?: number;
$$updateAt$$?: number;
$$seq$$?: number;
when?: number;
orderId?: number;
price?: number;
iState?: number;
} & Partial<ExprOp<OpAttr | string>>;
export type OpSortAttr = Partial<{
id: number;
$$createAt$$: number;
$$seq$$: number;
$$updateAt$$: number;
when: number;
orderId: number;
price: number;
iState: number;
[k: string]: any;
} | ExprOp<OpAttr | string>>;
export type OpAction = OakMakeAction<Action | string>;
export type OpUpdateAction = "update" | ParticularAction | string;

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,20 @@
{
"name": "结算计划",
"attr": {
"when": "结算时间",
"order": "订单",
"price": "结算金额",
"iState": "结算计划状态"
},
"action": {
"settle": "结算",
"close": "关闭"
},
"v": {
"iState": {
"unsettled": "未结算",
"settled": "已结算",
"closed": "已关闭"
}
}
}

View File

@ -1,9 +1,9 @@
import { ActionDef } from "oak-domain/lib/types/Action"; import { ActionDef } from "oak-domain/lib/types/Action";
import { GenericAction } from "oak-domain/lib/actions/action"; import { GenericAction } from "oak-domain/lib/actions/action";
export type IState = 'unsettled' | 'settled' | string; export type IState = 'unsettled' | 'settled' | 'closed' | string;
export type IAction = 'settle' | string; export type IAction = 'settle' | 'close' | string;
export declare const IActionDef: ActionDef<IAction, IState>; export declare const IActionDef: ActionDef<IAction, IState>;
export type ParticularAction = IAction | 'preSettle' | 'refund' | 'refundFailure'; export type ParticularAction = IAction | 'refund' | 'refundFailure';
export declare const actions: string[]; export declare const actions: string[];
export type Action = GenericAction | ParticularAction | string; export type Action = GenericAction | ParticularAction | string;
export declare const actionDefDict: { export declare const actionDefDict: {

View File

@ -1,10 +1,11 @@
export const IActionDef = { export const IActionDef = {
stm: { stm: {
settle: ['unsettled', 'settled'], settle: ['unsettled', 'settled'],
close: ['unsettled', 'closed'],
}, },
is: 'unsettled', is: 'unsettled',
}; };
export const actions = ["count", "stat", "download", "select", "aggregate", "create", "remove", "update", "settle", "preSettle", "refund", "refundFailure"]; export const actions = ["count", "stat", "download", "select", "aggregate", "create", "remove", "update", "settle", "close", "refund", "refundFailure"];
export const actionDefDict = { export const actionDefDict = {
iState: IActionDef iState: IActionDef
}; };

View File

@ -6,18 +6,18 @@ export const desc = {
type: "ref", type: "ref",
ref: "account" ref: "account"
}, },
planId: {
notNull: true,
type: "ref",
ref: "settlePlan"
},
price: { price: {
notNull: true, notNull: true,
type: "money" type: "money"
}, },
orderId: {
notNull: true,
type: "ref",
ref: "order"
},
iState: { iState: {
type: "enum", type: "enum",
enumeration: ["unsettled", "settled"] enumeration: ["unsettled", "settled", "closed"]
} }
}, },
actionType: "crud", actionType: "crud",

View File

@ -8,6 +8,7 @@ export const style = {
iState: { iState: {
unsettled: '#52BE80', unsettled: '#52BE80',
settled: '#2E86C1', settled: '#2E86C1',
closed: '#8C949C'
}, },
} }
}; };

View File

@ -5,8 +5,8 @@ import { Action, ParticularAction, IState } from "./Action";
import { Price } from "oak-domain/lib/types/DataType"; import { Price } from "oak-domain/lib/types/DataType";
export type OpSchema = EntityShape & { export type OpSchema = EntityShape & {
accountId: ForeignKey<"account">; accountId: ForeignKey<"account">;
planId: ForeignKey<"settlePlan">;
price: Price; price: Price;
orderId: ForeignKey<"order">;
iState?: IState | null; iState?: IState | null;
} & { } & {
[A in ExpressionKey]?: any; [A in ExpressionKey]?: any;
@ -18,8 +18,8 @@ export type OpFilter = {
$$seq$$: Q_NumberValue; $$seq$$: Q_NumberValue;
$$updateAt$$: Q_DateValue; $$updateAt$$: Q_DateValue;
accountId: Q_StringValue; accountId: Q_StringValue;
planId: Q_StringValue;
price: Q_NumberValue; price: Q_NumberValue;
orderId: Q_StringValue;
iState: Q_EnumValue<IState>; iState: Q_EnumValue<IState>;
} & ExprOp<OpAttr | string>; } & ExprOp<OpAttr | string>;
export type OpProjection = { export type OpProjection = {
@ -30,8 +30,8 @@ export type OpProjection = {
$$updateAt$$?: number; $$updateAt$$?: number;
$$seq$$?: number; $$seq$$?: number;
accountId?: number; accountId?: number;
planId?: number;
price?: number; price?: number;
orderId?: number;
iState?: number; iState?: number;
} & Partial<ExprOp<OpAttr | string>>; } & Partial<ExprOp<OpAttr | string>>;
export type OpSortAttr = Partial<{ export type OpSortAttr = Partial<{
@ -40,8 +40,8 @@ export type OpSortAttr = Partial<{
$$seq$$: number; $$seq$$: number;
$$updateAt$$: number; $$updateAt$$: number;
accountId: number; accountId: number;
planId: number;
price: number; price: number;
orderId: number;
iState: number; iState: number;
[k: string]: any; [k: string]: any;
} | ExprOp<OpAttr | string>>; } | ExprOp<OpAttr | string>>;

View File

@ -2,21 +2,22 @@
"name": "结算明细", "name": "结算明细",
"attr": { "attr": {
"account": "帐号", "account": "帐号",
"plan": "结算计划",
"price": "变化金额", "price": "变化金额",
"order": "订单",
"iState": "结算状态", "iState": "结算状态",
"opers": "相关帐户操作" "opers": "相关帐户操作"
}, },
"action": { "action": {
"preSettle": "预结算",
"settle": "结算", "settle": "结算",
"close": "关闭",
"refund": "退款", "refund": "退款",
"refundFailure": "退款失败" "refundFailure": "退款失败"
}, },
"v": { "v": {
"iState": { "iState": {
"unsettled": "未结算", "unsettled": "未结算",
"settled": "已结算" "settled": "已结算",
"closed": "已关闭"
} }
} }
} }

View File

@ -70,6 +70,7 @@ import { desc as orderDesc } from "./Order/Storage";
import { desc as payDesc } from "./Pay/Storage"; import { desc as payDesc } from "./Pay/Storage";
import { desc as refundDesc } from "./Refund/Storage"; import { desc as refundDesc } from "./Refund/Storage";
import { desc as settlementDesc } from "./Settlement/Storage"; import { desc as settlementDesc } from "./Settlement/Storage";
import { desc as settlePlanDesc } from "./SettlePlan/Storage";
import { desc as shipDesc } from "./Ship/Storage"; import { desc as shipDesc } from "./Ship/Storage";
import { desc as shipCompanyDesc } from "./ShipCompany/Storage"; import { desc as shipCompanyDesc } from "./ShipCompany/Storage";
import { desc as shipOrderDesc } from "./ShipOrder/Storage"; import { desc as shipOrderDesc } from "./ShipOrder/Storage";
@ -158,6 +159,7 @@ export const storageSchema = {
pay: payDesc, pay: payDesc,
refund: refundDesc, refund: refundDesc,
settlement: settlementDesc, settlement: settlementDesc,
settlePlan: settlePlanDesc,
ship: shipDesc, ship: shipDesc,
shipCompany: shipCompanyDesc, shipCompany: shipCompanyDesc,
shipOrder: shipOrderDesc, shipOrder: shipOrderDesc,

View File

@ -36,6 +36,7 @@ import { style as order } from "./Order/Style";
import { style as pay } from "./Pay/Style"; import { style as pay } from "./Pay/Style";
import { style as refund } from "./Refund/Style"; import { style as refund } from "./Refund/Style";
import { style as settlement } from "./Settlement/Style"; import { style as settlement } from "./Settlement/Style";
import { style as settlePlan } from "./SettlePlan/Style";
import { style as ship } from "./Ship/Style"; import { style as ship } from "./Ship/Style";
import { style as sysAccountOper } from "./SysAccountOper/Style"; import { style as sysAccountOper } from "./SysAccountOper/Style";
import { style as user } from "./User/Style"; import { style as user } from "./User/Style";
@ -84,6 +85,7 @@ export const styleDict = {
pay, pay,
refund, refund,
settlement, settlement,
settlePlan,
ship, ship,
sysAccountOper, sysAccountOper,
user, user,

View File

@ -19,7 +19,8 @@ export const desc = {
type: "ref", type: "ref",
ref: "platform" ref: "platform"
}, },
folder: { folder // 提现的loss在用户提现时计算
: {
type: "varchar", type: "varchar",
params: { params: {
length: 16 length: 16

View File

@ -1,5 +1,5 @@
import { Timer } from 'oak-domain/lib/types/Timer'; import { Timer } from 'oak-domain/lib/types/Timer';
import { EntityDict } from '../oak-app-domain/index'; import { EntityDict } from '../oak-app-domain/index';
import { BRC } from '../types/RuntimeCxt'; import { BRC } from '../types/RuntimeCxt';
declare const _default: Array<Timer<EntityDict, keyof EntityDict, BRC>>; declare const _default: Timer<EntityDict, keyof EntityDict, BRC>[];
export default _default; export default _default;

View File

@ -12,6 +12,7 @@ import withdrawTransferTriggers from './withdrawTransfer';
import depositTriggers from './deposit'; import depositTriggers from './deposit';
import shipTriggers from './ship'; import shipTriggers from './ship';
import orderTriggers from './order'; import orderTriggers from './order';
import settlePlanTriggers from './settlePlan';
const triggers = [ const triggers = [
...shipTriggers, ...shipTriggers,
...orderTriggers, ...orderTriggers,
@ -27,6 +28,7 @@ const triggers = [
...sysAccountOperTriggers, ...sysAccountOperTriggers,
...systemTriggers, ...systemTriggers,
...withdrawAccountTriggers, ...withdrawAccountTriggers,
...settlePlanTriggers,
]; ];
export default triggers; export default triggers;
export const optionalTriggers = [ export const optionalTriggers = [

View File

@ -1,8 +1,6 @@
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
import { DATA_SUBSCRIBER_KEYS } from '../config/constants'; import { DATA_SUBSCRIBER_KEYS } from '../config/constants';
import assert from 'assert';
const triggers = [ const triggers = [
{ /**{
name: '订单全部支付后对关联的settlement执行preSettle,更新settlement关联的type为preSettle的accountOper', name: '订单全部支付后对关联的settlement执行preSettle,更新settlement关联的type为preSettle的accountOper',
entity: 'order', entity: 'order',
action: 'payAll', action: 'payAll',
@ -20,7 +18,7 @@ const triggers = [
} }
}, { }, {
forUpdate: true, forUpdate: true,
}); })
const settlements = await context.select('settlement', { const settlements = await context.select('settlement', {
data: { data: {
id: 1, id: 1,
@ -37,38 +35,39 @@ const triggers = [
forUpdate: true, forUpdate: true,
}); });
assert(settlements && settlements.length > 0); assert(settlements && settlements.length > 0);
let amount = 0; let amount = 0;
for (const settlement of settlements) { for (const settlement of settlements) {
const { id: settlementId, price, accountId } = settlement; const { id: settlementId, price, accountId } = settlement;
amount += price; amount += price!;
//创建对应的accountOper //创建对应的accountOper
await context.operate('settlement', { await context.operate('settlement', {
id: await generateNewIdAsync(), id: await generateNewIdAsync(),
action: 'preSettle', action: 'preSettle',
data: { data: {
accountOper$entity: [{ accountOper$entity: [{
id: await generateNewIdAsync(),
action: 'create',
data: {
id: await generateNewIdAsync(), id: await generateNewIdAsync(),
action: 'create', totalPlus: price,
data: { availPlus: 0,
id: await generateNewIdAsync(), accountId: accountId,
totalPlus: price, type: 'preSettle',
availPlus: 0, }
accountId: accountId, }]
type: 'preSettle',
}
}]
}, },
filter: { filter: {
id: settlementId, id: settlementId,
} }
}, {}); }, {})
} }
assert(order.price === amount); assert(order.price === amount);
} }
return; return;
} }
}, },*/
{ /**{
name: '订单执行settle前对关联的settlement执行settle,更新settlement关联的type为settle的accountOper', name: '订单执行settle前对关联的settlement执行settle,更新settlement关联的type为settle的accountOper',
entity: 'order', entity: 'order',
action: 'settle', action: 'settle',
@ -77,6 +76,7 @@ const triggers = [
priority: 99, priority: 99,
fn: async ({ operation }, context, option) => { fn: async ({ operation }, context, option) => {
const { filter } = operation; const { filter } = operation;
let cnt = 0; let cnt = 0;
const orders = await context.select('order', { const orders = await context.select('order', {
data: { data: {
@ -100,17 +100,20 @@ const triggers = [
forUpdate: true, forUpdate: true,
dontCollect: true, dontCollect: true,
}); });
for (const order of orders) { for (const order of orders) {
const { settlement$order: settlements } = order || {}; const { settlement$order: settlements } = order || {};
assert(settlements && settlements.length > 0); assert(settlements && settlements.length > 0);
//将关联的settlement执行settle //将关联的settlement执行settle
for (const settlement of settlements) { for (const settlement of settlements) {
const { id: settlementId, price, accountId } = settlement; const { id: settlementId, price, accountId } = settlement;
await context.operate('settlement', {
id: await generateNewIdAsync(), await context.operate('settlement',
action: 'settle', {
data: { id: await generateNewIdAsync(),
accountOper$entity: [{ action: 'settle',
data: {
accountOper$entity: [{
id: await generateNewIdAsync(), id: await generateNewIdAsync(),
action: 'create', action: 'create',
data: { data: {
@ -121,17 +124,19 @@ const triggers = [
type: 'settle', type: 'settle',
} }
}] }]
},
filter: {
id: settlementId,
}
}, },
filter: { {}
id: settlementId, );
}
}, {});
cnt += settlements.length; cnt += settlements.length;
} }
} }
return cnt; return cnt;
}, },
}, },*/
{ {
name: '订单状态改变时,向订阅者发送消息', name: '订单状态改变时,向订阅者发送消息',
entity: 'order', entity: 'order',

View File

@ -2,7 +2,7 @@ import { generateNewId, generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
import { getAccountEntity, getPayClazz } from '../utils/payClazz'; import { getAccountEntity, getPayClazz } from '../utils/payClazz';
import assert from 'assert'; import assert from 'assert';
import { updateWithdrawState } from './withdraw'; import { updateWithdrawState } from './withdraw';
import { RefundExceedMax, PayUnRefundable } from '../types/Exception'; import { RefundExceedMax, PayUnRefundable, settlePlanExceed, refundOpersNotEnough, refundOpersExceed } from '../types/Exception';
/** /**
* 开始退款的逻辑 * 开始退款的逻辑
* @param context * @param context
@ -25,17 +25,31 @@ async function startRefunding(context, data) {
}, },
order: { order: {
id: 1, id: 1,
paid: 1,
refunded: 1,
settled: 1, settled: 1,
settlement$order: { settlePlanned: 1,
$entity: 'settlement', settlePlan$order: {
$entity: 'settlePlan',
data: { data: {
id: 1, id: 1,
accountId: 1,
price: 1, price: 1,
iState: 1, iState: 1,
settlement$plan: {
$entity: 'settlement',
data: {
id: 1,
accountId: 1,
price: 1,
iState: 1,
},
filter: {
iState: 'unsettled'
}
}
}, },
filter: { filter: {
iState: 'unsettled', iState: 'unsettled'
} }
} }
} }
@ -74,47 +88,91 @@ async function startRefunding(context, data) {
} }
else { else {
assert(order); assert(order);
//订单退款的钱要有明确的来源account // 对settlePlan检查
const { accountOper$entity: opers } = data; // 未结算的settlePlan的金额总和 = order.paid - order.refunded - order.settled - refunded.price
assert(opers && opers instanceof Array, '订单退款一定要有相应的account来源'); const { settlePlan$order: settlePlans, paid, refunded, settled } = order;
if (order.settled) { let settlePlanAmount = 0;
// 已经分账 settlePlans.forEach((settlePlan) => settlePlanAmount += settlePlan.price);
const allowPlanPrice = paid - refunded - settled - data.price;
if (settlePlanAmount > allowPlanPrice) {
throw new settlePlanExceed(settlePlanAmount - allowPlanPrice);
}
const settlements = settlePlans?.map((plan) => plan.settlement$plan).flat();
const { accountOper$entity: opers, } = data;
// 对opers检查
if (order.settled === (order.paid - order.refunded)) {
// 已全部结算
// 已全部结算的订单由refund传入的opers决定退款检查opers的金额总和等于refund的金额
let amount = 0; let amount = 0;
// 有明确的来源account
assert(opers && opers instanceof Array, '已结算的订单退款一定要有相应的account来源');
opers.forEach(({ action, data }) => { opers.forEach(({ action, data }) => {
assert(action === 'create'); assert(action === 'create');
const { type, totalPlus, availPlus, refundablePlus } = data; const { type, totalPlus, availPlus, accountId } = data;
assert(type === 'refund'); assert(type === 'refund');
assert(totalPlus === availPlus); assert(totalPlus === availPlus);
const settlement = settlements?.find((ele) => ele?.accountId === accountId);
assert(!!settlement, '请从订单分账的相关账户中选择订单退款的account来源');
amount += -totalPlus; amount += -totalPlus;
}); });
assert(amount === data.price); assert(amount === data.price);
//将order的settled更新
const newSettled = order.settled - data.price;
await context.operate('order', {
id: await generateNewIdAsync(),
action: 'update',
data: {
settled: newSettled,
},
filter: {
id: order.id,
}
}, {});
}
else if (order.settled === 0) {
//未结算
//未结算的订单无opers
assert(!(opers && opers.length > 0));
} }
else { else {
//未完成分账的订单退款关联的AccountOper的totalPlus总和等于refund的price //部分结算
//同时更新对应的settlement的price /**
let amount = 0; * 部分结算的订单:
const { settlement$order: settlements } = order; * 1. opers的金额总和 <= 订单已结算金额
for (const oper of opers) { * 2. opers的金额总和 + unsettled的金额 >= 退款金额
const { action, data } = oper; */
assert(action === 'create'); let opersPrice = 0;
const { type, totalPlus, accountId } = data; if (opers && opers.length > 0) {
assert(type === 'refund'); opers.forEach(({ action, data }) => {
amount += -totalPlus; assert(action === 'create');
const settlement = settlements?.find((ele) => ele.accountId === accountId); const { type, totalPlus, availPlus, accountId } = data;
assert(!!settlement, '请从订单分账的相关账户中选择订单退款的account来源'); assert(type === 'refund');
const settlementNewPrice = settlement.price + totalPlus; //可能为负值 assert(totalPlus === availPlus);
await context.operate('settlement', { const settlement = settlements?.find((ele) => ele?.accountId === accountId);
id: await generateNewIdAsync(), assert(!!settlement, '请从订单分账的相关账户中选择订单退款的account来源');
action: 'refund', opersPrice += -totalPlus;
data: { });
price: settlementNewPrice,
},
filter: {
id: settlement.id,
}
}, {});
} }
assert(amount === data.price); const { paid, refunded, settled, settlePlan$order: settlePlans } = order;
const orderUnsettledPrice = paid - refunded - settled;
if (opersPrice > settled) {
throw new refundOpersExceed(opersPrice - settled);
}
if (opersPrice < data.price - orderUnsettledPrice) {
throw new refundOpersNotEnough(opersPrice - (data.price - orderUnsettledPrice));
}
//将order的settled更新
const newSettled = order.settled - opersPrice;
await context.operate('order', {
id: await generateNewIdAsync(),
action: 'update',
data: {
settled: newSettled,
},
filter: {
id: order.id,
}
}, {});
} }
} }
data.pay = { data.pay = {
@ -309,18 +367,6 @@ async function failRefunding(context, refundId) {
order: { order: {
id: 1, id: 1,
settled: 1, settled: 1,
settlement$order: {
$entity: 'settlement',
data: {
id: 1,
accountId: 1,
price: 1,
iState: 1,
},
filter: {
iState: 'unsettled',
}
}
} }
}, },
filter: { filter: {
@ -367,51 +413,38 @@ async function failRefunding(context, refundId) {
entityId: refundId, entityId: refundId,
}, },
}, { dontCollect: true }); }, { dontCollect: true });
if (order.settled) { let opersPrice = 0;
// 已经分账 for (const oper of accountOpers) {
let amount = 0; const { totalPlus, availPlus, accountId } = oper;
for (const oper of accountOpers) { assert(totalPlus < 0 && totalPlus === availPlus);
const { totalPlus, availPlus, accountId } = oper; await context.operate('accountOper', {
assert(totalPlus < 0 && totalPlus === availPlus); id: await generateNewIdAsync(),
await context.operate('accountOper', { action: 'create',
data: {
id: await generateNewIdAsync(), id: await generateNewIdAsync(),
action: 'create', totalPlus: -totalPlus,
data: { availPlus: -availPlus,
id: await generateNewIdAsync(), type: 'refundFailure',
totalPlus: -totalPlus, entity: 'refund',
availPlus: -availPlus, entityId: refundId,
type: 'refundFailure', accountId,
entity: 'refund', }
entityId: refundId, }, {});
accountId, opersPrice += -availPlus;
}
}, {});
amount += -availPlus;
}
assert(amount === refund.price);
} }
else { //如果refund有accountOper回退order.settled变化
//未完成分账的订单,需要修改settlement if (opersPrice > 0) {
let amount = 0; const newSettled = order.settled + opersPrice;
const { settlement$order: settlements } = order; await context.operate('order', {
for (const oper of accountOpers) { id: await generateNewIdAsync(),
const { totalPlus, availPlus, accountId } = oper; action: 'update',
amount += -totalPlus; data: {
const settlement = settlements?.find((ele) => ele.accountId === accountId); settled: newSettled
assert(!!settlement); },
const settlementNewPrice = settlement.price - totalPlus; filter: {
await context.operate('settlement', { id: order.id,
id: await generateNewIdAsync(), }
action: 'refundFailure', }, {});
data: {
price: settlementNewPrice,
},
filter: {
id: settlement.id,
}
}, {});
}
assert(amount === refund.price);
} }
return 1 + accountOpers.length; return 1 + accountOpers.length;
} }

5
es/triggers/settlePlan.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import { Trigger } from 'oak-domain/lib/types/Trigger';
import { EntityDict } from '../oak-app-domain';
import { BRC } from '../types/RuntimeCxt';
declare const triggers: Trigger<EntityDict, 'settlePlan', BRC>[];
export default triggers;

195
es/triggers/settlePlan.js Normal file
View File

@ -0,0 +1,195 @@
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
import assert from 'assert';
const triggers = [
{
name: '当settlePlan创建时更新关联order的settlePlanned',
entity: 'settlePlan',
action: 'create',
when: 'before',
asRoot: true,
priority: 99,
fn: async ({ operation }, context, option) => {
const { data } = operation;
let count = 0;
const updateOrderFn = async (settlePlan) => {
const [order] = await context.select('order', {
data: {
id: 1,
paid: 1,
refunded: 1,
settlePlanned: 1,
},
filter: {
id: settlePlan.orderId,
}
}, { forUpdate: true });
const { id, paid, refunded, settlePlanned } = order;
const newSettlePlanned = settlePlan.price + settlePlanned;
await context.operate('order', {
id: await generateNewIdAsync(),
action: 'update',
data: {
settlePlanned: newSettlePlanned,
},
filter: {
id,
}
}, option);
};
if (data instanceof Array) {
for (const d of data) {
await updateOrderFn(d);
count++;
}
}
else {
await updateOrderFn(data);
count++;
}
return count;
},
},
{
name: '当settlePlan执行settle时将关联的settlement执行settle并更新order的settled',
entity: 'settlePlan',
action: 'settle',
when: 'before',
asRoot: true,
priority: 99,
fn: async ({ operation }, context, option) => {
const { filter } = operation;
const settlePlans = await context.select('settlePlan', {
data: {
id: 1,
price: 1,
settlement$plan: {
$entity: 'settlement',
data: {
id: 1,
price: 1,
accountId: 1,
iState: 1,
},
filter: {
iState: 'unsettled',
}
},
orderId: 1,
order: {
id: 1,
paid: 1,
refunded: 1,
settled: 1,
}
},
filter,
}, { forUpdate: true });
for (const settlePlan of settlePlans) {
const { id, price: planPrice, settlement$plan: settlements, orderId, order } = settlePlan;
assert(settlements && settlements.length > 0);
//关联的settlement均执行settle并生成accountOper
for (const settlement of settlements) {
const { id: settlementId, price: settlementPrice, accountId, } = settlement;
await context.operate('settlement', {
id: await generateNewIdAsync(),
action: 'settle',
data: {
accountOper$entity: [{
id: await generateNewIdAsync(),
action: 'create',
data: {
id: await generateNewIdAsync(),
totalPlus: settlementPrice,
availPlus: settlementPrice,
accountId: accountId,
type: 'settle',
}
}]
},
filter: {
id: settlementId,
}
}, option);
}
//更新order的settled
const newSettledPrice = order?.settled + planPrice;
await context.operate('order', {
id: await generateNewIdAsync(),
action: 'update',
data: {
settled: newSettledPrice,
},
filter: {
id: orderId,
}
}, option);
}
return settlePlans.length;
},
},
{
name: '当settlePlan执行close时将关联的settlement执行close并更新order的settlePlanned',
entity: 'settlePlan',
action: 'close',
when: 'before',
asRoot: true,
priority: 99,
fn: async ({ operation }, context, option) => {
const { filter } = operation;
const settlePlans = await context.select('settlePlan', {
data: {
id: 1,
price: 1,
settlement$plan: {
$entity: 'settlement',
data: {
id: 1,
price: 1,
accountId: 1,
iState: 1,
},
filter: {
iState: 'unsettled',
}
},
orderId: 1,
order: {
id: 1,
settlePlanned: 1,
}
},
filter,
}, { forUpdate: true });
for (const settlePlan of settlePlans) {
const { id, price: planPrice, settlement$plan: settlements, orderId, order } = settlePlan || {};
assert(settlements && settlements.length > 0);
//关联的settlement均执行close
for (const settlement of settlements) {
const { id: settlementId, } = settlement;
await context.operate('settlement', {
id: await generateNewIdAsync(),
action: 'close',
data: {},
filter: {
id: settlementId,
}
}, option);
}
//更新order的settlePlanned
const newSettlePlanned = order?.settlePlanned - planPrice;
await context.operate('order', {
id: await generateNewIdAsync(),
action: 'update',
data: {
settlePlanned: newSettlePlanned,
},
filter: {
id: orderId,
}
}, option);
}
return settlePlans.length;
},
},
];
export default triggers;

View File

@ -6,6 +6,6 @@ import { BRC } from '../types/RuntimeCxt';
* @param context * @param context
* @param refunds * @param refunds
*/ */
export declare function updateWithdrawState(context: BRC, id: string): Promise<1 | 0>; export declare function updateWithdrawState(context: BRC, id: string): Promise<0 | 1>;
declare const triggers: Trigger<EntityDict, 'withdraw', BRC>[]; declare const triggers: Trigger<EntityDict, 'withdraw', BRC>[];
export default triggers; export default triggers;

View File

@ -1,7 +1,73 @@
import { OakException, OpRecord } from 'oak-domain/lib/types'; import { OakException, OpRecord } from 'oak-domain/lib/types';
import { EntityDict } from '../oak-app-domain/index'; import { EntityDict } from '../oak-app-domain/index';
/**
* 退opers的price总和小于本次退款金额-
*/
export declare class refundOpersNotEnough<ED extends EntityDict> extends OakException<ED> {
price: number;
constructor(price: number, message?: string, _module?: string, params?: Record<string, any>);
getSerialData(): {
price: number;
name: string;
message: string;
_module: string | undefined;
params: Record<string, any> | undefined;
opRecords: OpRecord<ED>[];
tag1: string | undefined;
tag2: boolean | undefined;
tag3: any;
};
}
/**
* 退opers的price总和大于订单已结算金额
*/
export declare class refundOpersExceed<ED extends EntityDict> extends OakException<ED> {
price: number;
constructor(price: number, message?: string, _module?: string, params?: Record<string, any>);
getSerialData(): {
price: number;
name: string;
message: string;
_module: string | undefined;
params: Record<string, any> | undefined;
opRecords: OpRecord<ED>[];
tag1: string | undefined;
tag2: boolean | undefined;
tag3: any;
};
}
/**
* 退settlePlan金额超出order可计划结算金额
*/
export declare class settlePlanExceed<ED extends EntityDict> extends OakException<ED> {
price: number;
constructor(price: number, message?: string, _module?: string, params?: Record<string, any>);
getSerialData(): {
price: number;
name: string;
message: string;
_module: string | undefined;
params: Record<string, any> | undefined;
opRecords: OpRecord<ED>[];
tag1: string | undefined;
tag2: boolean | undefined;
tag3: any;
};
}
export declare class UploadShipException<ED extends EntityDict> extends OakException<ED> { export declare class UploadShipException<ED extends EntityDict> extends OakException<ED> {
constructor(message?: string); reason: any;
constructor(reason: any, message?: string, _module?: string, params?: Record<string, any>);
getSerialData(): {
reason: any;
name: string;
message: string;
_module: string | undefined;
params: Record<string, any> | undefined;
opRecords: OpRecord<ED>[];
tag1: string | undefined;
tag2: boolean | undefined;
tag3: any;
};
} }
export declare class ExternalPayUtilException<ED extends EntityDict> extends OakException<ED> { export declare class ExternalPayUtilException<ED extends EntityDict> extends OakException<ED> {
reason: any; reason: any;

View File

@ -1,8 +1,68 @@
import { OakException } from 'oak-domain/lib/types'; import { OakException } from 'oak-domain/lib/types';
import makeDepedentException from './DependentExceptions'; import makeDepedentException from './DependentExceptions';
/**
* 退款时级联创建的opers的price总和小于本次退款金额-订单未结算金额
*/
export class refundOpersNotEnough extends OakException {
price; //opers需增加的金额 显示为负数
constructor(price, message, _module, params) {
super(message || 'error::refund.create.opersNotEnough', _module || 'oak-pay-business', params);
this.price = price;
}
getSerialData() {
const data = super.getSerialData();
return {
...data,
price: this.price,
};
}
}
/**
* 退款时级联创建的opers的price总和大于订单已结算金额
*/
export class refundOpersExceed extends OakException {
price; //opers需减少的金额
constructor(price, message, _module, params) {
super(message || 'error::settlePlan.create.opersExceed', _module || 'oak-pay-business', params);
this.price = price;
}
getSerialData() {
const data = super.getSerialData();
return {
...data,
price: this.price,
};
}
}
/**
* 退款时settlePlan金额超出order可计划结算金额
*/
export class settlePlanExceed extends OakException {
price; //超出的可结算金额 显示为负数
constructor(price, message, _module, params) {
super(message || 'error::settlePlan.exceed', _module || 'oak-pay-business', params);
this.price = price;
}
getSerialData() {
const data = super.getSerialData();
return {
...data,
price: this.price,
};
}
}
export class UploadShipException extends OakException { export class UploadShipException extends OakException {
constructor(message) { reason;
super(message || '调用发货接口失败'); constructor(reason, message, _module, params) {
super(message || 'error::ship.uploadShipException', _module || 'oak-pay-business', params);
this.reason = reason;
}
getSerialData() {
const data = super.getSerialData();
return {
...data,
reason: this.reason,
};
} }
} }
export class ExternalPayUtilException extends OakException { export class ExternalPayUtilException extends OakException {

1
es/utils/pay.d.ts vendored
View File

@ -1,3 +1,4 @@
/// <reference types="node" />
import { EntityDict } from '../oak-app-domain'; import { EntityDict } from '../oak-app-domain';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity'; import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
import BackendRuntimeContext from '../context/BackendRuntimeContext'; import BackendRuntimeContext from '../context/BackendRuntimeContext';

View File

@ -190,10 +190,10 @@ export default class AliPay extends AliPayDebug {
const qrCodeWidth = this.apProduct.config?.qrCodeWidth || 100; const qrCodeWidth = this.apProduct.config?.qrCodeWidth || 100;
const params = { const params = {
bizContent: { bizContent: {
subject: pay.order?.desc || (pay.orderId ? '订单支付' : '帐户充值'), // 订单标题 subject: pay.order?.desc || (pay.orderId ? '订单支付' : '帐户充值'),
out_trade_no: out_trade_no, // 商户订单号64个字符以内、可包含字母、数字、下划线需保证在商户端不重复 out_trade_no: out_trade_no,
total_amount: totalAmount, // 订单总金额,单位为元 total_amount: totalAmount,
product_code: 'FAST_INSTANT_TRADE_PAY', // 销售产品码,商家和支付宝签约的产品码 product_code: 'FAST_INSTANT_TRADE_PAY',
notify_url: payNotifyUrl, notify_url: payNotifyUrl,
qr_pay_mode: qrPayMode, qr_pay_mode: qrPayMode,
qrcode_width: qrCodeWidth, qrcode_width: qrCodeWidth,

View File

@ -189,7 +189,7 @@ export async function uploadShippingInfo(shipId, context) {
const result = await wechatInstance.uploadShippingInfo(shipInfo); const result = await wechatInstance.uploadShippingInfo(shipInfo);
if (result?.errcode !== 0) { if (result?.errcode !== 0) {
console.error(JSON.stringify(result)); console.error(JSON.stringify(result));
throw new UploadShipException(result?.message); throw new UploadShipException(result);
} }
} }
} }
@ -242,7 +242,7 @@ export async function uploadShippingInfo(shipId, context) {
const result = await wechatInstance.uploadShippingInfo(shipInfo); const result = await wechatInstance.uploadShippingInfo(shipInfo);
if (result?.errcode !== 0) { if (result?.errcode !== 0) {
console.error(JSON.stringify(result)); console.error(JSON.stringify(result));
throw new UploadShipException(result?.message); throw new UploadShipException(result);
} }
} }
} }

View File

@ -157,9 +157,9 @@ export default class WechatMpShipDebug {
name: from.name, name: from.name,
mobile: from.phone, mobile: from.phone,
// country: from!.area!.parent!.parent!.name!, //国家 // country: from!.area!.parent!.parent!.name!, //国家
province: from.area.parent.parent.name, //省份 province: from.area.parent.parent.name,
city: from.area.parent.name, //市 city: from.area.parent.name,
area: from.area.name, // 区 area: from.area.name,
address: from.detail, //详细地址 address: from.detail, //详细地址
}, },
receiver: { receiver: {

View File

@ -2,10 +2,12 @@ import orderWatchers from './order';
import payWatchers from './pay'; import payWatchers from './pay';
import refundWatchers from './refund'; import refundWatchers from './refund';
import shipWatchers from './ship'; import shipWatchers from './ship';
import settlePlanWatchers from './settlePlan';
const watchers = [ const watchers = [
...orderWatchers, ...orderWatchers,
...payWatchers, ...payWatchers,
...refundWatchers, ...refundWatchers,
...shipWatchers, ...shipWatchers,
...settlePlanWatchers,
]; ];
export default watchers; export default watchers;

View File

@ -32,7 +32,6 @@ const watchers = [
return results.reduce((prev, cur) => mergeOperationResult(prev, cur)); return results.reduce((prev, cur) => mergeOperationResult(prev, cur));
} }
}, },
/* triggerbug
{ {
name: '当pay达到禁止退款期限时关闭退款允许', name: '当pay达到禁止退款期限时关闭退款允许',
entity: 'pay', entity: 'pay',
@ -49,7 +48,7 @@ const watchers = [
actionData: { actionData: {
refundable: false, refundable: false,
} }
}, */ },
{ {
name: '当pay达到过期期限时关闭pay', name: '当pay达到过期期限时关闭pay',
entity: 'pay', entity: 'pay',

5
es/watchers/settlePlan.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import { Watcher } from 'oak-domain/lib/types/Watcher';
import { EntityDict } from '../oak-app-domain';
import { BRC } from '../types/RuntimeCxt';
declare const watchers: Watcher<EntityDict, 'settlePlan', BRC>[];
export default watchers;

18
es/watchers/settlePlan.js Normal file
View File

@ -0,0 +1,18 @@
const watchers = [
{
name: '当settlePlan达到结算时间时结算settlePlan',
entity: 'settlePlan',
filter: () => {
const now = Date.now();
return {
iState: 'unsettled',
when: {
$lte: now,
},
};
},
action: 'settle',
actionData: {},
}
];
export default watchers;

View File

@ -1,7 +1,6 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.getMpShipState = getMpShipState; exports.getExpressPrintInfo = exports.getMpShipState = void 0;
exports.getExpressPrintInfo = getExpressPrintInfo;
const types_1 = require("oak-domain/lib/types"); const types_1 = require("oak-domain/lib/types");
const ship_1 = require("../utils/ship"); const ship_1 = require("../utils/ship");
const shipClazz_1 = require("../utils/shipClazz"); const shipClazz_1 = require("../utils/shipClazz");
@ -19,6 +18,7 @@ async function getMpShipState(params, context) {
return shipState; return shipState;
} }
} }
exports.getMpShipState = getMpShipState;
/** /**
* 获取打印面单 * 获取打印面单
*/ */
@ -43,3 +43,4 @@ async function getExpressPrintInfo(params, context) {
const clazz = await (0, shipClazz_1.getShipClazz)(entity, entityId, context); const clazz = await (0, shipClazz_1.getShipClazz)(entity, entityId, context);
return await clazz.getPrintInfo(shipId, context); return await clazz.getPrintInfo(shipId, context);
} }
exports.getExpressPrintInfo = getExpressPrintInfo;

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.getWithdrawCreateData = getWithdrawCreateData; exports.getWithdrawCreateData = void 0;
const tslib_1 = require("tslib"); const tslib_1 = require("tslib");
const types_1 = require("oak-domain/lib/types"); const types_1 = require("oak-domain/lib/types");
const uuid_1 = require("oak-domain/lib/utils/uuid"); const uuid_1 = require("oak-domain/lib/utils/uuid");
@ -211,3 +211,4 @@ async function getWithdrawCreateData(params, context) {
data.loss = totalLoss; data.loss = totalLoss;
return data; return data;
} }
exports.getWithdrawCreateData = getWithdrawCreateData;

View File

@ -1,12 +1,12 @@
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.accountEntities = void 0; exports.accountEntities = exports.registerAccountEntity = void 0;
exports.registerAccountEntity = registerAccountEntity;
const uuid_1 = require("oak-domain/lib/utils/uuid"); const uuid_1 = require("oak-domain/lib/utils/uuid");
// 当注入一个新的account entity时将withdrawChannel的删除与之相关联 // 当注入一个新的account entity时将withdrawChannel的删除与之相关联
function registerAccountEntity(entity) { function registerAccountEntity(entity) {
exports.accountEntities.push(entity); exports.accountEntities.push(entity);
} }
exports.registerAccountEntity = registerAccountEntity;
exports.accountEntities = ['offlineAccount']; exports.accountEntities = ['offlineAccount'];
const triggers = [ const triggers = [
...exports.accountEntities.filter(ele => !!ele).map((entity) => [ ...exports.accountEntities.filter(ele => !!ele).map((entity) => [

View File

@ -102,22 +102,22 @@ const checkers = [
} }
break; break;
} }
case 'preSettle': { // case 'preSettle': {
//预分账时账户total增加avail不变refundable不变 // //预分账时账户total增加avail不变refundable不变
if (totalPlus < 0 || availPlus !== 0 || (refundablePlus && refundablePlus !== 0)) { // if (totalPlus < 0 || availPlus !== 0 || (refundablePlus && refundablePlus !== 0)) {
throw new types_1.OakInputIllegalException('accountOper', ['totalPlus', 'availPlus', 'refundablePlus'], 'accountOper为preSettle时其totalPlus必须为非负数、availPlus必须为0refundable必须为空或者0'); // throw new OakInputIllegalException('accountOper', ['totalPlus', 'availPlus', 'refundablePlus'], 'accountOper为preSettle时其totalPlus必须为非负数、availPlus必须为0refundable必须为空或者0');
} // }
break; // break;
} // }
case 'settle': { case 'settle': {
//分账时账户total不变refundable不变 //分账时账户total增加avail增加refundable不变
if (totalPlus !== 0 || (refundablePlus && refundablePlus !== 0)) { if (totalPlus < 0 || availPlus < 0 || (refundablePlus && refundablePlus !== 0)) {
throw new types_1.OakInputIllegalException('accountOper', ['totalPlus', 'refundablePlus'], 'accountOper为settle时其totalPlus必须为0refundable必须为空或者0'); throw new types_1.OakInputIllegalException('accountOper', ['totalPlus', 'refundablePlus'], 'accountOper为settle时其totalPlus、availPlus必须为非负数refundable必须为空或者0');
} }
break; break;
} }
default: { default: {
(0, assert_1.default)(false); // assert(false);
break; break;
} }
} }

View File

@ -12,6 +12,7 @@ const withdrawAccount_1 = tslib_1.__importDefault(require("./withdrawAccount"));
const refund_1 = tslib_1.__importDefault(require("./refund")); const refund_1 = tslib_1.__importDefault(require("./refund"));
const withdrawTransfer_1 = tslib_1.__importDefault(require("./withdrawTransfer")); const withdrawTransfer_1 = tslib_1.__importDefault(require("./withdrawTransfer"));
const ship_1 = tslib_1.__importDefault(require("./ship")); const ship_1 = tslib_1.__importDefault(require("./ship"));
const settlePlan_1 = tslib_1.__importDefault(require("./settlePlan"));
const checkers = [ const checkers = [
...refund_1.default, ...refund_1.default,
...withdrawAccount_1.default, ...withdrawAccount_1.default,
@ -24,5 +25,6 @@ const checkers = [
...wpProduct_1.default, ...wpProduct_1.default,
...withdrawTransfer_1.default, ...withdrawTransfer_1.default,
...ship_1.default, ...ship_1.default,
...settlePlan_1.default,
]; ];
exports.default = checkers; exports.default = checkers;

View File

@ -16,7 +16,8 @@ const checkers = [
} }
data.paid = 0; data.paid = 0;
data.refunded = 0; data.refunded = 0;
data.settled = false; data.settled = 0;
data.settlePlanned = 0;
if (!data.systemId) { if (!data.systemId) {
const contextSystemId = context.getApplication()?.systemId; const contextSystemId = context.getApplication()?.systemId;
(0, assert_1.default)(contextSystemId); (0, assert_1.default)(contextSystemId);
@ -108,51 +109,59 @@ const checkers = [
}); });
} }
}, },
/**todo settlePlan settle
{ {
// 订单结算检查存在关联的未结算的settlement其price之和等于订单的已支付与已退款的差值 // 订单结算检查存在关联的未结算的settlement其price之和等于订单的已支付与已退款的差值
type: 'logicalData', type: 'logicalData',
entity: 'order', entity: 'order',
action: 'settle', action: 'settle',
checker: (operation, context) => { checker: (operation, context) => {
const { data, filter } = operation; const { data, filter } = operation as EntityDict['order']['Update'];
(0, assert_1.default)(typeof filter.id === 'string');
assert(typeof filter!.id === 'string');
data.settled = true; data.settled = true;
return (0, executor_1.pipeline)(() => context.select('order', { return pipeline(
data: { () => context.select('order', {
id: 1, data: {
price: 1, id: 1,
paid: 1, price: 1,
refunded: 1, paid: 1,
iState: 1, refunded: 1,
settlement$order: { iState: 1,
$entity: 'settlement', settlement$order: {
data: { $entity: 'settlement',
id: 1, data: {
accountId: 1, id: 1,
price: 1, accountId: 1,
iState: 1, price: 1,
}, iState: 1,
filter: { },
iState: 'unsettled' filter: {
iState: 'unsettled'
}
} }
} },
}, filter: {
filter: { id: filter!.id!,
id: filter.id, },
}, }, {}),
}, {}), (orders) => { (orders: EntityDict['order']['Schema'][]) => {
const [order] = orders; const [order] = orders;
const { price, paid, refunded, iState, settlement$order: settlements } = order; const { price, paid, refunded, iState, settlement$order: settlements } = order;
(0, assert_1.default)(['paid'].includes(iState) && refunded === 0 && paid === price); assert(['paid'].includes(iState!) && refunded === 0 && paid === price);
(0, assert_1.default)(settlements && settlements.length > 0, '该结算订单需添加结算明细'); assert(settlements && settlements.length > 0, '该结算订单需添加结算明细');
let amount = 0;
settlements.forEach((settlement) => { let amount = 0;
amount += settlement.price; settlements.forEach((settlement) => {
(0, assert_1.default)(settlement.iState === 'unsettled', '订单结算前settlement必须处于未分账状态'); amount += settlement.price;
}); assert(settlement.iState === 'unsettled', '订单结算前settlement必须处于未分账状态');
(0, assert_1.default)(amount === paid); })
}); assert(amount === paid);
}
);
} }
}, },
*/
]; ];
exports.default = checkers; exports.default = checkers;

5
lib/checkers/settlePlan.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import { Checker } from 'oak-domain/lib/types/Auth';
import { EntityDict } from '../oak-app-domain';
import { RuntimeCxt } from '../types/RuntimeCxt';
declare const checkers: Checker<EntityDict, 'settlePlan', RuntimeCxt>[];
export default checkers;

107
lib/checkers/settlePlan.js Normal file
View File

@ -0,0 +1,107 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const executor_1 = require("oak-domain/lib/utils/executor");
const assert_1 = require("oak-domain/lib/utils/assert");
const checkers = [
{
/**
* 1settlement.price总和等于settlePlan.price
* 2settlePlan.price <= order.paid - order.refunded - order.settlePlanned
*/
entity: 'settlePlan',
action: 'create',
type: 'logicalData',
priority: 1,
checker: (operation, context) => {
const { data } = operation;
const checkfn = (settlePlan) => {
return (0, executor_1.pipeline)(() => context.select('order', {
data: {
id: 1,
paid: 1,
refunded: 1,
settlePlanned: 1,
},
filter: {
id: settlePlan.orderId,
},
}, { dontCollect: true }), (orders) => {
const [order] = orders;
const { paid, refunded, settlePlanned } = order;
const orderPrice = paid - refunded - settlePlanned;
(0, assert_1.assert)(settlePlan.price <= orderPrice, '结算计划金额不大于订单可结算金额');
return context.select('settlement', {
data: {
id: 1,
price: 1,
iState: 1,
planId: 1,
},
filter: {
planId: settlePlan.id,
iState: 'unsettled',
},
}, { dontCollect: true });
}, (settlements) => {
let amount = 0;
settlements.forEach((settlement) => amount += settlement.price);
if (settlePlan.settlement$plan && settlePlan.settlement$plan.length > 0) {
for (const settlementOper of settlePlan.settlement$plan) {
const settlementData = settlementOper.data;
if (settlementData instanceof Array) {
settlementData.forEach((s) => amount += s.price ?? 0);
}
else {
amount += settlementData?.price ?? 0;
}
}
}
(0, assert_1.assert)(amount === settlePlan.price, '结算计划金额需等于关联的结算明细金额总和');
});
};
if (data instanceof Array) {
for (const d of data) {
checkfn(d);
}
}
else {
checkfn(data);
}
}
},
{
entity: 'settlePlan',
action: 'close',
type: 'logicalData',
checker: (operation, context) => {
const { filter } = operation;
return (0, executor_1.pipeline)(() => context.select('settlePlan', {
data: {
id: 1,
price: 1,
iState: 1,
settlement$plan: {
$entity: 'settlement',
data: {
id: 1,
price: 1,
iState: 1,
},
filter: {
iState: 'unsettled',
}
}
},
filter,
}, { dontCollect: true }), (settlePlans) => {
for (const settlePlan of settlePlans) {
const { price: planPrice, settlement$plan: settlements } = settlePlan;
let amount = 0;
settlements.forEach((settlement) => amount += settlement.price);
(0, assert_1.assert)(amount === planPrice, '结算计划金额需等于未结算的结算明细金额总和');
}
});
}
}
];
exports.default = checkers;

View File

@ -926,7 +926,9 @@ const i18ns = [
"create": { "create": {
"hasAnotherRefunding": "您有一笔退款正在进行中", "hasAnotherRefunding": "您有一笔退款正在进行中",
"exceedMax": "退款额度大于可用值", "exceedMax": "退款额度大于可用值",
"payUnrefundable": "支付已经不可退款" "payUnrefundable": "支付已经不可退款",
"opersNotEnough": "指定退款帐户的操作金额总和不足",
"opersExceed": "指定退款帐户的操作金额总和超过订单已结算金额"
} }
}, },
"pay": { "pay": {
@ -934,7 +936,11 @@ const i18ns = [
"priceOverflow": "支付金额总和大于订单金额" "priceOverflow": "支付金额总和大于订单金额"
}, },
"ship": { "ship": {
"noClazz": "当前物流未关联外部接口" "noClazz": "当前物流未关联外部接口",
"uploadShipException": "小程序上传发货信息异常"
},
"settlePlan": {
"exceed": "结算计划总金额超过订单可结算金额上限"
} }
} }
}, },

View File

@ -2,7 +2,7 @@ import { String, Price } from 'oak-domain/lib/types/DataType';
import { EntityShape } from 'oak-domain/lib/types/Entity'; import { EntityShape } from 'oak-domain/lib/types/Entity';
import { EntityDesc } from 'oak-domain/lib/types'; import { EntityDesc } from 'oak-domain/lib/types';
import { Schema as Account } from './Account'; import { Schema as Account } from './Account';
type Type = 'deposit' | 'withdraw' | 'consume' | 'consumeBack' | 'loan' | 'repay' | 'withdrawBack' | 'earn' | 'cutoffRefundable' | 'tax' | 'taxRefund' | 'refund' | 'refundFailure' | 'preSettle' | 'settle'; type Type = 'deposit' | 'withdraw' | 'consume' | 'consumeBack' | 'loan' | 'repay' | 'withdrawBack' | 'earn' | 'cutoffRefundable' | 'tax' | 'taxRefund' | 'refund' | 'refundFailure' | 'settle';
export interface Schema extends EntityShape { export interface Schema extends EntityShape {
account: Account; account: Account;
type: Type; type: Type;

View File

@ -33,7 +33,6 @@ exports.entityDesc = {
cutoffRefundable: '削减可自由退额度', cutoffRefundable: '削减可自由退额度',
refund: '退款', refund: '退款',
refundFailure: '退款失败', refundFailure: '退款失败',
preSettle: '预分账',
settle: '分账', settle: '分账',
}, },
}, },
@ -55,7 +54,6 @@ exports.entityDesc = {
cutoffRefundable: '#2E4053', cutoffRefundable: '#2E4053',
refund: '#CC3333', refund: '#CC3333',
refundFailure: '#009933', refundFailure: '#009933',
preSettle: '#8A631D',
settle: '#157d5a', settle: '#157d5a',
} }
} }

View File

@ -33,7 +33,7 @@ exports.entityDesc = {
keyType: '指定应用私钥类型', keyType: '指定应用私钥类型',
gateway: "支付宝网关地址", gateway: "支付宝网关地址",
wsServiceUrl: 'websocket服务地址', wsServiceUrl: 'websocket服务地址',
timeout: "网关超时时间", //(单位毫秒),默认值是 5000 timeout: "网关超时时间",
needEncrypt: "是否需要AES加解密", needEncrypt: "是否需要AES加解密",
encryptKey: 'AES密钥', //调用AES加解密相关接口时需要 encryptKey: 'AES密钥', //调用AES加解密相关接口时需要
}, },

View File

@ -9,13 +9,14 @@ export interface Schema extends EntityShape {
price: Price; price: Price;
paid: Price; paid: Price;
refunded: Price; refunded: Price;
settled: Price;
settlePlanned: Price;
title: String<32>; title: String<32>;
desc: Text; desc: Text;
timeoutAt?: Datetime; timeoutAt?: Datetime;
creator: User; creator: User;
entity: String<32>; entity: String<32>;
entityId: String<64>; entityId: String<64>;
settled: Boolean;
allowPartialPay?: Boolean; allowPartialPay?: Boolean;
system: System; system: System;
address?: Address; address?: Address;
@ -25,7 +26,7 @@ export interface Schema extends EntityShape {
export type IAction = 'startPaying' | 'payAll' | 'payPartially' | 'payNone' | 'timeout' | 'cancel' | 'startRefunding' | 'refundAll' | 'refundPartially' | 'refundNone'; export type IAction = 'startPaying' | 'payAll' | 'payPartially' | 'payNone' | 'timeout' | 'cancel' | 'startRefunding' | 'refundAll' | 'refundPartially' | 'refundNone';
export type IState = 'unpaid' | 'timeout' | 'cancelled' | 'paying' | 'partiallyPaid' | 'paid' | 'refunding' | 'partiallyRefunded' | 'refunded'; export type IState = 'unpaid' | 'timeout' | 'cancelled' | 'paying' | 'partiallyPaid' | 'paid' | 'refunding' | 'partiallyRefunded' | 'refunded';
export declare const IActionDef: ActionDef<IAction, IState>; export declare const IActionDef: ActionDef<IAction, IState>;
export type Action = IAction | 'settle'; export type Action = IAction;
export declare const entityDesc: EntityDesc<Schema, Action, '', { export declare const entityDesc: EntityDesc<Schema, Action, '', {
iState: IState; iState: IState;
}>; }>;

View File

@ -54,6 +54,8 @@ exports.entityDesc = {
price: '订单金额', price: '订单金额',
paid: '已支付金额', paid: '已支付金额',
refunded: '已退款金额', refunded: '已退款金额',
settled: '已结算金额',
settlePlanned: '已计划结算金额',
iState: '订单状态', iState: '订单状态',
title: '订单标题', title: '订单标题',
desc: "订单描述", desc: "订单描述",
@ -62,7 +64,6 @@ exports.entityDesc = {
creator: '创建者', creator: '创建者',
entity: '关联对象', entity: '关联对象',
entityId: '关联对象Id', entityId: '关联对象Id',
settled: '是否结算',
opers: '相关帐户操作', opers: '相关帐户操作',
system: '所属系统', system: '所属系统',
address: '收货地址', address: '收货地址',
@ -79,7 +80,6 @@ exports.entityDesc = {
refundAll: '完全退款', refundAll: '完全退款',
refundNone: '退款失败', refundNone: '退款失败',
refundPartially: '部分退款', refundPartially: '部分退款',
settle: '结算',
}, },
v: { v: {
iState: { iState: {
@ -108,7 +108,6 @@ exports.entityDesc = {
refundAll: '', refundAll: '',
refundNone: '', refundNone: '',
refundPartially: '', refundPartially: '',
settle: '',
}, },
color: { color: {
iState: { iState: {

Some files were not shown because too many files have changed in this diff Show More