oak-pay-business/es/triggers/ship.js

470 lines
17 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
import { DATA_SUBSCRIBER_KEYS } from '../config/constants';
import assert from 'assert';
import { getShipClazz, getShipEntity } from '../utils/shipClazz';
import { notifyConfirmReceive, uploadShippingInfo } from '../utils/ship';
import { promisify } from 'util';
const triggers = [
{
name: '当虚拟或自提类型的ship创建后自动发货',
entity: 'ship',
action: 'create',
when: 'commit',
strict: 'makeSure',
asRoot: true,
check: (operation) => ['virtual', 'pickup'].includes(operation.data.type),
fn: async ({ ids }, context, option) => {
for (const id of ids) {
const [ship] = await context.select('ship', {
data: {
id: 1,
iState: 1,
type: 1,
},
filter: {
id
}
}, { dontCollect: true, forUpdate: true });
const { iState, type } = ship;
if (iState && ['unshipped', 'unknown'].includes(iState) && type && ['virtual', 'pickup'].includes(type)) {
await context.operate('ship', {
id: await generateNewIdAsync(),
action: 'ship',
data: {},
filter: {
id,
}
}, option);
}
}
return;
},
},
{
name: '当物流类的ship创建后自动下单',
entity: 'ship',
action: 'create',
when: 'commit',
strict: 'makeSure',
asRoot: true,
check: (operation) => ['express'].includes(operation.data.type),
fn: async ({ ids }, context, option) => {
assert(ids.length === 1);
const id = ids[0];
const [ship] = await context.select('ship', {
data: {
id: 1,
entity: 1,
entityId: 1,
shipServiceId: 1,
},
filter: {
id
}
}, { dontCollect: true, forUpdate: true });
const { entity, entityId } = ship || {};
if (entity && entityId) {
const shipClazz = await getShipClazz(entity, entityId, context);
const extraShipId = await shipClazz.eOrder(id, context);
return {
extraShipId,
};
}
}
},
{
// deposit的ship和 shipClazz中有配置wechatShip且可获取openId的order的ship
entity: 'ship',
name: '当虚拟的ship变为shipping状态时调用小程序发货信息录入接口',
action: 'ship',
when: 'before',
asRoot: true,
priority: 99,
fn: async ({ operation }, context) => {
const { data, filter } = operation;
const ships = await context.select('ship', {
data: {
id: 1,
type: 1,
deposit$ship: {
$entity: 'deposit',
data: {
id: 1,
},
},
entity: 1,
entityId: 1,
shipServiceId: 1,
shipOrder$ship: {
$entity: 'shipOrder',
data: {
id: 1,
orderId: 1,
order: {
id: 1,
pay$order: {
$entity: 'pay',
data: {
id: 1,
meta: 1,
iState: 1,
entity: 1,
entityId: 1,
},
filter: {
iState: 'paid'
}
}
}
}
},
wechatMpShip: {
id: 1,
applicationId: 1,
}
},
filter,
}, {});
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) {
//充值 (此时该充值必定为受发货限制的小程序上的充值)
//等待5秒以避免小程序订单号查询不到
const sleep = promisify(setTimeout);
await sleep(5 * 1000);
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 (needUpload) {
await uploadShippingInfo(shipId, context);
cnt++;
}
}
}
return cnt;
}
},
{
entity: 'ship',
name: '当ship状态发生变化时尝试向订阅者推送',
action: ['ship', 'receive', 'cancel', 'reject', 'unknow', 'startReceiving', 'succeedReceiving'],
when: 'after',
fn: async ({ operation }, context, option) => {
const { filter, id } = operation;
const { id: shipId } = filter;
const [ship] = await context.select('ship', {
data: {
id: 1,
deposit$ship: {
$entity: 'deposit',
data: {
id: 1,
}
},
shipOrder$ship: {
$entity: 'shipOrder',
data: {
id: 1,
orderId: 1,
}
}
},
filter,
}, {});
const { deposit$ship: deposits, shipOrder$ship: shipOrders } = ship || {};
const depositIds = deposits?.map((ele) => ele.id);
const orderIds = shipOrders?.map((ele) => ele.orderId);
if (shipId) {
context.saveOperationToEvent(id, `${DATA_SUBSCRIBER_KEYS.shipStateChanged}-${shipId}`);
}
const selectionId = await generateNewIdAsync();
await context.select('ship', {
id: selectionId,
data: {
id: 1,
iState: 1,
deposit$ship: {
$entity: 'deposit',
data: {
id: 1,
iState: 1,
}
},
shipOrder$ship: {
$entity: 'shipOrder',
data: {
id: 1,
orderId: 1,
order: {
id: 1,
iState: 1,
}
}
}
},
filter: {
id: shipId,
}
}, {});
if (depositIds && depositIds.length > 0) {
depositIds.forEach((depositId) => {
context.saveOperationToEvent(selectionId, `${DATA_SUBSCRIBER_KEYS.shipStateChanged}-${depositId}`);
});
}
if (orderIds && orderIds.length > 0) {
orderIds.forEach((orderId) => {
context.saveOperationToEvent(selectionId, `${DATA_SUBSCRIBER_KEYS.shipStateChanged}-${orderId}`);
});
}
return 1;
}
},
{
name: '当物流创建时,赋上对应的物流系统对象',
entity: 'ship',
action: 'create',
when: 'before',
priority: 75,
check: (operation) => operation.data.shipOrder$ship && operation.data.shipOrder$ship.length > 0,
fn: async ({ operation }, context) => {
const { data } = operation;
let count = 0;
if (data instanceof Array) {
for (const d of data) {
const { shipServiceId, shipOrder$ship } = d;
if (shipServiceId) {
const result = await getShipEntity(shipServiceId, shipOrder$ship.map(ele => ele.data.orderId), context);
if (result) {
d.entity = result[0];
d.entityId = result[1];
count++;
}
}
}
}
else {
const { shipServiceId, shipOrder$ship } = data;
if (shipServiceId) {
const result = await getShipEntity(shipServiceId, shipOrder$ship.map(ele => ele.data.orderId), context);
if (result) {
data.entity = result[0];
data.entityId = result[1];
count++;
}
}
}
return count;
}
},
{
name: '当物流类的ship取消后调用外部接口取消下单',
entity: 'ship',
action: 'cancel',
when: 'commit',
strict: 'makeSure',
asRoot: true,
filter: {
type: 'express',
entity: {
$exists: true,
},
extraShipId: {
$exists: true,
},
},
fn: async ({ ids }, context, option) => {
assert(ids.length === 1);
const id = ids[0];
const [ship] = await context.select('ship', {
data: {
id: 1,
entity: 1,
entityId: 1,
shipServiceId: 1,
extraShipId: 1,
},
filter: {
id
}
}, { dontCollect: true, forUpdate: true });
const { entity, entityId, extraShipId } = ship;
if (entity && entityId && extraShipId) {
const shipClazz = await getShipClazz(entity, entityId, context);
await shipClazz.cancelOrder(id, context);
}
}
},
{
name: '当物流类的ship签收后调用小程序确认收货提醒',
entity: 'ship',
action: 'startReceiving',
when: 'commit',
asRoot: true,
filter: {
type: 'express',
receiveAt: {
$exists: true,
}
},
fn: async ({ ids }, context, option) => {
assert(ids.length === 1);
const id = ids[0];
const [ship] = await context.select('ship', {
data: {
id: 1,
entity: 1,
entityId: 1,
shipServiceId: 1,
extraShipId: 1,
receiveAt: 1,
shipOrder$ship: {
$entity: 'shipOrder',
data: {
id: 1,
orderId: 1,
}
},
wechatMpShip: {
id: 1,
applicationId: 1,
}
},
filter: {
id
}
}, { dontCollect: true, forUpdate: true });
const { entity, entityId, extraShipId, shipOrder$ship, wechatMpShip } = ship;
if (entity && entityId && extraShipId && shipOrder$ship) {
const shipClazz = await getShipClazz(entity, entityId, context);
const { openId } = await shipClazz.getReceiverInfo(shipOrder$ship.map((ele) => ele.orderId), wechatMpShip?.applicationId, context);
if (openId) {
//当存在openId时调用小程序发货信息录入
await notifyConfirmReceive(id, context);
return 1;
}
}
}
},
{
name: '当虚拟或受发货限制的自提ship发货后自动开始确认收货流程',
entity: 'ship',
action: 'ship',
when: 'commit',
asRoot: true,
fn: async ({ ids }, context, option) => {
// 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,
orderId: 1,
order: {
id: 1,
pay$order: {
$entity: 'pay',
data: {
id: 1,
},
filter: {
entity: 'wpProduct',
wpProduct: {
needReceiving: true
}
}
}
}
}
},
},
filter: {
id
}
}, { 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);
}
}
},
},
{
name: '当虚拟ship确认收货后更新deposit状态',
entity: 'ship',
action: 'succeedReceiving',
when: 'after',
asRoot: true,
fn: async ({ operation }, context, option) => {
const { filter, id, data } = operation;
const ships = await context.select('ship', {
data: {
id: 1,
type: 1,
deposit$ship: {
$entity: 'deposit',
data: {
id: 1,
iState: 1,
}
}
},
filter,
}, { forUpdate: true });
let count = 0;
for (const ship of ships) {
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);
count++;
}
}
return count;
},
},
];
export default triggers;