cxtms 1.9.13

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.
Files changed (215) hide show
  1. package/README.md +384 -0
  2. package/dist/cli.d.ts +6 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +4784 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/extractUtils.d.ts +11 -0
  7. package/dist/extractUtils.d.ts.map +1 -0
  8. package/dist/extractUtils.js +19 -0
  9. package/dist/extractUtils.js.map +1 -0
  10. package/dist/index.d.ts +7 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +11 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/types.d.ts +129 -0
  15. package/dist/types.d.ts.map +1 -0
  16. package/dist/types.js +6 -0
  17. package/dist/types.js.map +1 -0
  18. package/dist/utils/schemaLoader.d.ts +17 -0
  19. package/dist/utils/schemaLoader.d.ts.map +1 -0
  20. package/dist/utils/schemaLoader.js +134 -0
  21. package/dist/utils/schemaLoader.js.map +1 -0
  22. package/dist/validator.d.ts +72 -0
  23. package/dist/validator.d.ts.map +1 -0
  24. package/dist/validator.js +432 -0
  25. package/dist/validator.js.map +1 -0
  26. package/dist/workflowValidator.d.ts +103 -0
  27. package/dist/workflowValidator.d.ts.map +1 -0
  28. package/dist/workflowValidator.js +753 -0
  29. package/dist/workflowValidator.js.map +1 -0
  30. package/package.json +51 -0
  31. package/schemas/actions/all.json +27 -0
  32. package/schemas/actions/clipboard.json +46 -0
  33. package/schemas/actions/confirm.json +21 -0
  34. package/schemas/actions/consoleLog.json +16 -0
  35. package/schemas/actions/dialog.json +25 -0
  36. package/schemas/actions/fileDownload.json +16 -0
  37. package/schemas/actions/forEach.json +31 -0
  38. package/schemas/actions/if.json +12 -0
  39. package/schemas/actions/mutation.json +25 -0
  40. package/schemas/actions/navigate.json +18 -0
  41. package/schemas/actions/navigateBack.json +22 -0
  42. package/schemas/actions/navigateBackOrClose.json +21 -0
  43. package/schemas/actions/notification.json +19 -0
  44. package/schemas/actions/openBarcodeScanner.json +104 -0
  45. package/schemas/actions/query.json +32 -0
  46. package/schemas/actions/refresh.json +13 -0
  47. package/schemas/actions/resetDirtyState.json +22 -0
  48. package/schemas/actions/setFields.json +21 -0
  49. package/schemas/actions/setStore.json +13 -0
  50. package/schemas/actions/validateForm.json +15 -0
  51. package/schemas/actions/workflow.json +24 -0
  52. package/schemas/components/README.md +147 -0
  53. package/schemas/components/appComponent.json +58 -0
  54. package/schemas/components/barcodeScanner.json +69 -0
  55. package/schemas/components/button.json +123 -0
  56. package/schemas/components/calendar.json +489 -0
  57. package/schemas/components/card.json +176 -0
  58. package/schemas/components/collection.json +54 -0
  59. package/schemas/components/dataGrid.json +119 -0
  60. package/schemas/components/datasource.json +151 -0
  61. package/schemas/components/dropdown.json +57 -0
  62. package/schemas/components/field-collection.json +618 -0
  63. package/schemas/components/field.json +265 -0
  64. package/schemas/components/form.json +234 -0
  65. package/schemas/components/index.json +71 -0
  66. package/schemas/components/layout.json +69 -0
  67. package/schemas/components/module.json +167 -0
  68. package/schemas/components/navDropdown.json +36 -0
  69. package/schemas/components/navbar.json +78 -0
  70. package/schemas/components/navbarItem.json +28 -0
  71. package/schemas/components/navbarLink.json +36 -0
  72. package/schemas/components/row.json +31 -0
  73. package/schemas/components/slot.json +30 -0
  74. package/schemas/components/tab.json +34 -0
  75. package/schemas/components/tabs.json +35 -0
  76. package/schemas/components/timeline.json +172 -0
  77. package/schemas/components/timelineGrid.json +328 -0
  78. package/schemas/fields/README.md +66 -0
  79. package/schemas/fields/attachment.json +156 -0
  80. package/schemas/fields/autocomplete-googleplaces.json +130 -0
  81. package/schemas/fields/checkbox.json +82 -0
  82. package/schemas/fields/date.json +88 -0
  83. package/schemas/fields/datetime.json +75 -0
  84. package/schemas/fields/email.json +75 -0
  85. package/schemas/fields/index.json +53 -0
  86. package/schemas/fields/number.json +91 -0
  87. package/schemas/fields/password.json +70 -0
  88. package/schemas/fields/radio.json +94 -0
  89. package/schemas/fields/rangedatetime.json +56 -0
  90. package/schemas/fields/select-async.json +334 -0
  91. package/schemas/fields/select.json +115 -0
  92. package/schemas/fields/tel.json +79 -0
  93. package/schemas/fields/text.json +86 -0
  94. package/schemas/fields/textarea.json +95 -0
  95. package/schemas/fields/time.json +91 -0
  96. package/schemas/fields/url.json +74 -0
  97. package/schemas/schema.graphql +12248 -0
  98. package/schemas/schemas.json +610 -0
  99. package/schemas/workflows/activity.json +96 -0
  100. package/schemas/workflows/common/condition.json +48 -0
  101. package/schemas/workflows/common/expression.json +76 -0
  102. package/schemas/workflows/common/mapping.json +173 -0
  103. package/schemas/workflows/common/step.json +38 -0
  104. package/schemas/workflows/flow/aggregation.json +44 -0
  105. package/schemas/workflows/flow/entity.json +129 -0
  106. package/schemas/workflows/flow/state.json +105 -0
  107. package/schemas/workflows/flow/transition.json +143 -0
  108. package/schemas/workflows/input.json +122 -0
  109. package/schemas/workflows/output.json +61 -0
  110. package/schemas/workflows/schedule.json +26 -0
  111. package/schemas/workflows/tasks/accounting-transaction.json +95 -0
  112. package/schemas/workflows/tasks/action-event.json +65 -0
  113. package/schemas/workflows/tasks/all.json +152 -0
  114. package/schemas/workflows/tasks/appmodule.json +56 -0
  115. package/schemas/workflows/tasks/attachment.json +97 -0
  116. package/schemas/workflows/tasks/authentication.json +86 -0
  117. package/schemas/workflows/tasks/caching.json +68 -0
  118. package/schemas/workflows/tasks/charge.json +92 -0
  119. package/schemas/workflows/tasks/commodity.json +92 -0
  120. package/schemas/workflows/tasks/contact-address.json +72 -0
  121. package/schemas/workflows/tasks/contact-payment-method.json +72 -0
  122. package/schemas/workflows/tasks/contact.json +82 -0
  123. package/schemas/workflows/tasks/csv.json +81 -0
  124. package/schemas/workflows/tasks/document-render.json +105 -0
  125. package/schemas/workflows/tasks/document-send.json +84 -0
  126. package/schemas/workflows/tasks/edi.json +157 -0
  127. package/schemas/workflows/tasks/email-send.json +110 -0
  128. package/schemas/workflows/tasks/error.json +72 -0
  129. package/schemas/workflows/tasks/export.json +90 -0
  130. package/schemas/workflows/tasks/filetransfer.json +102 -0
  131. package/schemas/workflows/tasks/flow-transition.json +68 -0
  132. package/schemas/workflows/tasks/foreach.json +69 -0
  133. package/schemas/workflows/tasks/generic.json +47 -0
  134. package/schemas/workflows/tasks/graphql.json +78 -0
  135. package/schemas/workflows/tasks/httpRequest.json +161 -0
  136. package/schemas/workflows/tasks/import.json +64 -0
  137. package/schemas/workflows/tasks/inventory.json +67 -0
  138. package/schemas/workflows/tasks/job.json +88 -0
  139. package/schemas/workflows/tasks/log.json +73 -0
  140. package/schemas/workflows/tasks/map.json +58 -0
  141. package/schemas/workflows/tasks/movement.json +54 -0
  142. package/schemas/workflows/tasks/note.json +59 -0
  143. package/schemas/workflows/tasks/number.json +65 -0
  144. package/schemas/workflows/tasks/order-tracking-event.json +109 -0
  145. package/schemas/workflows/tasks/order.json +139 -0
  146. package/schemas/workflows/tasks/payment.json +85 -0
  147. package/schemas/workflows/tasks/pdf-document.json +60 -0
  148. package/schemas/workflows/tasks/postal-codes.json +92 -0
  149. package/schemas/workflows/tasks/resolve-timezone.json +65 -0
  150. package/schemas/workflows/tasks/setVariable.json +76 -0
  151. package/schemas/workflows/tasks/switch.json +75 -0
  152. package/schemas/workflows/tasks/template.json +73 -0
  153. package/schemas/workflows/tasks/tracking-event.json +137 -0
  154. package/schemas/workflows/tasks/transmission.json +185 -0
  155. package/schemas/workflows/tasks/unzip-file.json +68 -0
  156. package/schemas/workflows/tasks/user.json +70 -0
  157. package/schemas/workflows/tasks/validation.json +99 -0
  158. package/schemas/workflows/tasks/while.json +53 -0
  159. package/schemas/workflows/tasks/workflow-execute.json +82 -0
  160. package/schemas/workflows/trigger.json +90 -0
  161. package/schemas/workflows/variable.json +46 -0
  162. package/schemas/workflows/workflow.json +335 -0
  163. package/scripts/postinstall.js +291 -0
  164. package/scripts/setup-vscode.js +80 -0
  165. package/skills/cxtms-developer/SKILL.md +118 -0
  166. package/skills/cxtms-developer/ref-cli-auth.md +120 -0
  167. package/skills/cxtms-developer/ref-entity-accounting.md +180 -0
  168. package/skills/cxtms-developer/ref-entity-commodity.md +239 -0
  169. package/skills/cxtms-developer/ref-entity-contact.md +163 -0
  170. package/skills/cxtms-developer/ref-entity-geography.md +154 -0
  171. package/skills/cxtms-developer/ref-entity-job.md +77 -0
  172. package/skills/cxtms-developer/ref-entity-notification.md +85 -0
  173. package/skills/cxtms-developer/ref-entity-order-sub.md +160 -0
  174. package/skills/cxtms-developer/ref-entity-order.md +183 -0
  175. package/skills/cxtms-developer/ref-entity-organization.md +41 -0
  176. package/skills/cxtms-developer/ref-entity-rate.md +182 -0
  177. package/skills/cxtms-developer/ref-entity-shared.md +176 -0
  178. package/skills/cxtms-developer/ref-entity-warehouse.md +115 -0
  179. package/skills/cxtms-developer/ref-graphql-query.md +309 -0
  180. package/skills/cxtms-module-builder/SKILL.md +477 -0
  181. package/skills/cxtms-module-builder/ref-components-data.md +293 -0
  182. package/skills/cxtms-module-builder/ref-components-display.md +411 -0
  183. package/skills/cxtms-module-builder/ref-components-forms.md +369 -0
  184. package/skills/cxtms-module-builder/ref-components-interactive.md +317 -0
  185. package/skills/cxtms-module-builder/ref-components-layout.md +390 -0
  186. package/skills/cxtms-module-builder/ref-components-specialized.md +477 -0
  187. package/skills/cxtms-workflow-builder/SKILL.md +438 -0
  188. package/skills/cxtms-workflow-builder/ref-accounting.md +66 -0
  189. package/skills/cxtms-workflow-builder/ref-communication.md +169 -0
  190. package/skills/cxtms-workflow-builder/ref-entity.md +342 -0
  191. package/skills/cxtms-workflow-builder/ref-expressions-ncalc.md +128 -0
  192. package/skills/cxtms-workflow-builder/ref-expressions-template.md +161 -0
  193. package/skills/cxtms-workflow-builder/ref-filetransfer.md +80 -0
  194. package/skills/cxtms-workflow-builder/ref-flow.md +210 -0
  195. package/skills/cxtms-workflow-builder/ref-other.md +157 -0
  196. package/skills/cxtms-workflow-builder/ref-query.md +105 -0
  197. package/skills/cxtms-workflow-builder/ref-utilities.md +417 -0
  198. package/templates/module-configuration.yaml +44 -0
  199. package/templates/module-form.yaml +152 -0
  200. package/templates/module-grid.yaml +229 -0
  201. package/templates/module-select.yaml +139 -0
  202. package/templates/module.yaml +84 -0
  203. package/templates/workflow-api-tracking.yaml +189 -0
  204. package/templates/workflow-basic.yaml +76 -0
  205. package/templates/workflow-document.yaml +155 -0
  206. package/templates/workflow-entity-trigger.yaml +90 -0
  207. package/templates/workflow-ftp-edi.yaml +158 -0
  208. package/templates/workflow-ftp-tracking.yaml +161 -0
  209. package/templates/workflow-mcp-tool.yaml +112 -0
  210. package/templates/workflow-public-api.yaml +135 -0
  211. package/templates/workflow-scheduled-execute.yaml +75 -0
  212. package/templates/workflow-scheduled.yaml +125 -0
  213. package/templates/workflow-utility.yaml +96 -0
  214. package/templates/workflow-webhook.yaml +128 -0
  215. package/templates/workflow.yaml +140 -0
@@ -0,0 +1,154 @@
1
+ # Geography & Lookup Entity Reference
2
+
3
+ ## Contents
4
+ - Country
5
+ - State
6
+ - City
7
+ - PostalCode
8
+ - Port
9
+ - Vessel
10
+ - CustomCode
11
+ - ModeOfTransportation
12
+
13
+ Country, State, City, PostalCode, Port, Vessel, CustomCode, ModeOfTransportation.
14
+
15
+ ## Country
16
+
17
+ Composite key: `organizationId` + `countryCode`.
18
+
19
+ | Field | Type | Notes |
20
+ |-------|------|-------|
21
+ | `countryCode` | `string` | PK part (ISO code) |
22
+ | `organizationId` | `int` | PK part |
23
+ | `name` | `string` | |
24
+ | `customValues` | `Dictionary` | jsonb |
25
+
26
+ **Collections:** `states`
27
+
28
+ ---
29
+
30
+ ## State
31
+
32
+ Composite key: `organizationId` + `countryCode` + `stateCode`.
33
+
34
+ | Field | Type | Notes |
35
+ |-------|------|-------|
36
+ | `stateCode` | `string` | PK part |
37
+ | `countryCode` | `string` | PK part, FK to Country |
38
+ | `organizationId` | `int` | PK part |
39
+ | `name` | `string` | |
40
+ | `customValues` | `Dictionary` | jsonb |
41
+
42
+ **Navigation:** `country`
43
+
44
+ ---
45
+
46
+ ## City
47
+
48
+ | Field | Type | Notes |
49
+ |-------|------|-------|
50
+ | `cityId` | `int` | PK |
51
+ | `organizationId` | `int` | |
52
+ | `cityName` | `string` | |
53
+ | `stateCode` | `string` | FK to State |
54
+ | `countryCode` | `string` | FK to Country |
55
+ | `longitude` | `double?` | From Location.X (GraphQL) |
56
+ | `latitude` | `double?` | From Location.Y (GraphQL) |
57
+ | `customValues` | `Dictionary` | jsonb |
58
+
59
+ **Navigation:** `state`, `country`
60
+
61
+ ---
62
+
63
+ ## PostalCode
64
+
65
+ PK: `id` (int, auto). Scoped per organization.
66
+
67
+ | Field | Type | Notes |
68
+ |-------|------|-------|
69
+ | `id` | `int` | PK |
70
+ | `organizationId` | `int` | |
71
+ | `code` | `string` | Postal/zip code value |
72
+ | `countryCode` | `string` | FK to Country |
73
+ | `placeName` | `string` | Place/city name |
74
+ | `stateCode` | `string?` | FK to State |
75
+ | `accuracy` | `AccuracyTypes?` | 1=Region, 2=Municipality, 3=Neighborhood, 4=Place, 5=Street, 6=Centroid |
76
+ | `timeZone` | `string?` | IANA timezone ID (e.g., `America/Chicago`). GraphQL auto-resolves from GPS coordinates when not stored |
77
+ | `longitude` | `double?` | From Location.X (GraphQL computed) |
78
+ | `latitude` | `double?` | From Location.Y (GraphQL computed) |
79
+ | `customValues` | `Dictionary` | jsonb |
80
+ | `location` | `Point?` | WGS 84 (SRID 4326). X=longitude, Y=latitude |
81
+
82
+ **Navigation:** `country`, `state`
83
+
84
+ **Mutations:** `ChangeCode`, `ChangePlaceName`, `ChangeCoordinates(lat, lng, accuracy)`, `ChangeCountry`/`ChangeCountryCode`, `ChangeState`/`ChangeStateCode`, `ChangeTimeZone`, `ChangeCustomValues`, `ChangeLatitude`, `ChangeLongitude`
85
+
86
+ ---
87
+
88
+ ## Port
89
+
90
+ String-based PK (e.g., UN/LOCODE).
91
+
92
+ | Field | Type | Notes |
93
+ |-------|------|-------|
94
+ | `portId` | `string` | PK |
95
+ | `organizationId` | `int` | |
96
+ | `name` | `string` | |
97
+ | `countryCode` | `string` | FK to Country |
98
+ | `stateCode` | `string?` | FK to State |
99
+ | `isAir` | `bool` | Mode flags |
100
+ | `isMariTime` | `bool` | |
101
+ | `isRoad` | `bool` | |
102
+ | `isRail` | `bool` | |
103
+ | `isMail` | `bool` | |
104
+ | `isBorderCrossingPoint` | `bool` | |
105
+ | `isMyCompany` | `bool` | |
106
+ | `portRemarks` | `string?` | |
107
+ | `customValues` | `Dictionary` | jsonb |
108
+
109
+ **Navigation:** `country`, `state`
110
+
111
+ ---
112
+
113
+ ## Vessel
114
+
115
+ | Field | Type | Notes |
116
+ |-------|------|-------|
117
+ | `vesselId` | `int` | PK |
118
+ | `organizationId` | `int` | |
119
+ | `name` | `string` | |
120
+ | `vesselCode` | `string?` | |
121
+ | `carrierId` | `int?` | FK to Contact (carrier) |
122
+ | `countryCode` | `string?` | FK to Country (flag state) |
123
+
124
+ **Navigation:** `carrier`, `country`. No customValues.
125
+
126
+ ---
127
+
128
+ ## CustomCode
129
+
130
+ Organization-specific lookup codes (Schedule D, Schedule K, etc.).
131
+
132
+ | Field | Type | Notes |
133
+ |-------|------|-------|
134
+ | `id` | `int` | PK |
135
+ | `organizationId` | `int` | |
136
+ | `code` | `string` | |
137
+ | `description` | `string` | |
138
+ | `isCommonlyUsed` | `bool` | |
139
+ | `codeType` | `CustomCodeTypes` enum | ScheduleD, ScheduleK |
140
+
141
+ No customValues.
142
+
143
+ ---
144
+
145
+ ## ModeOfTransportation
146
+
147
+ | Field | Type | Notes |
148
+ |-------|------|-------|
149
+ | `modeOfTransportationId` | `int` | PK |
150
+ | `organizationId` | `int` | |
151
+ | `description` | `string` | e.g., "Air", "Ocean", "Ground" |
152
+ | `customValues` | `Dictionary` | jsonb |
153
+
154
+ Referenced by Rate, Lane, Discount, and Order (via `customValues.modeOfTransportationId`).
@@ -0,0 +1,77 @@
1
+ # Job Entity Field Reference
2
+
3
+ Job groups related orders and accounting transactions.
4
+
5
+ ## Job
6
+
7
+ ### Fields
8
+
9
+ | Field | Type | Notes |
10
+ |-------|------|-------|
11
+ | `jobId` | `Guid` | PK (UUID) |
12
+ | `organizationId` | `int` | Tenant scope |
13
+ | `jobNumber` | `string` | Business-facing number |
14
+ | `description` | `string?` | |
15
+ | `isDraft` | `bool` | |
16
+ | `customerId` | `int?` | FK to Contact |
17
+ | `divisionId` | `int?` | FK to Division |
18
+ | `employeeId` | `int?` | FK to Contact |
19
+ | `jobStatusId` | `int?` | FK to JobStatus |
20
+ | `customValues` | `Dictionary` | jsonb |
21
+
22
+ ### Navigation
23
+
24
+ | Field | Type |
25
+ |-------|------|
26
+ | `customer` | `Contact?` |
27
+ | `division` | `Division?` |
28
+ | `employee` | `Contact?` |
29
+ | `jobStatus` | `JobStatus?` |
30
+
31
+ ### Collections
32
+
33
+ | Field | Type | Notes |
34
+ |-------|------|-------|
35
+ | `orders` | `[Order]` | Via JobOrder join |
36
+ | `accountingTransactions` | `[AccountingTransaction]` | Via JobAccountingTransaction join |
37
+ | `commodities` | `[Commodity]` | Direct FK |
38
+
39
+ ### GraphQL Computed
40
+
41
+ - `getJobOrders(filter)` — orders via JobOrder join
42
+
43
+ ---
44
+
45
+ ## JobOrder (Join Entity)
46
+
47
+ | Field | Type | Notes |
48
+ |-------|------|-------|
49
+ | `jobId` | `Guid` | FK to Job |
50
+ | `orderId` | `int` | FK to Order |
51
+
52
+ No customValues. No audit fields (uses BaseEntity, not AuditableEntity).
53
+
54
+ ---
55
+
56
+ ## JobStatus
57
+
58
+ | Field | Type | Notes |
59
+ |-------|------|-------|
60
+ | `jobStatusId` | `int` | PK |
61
+ | `organizationId` | `int` | |
62
+ | `jobStatusName` | `string` | |
63
+ | `priority` | `int` | |
64
+ | `statusStage` | `StatusStage` enum | Pending=1, InProgress, Completed |
65
+ | `customValues` | `Dictionary` | jsonb |
66
+
67
+ ---
68
+
69
+ ## StatusStage Enum
70
+
71
+ Used by JobStatus, OrderStatus, ContactStatus:
72
+
73
+ | Value | Int |
74
+ |-------|-----|
75
+ | `Pending` | 1 |
76
+ | `InProgress` | 2 |
77
+ | `Completed` | 3 |
@@ -0,0 +1,85 @@
1
+ # Notification Entity Reference
2
+
3
+ Real-time notification system. Notifications are org-scoped with per-user read tracking via `UserNotification`.
4
+
5
+ ## Notification
6
+
7
+ | Field | Type | Notes |
8
+ |-------|------|-------|
9
+ | `notificationId` | `int` | PK |
10
+ | `organizationId` | `int` | FK to Organization |
11
+ | `title` | `string` | Required |
12
+ | `message` | `string?` | Body text, supports Markdown |
13
+ | `type` | `NotificationType` | System=0, OrderUpdate=1, TaskAssignment=2, Alert=3, Info=4 |
14
+ | `priority` | `NotificationPriority` | Low=0, Normal=1, High=2, Urgent=3 |
15
+ | `targetUserId` | `string?` | If set, targets one user; if null, broadcasts to all active org users |
16
+ | `entityType` | `string?` | Linked entity type (e.g. "Order", "Job") |
17
+ | `entityId` | `int?` | Linked entity PK |
18
+ | `expiresAt` | `DateTime?` | Optional expiration |
19
+ | `created` / `lastModified` | `DateTime` | Audit fields (from `AuditableEntity`) |
20
+ | `createdBy` / `lastModifiedBy` | `string` | Audit fields |
21
+
22
+ ### Domain Methods
23
+
24
+ - `ChangeTitle(string)`, `ChangeMessage(string?)`, `ChangeType(NotificationType)`, `ChangePriority(NotificationPriority)`, `ChangeExpiresAt(DateTime?)`
25
+
26
+ ---
27
+
28
+ ## UserNotification
29
+
30
+ Per-user read state join entity.
31
+
32
+ | Field | Type | Notes |
33
+ |-------|------|-------|
34
+ | `userNotificationId` | `int` | PK |
35
+ | `notificationId` | `int` | FK to Notification |
36
+ | `userId` | `string` | FK to ApplicationUser |
37
+ | `isRead` | `bool` | Default false |
38
+ | `readAt` | `DateTime?` | Set when marked read |
39
+
40
+ ### Domain Methods
41
+
42
+ - `MarkAsRead()` — sets `IsRead = true`, `ReadAt = UtcNow`
43
+ - `MarkAsUnread()` — resets both
44
+
45
+ ---
46
+
47
+ ## GraphQL
48
+
49
+ ### Queries
50
+
51
+ - `getNotification(organizationId, notificationId)` → single notification for current user (projected from UserNotification)
52
+ - `getNotifications(organizationId, filter?, search?, orderBy?)` → offset-paged list for current user; default sort: `-notification.created`
53
+ - `getUnreadNotificationCount(organizationId)` → int
54
+
55
+ ### Mutations
56
+
57
+ - `createNotification(organizationId, values)` → creates Notification + UserNotification rows; publishes to subscription topic per user
58
+ - `markNotificationRead(organizationId, notificationId)` → bool
59
+ - `markAllNotificationsRead(organizationId)` → int (count marked)
60
+ - `deleteNotification(organizationId, notificationId)` → DeleteResult
61
+
62
+ ### Subscriptions
63
+
64
+ - `onNotificationReceived(organizationId, userId)` → real-time via PostgreSQL NOTIFY/LISTEN
65
+ - Topic: `{organizationId}_{userId}_notifications`
66
+
67
+ ### GraphQL DTO (projected from UserNotification)
68
+
69
+ Flattens `Notification` + `UserNotification` into single DTO: `notificationId`, `organizationId`, `title`, `message`, `type`, `priority`, `targetUserId`, `entityType`, `entityId`, `expiresAt`, `isRead`, `readAt`, `created`, `createdBy`, `lastModified`, `lastModifiedBy`, plus resolved `createdUser` / `updatedUser`.
70
+
71
+ ---
72
+
73
+ ## Targeting Logic
74
+
75
+ On `CreateNotification`:
76
+ 1. If `targetUserId` is provided → single `UserNotification` row
77
+ 2. If null → queries all active `UserEmployee` records in org → one `UserNotification` per user
78
+ 3. After save, publishes `NotificationDto` to each user's subscription topic via `INotificationEventSender`
79
+
80
+ ## Infrastructure
81
+
82
+ - `NotificationConfiguration` — EF Core config: title max length, indexes on `OrganizationId`, composite index on `(OrganizationId, Created DESC)` for paging
83
+ - `UserNotificationConfiguration` — indexes on `UserId`, `NotificationId`, composite on `(UserId, IsRead)`
84
+ - `NotificationEventSender` — uses HotChocolate `ITopicEventSender` to publish to subscription topics
85
+ - Real-time delivery: PostgreSQL `NOTIFY/LISTEN` channel (configured in `DependencyInjection`)
@@ -0,0 +1,160 @@
1
+ # Order Sub-Entity Field Reference
2
+
3
+ ## Contents
4
+ - OrderEntity
5
+ - TrackingEvent
6
+ - EventDefinition
7
+ - LinkedOrder
8
+ - OrderDocument
9
+
10
+ Entities associated with orders: OrderEntity (parties), TrackingEvent, LinkedOrder, OrderDocument.
11
+
12
+ ## OrderEntity
13
+
14
+ Represents a party role (Shipper, Consignee, Carrier, etc.) on an order.
15
+
16
+ ### Fields
17
+
18
+ | Field | Type | Notes |
19
+ |-------|------|-------|
20
+ | `orderEntityId` | `int` | PK |
21
+ | `orderId` | `int` | FK to Order |
22
+ | `contactId` | `int?` | FK to Contact |
23
+ | `contactAddressId` | `int?` | FK to ContactAddress |
24
+ | `nonContactName` | `string?` | Name when no contact linked |
25
+ | `entityType` | `EntityTypes` enum | Shipper, Consignee, Carrier, etc. |
26
+ | `orderEntitySequence` | `int` | Sort order |
27
+ | `isDeleted` | `bool?` | Soft delete |
28
+ | `customValues` | `Dictionary` | jsonb |
29
+
30
+ ### Navigation
31
+
32
+ | Field | Type |
33
+ |-------|------|
34
+ | `contact` | `Contact?` |
35
+ | `contactAddress` | `ContactAddress?` |
36
+
37
+ ### GraphQL Computed
38
+
39
+ - `contactName` — mapped from `contact.name`
40
+ - `attachments` — filterable collection
41
+ - `getOrderEntityAttachments(idPropertyName, filter, orderBy, search)` — resolver
42
+
43
+ ### Import Behavior (Order/Import)
44
+
45
+ When importing order entities via `Order/Import@1`:
46
+ - The `contact` and `contactAddress` nested objects are excluded from direct field mapping and processed separately.
47
+ - **ContactAddress matching** uses `ImportOrderOptions.ContactAddressMatchByFields` — scoped to organization and (when persisted) to the resolved contact. Supports Lucene filter-based matching on any ContactAddress field (e.g., `["addressLine", "postalCode"]`). If null/empty, falls back to matching by `contactAddressId` only.
48
+ - Both contacts and contact addresses are cached per import session to prevent duplicate creation.
49
+
50
+ ### EntityTypes Enum
51
+
52
+ Shipper=0, Consignee=1, Carrier=2, Vendor=3, UltimateConsignee=4, NotifyParty=5, Intermediate=6, ForwardingAgent=7, DestinationAgent=8, PickupFrom=9, DeliverTo=10, DeliveryCarrier=11, ReceivedBy=12, USPPI=13
53
+
54
+ ---
55
+
56
+ ## TrackingEvent
57
+
58
+ Milestone/tracking event on an order or commodity.
59
+
60
+ ### Fields
61
+
62
+ | Field | Type | Notes |
63
+ |-------|------|-------|
64
+ | `trackingEventId` | `int` | PK |
65
+ | `eventDefinitionId` | `int` | FK to EventDefinition |
66
+ | `eventDate` | `DateTime?` | When the event occurred |
67
+ | `description` | `string?` | |
68
+ | `location` | `string?` | |
69
+ | `isInactive` | `bool` | |
70
+ | `includeInTracking` | `bool` | Show in tracking UI |
71
+ | `sendEmail` | `bool` | Trigger email notification |
72
+ | `customValues` | `Dictionary` | jsonb |
73
+
74
+ ### Navigation
75
+
76
+ | Field | Type |
77
+ |-------|------|
78
+ | `eventDefinition` | `EventDefinition` |
79
+
80
+ ---
81
+
82
+ ## EventDefinition
83
+
84
+ Template/type definition for tracking events.
85
+
86
+ ### Fields
87
+
88
+ | Field | Type | Notes |
89
+ |-------|------|-------|
90
+ | `eventDefinitionId` | `int` | PK |
91
+ | `eventName` | `string` | |
92
+ | `description` | `string?` | |
93
+ | `location` | `string?` | Default location |
94
+ | `isInactive` | `bool` | |
95
+ | `includeInTracking` | `bool` | Default for events |
96
+ | `sendEmail` | `bool` | Default for events |
97
+ | `sendEmailDocumentId` | `int?` | FK to DocumentTemplate |
98
+ | `isAutomaticCreate` | `bool` | Auto-create on triggers |
99
+ | `triggerEventName` | `string?` | Trigger config |
100
+ | `triggerEntityName` | `string?` | |
101
+ | `triggerConditionFields` | `string?` | |
102
+ | `customValues` | `Dictionary` | jsonb |
103
+
104
+ ### GraphQL Resolvers
105
+
106
+ | Resolver | Arguments | Returns | Description |
107
+ |----------|-----------|---------|-------------|
108
+ | `getContact` | `customValuesKey: String!` | `Contact` | Looks up a Contact by ID stored in `customValues[key]` |
109
+
110
+ ---
111
+
112
+ ## LinkedOrder
113
+
114
+ Links between orders (source → target).
115
+
116
+ ### Fields
117
+
118
+ | Field | Type | Notes |
119
+ |-------|------|-------|
120
+ | `sourceOrderId` | `int` | FK to Order (source) |
121
+ | `targetOrderId` | `int` | FK to Order (target) |
122
+ | `isDeleted` | `bool` | Soft delete |
123
+ | `customValues` | `Dictionary` | jsonb |
124
+
125
+ ### Navigation
126
+
127
+ | Field | Type |
128
+ |-------|------|
129
+ | `sourceOrder` | `Order` |
130
+ | `targetOrder` | `Order` |
131
+
132
+ ---
133
+
134
+ ## OrderDocument
135
+
136
+ Document template linked to an order for generation.
137
+
138
+ ### Fields
139
+
140
+ | Field | Type | Notes |
141
+ |-------|------|-------|
142
+ | `orderDocumentId` | `int` | PK |
143
+ | `orderId` | `int` | FK to Order |
144
+ | `documentTemplateId` | `int?` | FK to DocumentTemplate |
145
+ | `workflowId` | `Guid?` | FK to Workflow (for generation) |
146
+ | `lastGeneratedFile` | `string?` | File path/key |
147
+ | `lastGeneratedTime` | `DateTime?` | |
148
+ | `regenerateOnOrderChange` | `bool` | Auto-regenerate |
149
+ | `metadata` | `Dictionary` | jsonb — auto-populated keys: `orderId`, `orderPickupId`, `orderDeliveryId`, `thirdPartyContactId`, `carrierId` |
150
+
151
+ ### Navigation
152
+
153
+ | Field | Type |
154
+ |-------|------|
155
+ | `order` | `Order` |
156
+ | `documentTemplate` | `DocumentTemplate?` |
157
+
158
+ ### GraphQL Computed
159
+
160
+ - `getLinkToDocument(expiresInDays)` — returns signed URL
@@ -0,0 +1,183 @@
1
+ # Order Entity Field Reference
2
+
3
+ ## Contents
4
+ - Order Scalar Fields
5
+ - Order Navigation Properties
6
+ - Order Collection Properties
7
+ - Pre-filtered OrderEntity Collections (GraphQL)
8
+ - Order Computed/Resolved GraphQL Fields
9
+ - OrderTypes Enum
10
+ - EntityTypes Enum (for OrderEntity)
11
+ - Order CustomValues
12
+
13
+ Field names as used in workflow expressions: `{{ entity.orderId }}`, `{{ entity.customValues.myField }}`.
14
+
15
+ ## Scalar Fields
16
+
17
+ | Field | Type | Notes |
18
+ |-------|------|-------|
19
+ | `orderId` | `int` | Primary key |
20
+ | `organizationId` | `int` | Tenant scope |
21
+ | `orderNumber` | `string` | Business-facing number |
22
+ | `trackingNumber` | `string?` | |
23
+ | `orderType` | `OrderTypes` enum | See enum below |
24
+ | `isDraft` | `bool` | Draft orders excluded from default queries |
25
+ | `orderStatusId` | `int` | FK to OrderStatus |
26
+ | `lastOrderStatusModified` | `DateTime?` | Auto-set on status change |
27
+ | `entityTypeId` | `int?` | FK to EntityType |
28
+ | `divisionId` | `int` | FK to Division |
29
+ | `equipmentTypeId` | `int?` | FK to EquipmentType |
30
+ | `billToContactId` | `int?` | FK to Contact |
31
+ | `employeeContactId` | `int?` | FK to Contact |
32
+ | `salespersonContactId` | `int?` | FK to Contact |
33
+ | `created` | `DateTime` | |
34
+ | `createdBy` | `string` | User ID |
35
+ | `lastModified` | `DateTime` | |
36
+ | `lastModifiedBy` | `string` | User ID |
37
+
38
+ ## Navigation Properties
39
+
40
+ | Field | Type | Notes |
41
+ |-------|------|-------|
42
+ | `orderStatus` | `OrderStatus` | `.statusName`, `.statusStage` |
43
+ | `division` | `Division` | `.name` |
44
+ | `equipmentType` | `EquipmentType` | |
45
+ | `billToContact` | `Contact` | Full contact object |
46
+ | `employeeContact` | `Contact` | |
47
+ | `salespersonContact` | `Contact` | |
48
+ | `organization` | `Organization` | |
49
+ | `entityType` | `EntityType` | |
50
+ | `createdUser` | `User` | `.firstName`, `.lastName`, `.email` |
51
+ | `updatedUser` | `User` | |
52
+
53
+ ## Collection Properties
54
+
55
+ | Field | Type | Notes |
56
+ |-------|------|-------|
57
+ | `orderEntities` | `[OrderEntity]` | Shipper, Consignee, Carrier, etc. (by `entityType`) |
58
+ | `charges` | `[Charge]` | Direct charges |
59
+ | `orderCommodities` | `[OrderCommodity]` | Join to commodities (has own `customValues`) |
60
+ | `trackingEvents` | `[TrackingEvent]` | Milestones |
61
+ | `orderDocuments` | `[OrderDocument]` | |
62
+ | `jobs` | `[Job]` | |
63
+ | `jobOrders` | `[JobOrder]` | |
64
+ | `orderTags` | `[OrderTag]` | |
65
+ | `orderCarriers` | `[OrderCarrier]` | |
66
+ | `allTags` | `[OrderAllTagsView]` | View: all tags including from commodities |
67
+ | `allRelatedOrders` | `[OrderRelatedOrdersView]` | Orders sharing commodities |
68
+ | `attachmentsSummary` | `OrderAttachmentSummaryView?` | DB view: `.totalCount`, `.hasAny` (active attachments) |
69
+ | `notesSummary` | `OrderNoteSummaryView?` | DB view: `.totalCount`, `.hasAny` (non-deleted notes) |
70
+ | `outgoingLinks` | `[LinkedOrder]` | |
71
+ | `incomingLinks` | `[LinkedOrder]` | |
72
+
73
+ ## Pre-filtered OrderEntity Collections (GraphQL)
74
+
75
+ These are virtual fields that filter `orderEntities` by type:
76
+
77
+ | Field | EntityType |
78
+ |-------|------------|
79
+ | `orderEntityCarriers` | Carrier |
80
+ | `orderEntityVendors` | Vendor |
81
+ | `orderEntityPickups` | Shipper |
82
+ | `orderEntityDeliveries` | Consignee |
83
+ | `orderEntityDeliveryCarriers` | DeliveryCarrier |
84
+ | `orderEntityDeliverTo` | DeliverTo |
85
+ | `orderEntityPickupFrom` | PickupFrom |
86
+ | `orderEntityDestinationAgent` | DestinationAgent |
87
+ | `orderEntityForwardingAgent` | ForwardingAgent |
88
+ | `orderEntityIntermediate` | Intermediate |
89
+ | `orderEntityNotifyParty` | NotifyParty |
90
+ | `orderEntityUltimateConsignee` | UltimateConsignee |
91
+ | `orderEntityReceivedBy` | ReceivedBy |
92
+ | `orderEntityUsppi` | USPPI |
93
+
94
+ ## Computed/Resolved GraphQL Fields
95
+
96
+ | Field | Returns | Notes |
97
+ |-------|---------|-------|
98
+ | `commoditySummary` | `CommoditySummary` | `.totalWeight`, `.totalPieces`, `.totalQuantity`, `.totalVolume` |
99
+ | `accountingSummary` | `AccountingSummary` | |
100
+ | `getContact(idPropertyName)` | `Contact` | Resolve contact from `customValues[idPropertyName]` |
101
+ | `getPort(idPropertyName)` | `Port` | Resolve port from `customValues[idPropertyName]` |
102
+ | `getVessel(idPropertyName)` | `Vessel` | Resolve vessel from `customValues[idPropertyName]` |
103
+ | `getCountry(idPropertyName)` | `Country` | Resolve country from `customValues[idPropertyName]` |
104
+ | `getRoute(idPropertyName)` | `Route` | Resolve route from `customValues[idPropertyName]` |
105
+ | `getModeOfTransportation(idPropertyName)` | `ModeOfTransportation` | |
106
+ | `getCustomCode(idPropertyName)` | `CustomCode` | |
107
+ | `getRelatedOrderByProperty(idPropertyName)` | `Order` | Resolve related order from `customValues[idPropertyName]` |
108
+ | `getCharge(chargeDescription)` | `Charge` | Single charge by description |
109
+ | `getChargesByChargeType(chargeType)` | `[Charge]` | Charges filtered by type |
110
+ | `getOrderSummary(weightUnit, volumeUnit, dimensionsUnit)` | `OrderSummary` | |
111
+ | `lastTrackingEvent(eventDefinitionName)` | `TrackingEvent` | Most recent |
112
+ | `attachmentsSummary` | `OrderAttachmentSummaryGqlDto` | `.totalCount` (int), `.hasAny` (bool) — batched DataLoader, backed by DB view |
113
+ | `notesSummary` | `OrderNoteSummaryGqlDto` | `.totalCount` (int), `.hasAny` (bool) — batched DataLoader, backed by DB view |
114
+ | `notesCount(threadFilter)` | `int` | |
115
+ | `changeHistory(startDate, endDate, maxResults)` | `[ChangeHistory]` | Audit trail |
116
+ | `getCommoditiesWithRelatedOrder(orderType!, filter?)` | `[Commodity]` | Leaf commodities linked to related orders of specified type. Traverses commodity hierarchy, excludes wrappers. |
117
+
118
+ ## OrderTypes Enum
119
+
120
+ | Value | Int | Notes |
121
+ |-------|-----|-------|
122
+ | `Order` | 0 | Generic order |
123
+ | `Quote` | 1 | |
124
+ | `WarehouseReceipt` | 2 | Warehouse order |
125
+ | `Purchase` | 3 | Pickup order |
126
+ | `ParcelShipment` | 4 | |
127
+ | `AirShipmentOrder` | 5 | |
128
+ | `OceanShipmentOrder` | 6 | |
129
+ | `CargoMovement` | 7 | |
130
+ | `EntityType` | 8 | Type defined by EntityType |
131
+ | `PickupOrder` | 9 | |
132
+ | `LoadOrder` | 10 | |
133
+ | `BookingOrder` | 11 | |
134
+ | `Freight` | 12 | |
135
+ | `DeliveryOrder` | 13 | |
136
+
137
+ ## EntityTypes Enum (for OrderEntity)
138
+
139
+ | Value | Int | Description |
140
+ |-------|-----|-------------|
141
+ | `Shipper` | 0 | Origin party |
142
+ | `Consignee` | 1 | Destination party |
143
+ | `Carrier` | 2 | Transport provider |
144
+ | `Vendor` | 3 | |
145
+ | `UltimateConsignee` | 4 | |
146
+ | `NotifyParty` | 5 | |
147
+ | `Intermediate` | 6 | |
148
+ | `ForwardingAgent` | 7 | |
149
+ | `DestinationAgent` | 8 | |
150
+ | `PickupFrom` | 9 | |
151
+ | `DeliverTo` | 10 | |
152
+ | `DeliveryCarrier` | 11 | |
153
+ | `ReceivedBy` | 12 | |
154
+ | `USPPI` | 13 | US Principal Party in Interest |
155
+
156
+ ## CustomValues
157
+
158
+ `Dictionary<string, object?>` stored as PostgreSQL `jsonb`. Access in workflows:
159
+
160
+ ```yaml
161
+ # Template expressions
162
+ value: "{{ entity.customValues.myField }}"
163
+ value: "{{ entity.customValues['my-field'] }}"
164
+
165
+ # NCalc conditions
166
+ conditions:
167
+ - expression: "isNullOrEmpty([entity.customValues.myField?]) = false"
168
+
169
+ # Update via Order/Update task
170
+ inputs:
171
+ orderId: "{{ entity.orderId }}"
172
+ order:
173
+ CustomValues.myField: "newValue" # Dot notation (single field)
174
+ customValues: # Bulk update (merge)
175
+ field1: "value1"
176
+ field2: "{{ computed }}"
177
+ ```
178
+
179
+ **Known system customValues keys:**
180
+ - `modeOfTransportationId` / `modeOfTransportationIdDescription` — transport mode
181
+
182
+ **Resolver pattern** — Many GraphQL fields resolve entities from customValues IDs:
183
+ `getContact(idPropertyName)` reads `customValues[idPropertyName]` as a contact ID and returns the full Contact object. Same pattern for ports, vessels, countries, routes, etc.
@@ -0,0 +1,41 @@
1
+ # Organization Entity Reference
2
+
3
+ Core tenant entity. Each organization represents a company/tenant in the system.
4
+
5
+ ## Fields
6
+
7
+ | Field | Type | Notes |
8
+ |-------|------|-------|
9
+ | `organizationId` | `int` | PK |
10
+ | `companyName` | `string` | Required |
11
+ | `addressLine` | `string?` | |
12
+ | `addressLine2` | `string?` | |
13
+ | `cityName` | `string?` | |
14
+ | `countryCode` | `string?` | |
15
+ | `stateCode` | `string?` | |
16
+ | `postalCode` | `string?` | |
17
+ | `phoneNumber` | `string?` | |
18
+ | `faxNumber` | `string?` | |
19
+ | `uniqueId` | `Guid` | Immutable external identifier |
20
+ | `slug` | `string?` | URL-friendly identifier for Public API routes (lowercase, hyphenated) |
21
+ | `isDeleted` | `bool` | Soft delete |
22
+ | `customValues` | `Dictionary?` | jsonb, merged on update |
23
+ | `created` / `lastModified` | `DateTime` | Audit fields (from `AuditableEntity`) |
24
+ | `createdBy` / `lastModifiedBy` | `string` | Audit fields |
25
+
26
+ ## Slug
27
+
28
+ Generated by `SlugGenerator`: lowercased, non-alphanumeric stripped, spaces→hyphens, truncated to max length. Numeric suffix appended for uniqueness.
29
+
30
+ Used by `PublicApiOrganizationResolver` to resolve org by slug or GUID in Public API URLs. Cached 1h sliding.
31
+
32
+ ## Relationships
33
+
34
+ - `AspNetUserEmployees` — users belonging to this organization
35
+
36
+ ## Domain Methods
37
+
38
+ - `ChangeSlug(string?)` — trims and lowercases
39
+ - `ChangeCompanyName(string)`, `ChangeAddressLine(string?)`, etc.
40
+ - `ChangeCustomValues(Dictionary?)` — merges into existing values
41
+ - `DeleteOrganization()` — sets `IsDeleted = true`