ship实体添加receiveAt

This commit is contained in:
lxy 2025-03-14 15:24:43 +08:00
parent 3c8298e08d
commit b752c97da1
34 changed files with 131 additions and 40 deletions

View File

@ -42,6 +42,18 @@ const checkers = [
}, },
iState: 'unshipped', iState: 'unshipped',
} }
},
{
entity: 'ship',
type: 'logicalData',
action: 'receive',
checker: (operation) => {
const { data } = operation;
if (!data.receiveAt) {
const now = Date.now();
data.receiveAt = now;
}
}
} }
]; ];
export default checkers; export default checkers;

View File

@ -1,4 +1,4 @@
import { String, Int } from 'oak-domain/lib/types/DataType'; import { String, Datetime, Int } from 'oak-domain/lib/types/DataType';
import { EntityShape } from 'oak-domain/lib/types/Entity'; import { EntityShape } from 'oak-domain/lib/types/Entity';
import { ActionDef, EntityDesc } from 'oak-domain/lib/types'; import { ActionDef, EntityDesc } from 'oak-domain/lib/types';
import { Schema as ShipService } from './ShipService'; import { Schema as ShipService } from './ShipService';
@ -21,6 +21,7 @@ export interface Schema extends EntityShape {
phantom5?: Object; phantom5?: Object;
extraShipId?: String<128>; extraShipId?: String<128>;
extraPaths?: Paths; extraPaths?: Paths;
receiveAt?: Datetime;
} }
type IState = 'unshipped' | 'shipping' | 'cancelled' | 'received' | 'rejected' | 'unknown'; type IState = 'unshipped' | 'shipping' | 'cancelled' | 'received' | 'rejected' | 'unknown';
type IAction = 'ship' | 'receive' | 'cancel' | 'reject' | 'unknow'; type IAction = 'ship' | 'receive' | 'cancel' | 'reject' | 'unknow';

View File

@ -46,6 +46,7 @@ export const entityDesc = {
phantom5: '结构化项', phantom5: '结构化项',
extraShipId: '外部订单Id', extraShipId: '外部订单Id',
extraPaths: '外部轨迹信息', extraPaths: '外部轨迹信息',
receiveAt: '签收时间',
}, },
v: { v: {
iState: { iState: {

View File

@ -69,6 +69,9 @@ export const desc = {
extraPaths: { extraPaths: {
type: "object" type: "object"
}, },
receiveAt: {
type: "datetime"
},
iState: { iState: {
type: "enum", type: "enum",
enumeration: ["unshipped", "shipping", "cancelled", "received", "rejected", "unknown"] enumeration: ["unshipped", "shipping", "cancelled", "received", "rejected", "unknown"]

View File

@ -2,7 +2,7 @@ import { ForeignKey, JsonProjection } from "oak-domain/lib/types/DataType";
import { Q_DateValue, Q_NumberValue, Q_StringValue, Q_EnumValue, NodeId, ExprOp, ExpressionKey, JsonFilter } from "oak-domain/lib/types/Demand"; import { Q_DateValue, Q_NumberValue, Q_StringValue, Q_EnumValue, NodeId, ExprOp, ExpressionKey, JsonFilter } from "oak-domain/lib/types/Demand";
import { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/Entity"; import { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/Entity";
import { Action, ParticularAction, IState } from "./Action"; import { Action, ParticularAction, IState } from "./Action";
import { String, Int } from "oak-domain/lib/types/DataType"; import { String, Int, Datetime } from "oak-domain/lib/types/DataType";
type Paths = Array<{ type Paths = Array<{
time: number; time: number;
action: string; action: string;
@ -21,6 +21,7 @@ export type OpSchema = EntityShape & {
phantom5?: Object | null; phantom5?: Object | null;
extraShipId?: String<128> | null; extraShipId?: String<128> | null;
extraPaths?: Paths | null; extraPaths?: Paths | null;
receiveAt?: Datetime | null;
iState?: IState | null; iState?: IState | null;
} & { } & {
[A in ExpressionKey]?: any; [A in ExpressionKey]?: any;
@ -44,6 +45,7 @@ export type OpFilter = {
phantom5: Object; phantom5: Object;
extraShipId: Q_StringValue; extraShipId: Q_StringValue;
extraPaths: JsonFilter<Paths>; extraPaths: JsonFilter<Paths>;
receiveAt: Q_DateValue;
iState: Q_EnumValue<IState>; iState: Q_EnumValue<IState>;
} & ExprOp<OpAttr | string>; } & ExprOp<OpAttr | string>;
export type OpProjection = { export type OpProjection = {
@ -66,6 +68,7 @@ export type OpProjection = {
phantom5?: number | Object; phantom5?: number | Object;
extraShipId?: number; extraShipId?: number;
extraPaths?: number | JsonProjection<Paths>; extraPaths?: number | JsonProjection<Paths>;
receiveAt?: number;
iState?: number; iState?: number;
} & Partial<ExprOp<OpAttr | string>>; } & Partial<ExprOp<OpAttr | string>>;
export type OpSortAttr = Partial<{ export type OpSortAttr = Partial<{
@ -82,6 +85,7 @@ export type OpSortAttr = Partial<{
phantom4: number; phantom4: number;
extraShipId: number; extraShipId: number;
extraPaths: number; extraPaths: number;
receiveAt: number;
iState: number; iState: number;
[k: string]: any; [k: string]: any;
} | ExprOp<OpAttr | string>>; } | ExprOp<OpAttr | string>>;

View File

@ -14,7 +14,8 @@
"phantom4": "索引项四", "phantom4": "索引项四",
"phantom5": "结构化项", "phantom5": "结构化项",
"extraShipId": "外部订单Id", "extraShipId": "外部订单Id",
"extraPaths": "外部轨迹信息" "extraPaths": "外部轨迹信息",
"receiveAt": "签收时间"
}, },
"v": { "v": {
"iState": { "iState": {

View File

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

View File

@ -9,7 +9,10 @@ export default interface ShipClazz<ED extends EntityDict & BaseEntityDict, Conte
available(shipServiceId: string, orderIds: string[], context: Context): Promise<boolean>; available(shipServiceId: string, orderIds: string[], context: Context): Promise<boolean>;
eOrder(shipId: string, context: Context): Promise<string>; eOrder(shipId: string, context: Context): Promise<string>;
cancelOrder(shipId: string, context: Context): Promise<void>; cancelOrder(shipId: string, context: Context): Promise<void>;
syncState(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['iState']>; syncState(shipId: string, context: Context): Promise<{
state: EntityDict['ship']['OpSchema']['iState'];
time?: number;
}>;
syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']>; syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']>;
getPrintInfo(shipId: string, context: Context): Promise<{ getPrintInfo(shipId: string, context: Context): Promise<{
type: 'html'; type: 'html';

View File

@ -337,14 +337,17 @@ export async function refreshtShipState(ship, context) {
} }
const { entity, entityId } = ship2; const { entity, entityId } = ship2;
const clazz = await getShipClazz(entity, entityId, context); const clazz = await getShipClazz(entity, entityId, context);
const state = await clazz.syncState(ship2.id, context); const { state, time } = await clazz.syncState(ship2.id, context);
let action = undefined; let action = undefined, updateData = {};
switch (state) { switch (state) {
case 'shipping': //已发货 case 'shipping': //已发货
action = 'ship'; action = 'ship';
break; break;
case 'received': //已收货 case 'received': //已收货
action = 'receive'; action = 'receive';
updateData = {
receiveAt: time
};
break; break;
case 'unknow': //不明 case 'unknow': //不明
action = 'unknow'; action = 'unknow';
@ -356,7 +359,7 @@ export async function refreshtShipState(ship, context) {
return await context.operate('ship', { return await context.operate('ship', {
id: await generateNewIdAsync(), id: await generateNewIdAsync(),
action, action,
data: {}, data: updateData,
filter: { filter: {
id: ship2.id, id: ship2.id,
} }

View File

@ -5,7 +5,10 @@ import DebugClazz from './WechatMpShip.debug';
export default class WechatMpShip<ED extends EntityDict & BaseEntityDict, Context extends BackendRuntimeContext<ED>> extends DebugClazz<ED, Context> { export default class WechatMpShip<ED extends EntityDict & BaseEntityDict, Context extends BackendRuntimeContext<ED>> extends DebugClazz<ED, Context> {
eOrder(shipId: string, context: Context): Promise<string>; eOrder(shipId: string, context: Context): Promise<string>;
cancelOrder(shipId: string, context: Context): Promise<void>; cancelOrder(shipId: string, context: Context): Promise<void>;
syncState(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['iState']>; syncState(shipId: string, context: Context): Promise<{
state: EntityDict['ship']['OpSchema']['iState'];
time?: number;
}>;
syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']>; syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']>;
getPrintInfo(shipId: string, context: Context): Promise<{ getPrintInfo(shipId: string, context: Context): Promise<{
type: 'html'; type: 'html';

View File

@ -40,7 +40,10 @@ export default class WechatMpShipDebug<ED extends EntityDict & BaseEntityDict, C
}>; }>;
eOrder(shipId: string, context: Context): Promise<string>; eOrder(shipId: string, context: Context): Promise<string>;
cancelOrder(shipId: string, context: Context): Promise<void>; cancelOrder(shipId: string, context: Context): Promise<void>;
syncState(shipId: string, context: Context): Promise<EntityDict["ship"]["OpSchema"]["iState"]>; syncState(shipId: string, context: Context): Promise<{
state: EntityDict['ship']['OpSchema']['iState'];
time?: number;
}>;
syncPaths(shipId: string, context: Context): Promise<EntityDict["ship"]["OpSchema"]["extraPaths"]>; syncPaths(shipId: string, context: Context): Promise<EntityDict["ship"]["OpSchema"]["extraPaths"]>;
getPrintInfo(shipId: string, context: Context): Promise<{ getPrintInfo(shipId: string, context: Context): Promise<{
type: "html"; type: "html";

View File

@ -285,13 +285,14 @@ export default class WechatMpShipDebug {
const data = await this.prepareGetPath(shipId, context); const data = await this.prepareGetPath(shipId, context);
console.log('mock syncState to wechatMpShip, data:', data); console.log('mock syncState to wechatMpShip, data:', data);
const r = Math.random(); const r = Math.random();
const now = Date.now();
if (r < 0.3) { if (r < 0.3) {
return 'shipping'; return { state: 'shipping', time: now };
} }
else if (r > 0.95) { else if (r > 0.95) {
return 'unknow'; return { state: 'unknow', time: now };
} }
return 'received'; return { state: 'received', time: now };
} }
async syncPaths(shipId, context) { async syncPaths(shipId, context) {
const data = await this.prepareGetPath(shipId, context); const data = await this.prepareGetPath(shipId, context);

View File

@ -18,6 +18,7 @@ export default class WechatMpShip extends DebugClazz {
const { path_item_num, path_item_list } = result; const { path_item_num, path_item_list } = result;
const latestPath = path_item_list[path_item_num - 1] || undefined; const latestPath = path_item_list[path_item_num - 1] || undefined;
const latestType = latestPath?.action_type; const latestType = latestPath?.action_type;
const latestTime = latestPath?.action_time;
/** /**
* action_type: * action_type:
* 100001 揽件阶段-揽件成功 * 100001 揽件阶段-揽件成功
@ -54,7 +55,7 @@ export default class WechatMpShip extends DebugClazz {
break; break;
} }
} }
return state; return { state, time: latestTime };
} }
async syncPaths(shipId, context) { async syncPaths(shipId, context) {
const instance = await this.getInstance(context); const instance = await this.getInstance(context);

View File

@ -1,6 +1,6 @@
import { mergeOperationResult } from 'oak-domain/lib/utils/operationResult'; import { mergeOperationResult } from 'oak-domain/lib/utils/operationResult';
import { shipProjection, refreshtShipState } from '../utils/ship'; import { shipProjection, refreshtShipState } from '../utils/ship';
const QUERY_PAYING_STATE_GAP = process.env.NODE_ENV === 'production' ? 600 * 1000 : 60 * 1000; const QUERY_PAYING_STATE_GAP = process.env.NODE_ENV === 'production' ? 3600 * 1000 : 60 * 1000;
const watchers = [ const watchers = [
{ {
name: '对shipping状态的物流同步其真实状态', name: '对shipping状态的物流同步其真实状态',

View File

@ -44,6 +44,18 @@ const checkers = [
}, },
iState: 'unshipped', iState: 'unshipped',
} }
},
{
entity: 'ship',
type: 'logicalData',
action: 'receive',
checker: (operation) => {
const { data } = operation;
if (!data.receiveAt) {
const now = Date.now();
data.receiveAt = now;
}
}
} }
]; ];
exports.default = checkers; exports.default = checkers;

View File

@ -1,4 +1,4 @@
import { String, Int } from 'oak-domain/lib/types/DataType'; import { String, Datetime, Int } from 'oak-domain/lib/types/DataType';
import { EntityShape } from 'oak-domain/lib/types/Entity'; import { EntityShape } from 'oak-domain/lib/types/Entity';
import { ActionDef, EntityDesc } from 'oak-domain/lib/types'; import { ActionDef, EntityDesc } from 'oak-domain/lib/types';
import { Schema as ShipService } from './ShipService'; import { Schema as ShipService } from './ShipService';
@ -21,6 +21,7 @@ export interface Schema extends EntityShape {
phantom5?: Object; phantom5?: Object;
extraShipId?: String<128>; extraShipId?: String<128>;
extraPaths?: Paths; extraPaths?: Paths;
receiveAt?: Datetime;
} }
type IState = 'unshipped' | 'shipping' | 'cancelled' | 'received' | 'rejected' | 'unknown'; type IState = 'unshipped' | 'shipping' | 'cancelled' | 'received' | 'rejected' | 'unknown';
type IAction = 'ship' | 'receive' | 'cancel' | 'reject' | 'unknow'; type IAction = 'ship' | 'receive' | 'cancel' | 'reject' | 'unknow';

View File

@ -49,6 +49,7 @@ exports.entityDesc = {
phantom5: '结构化项', phantom5: '结构化项',
extraShipId: '外部订单Id', extraShipId: '外部订单Id',
extraPaths: '外部轨迹信息', extraPaths: '外部轨迹信息',
receiveAt: '签收时间',
}, },
v: { v: {
iState: { iState: {

View File

@ -72,6 +72,9 @@ exports.desc = {
extraPaths: { extraPaths: {
type: "object" type: "object"
}, },
receiveAt: {
type: "datetime"
},
iState: { iState: {
type: "enum", type: "enum",
enumeration: ["unshipped", "shipping", "cancelled", "received", "rejected", "unknown"] enumeration: ["unshipped", "shipping", "cancelled", "received", "rejected", "unknown"]

View File

@ -2,7 +2,7 @@ import { ForeignKey, JsonProjection } from "oak-domain/lib/types/DataType";
import { Q_DateValue, Q_NumberValue, Q_StringValue, Q_EnumValue, NodeId, ExprOp, ExpressionKey, JsonFilter } from "oak-domain/lib/types/Demand"; import { Q_DateValue, Q_NumberValue, Q_StringValue, Q_EnumValue, NodeId, ExprOp, ExpressionKey, JsonFilter } from "oak-domain/lib/types/Demand";
import { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/Entity"; import { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/Entity";
import { Action, ParticularAction, IState } from "./Action"; import { Action, ParticularAction, IState } from "./Action";
import { String, Int } from "oak-domain/lib/types/DataType"; import { String, Int, Datetime } from "oak-domain/lib/types/DataType";
type Paths = Array<{ type Paths = Array<{
time: number; time: number;
action: string; action: string;
@ -21,6 +21,7 @@ export type OpSchema = EntityShape & {
phantom5?: Object | null; phantom5?: Object | null;
extraShipId?: String<128> | null; extraShipId?: String<128> | null;
extraPaths?: Paths | null; extraPaths?: Paths | null;
receiveAt?: Datetime | null;
iState?: IState | null; iState?: IState | null;
} & { } & {
[A in ExpressionKey]?: any; [A in ExpressionKey]?: any;
@ -44,6 +45,7 @@ export type OpFilter = {
phantom5: Object; phantom5: Object;
extraShipId: Q_StringValue; extraShipId: Q_StringValue;
extraPaths: JsonFilter<Paths>; extraPaths: JsonFilter<Paths>;
receiveAt: Q_DateValue;
iState: Q_EnumValue<IState>; iState: Q_EnumValue<IState>;
} & ExprOp<OpAttr | string>; } & ExprOp<OpAttr | string>;
export type OpProjection = { export type OpProjection = {
@ -66,6 +68,7 @@ export type OpProjection = {
phantom5?: number | Object; phantom5?: number | Object;
extraShipId?: number; extraShipId?: number;
extraPaths?: number | JsonProjection<Paths>; extraPaths?: number | JsonProjection<Paths>;
receiveAt?: number;
iState?: number; iState?: number;
} & Partial<ExprOp<OpAttr | string>>; } & Partial<ExprOp<OpAttr | string>>;
export type OpSortAttr = Partial<{ export type OpSortAttr = Partial<{
@ -82,6 +85,7 @@ export type OpSortAttr = Partial<{
phantom4: number; phantom4: number;
extraShipId: number; extraShipId: number;
extraPaths: number; extraPaths: number;
receiveAt: number;
iState: number; iState: number;
[k: string]: any; [k: string]: any;
} | ExprOp<OpAttr | string>>; } | ExprOp<OpAttr | string>>;

View File

@ -14,7 +14,8 @@
"phantom4": "索引项四", "phantom4": "索引项四",
"phantom5": "结构化项", "phantom5": "结构化项",
"extraShipId": "外部订单Id", "extraShipId": "外部订单Id",
"extraPaths": "外部轨迹信息" "extraPaths": "外部轨迹信息",
"receiveAt": "签收时间"
}, },
"v": { "v": {
"iState": { "iState": {

View File

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

View File

@ -9,7 +9,10 @@ export default interface ShipClazz<ED extends EntityDict & BaseEntityDict, Conte
available(shipServiceId: string, orderIds: string[], context: Context): Promise<boolean>; available(shipServiceId: string, orderIds: string[], context: Context): Promise<boolean>;
eOrder(shipId: string, context: Context): Promise<string>; eOrder(shipId: string, context: Context): Promise<string>;
cancelOrder(shipId: string, context: Context): Promise<void>; cancelOrder(shipId: string, context: Context): Promise<void>;
syncState(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['iState']>; syncState(shipId: string, context: Context): Promise<{
state: EntityDict['ship']['OpSchema']['iState'];
time?: number;
}>;
syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']>; syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']>;
getPrintInfo(shipId: string, context: Context): Promise<{ getPrintInfo(shipId: string, context: Context): Promise<{
type: 'html'; type: 'html';

View File

@ -344,14 +344,17 @@ async function refreshtShipState(ship, context) {
} }
const { entity, entityId } = ship2; const { entity, entityId } = ship2;
const clazz = await (0, shipClazz_1.getShipClazz)(entity, entityId, context); const clazz = await (0, shipClazz_1.getShipClazz)(entity, entityId, context);
const state = await clazz.syncState(ship2.id, context); const { state, time } = await clazz.syncState(ship2.id, context);
let action = undefined; let action = undefined, updateData = {};
switch (state) { switch (state) {
case 'shipping': //已发货 case 'shipping': //已发货
action = 'ship'; action = 'ship';
break; break;
case 'received': //已收货 case 'received': //已收货
action = 'receive'; action = 'receive';
updateData = {
receiveAt: time
};
break; break;
case 'unknow': //不明 case 'unknow': //不明
action = 'unknow'; action = 'unknow';
@ -363,7 +366,7 @@ async function refreshtShipState(ship, context) {
return await context.operate('ship', { return await context.operate('ship', {
id: await (0, uuid_1.generateNewIdAsync)(), id: await (0, uuid_1.generateNewIdAsync)(),
action, action,
data: {}, data: updateData,
filter: { filter: {
id: ship2.id, id: ship2.id,
} }

View File

@ -5,7 +5,10 @@ import DebugClazz from './WechatMpShip.debug';
export default class WechatMpShip<ED extends EntityDict & BaseEntityDict, Context extends BackendRuntimeContext<ED>> extends DebugClazz<ED, Context> { export default class WechatMpShip<ED extends EntityDict & BaseEntityDict, Context extends BackendRuntimeContext<ED>> extends DebugClazz<ED, Context> {
eOrder(shipId: string, context: Context): Promise<string>; eOrder(shipId: string, context: Context): Promise<string>;
cancelOrder(shipId: string, context: Context): Promise<void>; cancelOrder(shipId: string, context: Context): Promise<void>;
syncState(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['iState']>; syncState(shipId: string, context: Context): Promise<{
state: EntityDict['ship']['OpSchema']['iState'];
time?: number;
}>;
syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']>; syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']>;
getPrintInfo(shipId: string, context: Context): Promise<{ getPrintInfo(shipId: string, context: Context): Promise<{
type: 'html'; type: 'html';

View File

@ -40,7 +40,10 @@ export default class WechatMpShipDebug<ED extends EntityDict & BaseEntityDict, C
}>; }>;
eOrder(shipId: string, context: Context): Promise<string>; eOrder(shipId: string, context: Context): Promise<string>;
cancelOrder(shipId: string, context: Context): Promise<void>; cancelOrder(shipId: string, context: Context): Promise<void>;
syncState(shipId: string, context: Context): Promise<EntityDict["ship"]["OpSchema"]["iState"]>; syncState(shipId: string, context: Context): Promise<{
state: EntityDict['ship']['OpSchema']['iState'];
time?: number;
}>;
syncPaths(shipId: string, context: Context): Promise<EntityDict["ship"]["OpSchema"]["extraPaths"]>; syncPaths(shipId: string, context: Context): Promise<EntityDict["ship"]["OpSchema"]["extraPaths"]>;
getPrintInfo(shipId: string, context: Context): Promise<{ getPrintInfo(shipId: string, context: Context): Promise<{
type: "html"; type: "html";

View File

@ -288,13 +288,14 @@ class WechatMpShipDebug {
const data = await this.prepareGetPath(shipId, context); const data = await this.prepareGetPath(shipId, context);
console.log('mock syncState to wechatMpShip, data:', data); console.log('mock syncState to wechatMpShip, data:', data);
const r = Math.random(); const r = Math.random();
const now = Date.now();
if (r < 0.3) { if (r < 0.3) {
return 'shipping'; return { state: 'shipping', time: now };
} }
else if (r > 0.95) { else if (r > 0.95) {
return 'unknow'; return { state: 'unknow', time: now };
} }
return 'received'; return { state: 'received', time: now };
} }
async syncPaths(shipId, context) { async syncPaths(shipId, context) {
const data = await this.prepareGetPath(shipId, context); const data = await this.prepareGetPath(shipId, context);

View File

@ -21,6 +21,7 @@ class WechatMpShip extends WechatMpShip_debug_1.default {
const { path_item_num, path_item_list } = result; const { path_item_num, path_item_list } = result;
const latestPath = path_item_list[path_item_num - 1] || undefined; const latestPath = path_item_list[path_item_num - 1] || undefined;
const latestType = latestPath?.action_type; const latestType = latestPath?.action_type;
const latestTime = latestPath?.action_time;
/** /**
* action_type: * action_type:
* 100001 揽件阶段-揽件成功 * 100001 揽件阶段-揽件成功
@ -57,7 +58,7 @@ class WechatMpShip extends WechatMpShip_debug_1.default {
break; break;
} }
} }
return state; return { state, time: latestTime };
} }
async syncPaths(shipId, context) { async syncPaths(shipId, context) {
const instance = await this.getInstance(context); const instance = await this.getInstance(context);

View File

@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
const operationResult_1 = require("oak-domain/lib/utils/operationResult"); const operationResult_1 = require("oak-domain/lib/utils/operationResult");
const ship_1 = require("../utils/ship"); const ship_1 = require("../utils/ship");
const QUERY_PAYING_STATE_GAP = process.env.NODE_ENV === 'production' ? 600 * 1000 : 60 * 1000; const QUERY_PAYING_STATE_GAP = process.env.NODE_ENV === 'production' ? 3600 * 1000 : 60 * 1000;
const watchers = [ const watchers = [
{ {
name: '对shipping状态的物流同步其真实状态', name: '对shipping状态的物流同步其真实状态',

View File

@ -49,6 +49,18 @@ const checkers: Checker<EntityDict, 'ship', RuntimeCxt>[] = [
}, },
iState: 'unshipped', iState: 'unshipped',
} }
},
{
entity: 'ship',
type: 'logicalData',
action: 'receive',
checker: (operation) => {
const { data } = operation as EntityDict['ship']['Update'];
if (!data.receiveAt) {
const now = Date.now();
data.receiveAt = now;
}
}
} }
]; ];

View File

@ -30,6 +30,7 @@ export interface Schema extends EntityShape {
phantom5?: Object; phantom5?: Object;
extraShipId?: String<128>; extraShipId?: String<128>;
extraPaths?: Paths; extraPaths?: Paths;
receiveAt?: Datetime;
}; };
type IState = 'unshipped' | 'shipping' | 'cancelled' | 'received' | 'rejected' | 'unknown'; type IState = 'unshipped' | 'shipping' | 'cancelled' | 'received' | 'rejected' | 'unknown';
@ -87,6 +88,7 @@ export const entityDesc: EntityDesc<Schema, Action, '', {
phantom5: '结构化项', phantom5: '结构化项',
extraShipId: '外部订单Id', extraShipId: '外部订单Id',
extraPaths: '外部轨迹信息', extraPaths: '外部轨迹信息',
receiveAt: '签收时间',
}, },
v: { v: {
iState: { iState: {

View File

@ -17,7 +17,7 @@ export default interface ShipClazz<ED extends EntityDict & BaseEntityDict, Conte
cancelOrder(shipId: string, context: Context): Promise<void>; cancelOrder(shipId: string, context: Context): Promise<void>;
// 同步状态 // 同步状态
syncState(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['iState']>; syncState(shipId: string, context: Context): Promise<{ state: EntityDict['ship']['OpSchema']['iState'], time?: number }>;
// 同步轨迹 // 同步轨迹
syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']>; syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']>;

View File

@ -385,14 +385,17 @@ export async function refreshtShipState(
} }
const { entity, entityId } = ship2; const { entity, entityId } = ship2;
const clazz = await getShipClazz(entity!, entityId!, context); const clazz = await getShipClazz(entity!, entityId!, context);
const state = await clazz.syncState(ship2.id!, context); const { state, time } = await clazz.syncState(ship2.id!, context);
let action = undefined; let action = undefined, updateData: EntityDict['ship']['UpdateOperationData'] = {};
switch (state) { switch (state) {
case 'shipping': //已发货 case 'shipping': //已发货
action = 'ship'; action = 'ship';
break; break;
case 'received': //已收货 case 'received': //已收货
action = 'receive'; action = 'receive';
updateData = {
receiveAt: time
}
break; break;
case 'unknow': //不明 case 'unknow': //不明
action = 'unknow'; action = 'unknow';
@ -404,7 +407,7 @@ export async function refreshtShipState(
return await context.operate('ship', { return await context.operate('ship', {
id: await generateNewIdAsync(), id: await generateNewIdAsync(),
action, action,
data: {}, data: updateData,
filter: { filter: {
id: ship2.id, id: ship2.id,
} }

View File

@ -333,17 +333,18 @@ export default class WechatMpShipDebug<ED extends EntityDict & BaseEntityDict, C
console.log('mock cancelOrder to wechatMpShip, data:', data); console.log('mock cancelOrder to wechatMpShip, data:', data);
} }
async syncState(shipId: string, context: Context): Promise<EntityDict["ship"]["OpSchema"]["iState"]> { async syncState(shipId: string, context: Context): Promise<{ state: EntityDict['ship']['OpSchema']['iState'], time?: number }> {
const data = await this.prepareGetPath(shipId, context); const data = await this.prepareGetPath(shipId, context);
console.log('mock syncState to wechatMpShip, data:', data); console.log('mock syncState to wechatMpShip, data:', data);
const r = Math.random(); const r = Math.random();
const now = Date.now();
if (r < 0.3) { if (r < 0.3) {
return 'shipping'; return { state: 'shipping', time: now };
} }
else if (r > 0.95) { else if (r > 0.95) {
return 'unknow'; return { state: 'unknow', time: now };
} }
return 'received'; return { state: 'received', time: now };
} }
async syncPaths(shipId: string, context: Context): Promise<EntityDict["ship"]["OpSchema"]["extraPaths"]> { async syncPaths(shipId: string, context: Context): Promise<EntityDict["ship"]["OpSchema"]["extraPaths"]> {
const data = await this.prepareGetPath(shipId, context); const data = await this.prepareGetPath(shipId, context);

View File

@ -19,13 +19,14 @@ export default class WechatMpShip<ED extends EntityDict & BaseEntityDict, Contex
await instance.cancelExpressOrder(data); await instance.cancelExpressOrder(data);
} }
async syncState(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['iState']> { async syncState(shipId: string, context: Context): Promise<{ state: EntityDict['ship']['OpSchema']['iState'], time?: number }> {
const instance = await this.getInstance(context); const instance = await this.getInstance(context);
const data = await this.prepareGetPath(shipId, context); const data = await this.prepareGetPath(shipId, context);
const result = await instance.getExpressPath(data); const result = await instance.getExpressPath(data);
const { path_item_num, path_item_list } = result; const { path_item_num, path_item_list } = result;
const latestPath = path_item_list[path_item_num - 1] || undefined; const latestPath = path_item_list[path_item_num - 1] || undefined;
const latestType = latestPath?.action_type; const latestType = latestPath?.action_type;
const latestTime = latestPath?.action_time;
/** /**
* action_type: * action_type:
* 100001 - * 100001 -
@ -63,7 +64,7 @@ export default class WechatMpShip<ED extends EntityDict & BaseEntityDict, Contex
break; break;
} }
} }
return state; return { state, time: latestTime };
} }
async syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']> { async syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']> {