truflow 0.0.188 → 0.0.190

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 (42) hide show
  1. package/dist/Helpers/IOrders/IMoveOrder.d.ts +1 -1
  2. package/dist/Helpers/IZapier/index.d.ts +7 -6
  3. package/dist/IAutomation.d.ts +197 -0
  4. package/dist/IDailyTotal.d.ts +6 -0
  5. package/dist/IExporter.d.ts +1 -0
  6. package/dist/IExpress.d.ts +2 -0
  7. package/dist/IExpress.js +1 -0
  8. package/dist/IInventory.d.ts +37 -2
  9. package/dist/IMailCache.d.ts +13 -0
  10. package/dist/IOrder.d.ts +1 -1
  11. package/dist/ISchedule.d.ts +119 -0
  12. package/dist/ISetting.d.ts +31 -2
  13. package/dist/ISupplier.d.ts +1 -0
  14. package/dist/Inventory/IInventoryTransfer.d.ts +122 -0
  15. package/dist/Inventory/IInventoryTransfer.js +2 -0
  16. package/dist/Inventory/ILocation.d.ts +6 -0
  17. package/dist/{IInventoryLocation.d.ts → Inventory/ISelectFieldDefinition.d.ts} +20 -34
  18. package/dist/Inventory/ISelectFieldDefinition.js +2 -0
  19. package/dist/index.d.ts +4 -0
  20. package/dist/index.js +4 -0
  21. package/package-lock.json +2180 -0
  22. package/package.json +13 -4
  23. package/src/Helpers/IOrders/IMoveOrder.ts +1 -1
  24. package/src/Helpers/IZapier/index.ts +9 -6
  25. package/src/IAutomation.ts +264 -0
  26. package/src/IDailyTotal.ts +7 -0
  27. package/src/IExporter.ts +1 -0
  28. package/src/IExpress.ts +1 -0
  29. package/src/IIntegration.ts +1 -0
  30. package/src/IInventory.ts +40 -2
  31. package/src/IMailCache.ts +14 -0
  32. package/src/IOrder.ts +1 -1
  33. package/src/ISchedule.ts +125 -0
  34. package/src/ISetting.ts +49 -2
  35. package/src/ISupplier.ts +1 -0
  36. package/src/Inventory/IInventoryTransfer.ts +108 -0
  37. package/src/Inventory/ILocation.ts +12 -0
  38. package/src/Inventory/ISelectFieldDefinition.ts +29 -0
  39. package/src/index.ts +4 -0
  40. package/dist/ILocation.d.ts +0 -75
  41. /package/dist/{IInventoryLocation.js → IAutomation.js} +0 -0
  42. /package/dist/{ILocation.js → ISchedule.js} +0 -0
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "truflow",
3
- "version": "0.0.188",
3
+ "version": "0.0.190",
4
4
  "main": "./dist/index.js",
5
5
  "license": "MIT",
6
6
  "scripts": {
7
7
  "build": "tsc",
8
+ "watch": "tsc --watch",
8
9
  "prepublish": "tsc"
9
10
  },
10
11
  "dependencies": {
@@ -12,8 +13,16 @@
12
13
  "@types/express": "^4.17.17",
13
14
  "@types/luxon": "^3.3.0",
14
15
  "mongoose": "^7.3.4",
15
- "socket.io": "^4.7.5",
16
- "typescript": "^5.1.6"
16
+ "socket.io": "^4.7.5"
17
17
  },
18
- "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
18
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
19
+ "devDependencies": {
20
+ "@hokify/agenda": "^6.3.0",
21
+ "@types/node": "^24.10.1",
22
+ "express": "^5.2.1",
23
+ "luxon": "^3.7.2",
24
+ "mongoose": "^9.0.1",
25
+ "socket.io": "^4.8.1",
26
+ "typescript": "5.3.3"
27
+ }
19
28
  }
@@ -5,7 +5,7 @@ export interface IMoveOrderTotalsData {
5
5
  startDate: string;
6
6
  updatedStartDate: string;
7
7
  entries: {
8
- limitsGroup: string;
8
+ productionLine: string;
9
9
  quantity: number;
10
10
  }[];
11
11
  }
@@ -1,25 +1,28 @@
1
1
  import { DateTime } from "luxon";
2
- import { ILimit } from "../../ISetting";
2
+ import { IProductionLine } from "../../ISetting";
3
3
  import { IZapierOrder } from "../../Routes/IZapierRoutes";
4
4
  import { IOrderProduct, IOrder } from "../../IOrder";
5
5
  import mongoose from "mongoose";
6
6
 
7
- export type IFetchLimits = (type: string) => Promise<ILimit>;
7
+ export type IFetchProductionLines = (type: string) => Promise<IProductionLine>;
8
+ // Backward compatibility alias
9
+ export type IFetchLimits = IFetchProductionLines;
8
10
 
9
11
  export type ICalculateInitialStartDate = (
10
12
  shipDate: DateTime,
11
- limits: ILimit
13
+ productionLine: IProductionLine
12
14
  ) => Promise<{ startDate: DateTime; isHighlighted: boolean }>;
13
15
 
14
16
  export type ICheckDailyTotals = (
15
17
  date: string,
16
18
  quantity: number,
17
- limitData: ILimit
19
+ productionLineData: IProductionLine
18
20
  ) => Promise<{ result: boolean; exists?: boolean } | boolean>;
19
21
 
20
22
  export type ICalculateStartDate = (
21
23
  startDate: DateTime,
22
- isHighlighted: boolean
24
+ isHighlighted: boolean,
25
+ productionLineId?: string
23
26
  ) => Promise<{ startDate: DateTime; isHighlighted: boolean }>;
24
27
 
25
28
  export type ICalculateRPD = (
@@ -29,7 +32,7 @@ export type ICalculateRPD = (
29
32
 
30
33
  export type ICalculateShipDate = (
31
34
  startDate: DateTime,
32
- limits: ILimit
35
+ productionLine: IProductionLine
33
36
  ) => Promise<DateTime>;
34
37
 
35
38
  export type ICalculateStartDates = (
@@ -0,0 +1,264 @@
1
+ import mongoose, { Document } from "mongoose";
2
+
3
+ // Trigger types that can start an automation
4
+ export type AutomationTriggerType =
5
+ | "order.created" // When a new order is created
6
+ | "order.updated" // When an order is updated
7
+ | "order.status_changed" // When order status changes
8
+ | "schedule.entry_added" // When order matches schedule filters and is added
9
+ | "schedule.field_changed" // When a custom schedule field value changes
10
+ | "measurement.added" // When a measurement is added to an order product
11
+ | "measurement.completed"; // When all measurements are completed for an order
12
+
13
+ // Action types that can be executed
14
+ export type AutomationActionType =
15
+ | "webhook" // Trigger a webhook (HTTP request)
16
+ | "email" // Send an email
17
+ | "notification" // Send in-app notification to user(s)
18
+ | "sms" // Send SMS/text message
19
+ | "slack" // Post to Slack channel
20
+ | "update_field" // Update order or schedule entry field
21
+ | "add_note"; // Add a note to the order
22
+
23
+ // Condition operators for filtering
24
+ export type AutomationConditionOperator =
25
+ | "equals"
26
+ | "notEquals"
27
+ | "contains"
28
+ | "notContains"
29
+ | "greaterThan"
30
+ | "lessThan"
31
+ | "greaterThanOrEqual"
32
+ | "lessThanOrEqual"
33
+ | "exists"
34
+ | "notExists"
35
+ | "in" // Value is in array
36
+ | "notIn"; // Value is not in array
37
+
38
+ // Condition for filtering when automation should run
39
+ export interface IAutomationCondition {
40
+ field: string; // e.g., "status", "allmoxyData.productAttributes.finish_color"
41
+ operator: AutomationConditionOperator;
42
+ value?: string | number; // Value to compare against (not needed for exists/notExists)
43
+ }
44
+
45
+ // Filter operators with more options
46
+ export type AutomationFilterOperator = AutomationConditionOperator;
47
+
48
+ // Logic operator for combining multiple filters
49
+ export type AutomationFilterLogic = "AND" | "OR";
50
+
51
+ // Individual filter definition
52
+ export interface IAutomationFilter {
53
+ field: string; // Field to check (e.g., "order.companyName", "measurement.width")
54
+ operator: AutomationFilterOperator;
55
+ value?: any; // Value to compare against (can be string, number, array for in/notIn)
56
+ enabled?: boolean; // Allow temporarily disabling individual filters
57
+ }
58
+
59
+ // Filter group that can be AND/OR combined
60
+ export interface IAutomationFilterGroup {
61
+ logic: AutomationFilterLogic; // How to combine filters in this group (AND/OR)
62
+ filters: IAutomationFilter[]; // Individual filters in the group
63
+ }
64
+
65
+ // Result of evaluating a single filter
66
+ export interface IAutomationFilterEvaluationResult {
67
+ filter: IAutomationFilter;
68
+ matched: boolean;
69
+ actualValue?: any; // The actual value that was checked
70
+ reason?: string; // Human-readable reason for match/no-match
71
+ }
72
+
73
+ // Result of evaluating all filters
74
+ export interface IAutomationFiltersEvaluationResult {
75
+ matched: boolean; // Overall result: did filters pass?
76
+ filterResults: IAutomationFilterEvaluationResult[]; // Results for each filter
77
+ logic: AutomationFilterLogic; // Logic used to combine filters
78
+ }
79
+
80
+ // Webhook action configuration
81
+ export interface IAutomationWebhookAction {
82
+ type: "webhook";
83
+ url: string; // Webhook URL
84
+ method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; // HTTP method (default: POST)
85
+ queryParams?: Record<string, string>; // Optional query parameters
86
+ headers?: Record<string, string>; // Optional custom headers
87
+ body?: Record<string, any>; // Optional custom body template (not used for GET)
88
+ }
89
+
90
+ // Email action configuration
91
+ export interface IAutomationEmailAction {
92
+ type: "email";
93
+ to: string[]; // Array of email addresses (can use template variables)
94
+ subject: string; // Email subject (can use template variables)
95
+ body: string; // Email body (can use template variables)
96
+ cc?: string[]; // Optional CC addresses
97
+ bcc?: string[]; // Optional BCC addresses
98
+ }
99
+
100
+ // Notification action configuration
101
+ export interface IAutomationNotificationAction {
102
+ type: "notification";
103
+ userIds: string[]; // Array of user IDs to notify (can be empty for dynamic)
104
+ title: string; // Notification title (can use template variables)
105
+ message: string; // Notification message (can use template variables)
106
+ notificationType: "info" | "success" | "warning" | "error";
107
+ }
108
+
109
+ // SMS action configuration
110
+ export interface IAutomationSMSAction {
111
+ type: "sms";
112
+ phoneNumbers: string[]; // Array of phone numbers (can use template variables)
113
+ message: string; // SMS message (can use template variables)
114
+ }
115
+
116
+ // Slack action configuration
117
+ export interface IAutomationSlackAction {
118
+ type: "slack";
119
+ channel: string; // Slack channel (e.g., "#general" or webhook URL)
120
+ message: string; // Message to post (can use template variables)
121
+ username?: string; // Optional bot username
122
+ iconEmoji?: string; // Optional emoji icon (e.g., ":robot_face:")
123
+ }
124
+
125
+ // Update field action configuration
126
+ export interface IAutomationUpdateFieldAction {
127
+ type: "update_field";
128
+ targetType: "order" | "scheduleEntry"; // What to update
129
+ fieldName: string; // Field to update (e.g., "status", "customStatus.drill_specs_confirmed")
130
+ value: string; // New value (can use template variables)
131
+ }
132
+
133
+ // Add note action configuration
134
+ export interface IAutomationAddNoteAction {
135
+ type: "add_note";
136
+ noteText: string; // Note text (can use template variables)
137
+ mentionUserIds?: string[]; // Optional user IDs to mention
138
+ }
139
+
140
+ // Union type for all action configurations
141
+ export type IAutomationAction =
142
+ | IAutomationWebhookAction
143
+ | IAutomationEmailAction
144
+ | IAutomationNotificationAction
145
+ | IAutomationSMSAction
146
+ | IAutomationSlackAction
147
+ | IAutomationUpdateFieldAction
148
+ | IAutomationAddNoteAction;
149
+
150
+ // Main automation configuration
151
+ export interface ILeanAutomation {
152
+ _id: mongoose.Types.ObjectId;
153
+ name: string; // Human-readable name for the automation
154
+ description?: string; // Optional description
155
+ enabled: boolean; // Whether the automation is active
156
+
157
+ // Trigger configuration
158
+ triggerType: AutomationTriggerType; // What event triggers this automation
159
+
160
+ // Filters - Pre-conditions that must be met before running
161
+ filters?: IAutomationFilterGroup; // Filter group with AND/OR logic
162
+
163
+ // Conditions (DEPRECATED - use filters instead, kept for backwards compatibility)
164
+ conditions?: IAutomationCondition[]; // Optional conditions that must be met
165
+
166
+ // Optional: Link to specific schedule (for schedule-related triggers)
167
+ scheduleId?: mongoose.Types.ObjectId;
168
+
169
+ // Actions to execute when triggered
170
+ actions: IAutomationAction[]; // Array of actions to perform
171
+
172
+ // Metadata
173
+ createdBy?: mongoose.Types.ObjectId; // User who created this automation
174
+ lastTriggeredAt?: Date; // Last time this automation ran
175
+ triggerCount?: number; // Number of times this automation has been triggered
176
+
177
+ createdAt?: Date;
178
+ updatedAt?: Date;
179
+ }
180
+
181
+ export type IAutomation = ILeanAutomation & Document;
182
+
183
+ // Context data passed to automation for template variable replacement
184
+ export interface IAutomationContext {
185
+ order?: {
186
+ id: number;
187
+ name: string;
188
+ companyName: string;
189
+ status: string;
190
+ shipDate: string;
191
+ orderProducts?: any[];
192
+ [key: string]: any;
193
+ };
194
+ orderProduct?: {
195
+ id: string;
196
+ type: string;
197
+ quantity: number;
198
+ allmoxyData?: {
199
+ productId?: number;
200
+ productAttributes?: Array<{
201
+ attributeName: string;
202
+ value: any;
203
+ }>;
204
+ };
205
+ [key: string]: any;
206
+ };
207
+ measurement?: {
208
+ width: number;
209
+ height: number;
210
+ angle: number;
211
+ outOfSquare: number;
212
+ comments?: string;
213
+ [key: string]: any;
214
+ };
215
+ schedule?: {
216
+ id: string;
217
+ name: string;
218
+ [key: string]: any;
219
+ };
220
+ scheduleEntry?: {
221
+ id: string;
222
+ scheduleId: string;
223
+ orderId: number;
224
+ orderProductId: string;
225
+ customStatus?: { [key: string]: any };
226
+ [key: string]: any;
227
+ };
228
+ fieldChange?: {
229
+ fieldName: string; // Name of the field that changed
230
+ oldValue: any; // Previous value
231
+ newValue: any; // New value
232
+ };
233
+ triggeredBy?: {
234
+ userId?: string;
235
+ userName?: string;
236
+ source?: string;
237
+ };
238
+ [key: string]: any; // Allow additional context fields
239
+ }
240
+
241
+ // Execution log for tracking automation runs
242
+ export interface ILeanAutomationLog {
243
+ _id: mongoose.Types.ObjectId;
244
+ automationId: mongoose.Types.ObjectId;
245
+ automationName: string;
246
+ triggerType: AutomationTriggerType;
247
+ status: "success" | "error" | "partial" | "skipped"; // partial = some actions failed, skipped = filters didn't match
248
+ context: IAutomationContext; // Context data at time of execution
249
+
250
+ // Filter evaluation results
251
+ filterEvaluation?: IAutomationFiltersEvaluationResult; // Results of filter evaluation
252
+
253
+ actionsExecuted: {
254
+ actionType: AutomationActionType;
255
+ status: "success" | "error";
256
+ error?: string;
257
+ details?: any; // Action-specific execution details
258
+ }[];
259
+ error?: string;
260
+ executedAt: Date;
261
+ createdAt?: Date;
262
+ }
263
+
264
+ export type IAutomationLog = ILeanAutomationLog & Document;
@@ -2,8 +2,15 @@ import { Document } from "mongoose";
2
2
 
3
3
  export type IDailyTotal = ILeanDailyTotal & Document;
4
4
 
5
+ export interface ILockedProductionLine {
6
+ productionLineId: string;
7
+ productionLineName: string;
8
+ reason: string;
9
+ }
10
+
5
11
  export interface ILeanDailyTotal {
6
12
  _id: string;
7
13
  locked: boolean;
14
+ lockedProductionLines?: ILockedProductionLine[];
8
15
  [key: string]: any;
9
16
  }
package/src/IExporter.ts CHANGED
@@ -17,4 +17,5 @@ export interface ILeanExporter {
17
17
  csvGenerator?: IHeader[];
18
18
  ignoreEmptyFiles: boolean;
19
19
  firstLineHeaders: boolean;
20
+ enabled: boolean;
20
21
  }
package/src/IExpress.ts CHANGED
@@ -10,5 +10,6 @@ export enum IHTTPMethod {
10
10
  GET = "get",
11
11
  POST = "post",
12
12
  PUT = "put",
13
+ PATCH = "patch",
13
14
  DELETE = "delete",
14
15
  }
@@ -36,3 +36,4 @@ export interface ILeanAllmoxyIntegration extends ILeanIntegration {
36
36
  }
37
37
 
38
38
  export type IAllmoxyIntegration = ILeanAllmoxyIntegration & Document;
39
+
package/src/IInventory.ts CHANGED
@@ -8,6 +8,7 @@ export interface IField {
8
8
  type: "number" | "text" | "select" | "calculation" | "tag"; // Field type
9
9
  required?: boolean; // Whether this field is required
10
10
  options?: string[]; // For select fields, the available options
11
+ selectFieldDefinitionId?: mongoose.Types.ObjectId; // Reference to SelectFieldDefinition for select fields
11
12
  default?: any; // Default value
12
13
  unit?: string; // Unit of measurement if applicable
13
14
  validation?: {
@@ -36,11 +37,34 @@ export interface IInventoryType {
36
37
  name: string; // e.g., "Lumber", "Steel", "Hardware"
37
38
  description?: string;
38
39
  fields: IField[]; // Custom fields for this type
40
+ uniqueIdentifierField?: string; // Field key used as the unique identifier
39
41
  defaultLocation?: mongoose.Types.ObjectId;
40
42
  tagGenerationEnabled?: boolean;
41
43
  enableSupplierField?: boolean; // Whether to show supplier selection
44
+ supplierRequired?: boolean; // Whether supplier is required when enabled
42
45
  enableLocationField?: boolean; // Whether to show location selection
46
+ locationRequired?: boolean; // Whether location is required when enabled
47
+ locationPrecision?: "rack" | "shelf" | "bin"; // Maximum level of location detail allowed
48
+ requiredLocationLevel?: "rack" | "shelf" | "bin"; // Minimum level of location detail required
43
49
  groupingAttributes?: string[]; // Field keys that can be used for grouping
50
+ quantityField?: string; // The field key that represents item quantity
51
+ // Inventory min/max settings
52
+ minQuantity?: number; // Minimum quantity before reorder alert
53
+ maxQuantity?: number; // Maximum quantity to maintain
54
+ minMaxRequired?: boolean; // Whether min/max is required for items of this type
55
+ // Lift tag configuration
56
+ liftTagConfig?: {
57
+ enabled: boolean;
58
+ size?: string; // Label size text (e.g., "2x4")
59
+ fieldsToInclude: string[]; // Field keys to include on the tag
60
+ includeBarcode?: boolean;
61
+ showFieldLabels?: boolean;
62
+ identifierFontSize?: number;
63
+ includeCreatedDate?: boolean;
64
+ widthInches?: number;
65
+ heightInches?: number;
66
+ textAlignment?: "left" | "right";
67
+ };
44
68
  }
45
69
 
46
70
  export interface IHistoryEntry {
@@ -55,9 +79,18 @@ export interface IInventoryItem {
55
79
  _id: string;
56
80
  type: string | IInventoryType;
57
81
  location?: string | ILocation;
82
+ locationPath?: {
83
+ rackId?: mongoose.Types.ObjectId;
84
+ shelfId?: mongoose.Types.ObjectId;
85
+ binId?: mongoose.Types.ObjectId;
86
+ };
58
87
  fields: Map<string, any>;
59
- tags: string[];
88
+ tag: string;
60
89
  history: IHistoryEntry[];
90
+ // Min/max quantities for this specific item
91
+ minQuantity?: number; // Minimum quantity before reorder alert
92
+ maxQuantity?: number; // Maximum quantity to maintain
93
+ currentQuantity?: number; // Current quantity (derived from quantity field if set)
61
94
  createdAt: Date;
62
95
  updatedAt: Date;
63
96
  }
@@ -97,10 +130,15 @@ export interface IInventoryItemResponse {
97
130
  name: string;
98
131
  [key: string]: any;
99
132
  }; // Populated location reference
133
+ locationPath?: {
134
+ rackId?: mongoose.Types.ObjectId;
135
+ shelfId?: mongoose.Types.ObjectId;
136
+ binId?: mongoose.Types.ObjectId;
137
+ };
100
138
  fields: {
101
139
  [key: string]: any;
102
140
  }; // Converted from Map to plain object
103
- tags: string[];
141
+ tag: string;
104
142
  history: {
105
143
  date: Date;
106
144
  action: string;
package/src/IMailCache.ts CHANGED
@@ -9,11 +9,25 @@ export interface ILeanMailCache {
9
9
  state: string;
10
10
  logs: string[];
11
11
  exporterID: string;
12
+ pdfAttachments?: IPDFAttachment[];
12
13
  }
13
14
 
14
15
  export interface IAttachment {
15
16
  fileName: string;
16
17
  content: string;
18
+ contentType?: string;
19
+ }
20
+
21
+ export interface IPDFAttachment {
22
+ _id?: mongoose.Types.ObjectId;
23
+ fileName: string;
24
+ fileSize: number;
25
+ contentType: string;
26
+ uploadedAt: Date;
27
+ uploadedBy?: string;
28
+ storagePath?: string;
29
+ gridFSId?: mongoose.Types.ObjectId;
30
+ orderNumber?: number;
17
31
  }
18
32
 
19
33
  export type IMailCache = ILeanMailCache & Document;
package/src/IOrder.ts CHANGED
@@ -48,7 +48,7 @@ export interface IOrderProduct {
48
48
  _id: string;
49
49
  quantity: number;
50
50
  type: string;
51
- limitsGroup: string;
51
+ productionLine: string;
52
52
  startDate: string;
53
53
  hasStarted: boolean;
54
54
  highlight: boolean;
@@ -0,0 +1,125 @@
1
+ import mongoose, { Document } from "mongoose";
2
+
3
+ // Filter condition for matching Allmoxy products/attributes
4
+ export interface IScheduleFilterCondition {
5
+ field: "product" | "attribute";
6
+ productId?: number;
7
+ attributeName?: string;
8
+ operator: "equals" | "notEquals" | "contains" | "greaterThan" | "lessThan" | "greaterThanOrEqual" | "lessThanOrEqual";
9
+ value: string;
10
+ }
11
+
12
+ // A filter group - conditions are ANDed together
13
+ export interface IScheduleFilterGroup {
14
+ conditions: IScheduleFilterCondition[];
15
+ }
16
+
17
+ // Column/Stage configuration for the schedule
18
+ export interface IScheduleColumn {
19
+ _id?: mongoose.Types.ObjectId;
20
+ name: string;
21
+ machineId: mongoose.Types.ObjectId;
22
+ offsetDays: number; // Days offset from the base date (ship date or start date)
23
+ order: number; // Display order of this column
24
+ }
25
+
26
+ // Display column configuration - controls order and visibility of all columns
27
+ export interface IScheduleDisplayColumn {
28
+ type: "orderNumber" | "company" | "product" | "quantity" | "shipDate" | "startDate" | "status" | "attribute" | "stage" | "customField";
29
+ stageColumnId?: mongoose.Types.ObjectId; // Reference to the stage column if type is "stage"
30
+ attributeName?: string; // Reference to the attribute if type is "attribute"
31
+ customFieldName?: string; // Reference to the custom field name if type is "customField"
32
+ order: number;
33
+ visible: boolean; // Whether column is visible in the schedule view
34
+ }
35
+
36
+ // Additional attribute with optional display condition
37
+ export interface IScheduleAdditionalAttribute {
38
+ attributeName: string;
39
+ label?: string; // Optional custom label for display
40
+ // Optional condition - if specified, attribute only displays when condition is met
41
+ displayCondition?: {
42
+ operator: "equals" | "notEquals" | "contains" | "greaterThan" | "lessThan" | "greaterThanOrEqual" | "lessThanOrEqual";
43
+ value: string;
44
+ };
45
+ }
46
+
47
+ // Schedule View - different ways to view the same schedule data
48
+ export interface IScheduleView {
49
+ _id?: mongoose.Types.ObjectId;
50
+ name: string;
51
+ layoutType: "table" | "kanban" | "gantt";
52
+ // Display column configuration (for table layout)
53
+ displayColumns?: IScheduleDisplayColumn[];
54
+ // Sorting configuration
55
+ sortField?: string; // Can be "shipDate", "startDate", "status", or a column ID
56
+ sortDirection?: "asc" | "desc";
57
+ // Additional attributes to show (beyond filter attributes)
58
+ additionalAttributes?: (string | IScheduleAdditionalAttribute)[]; // Array of attribute names or attribute configs
59
+ combineAdditionalAttributes?: boolean; // Whether to show all additional attributes in one column (like matched attributes)
60
+ // Product grouping configuration
61
+ groupByMatchingAttributes?: boolean; // Whether to group products with matching filter attributes in the same order
62
+ isDefault?: boolean; // Whether this is the default view
63
+ }
64
+
65
+ // Custom field definition for schedule entries
66
+ export interface IScheduleCustomField {
67
+ _id?: mongoose.Types.ObjectId;
68
+ name: string; // Internal field name (e.g., "drill_specs_confirmed")
69
+ label: string; // Display label (e.g., "Drill Specs Confirmed")
70
+ fieldType: "boolean" | "select" | "text" | "number"; // Type of field
71
+ options?: string[]; // Options for select fields (e.g., ["in process", "stuck", "completed"])
72
+ defaultValue?: string | boolean | number; // Default value for new entries
73
+ required?: boolean; // Whether field is required
74
+ order?: number; // Display order
75
+ }
76
+
77
+ // The main Schedule configuration
78
+ export interface ILeanSchedule {
79
+ _id: mongoose.Types.ObjectId;
80
+ name: string;
81
+ description?: string;
82
+ enabled: boolean;
83
+ // Filter configuration - groups are ORed together
84
+ filterGroups: IScheduleFilterGroup[];
85
+ // Column/Stage configuration
86
+ columns: IScheduleColumn[];
87
+ // Views for this schedule
88
+ views?: IScheduleView[];
89
+ // Custom fields for this schedule
90
+ customFields?: IScheduleCustomField[];
91
+ // Base date field to calculate offsets from
92
+ baseDateField: "shipDate" | "startDate";
93
+ // Legacy fields (kept for backward compatibility, will be migrated to default view)
94
+ displayColumns?: IScheduleDisplayColumn[];
95
+ hidePastShipDates?: boolean;
96
+ showShipDate?: boolean;
97
+ showStartDate?: boolean;
98
+ defaultSortField?: string;
99
+ defaultSortDirection?: "asc" | "desc";
100
+ createdAt?: Date;
101
+ updatedAt?: Date;
102
+ }
103
+
104
+ export type ISchedule = ILeanSchedule & Document;
105
+
106
+ // Schedule Entry - the actual scheduled dates for an order product
107
+ export interface IScheduleEntryDate {
108
+ columnId: mongoose.Types.ObjectId;
109
+ date: string; // ISO date string
110
+ }
111
+
112
+ export interface ILeanScheduleEntry {
113
+ _id: mongoose.Types.ObjectId;
114
+ scheduleId: mongoose.Types.ObjectId;
115
+ orderId: number;
116
+ orderProductId: string;
117
+ dates: IScheduleEntryDate[];
118
+ notes?: string;
119
+ status?: string; // Legacy status field
120
+ customStatus?: { [key: string]: any }; // Custom status fields (key-value pairs)
121
+ createdAt?: Date;
122
+ updatedAt?: Date;
123
+ }
124
+
125
+ export type IScheduleEntry = ILeanScheduleEntry & Document;