@cxtms/cx-schema 1.1.0 → 1.2.1
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/.claude/skills/cx-core/SKILL.md +93 -0
- package/.claude/skills/cx-core/ref-entity-accounting.md +173 -0
- package/.claude/skills/cx-core/ref-entity-commodity.md +205 -0
- package/.claude/skills/cx-core/ref-entity-contact.md +153 -0
- package/.claude/skills/cx-core/ref-entity-geography.md +119 -0
- package/.claude/skills/cx-core/ref-entity-job.md +77 -0
- package/.claude/skills/cx-core/ref-entity-order-sub.md +140 -0
- package/.claude/skills/cx-core/ref-entity-order.md +168 -0
- package/.claude/skills/cx-core/ref-entity-rate.md +174 -0
- package/.claude/skills/cx-core/ref-entity-shared.md +147 -0
- package/.claude/skills/cx-core/ref-entity-warehouse.md +110 -0
- package/.claude/skills/cx-module/SKILL.md +402 -0
- package/.claude/skills/cx-module/ref-components-data.md +286 -0
- package/.claude/skills/cx-module/ref-components-display.md +394 -0
- package/.claude/skills/cx-module/ref-components-forms.md +362 -0
- package/.claude/skills/cx-module/ref-components-interactive.md +306 -0
- package/.claude/skills/cx-module/ref-components-layout.md +295 -0
- package/.claude/skills/cx-module/ref-components-specialized.md +427 -0
- package/.claude/skills/cx-workflow/SKILL.md +330 -0
- package/.claude/skills/cx-workflow/ref-accounting.md +66 -0
- package/.claude/skills/cx-workflow/ref-communication.md +161 -0
- package/.claude/skills/cx-workflow/ref-entity.md +162 -0
- package/.claude/skills/cx-workflow/ref-expressions.md +239 -0
- package/.claude/skills/cx-workflow/ref-filetransfer.md +80 -0
- package/.claude/skills/cx-workflow/ref-flow.md +180 -0
- package/.claude/skills/cx-workflow/ref-other.md +120 -0
- package/.claude/skills/cx-workflow/ref-query.md +85 -0
- package/.claude/skills/cx-workflow/ref-utilities.md +192 -0
- package/dist/cli.js +252 -33
- package/dist/cli.js.map +1 -1
- package/package.json +3 -2
- package/schemas/workflows/tasks/action-event.json +65 -0
- package/schemas/workflows/tasks/all.json +126 -26
- package/schemas/workflows/tasks/appmodule.json +56 -0
- package/schemas/workflows/tasks/attachment.json +4 -1
- package/schemas/workflows/tasks/authentication.json +72 -0
- package/schemas/workflows/tasks/caching.json +68 -0
- package/schemas/workflows/tasks/charge.json +3 -1
- package/schemas/workflows/tasks/commodity.json +3 -0
- package/schemas/workflows/tasks/contact-address.json +72 -0
- package/schemas/workflows/tasks/contact-payment-method.json +72 -0
- package/schemas/workflows/tasks/edi.json +65 -0
- package/schemas/workflows/tasks/filetransfer.json +102 -0
- package/schemas/workflows/tasks/flow-transition.json +68 -0
- package/schemas/workflows/tasks/httpRequest.json +23 -0
- package/schemas/workflows/tasks/import.json +64 -0
- package/schemas/workflows/tasks/inventory.json +67 -0
- package/schemas/workflows/tasks/movement.json +54 -0
- package/schemas/workflows/tasks/note.json +59 -0
- package/schemas/workflows/tasks/number.json +65 -0
- package/schemas/workflows/tasks/order.json +8 -1
- package/schemas/workflows/tasks/pdf-document.json +60 -0
- package/schemas/workflows/tasks/user.json +70 -0
- package/scripts/postinstall.js +2 -2
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Entity CRUD Tasks Reference
|
|
2
|
+
|
|
3
|
+
All entity tasks follow the `Namespace/Operation@Version` pattern. Outputs are stored as `ActivityName.StepName.outputKey`.
|
|
4
|
+
|
|
5
|
+
## Generic Entity Change
|
|
6
|
+
|
|
7
|
+
| Task | Description |
|
|
8
|
+
|------|-------------|
|
|
9
|
+
| `Entity/Change` | Generic entity change (works for any entity type) |
|
|
10
|
+
|
|
11
|
+
## Order
|
|
12
|
+
|
|
13
|
+
| Task | Description |
|
|
14
|
+
|------|-------------|
|
|
15
|
+
| `Order/Create` | Create a new order |
|
|
16
|
+
| `Order/Update` (v1, v2) | Update order fields |
|
|
17
|
+
| `Order/Delete` | Delete an order |
|
|
18
|
+
| `Order/Get` | Get order by ID |
|
|
19
|
+
| `Order/Copy` | Copy/duplicate an order |
|
|
20
|
+
| `Order/Split` | Split order into multiple |
|
|
21
|
+
| `Order/Purge` | Purge order data |
|
|
22
|
+
| `Order/Import` | Import order from external data |
|
|
23
|
+
| `Order/RecalculateCharges` | Recalculate all charges |
|
|
24
|
+
| `Order/GenerateTrackingNumber` | Generate tracking number |
|
|
25
|
+
| `Order/GetCargoMovementByPalletQuery` | Query cargo movements by pallet |
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
- task: "Order/Create@1"
|
|
29
|
+
name: CreateOrder
|
|
30
|
+
inputs:
|
|
31
|
+
orderType: "ParcelShipment"
|
|
32
|
+
entity:
|
|
33
|
+
customer: "{{ inputs.customerId }}"
|
|
34
|
+
status: "Draft"
|
|
35
|
+
outputs:
|
|
36
|
+
- name: order
|
|
37
|
+
mapping: "order"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
- task: "Order/Update@2"
|
|
42
|
+
name: UpdateOrder
|
|
43
|
+
inputs:
|
|
44
|
+
orderId: "{{ inputs.orderId }}"
|
|
45
|
+
entity:
|
|
46
|
+
status: "Active"
|
|
47
|
+
notes: "Updated by workflow"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Contact
|
|
51
|
+
|
|
52
|
+
| Task | Description |
|
|
53
|
+
|------|-------------|
|
|
54
|
+
| `Contact/Create` | Create contact |
|
|
55
|
+
| `Contact/Update` | Update contact |
|
|
56
|
+
| `Contact/Delete` | Delete contact |
|
|
57
|
+
|
|
58
|
+
## Contact Address
|
|
59
|
+
|
|
60
|
+
| Task | Description |
|
|
61
|
+
|------|-------------|
|
|
62
|
+
| `ContactAddress/Create` | Create address |
|
|
63
|
+
| `ContactAddress/Update` | Update address |
|
|
64
|
+
| `ContactAddress/Delete` | Delete address |
|
|
65
|
+
| `ContactAddress/Import` | Bulk import addresses |
|
|
66
|
+
|
|
67
|
+
## Contact Payment Method
|
|
68
|
+
|
|
69
|
+
| Task | Description |
|
|
70
|
+
|------|-------------|
|
|
71
|
+
| `ContactPaymentMethod/Create` | Create payment method |
|
|
72
|
+
| `ContactPaymentMethod/Update` | Update payment method |
|
|
73
|
+
| `ContactPaymentMethod/SendChargedAmount` | Send charged amount notification |
|
|
74
|
+
| `ContactPaymentMethod/VerifyChargedAmount` | Verify charged amount |
|
|
75
|
+
|
|
76
|
+
## Commodity
|
|
77
|
+
|
|
78
|
+
| Task | Description |
|
|
79
|
+
|------|-------------|
|
|
80
|
+
| `Commodity/Create` | Create commodity |
|
|
81
|
+
| `Commodity/Update` (v1, v2) | Update commodity |
|
|
82
|
+
| `Commodity/Split` | Split commodity into multiple |
|
|
83
|
+
| `Commodity/Repack` | Repack commodities |
|
|
84
|
+
| `Commodity/Unpack` | Unpack commodity |
|
|
85
|
+
|
|
86
|
+
## Commodity Tracking Number
|
|
87
|
+
|
|
88
|
+
| Task | Description |
|
|
89
|
+
|------|-------------|
|
|
90
|
+
| `CommodityTrackingNumber/Create` | Create tracking number |
|
|
91
|
+
| `CommodityTrackingNumber/Update` | Update tracking number |
|
|
92
|
+
| `CommodityTrackingNumber/Delete` | Delete tracking number |
|
|
93
|
+
|
|
94
|
+
## Job
|
|
95
|
+
|
|
96
|
+
| Task | Description |
|
|
97
|
+
|------|-------------|
|
|
98
|
+
| `Job/Create` | Create job |
|
|
99
|
+
| `Job/Update` | Update job |
|
|
100
|
+
| `Job/Delete` | Delete job |
|
|
101
|
+
| `Job/Assign` | Assign job to user/driver |
|
|
102
|
+
| `Job/Unassign` | Unassign job |
|
|
103
|
+
|
|
104
|
+
## Charge
|
|
105
|
+
|
|
106
|
+
| Task | Description |
|
|
107
|
+
|------|-------------|
|
|
108
|
+
| `Charge/Create` | Create charge |
|
|
109
|
+
| `Charge/Update` | Update charge |
|
|
110
|
+
| `Charge/Delete` | Delete charge |
|
|
111
|
+
| `Charge/DynamicUpdate` | Dynamic update (partial fields) |
|
|
112
|
+
| `Charge/Calculate` | Calculate charge amount |
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
- task: "Charge/Create@1"
|
|
116
|
+
name: CreateCharge
|
|
117
|
+
inputs:
|
|
118
|
+
orderId: "{{ inputs.orderId }}"
|
|
119
|
+
chargeType: "Freight"
|
|
120
|
+
amount: "{{ Data.GetRate.rate.amount }}"
|
|
121
|
+
currency: "USD"
|
|
122
|
+
outputs:
|
|
123
|
+
- name: charge
|
|
124
|
+
mapping: "charge"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Discount
|
|
128
|
+
|
|
129
|
+
| Task | Description |
|
|
130
|
+
|------|-------------|
|
|
131
|
+
| `Discount/Update` | Update discount |
|
|
132
|
+
|
|
133
|
+
## Order Sub-Entities
|
|
134
|
+
|
|
135
|
+
| Task | Description |
|
|
136
|
+
|------|-------------|
|
|
137
|
+
| `OrderCommodity/Create` | Link commodity to order |
|
|
138
|
+
| `OrderCommodity/Update` | Update order-commodity link |
|
|
139
|
+
| `OrderCommodity/Delete` | Remove commodity from order |
|
|
140
|
+
| `OrderCharge/Create` | Create order charge |
|
|
141
|
+
| `OrderDocument/Create` | Create order document |
|
|
142
|
+
| `OrderDocument/Send` | Send order document |
|
|
143
|
+
| `OrderTrackingEvent/Create` | Create tracking event |
|
|
144
|
+
| `OrderEntity/ChangeCustomValue` | Change custom field value |
|
|
145
|
+
|
|
146
|
+
## Inventory
|
|
147
|
+
|
|
148
|
+
| Task | Description |
|
|
149
|
+
|------|-------------|
|
|
150
|
+
| `InventoryItem/Create` | Create inventory item |
|
|
151
|
+
| `InventoryItem/Update` | Update inventory item |
|
|
152
|
+
| `InventoryItem/Delete` | Delete inventory item |
|
|
153
|
+
|
|
154
|
+
## Other
|
|
155
|
+
|
|
156
|
+
| Task | Description |
|
|
157
|
+
|------|-------------|
|
|
158
|
+
| `Movement/Create` | Create cargo movement |
|
|
159
|
+
| `Country/Create`, `Country/Update`, `Country/Delete` | Country CRUD |
|
|
160
|
+
| `Cities/Import` | Import cities |
|
|
161
|
+
| `Rate/Update` | Update rate |
|
|
162
|
+
| `TrackingEvent/Import` | Import tracking events |
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# Variable References & Expressions
|
|
2
|
+
|
|
3
|
+
There are **two distinct syntaxes** for referencing variables, used in different contexts.
|
|
4
|
+
|
|
5
|
+
## Template Expressions: `{{ path }}` (in step inputs)
|
|
6
|
+
|
|
7
|
+
Used in step `inputs` values. Resolves variable paths from scoped variables.
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
inputs:
|
|
11
|
+
orderId: "{{ inputs.orderId }}" # Simple reference
|
|
12
|
+
url: "{{ chopinConfig.baseUrl }}/api/v1" # String interpolation
|
|
13
|
+
order: "{{ Data.GetOrder.order }}" # Raw object (single {{ }})
|
|
14
|
+
name: "Order {{ Data.GetOrder.order.orderNumber }}" # String interpolation (multiple)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Key behavior**: A single `{{ path }}` returns the **raw object** (preserving type). Multiple `{{ }}` in a string returns string interpolation (each resolved value is `.ToString()`).
|
|
18
|
+
|
|
19
|
+
### Type Converters (prefix in {{ }})
|
|
20
|
+
|
|
21
|
+
```yaml
|
|
22
|
+
organizationId: "{{ int organizationId }}"
|
|
23
|
+
amount: "{{ decimal totalAmount }}"
|
|
24
|
+
isActive: "{{ bool isActive }}"
|
|
25
|
+
flag: "{{ boolOrFalse someFlag }}" # null -> false
|
|
26
|
+
flagOn: "{{ boolOrTrue someFlag }}" # null -> true
|
|
27
|
+
notes: "{{ emptyIfNull notes }}" # null -> ""
|
|
28
|
+
notes: "{{ nullIfEmpty notes }}" # "" or whitespace -> null
|
|
29
|
+
config: "{{ fromJson configJsonString }}" # JSON string -> dict/array
|
|
30
|
+
payload: "{{ toJson someObject }}" # object -> JSON string
|
|
31
|
+
name: "{{ trim value }}"
|
|
32
|
+
search: "{{ luceneString query }}" # escape & quote for Lucene
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
| Converter | Returns | Null handling |
|
|
36
|
+
|-----------|---------|---------------|
|
|
37
|
+
| `string` | `string` | null. Reads `Stream` to string if value is Stream |
|
|
38
|
+
| `int` | `int` | Throws on null |
|
|
39
|
+
| `decimal` | `decimal` | Throws on null |
|
|
40
|
+
| `bool` | `bool` | Throws on null |
|
|
41
|
+
| `boolOrFalse` | `bool` | `false` if null |
|
|
42
|
+
| `boolOrTrue` | `bool` | `true` if null |
|
|
43
|
+
| `datetime` | `DateTime` | Throws on null |
|
|
44
|
+
| `emptyIfNull` | same type | `""` if null, `0` for int?, `0m` for decimal? |
|
|
45
|
+
| `nullIfEmpty` | same type | `null` if empty/whitespace string or empty collection |
|
|
46
|
+
| `luceneString` | `string` | null |
|
|
47
|
+
| `transliterate` | `string` | null (Unicode -> ASCII via Unidecode) |
|
|
48
|
+
| `transliterateUa` | `string` | null (Ukrainian-specific rules) |
|
|
49
|
+
| `fromJson` | `dict` or `array` | null. Empty string -> empty dict |
|
|
50
|
+
| `toJson` | `string` | `""` if null |
|
|
51
|
+
| `trim` | `string` | null |
|
|
52
|
+
|
|
53
|
+
### Value Directives (in YAML input mappings)
|
|
54
|
+
|
|
55
|
+
**`expression`** -- Evaluate NCalc expression as a value:
|
|
56
|
+
```yaml
|
|
57
|
+
amount:
|
|
58
|
+
expression: "[price] * [quantity]"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**`coalesce`** -- First non-null value from a list:
|
|
62
|
+
```yaml
|
|
63
|
+
displayName:
|
|
64
|
+
coalesce:
|
|
65
|
+
- "{{ customer.name? }}"
|
|
66
|
+
- "{{ customer.email? }}"
|
|
67
|
+
- "Unknown"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**`foreach`** (value context) -- Transform collections inline:
|
|
71
|
+
```yaml
|
|
72
|
+
commodities:
|
|
73
|
+
foreach: "sourceCommodities"
|
|
74
|
+
item: "item" # default: "item"
|
|
75
|
+
conditions: "[item.isActive] = true" # optional NCalc filter per item
|
|
76
|
+
continueOnError: false # optional, skip errors
|
|
77
|
+
mapping: # dict -> List<dict>, string -> List<object>
|
|
78
|
+
name: "{{ item.name }}"
|
|
79
|
+
quantity: "{{ item.qty }}"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**`switch`** (value context) -- Value-based switch (case-insensitive match):
|
|
83
|
+
```yaml
|
|
84
|
+
perLb:
|
|
85
|
+
switch: "{{ contact.commissionTier }}"
|
|
86
|
+
cases:
|
|
87
|
+
"tier1": "{{ rate.customValues.commission_per_lb_tier1 }}"
|
|
88
|
+
"tier2": "{{ rate.customValues.commission_per_lb_tier2 }}"
|
|
89
|
+
default: "0"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**`extends`** -- Extend/merge an existing object or array:
|
|
93
|
+
```yaml
|
|
94
|
+
orderData:
|
|
95
|
+
extends: "{{ existingOrder }}" # base object or array
|
|
96
|
+
defaultIfNull: {} # fallback if extends is null
|
|
97
|
+
mapping: # dict: merge overrides. array: append items
|
|
98
|
+
status: "Updated"
|
|
99
|
+
notes: "{{ newNotes }}"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**`$raw`** -- Prevent template parsing (pass as-is):
|
|
103
|
+
```yaml
|
|
104
|
+
template:
|
|
105
|
+
$raw: "This {{ won't }} be parsed"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**`$eval`** -- Parse JSON string then evaluate as template:
|
|
109
|
+
```yaml
|
|
110
|
+
dynamicConfig:
|
|
111
|
+
$eval: "{{ configJsonString }}"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**`decrypt`** / **`encrypt`** -- AES-CBC encryption (optional key/IV, has defaults):
|
|
115
|
+
```yaml
|
|
116
|
+
apiKey:
|
|
117
|
+
decrypt:
|
|
118
|
+
encryptedValue: "{{ encryptedApiKey }}"
|
|
119
|
+
key: "{{ encryptionKey }}" # optional Base64 AES key
|
|
120
|
+
initializationVector: "{{ iv }}" # optional Base64 IV
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## NCalc Expressions: `[variable]` (in conditions and expression directives)
|
|
126
|
+
|
|
127
|
+
Used in `conditions[].expression`, `switch` case `when`, and `expression:` value directives. Variables use **square bracket** `[name]` syntax.
|
|
128
|
+
|
|
129
|
+
```yaml
|
|
130
|
+
conditions:
|
|
131
|
+
- expression: "[status] = 'Active' AND [amount] > 100"
|
|
132
|
+
- expression: "isNullOrEmpty([Data.GetOrder.order?]) = false"
|
|
133
|
+
- expression: "any([changes], [each.key] = 'Status') = true"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Parameter resolution rules**:
|
|
137
|
+
- Empty strings are converted to `null` (so `""` is treated as no value)
|
|
138
|
+
- Numeric strings are auto-converted to `decimal` when needed (e.g., `[price] > 100` works even if price is the string `"150"`)
|
|
139
|
+
- Dot paths resolve deep: `[Activity.Step.output.nested.field]`
|
|
140
|
+
- Optional suffix `?` prevents errors: `[order.customer?.name?]`
|
|
141
|
+
|
|
142
|
+
### Operators
|
|
143
|
+
|
|
144
|
+
| Type | Operators |
|
|
145
|
+
|------|-----------|
|
|
146
|
+
| Comparison | `=`, `!=`, `<>`, `<`, `>`, `<=`, `>=` |
|
|
147
|
+
| Logical | `AND`, `OR`, `NOT` (also `&&`, `\|\|`, `!`) |
|
|
148
|
+
| Arithmetic | `+`, `-`, `*`, `/`, `%` |
|
|
149
|
+
| Ternary | `if(condition, trueVal, falseVal)` |
|
|
150
|
+
| Membership | `in(value, val1, val2, ...)` |
|
|
151
|
+
|
|
152
|
+
### Iterator Variables
|
|
153
|
+
|
|
154
|
+
Functions use two iterator variable names:
|
|
155
|
+
- **`[each.*]`** -- used by: `any`, `all`, `sum`, `join` (3-arg)
|
|
156
|
+
- **`[item.*]`** -- used by: `first`, `last`, `groupBy`
|
|
157
|
+
|
|
158
|
+
### Collection Functions
|
|
159
|
+
|
|
160
|
+
| Function | Description |
|
|
161
|
+
|----------|-------------|
|
|
162
|
+
| `any([items], [each.prop] = 'val')` | True if any item matches expression. Without expression: checks if collection contains the value |
|
|
163
|
+
| `all([items], [each.prop] > 0)` | True if all items match. Returns `false` for null/empty collections |
|
|
164
|
+
| `count([items])` | Count items in list or JToken. Returns `0` for non-collections |
|
|
165
|
+
| `sum([items], [each.amount])` | Sum values as `decimal`. Optional `[each.*]` accessor. Skips nulls |
|
|
166
|
+
| `first([items])` or `first([items], [item.name])` | First item or evaluate expression on first item. Returns `""` if empty |
|
|
167
|
+
| `last([items])` or `last([items], [item.name])` | Last item or evaluate expression on last item. Returns `""` if empty |
|
|
168
|
+
| `distinct([items])` | Remove duplicates. Uses deep comparison for dictionaries |
|
|
169
|
+
| `reverse([items])` | Reverse collection or string |
|
|
170
|
+
| `contains([source], 'needle')` | String contains, JArray contains, list contains, or dict key/value contains |
|
|
171
|
+
| `removeEmpty([items])` | Remove null and whitespace-only items |
|
|
172
|
+
| `concat([list1], [list2], ...)` | Concatenate multiple collections into flat list. Variadic args. Skips nulls |
|
|
173
|
+
| `groupBy([items], [item.cat])` | Group by one or more key expressions. Returns `[{key, items}]`. Multi-key: keys joined with `\|` |
|
|
174
|
+
| `join([items], [each.name], ',')` | Join collection with `[each.*]` accessor and separator (3-arg) |
|
|
175
|
+
| `join([items], ',')` | Join collection directly with separator (2-arg) |
|
|
176
|
+
| `split([str], ' ')` | Split string by first character of separator. Returns `List<string>` |
|
|
177
|
+
|
|
178
|
+
### String Functions
|
|
179
|
+
|
|
180
|
+
| Function | Description |
|
|
181
|
+
|----------|-------------|
|
|
182
|
+
| `isNullOrEmpty([var])` | True if null, empty string, or empty list |
|
|
183
|
+
| `length([var])` | String length or collection count. `0` for null strings and non-collections |
|
|
184
|
+
| `lower([name])` / `upper([code])` | Case conversion. Handles string, JToken, any `.ToString()` |
|
|
185
|
+
| `left([code], 3)` / `right([code], 3)` | Left/right N characters. Returns full string if shorter than N |
|
|
186
|
+
| `replace([str], 'old', 'new')` | String replacement. Returns null if any arg is null |
|
|
187
|
+
| `trim([value])` | Trim whitespace. Returns `""` for null |
|
|
188
|
+
| `format('{0}-{1}', [prefix], [id])` | String.Format style. Variadic args. Returns null if format is null |
|
|
189
|
+
| `base64([value])` / `fromBase64([encoded])` | Base64 encode/decode. Handles string, byte[], JToken |
|
|
190
|
+
| `bool([value])` | Convert to boolean: null->`false`, empty string->`false`, "true"/"false"->parsed, non-zero number->`true`, any object->`true` |
|
|
191
|
+
| `transliterate([value])` | Unicode to ASCII (Unidecode). Returns `""` for null |
|
|
192
|
+
| `transliterateUa([value])` | Ukrainian-specific transliteration. Returns `""` for null |
|
|
193
|
+
| `parseAddress([address])` | Parse address -> `{StreetNumber, StreetName}`. Handles US and EU formats |
|
|
194
|
+
|
|
195
|
+
### Date Functions
|
|
196
|
+
|
|
197
|
+
| Function | Description |
|
|
198
|
+
|----------|-------------|
|
|
199
|
+
| `now()` | Current UTC `DateTime` |
|
|
200
|
+
| `now('yyyy-MM-dd', 'en-US')` | Formatted current time as string |
|
|
201
|
+
| `addDays([date], 30)` | Add days (decimal, can be negative). Accepts DateTime, DateTimeOffset, string |
|
|
202
|
+
| `addHours([date], 2)` | Add hours (decimal, can be negative). Same type handling |
|
|
203
|
+
| `formatDate([date], 'dd/MM/yyyy', 'en-US')` | Format date with culture. Accepts DateTime or string |
|
|
204
|
+
| `dateFromUnix([unixTime])` | Unix timestamp (seconds) -> `DateTimeOffset`. Accepts int, long, decimal, string |
|
|
205
|
+
| `dateToUtc([date])` or `dateToUtc([date], 'en-US')` | Convert to UTC. Optional culture for string parsing |
|
|
206
|
+
|
|
207
|
+
### Math Functions (NCalc built-in)
|
|
208
|
+
|
|
209
|
+
`Abs(x)`, `Ceiling(x)`, `Floor(x)`, `Round(x, decimals)`, `Min(x, y)`, `Max(x, y)`, `Pow(x, y)`, `Sqrt(x)`, `Truncate(x)`
|
|
210
|
+
|
|
211
|
+
Custom: `ceiling([value])` -- same as `Ceiling` but handles type conversion to double.
|
|
212
|
+
|
|
213
|
+
### Domain Functions
|
|
214
|
+
|
|
215
|
+
| Function | Description |
|
|
216
|
+
|----------|-------------|
|
|
217
|
+
| `convertWeight([weight], 'Kg', 'Lb')` | Weight unit conversion. Returns `decimal` rounded to 5 places |
|
|
218
|
+
| `convertDimension([length], 'Cm', 'In')` | Dimension unit conversion. Returns `decimal` rounded to 3 places |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Property Path Syntax (in collection, mapping, variable paths)
|
|
223
|
+
|
|
224
|
+
Used in `collection:` (foreach), `mapping:` (outputs), and variable resolution.
|
|
225
|
+
|
|
226
|
+
| Pattern | Description | Example |
|
|
227
|
+
|---------|-------------|---------|
|
|
228
|
+
| `a.b.c` | Dot-separated nested path | `order.customer.name` |
|
|
229
|
+
| `prop?` | Optional access (null if missing) | `order.customer?.name?` |
|
|
230
|
+
| `list[0]` | Array index | `items[0]` |
|
|
231
|
+
| `list[^1]` | Index from end (last item) | `items[^1]` |
|
|
232
|
+
| `list[*]` | Flatten/wildcard (all items) | `containers[*].commodities` |
|
|
233
|
+
| `list[**]` | Recursive flatten (all depths) | `containerCommodities[**]` |
|
|
234
|
+
| `list[-1]` | Depth filter (leaves only) | `tree[**][-1]` |
|
|
235
|
+
| `list[condition]` | Filter by condition | `items[status=Active]` |
|
|
236
|
+
| `dict['key']` | Dictionary key access | `customValues['myField']` |
|
|
237
|
+
| `list[*].{f1 f2}` | Field selector (projection) | `items[*].{name description}` |
|
|
238
|
+
| `list[*].{alias:source}` | Field selector with alias | `items[*].{id:commodityId}` |
|
|
239
|
+
| `list[*].{alias:_.parent}` | Field selector referencing parent | `items[*].{parentId:_.orderId}` |
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# File Transfer Tasks Reference
|
|
2
|
+
|
|
3
|
+
SFTP/FTP file transfer operations. Use `FileTransfer/Connect` to establish a session, perform file operations, then `FileTransfer/Disconnect`.
|
|
4
|
+
|
|
5
|
+
## Connection Lifecycle
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
activities:
|
|
9
|
+
- name: Transfer
|
|
10
|
+
steps:
|
|
11
|
+
- task: "FileTransfer/Connect@1"
|
|
12
|
+
name: Connect
|
|
13
|
+
inputs:
|
|
14
|
+
host: "{{ sftpConfig.host }}"
|
|
15
|
+
port: "{{ sftpConfig.port }}"
|
|
16
|
+
username: "{{ sftpConfig.username }}"
|
|
17
|
+
password: "{{ sftpConfig.password }}"
|
|
18
|
+
protocol: "sftp"
|
|
19
|
+
outputs:
|
|
20
|
+
- name: connection
|
|
21
|
+
mapping: "connection"
|
|
22
|
+
|
|
23
|
+
- task: "FileTransfer/ListFiles@1"
|
|
24
|
+
name: ListFiles
|
|
25
|
+
inputs:
|
|
26
|
+
connection: "{{ Transfer.Connect.connection }}"
|
|
27
|
+
path: "/incoming"
|
|
28
|
+
outputs:
|
|
29
|
+
- name: files
|
|
30
|
+
mapping: "files"
|
|
31
|
+
|
|
32
|
+
- task: foreach
|
|
33
|
+
name: ProcessFiles
|
|
34
|
+
collection: "Transfer.ListFiles.files"
|
|
35
|
+
item: "file"
|
|
36
|
+
steps:
|
|
37
|
+
- task: "FileTransfer/DownloadFile@1"
|
|
38
|
+
name: Download
|
|
39
|
+
inputs:
|
|
40
|
+
connection: "{{ Transfer.Connect.connection }}"
|
|
41
|
+
path: "{{ file.path }}"
|
|
42
|
+
outputs:
|
|
43
|
+
- name: content
|
|
44
|
+
mapping: "content"
|
|
45
|
+
|
|
46
|
+
- task: "FileTransfer/MoveFile@1"
|
|
47
|
+
name: Archive
|
|
48
|
+
inputs:
|
|
49
|
+
connection: "{{ Transfer.Connect.connection }}"
|
|
50
|
+
sourcePath: "{{ file.path }}"
|
|
51
|
+
destinationPath: "/processed/{{ file.name }}"
|
|
52
|
+
|
|
53
|
+
- task: "FileTransfer/Disconnect@1"
|
|
54
|
+
name: Disconnect
|
|
55
|
+
inputs:
|
|
56
|
+
connection: "{{ Transfer.Connect.connection }}"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Available Tasks
|
|
60
|
+
|
|
61
|
+
| Task | Description |
|
|
62
|
+
|------|-------------|
|
|
63
|
+
| `FileTransfer/Connect` | Establish SFTP/FTP connection |
|
|
64
|
+
| `FileTransfer/Disconnect` | Close connection |
|
|
65
|
+
| `FileTransfer/ListFiles` | List files in remote directory |
|
|
66
|
+
| `FileTransfer/DownloadFile` | Download file content |
|
|
67
|
+
| `FileTransfer/UploadFile` | Upload file to remote |
|
|
68
|
+
| `FileTransfer/MoveFile` | Move/rename remote file |
|
|
69
|
+
| `FileTransfer/DeleteFile` | Delete remote file |
|
|
70
|
+
|
|
71
|
+
## Upload Example
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
- task: "FileTransfer/UploadFile@1"
|
|
75
|
+
name: Upload
|
|
76
|
+
inputs:
|
|
77
|
+
connection: "{{ Transfer.Connect.connection }}"
|
|
78
|
+
path: "/outgoing/report.csv"
|
|
79
|
+
content: "{{ GenerateReport.Export.file }}"
|
|
80
|
+
```
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Flow Workflow YAML Reference
|
|
2
|
+
|
|
3
|
+
Flow workflows are declarative state machines for entity lifecycle management. Use `workflowType: Flow` in the workflow section.
|
|
4
|
+
|
|
5
|
+
## Top-Level Structure
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
workflow:
|
|
9
|
+
workflowId: "<uuid>"
|
|
10
|
+
name: "Flow Workflow Name"
|
|
11
|
+
workflowType: Flow # Required - identifies this as a Flow workflow
|
|
12
|
+
executionMode: Async
|
|
13
|
+
isActive: true
|
|
14
|
+
priority: 75 # 0-100, default 50
|
|
15
|
+
tags: ["tag1"]
|
|
16
|
+
agentInstruction: "AI guidance" # Optional
|
|
17
|
+
concurrency:
|
|
18
|
+
enabled: true
|
|
19
|
+
group: "groupName"
|
|
20
|
+
waitTime: 30
|
|
21
|
+
|
|
22
|
+
entity: # Required for Flow (replaces activities)
|
|
23
|
+
name: <EntityName>
|
|
24
|
+
type: <EntityType> # Required for Order, AccountingTransaction, Contact
|
|
25
|
+
includes: [<navigation-paths>] # Optional
|
|
26
|
+
query: "<graphql-query>" # Optional
|
|
27
|
+
|
|
28
|
+
states: [...] # Required, at least 1 state
|
|
29
|
+
transitions: [...] # Required, at least 1 transition
|
|
30
|
+
aggregations: [...] # Optional
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Entity Section
|
|
34
|
+
|
|
35
|
+
Specifies which entity's lifecycle this flow manages.
|
|
36
|
+
|
|
37
|
+
### Valid Entity Names
|
|
38
|
+
Order, Commodity, AccountingTransaction, Workflow, OrganizationConfig, Contact, AppModule, Attachment, OrderCommodity, TrackingEvent, JobOrder
|
|
39
|
+
|
|
40
|
+
### Entity Types (required for specific entities)
|
|
41
|
+
|
|
42
|
+
**Order** requires type: Brokerage, ParcelShipment, Quote, WarehouseReceipt, AirShipmentOrder, OceanShipmentOrder, LoadOrder, DeliveryOrder
|
|
43
|
+
**AccountingTransaction** requires type: Invoice, Bill, CreditMemo
|
|
44
|
+
**Contact** requires type: Customer, Carrier, Vendor, Driver, Employee
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
entity:
|
|
48
|
+
name: Order
|
|
49
|
+
type: ParcelShipment
|
|
50
|
+
includes:
|
|
51
|
+
- Commodities
|
|
52
|
+
- Customer
|
|
53
|
+
- Charges
|
|
54
|
+
query: "{ commodities { id, quantity }, customer { name, email } }"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## States Section
|
|
58
|
+
|
|
59
|
+
Each state represents a status in the entity lifecycle.
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
states:
|
|
63
|
+
- name: Draft # Required, unique
|
|
64
|
+
stage: Entry # Optional grouping label
|
|
65
|
+
isInitial: true # At most 1 initial state
|
|
66
|
+
- name: Active
|
|
67
|
+
stage: Processing
|
|
68
|
+
- name: AwaitingPickup
|
|
69
|
+
parent: Active # Hierarchical state
|
|
70
|
+
- name: InTransit
|
|
71
|
+
parent: Active
|
|
72
|
+
onEnter: # Steps on entering this state
|
|
73
|
+
- task: "Email/Send"
|
|
74
|
+
inputs:
|
|
75
|
+
template: in_transit_notification
|
|
76
|
+
onExit: # Steps on exiting this state
|
|
77
|
+
- task: "Utilities/Log@1"
|
|
78
|
+
inputs:
|
|
79
|
+
message: "Leaving InTransit"
|
|
80
|
+
- name: Delivered
|
|
81
|
+
stage: Complete
|
|
82
|
+
isFinal: true # Terminal state, no outgoing transitions
|
|
83
|
+
requireConfirmation: true # User must confirm before entering
|
|
84
|
+
query: "{ charges { id, amount } }" # State-specific data query
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### State Rules
|
|
88
|
+
- **name**: Required, must be unique across all states
|
|
89
|
+
- **isInitial**: At most one state can be initial
|
|
90
|
+
- **isFinal**: Final states cannot be transition sources
|
|
91
|
+
- **parent**: References another state; parent cannot be initial or final; children inherit parent transitions
|
|
92
|
+
|
|
93
|
+
## Transitions Section
|
|
94
|
+
|
|
95
|
+
Define how entities move between states.
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
transitions:
|
|
99
|
+
- name: submit # Required, unique
|
|
100
|
+
displayName: "Submit Order" # Optional UI label
|
|
101
|
+
from: Draft # Single state
|
|
102
|
+
to: Submitted # Must be a leaf state (no children)
|
|
103
|
+
trigger: manual # manual | auto | event
|
|
104
|
+
|
|
105
|
+
- name: auto_approve
|
|
106
|
+
from: Submitted
|
|
107
|
+
to: Approved
|
|
108
|
+
trigger: auto # Evaluated automatically
|
|
109
|
+
priority: 10 # Higher = checked first (default 50)
|
|
110
|
+
conditions:
|
|
111
|
+
- expression: "Order.Amount < 1000"
|
|
112
|
+
|
|
113
|
+
- name: payment_received
|
|
114
|
+
from: AwaitingPayment
|
|
115
|
+
to: Paid
|
|
116
|
+
trigger: event # External event-driven
|
|
117
|
+
eventName: PaymentConfirmed # Required when trigger is 'event'
|
|
118
|
+
|
|
119
|
+
- name: bulk_transition
|
|
120
|
+
from: # Array of source states
|
|
121
|
+
- Draft
|
|
122
|
+
- Submitted
|
|
123
|
+
to: Cancelled
|
|
124
|
+
trigger: manual
|
|
125
|
+
|
|
126
|
+
- name: force_cancel
|
|
127
|
+
from: "*" # Wildcard: any non-final state
|
|
128
|
+
to: Cancelled
|
|
129
|
+
trigger: manual
|
|
130
|
+
steps: # Steps during transition
|
|
131
|
+
- task: "Utilities/Log@1"
|
|
132
|
+
inputs:
|
|
133
|
+
message: "Force cancelled"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Trigger Types
|
|
137
|
+
- **manual**: User-initiated or API call
|
|
138
|
+
- **auto**: Automatic evaluation based on conditions; sorted by priority descending
|
|
139
|
+
- **event**: External event-driven; requires `eventName`
|
|
140
|
+
|
|
141
|
+
### From States
|
|
142
|
+
- Single state: `from: Draft`
|
|
143
|
+
- Multiple states: `from: [Draft, Submitted]`
|
|
144
|
+
- Wildcard (any non-final state): `from: "*"`
|
|
145
|
+
|
|
146
|
+
### Execution Order
|
|
147
|
+
1. Validate transition from current state
|
|
148
|
+
2. Execute `onExit` steps (from source state)
|
|
149
|
+
3. Execute transition `steps`
|
|
150
|
+
4. Update entity status
|
|
151
|
+
5. Execute `onEnter` steps (on target state)
|
|
152
|
+
|
|
153
|
+
## Aggregations Section
|
|
154
|
+
|
|
155
|
+
Reusable data queries for conditions.
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
aggregations:
|
|
159
|
+
- name: allItemsReceived # Required, unique
|
|
160
|
+
expression: "all(Order.Commodities, item.ReceivedQuantity >= item.Quantity)"
|
|
161
|
+
- name: totalWeight
|
|
162
|
+
expression: "sum(Order.Commodities, item.Weight)"
|
|
163
|
+
- name: hasAnyDamaged
|
|
164
|
+
expression: "any(Order.Commodities, item.IsDamaged)"
|
|
165
|
+
- name: itemCount
|
|
166
|
+
expression: "count(Order.Commodities)"
|
|
167
|
+
- name: chargesByType
|
|
168
|
+
expression: "sum(Order.Charges, item.Amount)"
|
|
169
|
+
parameter: chargeType # Optional parameter
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Valid Aggregation Functions
|
|
173
|
+
- **all(collection, predicate)** - All items match
|
|
174
|
+
- **any(collection, predicate)** - At least one matches
|
|
175
|
+
- **sum(collection, selector)** - Sum values
|
|
176
|
+
- **count(collection)** - Count items
|
|
177
|
+
- **first(collection)** - First item
|
|
178
|
+
- **last(collection)** - Last item
|
|
179
|
+
- **distinct(collection, selector)** - Unique values
|
|
180
|
+
- **groupBy(collection, selector)** - Group by value
|