build
This commit is contained in:
parent
5c0508cb33
commit
c4021ff42c
|
|
@ -99,22 +99,22 @@ const checkers = [
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'preSettle': {
|
||||
//预分账时账户total增加,avail不变,refundable不变
|
||||
if (totalPlus < 0 || availPlus !== 0 || (refundablePlus && refundablePlus !== 0)) {
|
||||
throw new OakInputIllegalException('accountOper', ['totalPlus', 'availPlus', 'refundablePlus'], 'accountOper为preSettle时,其totalPlus必须为非负数、availPlus必须为0,refundable必须为空或者0');
|
||||
}
|
||||
break;
|
||||
}
|
||||
// case 'preSettle': {
|
||||
// //预分账时账户total增加,avail不变,refundable不变
|
||||
// if (totalPlus < 0 || availPlus !== 0 || (refundablePlus && refundablePlus !== 0)) {
|
||||
// throw new OakInputIllegalException('accountOper', ['totalPlus', 'availPlus', 'refundablePlus'], 'accountOper为preSettle时,其totalPlus必须为非负数、availPlus必须为0,refundable必须为空或者0');
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
case 'settle': {
|
||||
//分账时账户total不变,refundable不变
|
||||
if (totalPlus !== 0 || (refundablePlus && refundablePlus !== 0)) {
|
||||
throw new OakInputIllegalException('accountOper', ['totalPlus', 'refundablePlus'], 'accountOper为settle时,其totalPlus必须为0,refundable必须为空或者0');
|
||||
//分账时账户total增加,avail增加,refundable不变
|
||||
if (totalPlus < 0 || availPlus < 0 || (refundablePlus && refundablePlus !== 0)) {
|
||||
throw new OakInputIllegalException('accountOper', ['totalPlus', 'refundablePlus'], 'accountOper为settle时,其totalPlus、availPlus必须为非负数,refundable必须为空或者0');
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
// assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import withdrawAccounts from './withdrawAccount';
|
|||
import refundCheckers from './refund';
|
||||
import withdrawTransferCheckers from './withdrawTransfer';
|
||||
import shipCheckers from './ship';
|
||||
import settlePlanCheckers from './settlePlan';
|
||||
const checkers = [
|
||||
...refundCheckers,
|
||||
...withdrawAccounts,
|
||||
|
|
@ -21,5 +22,6 @@ const checkers = [
|
|||
...wpProductCheckers,
|
||||
...withdrawTransferCheckers,
|
||||
...shipCheckers,
|
||||
...settlePlanCheckers,
|
||||
];
|
||||
export default checkers;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ const checkers = [
|
|||
}
|
||||
data.paid = 0;
|
||||
data.refunded = 0;
|
||||
data.settled = false;
|
||||
data.settled = 0;
|
||||
data.settlePlanned = 0;
|
||||
if (!data.systemId) {
|
||||
const contextSystemId = context.getApplication()?.systemId;
|
||||
assert(contextSystemId);
|
||||
|
|
@ -105,51 +106,59 @@ const checkers = [
|
|||
});
|
||||
}
|
||||
},
|
||||
/**todo 调整至settlePlan 执行settle
|
||||
{
|
||||
// 订单结算,检查存在关联的未结算的settlement,其price之和等于订单的已支付与已退款的差值
|
||||
type: 'logicalData',
|
||||
entity: 'order',
|
||||
action: 'settle',
|
||||
checker: (operation, context) => {
|
||||
const { data, filter } = operation;
|
||||
assert(typeof filter.id === 'string');
|
||||
const { data, filter } = operation as EntityDict['order']['Update'];
|
||||
|
||||
assert(typeof filter!.id === 'string');
|
||||
|
||||
data.settled = true;
|
||||
return pipeline(() => context.select('order', {
|
||||
data: {
|
||||
id: 1,
|
||||
price: 1,
|
||||
paid: 1,
|
||||
refunded: 1,
|
||||
iState: 1,
|
||||
settlement$order: {
|
||||
$entity: 'settlement',
|
||||
data: {
|
||||
id: 1,
|
||||
accountId: 1,
|
||||
price: 1,
|
||||
iState: 1,
|
||||
},
|
||||
filter: {
|
||||
iState: 'unsettled'
|
||||
return pipeline(
|
||||
() => context.select('order', {
|
||||
data: {
|
||||
id: 1,
|
||||
price: 1,
|
||||
paid: 1,
|
||||
refunded: 1,
|
||||
iState: 1,
|
||||
settlement$order: {
|
||||
$entity: 'settlement',
|
||||
data: {
|
||||
id: 1,
|
||||
accountId: 1,
|
||||
price: 1,
|
||||
iState: 1,
|
||||
},
|
||||
filter: {
|
||||
iState: 'unsettled'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
id: filter.id,
|
||||
},
|
||||
}, {}), (orders) => {
|
||||
const [order] = orders;
|
||||
const { price, paid, refunded, iState, settlement$order: settlements } = order;
|
||||
assert(['paid'].includes(iState) && refunded === 0 && paid === price);
|
||||
assert(settlements && settlements.length > 0, '该结算订单需添加结算明细');
|
||||
let amount = 0;
|
||||
settlements.forEach((settlement) => {
|
||||
amount += settlement.price;
|
||||
assert(settlement.iState === 'unsettled', '订单结算前,settlement必须处于未分账状态');
|
||||
});
|
||||
assert(amount === paid);
|
||||
});
|
||||
},
|
||||
filter: {
|
||||
id: filter!.id!,
|
||||
},
|
||||
}, {}),
|
||||
(orders: EntityDict['order']['Schema'][]) => {
|
||||
const [order] = orders;
|
||||
const { price, paid, refunded, iState, settlement$order: settlements } = order;
|
||||
assert(['paid'].includes(iState!) && refunded === 0 && paid === price);
|
||||
assert(settlements && settlements.length > 0, '该结算订单需添加结算明细');
|
||||
|
||||
let amount = 0;
|
||||
settlements.forEach((settlement) => {
|
||||
amount += settlement.price;
|
||||
assert(settlement.iState === 'unsettled', '订单结算前,settlement必须处于未分账状态');
|
||||
})
|
||||
assert(amount === paid);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
*/
|
||||
];
|
||||
export default checkers;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
import { pipeline } from 'oak-domain/lib/utils/executor';
|
||||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
const checkers = [
|
||||
{
|
||||
/**
|
||||
* 1、settlement.price总和等于settlePlan.price
|
||||
* 2、settlePlan.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;
|
||||
|
|
@ -4,15 +4,71 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef } from 'oak-frontend-base';
|
||||
import AbsFilterPanel from 'oak-frontend-base/es/components/filterPanel';
|
||||
import AbsList from 'oak-frontend-base/es/components/list';
|
||||
import AbsListPro from 'oak-frontend-base/es/components/listPro';
|
||||
import AbsDetail from 'oak-frontend-base/es/components/detail';
|
||||
import AbsUpsert from 'oak-frontend-base/es/components/upsert';
|
||||
declare const FilterPanel: <T extends keyof EntityDict>(...props: Parameters<typeof AbsFilterPanel<EntityDict, T>>) => React.ReactElement;
|
||||
declare const List: <T extends keyof EntityDict>(...props: Parameters<typeof AbsList<EntityDict, T>>) => React.ReactElement;
|
||||
declare const ListPro: <T extends keyof EntityDict>(...props: Parameters<typeof AbsListPro<EntityDict, T>>) => React.ReactElement;
|
||||
declare const Detail: <T extends keyof EntityDict>(...props: Parameters<typeof AbsDetail<EntityDict, T>>) => React.ReactElement;
|
||||
declare const Upsert: <T extends keyof EntityDict>(...props: Parameters<typeof AbsUpsert<EntityDict, T>>) => React.ReactElement;
|
||||
import { ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef, ListButtonProps, OakAbsAttrUpsertDef } from 'oak-frontend-base';
|
||||
declare const FilterPanel: <T extends keyof EntityDict>(props: ReactComponentProps<EntityDict, T, false, {
|
||||
entity: T;
|
||||
columns: ColumnProps<EntityDict, T>[];
|
||||
}>) => React.ReactElement;
|
||||
declare const List: <T extends keyof EntityDict>(props: ReactComponentProps<EntityDict, T, false, {
|
||||
entity: T;
|
||||
extraActions: OakExtraActionProps[] | ((row: RowWithActions<EntityDict, T>) => OakExtraActionProps[]);
|
||||
onAction: onActionFnDef;
|
||||
disabledOp: boolean;
|
||||
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, };
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
export default function Render(props: {
|
||||
accountOpers: EntityDict['accountOper']['OpSchema'][];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { EntityDict } from "../../../oak-app-domain";
|
|||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "order", false, {
|
||||
accountId: string;
|
||||
accountAvailMax: number;
|
||||
onSetPays: (pays: Partial<EntityDict["pay"]["CreateOperationData"]>[]) => void;
|
||||
onSetPays: (pays: Partial<EntityDict['pay']['CreateOperationData']>[]) => void;
|
||||
accountTips: string;
|
||||
autoStartPay: boolean;
|
||||
}>) => React.ReactElement;
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ export default OakComponent({
|
|||
},
|
||||
isList: false,
|
||||
properties: {
|
||||
accountId: '', // 是否可以使用帐户中的余额抵扣
|
||||
accountAvailMax: 0, // 本次交易可以使用的帐户中的Avail max值,调用者自己保证此数值的一致性,不要扣成负数
|
||||
accountId: '',
|
||||
accountAvailMax: 0,
|
||||
onSetPays: (pays) => undefined,
|
||||
accountTips: '', // 使用余额支付的提示说明
|
||||
accountTips: '',
|
||||
autoStartPay: false,
|
||||
},
|
||||
formData({ data }) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="react" />
|
||||
export default function Info(props: {
|
||||
price: number;
|
||||
t: (k: string) => string;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="react" />
|
||||
import { PayChannelOption } from "../../../types/Pay";
|
||||
export default function Render(props: {
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="react" />
|
||||
import { PayChannelOption } from "../../../types/Pay";
|
||||
export default function Render(props: {
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
import { EntityDict } from "../../../../oak-app-domain";
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "wechatMpShip", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ export default OakComponent({
|
|||
},
|
||||
},
|
||||
filter: {
|
||||
settled: false,
|
||||
settled: 0,
|
||||
price: {
|
||||
$gt: 0,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
import { EntityDict } from "../../../oak-app-domain";
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "withdraw", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function render(props: {
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export default function render(props: {
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, "withdrawTransfer", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -924,7 +924,9 @@ const i18ns = [
|
|||
"create": {
|
||||
"hasAnotherRefunding": "您有一笔退款正在进行中",
|
||||
"exceedMax": "退款额度大于可用值",
|
||||
"payUnrefundable": "支付已经不可退款"
|
||||
"payUnrefundable": "支付已经不可退款",
|
||||
"opersNotEnough": "指定退款帐户的操作金额总和不足",
|
||||
"opersExceed": "指定退款帐户的操作金额总和超过订单已结算金额"
|
||||
}
|
||||
},
|
||||
"pay": {
|
||||
|
|
@ -932,7 +934,11 @@ const i18ns = [
|
|||
"priceOverflow": "支付金额总和大于订单金额"
|
||||
},
|
||||
"ship": {
|
||||
"noClazz": "当前物流未关联外部接口"
|
||||
"noClazz": "当前物流未关联外部接口",
|
||||
"uploadShipException": "小程序上传发货信息异常"
|
||||
},
|
||||
"settlePlan": {
|
||||
"exceed": "结算计划总金额超过订单可结算金额上限"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { String, Price } from 'oak-domain/lib/types/DataType';
|
|||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDesc } from 'oak-domain/lib/types';
|
||||
import { Schema as Account } from './Account';
|
||||
type Type = 'deposit' | 'withdraw' | 'consume' | '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 {
|
||||
account: Account;
|
||||
type: Type;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ export const entityDesc = {
|
|||
cutoffRefundable: '削减可自由退额度',
|
||||
refund: '退款',
|
||||
refundFailure: '退款失败',
|
||||
preSettle: '预分账',
|
||||
settle: '分账',
|
||||
},
|
||||
},
|
||||
|
|
@ -52,7 +51,6 @@ export const entityDesc = {
|
|||
cutoffRefundable: '#2E4053',
|
||||
refund: '#CC3333',
|
||||
refundFailure: '#009933',
|
||||
preSettle: '#8A631D',
|
||||
settle: '#157d5a',
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export const entityDesc = {
|
|||
keyType: '指定应用私钥类型',
|
||||
gateway: "支付宝网关地址",
|
||||
wsServiceUrl: 'websocket服务地址',
|
||||
timeout: "网关超时时间", //(单位毫秒),默认值是 5000
|
||||
timeout: "网关超时时间",
|
||||
needEncrypt: "是否需要AES加解密",
|
||||
encryptKey: 'AES密钥', //调用AES加解密相关接口时需要
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ export interface Schema extends EntityShape {
|
|||
price: Price;
|
||||
paid: Price;
|
||||
refunded: Price;
|
||||
settled: Price;
|
||||
settlePlanned: Price;
|
||||
title: String<32>;
|
||||
desc: Text;
|
||||
timeoutAt?: Datetime;
|
||||
creator: User;
|
||||
entity: String<32>;
|
||||
entityId: String<64>;
|
||||
settled: Boolean;
|
||||
allowPartialPay?: Boolean;
|
||||
system: System;
|
||||
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 IState = 'unpaid' | 'timeout' | 'cancelled' | 'paying' | 'partiallyPaid' | 'paid' | 'refunding' | 'partiallyRefunded' | 'refunded';
|
||||
export declare const IActionDef: ActionDef<IAction, IState>;
|
||||
export type Action = IAction | 'settle';
|
||||
export type Action = IAction;
|
||||
export declare const entityDesc: EntityDesc<Schema, Action, '', {
|
||||
iState: IState;
|
||||
}>;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ export const entityDesc = {
|
|||
price: '订单金额',
|
||||
paid: '已支付金额',
|
||||
refunded: '已退款金额',
|
||||
settled: '已结算金额',
|
||||
settlePlanned: '已计划结算金额',
|
||||
iState: '订单状态',
|
||||
title: '订单标题',
|
||||
desc: "订单描述",
|
||||
|
|
@ -59,7 +61,6 @@ export const entityDesc = {
|
|||
creator: '创建者',
|
||||
entity: '关联对象',
|
||||
entityId: '关联对象Id',
|
||||
settled: '是否结算',
|
||||
opers: '相关帐户操作',
|
||||
system: '所属系统',
|
||||
address: '收货地址',
|
||||
|
|
@ -76,7 +77,6 @@ export const entityDesc = {
|
|||
refundAll: '完全退款',
|
||||
refundNone: '退款失败',
|
||||
refundPartially: '部分退款',
|
||||
settle: '结算',
|
||||
},
|
||||
v: {
|
||||
iState: {
|
||||
|
|
@ -105,7 +105,6 @@ export const entityDesc = {
|
|||
refundAll: '',
|
||||
refundNone: '',
|
||||
refundPartially: '',
|
||||
settle: '',
|
||||
},
|
||||
color: {
|
||||
iState: {
|
||||
|
|
|
|||
|
|
@ -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 {};
|
||||
|
|
@ -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'
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -2,18 +2,18 @@ import { Price } 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 Account } from './Account';
|
||||
import { Schema as Order } from './Order';
|
||||
import { Schema as SettlePlan } from './SettlePlan';
|
||||
import { Schema as AccountOper } from './AccountOper';
|
||||
export interface Schema extends EntityShape {
|
||||
account: Account;
|
||||
plan: SettlePlan;
|
||||
price: Price;
|
||||
order: Order;
|
||||
opers?: AccountOper[];
|
||||
}
|
||||
type IState = 'unsettled' | 'settled';
|
||||
type IAction = 'settle';
|
||||
type IState = 'unsettled' | 'settled' | 'closed';
|
||||
type IAction = 'settle' | 'close';
|
||||
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, '', {
|
||||
iState: IState;
|
||||
}>;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
export const IActionDef = {
|
||||
stm: {
|
||||
settle: ['unsettled', 'settled'],
|
||||
close: ['unsettled', 'closed'],
|
||||
},
|
||||
is: 'unsettled',
|
||||
};
|
||||
|
|
@ -11,14 +12,14 @@ export const entityDesc = {
|
|||
name: '结算明细',
|
||||
attr: {
|
||||
account: '帐号',
|
||||
plan: '结算计划',
|
||||
price: '变化金额',
|
||||
order: '订单',
|
||||
iState: '结算状态',
|
||||
opers: '相关帐户操作',
|
||||
},
|
||||
action: {
|
||||
preSettle: '预结算',
|
||||
settle: '结算',
|
||||
close: '关闭',
|
||||
refund: '退款',
|
||||
refundFailure: '退款失败',
|
||||
},
|
||||
|
|
@ -26,6 +27,7 @@ export const entityDesc = {
|
|||
iState: {
|
||||
unsettled: '未结算',
|
||||
settled: '已结算',
|
||||
closed: '已关闭',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -40,6 +42,7 @@ export const entityDesc = {
|
|||
iState: {
|
||||
unsettled: '#52BE80',
|
||||
settled: '#2E86C1',
|
||||
closed: '#8C949C'
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@
|
|||
"create": {
|
||||
"hasAnotherRefunding": "您有一笔退款正在进行中",
|
||||
"exceedMax": "退款额度大于可用值",
|
||||
"payUnrefundable": "支付已经不可退款"
|
||||
"payUnrefundable": "支付已经不可退款",
|
||||
"opersNotEnough": "指定退款帐户的操作金额总和不足",
|
||||
"opersExceed": "指定退款帐户的操作金额总和超过订单已结算金额"
|
||||
}
|
||||
},
|
||||
"pay": {
|
||||
|
|
@ -29,6 +31,10 @@
|
|||
"priceOverflow": "支付金额总和大于订单金额"
|
||||
},
|
||||
"ship": {
|
||||
"noClazz": "当前物流未关联外部接口"
|
||||
"noClazz": "当前物流未关联外部接口",
|
||||
"uploadShipException": "小程序上传发货信息异常"
|
||||
},
|
||||
"settlePlan": {
|
||||
"exceed": "结算计划总金额超过订单可结算金额上限"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export const desc = {
|
|||
type: {
|
||||
notNull: true,
|
||||
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: {
|
||||
notNull: true,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ export const style = {
|
|||
cutoffRefundable: '#2E4053',
|
||||
refund: '#CC3333',
|
||||
refundFailure: '#009933',
|
||||
preSettle: '#8A631D',
|
||||
settle: '#157d5a',
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 { AppendOnlyAction } from "oak-domain/lib/actions/action";
|
||||
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 & {
|
||||
accountId: ForeignKey<"account">;
|
||||
type: Type;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
"cutoffRefundable": "削减可自由退额度",
|
||||
"refund": "退款",
|
||||
"refundFailure": "退款失败",
|
||||
"preSettle": "预分账",
|
||||
"settle": "分账"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ export declare const actionDefDict: {
|
|||
settlement: {
|
||||
iState: import("oak-domain/lib/types").ActionDef<string, string>;
|
||||
};
|
||||
settlePlan: {
|
||||
iState: import("oak-domain/lib/types").ActionDef<string, string>;
|
||||
};
|
||||
ship: {
|
||||
iState: import("oak-domain/lib/types").ActionDef<string, string>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import { actionDefDict as order } from "./Order/Action";
|
|||
import { actionDefDict as pay } from "./Pay/Action";
|
||||
import { actionDefDict as refund } from "./Refund/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 user } from "./User/Action";
|
||||
import { actionDefDict as withdraw } from "./Withdraw/Action";
|
||||
|
|
@ -58,6 +59,7 @@ export const actionDefDict = {
|
|||
pay,
|
||||
refund,
|
||||
settlement,
|
||||
settlePlan,
|
||||
ship,
|
||||
user,
|
||||
withdraw,
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ import * as BaseOrder from "./Order/_baseSchema";
|
|||
import * as BasePay from "./Pay/_baseSchema";
|
||||
import * as BaseRefund from "./Refund/_baseSchema";
|
||||
import * as BaseSettlement from "./Settlement/_baseSchema";
|
||||
import * as BaseSettlePlan from "./SettlePlan/_baseSchema";
|
||||
import * as BaseShip from "./Ship/_baseSchema";
|
||||
import * as BaseShipCompany from "./ShipCompany/_baseSchema";
|
||||
import * as BaseShipOrder from "./ShipOrder/_baseSchema";
|
||||
|
|
@ -4411,11 +4412,11 @@ export type Order = {
|
|||
system: System["Schema"];
|
||||
address?: Address["Schema"];
|
||||
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">>;
|
||||
accountOper$entity?: Array<Omit<AccountOper["Schema"], "entity">>;
|
||||
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">>;
|
||||
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"]> & {
|
||||
$entity: "pay";
|
||||
};
|
||||
settlement$order?: OakSelection<"select", Omit<Settlement["Projection"], "order">, Omit<Settlement["Filter"], "order">, Settlement["Sorter"]> & {
|
||||
$entity: "settlement";
|
||||
settlePlan$order?: OakSelection<"select", Omit<SettlePlan["Projection"], "order">, Omit<SettlePlan["Filter"], "order">, SettlePlan["Sorter"]> & {
|
||||
$entity: "settlePlan";
|
||||
};
|
||||
settlement$order$$aggr?: DeduceAggregation<Omit<Settlement["Projection"], "order">, Omit<Settlement["Filter"], "order">, Settlement["Sorter"]> & {
|
||||
$entity: "settlement";
|
||||
settlePlan$order$$aggr?: DeduceAggregation<Omit<SettlePlan["Projection"], "order">, Omit<SettlePlan["Filter"], "order">, SettlePlan["Sorter"]> & {
|
||||
$entity: "settlePlan";
|
||||
};
|
||||
shipOrder$order?: OakSelection<"select", Omit<ShipOrder["Projection"], "order">, Omit<ShipOrder["Filter"], "order">, ShipOrder["Sorter"]> & {
|
||||
$entity: "shipOrder";
|
||||
|
|
@ -4453,7 +4454,7 @@ export type Order = {
|
|||
system: MakeFilter<System["FilterUnit"]>;
|
||||
address: MakeFilter<Address["FilterUnit"]>;
|
||||
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;
|
||||
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"]>;
|
||||
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"]>)[];
|
||||
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"]>)[];
|
||||
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"]>;
|
||||
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"]>)[];
|
||||
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"]>)[];
|
||||
accountOper$entity?: OakOperation<"create", Omit<AccountOper["CreateOperationData"], "order"> | Omit<AccountOper["CreateOperationData"], "order">[]>[];
|
||||
}>;
|
||||
|
|
@ -4684,13 +4685,13 @@ export type Settlement = {
|
|||
Action: BaseSettlement.OpAction;
|
||||
Schema: BaseSettlement.OpSchema & {
|
||||
account: Account["Schema"];
|
||||
order: Order["Schema"];
|
||||
plan: SettlePlan["Schema"];
|
||||
accountOper$entity?: Array<Omit<AccountOper["Schema"], "entity">>;
|
||||
accountOper$entity$$aggr?: AggregationResult<Omit<AccountOper["Schema"], "entity">>;
|
||||
};
|
||||
Projection: BaseSettlement.OpProjection & {
|
||||
account?: Account["Projection"];
|
||||
order?: Order["Projection"];
|
||||
plan?: SettlePlan["Projection"];
|
||||
accountOper$entity?: OakSelection<"select", Omit<AccountOper["Projection"], "settlement">, Omit<AccountOper["Filter"], "settlement">, AccountOper["Sorter"]> & {
|
||||
$entity: "accountOper";
|
||||
};
|
||||
|
|
@ -4700,13 +4701,13 @@ export type Settlement = {
|
|||
};
|
||||
FilterUnit: BaseSettlement.OpFilter & {
|
||||
account: MakeFilter<Account["FilterUnit"]>;
|
||||
order: MakeFilter<Order["FilterUnit"]>;
|
||||
plan: MakeFilter<SettlePlan["FilterUnit"]>;
|
||||
accountOper$entity: MakeFilter<Omit<AccountOper["FilterUnit"], "entity">> & SubQueryPredicateMetadata;
|
||||
};
|
||||
Filter: MakeFilter<Settlement["FilterUnit"]>;
|
||||
SortAttr: Partial<BaseSettlement.OpSortAttr | {
|
||||
account: Account["SortAttr"];
|
||||
order: Order["SortAttr"];
|
||||
plan: SettlePlan["SortAttr"];
|
||||
}>;
|
||||
SortNode: {
|
||||
$attr: Settlement["SortAttr"];
|
||||
|
|
@ -4717,7 +4718,7 @@ export type Settlement = {
|
|||
Aggregation: DeduceAggregation<Settlement["Projection"], Settlement["Filter"], Settlement["Sorter"]>;
|
||||
CreateOperationData: FormCreateData<BaseSettlement.OpSchema & {
|
||||
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">[]>[];
|
||||
}>;
|
||||
CreateSingle: OakOperation<"create", Settlement["CreateOperationData"]>;
|
||||
|
|
@ -4725,7 +4726,7 @@ export type Settlement = {
|
|||
Create: Settlement["CreateSingle"] | Settlement["CreateMulti"];
|
||||
UpdateOperationData: FormUpdateData<BaseSettlement.OpSchema & {
|
||||
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">[]>[];
|
||||
}>;
|
||||
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"]>;
|
||||
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 = {
|
||||
OpSchema: BaseShip.OpSchema;
|
||||
Action: BaseShip.OpAction;
|
||||
|
|
@ -5719,6 +5768,7 @@ export type EntityDict = {
|
|||
pay: Pay;
|
||||
refund: Refund;
|
||||
settlement: Settlement;
|
||||
settlePlan: SettlePlan;
|
||||
ship: Ship;
|
||||
shipCompany: ShipCompany;
|
||||
shipOrder: ShipOrder;
|
||||
|
|
|
|||
|
|
@ -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 IState = 'unpaid' | 'timeout' | 'cancelled' | 'paying' | 'partiallyPaid' | 'paid' | 'refunding' | 'partiallyRefunded' | 'refunded' | string;
|
||||
export declare const IActionDef: ActionDef<IAction, IState>;
|
||||
export type ParticularAction = IAction | 'settle';
|
||||
export type ParticularAction = IAction;
|
||||
export declare const actions: string[];
|
||||
export type Action = GenericAction | ParticularAction | string;
|
||||
export declare const actionDefDict: {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export const IActionDef = {
|
|||
},
|
||||
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 = {
|
||||
iState: IActionDef
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,6 +13,14 @@ export const desc = {
|
|||
notNull: true,
|
||||
type: "money"
|
||||
},
|
||||
settled: {
|
||||
notNull: true,
|
||||
type: "money"
|
||||
},
|
||||
settlePlanned: {
|
||||
notNull: true,
|
||||
type: "money"
|
||||
},
|
||||
title: {
|
||||
notNull: true,
|
||||
type: "varchar",
|
||||
|
|
@ -46,10 +54,6 @@ export const desc = {
|
|||
length: 64
|
||||
}
|
||||
},
|
||||
settled: {
|
||||
notNull: true,
|
||||
type: "boolean"
|
||||
},
|
||||
allowPartialPay: {
|
||||
type: "boolean"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ export const style = {
|
|||
refundAll: '',
|
||||
refundNone: '',
|
||||
refundPartially: '',
|
||||
settle: '',
|
||||
},
|
||||
color: {
|
||||
iState: {
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@ export type OpSchema = EntityShape & {
|
|||
price: Price;
|
||||
paid: Price;
|
||||
refunded: Price;
|
||||
settled: Price;
|
||||
settlePlanned: Price;
|
||||
title: String<32>;
|
||||
desc: Text;
|
||||
timeoutAt?: Datetime | null;
|
||||
creatorId: ForeignKey<"user">;
|
||||
entity: String<32>;
|
||||
entityId: String<64>;
|
||||
settled: Boolean;
|
||||
allowPartialPay?: Boolean | null;
|
||||
systemId: ForeignKey<"system">;
|
||||
addressId?: ForeignKey<"address"> | null;
|
||||
|
|
@ -31,13 +32,14 @@ export type OpFilter = {
|
|||
price: Q_NumberValue;
|
||||
paid: Q_NumberValue;
|
||||
refunded: Q_NumberValue;
|
||||
settled: Q_NumberValue;
|
||||
settlePlanned: Q_NumberValue;
|
||||
title: Q_StringValue;
|
||||
desc: Q_StringValue;
|
||||
timeoutAt: Q_DateValue;
|
||||
creatorId: Q_StringValue;
|
||||
entity: Q_StringValue;
|
||||
entityId: Q_StringValue;
|
||||
settled: Q_BooleanValue;
|
||||
allowPartialPay: Q_BooleanValue;
|
||||
systemId: Q_StringValue;
|
||||
addressId: Q_StringValue;
|
||||
|
|
@ -54,13 +56,14 @@ export type OpProjection = {
|
|||
price?: number;
|
||||
paid?: number;
|
||||
refunded?: number;
|
||||
settled?: number;
|
||||
settlePlanned?: number;
|
||||
title?: number;
|
||||
desc?: number;
|
||||
timeoutAt?: number;
|
||||
creatorId?: number;
|
||||
entity?: number;
|
||||
entityId?: number;
|
||||
settled?: number;
|
||||
allowPartialPay?: number;
|
||||
systemId?: number;
|
||||
addressId?: number;
|
||||
|
|
@ -75,13 +78,14 @@ export type OpSortAttr = Partial<{
|
|||
price: number;
|
||||
paid: number;
|
||||
refunded: number;
|
||||
settled: number;
|
||||
settlePlanned: number;
|
||||
title: number;
|
||||
desc: number;
|
||||
timeoutAt: number;
|
||||
creatorId: number;
|
||||
entity: number;
|
||||
entityId: number;
|
||||
settled: number;
|
||||
allowPartialPay: number;
|
||||
systemId: number;
|
||||
addressId: number;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
"price": "订单金额",
|
||||
"paid": "已支付金额",
|
||||
"refunded": "已退款金额",
|
||||
"settled": "已结算金额",
|
||||
"settlePlanned": "已计划结算金额",
|
||||
"iState": "订单状态",
|
||||
"title": "订单标题",
|
||||
"desc": "订单描述",
|
||||
|
|
@ -12,7 +14,6 @@
|
|||
"creator": "创建者",
|
||||
"entity": "关联对象",
|
||||
"entityId": "关联对象Id",
|
||||
"settled": "是否结算",
|
||||
"opers": "相关帐户操作",
|
||||
"system": "所属系统",
|
||||
"address": "收货地址",
|
||||
|
|
@ -28,8 +29,7 @@
|
|||
"startRefunding": "开始退款",
|
||||
"refundAll": "完全退款",
|
||||
"refundNone": "退款失败",
|
||||
"refundPartially": "部分退款",
|
||||
"settle": "结算"
|
||||
"refundPartially": "部分退款"
|
||||
},
|
||||
"v": {
|
||||
"iState": {
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
@ -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
|
||||
};
|
||||
|
|
@ -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"];
|
||||
|
|
@ -0,0 +1 @@
|
|||
export * from "./_baseSchema";
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { StorageDesc } from "oak-domain/lib/types/Storage";
|
||||
import { OpSchema } from "./Schema";
|
||||
export declare const desc: StorageDesc<OpSchema>;
|
||||
|
|
@ -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
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { Action, OpSchema } from "./Schema";
|
||||
import { StyleDef } from "oak-domain/lib/types/Style";
|
||||
export declare const style: StyleDef<OpSchema, Action>;
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
export const style = {
|
||||
icon: {
|
||||
settle: '',
|
||||
close: '',
|
||||
},
|
||||
color: {
|
||||
iState: {
|
||||
unsettled: '#52BE80',
|
||||
settled: '#2E86C1',
|
||||
closed: '#8C949C'
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
@ -0,0 +1 @@
|
|||
export {};
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "结算计划",
|
||||
"attr": {
|
||||
"when": "结算时间",
|
||||
"order": "订单",
|
||||
"price": "结算金额",
|
||||
"iState": "结算计划状态"
|
||||
},
|
||||
"action": {
|
||||
"settle": "结算",
|
||||
"close": "关闭"
|
||||
},
|
||||
"v": {
|
||||
"iState": {
|
||||
"unsettled": "未结算",
|
||||
"settled": "已结算",
|
||||
"closed": "已关闭"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import { ActionDef } from "oak-domain/lib/types/Action";
|
||||
import { GenericAction } from "oak-domain/lib/actions/action";
|
||||
export type IState = 'unsettled' | 'settled' | string;
|
||||
export type IAction = 'settle' | string;
|
||||
export type IState = 'unsettled' | 'settled' | 'closed' | string;
|
||||
export type IAction = 'settle' | 'close' | string;
|
||||
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 type Action = GenericAction | ParticularAction | string;
|
||||
export declare const actionDefDict: {
|
||||
|
|
|
|||
|
|
@ -1,10 +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", "preSettle", "refund", "refundFailure"];
|
||||
export const actions = ["count", "stat", "download", "select", "aggregate", "create", "remove", "update", "settle", "close", "refund", "refundFailure"];
|
||||
export const actionDefDict = {
|
||||
iState: IActionDef
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,18 +6,18 @@ export const desc = {
|
|||
type: "ref",
|
||||
ref: "account"
|
||||
},
|
||||
planId: {
|
||||
notNull: true,
|
||||
type: "ref",
|
||||
ref: "settlePlan"
|
||||
},
|
||||
price: {
|
||||
notNull: true,
|
||||
type: "money"
|
||||
},
|
||||
orderId: {
|
||||
notNull: true,
|
||||
type: "ref",
|
||||
ref: "order"
|
||||
},
|
||||
iState: {
|
||||
type: "enum",
|
||||
enumeration: ["unsettled", "settled"]
|
||||
enumeration: ["unsettled", "settled", "closed"]
|
||||
}
|
||||
},
|
||||
actionType: "crud",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export const style = {
|
|||
iState: {
|
||||
unsettled: '#52BE80',
|
||||
settled: '#2E86C1',
|
||||
closed: '#8C949C'
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import { Action, ParticularAction, IState } from "./Action";
|
|||
import { Price } from "oak-domain/lib/types/DataType";
|
||||
export type OpSchema = EntityShape & {
|
||||
accountId: ForeignKey<"account">;
|
||||
planId: ForeignKey<"settlePlan">;
|
||||
price: Price;
|
||||
orderId: ForeignKey<"order">;
|
||||
iState?: IState | null;
|
||||
} & {
|
||||
[A in ExpressionKey]?: any;
|
||||
|
|
@ -18,8 +18,8 @@ export type OpFilter = {
|
|||
$$seq$$: Q_NumberValue;
|
||||
$$updateAt$$: Q_DateValue;
|
||||
accountId: Q_StringValue;
|
||||
planId: Q_StringValue;
|
||||
price: Q_NumberValue;
|
||||
orderId: Q_StringValue;
|
||||
iState: Q_EnumValue<IState>;
|
||||
} & ExprOp<OpAttr | string>;
|
||||
export type OpProjection = {
|
||||
|
|
@ -30,8 +30,8 @@ export type OpProjection = {
|
|||
$$updateAt$$?: number;
|
||||
$$seq$$?: number;
|
||||
accountId?: number;
|
||||
planId?: number;
|
||||
price?: number;
|
||||
orderId?: number;
|
||||
iState?: number;
|
||||
} & Partial<ExprOp<OpAttr | string>>;
|
||||
export type OpSortAttr = Partial<{
|
||||
|
|
@ -40,8 +40,8 @@ export type OpSortAttr = Partial<{
|
|||
$$seq$$: number;
|
||||
$$updateAt$$: number;
|
||||
accountId: number;
|
||||
planId: number;
|
||||
price: number;
|
||||
orderId: number;
|
||||
iState: number;
|
||||
[k: string]: any;
|
||||
} | ExprOp<OpAttr | string>>;
|
||||
|
|
|
|||
|
|
@ -2,21 +2,22 @@
|
|||
"name": "结算明细",
|
||||
"attr": {
|
||||
"account": "帐号",
|
||||
"plan": "结算计划",
|
||||
"price": "变化金额",
|
||||
"order": "订单",
|
||||
"iState": "结算状态",
|
||||
"opers": "相关帐户操作"
|
||||
},
|
||||
"action": {
|
||||
"preSettle": "预结算",
|
||||
"settle": "结算",
|
||||
"close": "关闭",
|
||||
"refund": "退款",
|
||||
"refundFailure": "退款失败"
|
||||
},
|
||||
"v": {
|
||||
"iState": {
|
||||
"unsettled": "未结算",
|
||||
"settled": "已结算"
|
||||
"settled": "已结算",
|
||||
"closed": "已关闭"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ import { desc as orderDesc } from "./Order/Storage";
|
|||
import { desc as payDesc } from "./Pay/Storage";
|
||||
import { desc as refundDesc } from "./Refund/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 shipCompanyDesc } from "./ShipCompany/Storage";
|
||||
import { desc as shipOrderDesc } from "./ShipOrder/Storage";
|
||||
|
|
@ -158,6 +159,7 @@ export const storageSchema = {
|
|||
pay: payDesc,
|
||||
refund: refundDesc,
|
||||
settlement: settlementDesc,
|
||||
settlePlan: settlePlanDesc,
|
||||
ship: shipDesc,
|
||||
shipCompany: shipCompanyDesc,
|
||||
shipOrder: shipOrderDesc,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import { style as order } from "./Order/Style";
|
|||
import { style as pay } from "./Pay/Style";
|
||||
import { style as refund } from "./Refund/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 sysAccountOper } from "./SysAccountOper/Style";
|
||||
import { style as user } from "./User/Style";
|
||||
|
|
@ -84,6 +85,7 @@ export const styleDict = {
|
|||
pay,
|
||||
refund,
|
||||
settlement,
|
||||
settlePlan,
|
||||
ship,
|
||||
sysAccountOper,
|
||||
user,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ export const desc = {
|
|||
type: "ref",
|
||||
ref: "platform"
|
||||
},
|
||||
folder: {
|
||||
folder // 提现的loss在用户提现时计算
|
||||
: {
|
||||
type: "varchar",
|
||||
params: {
|
||||
length: 16
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Timer } from 'oak-domain/lib/types/Timer';
|
||||
import { EntityDict } from '../oak-app-domain/index';
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import withdrawTransferTriggers from './withdrawTransfer';
|
|||
import depositTriggers from './deposit';
|
||||
import shipTriggers from './ship';
|
||||
import orderTriggers from './order';
|
||||
import settlePlanTriggers from './settlePlan';
|
||||
const triggers = [
|
||||
...shipTriggers,
|
||||
...orderTriggers,
|
||||
|
|
@ -27,6 +28,7 @@ const triggers = [
|
|||
...sysAccountOperTriggers,
|
||||
...systemTriggers,
|
||||
...withdrawAccountTriggers,
|
||||
...settlePlanTriggers,
|
||||
];
|
||||
export default triggers;
|
||||
export const optionalTriggers = [
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
||||
import { DATA_SUBSCRIBER_KEYS } from '../config/constants';
|
||||
import assert from 'assert';
|
||||
const triggers = [
|
||||
{
|
||||
/**{
|
||||
name: '订单全部支付后对关联的settlement执行preSettle,更新settlement关联的type为preSettle的accountOper',
|
||||
entity: 'order',
|
||||
action: 'payAll',
|
||||
|
|
@ -20,7 +18,7 @@ const triggers = [
|
|||
}
|
||||
}, {
|
||||
forUpdate: true,
|
||||
});
|
||||
})
|
||||
const settlements = await context.select('settlement', {
|
||||
data: {
|
||||
id: 1,
|
||||
|
|
@ -37,38 +35,39 @@ const triggers = [
|
|||
forUpdate: true,
|
||||
});
|
||||
assert(settlements && settlements.length > 0);
|
||||
|
||||
let amount = 0;
|
||||
for (const settlement of settlements) {
|
||||
const { id: settlementId, price, accountId } = settlement;
|
||||
amount += price;
|
||||
amount += price!;
|
||||
//创建对应的accountOper
|
||||
await context.operate('settlement', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'preSettle',
|
||||
data: {
|
||||
accountOper$entity: [{
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
totalPlus: price,
|
||||
availPlus: 0,
|
||||
accountId: accountId,
|
||||
type: 'preSettle',
|
||||
}
|
||||
}]
|
||||
totalPlus: price,
|
||||
availPlus: 0,
|
||||
accountId: accountId,
|
||||
type: 'preSettle',
|
||||
}
|
||||
}]
|
||||
},
|
||||
filter: {
|
||||
id: settlementId,
|
||||
}
|
||||
}, {});
|
||||
}, {})
|
||||
}
|
||||
assert(order.price === amount);
|
||||
}
|
||||
return;
|
||||
}
|
||||
},
|
||||
{
|
||||
},*/
|
||||
/**{
|
||||
name: '订单执行settle前,对关联的settlement执行settle,更新settlement关联的type为settle的accountOper',
|
||||
entity: 'order',
|
||||
action: 'settle',
|
||||
|
|
@ -77,6 +76,7 @@ const triggers = [
|
|||
priority: 99,
|
||||
fn: async ({ operation }, context, option) => {
|
||||
const { filter } = operation;
|
||||
|
||||
let cnt = 0;
|
||||
const orders = await context.select('order', {
|
||||
data: {
|
||||
|
|
@ -100,17 +100,20 @@ const triggers = [
|
|||
forUpdate: true,
|
||||
dontCollect: true,
|
||||
});
|
||||
|
||||
for (const order of orders) {
|
||||
const { settlement$order: settlements } = order || {};
|
||||
assert(settlements && settlements.length > 0);
|
||||
//将关联的settlement执行settle
|
||||
for (const settlement of settlements) {
|
||||
const { id: settlementId, price, accountId } = settlement;
|
||||
await context.operate('settlement', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'settle',
|
||||
data: {
|
||||
accountOper$entity: [{
|
||||
|
||||
await context.operate('settlement',
|
||||
{
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'settle',
|
||||
data: {
|
||||
accountOper$entity: [{
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: {
|
||||
|
|
@ -121,17 +124,19 @@ const triggers = [
|
|||
type: 'settle',
|
||||
}
|
||||
}]
|
||||
},
|
||||
filter: {
|
||||
id: settlementId,
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
id: settlementId,
|
||||
}
|
||||
}, {});
|
||||
{}
|
||||
);
|
||||
cnt += settlements.length;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
},
|
||||
},
|
||||
},*/
|
||||
{
|
||||
name: '订单状态改变时,向订阅者发送消息',
|
||||
entity: 'order',
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { generateNewId, generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
|||
import { getAccountEntity, getPayClazz } from '../utils/payClazz';
|
||||
import assert from 'assert';
|
||||
import { updateWithdrawState } from './withdraw';
|
||||
import { RefundExceedMax, PayUnRefundable } from '../types/Exception';
|
||||
import { RefundExceedMax, PayUnRefundable, settlePlanExceed, refundOpersNotEnough, refundOpersExceed } from '../types/Exception';
|
||||
/**
|
||||
* 开始退款的逻辑
|
||||
* @param context
|
||||
|
|
@ -25,17 +25,31 @@ async function startRefunding(context, data) {
|
|||
},
|
||||
order: {
|
||||
id: 1,
|
||||
paid: 1,
|
||||
refunded: 1,
|
||||
settled: 1,
|
||||
settlement$order: {
|
||||
$entity: 'settlement',
|
||||
settlePlanned: 1,
|
||||
settlePlan$order: {
|
||||
$entity: 'settlePlan',
|
||||
data: {
|
||||
id: 1,
|
||||
accountId: 1,
|
||||
price: 1,
|
||||
iState: 1,
|
||||
settlement$plan: {
|
||||
$entity: 'settlement',
|
||||
data: {
|
||||
id: 1,
|
||||
accountId: 1,
|
||||
price: 1,
|
||||
iState: 1,
|
||||
},
|
||||
filter: {
|
||||
iState: 'unsettled'
|
||||
}
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
iState: 'unsettled',
|
||||
iState: 'unsettled'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -74,47 +88,91 @@ async function startRefunding(context, data) {
|
|||
}
|
||||
else {
|
||||
assert(order);
|
||||
//订单退款的钱要有明确的来源account
|
||||
const { accountOper$entity: opers } = data;
|
||||
assert(opers && opers instanceof Array, '订单退款一定要有相应的account来源');
|
||||
if (order.settled) {
|
||||
// 已经分账
|
||||
// 对settlePlan检查
|
||||
// 未结算的settlePlan的金额总和 = order.paid - order.refunded - order.settled - refunded.price
|
||||
const { settlePlan$order: settlePlans, paid, refunded, settled } = order;
|
||||
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;
|
||||
// 有明确的来源account
|
||||
assert(opers && opers instanceof Array, '已结算的订单退款一定要有相应的account来源');
|
||||
opers.forEach(({ action, data }) => {
|
||||
assert(action === 'create');
|
||||
const { type, totalPlus, availPlus, refundablePlus } = data;
|
||||
const { type, totalPlus, availPlus, accountId } = data;
|
||||
assert(type === 'refund');
|
||||
assert(totalPlus === availPlus);
|
||||
const settlement = settlements?.find((ele) => ele?.accountId === accountId);
|
||||
assert(!!settlement, '请从订单分账的相关账户中选择订单退款的account来源');
|
||||
amount += -totalPlus;
|
||||
});
|
||||
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 {
|
||||
//未完成分账的订单退款,关联的AccountOper的totalPlus总和等于refund的price
|
||||
//同时更新对应的settlement的price
|
||||
let amount = 0;
|
||||
const { settlement$order: settlements } = order;
|
||||
for (const oper of opers) {
|
||||
const { action, data } = oper;
|
||||
assert(action === 'create');
|
||||
const { type, totalPlus, accountId } = data;
|
||||
assert(type === 'refund');
|
||||
amount += -totalPlus;
|
||||
const settlement = settlements?.find((ele) => ele.accountId === accountId);
|
||||
assert(!!settlement, '请从订单分账的相关账户中选择订单退款的account来源');
|
||||
const settlementNewPrice = settlement.price + totalPlus; //可能为负值
|
||||
await context.operate('settlement', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'refund',
|
||||
data: {
|
||||
price: settlementNewPrice,
|
||||
},
|
||||
filter: {
|
||||
id: settlement.id,
|
||||
}
|
||||
}, {});
|
||||
//部分结算
|
||||
/**
|
||||
* 部分结算的订单:
|
||||
* 1. opers的金额总和 <= 订单已结算金额
|
||||
* 2. opers的金额总和 + unsettled的金额 >= 退款金额
|
||||
*/
|
||||
let opersPrice = 0;
|
||||
if (opers && opers.length > 0) {
|
||||
opers.forEach(({ action, data }) => {
|
||||
assert(action === 'create');
|
||||
const { type, totalPlus, availPlus, accountId } = data;
|
||||
assert(type === 'refund');
|
||||
assert(totalPlus === availPlus);
|
||||
const settlement = settlements?.find((ele) => ele?.accountId === accountId);
|
||||
assert(!!settlement, '请从订单分账的相关账户中选择订单退款的account来源');
|
||||
opersPrice += -totalPlus;
|
||||
});
|
||||
}
|
||||
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 = {
|
||||
|
|
@ -309,18 +367,6 @@ async function failRefunding(context, refundId) {
|
|||
order: {
|
||||
id: 1,
|
||||
settled: 1,
|
||||
settlement$order: {
|
||||
$entity: 'settlement',
|
||||
data: {
|
||||
id: 1,
|
||||
accountId: 1,
|
||||
price: 1,
|
||||
iState: 1,
|
||||
},
|
||||
filter: {
|
||||
iState: 'unsettled',
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
|
|
@ -367,51 +413,38 @@ async function failRefunding(context, refundId) {
|
|||
entityId: refundId,
|
||||
},
|
||||
}, { dontCollect: true });
|
||||
if (order.settled) {
|
||||
// 已经分账
|
||||
let amount = 0;
|
||||
for (const oper of accountOpers) {
|
||||
const { totalPlus, availPlus, accountId } = oper;
|
||||
assert(totalPlus < 0 && totalPlus === availPlus);
|
||||
await context.operate('accountOper', {
|
||||
let opersPrice = 0;
|
||||
for (const oper of accountOpers) {
|
||||
const { totalPlus, availPlus, accountId } = oper;
|
||||
assert(totalPlus < 0 && totalPlus === availPlus);
|
||||
await context.operate('accountOper', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id: await generateNewIdAsync(),
|
||||
totalPlus: -totalPlus,
|
||||
availPlus: -availPlus,
|
||||
type: 'refundFailure',
|
||||
entity: 'refund',
|
||||
entityId: refundId,
|
||||
accountId,
|
||||
}
|
||||
}, {});
|
||||
amount += -availPlus;
|
||||
}
|
||||
assert(amount === refund.price);
|
||||
totalPlus: -totalPlus,
|
||||
availPlus: -availPlus,
|
||||
type: 'refundFailure',
|
||||
entity: 'refund',
|
||||
entityId: refundId,
|
||||
accountId,
|
||||
}
|
||||
}, {});
|
||||
opersPrice += -availPlus;
|
||||
}
|
||||
else {
|
||||
//未完成分账的订单,需要修改settlement
|
||||
let amount = 0;
|
||||
const { settlement$order: settlements } = order;
|
||||
for (const oper of accountOpers) {
|
||||
const { totalPlus, availPlus, accountId } = oper;
|
||||
amount += -totalPlus;
|
||||
const settlement = settlements?.find((ele) => ele.accountId === accountId);
|
||||
assert(!!settlement);
|
||||
const settlementNewPrice = settlement.price - totalPlus;
|
||||
await context.operate('settlement', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'refundFailure',
|
||||
data: {
|
||||
price: settlementNewPrice,
|
||||
},
|
||||
filter: {
|
||||
id: settlement.id,
|
||||
}
|
||||
}, {});
|
||||
}
|
||||
assert(amount === refund.price);
|
||||
//如果refund有accountOper回退order.settled变化
|
||||
if (opersPrice > 0) {
|
||||
const newSettled = order.settled + opersPrice;
|
||||
await context.operate('order', {
|
||||
id: await generateNewIdAsync(),
|
||||
action: 'update',
|
||||
data: {
|
||||
settled: newSettled
|
||||
},
|
||||
filter: {
|
||||
id: order.id,
|
||||
}
|
||||
}, {});
|
||||
}
|
||||
return 1 + accountOpers.length;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -6,6 +6,6 @@ import { BRC } from '../types/RuntimeCxt';
|
|||
* @param context
|
||||
* @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>[];
|
||||
export default triggers;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,73 @@
|
|||
import { OakException, OpRecord } from 'oak-domain/lib/types';
|
||||
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> {
|
||||
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> {
|
||||
reason: any;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,68 @@
|
|||
import { OakException } from 'oak-domain/lib/types';
|
||||
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 {
|
||||
constructor(message) {
|
||||
super(message || '调用发货接口失败');
|
||||
reason;
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="node" />
|
||||
import { EntityDict } from '../oak-app-domain';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import BackendRuntimeContext from '../context/BackendRuntimeContext';
|
||||
|
|
|
|||
|
|
@ -190,10 +190,10 @@ export default class AliPay extends AliPayDebug {
|
|||
const qrCodeWidth = this.apProduct.config?.qrCodeWidth || 100;
|
||||
const params = {
|
||||
bizContent: {
|
||||
subject: pay.order?.desc || (pay.orderId ? '订单支付' : '帐户充值'), // 订单标题
|
||||
out_trade_no: out_trade_no, // 商户订单号,64个字符以内、可包含字母、数字、下划线;需保证在商户端不重复
|
||||
total_amount: totalAmount, // 订单总金额,单位为元
|
||||
product_code: 'FAST_INSTANT_TRADE_PAY', // 销售产品码,商家和支付宝签约的产品码
|
||||
subject: pay.order?.desc || (pay.orderId ? '订单支付' : '帐户充值'),
|
||||
out_trade_no: out_trade_no,
|
||||
total_amount: totalAmount,
|
||||
product_code: 'FAST_INSTANT_TRADE_PAY',
|
||||
notify_url: payNotifyUrl,
|
||||
qr_pay_mode: qrPayMode,
|
||||
qrcode_width: qrCodeWidth,
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ export async function uploadShippingInfo(shipId, context) {
|
|||
const result = await wechatInstance.uploadShippingInfo(shipInfo);
|
||||
if (result?.errcode !== 0) {
|
||||
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);
|
||||
if (result?.errcode !== 0) {
|
||||
console.error(JSON.stringify(result));
|
||||
throw new UploadShipException(result?.message);
|
||||
throw new UploadShipException(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,9 +157,9 @@ export default class WechatMpShipDebug {
|
|||
name: from.name,
|
||||
mobile: from.phone,
|
||||
// country: from!.area!.parent!.parent!.name!, //国家
|
||||
province: from.area.parent.parent.name, //省份
|
||||
city: from.area.parent.name, //市
|
||||
area: from.area.name, // 区
|
||||
province: from.area.parent.parent.name,
|
||||
city: from.area.parent.name,
|
||||
area: from.area.name,
|
||||
address: from.detail, //详细地址
|
||||
},
|
||||
receiver: {
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ import orderWatchers from './order';
|
|||
import payWatchers from './pay';
|
||||
import refundWatchers from './refund';
|
||||
import shipWatchers from './ship';
|
||||
import settlePlanWatchers from './settlePlan';
|
||||
const watchers = [
|
||||
...orderWatchers,
|
||||
...payWatchers,
|
||||
...refundWatchers,
|
||||
...shipWatchers,
|
||||
...settlePlanWatchers,
|
||||
];
|
||||
export default watchers;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ const watchers = [
|
|||
return results.reduce((prev, cur) => mergeOperationResult(prev, cur));
|
||||
}
|
||||
},
|
||||
/* 临时注释掉,trigger上有个bug,改完再放回来
|
||||
{
|
||||
name: '当pay达到禁止退款期限时,关闭退款允许',
|
||||
entity: 'pay',
|
||||
|
|
@ -49,7 +48,7 @@ const watchers = [
|
|||
actionData: {
|
||||
refundable: false,
|
||||
}
|
||||
}, */
|
||||
},
|
||||
{
|
||||
name: '当pay达到过期期限时,关闭pay',
|
||||
entity: 'pay',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getMpShipState = getMpShipState;
|
||||
exports.getExpressPrintInfo = getExpressPrintInfo;
|
||||
exports.getExpressPrintInfo = exports.getMpShipState = void 0;
|
||||
const types_1 = require("oak-domain/lib/types");
|
||||
const ship_1 = require("../utils/ship");
|
||||
const shipClazz_1 = require("../utils/shipClazz");
|
||||
|
|
@ -19,6 +18,7 @@ async function getMpShipState(params, context) {
|
|||
return shipState;
|
||||
}
|
||||
}
|
||||
exports.getMpShipState = getMpShipState;
|
||||
/**
|
||||
* 获取打印面单
|
||||
*/
|
||||
|
|
@ -43,3 +43,4 @@ async function getExpressPrintInfo(params, context) {
|
|||
const clazz = await (0, shipClazz_1.getShipClazz)(entity, entityId, context);
|
||||
return await clazz.getPrintInfo(shipId, context);
|
||||
}
|
||||
exports.getExpressPrintInfo = getExpressPrintInfo;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getWithdrawCreateData = getWithdrawCreateData;
|
||||
exports.getWithdrawCreateData = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const types_1 = require("oak-domain/lib/types");
|
||||
const uuid_1 = require("oak-domain/lib/utils/uuid");
|
||||
|
|
@ -211,3 +211,4 @@ async function getWithdrawCreateData(params, context) {
|
|||
data.loss = totalLoss;
|
||||
return data;
|
||||
}
|
||||
exports.getWithdrawCreateData = getWithdrawCreateData;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.accountEntities = void 0;
|
||||
exports.registerAccountEntity = registerAccountEntity;
|
||||
exports.accountEntities = exports.registerAccountEntity = void 0;
|
||||
const uuid_1 = require("oak-domain/lib/utils/uuid");
|
||||
// 当注入一个新的account entity时,将withdrawChannel的删除与之相关联
|
||||
function registerAccountEntity(entity) {
|
||||
exports.accountEntities.push(entity);
|
||||
}
|
||||
exports.registerAccountEntity = registerAccountEntity;
|
||||
exports.accountEntities = ['offlineAccount'];
|
||||
const triggers = [
|
||||
...exports.accountEntities.filter(ele => !!ele).map((entity) => [
|
||||
|
|
|
|||
|
|
@ -102,22 +102,22 @@ const checkers = [
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'preSettle': {
|
||||
//预分账时账户total增加,avail不变,refundable不变
|
||||
if (totalPlus < 0 || availPlus !== 0 || (refundablePlus && refundablePlus !== 0)) {
|
||||
throw new types_1.OakInputIllegalException('accountOper', ['totalPlus', 'availPlus', 'refundablePlus'], 'accountOper为preSettle时,其totalPlus必须为非负数、availPlus必须为0,refundable必须为空或者0');
|
||||
}
|
||||
break;
|
||||
}
|
||||
// case 'preSettle': {
|
||||
// //预分账时账户total增加,avail不变,refundable不变
|
||||
// if (totalPlus < 0 || availPlus !== 0 || (refundablePlus && refundablePlus !== 0)) {
|
||||
// throw new OakInputIllegalException('accountOper', ['totalPlus', 'availPlus', 'refundablePlus'], 'accountOper为preSettle时,其totalPlus必须为非负数、availPlus必须为0,refundable必须为空或者0');
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
case 'settle': {
|
||||
//分账时账户total不变,refundable不变
|
||||
if (totalPlus !== 0 || (refundablePlus && refundablePlus !== 0)) {
|
||||
throw new types_1.OakInputIllegalException('accountOper', ['totalPlus', 'refundablePlus'], 'accountOper为settle时,其totalPlus必须为0,refundable必须为空或者0');
|
||||
//分账时账户total增加,avail增加,refundable不变
|
||||
if (totalPlus < 0 || availPlus < 0 || (refundablePlus && refundablePlus !== 0)) {
|
||||
throw new types_1.OakInputIllegalException('accountOper', ['totalPlus', 'refundablePlus'], 'accountOper为settle时,其totalPlus、availPlus必须为非负数,refundable必须为空或者0');
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
(0, assert_1.default)(false);
|
||||
// assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ const withdrawAccount_1 = tslib_1.__importDefault(require("./withdrawAccount"));
|
|||
const refund_1 = tslib_1.__importDefault(require("./refund"));
|
||||
const withdrawTransfer_1 = tslib_1.__importDefault(require("./withdrawTransfer"));
|
||||
const ship_1 = tslib_1.__importDefault(require("./ship"));
|
||||
const settlePlan_1 = tslib_1.__importDefault(require("./settlePlan"));
|
||||
const checkers = [
|
||||
...refund_1.default,
|
||||
...withdrawAccount_1.default,
|
||||
|
|
@ -24,5 +25,6 @@ const checkers = [
|
|||
...wpProduct_1.default,
|
||||
...withdrawTransfer_1.default,
|
||||
...ship_1.default,
|
||||
...settlePlan_1.default,
|
||||
];
|
||||
exports.default = checkers;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ const checkers = [
|
|||
}
|
||||
data.paid = 0;
|
||||
data.refunded = 0;
|
||||
data.settled = false;
|
||||
data.settled = 0;
|
||||
data.settlePlanned = 0;
|
||||
if (!data.systemId) {
|
||||
const contextSystemId = context.getApplication()?.systemId;
|
||||
(0, assert_1.default)(contextSystemId);
|
||||
|
|
@ -108,51 +109,59 @@ const checkers = [
|
|||
});
|
||||
}
|
||||
},
|
||||
/**todo 调整至settlePlan 执行settle
|
||||
{
|
||||
// 订单结算,检查存在关联的未结算的settlement,其price之和等于订单的已支付与已退款的差值
|
||||
type: 'logicalData',
|
||||
entity: 'order',
|
||||
action: 'settle',
|
||||
checker: (operation, context) => {
|
||||
const { data, filter } = operation;
|
||||
(0, assert_1.default)(typeof filter.id === 'string');
|
||||
const { data, filter } = operation as EntityDict['order']['Update'];
|
||||
|
||||
assert(typeof filter!.id === 'string');
|
||||
|
||||
data.settled = true;
|
||||
return (0, executor_1.pipeline)(() => context.select('order', {
|
||||
data: {
|
||||
id: 1,
|
||||
price: 1,
|
||||
paid: 1,
|
||||
refunded: 1,
|
||||
iState: 1,
|
||||
settlement$order: {
|
||||
$entity: 'settlement',
|
||||
data: {
|
||||
id: 1,
|
||||
accountId: 1,
|
||||
price: 1,
|
||||
iState: 1,
|
||||
},
|
||||
filter: {
|
||||
iState: 'unsettled'
|
||||
return pipeline(
|
||||
() => context.select('order', {
|
||||
data: {
|
||||
id: 1,
|
||||
price: 1,
|
||||
paid: 1,
|
||||
refunded: 1,
|
||||
iState: 1,
|
||||
settlement$order: {
|
||||
$entity: 'settlement',
|
||||
data: {
|
||||
id: 1,
|
||||
accountId: 1,
|
||||
price: 1,
|
||||
iState: 1,
|
||||
},
|
||||
filter: {
|
||||
iState: 'unsettled'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
id: filter.id,
|
||||
},
|
||||
}, {}), (orders) => {
|
||||
const [order] = orders;
|
||||
const { price, paid, refunded, iState, settlement$order: settlements } = order;
|
||||
(0, assert_1.default)(['paid'].includes(iState) && refunded === 0 && paid === price);
|
||||
(0, assert_1.default)(settlements && settlements.length > 0, '该结算订单需添加结算明细');
|
||||
let amount = 0;
|
||||
settlements.forEach((settlement) => {
|
||||
amount += settlement.price;
|
||||
(0, assert_1.default)(settlement.iState === 'unsettled', '订单结算前,settlement必须处于未分账状态');
|
||||
});
|
||||
(0, assert_1.default)(amount === paid);
|
||||
});
|
||||
},
|
||||
filter: {
|
||||
id: filter!.id!,
|
||||
},
|
||||
}, {}),
|
||||
(orders: EntityDict['order']['Schema'][]) => {
|
||||
const [order] = orders;
|
||||
const { price, paid, refunded, iState, settlement$order: settlements } = order;
|
||||
assert(['paid'].includes(iState!) && refunded === 0 && paid === price);
|
||||
assert(settlements && settlements.length > 0, '该结算订单需添加结算明细');
|
||||
|
||||
let amount = 0;
|
||||
settlements.forEach((settlement) => {
|
||||
amount += settlement.price;
|
||||
assert(settlement.iState === 'unsettled', '订单结算前,settlement必须处于未分账状态');
|
||||
})
|
||||
assert(amount === paid);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
*/
|
||||
];
|
||||
exports.default = checkers;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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 = [
|
||||
{
|
||||
/**
|
||||
* 1、settlement.price总和等于settlePlan.price
|
||||
* 2、settlePlan.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;
|
||||
|
|
@ -926,7 +926,9 @@ const i18ns = [
|
|||
"create": {
|
||||
"hasAnotherRefunding": "您有一笔退款正在进行中",
|
||||
"exceedMax": "退款额度大于可用值",
|
||||
"payUnrefundable": "支付已经不可退款"
|
||||
"payUnrefundable": "支付已经不可退款",
|
||||
"opersNotEnough": "指定退款帐户的操作金额总和不足",
|
||||
"opersExceed": "指定退款帐户的操作金额总和超过订单已结算金额"
|
||||
}
|
||||
},
|
||||
"pay": {
|
||||
|
|
@ -934,7 +936,11 @@ const i18ns = [
|
|||
"priceOverflow": "支付金额总和大于订单金额"
|
||||
},
|
||||
"ship": {
|
||||
"noClazz": "当前物流未关联外部接口"
|
||||
"noClazz": "当前物流未关联外部接口",
|
||||
"uploadShipException": "小程序上传发货信息异常"
|
||||
},
|
||||
"settlePlan": {
|
||||
"exceed": "结算计划总金额超过订单可结算金额上限"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { String, Price } from 'oak-domain/lib/types/DataType';
|
|||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDesc } from 'oak-domain/lib/types';
|
||||
import { Schema as Account } from './Account';
|
||||
type Type = 'deposit' | 'withdraw' | 'consume' | '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 {
|
||||
account: Account;
|
||||
type: Type;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ exports.entityDesc = {
|
|||
cutoffRefundable: '削减可自由退额度',
|
||||
refund: '退款',
|
||||
refundFailure: '退款失败',
|
||||
preSettle: '预分账',
|
||||
settle: '分账',
|
||||
},
|
||||
},
|
||||
|
|
@ -55,7 +54,6 @@ exports.entityDesc = {
|
|||
cutoffRefundable: '#2E4053',
|
||||
refund: '#CC3333',
|
||||
refundFailure: '#009933',
|
||||
preSettle: '#8A631D',
|
||||
settle: '#157d5a',
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ exports.entityDesc = {
|
|||
keyType: '指定应用私钥类型',
|
||||
gateway: "支付宝网关地址",
|
||||
wsServiceUrl: 'websocket服务地址',
|
||||
timeout: "网关超时时间", //(单位毫秒),默认值是 5000
|
||||
timeout: "网关超时时间",
|
||||
needEncrypt: "是否需要AES加解密",
|
||||
encryptKey: 'AES密钥', //调用AES加解密相关接口时需要
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ export interface Schema extends EntityShape {
|
|||
price: Price;
|
||||
paid: Price;
|
||||
refunded: Price;
|
||||
settled: Price;
|
||||
settlePlanned: Price;
|
||||
title: String<32>;
|
||||
desc: Text;
|
||||
timeoutAt?: Datetime;
|
||||
creator: User;
|
||||
entity: String<32>;
|
||||
entityId: String<64>;
|
||||
settled: Boolean;
|
||||
allowPartialPay?: Boolean;
|
||||
system: System;
|
||||
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 IState = 'unpaid' | 'timeout' | 'cancelled' | 'paying' | 'partiallyPaid' | 'paid' | 'refunding' | 'partiallyRefunded' | 'refunded';
|
||||
export declare const IActionDef: ActionDef<IAction, IState>;
|
||||
export type Action = IAction | 'settle';
|
||||
export type Action = IAction;
|
||||
export declare const entityDesc: EntityDesc<Schema, Action, '', {
|
||||
iState: IState;
|
||||
}>;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ exports.entityDesc = {
|
|||
price: '订单金额',
|
||||
paid: '已支付金额',
|
||||
refunded: '已退款金额',
|
||||
settled: '已结算金额',
|
||||
settlePlanned: '已计划结算金额',
|
||||
iState: '订单状态',
|
||||
title: '订单标题',
|
||||
desc: "订单描述",
|
||||
|
|
@ -62,7 +64,6 @@ exports.entityDesc = {
|
|||
creator: '创建者',
|
||||
entity: '关联对象',
|
||||
entityId: '关联对象Id',
|
||||
settled: '是否结算',
|
||||
opers: '相关帐户操作',
|
||||
system: '所属系统',
|
||||
address: '收货地址',
|
||||
|
|
@ -79,7 +80,6 @@ exports.entityDesc = {
|
|||
refundAll: '完全退款',
|
||||
refundNone: '退款失败',
|
||||
refundPartially: '部分退款',
|
||||
settle: '结算',
|
||||
},
|
||||
v: {
|
||||
iState: {
|
||||
|
|
@ -108,7 +108,6 @@ exports.entityDesc = {
|
|||
refundAll: '',
|
||||
refundNone: '',
|
||||
refundPartially: '',
|
||||
settle: '',
|
||||
},
|
||||
color: {
|
||||
iState: {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue