微信支付充值调整

This commit is contained in:
lxy 2025-04-08 12:10:06 +08:00
parent 7d3240059c
commit 5f02a3b8cc
23 changed files with 699 additions and 396 deletions

View File

@ -221,9 +221,9 @@ export default OakComponent({
gotoHistoryMp() {
this.props.onGoToHistory();
},
async onUnreceivedDepositClickMp() {
async onUnreceivedDepositClickMp(noMessage) {
const { unreceivedDepositId } = this.state;
const { data: deposits } = await this.features.cache.refresh('deposit', {
const { data: [deposit] } = await this.features.cache.refresh('deposit', {
data: {
id: 1,
iState: 1,
@ -251,10 +251,10 @@ export default OakComponent({
id: unreceivedDepositId,
}
});
const ship = deposits?.[0]?.ship;
const ship = deposit?.ship;
if (ship && ship.id) {
if (ship.iState === 'receiving') {
const transactionId = ship.deposit$ship?.[0]?.pay$deposit?.[0]?.meta?.transaction_id;
const transactionId = deposit?.pay$deposit?.[0]?.meta?.transaction_id;
console.log('transaction_id', transactionId);
if (process.env.NODE_ENV === 'development') {
await this.features.cache.operate('ship', [{
@ -278,9 +278,9 @@ export default OakComponent({
extraData: {
transaction_id: transactionId,
},
async success() {
success: async () => {
console.log('success');
const mpShipState = await this.features.cache.exec('getMpShipState', {
const { result: mpShipState } = await this.features.cache.exec('getMpShipState', {
shipId: ship.id,
});
if (mpShipState === 'received') {
@ -325,17 +325,21 @@ export default OakComponent({
}
}
else {
this.setMessage({
type: 'warning',
content: this.t('no transactionId'),
});
if (!noMessage) {
this.setMessage({
type: 'warning',
content: this.t('no transactionId'),
});
}
}
}
else {
this.setMessage({
content: this.t('ship.wait'),
type: 'warning',
});
if (!noMessage) {
this.setMessage({
content: this.t('ship.wait'),
type: 'warning',
});
}
}
}
}
@ -356,7 +360,47 @@ export default OakComponent({
async ready() {
const { oakId } = this.props;
assert(typeof oakId === 'string');
const unsub = await this.subDataEvents([`${DATA_SUBSCRIBER_KEYS.accountNumberChanged}-${oakId}`]);
const unsub = await this.subDataEvents([`${DATA_SUBSCRIBER_KEYS.accountNumberChanged}-${oakId}`, `${DATA_SUBSCRIBER_KEYS.depositStateChanged}-${oakId}`], async (event, opRecords) => {
for (const record of opRecords) {
if (record.a === 'succeed') {
const { e, d } = record;
if (e === 'deposit') {
await this.features.cache.refresh('deposit', {
data: {
id: 1,
accountId: 1,
iState: 1,
pay$deposit: {
$entity: 'pay',
data: {
id: 1,
meta: 1,
iState: 1,
entity: 1,
entityId: 1,
},
filter: {
entity: 'wpProduct',
iState: 'paid',
}
},
shipId: 1,
ship: {
id: 1,
iState: 1,
}
},
filter: {
accountId: oakId,
iState: {
$in: ['depositing', 'shipped'],
},
}
});
}
}
}
});
this.setState({
unsub,
});
@ -364,6 +408,12 @@ export default OakComponent({
detached() {
const { unsub } = this.state;
unsub && unsub();
}
},
async mature() {
const { unreceivedDepositId } = this.state;
if (!!unreceivedDepositId && process.env.OAK_PLATFORM === 'wechatMp') {
await this.onUnreceivedDepositClickMp(true);
}
},
}
});

View File

@ -1,5 +1,5 @@
<view class="container">
<l-notice-bar show="{{unreceivedDepositId}}" front-icon-name="notification" end-icon-name="right"
<l-notice-bar show="{{!!unreceivedDepositId}}" front-icon-name="notification" end-icon-name="right"
bind:lintap="onUnreceivedDepositClickMp" bind:linicontap="onUnreceivedDepositClickMp">
{{t('ship.unconfirm')}}
</l-notice-bar>

View File

@ -37,7 +37,7 @@ function PayConfig(props) {
</Popover>}>
<Form labelCol={{ span: 8 }} wrapperCol={{ span: 18 }} layout="horizontal" style={{ width: '100%' }}>
<Form.Item label={t('payConfig.label.ratio')}>
<InputNumber value={depositLoss?.ratio} max={20} min={0.01} addonAfter={"%"} step={0.01} precision={2} disabled={!update} onChange={(value) => {
<InputNumber value={depositLoss?.ratio} max={20} min={0} addonAfter={"%"} step={0.01} precision={2} disabled={!update} onChange={(value) => {
const ratio = value;
updateDepositLoss({
ratio: ratio || 0

View File

@ -3,4 +3,5 @@ export declare const DATA_SUBSCRIBER_KEYS: {
orderStateChanged: string;
accountNumberChanged: string;
shipStateChanged: string;
depositStateChanged: string;
};

View File

@ -3,4 +3,5 @@ export const DATA_SUBSCRIBER_KEYS = {
orderStateChanged: 'oak-pay-business-osc',
accountNumberChanged: 'oak-pay-business-anc',
shipStateChanged: 'oak-pay-business-ssc',
depositStateChanged: 'oak-pay-business-dsc',
};

View File

@ -66,5 +66,21 @@ const timers = [
return results.reduce((prev, cur) => mergeOperationResult(prev, cur));
},
},
{
name: '对虚拟或自提类型的ship自动发货',
cron: '0 * * * * ?',
entity: 'ship',
filter: {
type: {
$in: ['virtual', 'pickup'],
},
iState: 'unshipped',
},
projection: {
id: 1,
},
action: 'ship',
actionData: {},
},
];
export default timers;

View File

@ -1,6 +1,7 @@
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
import assert from 'assert';
import { getPayClazz } from '../utils/payClazz';
import { DATA_SUBSCRIBER_KEYS } from '../config/constants';
const triggers = [
/* {
entity: 'deposit',
@ -144,6 +145,32 @@ const triggers = [
}
return cnt;
}
}
},
{
entity: 'deposit',
name: '当deposit状态发生变化时尝试向关联的account订阅者推送',
action: ['succeed', 'fail', 'ship'],
when: 'after',
fn: async ({ operation }, context, option) => {
const { filter, id } = operation;
const { id: depositId } = filter;
const [deposit] = await context.select('deposit', {
data: {
id: 1,
accountId: 1,
},
filter: {
id: depositId,
}
}, {
forUpdate: true,
});
const { accountId } = deposit;
if (accountId) {
context.saveOperationToEvent(id, `${DATA_SUBSCRIBER_KEYS.depositStateChanged}-${accountId}`);
}
return 1;
}
},
];
export default triggers;

View File

@ -68,7 +68,7 @@ const triggers = [
priority: 99,
fn: async ({ operation }, context) => {
const { data, filter } = operation;
const [ship] = await context.select('ship', {
const ships = await context.select('ship', {
data: {
id: 1,
type: 1,
@ -111,40 +111,43 @@ const triggers = [
},
filter,
}, {});
const { id: shipId, type, deposit$ship: deposits, shipOrder$ship, shipServiceId, entity, entityId, wechatMpShip } = ship || {};
if (deposits && deposits.length > 0) {
//充值 (此时该充值必定为受发货限制的小程序上的充值)
await uploadShippingInfo(shipId, context);
return 1;
}
if (shipOrder$ship && shipOrder$ship.length > 0) {
//订单
const wpPayIds = ship.shipOrder$ship?.map((ele) => ele.order).map((order) => order.pay$order).flat().filter((pay) => pay?.entity === 'wpProduct').map((ele) => ele?.id);
let needUpload = false;
if (wpPayIds && wpPayIds.length > 0) {
const cnt = await context.count('pay', {
filter: {
id: {
$in: wpPayIds,
},
iState: {
$ne: 'closed',
},
wpProduct: {
needReceiving: true,
let cnt = 0;
for (const ship of ships) {
const { id: shipId, type, deposit$ship: deposits, shipOrder$ship, shipServiceId, entity, entityId, wechatMpShip } = ship || {};
if (deposits && deposits.length > 0) {
//充值 (此时该充值必定为受发货限制的小程序上的充值)
await uploadShippingInfo(shipId, context);
cnt++;
}
else if (shipOrder$ship && shipOrder$ship.length > 0) {
//订单
const wpPayIds = ship.shipOrder$ship?.map((ele) => ele.order).map((order) => order.pay$order).flat().filter((pay) => pay?.entity === 'wpProduct').map((ele) => ele?.id);
let needUpload = false;
if (wpPayIds && wpPayIds.length > 0) {
const cnt = await context.count('pay', {
filter: {
id: {
$in: wpPayIds,
},
iState: {
$ne: 'closed',
},
wpProduct: {
needReceiving: true,
}
}
}, {});
if (cnt > 0) {
needUpload = true;
}
}, {});
if (cnt > 0) {
needUpload = true;
}
if (needUpload) {
await uploadShippingInfo(shipId, context);
cnt++;
}
}
if (needUpload) {
await uploadShippingInfo(shipId, context);
return 1;
}
}
return 0;
return cnt;
}
},
{
@ -294,51 +297,52 @@ const triggers = [
when: 'commit',
asRoot: true,
fn: async ({ ids }, context, option) => {
assert(ids.length === 1);
const id = ids[0];
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
receiveAt: 1,
shipOrder$ship: {
$entity: 'shipOrder',
data: {
id: 1,
orderId: 1,
order: {
// assert(ids.length === 1);
for (const id of ids) {
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
receiveAt: 1,
shipOrder$ship: {
$entity: 'shipOrder',
data: {
id: 1,
pay$order: {
$entity: 'pay',
data: {
id: 1,
},
filter: {
entity: 'wpProduct',
wpProduct: {
needReceiving: true
orderId: 1,
order: {
id: 1,
pay$order: {
$entity: 'pay',
data: {
id: 1,
},
filter: {
entity: 'wpProduct',
wpProduct: {
needReceiving: true
}
}
}
}
}
}
},
},
},
filter: {
id
}
}, { dontCollect: true, forUpdate: true });
const { type, shipOrder$ship } = ship;
const wpPay = shipOrder$ship?.map((shipOrder) => shipOrder?.order?.pay$order).flat();
if (type === 'virtual' || (type === 'pickup' && wpPay && wpPay.length > 0)) {
await context.operate('ship', {
id: await generateNewIdAsync(),
action: 'startReceiving',
data: {},
filter: {
id,
id
}
}, option);
}, { dontCollect: true, forUpdate: true });
const { type, shipOrder$ship } = ship;
const wpPay = shipOrder$ship?.map((shipOrder) => shipOrder?.order?.pay$order).flat();
if (type === 'virtual' || (type === 'pickup' && wpPay && wpPay.length > 0)) {
await context.operate('ship', {
id: await generateNewIdAsync(),
action: 'startReceiving',
data: {},
filter: {
id,
}
}, option);
}
}
},
},
@ -349,35 +353,36 @@ const triggers = [
when: 'commit',
asRoot: true,
fn: async ({ ids }, context, option) => {
assert(ids.length === 1);
const id = ids[0];
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
deposit$ship: {
$entity: 'deposit',
data: {
id: 1,
iState: 1,
// assert(ids.length === 1);
for (const id of ids) {
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
deposit$ship: {
$entity: 'deposit',
data: {
id: 1,
iState: 1,
}
}
}
},
filter: {
id
}
}, { dontCollect: true, forUpdate: true });
const { type, deposit$ship: deposits } = ship;
if (type === 'virtual' && deposits && deposits.length > 0) {
const [deposit] = deposits;
await context.operate('deposit', {
id: await generateNewIdAsync(),
action: 'succeed',
data: {},
},
filter: {
id: deposit.id,
id
}
}, option);
}, { dontCollect: true, forUpdate: true });
const { type, deposit$ship: deposits } = ship;
if (type === 'virtual' && deposits && deposits.length > 0) {
const [deposit] = deposits;
await context.operate('deposit', {
id: await generateNewIdAsync(),
action: 'succeed',
data: {},
filter: {
id: deposit.id,
}
}, option);
}
}
},
},

View File

@ -2,7 +2,6 @@ import { WechatSDK } from 'oak-external-sdk';
import { assert } from 'oak-domain/lib/utils/assert';
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
import { UploadShipException } from '../types/Exception';
import dayjs from 'dayjs';
import { isMobile } from 'oak-domain/lib/utils/validator';
import { getShipClazz } from './shipClazz';
export const shipProjection = {
@ -145,7 +144,10 @@ export async function uploadShippingInfo(shipId, context) {
// assert(iState === 'unshipped'); //可更改一次发货信息
//发货信息录入前检查小程序订单发货状态
const shipState = await getOrderShipState(context, shipId);
const now = dayjs().format();
const date = new Date();
const isoString = date.toISOString().replace('Z', ''); // 移除UTC的'Z'
// 手动添加时区偏移(例如 +08:00
const finalFormat = `${isoString}+08:00`;
// const application = context.getApplication();
// const { type, config } = application!;
// assert(type === 'wechatMp');
@ -167,14 +169,14 @@ export async function uploadShippingInfo(shipId, context) {
order_number_type: 2,
transaction_id: meta?.transaction_id,
},
logistic_type: 3,
logistics_type: 3,
delivery_mode: 1,
shipping_list: [
{
item_desc: '账户充值',
}
],
upload_time: now,
upload_time: finalFormat,
payer: {
openid: meta?.payer?.openid,
},
@ -224,10 +226,10 @@ export async function uploadShippingInfo(shipId, context) {
order_number_type: 2,
transaction_id: meta?.transaction_id,
},
logistic_type: shipType === 'express' ? 1 : 4,
logistics_type: shipType === 'express' ? 1 : 4,
delivery_mode: 1,
shipping_list: shippingList,
upload_time: now,
upload_time: finalFormat,
payer: {
openid: meta?.payer?.openid,
},
@ -262,7 +264,7 @@ export async function getOrderShipState(context, shipId) {
forUpdate: true
});
assert(ship);
const { deposit$ship: deposits, shipOrder$ship } = ship;
const { deposit$ship: deposits, shipOrder$ship, type } = ship;
let info = undefined, wechatInstance = undefined;
if (deposits && deposits.length > 0) {
//充值
@ -303,10 +305,20 @@ export async function getOrderShipState(context, shipId) {
state = 'unshipped';
break;
case 2: //已发货
state = 'shipping';
if (['pickup', 'virtual'].includes(type)) {
state = 'receiving';
}
else {
state = 'shipping';
}
// action = 'ship';
break;
case 3: //确认收货
if (type === 'express') {
state = 'receiving';
}
break;
case 4: //交易完成
state = 'received';
// action = 'receive';
break;
@ -335,25 +347,30 @@ export async function refreshMpOrderShipState(shipId, context) {
forUpdate: true
});
const mpState = await getOrderShipState(context, shipId);
let action = undefined;
switch (mpState) {
case 'shipping': //已发货
action = 'ship';
break;
case 'received': //已收货
action = 'succeedReceiving';
break;
case 'unknow': //不明
action = 'unknow';
break;
default:
action = undefined;
}
if (action && ship.iState !== mpState) {
// let action = undefined;
// switch (mpState) {
// case 'shipping': //已发货
// action = 'ship';
// break;
// case 'receiving': //已收货
// action = 'startReceiving';
// break;
// case 'received': //已确认
// action = 'succeedReceiving';
// break;
// case 'unknow': //不明
// action = 'unknow';
// break;
// default:
// action = undefined;
// }
if (ship.iState !== mpState) {
return await context.operate('ship', {
id: await generateNewIdAsync(),
action,
data: {},
action: 'update',
data: {
iState: mpState,
},
filter: {
id: ship.id,
}

View File

@ -3,4 +3,5 @@ export declare const DATA_SUBSCRIBER_KEYS: {
orderStateChanged: string;
accountNumberChanged: string;
shipStateChanged: string;
depositStateChanged: string;
};

View File

@ -6,4 +6,5 @@ exports.DATA_SUBSCRIBER_KEYS = {
orderStateChanged: 'oak-pay-business-osc',
accountNumberChanged: 'oak-pay-business-anc',
shipStateChanged: 'oak-pay-business-ssc',
depositStateChanged: 'oak-pay-business-dsc',
};

View File

@ -68,5 +68,21 @@ const timers = [
return results.reduce((prev, cur) => (0, operationResult_1.mergeOperationResult)(prev, cur));
},
},
{
name: '对虚拟或自提类型的ship自动发货',
cron: '0 * * * * ?',
entity: 'ship',
filter: {
type: {
$in: ['virtual', 'pickup'],
},
iState: 'unshipped',
},
projection: {
id: 1,
},
action: 'ship',
actionData: {},
},
];
exports.default = timers;

View File

@ -4,6 +4,7 @@ const tslib_1 = require("tslib");
const uuid_1 = require("oak-domain/lib/utils/uuid");
const assert_1 = tslib_1.__importDefault(require("assert"));
const payClazz_1 = require("../utils/payClazz");
const constants_1 = require("../config/constants");
const triggers = [
/* {
entity: 'deposit',
@ -147,6 +148,32 @@ const triggers = [
}
return cnt;
}
}
},
{
entity: 'deposit',
name: '当deposit状态发生变化时尝试向关联的account订阅者推送',
action: ['succeed', 'fail', 'ship'],
when: 'after',
fn: async ({ operation }, context, option) => {
const { filter, id } = operation;
const { id: depositId } = filter;
const [deposit] = await context.select('deposit', {
data: {
id: 1,
accountId: 1,
},
filter: {
id: depositId,
}
}, {
forUpdate: true,
});
const { accountId } = deposit;
if (accountId) {
context.saveOperationToEvent(id, `${constants_1.DATA_SUBSCRIBER_KEYS.depositStateChanged}-${accountId}`);
}
return 1;
}
},
];
exports.default = triggers;

View File

@ -71,7 +71,7 @@ const triggers = [
priority: 99,
fn: async ({ operation }, context) => {
const { data, filter } = operation;
const [ship] = await context.select('ship', {
const ships = await context.select('ship', {
data: {
id: 1,
type: 1,
@ -114,40 +114,43 @@ const triggers = [
},
filter,
}, {});
const { id: shipId, type, deposit$ship: deposits, shipOrder$ship, shipServiceId, entity, entityId, wechatMpShip } = ship || {};
if (deposits && deposits.length > 0) {
//充值 (此时该充值必定为受发货限制的小程序上的充值)
await (0, ship_1.uploadShippingInfo)(shipId, context);
return 1;
}
if (shipOrder$ship && shipOrder$ship.length > 0) {
//订单
const wpPayIds = ship.shipOrder$ship?.map((ele) => ele.order).map((order) => order.pay$order).flat().filter((pay) => pay?.entity === 'wpProduct').map((ele) => ele?.id);
let needUpload = false;
if (wpPayIds && wpPayIds.length > 0) {
const cnt = await context.count('pay', {
filter: {
id: {
$in: wpPayIds,
},
iState: {
$ne: 'closed',
},
wpProduct: {
needReceiving: true,
let cnt = 0;
for (const ship of ships) {
const { id: shipId, type, deposit$ship: deposits, shipOrder$ship, shipServiceId, entity, entityId, wechatMpShip } = ship || {};
if (deposits && deposits.length > 0) {
//充值 (此时该充值必定为受发货限制的小程序上的充值)
await (0, ship_1.uploadShippingInfo)(shipId, context);
cnt++;
}
else if (shipOrder$ship && shipOrder$ship.length > 0) {
//订单
const wpPayIds = ship.shipOrder$ship?.map((ele) => ele.order).map((order) => order.pay$order).flat().filter((pay) => pay?.entity === 'wpProduct').map((ele) => ele?.id);
let needUpload = false;
if (wpPayIds && wpPayIds.length > 0) {
const cnt = await context.count('pay', {
filter: {
id: {
$in: wpPayIds,
},
iState: {
$ne: 'closed',
},
wpProduct: {
needReceiving: true,
}
}
}, {});
if (cnt > 0) {
needUpload = true;
}
}, {});
if (cnt > 0) {
needUpload = true;
}
if (needUpload) {
await (0, ship_1.uploadShippingInfo)(shipId, context);
cnt++;
}
}
if (needUpload) {
await (0, ship_1.uploadShippingInfo)(shipId, context);
return 1;
}
}
return 0;
return cnt;
}
},
{
@ -297,51 +300,52 @@ const triggers = [
when: 'commit',
asRoot: true,
fn: async ({ ids }, context, option) => {
(0, assert_1.default)(ids.length === 1);
const id = ids[0];
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
receiveAt: 1,
shipOrder$ship: {
$entity: 'shipOrder',
data: {
id: 1,
orderId: 1,
order: {
// assert(ids.length === 1);
for (const id of ids) {
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
receiveAt: 1,
shipOrder$ship: {
$entity: 'shipOrder',
data: {
id: 1,
pay$order: {
$entity: 'pay',
data: {
id: 1,
},
filter: {
entity: 'wpProduct',
wpProduct: {
needReceiving: true
orderId: 1,
order: {
id: 1,
pay$order: {
$entity: 'pay',
data: {
id: 1,
},
filter: {
entity: 'wpProduct',
wpProduct: {
needReceiving: true
}
}
}
}
}
}
},
},
},
filter: {
id
}
}, { dontCollect: true, forUpdate: true });
const { type, shipOrder$ship } = ship;
const wpPay = shipOrder$ship?.map((shipOrder) => shipOrder?.order?.pay$order).flat();
if (type === 'virtual' || (type === 'pickup' && wpPay && wpPay.length > 0)) {
await context.operate('ship', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'startReceiving',
data: {},
filter: {
id,
id
}
}, option);
}, { dontCollect: true, forUpdate: true });
const { type, shipOrder$ship } = ship;
const wpPay = shipOrder$ship?.map((shipOrder) => shipOrder?.order?.pay$order).flat();
if (type === 'virtual' || (type === 'pickup' && wpPay && wpPay.length > 0)) {
await context.operate('ship', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'startReceiving',
data: {},
filter: {
id,
}
}, option);
}
}
},
},
@ -352,35 +356,36 @@ const triggers = [
when: 'commit',
asRoot: true,
fn: async ({ ids }, context, option) => {
(0, assert_1.default)(ids.length === 1);
const id = ids[0];
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
deposit$ship: {
$entity: 'deposit',
data: {
id: 1,
iState: 1,
// assert(ids.length === 1);
for (const id of ids) {
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
deposit$ship: {
$entity: 'deposit',
data: {
id: 1,
iState: 1,
}
}
}
},
filter: {
id
}
}, { dontCollect: true, forUpdate: true });
const { type, deposit$ship: deposits } = ship;
if (type === 'virtual' && deposits && deposits.length > 0) {
const [deposit] = deposits;
await context.operate('deposit', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'succeed',
data: {},
},
filter: {
id: deposit.id,
id
}
}, option);
}, { dontCollect: true, forUpdate: true });
const { type, deposit$ship: deposits } = ship;
if (type === 'virtual' && deposits && deposits.length > 0) {
const [deposit] = deposits;
await context.operate('deposit', {
id: await (0, uuid_1.generateNewIdAsync)(),
action: 'succeed',
data: {},
filter: {
id: deposit.id,
}
}, option);
}
}
},
},

View File

@ -1,12 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.notifyConfirmReceive = exports.refreshShipState = exports.refreshMpOrderShipState = exports.getOrderShipState = exports.uploadShippingInfo = exports.maskPhone = exports.shipProjection = void 0;
const tslib_1 = require("tslib");
const oak_external_sdk_1 = require("oak-external-sdk");
const assert_1 = require("oak-domain/lib/utils/assert");
const uuid_1 = require("oak-domain/lib/utils/uuid");
const Exception_1 = require("../types/Exception");
const dayjs_1 = tslib_1.__importDefault(require("dayjs"));
const validator_1 = require("oak-domain/lib/utils/validator");
const shipClazz_1 = require("./shipClazz");
exports.shipProjection = {
@ -150,7 +148,10 @@ async function uploadShippingInfo(shipId, context) {
// assert(iState === 'unshipped'); //可更改一次发货信息
//发货信息录入前检查小程序订单发货状态
const shipState = await getOrderShipState(context, shipId);
const now = (0, dayjs_1.default)().format();
const date = new Date();
const isoString = date.toISOString().replace('Z', ''); // 移除UTC的'Z'
// 手动添加时区偏移(例如 +08:00
const finalFormat = `${isoString}+08:00`;
// const application = context.getApplication();
// const { type, config } = application!;
// assert(type === 'wechatMp');
@ -172,14 +173,14 @@ async function uploadShippingInfo(shipId, context) {
order_number_type: 2,
transaction_id: meta?.transaction_id,
},
logistic_type: 3,
logistics_type: 3,
delivery_mode: 1,
shipping_list: [
{
item_desc: '账户充值',
}
],
upload_time: now,
upload_time: finalFormat,
payer: {
openid: meta?.payer?.openid,
},
@ -229,10 +230,10 @@ async function uploadShippingInfo(shipId, context) {
order_number_type: 2,
transaction_id: meta?.transaction_id,
},
logistic_type: shipType === 'express' ? 1 : 4,
logistics_type: shipType === 'express' ? 1 : 4,
delivery_mode: 1,
shipping_list: shippingList,
upload_time: now,
upload_time: finalFormat,
payer: {
openid: meta?.payer?.openid,
},
@ -268,7 +269,7 @@ async function getOrderShipState(context, shipId) {
forUpdate: true
});
(0, assert_1.assert)(ship);
const { deposit$ship: deposits, shipOrder$ship } = ship;
const { deposit$ship: deposits, shipOrder$ship, type } = ship;
let info = undefined, wechatInstance = undefined;
if (deposits && deposits.length > 0) {
//充值
@ -309,10 +310,20 @@ async function getOrderShipState(context, shipId) {
state = 'unshipped';
break;
case 2: //已发货
state = 'shipping';
if (['pickup', 'virtual'].includes(type)) {
state = 'receiving';
}
else {
state = 'shipping';
}
// action = 'ship';
break;
case 3: //确认收货
if (type === 'express') {
state = 'receiving';
}
break;
case 4: //交易完成
state = 'received';
// action = 'receive';
break;
@ -342,25 +353,30 @@ async function refreshMpOrderShipState(shipId, context) {
forUpdate: true
});
const mpState = await getOrderShipState(context, shipId);
let action = undefined;
switch (mpState) {
case 'shipping': //已发货
action = 'ship';
break;
case 'received': //已收货
action = 'succeedReceiving';
break;
case 'unknow': //不明
action = 'unknow';
break;
default:
action = undefined;
}
if (action && ship.iState !== mpState) {
// let action = undefined;
// switch (mpState) {
// case 'shipping': //已发货
// action = 'ship';
// break;
// case 'receiving': //已收货
// action = 'startReceiving';
// break;
// case 'received': //已确认
// action = 'succeedReceiving';
// break;
// case 'unknow': //不明
// action = 'unknow';
// break;
// default:
// action = undefined;
// }
if (ship.iState !== mpState) {
return await context.operate('ship', {
id: await (0, uuid_1.generateNewIdAsync)(),
action,
data: {},
action: 'update',
data: {
iState: mpState,
},
filter: {
id: ship.id,
}

View File

@ -3,6 +3,8 @@ import { generateNewIdAsync } from "oak-domain/lib/utils/uuid";
import assert from 'assert';
import { DATA_SUBSCRIBER_KEYS } from "../../../config/constants";
import { PayChannel } from "@project/types/Pay";
import { OpRecord } from "oak-domain/lib/types";
import { ED } from "oak-frontend-base";
export default OakComponent({
entity: 'account',
@ -225,9 +227,9 @@ export default OakComponent({
gotoHistoryMp() {
this.props.onGoToHistory!();
},
async onUnreceivedDepositClickMp() {
async onUnreceivedDepositClickMp(noMessage?: boolean) {
const { unreceivedDepositId } = this.state;
const { data: deposits } = await this.features.cache.refresh('deposit', {
const { data: [deposit] } = await this.features.cache.refresh('deposit', {
data: {
id: 1,
iState: 1,
@ -255,10 +257,10 @@ export default OakComponent({
id: unreceivedDepositId,
}
});
const ship = deposits?.[0]?.ship;
const ship = deposit?.ship;
if (ship && ship.id) {
if (ship.iState === 'receiving') {
const transactionId = (ship.deposit$ship?.[0]?.pay$deposit?.[0]?.meta as { transaction_id: string })?.transaction_id;
const transactionId = (deposit?.pay$deposit?.[0]?.meta as { transaction_id: string })?.transaction_id;
console.log('transaction_id', transactionId);
if (process.env.NODE_ENV === 'development') {
await this.features.cache.operate('ship',
@ -284,9 +286,9 @@ export default OakComponent({
extraData: {
transaction_id: transactionId,
},
async success() {
success: async () => {
console.log('success');
const mpShipState = await this.features.cache.exec('getMpShipState', {
const { result: mpShipState } = await this.features.cache.exec('getMpShipState', {
shipId: ship.id,
})
if (mpShipState === 'received') {
@ -330,16 +332,20 @@ export default OakComponent({
})
}
} else {
this.setMessage({
type: 'warning',
content: this.t('no transactionId'),
})
if (!noMessage) {
this.setMessage({
type: 'warning',
content: this.t('no transactionId'),
})
}
}
} else {
this.setMessage({
content: this.t('ship.wait'),
type: 'warning',
})
if (!noMessage) {
this.setMessage({
content: this.t('ship.wait'),
type: 'warning',
})
}
}
}
}
@ -360,7 +366,49 @@ export default OakComponent({
async ready() {
const { oakId } = this.props;
assert(typeof oakId === 'string');
const unsub = await this.subDataEvents([`${DATA_SUBSCRIBER_KEYS.accountNumberChanged}-${oakId}`]);
const unsub = await this.subDataEvents([`${DATA_SUBSCRIBER_KEYS.accountNumberChanged}-${oakId}`, `${DATA_SUBSCRIBER_KEYS.depositStateChanged}-${oakId}`],
async (event: string, opRecords: OpRecord<ED>[]) => {
for (const record of opRecords) {
if (record.a === 'succeed') {
const { e, d } = record;
if (e === 'deposit') {
await this.features.cache.refresh('deposit', {
data: {
id: 1,
accountId: 1,
iState: 1,
pay$deposit: {
$entity: 'pay',
data: {
id: 1,
meta: 1,
iState: 1,
entity: 1,
entityId: 1,
},
filter: {
entity: 'wpProduct',
iState: 'paid',
}
},
shipId: 1,
ship: {
id: 1,
iState: 1,
}
},
filter: {
accountId: oakId,
iState: {
$in: ['depositing', 'shipped'],
},
}
})
}
}
}
}
);
this.setState({
unsub,
})
@ -368,6 +416,12 @@ export default OakComponent({
detached() {
const { unsub } = this.state;
unsub && unsub();
}
},
async mature() {
const { unreceivedDepositId } = this.state;
if (!!unreceivedDepositId && process.env.OAK_PLATFORM === 'wechatMp') {
await this.onUnreceivedDepositClickMp(true);
}
},
}
})

View File

@ -1,5 +1,5 @@
<view class="container">
<l-notice-bar show="{{unreceivedDepositId}}" front-icon-name="notification" end-icon-name="right"
<l-notice-bar show="{{!!unreceivedDepositId}}" front-icon-name="notification" end-icon-name="right"
bind:lintap="onUnreceivedDepositClickMp" bind:linicontap="onUnreceivedDepositClickMp">
{{t('ship.unconfirm')}}
</l-notice-bar>

View File

@ -78,7 +78,7 @@ function PayConfig(props: {
<InputNumber
value={depositLoss?.ratio}
max={20}
min={0.01}
min={0}
addonAfter={"%"}
step={0.01}
precision={2}

View File

@ -3,4 +3,5 @@ export const DATA_SUBSCRIBER_KEYS = {
orderStateChanged: 'oak-pay-business-osc',
accountNumberChanged: 'oak-pay-business-anc',
shipStateChanged: 'oak-pay-business-ssc',
depositStateChanged: 'oak-pay-business-dsc',
};

View File

@ -75,6 +75,22 @@ const timers: Array<Timer<EntityDict, 'ship', BRC>> = [
);
},
},
{
name: '对虚拟或自提类型的ship自动发货',
cron: '0 * * * * ?',
entity: 'ship',
filter: {
type: {
$in: ['virtual', 'pickup'],
},
iState: 'unshipped',
},
projection: {
id: 1,
},
action: 'ship',
actionData: {},
},
];
export default timers;

View File

@ -4,6 +4,7 @@ import { EntityDict } from '../oak-app-domain';
import { BRC } from '../types/RuntimeCxt';
import assert from 'assert';
import { getPayClazz } from '../utils/payClazz';
import { DATA_SUBSCRIBER_KEYS } from '@project/config/constants';
const triggers: Trigger<EntityDict, 'deposit', BRC>[] = [
/* {
@ -157,7 +158,33 @@ const triggers: Trigger<EntityDict, 'deposit', BRC>[] = [
}
return cnt;
}
}
},
{
entity: 'deposit',
name: '当deposit状态发生变化时尝试向关联的account订阅者推送',
action: ['succeed', 'fail', 'ship'],
when: 'after',
fn: async ({ operation }, context, option) => {
const { filter, id } = operation as EntityDict['deposit']['Update'];
const { id: depositId } = filter as { id: string };
const [deposit] = await context.select('deposit', {
data: {
id: 1,
accountId: 1,
},
filter: {
id: depositId,
}
}, {
forUpdate: true,
});
const { accountId } = deposit;
if (accountId) {
context.saveOperationToEvent(id, `${DATA_SUBSCRIBER_KEYS.depositStateChanged}-${accountId}`);
}
return 1;
}
} as UpdateTriggerInTxn<EntityDict, 'deposit', BRC>,
];
export default triggers;

View File

@ -76,7 +76,7 @@ const triggers: Trigger<EntityDict, 'ship', BRC>[] = [
priority: 99,
fn: async ({ operation }, context) => {
const { data, filter } = operation;
const [ship] = await context.select('ship', {
const ships = await context.select('ship', {
data: {
id: 1,
type: 1,
@ -120,40 +120,42 @@ const triggers: Trigger<EntityDict, 'ship', BRC>[] = [
},
filter,
}, {});
const { id: shipId, type, deposit$ship: deposits, shipOrder$ship, shipServiceId, entity, entityId, wechatMpShip } = ship || {};
if (deposits && deposits.length > 0) {
//充值 (此时该充值必定为受发货限制的小程序上的充值)
await uploadShippingInfo(shipId!, context);
return 1;
}
if (shipOrder$ship && shipOrder$ship.length > 0) {
//订单
const wpPayIds = ship.shipOrder$ship?.map((ele) => ele.order).map((order) => order.pay$order).flat().filter((pay) => pay?.entity === 'wpProduct').map((ele) => ele?.id!);
let needUpload = false;
if (wpPayIds && wpPayIds.length > 0) {
const cnt = await context.count('pay', {
filter: {
id: {
$in: wpPayIds,
},
iState: {
$ne: 'closed',
},
wpProduct: {
needReceiving: true,
let cnt = 0;
for (const ship of ships) {
const { id: shipId, type, deposit$ship: deposits, shipOrder$ship, shipServiceId, entity, entityId, wechatMpShip } = ship || {};
if (deposits && deposits.length > 0) {
//充值 (此时该充值必定为受发货限制的小程序上的充值)
await uploadShippingInfo(shipId!, context);
cnt++;
} else if (shipOrder$ship && shipOrder$ship.length > 0) {
//订单
const wpPayIds = ship.shipOrder$ship?.map((ele) => ele.order).map((order) => order.pay$order).flat().filter((pay) => pay?.entity === 'wpProduct').map((ele) => ele?.id!);
let needUpload = false;
if (wpPayIds && wpPayIds.length > 0) {
const cnt = await context.count('pay', {
filter: {
id: {
$in: wpPayIds,
},
iState: {
$ne: 'closed',
},
wpProduct: {
needReceiving: true,
}
}
}, {});
if (cnt > 0) {
needUpload = true;
}
}, {});
if (cnt > 0) {
needUpload = true;
}
if (needUpload) {
await uploadShippingInfo(shipId!, context);
cnt++;
}
}
if (needUpload) {
await uploadShippingInfo(shipId!, context);
return 1;
}
}
return 0;
return cnt;
}
},
{
@ -307,53 +309,54 @@ const triggers: Trigger<EntityDict, 'ship', BRC>[] = [
when: 'commit',
asRoot: true,
fn: async ({ ids }, context, option) => {
assert(ids.length === 1);
const id = ids[0];
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
receiveAt: 1,
shipOrder$ship: {
$entity: 'shipOrder',
data: {
id: 1,
orderId: 1,
order: {
// assert(ids.length === 1);
for (const id of ids) {
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
receiveAt: 1,
shipOrder$ship: {
$entity: 'shipOrder',
data: {
id: 1,
pay$order: {
$entity: 'pay',
data: {
id: 1,
},
filter: {
entity: 'wpProduct',
wpProduct: {
needReceiving: true
orderId: 1,
order: {
id: 1,
pay$order: {
$entity: 'pay',
data: {
id: 1,
},
filter: {
entity: 'wpProduct',
wpProduct: {
needReceiving: true
}
}
}
}
}
}
},
},
filter: {
id
}
}, { dontCollect: true, forUpdate: true });
const { type, shipOrder$ship } = ship;
const wpPay = shipOrder$ship?.map((shipOrder) => shipOrder?.order?.pay$order).flat();
if (type === 'virtual' || (type === 'pickup' && wpPay && wpPay.length > 0)) {
await context.operate('ship', {
id: await generateNewIdAsync(),
action: 'startReceiving',
data: {
}
},
},
filter: {
id,
id
}
}, option);
}, { dontCollect: true, forUpdate: true });
const { type, shipOrder$ship } = ship;
const wpPay = shipOrder$ship?.map((shipOrder) => shipOrder?.order?.pay$order).flat();
if (type === 'virtual' || (type === 'pickup' && wpPay && wpPay.length > 0)) {
await context.operate('ship', {
id: await generateNewIdAsync(),
action: 'startReceiving',
data: {
},
filter: {
id,
}
}, option);
}
}
},
} as UpdateTriggerCrossTxn<EntityDict, 'ship', BRC>,
@ -364,36 +367,37 @@ const triggers: Trigger<EntityDict, 'ship', BRC>[] = [
when: 'commit',
asRoot: true,
fn: async ({ ids }, context, option) => {
assert(ids.length === 1);
const id = ids[0];
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
deposit$ship: {
$entity: 'deposit',
data: {
id: 1,
iState: 1,
}
}
},
filter: {
id
}
}, { dontCollect: true, forUpdate: true });
const { type, deposit$ship: deposits } = ship;
if (type === 'virtual' && deposits && deposits.length > 0) {
const [deposit] = deposits;
await context.operate('deposit', {
id: await generateNewIdAsync(),
action: 'succeed',
// assert(ids.length === 1);
for (const id of ids) {
const [ship] = await context.select('ship', {
data: {
id: 1,
type: 1,
deposit$ship: {
$entity: 'deposit',
data: {
id: 1,
iState: 1,
}
}
},
filter: {
id: deposit.id,
id
}
}, option);
}, { dontCollect: true, forUpdate: true });
const { type, deposit$ship: deposits } = ship;
if (type === 'virtual' && deposits && deposits.length > 0) {
const [deposit] = deposits;
await context.operate('deposit', {
id: await generateNewIdAsync(),
action: 'succeed',
data: {
},
filter: {
id: deposit.id,
}
}, option);
}
}
},
} as UpdateTriggerCrossTxn<EntityDict, 'ship', BRC>,

View File

@ -155,7 +155,11 @@ export async function uploadShippingInfo(
//发货信息录入前检查小程序订单发货状态
const shipState = await getOrderShipState(context, shipId);
const now = dayjs().format();
const date = new Date();
const isoString = date.toISOString().replace('Z', ''); // 移除UTC的'Z'
// 手动添加时区偏移(例如 +08:00
const finalFormat = `${isoString}+08:00`;
// const application = context.getApplication();
// const { type, config } = application!;
@ -184,14 +188,14 @@ export async function uploadShippingInfo(
order_number_type: 2,
transaction_id: meta?.transaction_id,
},
logistic_type: 3,
logistics_type: 3,
delivery_mode: 1,
shipping_list: [
{
item_desc: '账户充值',
}
],
upload_time: now,
upload_time: finalFormat,
payer: {
openid: meta?.payer?.openid,
},
@ -248,10 +252,10 @@ export async function uploadShippingInfo(
order_number_type: 2,
transaction_id: meta?.transaction_id,
},
logistic_type: shipType === 'express' ? 1 : 4,
logistics_type: shipType === 'express' ? 1 : 4,
delivery_mode: 1,
shipping_list: shippingList,
upload_time: now,
upload_time: finalFormat,
payer: {
openid: meta?.payer?.openid,
},
@ -296,7 +300,7 @@ export async function getOrderShipState(
});
assert(ship);
const { deposit$ship: deposits, shipOrder$ship } = ship;
const { deposit$ship: deposits, shipOrder$ship, type } = ship;
let info = undefined, wechatInstance = undefined;
if (deposits && deposits.length > 0) {
@ -345,10 +349,19 @@ export async function getOrderShipState(
state = 'unshipped';
break;
case 2: //已发货
state = 'shipping';
if (['pickup', 'virtual'].includes(type!)) {
state = 'receiving';
} else {
state = 'shipping';
}
// action = 'ship';
break;
case 3: //确认收货
case 3://确认收货
if (type === 'express') {
state = 'receiving';
}
break;
case 4: //交易完成
state = 'received';
// action = 'receive';
break;
@ -381,25 +394,30 @@ export async function refreshMpOrderShipState(
forUpdate: true
});
const mpState = await getOrderShipState(context, shipId);
let action = undefined;
switch (mpState) {
case 'shipping': //已发货
action = 'ship';
break;
case 'received': //已收货
action = 'succeedReceiving';
break;
case 'unknow': //不明
action = 'unknow';
break;
default:
action = undefined;
}
if (action && ship.iState !== mpState) {
// let action = undefined;
// switch (mpState) {
// case 'shipping': //已发货
// action = 'ship';
// break;
// case 'receiving': //已收货
// action = 'startReceiving';
// break;
// case 'received': //已确认
// action = 'succeedReceiving';
// break;
// case 'unknow': //不明
// action = 'unknow';
// break;
// default:
// action = undefined;
// }
if (ship.iState !== mpState) {
return await context.operate('ship', {
id: await generateNewIdAsync(),
action,
data: {},
action: 'update',
data: {
iState: mpState,
},
filter: {
id: ship.id,
}