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',
}
},
{
entity: 'ship',
type: 'logicalData',
action: 'receive',
checker: (operation) => {
const { data } = operation;
if (!data.receiveAt) {
const now = Date.now();
data.receiveAt = now;
}
}
}
];
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 { ActionDef, EntityDesc } from 'oak-domain/lib/types';
import { Schema as ShipService } from './ShipService';
@ -21,6 +21,7 @@ export interface Schema extends EntityShape {
phantom5?: Object;
extraShipId?: String<128>;
extraPaths?: Paths;
receiveAt?: Datetime;
}
type IState = 'unshipped' | 'shipping' | 'cancelled' | 'received' | 'rejected' | 'unknown';
type IAction = 'ship' | 'receive' | 'cancel' | 'reject' | 'unknow';

View File

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

View File

@ -69,6 +69,9 @@ export const desc = {
extraPaths: {
type: "object"
},
receiveAt: {
type: "datetime"
},
iState: {
type: "enum",
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 { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/Entity";
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<{
time: number;
action: string;
@ -21,6 +21,7 @@ export type OpSchema = EntityShape & {
phantom5?: Object | null;
extraShipId?: String<128> | null;
extraPaths?: Paths | null;
receiveAt?: Datetime | null;
iState?: IState | null;
} & {
[A in ExpressionKey]?: any;
@ -44,6 +45,7 @@ export type OpFilter = {
phantom5: Object;
extraShipId: Q_StringValue;
extraPaths: JsonFilter<Paths>;
receiveAt: Q_DateValue;
iState: Q_EnumValue<IState>;
} & ExprOp<OpAttr | string>;
export type OpProjection = {
@ -66,6 +68,7 @@ export type OpProjection = {
phantom5?: number | Object;
extraShipId?: number;
extraPaths?: number | JsonProjection<Paths>;
receiveAt?: number;
iState?: number;
} & Partial<ExprOp<OpAttr | string>>;
export type OpSortAttr = Partial<{
@ -82,6 +85,7 @@ export type OpSortAttr = Partial<{
phantom4: number;
extraShipId: number;
extraPaths: number;
receiveAt: number;
iState: number;
[k: string]: any;
} | ExprOp<OpAttr | string>>;

View File

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

View File

@ -6,6 +6,6 @@ import { BRC } from '../types/RuntimeCxt';
* @param context
* @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>[];
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>;
eOrder(shipId: string, context: Context): Promise<string>;
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']>;
getPrintInfo(shipId: string, context: Context): Promise<{
type: 'html';

View File

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

View File

@ -40,7 +40,10 @@ export default class WechatMpShipDebug<ED extends EntityDict & BaseEntityDict, C
}>;
eOrder(shipId: string, context: Context): Promise<string>;
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"]>;
getPrintInfo(shipId: string, context: Context): Promise<{
type: "html";

View File

@ -285,13 +285,14 @@ export default class WechatMpShipDebug {
const data = await this.prepareGetPath(shipId, context);
console.log('mock syncState to wechatMpShip, data:', data);
const r = Math.random();
const now = Date.now();
if (r < 0.3) {
return 'shipping';
return { state: 'shipping', time: now };
}
else if (r > 0.95) {
return 'unknow';
return { state: 'unknow', time: now };
}
return 'received';
return { state: 'received', time: now };
}
async syncPaths(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 latestPath = path_item_list[path_item_num - 1] || undefined;
const latestType = latestPath?.action_type;
const latestTime = latestPath?.action_time;
/**
* action_type:
* 100001 揽件阶段-揽件成功
@ -54,7 +55,7 @@ export default class WechatMpShip extends DebugClazz {
break;
}
}
return state;
return { state, time: latestTime };
}
async syncPaths(shipId, context) {
const instance = await this.getInstance(context);

View File

@ -1,6 +1,6 @@
import { mergeOperationResult } from 'oak-domain/lib/utils/operationResult';
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 = [
{
name: '对shipping状态的物流同步其真实状态',

View File

@ -44,6 +44,18 @@ const checkers = [
},
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;

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

View File

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

View File

@ -72,6 +72,9 @@ exports.desc = {
extraPaths: {
type: "object"
},
receiveAt: {
type: "datetime"
},
iState: {
type: "enum",
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 { MakeAction as OakMakeAction, EntityShape } from "oak-domain/lib/types/Entity";
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<{
time: number;
action: string;
@ -21,6 +21,7 @@ export type OpSchema = EntityShape & {
phantom5?: Object | null;
extraShipId?: String<128> | null;
extraPaths?: Paths | null;
receiveAt?: Datetime | null;
iState?: IState | null;
} & {
[A in ExpressionKey]?: any;
@ -44,6 +45,7 @@ export type OpFilter = {
phantom5: Object;
extraShipId: Q_StringValue;
extraPaths: JsonFilter<Paths>;
receiveAt: Q_DateValue;
iState: Q_EnumValue<IState>;
} & ExprOp<OpAttr | string>;
export type OpProjection = {
@ -66,6 +68,7 @@ export type OpProjection = {
phantom5?: number | Object;
extraShipId?: number;
extraPaths?: number | JsonProjection<Paths>;
receiveAt?: number;
iState?: number;
} & Partial<ExprOp<OpAttr | string>>;
export type OpSortAttr = Partial<{
@ -82,6 +85,7 @@ export type OpSortAttr = Partial<{
phantom4: number;
extraShipId: number;
extraPaths: number;
receiveAt: number;
iState: number;
[k: string]: any;
} | ExprOp<OpAttr | string>>;

View File

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

View File

@ -6,6 +6,6 @@ import { BRC } from '../types/RuntimeCxt';
* @param context
* @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>[];
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>;
eOrder(shipId: string, context: Context): Promise<string>;
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']>;
getPrintInfo(shipId: string, context: Context): Promise<{
type: 'html';

View File

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

View File

@ -40,7 +40,10 @@ export default class WechatMpShipDebug<ED extends EntityDict & BaseEntityDict, C
}>;
eOrder(shipId: string, context: Context): Promise<string>;
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"]>;
getPrintInfo(shipId: string, context: Context): Promise<{
type: "html";

View File

@ -288,13 +288,14 @@ class WechatMpShipDebug {
const data = await this.prepareGetPath(shipId, context);
console.log('mock syncState to wechatMpShip, data:', data);
const r = Math.random();
const now = Date.now();
if (r < 0.3) {
return 'shipping';
return { state: 'shipping', time: now };
}
else if (r > 0.95) {
return 'unknow';
return { state: 'unknow', time: now };
}
return 'received';
return { state: 'received', time: now };
}
async syncPaths(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 latestPath = path_item_list[path_item_num - 1] || undefined;
const latestType = latestPath?.action_type;
const latestTime = latestPath?.action_time;
/**
* action_type:
* 100001 揽件阶段-揽件成功
@ -57,7 +58,7 @@ class WechatMpShip extends WechatMpShip_debug_1.default {
break;
}
}
return state;
return { state, time: latestTime };
}
async syncPaths(shipId, context) {
const instance = await this.getInstance(context);

View File

@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
const operationResult_1 = require("oak-domain/lib/utils/operationResult");
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 = [
{
name: '对shipping状态的物流同步其真实状态',

View File

@ -49,6 +49,18 @@ const checkers: Checker<EntityDict, 'ship', RuntimeCxt>[] = [
},
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;
extraShipId?: String<128>;
extraPaths?: Paths;
receiveAt?: Datetime;
};
type IState = 'unshipped' | 'shipping' | 'cancelled' | 'received' | 'rejected' | 'unknown';
@ -87,6 +88,7 @@ export const entityDesc: EntityDesc<Schema, Action, '', {
phantom5: '结构化项',
extraShipId: '外部订单Id',
extraPaths: '外部轨迹信息',
receiveAt: '签收时间',
},
v: {
iState: {

View File

@ -17,7 +17,7 @@ export default interface ShipClazz<ED extends EntityDict & BaseEntityDict, Conte
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']>;

View File

@ -385,14 +385,17 @@ export async function refreshtShipState(
}
const { entity, entityId } = ship2;
const clazz = await getShipClazz(entity!, entityId!, context);
const state = await clazz.syncState(ship2.id!, context);
let action = undefined;
const { state, time } = await clazz.syncState(ship2.id!, context);
let action = undefined, updateData: EntityDict['ship']['UpdateOperationData'] = {};
switch (state) {
case 'shipping': //已发货
action = 'ship';
break;
case 'received': //已收货
action = 'receive';
updateData = {
receiveAt: time
}
break;
case 'unknow': //不明
action = 'unknow';
@ -404,7 +407,7 @@ export async function refreshtShipState(
return await context.operate('ship', {
id: await generateNewIdAsync(),
action,
data: {},
data: updateData,
filter: {
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);
}
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);
console.log('mock syncState to wechatMpShip, data:', data);
const r = Math.random();
const now = Date.now();
if (r < 0.3) {
return 'shipping';
return { state: 'shipping', time: now };
}
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"]> {
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);
}
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 data = await this.prepareGetPath(shipId, context);
const result = await instance.getExpressPath(data);
const { path_item_num, path_item_list } = result;
const latestPath = path_item_list[path_item_num - 1] || undefined;
const latestType = latestPath?.action_type;
const latestTime = latestPath?.action_time;
/**
* action_type:
* 100001 -
@ -63,7 +64,7 @@ export default class WechatMpShip<ED extends EntityDict & BaseEntityDict, Contex
break;
}
}
return state;
return { state, time: latestTime };
}
async syncPaths(shipId: string, context: Context): Promise<EntityDict['ship']['OpSchema']['extraPaths']> {