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

329 lines
12 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 { getShipState, uploadShippingInfo } from '../utils/ship';
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) {
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,
};
}
}
},
{
// tododeposit的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 [ship] = 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,
}
},
wechatMpShip: {
id: 1,
applicationId: 1,
}
},
filter,
}, {});
const { id: shipId, type, deposit$ship: deposits, shipOrder$ship, shipServiceId, entity, entityId, wechatMpShip } = ship || {};
if (deposits && deposits.length > 0) {
//充值 (此时该充值必定为受发货限制的小程序上的充值)
//发货前先查询,检查是否为未同步微信端发货状态
const shipState = await getShipState(context, shipId);
if (shipState === 'unshipped') {
await uploadShippingInfo(shipId, context);
return 1;
}
}
if (shipOrder$ship && shipOrder$ship.length > 0) {
//订单
const clazz = await getShipClazz(entity, entityId, context);
const { openId } = await clazz.getReceiverInfo(shipOrder$ship.map((ele) => ele.orderId), wechatMpShip?.applicationId, context);
if (openId) {
//当存在openId时调用小程序发货信息录入
const shipState = await getShipState(context, shipId);
//当已发货的订单再次调用小程序发货信息录入接口视为重新发货(仅可重新发货一次)
if (shipState && ['unshipped', 'shipping'].includes(shipState)) {
// 发货/更换发货
await uploadShippingInfo(shipId, context);
return 1;
}
}
}
return 0;
}
},
{
entity: 'ship',
name: '当ship状态发生变化时尝试向订阅者推送',
action: ['ship', 'receive', 'giveUp', 'reject'],
when: 'after',
fn: async ({ operation }, context, option) => {
const { filter, id } = operation;
const { id: shipId } = filter;
if (shipId) {
context.saveOperationToEvent(id, `${DATA_SUBSCRIBER_KEYS.shipStateChanged}-${shipId}`);
}
return 1;
}
},
{
name: '当物流创建时将对应的receivingMethod为express的order变为packaged状态',
entity: 'ship',
action: 'create',
when: 'after',
fn: async ({ operation }, context, option) => {
const { data } = operation;
const orders = await context.select('order', {
data: {
id: 1,
gState: 1,
},
filter: {
receivingMethod: 'express',
shipOrder$order: {
shipId: data.id,
}
}
}, { dontCollect: true });
orders.forEach(ele => assert(ele.gState === 'unshipped'));
await context.operate('order', {
id: await generateNewIdAsync(),
action: 'package',
data: {},
filter: {
id: {
$in: orders.map(ele => ele.id),
},
},
}, option);
return orders.length;
}
},
{
name: '当物流创建时,赋上对应的物流系统对象',
entity: 'ship',
action: 'create',
when: 'before',
priority: 75,
fn: async ({ operation }, context) => {
const { data } = operation;
let count = 0;
if (data instanceof Array) {
for (const d of data) {
const { shipServiceId, shipOrder$ship } = d;
assert(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;
assert(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: '当物流发货时将对应的order状态变为已发货/提货中',
entity: 'ship',
action: 'ship',
when: 'after',
fn: async ({ operation }, context, option) => {
const { filter } = operation;
assert(typeof filter.id === 'string');
const orders = await context.select('order', {
data: {
id: 1,
gState: 1,
},
filter: {
shipOrder$order: {
shipId: filter.id,
}
}
}, { dontCollect: true });
const packaged = orders.filter(ele => ele.gState === 'packaged');
if (packaged.length > 0) {
await context.operate('order', {
id: await generateNewIdAsync(),
action: 'send',
data: {},
filter: {
id: {
$in: packaged.map(ele => ele.id),
},
},
}, option);
}
const staged = orders.filter(ele => ele.gState === 'staging');
if (staged.length > 0) {
await context.operate('order', {
id: await generateNewIdAsync(),
action: 'startTaking',
data: {},
filter: {
id: {
$in: staged.map(ele => ele.id),
},
},
}, option);
}
assert(staged.length + packaged.length === orders.length);
return orders.length;
}
},
{
name: '当物流取消时将对应的order状态改回packaged/staging',
entity: 'ship',
action: 'cancel',
when: 'after',
fn: async ({ operation }, context, option) => {
const { filter } = operation;
assert(typeof filter.id === 'string');
const orders = await context.select('order', {
data: {
id: 1,
gState: 1,
receivingMethod: 1,
},
filter: {
shipOrder$order: {
shipId: filter.id,
}
}
}, { dontCollect: true });
await context.operate('order', {
id: await generateNewIdAsync(),
action: 'unship',
data: {},
filter: {
id: {
$in: orders.map(ele => ele.id),
},
},
}, option);
return orders.length;
}
},
{
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(extraShipId, context);
}
}
},
];
export default triggers;