@operato/twin-kernel 0.11.12 → 0.11.14
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/observed-reducer.js +4 -3
- package/dist-cjs/index.cjs +26 -19
- 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/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-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
|
*
|
|
@@ -1043,14 +1044,8 @@ var MES_BIZSTEP = {
|
|
|
1043
1044
|
// 원자재 수령
|
|
1044
1045
|
producing: "urn:epcglobal:cbv:bizstep:commissioning",
|
|
1045
1046
|
// 생산(제품 최초 생성)
|
|
1046
|
-
storing: "urn:epcglobal:cbv:bizstep:storing"
|
|
1047
|
+
storing: "urn:epcglobal:cbv:bizstep:storing"
|
|
1047
1048
|
// 완제품 저장
|
|
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
1049
|
};
|
|
1055
1050
|
var BTT_PRODORDER = "urn:epcglobal:cbv:btt:prodorder";
|
|
1056
1051
|
function sgtinUri(companyPrefix, itemRef, serial) {
|
|
@@ -2065,17 +2060,19 @@ var SPECS = {
|
|
|
2065
2060
|
/*
|
|
2066
2061
|
* **로트 상태** — ISA-95 `MaterialLot.Status`. 출하 승인(batch release)이 들어오는 문(§`OP_EVENT.materialLot`).
|
|
2067
2062
|
*
|
|
2068
|
-
* `disposition`(subjectId + decision) 과 필드가 겹치지 않는다 — 여기는 `
|
|
2069
|
-
*
|
|
2070
|
-
*
|
|
2063
|
+
* `disposition`(subjectId + decision) 과 필드가 겹치지 않는다 — 여기는 `lotId` + `status`. 정체 이름이 표준
|
|
2064
|
+
* `MaterialLotID` 인 이유가 하나 더 있다: 이 문은 `epc` 를 든 레코드를 EPCIS 어휘로 보고 받지 않는다
|
|
2065
|
+
* (§`operationalKindOf`). 값은 로트의 식별자(`ItemState.epc` 와 같은 값)다. 상태 낱말은 열려 있어 enum 이
|
|
2066
|
+
* 없다(오더 상태와 같은 규율). 로트 전체의 사실이므로 부분(`subLotId`)은 받지 않는다 — 부분마다 다른 상태가
|
|
2067
|
+
* 필요해지면 그것은 다른 사실이다.
|
|
2071
2068
|
*/
|
|
2072
2069
|
"material-lot": {
|
|
2073
2070
|
eventType: OP_EVENT.materialLot,
|
|
2074
|
-
match: ["
|
|
2071
|
+
match: ["lotId", "status"],
|
|
2075
2072
|
matchOrder: 85,
|
|
2076
|
-
identity: "
|
|
2077
|
-
required: ["
|
|
2078
|
-
fields: {
|
|
2073
|
+
identity: "lotId",
|
|
2074
|
+
required: ["lotId", "status"],
|
|
2075
|
+
fields: { lotId: "string", status: "string", decidedBy: "string", reason: "string", decidedAt: "string", recordTime: "string" }
|
|
2079
2076
|
},
|
|
2080
2077
|
test: {
|
|
2081
2078
|
eventType: OP_EVENT.test,
|
|
@@ -2921,9 +2918,9 @@ var ObservedReducer = class {
|
|
|
2921
2918
|
}
|
|
2922
2919
|
case OP_EVENT.materialLot: {
|
|
2923
2920
|
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.
|
|
2921
|
+
if (!d?.lotId || !d?.status) break;
|
|
2922
|
+
if (this.stale(`material-lot:${d.lotId}`, e)) return;
|
|
2923
|
+
const parts = [...this.items.values()].filter((i) => i.epc === d.lotId);
|
|
2927
2924
|
if (!parts.length) {
|
|
2928
2925
|
this.noteUnhandled(e, `${OP_EVENT.materialLot}:unknown-lot`);
|
|
2929
2926
|
break;
|
|
@@ -4367,7 +4364,14 @@ var FlowEngine = class {
|
|
|
4367
4364
|
parent: it.parent,
|
|
4368
4365
|
carriedBy: it.carriedBy,
|
|
4369
4366
|
expiry: it.expiry,
|
|
4370
|
-
ilmd: it.ilmd
|
|
4367
|
+
ilmd: it.ilmd,
|
|
4368
|
+
/*
|
|
4369
|
+
* 로트의 두 표준 칸 — ISA-95 `Disposition`(`nonconformance`)과 `Status`(`status`). 이 복사가 칸을 하나씩
|
|
4370
|
+
* 옮기는 자리라, 여기 없는 칸은 리듀서에 앉았어도 **스냅샷에 나오지 않는다**(2026-09-16 에 `status` 를
|
|
4371
|
+
* 넣다가 `nonconformance` 도 여기서 빠져 있던 것을 찾았다 — 자리는 있고 길이 없는 부류). 있을 때만 옮긴다.
|
|
4372
|
+
*/
|
|
4373
|
+
...it.nonconformance ? { nonconformance: it.nonconformance } : {},
|
|
4374
|
+
...it.status ? { status: it.status } : {}
|
|
4371
4375
|
});
|
|
4372
4376
|
}
|
|
4373
4377
|
for (const m of snap.equipment) {
|
|
@@ -6774,7 +6778,10 @@ var FlowEngine = class {
|
|
|
6774
6778
|
...i.uom ? { uom: i.uom } : {},
|
|
6775
6779
|
...i.quantities?.length ? { quantities: i.quantities } : {},
|
|
6776
6780
|
...i.expiry !== void 0 ? { expiry: i.expiry } : {},
|
|
6777
|
-
...i.ilmd ? { ilmd: i.ilmd } : {}
|
|
6781
|
+
...i.ilmd ? { ilmd: i.ilmd } : {},
|
|
6782
|
+
/* 로트의 두 표준 칸(§FlowItem) — 여기서 빠지면 리듀서·엔진에는 있고 스냅샷에는 없다. */
|
|
6783
|
+
...i.nonconformance ? { nonconformance: i.nonconformance } : {},
|
|
6784
|
+
...i.status ? { status: i.status } : {}
|
|
6778
6785
|
};
|
|
6779
6786
|
}
|
|
6780
6787
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@operato/twin-kernel",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.14",
|
|
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.22"
|
|
32
32
|
}
|
|
33
33
|
}
|