@operato/twin-kernel 0.11.12 → 0.11.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/flow-engine.d.ts +8 -1
- package/dist/flow-engine.js +12 -2
- package/dist/kernel.js +4 -4
- package/dist/observed-reducer.js +4 -3
- package/dist/yms-kernel.js +2 -2
- package/dist-cjs/index.cjs +51 -25
- package/package.json +2 -2
package/dist/flow-engine.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MaterialActual, TestResult, ISOTime, MaterialQuantity, WorkCalendarEntry, EffectivePeriod, Effectivity, OffCalendarReason, ResourceProperty, ResourceClassDef, MaterialDefinition, Attention, TwinModelDef, CanonicalEnvelope, Command, CommandAck, EventHandler, EquipmentMotion, AssetState, GeneratorSpec, InterventionOutcome, OrderState, PersonState, ScenarioControl, ScenarioOverride, StateSnapshot, TwinKernel, Unsubscribe, LocationState, ItemState, EquipmentState, OrderStatusDelta, TaskState, TaskStatus, StructureShift, IdentityGroundingView, IdentityDeclaration, TestSpecificationCriterion, LocationObservation } from '@operato/ops-contract';
|
|
1
|
+
import type { MaterialActual, TestResult, ISOTime, MaterialQuantity, WorkCalendarEntry, EffectivePeriod, Effectivity, OffCalendarReason, ResourceProperty, ResourceClassDef, MaterialDefinition, Attention, TwinModelDef, CanonicalEnvelope, Command, CommandAck, EventHandler, EquipmentMotion, AssetState, GeneratorSpec, InterventionOutcome, OrderState, PersonState, ScenarioControl, ScenarioOverride, StateSnapshot, TwinKernel, Unsubscribe, LocationState, ItemState, EquipmentState, OrderStatusDelta, TaskState, TaskStatus, StructureShift, IdentityGroundingView, IdentityDeclaration, TestSpecificationCriterion, LocationObservation, DispositionFact } from '@operato/ops-contract';
|
|
2
2
|
import { type RatedUsage, type UsedUsage } from '@operato/ops-contract';
|
|
3
3
|
import type { VocabularyElement } from '@operato/ops-contract';
|
|
4
4
|
import type { ReducerCheckpoint } from './observed-reducer.ts';
|
|
@@ -46,6 +46,13 @@ export interface FlowItem {
|
|
|
46
46
|
ilmd?: Record<string, unknown>;
|
|
47
47
|
/** 선언된 모든 수량 — 표준 `MaterialLot.Quantity`(복수). 관측에서 온 물품이 여러 단위를 들 수 있다. */
|
|
48
48
|
quantities?: MaterialQuantity[];
|
|
49
|
+
/**
|
|
50
|
+
* 로트의 두 표준 칸 — ISA-95 `Disposition`(`nonconformance`) · `Status`(`status`). 관측 모드에서 리듀서가
|
|
51
|
+
* 앉힌 것을 `settleObserved` 가 옮기고 `itemState` 가 스냅샷에 낸다. 둘 중 하나가 빠지면 리듀서에는 있는데
|
|
52
|
+
* 화면에는 없는 칸이 된다(2026-09-16 에 둘 다 그랬다).
|
|
53
|
+
*/
|
|
54
|
+
nonconformance?: DispositionFact;
|
|
55
|
+
status?: string;
|
|
49
56
|
}
|
|
50
57
|
/** 물리 자산 — 반복사용(팔레트·랙·용기). 설비도 물품도 아니다(GRAI vs SSCC 구분은 계약 주석 참조). */
|
|
51
58
|
export interface FlowAsset extends EffectivePeriod {
|
package/dist/flow-engine.js
CHANGED
|
@@ -1034,7 +1034,14 @@ export class FlowEngine {
|
|
|
1034
1034
|
...(it.subLotId ? { subLotId: it.subLotId } : {}),
|
|
1035
1035
|
...(it.definitionId ? { definitionId: it.definitionId } : {}),
|
|
1036
1036
|
gtin: it.gtin, qty: it.qty ?? 1, uom: it.uom, ...(it.quantities?.length ? { quantities: it.quantities } : {}),
|
|
1037
|
-
parent: it.parent, carriedBy: it.carriedBy, expiry: it.expiry, ilmd: it.ilmd
|
|
1037
|
+
parent: it.parent, carriedBy: it.carriedBy, expiry: it.expiry, ilmd: it.ilmd,
|
|
1038
|
+
/*
|
|
1039
|
+
* 로트의 두 표준 칸 — ISA-95 `Disposition`(`nonconformance`)과 `Status`(`status`). 이 복사가 칸을 하나씩
|
|
1040
|
+
* 옮기는 자리라, 여기 없는 칸은 리듀서에 앉았어도 **스냅샷에 나오지 않는다**(2026-09-16 에 `status` 를
|
|
1041
|
+
* 넣다가 `nonconformance` 도 여기서 빠져 있던 것을 찾았다 — 자리는 있고 길이 없는 부류). 있을 때만 옮긴다.
|
|
1042
|
+
*/
|
|
1043
|
+
...(it.nonconformance ? { nonconformance: it.nonconformance } : {}),
|
|
1044
|
+
...(it.status ? { status: it.status } : {})
|
|
1038
1045
|
});
|
|
1039
1046
|
}
|
|
1040
1047
|
for (const m of snap.equipment) {
|
|
@@ -3869,7 +3876,10 @@ export class FlowEngine {
|
|
|
3869
3876
|
...(i.uom ? { uom: i.uom } : {}),
|
|
3870
3877
|
...(i.quantities?.length ? { quantities: i.quantities } : {}),
|
|
3871
3878
|
...(i.expiry !== undefined ? { expiry: i.expiry } : {}),
|
|
3872
|
-
...(i.ilmd ? { ilmd: i.ilmd } : {})
|
|
3879
|
+
...(i.ilmd ? { ilmd: i.ilmd } : {}),
|
|
3880
|
+
/* 로트의 두 표준 칸(§FlowItem) — 여기서 빠지면 리듀서·엔진에는 있고 스냅샷에는 없다. */
|
|
3881
|
+
...(i.nonconformance ? { nonconformance: i.nonconformance } : {}),
|
|
3882
|
+
...(i.status ? { status: i.status } : {})
|
|
3873
3883
|
};
|
|
3874
3884
|
}
|
|
3875
3885
|
/**
|
package/dist/kernel.js
CHANGED
|
@@ -9,7 +9,7 @@ import { CMD } from '@operato/ops-contract';
|
|
|
9
9
|
import { firstFitPolicy } from "./allocation-policy.js";
|
|
10
10
|
import { FlowEngine } from "./flow-engine.js";
|
|
11
11
|
import { planMakeToOrder } from "./make-to-order.js";
|
|
12
|
-
import { BIZSTEP, BTT } from '@operato/ops-contract';
|
|
12
|
+
import { BIZSTEP, BTT, WMS_ORDER_KIND } from '@operato/ops-contract';
|
|
13
13
|
import { DISP, ILMD_ATTR, aggregationEvent, objectEvent, transactionEvent } from '@operato/ops-contract';
|
|
14
14
|
import { subLotIdOf, itemKeyOf } from '@operato/ops-contract';
|
|
15
15
|
const TRAVEL_MS = 30_000;
|
|
@@ -133,7 +133,7 @@ export class WmsKernel extends FlowEngine {
|
|
|
133
133
|
const so = this.requireBizTransactionId(`SO-${soSeq}`, 'salesorder');
|
|
134
134
|
const requested = lines.reduce((s, l) => s + l.qty, 0);
|
|
135
135
|
const order = {
|
|
136
|
-
id, kind:
|
|
136
|
+
id, kind: WMS_ORDER_KIND.outbound, status: 'created', requested, fulfilled: 0, bizTransaction: so,
|
|
137
137
|
allocated: [], picked: [], shipmentEpc: null, lines: lines.map(l => ({ gtin: l.gtin, requested: l.qty })),
|
|
138
138
|
...(spec ? this.promiseOf(spec) : {})
|
|
139
139
|
};
|
|
@@ -175,7 +175,7 @@ export class WmsKernel extends FlowEngine {
|
|
|
175
175
|
/* 할당은 아직 집은 것이 아니다 — 물건은 보관 자리에 있고 처분만 '예약' 으로 바뀐다.
|
|
176
176
|
* 그래서 단계는 storing 이다(피킹 관측은 실제로 집을 때 따로 난다). */
|
|
177
177
|
this.reserve(chosenAll, BIZSTEP.storing);
|
|
178
|
-
this.emit(transactionEvent({ eventTime: this.now(), action: 'ADD', bizStep: BIZSTEP.picking, bizTransactionList: [{ type: BTT.
|
|
178
|
+
this.emit(transactionEvent({ eventTime: this.now(), action: 'ADD', bizStep: BIZSTEP.picking, bizTransactionList: [{ type: BTT.poc, bizTransaction: o.bizTransaction }], epcList: chosenAll.slice() }));
|
|
179
179
|
for (const epc of chosenAll) {
|
|
180
180
|
const it = this.items.get(epc);
|
|
181
181
|
const id = `task-${++this.taskSeq}`;
|
|
@@ -363,7 +363,7 @@ export class WmsKernel extends FlowEngine {
|
|
|
363
363
|
const shpSeq = ++this.epcSeq;
|
|
364
364
|
const shipment = this.requireObjectId(`SHP-${shpSeq}`);
|
|
365
365
|
order.shipmentEpc = shipment;
|
|
366
|
-
const soTxn = [{ type: BTT.
|
|
366
|
+
const soTxn = [{ type: BTT.poc, bizTransaction: order.bizTransaction }];
|
|
367
367
|
// 패킹: 화물(shipment) ← 팔레트 조립(merge). 팔레트는 출하 DELETE 까지 독립 유지 → consume 없음.
|
|
368
368
|
this.aggregate(shipment, order.picked.slice(), { bizStep: BIZSTEP.packing, readPoint: staging.id, bizLocation: staging.id });
|
|
369
369
|
order.status = 'packed';
|
package/dist/observed-reducer.js
CHANGED
|
@@ -573,11 +573,12 @@ export class ObservedReducer {
|
|
|
573
573
|
* 않는다** — 모르는 로트의 상태는 `unhandled` 로 세어서 낸다.
|
|
574
574
|
*/
|
|
575
575
|
const d = e.data;
|
|
576
|
-
if (!d?.
|
|
576
|
+
if (!d?.lotId || !d?.status)
|
|
577
577
|
break;
|
|
578
|
-
if (this.stale(`material-lot:${d.
|
|
578
|
+
if (this.stale(`material-lot:${d.lotId}`, e))
|
|
579
579
|
return;
|
|
580
|
-
|
|
580
|
+
/* `lotId` 는 표준 `MaterialLotID` — 값은 로트의 식별자, 즉 여기서 `epc` 로 든 것과 같다. */
|
|
581
|
+
const parts = [...this.items.values()].filter(i => i.epc === d.lotId);
|
|
581
582
|
if (!parts.length) {
|
|
582
583
|
this.noteUnhandled(e, `${OP_EVENT.materialLot}:unknown-lot`);
|
|
583
584
|
break;
|
package/dist/yms-kernel.js
CHANGED
|
@@ -19,7 +19,7 @@ import { itemKeyOf } from '@operato/ops-contract';
|
|
|
19
19
|
import { firstFitPolicy } from "./allocation-policy.js";
|
|
20
20
|
import { FlowEngine } from "./flow-engine.js";
|
|
21
21
|
import { DISP, objectEvent, transactionEvent } from '@operato/ops-contract';
|
|
22
|
-
import { YARD_BIZSTEP
|
|
22
|
+
import { YARD_BIZSTEP } from '@operato/ops-contract';
|
|
23
23
|
const TRAVEL_MS = 20_000; // 야드 이동
|
|
24
24
|
const DWELL_MS = 30_000; // 도크 체류(상·하차) — depart 이동에 folded
|
|
25
25
|
const WINDOW_DELAY_MS = 40_000; // 도착 후 어포인트먼트 창까지(early arrival → 대기)
|
|
@@ -149,7 +149,7 @@ export class YmsKernel extends FlowEngine {
|
|
|
149
149
|
this.trailerCargo.set(trailer.epc, avail.slice(0, CARGO_PER_TRAILER).map(i => i.epc));
|
|
150
150
|
}
|
|
151
151
|
this.reserve([trailer.epc], bizStep); // 처분 변화를 이벤트로 — 미러가 "잡혔다" 를 알 수 있게
|
|
152
|
-
this.emit(transactionEvent({ eventTime: this.now(), action: 'ADD', bizStep, bizTransactionList: [{
|
|
152
|
+
this.emit(transactionEvent({ eventTime: this.now(), action: 'ADD', bizStep, bizTransactionList: [{ bizTransaction: o.bizTransaction }], epcList: [trailer.epc], readPoint: door.id }));
|
|
153
153
|
// drop: 야드→도크 pull. live: 게이트→도크 직행(spot-live). 둘 다 toNode=도크도어.
|
|
154
154
|
const dockKind = mode === 'drop' ? 'pull' : 'spot-live';
|
|
155
155
|
const task = { id: `task-${++this.taskSeq}`, kind: dockKind, status: 'created', itemEpc: trailer.epc, fromNode: trailer.location, toNode: door.id, resource: null, remainingMs: 0, durationMs: this.durationOf({ kind: dockKind, fromNode: trailer.location, toNode: door.id }, TRAVEL_MS), orderId: o.id };
|
package/dist-cjs/index.cjs
CHANGED
|
@@ -668,6 +668,7 @@ var OP_EVENT = {
|
|
|
668
668
|
* 접지 않는다 — 승인됐는데 안 나간 배치가 트윈이 보여야 할 상태다.
|
|
669
669
|
*/
|
|
670
670
|
materialLot: "material-lot.status",
|
|
671
|
+
// 레코드: { lotId(표준 MaterialLotID = ItemState.epc 의 값), status, decidedBy?, reason?, decidedAt? }
|
|
671
672
|
/**
|
|
672
673
|
* **이 목록이 전부다** — 연결된 시스템이 현재 목록을 한 바퀴 다 보낸 뒤 그것을 알린다.
|
|
673
674
|
*
|
|
@@ -992,8 +993,28 @@ var BIZSTEP = {
|
|
|
992
993
|
replenishing: "urn:epcglobal:cbv:bizstep:replenishing"
|
|
993
994
|
};
|
|
994
995
|
var BTT = {
|
|
996
|
+
/** Purchase Order — the document an inbound receipt is made against. */
|
|
995
997
|
po: "urn:epcglobal:cbv:btt:po",
|
|
996
|
-
|
|
998
|
+
/** Purchase Order Confirmation — the seller's sales order. */
|
|
999
|
+
poc: "urn:epcglobal:cbv:btt:poc",
|
|
1000
|
+
/** Despatch Advice (ASN) — announces an inbound delivery; also attached when shipping. */
|
|
1001
|
+
desadv: "urn:epcglobal:cbv:btt:desadv",
|
|
1002
|
+
/** Receiving Advice — the reply once an inbound receipt is complete. */
|
|
1003
|
+
recadv: "urn:epcglobal:cbv:btt:recadv",
|
|
1004
|
+
/** Return Merchandise Authorization — what a return is received against. */
|
|
1005
|
+
rma: "urn:epcglobal:cbv:btt:rma",
|
|
1006
|
+
/** Bill of Lading — the carrier's document, attached when shipping. */
|
|
1007
|
+
bol: "urn:epcglobal:cbv:btt:bol"
|
|
1008
|
+
};
|
|
1009
|
+
var WMS_ORDER_KIND = {
|
|
1010
|
+
/** Expected receipt (ASN). The kernel has no inbound order yet — arrival carries a `po` without one. */
|
|
1011
|
+
inbound: "inbound",
|
|
1012
|
+
/** Outbound order — what the kernel's sales order is. */
|
|
1013
|
+
outbound: "outbound",
|
|
1014
|
+
/** Receipt of returned goods. */
|
|
1015
|
+
return: "return",
|
|
1016
|
+
/** Stock transfer between sites. CBV has no document type for it: carry the id without a type. */
|
|
1017
|
+
transfer: "transfer"
|
|
997
1018
|
};
|
|
998
1019
|
var WMS_LOCATION_TYPES = ["dock", "storage", "staging", "dock-ship", "vas-station"];
|
|
999
1020
|
var WMS_LOCATION_LEVEL = {
|
|
@@ -1024,7 +1045,6 @@ var YARD_BIZSTEP = {
|
|
|
1024
1045
|
departing: "urn:epcglobal:cbv:bizstep:departing"
|
|
1025
1046
|
// 게이트-아웃
|
|
1026
1047
|
};
|
|
1027
|
-
var BTT_DELIVERY = "urn:epcglobal:cbv:btt:deliv";
|
|
1028
1048
|
var YMS_LOCATION_TYPES = ["gate", "yard-slot", "dock-door", "staging"];
|
|
1029
1049
|
var YMS_LOCATION_LEVEL = {
|
|
1030
1050
|
gate: "Other",
|
|
@@ -1043,14 +1063,8 @@ var MES_BIZSTEP = {
|
|
|
1043
1063
|
// 원자재 수령
|
|
1044
1064
|
producing: "urn:epcglobal:cbv:bizstep:commissioning",
|
|
1045
1065
|
// 생산(제품 최초 생성)
|
|
1046
|
-
storing: "urn:epcglobal:cbv:bizstep:storing"
|
|
1066
|
+
storing: "urn:epcglobal:cbv:bizstep:storing"
|
|
1047
1067
|
// 완제품 저장
|
|
1048
|
-
/**
|
|
1049
|
-
* **출하** — CBV `shipping`: 물품이 시설을 떠난다. 자재를 트윈 밖으로 내는 것은 이 사건이다(disposition
|
|
1050
|
-
* `in_transit`, readPoint = 출하 dock). 출하 **승인**은 이 사건이 아니라 로트 상태(`OP_EVENT.materialLot`)다 —
|
|
1051
|
-
* 승인됐는데 안 나간 배치가 보여야 한다(2026-09-16, ADR-0046 곁).
|
|
1052
|
-
*/
|
|
1053
|
-
shipping: "urn:epcglobal:cbv:bizstep:shipping"
|
|
1054
1068
|
};
|
|
1055
1069
|
var BTT_PRODORDER = "urn:epcglobal:cbv:btt:prodorder";
|
|
1056
1070
|
function sgtinUri(companyPrefix, itemRef, serial) {
|
|
@@ -2065,17 +2079,19 @@ var SPECS = {
|
|
|
2065
2079
|
/*
|
|
2066
2080
|
* **로트 상태** — ISA-95 `MaterialLot.Status`. 출하 승인(batch release)이 들어오는 문(§`OP_EVENT.materialLot`).
|
|
2067
2081
|
*
|
|
2068
|
-
* `disposition`(subjectId + decision) 과 필드가 겹치지 않는다 — 여기는 `
|
|
2069
|
-
*
|
|
2070
|
-
*
|
|
2082
|
+
* `disposition`(subjectId + decision) 과 필드가 겹치지 않는다 — 여기는 `lotId` + `status`. 정체 이름이 표준
|
|
2083
|
+
* `MaterialLotID` 인 이유가 하나 더 있다: 이 문은 `epc` 를 든 레코드를 EPCIS 어휘로 보고 받지 않는다
|
|
2084
|
+
* (§`operationalKindOf`). 값은 로트의 식별자(`ItemState.epc` 와 같은 값)다. 상태 낱말은 열려 있어 enum 이
|
|
2085
|
+
* 없다(오더 상태와 같은 규율). 로트 전체의 사실이므로 부분(`subLotId`)은 받지 않는다 — 부분마다 다른 상태가
|
|
2086
|
+
* 필요해지면 그것은 다른 사실이다.
|
|
2071
2087
|
*/
|
|
2072
2088
|
"material-lot": {
|
|
2073
2089
|
eventType: OP_EVENT.materialLot,
|
|
2074
|
-
match: ["
|
|
2090
|
+
match: ["lotId", "status"],
|
|
2075
2091
|
matchOrder: 85,
|
|
2076
|
-
identity: "
|
|
2077
|
-
required: ["
|
|
2078
|
-
fields: {
|
|
2092
|
+
identity: "lotId",
|
|
2093
|
+
required: ["lotId", "status"],
|
|
2094
|
+
fields: { lotId: "string", status: "string", decidedBy: "string", reason: "string", decidedAt: "string", recordTime: "string" }
|
|
2079
2095
|
},
|
|
2080
2096
|
test: {
|
|
2081
2097
|
eventType: OP_EVENT.test,
|
|
@@ -2921,9 +2937,9 @@ var ObservedReducer = class {
|
|
|
2921
2937
|
}
|
|
2922
2938
|
case OP_EVENT.materialLot: {
|
|
2923
2939
|
const d = e.data;
|
|
2924
|
-
if (!d?.
|
|
2925
|
-
if (this.stale(`material-lot:${d.
|
|
2926
|
-
const parts = [...this.items.values()].filter((i) => i.epc === d.
|
|
2940
|
+
if (!d?.lotId || !d?.status) break;
|
|
2941
|
+
if (this.stale(`material-lot:${d.lotId}`, e)) return;
|
|
2942
|
+
const parts = [...this.items.values()].filter((i) => i.epc === d.lotId);
|
|
2927
2943
|
if (!parts.length) {
|
|
2928
2944
|
this.noteUnhandled(e, `${OP_EVENT.materialLot}:unknown-lot`);
|
|
2929
2945
|
break;
|
|
@@ -4367,7 +4383,14 @@ var FlowEngine = class {
|
|
|
4367
4383
|
parent: it.parent,
|
|
4368
4384
|
carriedBy: it.carriedBy,
|
|
4369
4385
|
expiry: it.expiry,
|
|
4370
|
-
ilmd: it.ilmd
|
|
4386
|
+
ilmd: it.ilmd,
|
|
4387
|
+
/*
|
|
4388
|
+
* 로트의 두 표준 칸 — ISA-95 `Disposition`(`nonconformance`)과 `Status`(`status`). 이 복사가 칸을 하나씩
|
|
4389
|
+
* 옮기는 자리라, 여기 없는 칸은 리듀서에 앉았어도 **스냅샷에 나오지 않는다**(2026-09-16 에 `status` 를
|
|
4390
|
+
* 넣다가 `nonconformance` 도 여기서 빠져 있던 것을 찾았다 — 자리는 있고 길이 없는 부류). 있을 때만 옮긴다.
|
|
4391
|
+
*/
|
|
4392
|
+
...it.nonconformance ? { nonconformance: it.nonconformance } : {},
|
|
4393
|
+
...it.status ? { status: it.status } : {}
|
|
4371
4394
|
});
|
|
4372
4395
|
}
|
|
4373
4396
|
for (const m of snap.equipment) {
|
|
@@ -6774,7 +6797,10 @@ var FlowEngine = class {
|
|
|
6774
6797
|
...i.uom ? { uom: i.uom } : {},
|
|
6775
6798
|
...i.quantities?.length ? { quantities: i.quantities } : {},
|
|
6776
6799
|
...i.expiry !== void 0 ? { expiry: i.expiry } : {},
|
|
6777
|
-
...i.ilmd ? { ilmd: i.ilmd } : {}
|
|
6800
|
+
...i.ilmd ? { ilmd: i.ilmd } : {},
|
|
6801
|
+
/* 로트의 두 표준 칸(§FlowItem) — 여기서 빠지면 리듀서·엔진에는 있고 스냅샷에는 없다. */
|
|
6802
|
+
...i.nonconformance ? { nonconformance: i.nonconformance } : {},
|
|
6803
|
+
...i.status ? { status: i.status } : {}
|
|
6778
6804
|
};
|
|
6779
6805
|
}
|
|
6780
6806
|
/**
|
|
@@ -7123,7 +7149,7 @@ var WmsKernel = class extends FlowEngine {
|
|
|
7123
7149
|
const requested = lines.reduce((s, l) => s + l.qty, 0);
|
|
7124
7150
|
const order = {
|
|
7125
7151
|
id,
|
|
7126
|
-
kind:
|
|
7152
|
+
kind: WMS_ORDER_KIND.outbound,
|
|
7127
7153
|
status: "created",
|
|
7128
7154
|
requested,
|
|
7129
7155
|
fulfilled: 0,
|
|
@@ -7159,7 +7185,7 @@ var WmsKernel = class extends FlowEngine {
|
|
|
7159
7185
|
}
|
|
7160
7186
|
if (chosenAll.length === 0) return this.makeShortLines(o);
|
|
7161
7187
|
this.reserve(chosenAll, BIZSTEP.storing);
|
|
7162
|
-
this.emit(transactionEvent({ eventTime: this.now(), action: "ADD", bizStep: BIZSTEP.picking, bizTransactionList: [{ type: BTT.
|
|
7188
|
+
this.emit(transactionEvent({ eventTime: this.now(), action: "ADD", bizStep: BIZSTEP.picking, bizTransactionList: [{ type: BTT.poc, bizTransaction: o.bizTransaction }], epcList: chosenAll.slice() }));
|
|
7163
7189
|
for (const epc of chosenAll) {
|
|
7164
7190
|
const it = this.items.get(epc);
|
|
7165
7191
|
const id = `task-${++this.taskSeq}`;
|
|
@@ -7310,7 +7336,7 @@ var WmsKernel = class extends FlowEngine {
|
|
|
7310
7336
|
const shpSeq = ++this.epcSeq;
|
|
7311
7337
|
const shipment = this.requireObjectId(`SHP-${shpSeq}`);
|
|
7312
7338
|
order.shipmentEpc = shipment;
|
|
7313
|
-
const soTxn = [{ type: BTT.
|
|
7339
|
+
const soTxn = [{ type: BTT.poc, bizTransaction: order.bizTransaction }];
|
|
7314
7340
|
this.aggregate(shipment, order.picked.slice(), { bizStep: BIZSTEP.packing, readPoint: staging.id, bizLocation: staging.id });
|
|
7315
7341
|
order.status = "packed";
|
|
7316
7342
|
this.emit(objectEvent({ eventTime, action: "OBSERVE", bizStep: BIZSTEP.staging_outbound, disposition: DISP.reserved, epcList: [shipment], readPoint: staging.id, bizLocation: staging.id, bizTransactionList: soTxn }));
|
|
@@ -7450,7 +7476,7 @@ var YmsKernel = class extends FlowEngine {
|
|
|
7450
7476
|
this.trailerCargo.set(trailer.epc, avail.slice(0, CARGO_PER_TRAILER).map((i) => i.epc));
|
|
7451
7477
|
}
|
|
7452
7478
|
this.reserve([trailer.epc], bizStep);
|
|
7453
|
-
this.emit(transactionEvent({ eventTime: this.now(), action: "ADD", bizStep, bizTransactionList: [{
|
|
7479
|
+
this.emit(transactionEvent({ eventTime: this.now(), action: "ADD", bizStep, bizTransactionList: [{ bizTransaction: o.bizTransaction }], epcList: [trailer.epc], readPoint: door.id }));
|
|
7454
7480
|
const dockKind = mode === "drop" ? "pull" : "spot-live";
|
|
7455
7481
|
const task = { id: `task-${++this.taskSeq}`, kind: dockKind, status: "created", itemEpc: trailer.epc, fromNode: trailer.location, toNode: door.id, resource: null, remainingMs: 0, durationMs: this.durationOf({ kind: dockKind, fromNode: trailer.location, toNode: door.id }, TRAVEL_MS2), orderId: o.id };
|
|
7456
7482
|
this.tasks.set(task.id, task);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@operato/twin-kernel",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Twin Domain Kernel — framework-agnostic, zero-dep (domain + sim + 3-channel contract). WMS/YMS/MES, EPCIS 2.0 · ISA-95.",
|
|
6
6
|
"publishConfig": {
|
|
@@ -28,6 +28,6 @@
|
|
|
28
28
|
"test": "node --test test/*.test.ts"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@operato/ops-contract": "^0.9.
|
|
31
|
+
"@operato/ops-contract": "^0.9.24"
|
|
32
32
|
}
|
|
33
33
|
}
|