@freighttech/terminal-tracking 0.7.0
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/LICENSE +21 -0
- package/README.md +121 -0
- package/dist/generated/entities/terminal_config/index.js +53 -0
- package/dist/generated/entities/terminal_config/index.js.map +7 -0
- package/dist/generated/entities/terminal_event/index.js +59 -0
- package/dist/generated/entities/terminal_event/index.js.map +7 -0
- package/dist/generated/entities/terminal_tracking_job/index.js +37 -0
- package/dist/generated/entities/terminal_tracking_job/index.js.map +7 -0
- package/dist/generated/entities/terminal_vessel_visit/index.js +41 -0
- package/dist/generated/entities/terminal_vessel_visit/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +26 -0
- package/dist/generated/entities.ids.generated.js.map +7 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +7 -0
- package/dist/modules/terminal_tracking/acl.js +14 -0
- package/dist/modules/terminal_tracking/acl.js.map +7 -0
- package/dist/modules/terminal_tracking/api/openapi.js +27 -0
- package/dist/modules/terminal_tracking/api/openapi.js.map +7 -0
- package/dist/modules/terminal_tracking/api/terminal-configs/route.js +140 -0
- package/dist/modules/terminal_tracking/api/terminal-configs/route.js.map +7 -0
- package/dist/modules/terminal_tracking/api/terminal-configs/test/route.js +58 -0
- package/dist/modules/terminal_tracking/api/terminal-configs/test/route.js.map +7 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/details/route.js +109 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/details/route.js.map +7 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/poll/route.js +58 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/poll/route.js.map +7 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/route.js +189 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/route.js.map +7 -0
- package/dist/modules/terminal_tracking/api/utils.js +12 -0
- package/dist/modules/terminal_tracking/api/utils.js.map +7 -0
- package/dist/modules/terminal_tracking/api/vessel-visits/route.js +83 -0
- package/dist/modules/terminal_tracking/api/vessel-visits/route.js.map +7 -0
- package/dist/modules/terminal_tracking/backend/terminal-configs/page.js +669 -0
- package/dist/modules/terminal_tracking/backend/terminal-configs/page.js.map +7 -0
- package/dist/modules/terminal_tracking/backend/terminal-configs/page.meta.js +19 -0
- package/dist/modules/terminal_tracking/backend/terminal-configs/page.meta.js.map +7 -0
- package/dist/modules/terminal_tracking/backend/terminal-containers/page.js +275 -0
- package/dist/modules/terminal_tracking/backend/terminal-containers/page.js.map +7 -0
- package/dist/modules/terminal_tracking/backend/terminal-containers/page.meta.js +19 -0
- package/dist/modules/terminal_tracking/backend/terminal-containers/page.meta.js.map +7 -0
- package/dist/modules/terminal_tracking/ce.js +35 -0
- package/dist/modules/terminal_tracking/ce.js.map +7 -0
- package/dist/modules/terminal_tracking/commands/index.js +4 -0
- package/dist/modules/terminal_tracking/commands/index.js.map +7 -0
- package/dist/modules/terminal_tracking/commands/terminal-configs.js +107 -0
- package/dist/modules/terminal_tracking/commands/terminal-configs.js.map +7 -0
- package/dist/modules/terminal_tracking/commands/terminal-tracking.js +27 -0
- package/dist/modules/terminal_tracking/commands/terminal-tracking.js.map +7 -0
- package/dist/modules/terminal_tracking/commands/tracking-jobs.js +56 -0
- package/dist/modules/terminal_tracking/commands/tracking-jobs.js.map +7 -0
- package/dist/modules/terminal_tracking/components/ContainerDetailsDrawer.js +371 -0
- package/dist/modules/terminal_tracking/components/ContainerDetailsDrawer.js.map +7 -0
- package/dist/modules/terminal_tracking/data/entities.js +337 -0
- package/dist/modules/terminal_tracking/data/entities.js.map +7 -0
- package/dist/modules/terminal_tracking/data/validators.js +98 -0
- package/dist/modules/terminal_tracking/data/validators.js.map +7 -0
- package/dist/modules/terminal_tracking/di.js +39 -0
- package/dist/modules/terminal_tracking/di.js.map +7 -0
- package/dist/modules/terminal_tracking/encryption.js +14 -0
- package/dist/modules/terminal_tracking/encryption.js.map +7 -0
- package/dist/modules/terminal_tracking/events.js +45 -0
- package/dist/modules/terminal_tracking/events.js.map +7 -0
- package/dist/modules/terminal_tracking/i18n/de.json +175 -0
- package/dist/modules/terminal_tracking/i18n/en.json +178 -0
- package/dist/modules/terminal_tracking/i18n/es.json +175 -0
- package/dist/modules/terminal_tracking/i18n/pl.json +206 -0
- package/dist/modules/terminal_tracking/index.js +15 -0
- package/dist/modules/terminal_tracking/index.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/adapter.js +164 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/adapter.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/auth/basic.js +23 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/auth/basic.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/incos-semantics.js +146 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/incos-semantics.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/types.js +1 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/types.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/adapter.js +106 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/adapter.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/auth/token.js +120 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/auth/token.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/gct-semantics.js +77 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/gct-semantics.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/types.js +1 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/types.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/index.js +12 -0
- package/dist/modules/terminal_tracking/lib/adapters/index.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/adapter.js +121 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/adapter.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/auth/ropc.js +81 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/auth/ropc.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/http.js +66 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/http.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/n4-semantics.js +95 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/n4-semantics.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/data-table.js +70 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/data-table.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/vessel-data-table.js +44 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/vessel-data-table.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/proxy.js +15 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/proxy.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/types.js +1 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/types.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/zoned-time.js +27 -0
- package/dist/modules/terminal_tracking/lib/adapters/zoned-time.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/availability.js +40 -0
- package/dist/modules/terminal_tracking/lib/availability.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/ensure-schedule.js +51 -0
- package/dist/modules/terminal_tracking/lib/ensure-schedule.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/holds.js +240 -0
- package/dist/modules/terminal_tracking/lib/holds.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/logger.js +19 -0
- package/dist/modules/terminal_tracking/lib/logger.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/rate-limiter.js +30 -0
- package/dist/modules/terminal_tracking/lib/rate-limiter.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/stops.js +48 -0
- package/dist/modules/terminal_tracking/lib/stops.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/terminal-adapter.js +1 -0
- package/dist/modules/terminal_tracking/lib/terminal-adapter.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/totp.js +41 -0
- package/dist/modules/terminal_tracking/lib/totp.js.map +7 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260609120000_terminal_tracking.js +101 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260609120000_terminal_tracking.js.map +7 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260610120000_terminal_vessel_visits.js +39 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260610120000_terminal_vessel_visits.js.map +7 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260611120000_terminal_config_proxy.js +13 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260611120000_terminal_config_proxy.js.map +7 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260707120000_terminal_job_availability_markers.js +15 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260707120000_terminal_job_availability_markers.js.map +7 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260805120000_terminal_event_loaded_at.js +13 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260805120000_terminal_event_loaded_at.js.map +7 -0
- package/dist/modules/terminal_tracking/services/terminalMatcherService.js +61 -0
- package/dist/modules/terminal_tracking/services/terminalMatcherService.js.map +7 -0
- package/dist/modules/terminal_tracking/services/terminalRegistry.js +24 -0
- package/dist/modules/terminal_tracking/services/terminalRegistry.js.map +7 -0
- package/dist/modules/terminal_tracking/services/terminalTrackingService.js +687 -0
- package/dist/modules/terminal_tracking/services/terminalTrackingService.js.map +7 -0
- package/dist/modules/terminal_tracking/setup.js +23 -0
- package/dist/modules/terminal_tracking/setup.js.map +7 -0
- package/dist/modules/terminal_tracking/subscribers/terminal-tracking-job-initial-poll.js +22 -0
- package/dist/modules/terminal_tracking/subscribers/terminal-tracking-job-initial-poll.js.map +7 -0
- package/generated/entities/terminal_config/index.ts +36 -0
- package/generated/entities/terminal_event/index.ts +39 -0
- package/generated/entities/terminal_tracking_job/index.ts +28 -0
- package/generated/entities/terminal_vessel_visit/index.ts +30 -0
- package/generated/entities.ids.generated.ts +52 -0
- package/package.json +80 -0
- package/src/index.ts +44 -0
- package/src/modules/terminal_tracking/__integration__/TC-TRACK-301-gct-config-test-connection.spec.ts +66 -0
- package/src/modules/terminal_tracking/__integration__/TC-TRACK-317-bct-config-test-connection.spec.ts +68 -0
- package/src/modules/terminal_tracking/__integration__/helpers.ts +148 -0
- package/src/modules/terminal_tracking/__integration__/meta.ts +4 -0
- package/src/modules/terminal_tracking/acl.ts +10 -0
- package/src/modules/terminal_tracking/api/openapi.ts +28 -0
- package/src/modules/terminal_tracking/api/terminal-configs/route.ts +140 -0
- package/src/modules/terminal_tracking/api/terminal-configs/test/route.ts +64 -0
- package/src/modules/terminal_tracking/api/tracking-jobs/details/route.ts +116 -0
- package/src/modules/terminal_tracking/api/tracking-jobs/poll/route.ts +64 -0
- package/src/modules/terminal_tracking/api/tracking-jobs/route.ts +243 -0
- package/src/modules/terminal_tracking/api/utils.ts +10 -0
- package/src/modules/terminal_tracking/api/vessel-visits/route.ts +95 -0
- package/src/modules/terminal_tracking/backend/terminal-configs/page.meta.ts +16 -0
- package/src/modules/terminal_tracking/backend/terminal-configs/page.tsx +728 -0
- package/src/modules/terminal_tracking/backend/terminal-containers/page.meta.ts +16 -0
- package/src/modules/terminal_tracking/backend/terminal-containers/page.tsx +328 -0
- package/src/modules/terminal_tracking/ce.ts +31 -0
- package/src/modules/terminal_tracking/commands/index.ts +3 -0
- package/src/modules/terminal_tracking/commands/terminal-configs.ts +132 -0
- package/src/modules/terminal_tracking/commands/terminal-tracking.ts +34 -0
- package/src/modules/terminal_tracking/commands/tracking-jobs.ts +69 -0
- package/src/modules/terminal_tracking/components/ContainerDetailsDrawer.tsx +540 -0
- package/src/modules/terminal_tracking/data/entities.ts +386 -0
- package/src/modules/terminal_tracking/data/validators.ts +113 -0
- package/src/modules/terminal_tracking/di.ts +46 -0
- package/src/modules/terminal_tracking/encryption.ts +12 -0
- package/src/modules/terminal_tracking/events.ts +48 -0
- package/src/modules/terminal_tracking/i18n/de.json +175 -0
- package/src/modules/terminal_tracking/i18n/en.json +178 -0
- package/src/modules/terminal_tracking/i18n/es.json +175 -0
- package/src/modules/terminal_tracking/i18n/pl.json +206 -0
- package/src/modules/terminal_tracking/index.ts +13 -0
- package/src/modules/terminal_tracking/lib/__tests__/availability.test.ts +136 -0
- package/src/modules/terminal_tracking/lib/__tests__/ensure-schedule.test.ts +67 -0
- package/src/modules/terminal_tracking/lib/__tests__/holds.test.ts +73 -0
- package/src/modules/terminal_tracking/lib/__tests__/stops.test.ts +80 -0
- package/src/modules/terminal_tracking/lib/__tests__/totp.test.ts +38 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/__tests__/adapter.test.ts +196 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/__tests__/incos-semantics.test.ts +303 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/adapter.ts +219 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/auth/basic.ts +34 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/incos-semantics.ts +291 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/types.ts +113 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/__tests__/adapter.test.ts +238 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/__tests__/gct-semantics.test.ts +133 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/adapter.ts +152 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/auth/token.ts +219 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/gct-semantics.ts +136 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/types.ts +58 -0
- package/src/modules/terminal_tracking/lib/adapters/index.ts +16 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/adapter-proxy.test.ts +69 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/data-table.test.ts +179 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/http.test.ts +98 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/n4-semantics.test.ts +140 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/proxy.test.ts +19 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/vessel-data-table.test.ts +67 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/adapter.ts +163 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/auth/ropc.ts +104 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/http.ts +127 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/n4-semantics.ts +156 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/parsers/data-table.ts +102 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/parsers/vessel-data-table.ts +60 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/proxy.ts +24 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/types.ts +56 -0
- package/src/modules/terminal_tracking/lib/adapters/zoned-time.ts +65 -0
- package/src/modules/terminal_tracking/lib/availability.ts +119 -0
- package/src/modules/terminal_tracking/lib/ensure-schedule.ts +83 -0
- package/src/modules/terminal_tracking/lib/holds.ts +344 -0
- package/src/modules/terminal_tracking/lib/logger.ts +21 -0
- package/src/modules/terminal_tracking/lib/rate-limiter.ts +52 -0
- package/src/modules/terminal_tracking/lib/stops.ts +124 -0
- package/src/modules/terminal_tracking/lib/terminal-adapter.ts +136 -0
- package/src/modules/terminal_tracking/lib/totp.ts +63 -0
- package/src/modules/terminal_tracking/migrations/Migration20260609120000_terminal_tracking.ts +104 -0
- package/src/modules/terminal_tracking/migrations/Migration20260610120000_terminal_vessel_visits.ts +40 -0
- package/src/modules/terminal_tracking/migrations/Migration20260611120000_terminal_config_proxy.ts +11 -0
- package/src/modules/terminal_tracking/migrations/Migration20260707120000_terminal_job_availability_markers.ts +13 -0
- package/src/modules/terminal_tracking/migrations/Migration20260805120000_terminal_event_loaded_at.ts +16 -0
- package/src/modules/terminal_tracking/services/__tests__/availabilityEmit.test.ts +277 -0
- package/src/modules/terminal_tracking/services/__tests__/createJob.test.ts +59 -0
- package/src/modules/terminal_tracking/services/__tests__/pollAllBatch.test.ts +147 -0
- package/src/modules/terminal_tracking/services/__tests__/terminalMatcher.test.ts +70 -0
- package/src/modules/terminal_tracking/services/__tests__/vesselResolution.test.ts +453 -0
- package/src/modules/terminal_tracking/services/terminalMatcherService.ts +97 -0
- package/src/modules/terminal_tracking/services/terminalRegistry.ts +30 -0
- package/src/modules/terminal_tracking/services/terminalTrackingService.ts +912 -0
- package/src/modules/terminal_tracking/setup.ts +24 -0
- package/src/modules/terminal_tracking/subscribers/terminal-tracking-job-initial-poll.ts +32 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
{
|
|
2
|
+
"terminal_tracking": {
|
|
3
|
+
"title": "Terminal Tracking",
|
|
4
|
+
"stops": {
|
|
5
|
+
"title": "Restricciones de carga",
|
|
6
|
+
"vsl": "Sin carga a buque",
|
|
7
|
+
"road": "Sin recogida por carretera",
|
|
8
|
+
"rail": "Sin recogida por ferrocarril"
|
|
9
|
+
},
|
|
10
|
+
"nav": {
|
|
11
|
+
"group": "Terminal Tracking",
|
|
12
|
+
"terminal_configs": "Terminals",
|
|
13
|
+
"tracking_jobs": "Tracked Containers"
|
|
14
|
+
},
|
|
15
|
+
"errors": {
|
|
16
|
+
"tenant_required": "Tenant context is required",
|
|
17
|
+
"organization_required": "Organization context is required"
|
|
18
|
+
},
|
|
19
|
+
"terminal_config": {
|
|
20
|
+
"title": "Terminal Configurations",
|
|
21
|
+
"displayName": "Name",
|
|
22
|
+
"terminalCode": "Terminal code",
|
|
23
|
+
"adapterType": "Adapter",
|
|
24
|
+
"baseUrl": "API base URL",
|
|
25
|
+
"proxyUrl": "URL de proxy de la API (opcional)",
|
|
26
|
+
"unlocode": "UN/LOCODE",
|
|
27
|
+
"isActive": "Active",
|
|
28
|
+
"gctHint": "Clave (base32) mostrada en el panel de GCT junto al código QR. A partir de ella se calcula un código de un solo uso en cada inicio de sesión."
|
|
29
|
+
},
|
|
30
|
+
"tracking_job": {
|
|
31
|
+
"title": "Terminal Tracking Jobs",
|
|
32
|
+
"containerNumber": "Container",
|
|
33
|
+
"status": "Status",
|
|
34
|
+
"lastPollAt": "Last polled",
|
|
35
|
+
"details": "Container Details",
|
|
36
|
+
"noEvents": "No terminal events yet. Use \"Poll now\" to fetch.",
|
|
37
|
+
"leg": "Facility visit",
|
|
38
|
+
"recentErrors": "Recent poll errors",
|
|
39
|
+
"jobInfo": "Tracking",
|
|
40
|
+
"nextPollAt": "Next poll",
|
|
41
|
+
"retryCount": "Retries",
|
|
42
|
+
"jobId": "Job ID",
|
|
43
|
+
"actions": {
|
|
44
|
+
"details": "Details",
|
|
45
|
+
"poll": "Poll now"
|
|
46
|
+
},
|
|
47
|
+
"flash": {
|
|
48
|
+
"polled": "Consultado — {n} nuevos, {u} actualizados evento(s)"
|
|
49
|
+
},
|
|
50
|
+
"statuses": {
|
|
51
|
+
"active": "Activo",
|
|
52
|
+
"paused": "Pausado",
|
|
53
|
+
"deactivated": "Desactivado",
|
|
54
|
+
"failed": "Fallido",
|
|
55
|
+
"completed": "Completado"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"event": {
|
|
59
|
+
"source_badge": "Terminal",
|
|
60
|
+
"yardPosition": "Yard position",
|
|
61
|
+
"vgm": "VGM (kg)",
|
|
62
|
+
"visitPhase": "Visit phase",
|
|
63
|
+
"impediments": "Holds",
|
|
64
|
+
"seals": "Seals",
|
|
65
|
+
"eta": "ETA",
|
|
66
|
+
"etd": "ETD",
|
|
67
|
+
"ata": "ATA",
|
|
68
|
+
"atd": "ATD",
|
|
69
|
+
"gate_in": "Gate In",
|
|
70
|
+
"yard": "In Yard / Discharged",
|
|
71
|
+
"loaded": "Loaded",
|
|
72
|
+
"loadedAt": "Cargado el",
|
|
73
|
+
"departed": "Departed",
|
|
74
|
+
"ufvGkey": "Ufv_Gkey",
|
|
75
|
+
"rawData": "Raw terminal data"
|
|
76
|
+
},
|
|
77
|
+
"holds": {
|
|
78
|
+
"unknown": {
|
|
79
|
+
"label": "Bloqueo desconocido",
|
|
80
|
+
"description": "Bloqueo de terminal no reconocido. Consulte los detalles con la terminal.",
|
|
81
|
+
"resolution": "Contacte con la terminal para determinar cómo se levanta este bloqueo."
|
|
82
|
+
},
|
|
83
|
+
"cfs_appointment": {
|
|
84
|
+
"label": "Cita CFS",
|
|
85
|
+
"description": "Se aplica mientras se acepta un pedido de importación del almacén CFS.",
|
|
86
|
+
"resolution": "Se elimina automáticamente al completar el pedido y el trabajo del almacén."
|
|
87
|
+
},
|
|
88
|
+
"customs_import_permission": {
|
|
89
|
+
"label": "Permiso aduanero (importación)",
|
|
90
|
+
"description": "Se aplica sistemáticamente a todos los contenedores de importación pendientes de despacho aduanero.",
|
|
91
|
+
"resolution": "Se elimina automáticamente tras actualizar el número MRN mediante los códigos PCS polacos."
|
|
92
|
+
},
|
|
93
|
+
"customs_import_hold": {
|
|
94
|
+
"label": "Retención aduanera (importación)",
|
|
95
|
+
"description": "Aplicada manualmente por un agente de aduanas para escaneo, inspección o por un problema de despacho.",
|
|
96
|
+
"resolution": "Solo un agente de aduanas puede levantarla — contacte con la oficina de aduanas."
|
|
97
|
+
},
|
|
98
|
+
"line_import_permission": {
|
|
99
|
+
"label": "Permiso de la naviera (importación)",
|
|
100
|
+
"description": "Se aplica sistemáticamente a todos los contenedores de importación hasta que la naviera los libera.",
|
|
101
|
+
"resolution": "Se elimina cuando la naviera libera el contenedor mediante su número PIN."
|
|
102
|
+
},
|
|
103
|
+
"oog_hold": {
|
|
104
|
+
"label": "Retención OOG",
|
|
105
|
+
"description": "Se aplica a contenedores de importación fuera de gálibo que requieren permisos especiales.",
|
|
106
|
+
"resolution": "Debe ser verificada por Baltic Hub antes de la recogida; hasta entonces el contenedor no puede avisarse para retirada."
|
|
107
|
+
},
|
|
108
|
+
"cfs_hold": {
|
|
109
|
+
"label": "Retención CFS",
|
|
110
|
+
"description": "Se aplica mientras se acepta un pedido de exportación del almacén CFS.",
|
|
111
|
+
"resolution": "Se elimina automáticamente al completar el pedido y el trabajo del almacén."
|
|
112
|
+
},
|
|
113
|
+
"customs_export_permission": {
|
|
114
|
+
"label": "Permiso aduanero (exportación)",
|
|
115
|
+
"description": "Se aplica sistemáticamente a los contenedores de exportación pendientes de despacho aduanero.",
|
|
116
|
+
"resolution": "Se elimina automáticamente tras la actualización del MRN; debe levantarse antes del plazo de despacho aduanero."
|
|
117
|
+
},
|
|
118
|
+
"customs_export_hold": {
|
|
119
|
+
"label": "Retención aduanera (exportación)",
|
|
120
|
+
"description": "Aplicada manualmente por un agente de aduanas para escaneo, inspección o por un problema de despacho.",
|
|
121
|
+
"resolution": "Solo un agente de aduanas puede levantarla — contacte con la oficina de aduanas."
|
|
122
|
+
},
|
|
123
|
+
"unit_vgm_load_permission": {
|
|
124
|
+
"label": "Permiso de carga VGM",
|
|
125
|
+
"description": "Se aplica a todos los contenedores de exportación llenos que aún no tienen masa bruta verificada.",
|
|
126
|
+
"resolution": "Se elimina cuando se carga el peso VGM en Navis."
|
|
127
|
+
},
|
|
128
|
+
"dgd_hold": {
|
|
129
|
+
"label": "Retención DGD",
|
|
130
|
+
"description": "Se aplica automáticamente a todos los contenedores de exportación con carga IMO (peligrosa).",
|
|
131
|
+
"resolution": "Requiere la presentación del documento DGD (declaración de mercancías peligrosas)."
|
|
132
|
+
},
|
|
133
|
+
"scanning_hold": {
|
|
134
|
+
"label": "Retención de escaneo",
|
|
135
|
+
"description": "Aplicada manualmente por un agente de aduanas; el contenedor debe presentarse para escaneo.",
|
|
136
|
+
"resolution": "La levanta aduanas tras el escaneo (selección DCT_CFS_SCANNING)."
|
|
137
|
+
},
|
|
138
|
+
"empty_permission": {
|
|
139
|
+
"label": "Permiso (vacío)",
|
|
140
|
+
"description": "Se aplica sistemáticamente a todos los contenedores vacíos pendientes de una referencia de liberación.",
|
|
141
|
+
"resolution": "Se elimina al proporcionar el número EDO / de reserva de la naviera."
|
|
142
|
+
},
|
|
143
|
+
"missing_agent_permission": {
|
|
144
|
+
"label": "Falta permiso del agente",
|
|
145
|
+
"description": "Relacionado con un pago PCS inactivo. Actualmente no bloquea la carga al buque ni la recogida.",
|
|
146
|
+
"resolution": "Se elimina introduciendo el código de la naviera en el campo Agent One."
|
|
147
|
+
},
|
|
148
|
+
"technical_full_container": {
|
|
149
|
+
"label": "Técnico (contenedor lleno)",
|
|
150
|
+
"description": "Se aplica a todos los contenedores llenos de importación/exportación para el reconocimiento de caracteres OCR. No bloquea el movimiento.",
|
|
151
|
+
"resolution": "No requiere acción — solo informativo."
|
|
152
|
+
},
|
|
153
|
+
"technical_live_reefer": {
|
|
154
|
+
"label": "Técnico (reefer activo)",
|
|
155
|
+
"description": "Se aplica a todos los contenedores reefer llenos para apoyar el OCR. No bloquea las operaciones.",
|
|
156
|
+
"resolution": "No requiere acción — solo informativo."
|
|
157
|
+
},
|
|
158
|
+
"terminal_hold": {
|
|
159
|
+
"label": "Retención de terminal",
|
|
160
|
+
"description": "Se aplica por una irregularidad del contenedor (etiquetado incorrecto, vigas dobladas, etc.).",
|
|
161
|
+
"resolution": "Contacte con el Servicio de Atención al Cliente de Baltic Hub."
|
|
162
|
+
},
|
|
163
|
+
"czrm_hold": {
|
|
164
|
+
"label": "Retención CZRM",
|
|
165
|
+
"description": "Aplicada por la oficina de aduanas.",
|
|
166
|
+
"resolution": "Contacte directamente con la oficina de aduanas para levantarla."
|
|
167
|
+
},
|
|
168
|
+
"izrx_hold": {
|
|
169
|
+
"label": "Retención IZRX",
|
|
170
|
+
"description": "Aplicada por la oficina de aduanas.",
|
|
171
|
+
"resolution": "Contacte directamente con la oficina de aduanas para levantarla."
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
{
|
|
2
|
+
"terminal_tracking": {
|
|
3
|
+
"title": "Śledzenie terminali",
|
|
4
|
+
"stops": {
|
|
5
|
+
"title": "Ograniczenia załadunku",
|
|
6
|
+
"vsl": "Brak załadunku na statek",
|
|
7
|
+
"road": "Brak podjęcia drogowego",
|
|
8
|
+
"rail": "Brak podjęcia kolejowego"
|
|
9
|
+
},
|
|
10
|
+
"nav": {
|
|
11
|
+
"group": "Śledzenie terminali",
|
|
12
|
+
"terminal_configs": "Terminale",
|
|
13
|
+
"tracking_jobs": "Śledzone kontenery"
|
|
14
|
+
},
|
|
15
|
+
"errors": {
|
|
16
|
+
"tenant_required": "Wymagany jest kontekst najemcy",
|
|
17
|
+
"organization_required": "Wymagany jest kontekst organizacji"
|
|
18
|
+
},
|
|
19
|
+
"terminal_config": {
|
|
20
|
+
"title": "Konfiguracje terminali",
|
|
21
|
+
"displayName": "Nazwa",
|
|
22
|
+
"terminalCode": "Kod terminalu",
|
|
23
|
+
"adapterType": "Adapter",
|
|
24
|
+
"baseUrl": "Bazowy adres API",
|
|
25
|
+
"proxyUrl": "Adres proxy API (opcjonalnie)",
|
|
26
|
+
"unlocode": "UN/LOCODE",
|
|
27
|
+
"smdgCodes": "Kody SMDG (po przecinku)",
|
|
28
|
+
"bicCodes": "Kody BIC (po przecinku)",
|
|
29
|
+
"nameAliases": "Aliasy nazwy (po przecinku)",
|
|
30
|
+
"tokenUrl": "Adres URL tokenu",
|
|
31
|
+
"scope": "Zakres (scope)",
|
|
32
|
+
"clientId": "Identyfikator klienta",
|
|
33
|
+
"rateLimitRequests": "Limit zapytań",
|
|
34
|
+
"rateLimitWindowSeconds": "Okno (sekundy)",
|
|
35
|
+
"isActive": "Aktywny",
|
|
36
|
+
"unchanged": "bez zmian",
|
|
37
|
+
"credEditHint": "Pozostaw dane uwierzytelniające puste, aby ich nie zmieniać.",
|
|
38
|
+
"gctHint": "Klucz (base32) widoczny w panelu GCT obok kodu QR. Na jego podstawie przy każdym logowaniu obliczany jest aktualny kod jednorazowy.",
|
|
39
|
+
"section": {
|
|
40
|
+
"terminal": "Terminal",
|
|
41
|
+
"auth": "Uwierzytelnianie",
|
|
42
|
+
"matching": "Dopasowanie",
|
|
43
|
+
"advanced": "Zaawansowane"
|
|
44
|
+
},
|
|
45
|
+
"cred": {
|
|
46
|
+
"username": "Nazwa użytkownika",
|
|
47
|
+
"password": "Hasło",
|
|
48
|
+
"clientSecret": "Sekret klienta",
|
|
49
|
+
"companyCode": "Kod firmy",
|
|
50
|
+
"loginName": "Login",
|
|
51
|
+
"totpSecret": "Twój sekret 2FA"
|
|
52
|
+
},
|
|
53
|
+
"validation": {
|
|
54
|
+
"allCredentials": "Wprowadź wszystkie pola danych uwierzytelniających",
|
|
55
|
+
"credentialsRequired": "Dane uwierzytelniające są wymagane"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"tracking_job": {
|
|
59
|
+
"title": "Zadania śledzenia terminali",
|
|
60
|
+
"containerNumber": "Kontener",
|
|
61
|
+
"status": "Status",
|
|
62
|
+
"gateIn": "Wjazd",
|
|
63
|
+
"gateOut": "Wyjazd",
|
|
64
|
+
"holds": "Blokady",
|
|
65
|
+
"lastPollAt": "Ostatnie odpytanie",
|
|
66
|
+
"details": "Szczegóły kontenera",
|
|
67
|
+
"noEvents": "Brak zdarzeń terminalowych. Użyj „Odpytaj teraz”, aby pobrać.",
|
|
68
|
+
"leg": "Wizyta na terminalu",
|
|
69
|
+
"recentErrors": "Ostatnie błędy odpytania",
|
|
70
|
+
"jobInfo": "Śledzenie",
|
|
71
|
+
"nextPollAt": "Następne odpytanie",
|
|
72
|
+
"retryCount": "Ponowienia",
|
|
73
|
+
"jobId": "ID zadania",
|
|
74
|
+
"actions": {
|
|
75
|
+
"details": "Szczegóły",
|
|
76
|
+
"poll": "Odpytaj teraz"
|
|
77
|
+
},
|
|
78
|
+
"flash": {
|
|
79
|
+
"polled": "Odpytano — {n} nowych, {u} zaktualizowanych zdarzeń"
|
|
80
|
+
},
|
|
81
|
+
"statuses": {
|
|
82
|
+
"active": "Aktywny",
|
|
83
|
+
"paused": "Wstrzymany",
|
|
84
|
+
"deactivated": "Dezaktywowany",
|
|
85
|
+
"failed": "Błąd",
|
|
86
|
+
"completed": "Zakończony"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"event": {
|
|
90
|
+
"source_badge": "Terminal",
|
|
91
|
+
"yardPosition": "Pozycja na placu",
|
|
92
|
+
"vgm": "VGM (kg)",
|
|
93
|
+
"visitPhase": "Faza wizyty",
|
|
94
|
+
"impediments": "Blokady",
|
|
95
|
+
"seals": "Plomby",
|
|
96
|
+
"eta": "ETA",
|
|
97
|
+
"etd": "ETD",
|
|
98
|
+
"ata": "ATA",
|
|
99
|
+
"atd": "ATD",
|
|
100
|
+
"gate_in": "Wjazd (brama)",
|
|
101
|
+
"yard": "Na placu / rozładowany",
|
|
102
|
+
"loaded": "Załadowany",
|
|
103
|
+
"loadedAt": "Data załadunku",
|
|
104
|
+
"departed": "Wyjazd",
|
|
105
|
+
"ufvGkey": "Ufv_Gkey",
|
|
106
|
+
"rawData": "Surowe dane terminalu"
|
|
107
|
+
},
|
|
108
|
+
"holds": {
|
|
109
|
+
"unknown": {
|
|
110
|
+
"label": "Nieznana blokada",
|
|
111
|
+
"description": "Nierozpoznana blokada terminalowa. Szczegóły uzyskasz w terminalu.",
|
|
112
|
+
"resolution": "Skontaktuj się z terminalem, aby ustalić sposób zdjęcia blokady."
|
|
113
|
+
},
|
|
114
|
+
"cfs_appointment": {
|
|
115
|
+
"label": "Awizacja CFS",
|
|
116
|
+
"description": "Nakładana podczas przyjmowania zlecenia importowego przez magazyn CFS.",
|
|
117
|
+
"resolution": "Zdejmowana automatycznie po zrealizowaniu zlecenia i pracy magazynu."
|
|
118
|
+
},
|
|
119
|
+
"customs_import_permission": {
|
|
120
|
+
"label": "Pozwolenie celne (import)",
|
|
121
|
+
"description": "Nakładana systemowo na wszystkie kontenery importowe oczekujące na zwolnienie celne.",
|
|
122
|
+
"resolution": "Zdejmowana automatycznie po aktualizacji numeru MRN przy użyciu polskich kodów PCS."
|
|
123
|
+
},
|
|
124
|
+
"customs_import_hold": {
|
|
125
|
+
"label": "Blokada celna (import)",
|
|
126
|
+
"description": "Nakładana ręcznie przez funkcjonariusza celnego w celu skanowania, kontroli lub z powodu problemu z odprawą.",
|
|
127
|
+
"resolution": "Może ją zdjąć wyłącznie funkcjonariusz celny — skontaktuj się z urzędem celnym."
|
|
128
|
+
},
|
|
129
|
+
"line_import_permission": {
|
|
130
|
+
"label": "Pozwolenie armatora (import)",
|
|
131
|
+
"description": "Nakładana systemowo na wszystkie kontenery importowe do czasu zwolnienia przez armatora.",
|
|
132
|
+
"resolution": "Zdejmowana po zwolnieniu kontenera przez armatora numerem PIN."
|
|
133
|
+
},
|
|
134
|
+
"oog_hold": {
|
|
135
|
+
"label": "Blokada OOG",
|
|
136
|
+
"description": "Nakładana na ponadgabarytowe kontenery importowe wymagające specjalnych zezwoleń.",
|
|
137
|
+
"resolution": "Wymaga weryfikacji przez Baltic Hub przed odbiorem; do tego czasu kontener nie może zostać awizowany do odbioru."
|
|
138
|
+
},
|
|
139
|
+
"cfs_hold": {
|
|
140
|
+
"label": "Blokada CFS",
|
|
141
|
+
"description": "Nakładana podczas przyjmowania zlecenia eksportowego przez magazyn CFS.",
|
|
142
|
+
"resolution": "Zdejmowana automatycznie po zrealizowaniu zlecenia i pracy magazynu."
|
|
143
|
+
},
|
|
144
|
+
"customs_export_permission": {
|
|
145
|
+
"label": "Pozwolenie celne (eksport)",
|
|
146
|
+
"description": "Nakładana systemowo na kontenery eksportowe oczekujące na zwolnienie celne.",
|
|
147
|
+
"resolution": "Zdejmowana automatycznie po aktualizacji MRN; musi zostać zdjęta przed terminem odprawy celnej."
|
|
148
|
+
},
|
|
149
|
+
"customs_export_hold": {
|
|
150
|
+
"label": "Blokada celna (eksport)",
|
|
151
|
+
"description": "Nakładana ręcznie przez funkcjonariusza celnego w celu skanowania, kontroli lub z powodu problemu z odprawą.",
|
|
152
|
+
"resolution": "Może ją zdjąć wyłącznie funkcjonariusz celny — skontaktuj się z urzędem celnym."
|
|
153
|
+
},
|
|
154
|
+
"unit_vgm_load_permission": {
|
|
155
|
+
"label": "Pozwolenie VGM na załadunek",
|
|
156
|
+
"description": "Nakładana na wszystkie pełne kontenery eksportowe bez zweryfikowanej masy brutto (VGM).",
|
|
157
|
+
"resolution": "Zdejmowana po wprowadzeniu masy VGM do systemu Navis."
|
|
158
|
+
},
|
|
159
|
+
"dgd_hold": {
|
|
160
|
+
"label": "Blokada DGD",
|
|
161
|
+
"description": "Nakładana automatycznie na wszystkie kontenery eksportowe z ładunkiem IMO (niebezpiecznym).",
|
|
162
|
+
"resolution": "Wymaga złożenia dokumentu DGD (deklaracji ładunku niebezpiecznego)."
|
|
163
|
+
},
|
|
164
|
+
"scanning_hold": {
|
|
165
|
+
"label": "Blokada skanowania",
|
|
166
|
+
"description": "Nakładana ręcznie przez funkcjonariusza celnego; kontener musi zostać przedstawiony do skanowania.",
|
|
167
|
+
"resolution": "Zdejmowana przez służby celne po skanowaniu (wybór DCT_CFS_SCANNING)."
|
|
168
|
+
},
|
|
169
|
+
"empty_permission": {
|
|
170
|
+
"label": "Pozwolenie (pusty)",
|
|
171
|
+
"description": "Nakładana systemowo na wszystkie puste kontenery oczekujące na referencję zwolnienia.",
|
|
172
|
+
"resolution": "Zdejmowana po podaniu numeru EDO / bookingu od armatora."
|
|
173
|
+
},
|
|
174
|
+
"missing_agent_permission": {
|
|
175
|
+
"label": "Brak pozwolenia agenta",
|
|
176
|
+
"description": "Dotyczy nieaktywnej płatności PCS. Obecnie nie blokuje załadunku na statek ani odbioru.",
|
|
177
|
+
"resolution": "Zdejmowana po wpisaniu kodu armatora w polu Agent One."
|
|
178
|
+
},
|
|
179
|
+
"technical_full_container": {
|
|
180
|
+
"label": "Techniczna (pełny kontener)",
|
|
181
|
+
"description": "Nakładana na wszystkie pełne kontenery importowe/eksportowe w celu obsługi rozpoznawania znaków OCR. Nie blokuje ruchu.",
|
|
182
|
+
"resolution": "Nie wymaga działań — wyłącznie informacyjna."
|
|
183
|
+
},
|
|
184
|
+
"technical_live_reefer": {
|
|
185
|
+
"label": "Techniczna (aktywny reefer)",
|
|
186
|
+
"description": "Nakładana na wszystkie pełne kontenery chłodnicze w celu obsługi OCR. Nie blokuje operacji.",
|
|
187
|
+
"resolution": "Nie wymaga działań — wyłącznie informacyjna."
|
|
188
|
+
},
|
|
189
|
+
"terminal_hold": {
|
|
190
|
+
"label": "Blokada terminalowa",
|
|
191
|
+
"description": "Nakładana z powodu nieprawidłowości kontenera (błędne oznakowanie, wygięte belki kontenera itp.).",
|
|
192
|
+
"resolution": "Skontaktuj się z Biurem Obsługi Klienta Baltic Hub."
|
|
193
|
+
},
|
|
194
|
+
"czrm_hold": {
|
|
195
|
+
"label": "Blokada CZRM",
|
|
196
|
+
"description": "Nakładana przez urząd celny.",
|
|
197
|
+
"resolution": "Skontaktuj się bezpośrednio z urzędem celnym w celu jej zdjęcia."
|
|
198
|
+
},
|
|
199
|
+
"izrx_hold": {
|
|
200
|
+
"label": "Blokada IZRX",
|
|
201
|
+
"description": "Nakładana przez urząd celny.",
|
|
202
|
+
"resolution": "Skontaktuj się bezpośrednio z urzędem celnym w celu jej zdjęcia."
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import "./commands/index.js";
|
|
2
|
+
const metadata = {
|
|
3
|
+
name: "terminal_tracking",
|
|
4
|
+
title: "Terminal Tracking",
|
|
5
|
+
version: "0.1.0",
|
|
6
|
+
description: "Container terminal (Navis N4) tracking with per-terminal config, periodic polling, and events.",
|
|
7
|
+
author: "FreightTech",
|
|
8
|
+
license: "Proprietary"
|
|
9
|
+
};
|
|
10
|
+
import { features } from "./acl.js";
|
|
11
|
+
export {
|
|
12
|
+
features,
|
|
13
|
+
metadata
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/terminal_tracking/index.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ModuleInfo } from '@open-mercato/shared/modules/registry'\nimport './commands'\n\nexport const metadata: ModuleInfo = {\n name: 'terminal_tracking',\n title: 'Terminal Tracking',\n version: '0.1.0',\n description: 'Container terminal (Navis N4) tracking with per-terminal config, periodic polling, and events.',\n author: 'FreightTech',\n license: 'Proprietary',\n}\n\nexport { features } from './acl'\n"],
|
|
5
|
+
"mappings": "AACA,OAAO;AAEA,MAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,SAAS;AACX;AAEA,SAAS,gBAAgB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { basicAuthHeader, BctAuthError } from "./auth/basic.js";
|
|
2
|
+
import { mapContainerToEvents, normalizeIncosVesselVisit, splitVisitRef } from "./incos-semantics.js";
|
|
3
|
+
import { n4Request } from "../n4/http.js";
|
|
4
|
+
import { terminalLogger } from "../../logger.js";
|
|
5
|
+
function joinUrl(base, path) {
|
|
6
|
+
return `${base.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
|
|
7
|
+
}
|
|
8
|
+
class BctTerminalAdapter {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.adapterType = "bct";
|
|
11
|
+
this.defaultEndpoints = {
|
|
12
|
+
// INCOS's container-lookup base occupies the generic `unit` slot; the
|
|
13
|
+
// container number is appended as a path segment per request.
|
|
14
|
+
unit: "/rest-container/container",
|
|
15
|
+
// Vessel-visit lookup base; vesselCode + voyage are appended per request.
|
|
16
|
+
// Enrichment only runs when the TerminalConfig also sets `endpoints.vessel`
|
|
17
|
+
// (the service gates on it) — this is the path used when it does.
|
|
18
|
+
vessel: "/rest-vesselvisit/vesselvisit"
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
containerUrl(containerNumber, config) {
|
|
22
|
+
const path = config.endpoints?.unit?.trim() || this.defaultEndpoints.unit;
|
|
23
|
+
return `${joinUrl(config.baseUrl, path)}/${encodeURIComponent(containerNumber)}`;
|
|
24
|
+
}
|
|
25
|
+
vesselUrl(vesselCode, voyage, config) {
|
|
26
|
+
const path = config.endpoints?.vessel?.trim() || this.defaultEndpoints.vessel;
|
|
27
|
+
return `${joinUrl(config.baseUrl, path)}/${encodeURIComponent(vesselCode)}/${encodeURIComponent(voyage)}`;
|
|
28
|
+
}
|
|
29
|
+
async getContainer(containerNumber, config) {
|
|
30
|
+
const { status, ok, text } = await n4Request(
|
|
31
|
+
this.containerUrl(containerNumber, config),
|
|
32
|
+
{
|
|
33
|
+
method: "GET",
|
|
34
|
+
headers: {
|
|
35
|
+
Authorization: basicAuthHeader(config),
|
|
36
|
+
Accept: "application/json"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{ proxyUrl: config.proxyUrl, label: `${config.terminalCode} container` }
|
|
40
|
+
);
|
|
41
|
+
if (status === 401 || status === 403) {
|
|
42
|
+
throw new BctAuthError(`INCOS container lookup unauthorized (${status}) for ${config.terminalCode}`);
|
|
43
|
+
}
|
|
44
|
+
if (!ok) {
|
|
45
|
+
throw new Error(`INCOS container lookup failed (${status}) for ${config.terminalCode}`);
|
|
46
|
+
}
|
|
47
|
+
let parsed;
|
|
48
|
+
try {
|
|
49
|
+
parsed = JSON.parse(text);
|
|
50
|
+
} catch {
|
|
51
|
+
throw new Error(`INCOS container response was not valid JSON for ${config.terminalCode}`);
|
|
52
|
+
}
|
|
53
|
+
if (String(parsed.status ?? "").toUpperCase() !== "SUCCESS") return null;
|
|
54
|
+
const data = parsed.data;
|
|
55
|
+
if (!data || !data.container_nbr) return null;
|
|
56
|
+
return data;
|
|
57
|
+
}
|
|
58
|
+
async fetchEvents(input) {
|
|
59
|
+
const { containerNumber, config } = input;
|
|
60
|
+
const container = await this.getContainer(containerNumber, config);
|
|
61
|
+
const events = container ? mapContainerToEvents(container, config) : [];
|
|
62
|
+
terminalLogger.debug("bct fetchEvents", {
|
|
63
|
+
terminalCode: config.terminalCode,
|
|
64
|
+
container: containerNumber,
|
|
65
|
+
found: Boolean(container),
|
|
66
|
+
events: events.length
|
|
67
|
+
});
|
|
68
|
+
return { events, containerNumber };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* INCOS has no batch-by-container-number call, so fetch each container in turn.
|
|
72
|
+
* Kept as a distinct method (rather than falling through to per-container in
|
|
73
|
+
* the service) so the scheduler's batch path stays a single call site; the
|
|
74
|
+
* per-terminal rate limiter still throttles the underlying requests. A single
|
|
75
|
+
* container's failure is isolated so one bad number can't sink the whole poll —
|
|
76
|
+
* except an auth error, which is fatal to the batch (bad credentials would just
|
|
77
|
+
* repeat for every container).
|
|
78
|
+
*/
|
|
79
|
+
async fetchEventsBatch(input) {
|
|
80
|
+
const { containerNumbers, config } = input;
|
|
81
|
+
if (containerNumbers.length === 0) return { events: [] };
|
|
82
|
+
const events = [];
|
|
83
|
+
for (const containerNumber of containerNumbers) {
|
|
84
|
+
try {
|
|
85
|
+
const result = await this.fetchEvents({ containerNumber, config });
|
|
86
|
+
events.push(...result.events);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
if (err instanceof BctAuthError) throw err;
|
|
89
|
+
terminalLogger.warn("bct fetchEventsBatch: container failed", {
|
|
90
|
+
terminalCode: config.terminalCode,
|
|
91
|
+
container: containerNumber,
|
|
92
|
+
message: err instanceof Error ? err.message : String(err)
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { events };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Resolve a vessel visit for a `CODE/VOY` ref (as produced by the container
|
|
100
|
+
* mapping's `visitRefIn`/`visitRefOut`). INCOS keys visits by (vesselCode,
|
|
101
|
+
* voyage), so the ref is split back into the two path segments. Returns null
|
|
102
|
+
* when the ref is malformed or INCOS reports no such visit (or its per-caller
|
|
103
|
+
* vessel-lookup rate limit is hit — an ERROR envelope). Vessel-visit dates are
|
|
104
|
+
* `YYYY-MM-DD HH:MM:SS`, parsed by `normalizeIncosVesselVisit`.
|
|
105
|
+
*/
|
|
106
|
+
async fetchVesselVisit(input) {
|
|
107
|
+
const { visitRef, config } = input;
|
|
108
|
+
const parts = splitVisitRef(visitRef);
|
|
109
|
+
if (!parts) return null;
|
|
110
|
+
const { status, ok, text } = await n4Request(
|
|
111
|
+
this.vesselUrl(parts.vesselCode, parts.voyage, config),
|
|
112
|
+
{ method: "GET", headers: { Authorization: basicAuthHeader(config), Accept: "application/json" } },
|
|
113
|
+
{ proxyUrl: config.proxyUrl, label: `${config.terminalCode} vesselvisit` }
|
|
114
|
+
);
|
|
115
|
+
if (status === 401 || status === 403) {
|
|
116
|
+
throw new BctAuthError(`INCOS vessel lookup unauthorized (${status}) for ${config.terminalCode}`);
|
|
117
|
+
}
|
|
118
|
+
if (!ok) {
|
|
119
|
+
throw new Error(`INCOS vessel lookup failed (${status}) for ${config.terminalCode}`);
|
|
120
|
+
}
|
|
121
|
+
let parsed;
|
|
122
|
+
try {
|
|
123
|
+
parsed = JSON.parse(text);
|
|
124
|
+
} catch {
|
|
125
|
+
throw new Error(`INCOS vessel response was not valid JSON for ${config.terminalCode}`);
|
|
126
|
+
}
|
|
127
|
+
if (String(parsed.status ?? "").toUpperCase() !== "SUCCESS" || !parsed.data) return null;
|
|
128
|
+
return normalizeIncosVesselVisit(parsed.data, visitRef);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* INCOS has no ping/health route, so probe the container endpoint with a
|
|
132
|
+
* placeholder number. Verified live: a wrong password returns HTTP 401, while
|
|
133
|
+
* an unknown container returns HTTP 200 with a SUCCESS envelope of nulls — so
|
|
134
|
+
* a 401/403 means the Basic credentials are wrong and any other outcome proves
|
|
135
|
+
* the host is reachable and the credentials are accepted. Missing credentials
|
|
136
|
+
* surface via `basicAuthHeader` throwing before any request.
|
|
137
|
+
*/
|
|
138
|
+
async testConnection(config) {
|
|
139
|
+
const started = Date.now();
|
|
140
|
+
try {
|
|
141
|
+
const probe = "TEST0000000";
|
|
142
|
+
const { status } = await n4Request(
|
|
143
|
+
this.containerUrl(probe, config),
|
|
144
|
+
{ method: "GET", headers: { Authorization: basicAuthHeader(config), Accept: "application/json" } },
|
|
145
|
+
{ proxyUrl: config.proxyUrl, label: `${config.terminalCode} test`, retries: 0 }
|
|
146
|
+
);
|
|
147
|
+
if (status === 401 || status === 403) {
|
|
148
|
+
return {
|
|
149
|
+
success: false,
|
|
150
|
+
message: `Authentication rejected (${status}) \u2014 check username/password`,
|
|
151
|
+
latencyMs: Date.now() - started
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return { success: true, message: `Reachable and authenticated (HTTP ${status})`, latencyMs: Date.now() - started };
|
|
155
|
+
} catch (err) {
|
|
156
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
157
|
+
return { success: false, message, latencyMs: Date.now() - started };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
export {
|
|
162
|
+
BctTerminalAdapter
|
|
163
|
+
};
|
|
164
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/terminal_tracking/lib/adapters/bct/adapter.ts"],
|
|
4
|
+
"sourcesContent": ["import type {\n TerminalAdapter,\n TerminalFetchResult,\n TerminalFetchedEvent,\n TerminalAdapterTestResult,\n ResolvedTerminalConfig,\n NormalizedVesselVisit,\n} from '../../terminal-adapter'\nimport type { IncosContainer, IncosContainerResponse, IncosVesselVisitResponse } from './types'\nimport { basicAuthHeader, BctAuthError } from './auth/basic'\nimport { mapContainerToEvents, normalizeIncosVesselVisit, splitVisitRef } from './incos-semantics'\nimport { n4Request } from '../n4/http'\nimport { terminalLogger } from '../../logger'\n\nfunction joinUrl(base: string, path: string): string {\n return `${base.replace(/\\/$/, '')}/${path.replace(/^\\//, '')}`\n}\n\n/**\n * Config-driven adapter for the INCOS API that fronts BCT (Ba\u0142tycki Terminal\n * Kontenerowy, Gdynia). One instance serves every INCOS terminal configured with\n * `adapterType: 'bct'`; per-terminal differences live in the TerminalConfig.\n *\n * Differences from the N4 adapter that shape this code:\n * - Auth is plain HTTP Basic (see ./auth/basic.ts), not an OAuth2 Bearer grant \u2014\n * there is no token endpoint or cache; the header is rebuilt per request.\n * - The container lookup is a per-container path GET (`/rest-container/container/\n * {nbr}`) returning a single snapshot, so `fetchEventsBatch` loops\n * `fetchEvents` (bounded upstream by the per-terminal limiter), like GCT.\n * - INCOS keys a vessel visit on (vessel, voyage), so the container mapping packs\n * both into the visit ref (`CODE/VOY`) and `fetchVesselVisit` splits it back;\n * enrichment runs only when the TerminalConfig sets `endpoints.vessel`.\n */\nexport class BctTerminalAdapter implements TerminalAdapter {\n readonly adapterType = 'bct'\n\n readonly defaultEndpoints = {\n // INCOS's container-lookup base occupies the generic `unit` slot; the\n // container number is appended as a path segment per request.\n unit: '/rest-container/container',\n // Vessel-visit lookup base; vesselCode + voyage are appended per request.\n // Enrichment only runs when the TerminalConfig also sets `endpoints.vessel`\n // (the service gates on it) \u2014 this is the path used when it does.\n vessel: '/rest-vesselvisit/vesselvisit',\n }\n\n private containerUrl(containerNumber: string, config: ResolvedTerminalConfig): string {\n const path = config.endpoints?.unit?.trim() || this.defaultEndpoints.unit\n return `${joinUrl(config.baseUrl, path)}/${encodeURIComponent(containerNumber)}`\n }\n\n private vesselUrl(vesselCode: string, voyage: string, config: ResolvedTerminalConfig): string {\n const path = config.endpoints?.vessel?.trim() || this.defaultEndpoints.vessel\n return `${joinUrl(config.baseUrl, path)}/${encodeURIComponent(vesselCode)}/${encodeURIComponent(voyage)}`\n }\n\n private async getContainer(\n containerNumber: string,\n config: ResolvedTerminalConfig,\n ): Promise<IncosContainer | null> {\n const { status, ok, text } = await n4Request(\n this.containerUrl(containerNumber, config),\n {\n method: 'GET',\n headers: {\n Authorization: basicAuthHeader(config),\n Accept: 'application/json',\n },\n },\n { proxyUrl: config.proxyUrl, label: `${config.terminalCode} container` },\n )\n\n if (status === 401 || status === 403) {\n throw new BctAuthError(`INCOS container lookup unauthorized (${status}) for ${config.terminalCode}`)\n }\n if (!ok) {\n throw new Error(`INCOS container lookup failed (${status}) for ${config.terminalCode}`)\n }\n\n let parsed: IncosContainerResponse\n try {\n parsed = JSON.parse(text) as IncosContainerResponse\n } catch {\n throw new Error(`INCOS container response was not valid JSON for ${config.terminalCode}`)\n }\n\n // An unknown container does NOT error: INCOS echoes it back as a SUCCESS\n // envelope with the number filled in and every other field null (observed\n // live) \u2014 so the timestamp-gating in `mapContainerToEvents` yields no events\n // and the job keeps polling. A genuine ERROR envelope (bad request etc.) is\n // treated the same \"not found \u2192 no events\" way rather than thrown, so one odd\n // response can't sink a poll. (Bad credentials surface earlier as a 401.)\n if (String(parsed.status ?? '').toUpperCase() !== 'SUCCESS') return null\n const data = parsed.data\n if (!data || !data.container_nbr) return null\n return data\n }\n\n async fetchEvents(input: {\n containerNumber: string\n config: ResolvedTerminalConfig\n }): Promise<TerminalFetchResult> {\n const { containerNumber, config } = input\n const container = await this.getContainer(containerNumber, config)\n const events = container ? mapContainerToEvents(container, config) : []\n\n terminalLogger.debug('bct fetchEvents', {\n terminalCode: config.terminalCode,\n container: containerNumber,\n found: Boolean(container),\n events: events.length,\n })\n\n return { events, containerNumber }\n }\n\n /**\n * INCOS has no batch-by-container-number call, so fetch each container in turn.\n * Kept as a distinct method (rather than falling through to per-container in\n * the service) so the scheduler's batch path stays a single call site; the\n * per-terminal rate limiter still throttles the underlying requests. A single\n * container's failure is isolated so one bad number can't sink the whole poll \u2014\n * except an auth error, which is fatal to the batch (bad credentials would just\n * repeat for every container).\n */\n async fetchEventsBatch(input: {\n containerNumbers: string[]\n config: ResolvedTerminalConfig\n }): Promise<{ events: TerminalFetchedEvent[] }> {\n const { containerNumbers, config } = input\n if (containerNumbers.length === 0) return { events: [] }\n\n const events: TerminalFetchedEvent[] = []\n for (const containerNumber of containerNumbers) {\n try {\n const result = await this.fetchEvents({ containerNumber, config })\n events.push(...result.events)\n } catch (err) {\n if (err instanceof BctAuthError) throw err\n terminalLogger.warn('bct fetchEventsBatch: container failed', {\n terminalCode: config.terminalCode,\n container: containerNumber,\n message: err instanceof Error ? err.message : String(err),\n })\n }\n }\n return { events }\n }\n\n /**\n * Resolve a vessel visit for a `CODE/VOY` ref (as produced by the container\n * mapping's `visitRefIn`/`visitRefOut`). INCOS keys visits by (vesselCode,\n * voyage), so the ref is split back into the two path segments. Returns null\n * when the ref is malformed or INCOS reports no such visit (or its per-caller\n * vessel-lookup rate limit is hit \u2014 an ERROR envelope). Vessel-visit dates are\n * `YYYY-MM-DD HH:MM:SS`, parsed by `normalizeIncosVesselVisit`.\n */\n async fetchVesselVisit(input: {\n visitRef: string\n config: ResolvedTerminalConfig\n }): Promise<NormalizedVesselVisit | null> {\n const { visitRef, config } = input\n const parts = splitVisitRef(visitRef)\n if (!parts) return null\n\n const { status, ok, text } = await n4Request(\n this.vesselUrl(parts.vesselCode, parts.voyage, config),\n { method: 'GET', headers: { Authorization: basicAuthHeader(config), Accept: 'application/json' } },\n { proxyUrl: config.proxyUrl, label: `${config.terminalCode} vesselvisit` },\n )\n\n if (status === 401 || status === 403) {\n throw new BctAuthError(`INCOS vessel lookup unauthorized (${status}) for ${config.terminalCode}`)\n }\n if (!ok) {\n throw new Error(`INCOS vessel lookup failed (${status}) for ${config.terminalCode}`)\n }\n\n let parsed: IncosVesselVisitResponse\n try {\n parsed = JSON.parse(text) as IncosVesselVisitResponse\n } catch {\n throw new Error(`INCOS vessel response was not valid JSON for ${config.terminalCode}`)\n }\n if (String(parsed.status ?? '').toUpperCase() !== 'SUCCESS' || !parsed.data) return null\n return normalizeIncosVesselVisit(parsed.data, visitRef)\n }\n\n /**\n * INCOS has no ping/health route, so probe the container endpoint with a\n * placeholder number. Verified live: a wrong password returns HTTP 401, while\n * an unknown container returns HTTP 200 with a SUCCESS envelope of nulls \u2014 so\n * a 401/403 means the Basic credentials are wrong and any other outcome proves\n * the host is reachable and the credentials are accepted. Missing credentials\n * surface via `basicAuthHeader` throwing before any request.\n */\n async testConnection(config: ResolvedTerminalConfig): Promise<TerminalAdapterTestResult> {\n const started = Date.now()\n try {\n const probe = 'TEST0000000'\n const { status } = await n4Request(\n this.containerUrl(probe, config),\n { method: 'GET', headers: { Authorization: basicAuthHeader(config), Accept: 'application/json' } },\n { proxyUrl: config.proxyUrl, label: `${config.terminalCode} test`, retries: 0 },\n )\n if (status === 401 || status === 403) {\n return {\n success: false,\n message: `Authentication rejected (${status}) \u2014 check username/password`,\n latencyMs: Date.now() - started,\n }\n }\n return { success: true, message: `Reachable and authenticated (HTTP ${status})`, latencyMs: Date.now() - started }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n return { success: false, message, latencyMs: Date.now() - started }\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class BctAuthError extends Error {
|
|
2
|
+
constructor(message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = "BctAuthError";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
function basicAuthHeader(config) {
|
|
8
|
+
const auth = config.authConfig ?? {};
|
|
9
|
+
const username = String(auth.username ?? "");
|
|
10
|
+
const password = String(auth.password ?? "");
|
|
11
|
+
if (!username || !password) {
|
|
12
|
+
throw new BctAuthError(
|
|
13
|
+
`BCT/INCOS config ${config.terminalCode} is missing username/password in auth_config`
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
const token = Buffer.from(`${username}:${password}`, "utf8").toString("base64");
|
|
17
|
+
return `Basic ${token}`;
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
BctAuthError,
|
|
21
|
+
basicAuthHeader
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=basic.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/terminal_tracking/lib/adapters/bct/auth/basic.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ResolvedTerminalConfig } from '../../../terminal-adapter'\n\n/**\n * INCOS authenticates every call with plain HTTP Basic (`-u user:password` in\n * the vendor docs). There is no token endpoint or cache \u2014 the header is derived\n * from the decrypted `auth_config` on each request. Credentials live in\n * `auth_config` as `{ username, password }` (encrypted at rest; see\n * encryption.ts).\n */\n\nexport class BctAuthError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'BctAuthError'\n }\n}\n\n/**\n * Build the `Authorization: Basic <base64(user:pass)>` header for a config.\n * Throws `BctAuthError` when either credential is missing, so a misconfigured\n * terminal fails with a clear message rather than a silent 401.\n */\nexport function basicAuthHeader(config: ResolvedTerminalConfig): string {\n const auth = (config.authConfig ?? {}) as Record<string, unknown>\n const username = String(auth.username ?? '')\n const password = String(auth.password ?? '')\n if (!username || !password) {\n throw new BctAuthError(\n `BCT/INCOS config ${config.terminalCode} is missing username/password in auth_config`,\n )\n }\n const token = Buffer.from(`${username}:${password}`, 'utf8').toString('base64')\n return `Basic ${token}`\n}\n"],
|
|
5
|
+
"mappings": "AAUO,MAAM,qBAAqB,MAAM;AAAA,EACtC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAOO,SAAS,gBAAgB,QAAwC;AACtE,QAAM,OAAQ,OAAO,cAAc,CAAC;AACpC,QAAM,WAAW,OAAO,KAAK,YAAY,EAAE;AAC3C,QAAM,WAAW,OAAO,KAAK,YAAY,EAAE;AAC3C,MAAI,CAAC,YAAY,CAAC,UAAU;AAC1B,UAAM,IAAI;AAAA,MACR,oBAAoB,OAAO,YAAY;AAAA,IACzC;AAAA,EACF;AACA,QAAM,QAAQ,OAAO,KAAK,GAAG,QAAQ,IAAI,QAAQ,IAAI,MAAM,EAAE,SAAS,QAAQ;AAC9E,SAAO,SAAS,KAAK;AACvB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|