@machinemetrics/mm-erp-sdk 0.2.0-beta.2 → 0.3.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/README.md +5 -0
  2. package/dist/index.d.ts +42 -43
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +48 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/knexfile.d.ts.map +1 -1
  7. package/dist/knexfile.js +19 -0
  8. package/dist/knexfile.js.map +1 -0
  9. package/dist/migrations/20241015162631_create_cache_table.d.ts +4 -0
  10. package/dist/migrations/20241015162631_create_cache_table.d.ts.map +1 -0
  11. package/dist/migrations/20241015162631_create_cache_table.js +11 -15
  12. package/dist/migrations/20241015162631_create_cache_table.js.map +1 -1
  13. package/dist/migrations/20241015162632_create_sdk_cache_table.d.ts +4 -0
  14. package/dist/migrations/20241015162632_create_sdk_cache_table.d.ts.map +1 -0
  15. package/dist/migrations/20241015162632_create_sdk_cache_table.js +11 -15
  16. package/dist/migrations/20241015162632_create_sdk_cache_table.js.map +1 -1
  17. package/dist/migrations/20250103162631_create_record_tracking_table.d.ts +4 -0
  18. package/dist/migrations/20250103162631_create_record_tracking_table.d.ts.map +1 -0
  19. package/dist/migrations/20250103162631_create_record_tracking_table.js +14 -15
  20. package/dist/migrations/20250103162631_create_record_tracking_table.js.map +1 -1
  21. package/dist/services/caching-service/batch-cache-manager.d.ts +1 -1
  22. package/dist/services/caching-service/batch-cache-manager.d.ts.map +1 -1
  23. package/dist/services/caching-service/batch-cache-manager.js +84 -0
  24. package/dist/services/caching-service/batch-cache-manager.js.map +1 -0
  25. package/dist/services/caching-service/hashed-cache-manager.d.ts +2 -2
  26. package/dist/services/caching-service/hashed-cache-manager.d.ts.map +1 -1
  27. package/dist/services/caching-service/hashed-cache-manager.js +223 -0
  28. package/dist/services/caching-service/hashed-cache-manager.js.map +1 -0
  29. package/dist/services/caching-service/index.d.ts +1 -1
  30. package/dist/services/caching-service/index.d.ts.map +1 -1
  31. package/dist/services/caching-service/index.js +2 -0
  32. package/dist/services/caching-service/index.js.map +1 -0
  33. package/dist/services/caching-service/record-tracking-manager.d.ts +1 -1
  34. package/dist/services/caching-service/record-tracking-manager.d.ts.map +1 -1
  35. package/dist/services/caching-service/record-tracking-manager.js +28 -0
  36. package/dist/services/caching-service/record-tracking-manager.js.map +1 -0
  37. package/dist/services/data-sync-service/configuration-manager.d.ts +1 -1
  38. package/dist/services/data-sync-service/configuration-manager.d.ts.map +1 -1
  39. package/dist/services/data-sync-service/configuration-manager.js +163 -0
  40. package/dist/services/data-sync-service/configuration-manager.js.map +1 -0
  41. package/dist/services/data-sync-service/data-sync-service.d.ts.map +1 -1
  42. package/dist/services/data-sync-service/data-sync-service.js +95 -0
  43. package/dist/services/data-sync-service/data-sync-service.js.map +1 -0
  44. package/dist/services/data-sync-service/index.d.ts +3 -3
  45. package/dist/services/data-sync-service/index.d.ts.map +1 -1
  46. package/dist/services/data-sync-service/index.js +10 -0
  47. package/dist/services/data-sync-service/index.js.map +1 -0
  48. package/dist/services/data-sync-service/jobs/clean-up-expired-cache.d.ts.map +1 -1
  49. package/dist/services/data-sync-service/jobs/clean-up-expired-cache.js +42 -40
  50. package/dist/services/data-sync-service/jobs/clean-up-expired-cache.js.map +1 -1
  51. package/dist/services/data-sync-service/jobs/from-erp.d.ts.map +1 -1
  52. package/dist/services/data-sync-service/jobs/from-erp.js +50 -37
  53. package/dist/services/data-sync-service/jobs/from-erp.js.map +1 -1
  54. package/dist/services/data-sync-service/jobs/retry-failed-labor-tickets.d.ts.map +1 -1
  55. package/dist/services/data-sync-service/jobs/retry-failed-labor-tickets.js +38 -36
  56. package/dist/services/data-sync-service/jobs/retry-failed-labor-tickets.js.map +1 -1
  57. package/dist/services/data-sync-service/jobs/run-migrations.d.ts.map +1 -1
  58. package/dist/services/data-sync-service/jobs/run-migrations.js +24 -22
  59. package/dist/services/data-sync-service/jobs/run-migrations.js.map +1 -1
  60. package/dist/services/data-sync-service/jobs/to-erp.d.ts.map +1 -1
  61. package/dist/services/data-sync-service/jobs/to-erp.js +49 -49
  62. package/dist/services/data-sync-service/jobs/to-erp.js.map +1 -1
  63. package/dist/services/erp-api-services/errors.d.ts +1 -1
  64. package/dist/services/erp-api-services/errors.d.ts.map +1 -1
  65. package/dist/services/erp-api-services/errors.js +83 -0
  66. package/dist/services/erp-api-services/errors.js.map +1 -0
  67. package/dist/services/erp-api-services/graphql/graphql-service.d.ts +2 -2
  68. package/dist/services/erp-api-services/graphql/graphql-service.d.ts.map +1 -1
  69. package/dist/services/erp-api-services/graphql/graphql-service.js +102 -0
  70. package/dist/services/erp-api-services/graphql/graphql-service.js.map +1 -0
  71. package/dist/services/erp-api-services/graphql/types.js +6 -0
  72. package/dist/services/erp-api-services/graphql/types.js.map +1 -0
  73. package/dist/services/erp-api-services/index.d.ts +8 -8
  74. package/dist/services/erp-api-services/index.d.ts.map +1 -1
  75. package/dist/services/erp-api-services/index.js +13 -0
  76. package/dist/services/erp-api-services/index.js.map +1 -0
  77. package/dist/services/erp-api-services/oauth-client.js +41 -0
  78. package/dist/services/erp-api-services/oauth-client.js.map +1 -0
  79. package/dist/services/erp-api-services/rest/get-query-params.js +23 -0
  80. package/dist/services/erp-api-services/rest/get-query-params.js.map +1 -0
  81. package/dist/services/erp-api-services/rest/rest-api-service.d.ts +2 -2
  82. package/dist/services/erp-api-services/rest/rest-api-service.d.ts.map +1 -1
  83. package/dist/services/erp-api-services/rest/rest-api-service.js +163 -0
  84. package/dist/services/erp-api-services/rest/rest-api-service.js.map +1 -0
  85. package/dist/services/erp-api-services/types.d.ts +2 -2
  86. package/dist/services/erp-api-services/types.d.ts.map +1 -1
  87. package/dist/services/erp-api-services/types.js +2 -0
  88. package/dist/services/erp-api-services/types.js.map +1 -0
  89. package/dist/services/mm-api-service/index.d.ts +6 -13
  90. package/dist/services/mm-api-service/index.d.ts.map +1 -1
  91. package/dist/services/mm-api-service/index.js +15 -0
  92. package/dist/services/mm-api-service/index.js.map +1 -0
  93. package/dist/services/mm-api-service/mm-api-service.d.ts +7 -13
  94. package/dist/services/mm-api-service/mm-api-service.d.ts.map +1 -1
  95. package/dist/services/mm-api-service/mm-api-service.js +519 -0
  96. package/dist/services/mm-api-service/mm-api-service.js.map +1 -0
  97. package/dist/services/mm-api-service/token-mgr.js +113 -0
  98. package/dist/services/mm-api-service/token-mgr.js.map +1 -0
  99. package/dist/services/mm-api-service/types/checkpoint.js +2 -0
  100. package/dist/services/mm-api-service/types/checkpoint.js.map +1 -0
  101. package/dist/services/mm-api-service/types/entity-transformer.d.ts +2 -2
  102. package/dist/services/mm-api-service/types/entity-transformer.d.ts.map +1 -1
  103. package/dist/services/mm-api-service/types/entity-transformer.js +186 -0
  104. package/dist/services/mm-api-service/types/entity-transformer.js.map +1 -0
  105. package/dist/services/mm-api-service/types/mm-response-interfaces.js +34 -0
  106. package/dist/services/mm-api-service/types/mm-response-interfaces.js.map +1 -0
  107. package/dist/services/mm-api-service/types/receive-types.d.ts +0 -3
  108. package/dist/services/mm-api-service/types/receive-types.d.ts.map +1 -1
  109. package/dist/services/mm-api-service/types/receive-types.js +55 -0
  110. package/dist/services/mm-api-service/types/receive-types.js.map +1 -0
  111. package/dist/services/mm-api-service/types/send-types.js +337 -0
  112. package/dist/services/mm-api-service/types/send-types.js.map +1 -0
  113. package/dist/services/psql-erp-service/configuration.js +2 -0
  114. package/dist/services/psql-erp-service/configuration.js.map +1 -0
  115. package/dist/services/psql-erp-service/index.d.ts +3 -3
  116. package/dist/services/psql-erp-service/index.d.ts.map +1 -1
  117. package/dist/services/psql-erp-service/index.js +10 -0
  118. package/dist/services/psql-erp-service/index.js.map +1 -0
  119. package/dist/services/psql-erp-service/internal/types/psql-types.js +5 -0
  120. package/dist/services/psql-erp-service/internal/types/psql-types.js.map +1 -0
  121. package/dist/services/psql-erp-service/psql-helpers.js +99 -0
  122. package/dist/services/psql-erp-service/psql-helpers.js.map +1 -0
  123. package/dist/services/psql-erp-service/psql-service.d.ts +2 -2
  124. package/dist/services/psql-erp-service/psql-service.d.ts.map +1 -1
  125. package/dist/services/psql-erp-service/psql-service.js +187 -0
  126. package/dist/services/psql-erp-service/psql-service.js.map +1 -0
  127. package/dist/services/reporting-service/index.d.ts +1 -1
  128. package/dist/services/reporting-service/index.d.ts.map +1 -1
  129. package/dist/services/reporting-service/index.js +5 -0
  130. package/dist/services/reporting-service/index.js.map +1 -0
  131. package/dist/services/reporting-service/logger.d.ts.map +1 -1
  132. package/dist/services/reporting-service/logger.js +221 -0
  133. package/dist/services/reporting-service/logger.js.map +1 -0
  134. package/dist/services/sql-server-erp-service/configuration.js +2 -0
  135. package/dist/services/sql-server-erp-service/configuration.js.map +1 -0
  136. package/dist/services/sql-server-erp-service/index.d.ts +3 -3
  137. package/dist/services/sql-server-erp-service/index.d.ts.map +1 -1
  138. package/dist/services/sql-server-erp-service/index.js +11 -0
  139. package/dist/services/sql-server-erp-service/index.js.map +1 -0
  140. package/dist/services/sql-server-erp-service/internal/sql-labor-ticket-operations.d.ts +2 -2
  141. package/dist/services/sql-server-erp-service/internal/sql-labor-ticket-operations.d.ts.map +1 -1
  142. package/dist/services/sql-server-erp-service/internal/sql-labor-ticket-operations.js +50 -0
  143. package/dist/services/sql-server-erp-service/internal/sql-labor-ticket-operations.js.map +1 -0
  144. package/dist/services/sql-server-erp-service/internal/sql-server-config.js +40 -0
  145. package/dist/services/sql-server-erp-service/internal/sql-server-config.js.map +1 -0
  146. package/dist/services/sql-server-erp-service/internal/sql-transaction-manager.js +36 -0
  147. package/dist/services/sql-server-erp-service/internal/sql-transaction-manager.js.map +1 -0
  148. package/dist/services/sql-server-erp-service/internal/types/sql-server-types.js +2 -0
  149. package/dist/services/sql-server-erp-service/internal/types/sql-server-types.js.map +1 -0
  150. package/dist/services/sql-server-erp-service/sql-server-helpers.d.ts +3 -3
  151. package/dist/services/sql-server-erp-service/sql-server-helpers.d.ts.map +1 -1
  152. package/dist/services/sql-server-erp-service/sql-server-helpers.js +66 -0
  153. package/dist/services/sql-server-erp-service/sql-server-helpers.js.map +1 -0
  154. package/dist/services/sql-server-erp-service/sql-server-service.d.ts +2 -2
  155. package/dist/services/sql-server-erp-service/sql-server-service.d.ts.map +1 -1
  156. package/dist/services/sql-server-erp-service/sql-server-service.js +154 -0
  157. package/dist/services/sql-server-erp-service/sql-server-service.js.map +1 -0
  158. package/dist/services/sql-server-erp-service/types/sql-input-param.js +2 -0
  159. package/dist/services/sql-server-erp-service/types/sql-input-param.js.map +1 -0
  160. package/dist/services/sqlite-service/index.d.ts +1 -1
  161. package/dist/services/sqlite-service/index.d.ts.map +1 -1
  162. package/dist/services/sqlite-service/index.js +2 -0
  163. package/dist/services/sqlite-service/index.js.map +1 -0
  164. package/dist/services/sqlite-service/sqlite-coordinator.js +60 -0
  165. package/dist/services/sqlite-service/sqlite-coordinator.js.map +1 -0
  166. package/dist/types/erp-connector.d.ts +9 -2
  167. package/dist/types/erp-connector.d.ts.map +1 -1
  168. package/dist/types/erp-connector.js +2 -0
  169. package/dist/types/erp-connector.js.map +1 -0
  170. package/dist/types/erp-types.js +13 -0
  171. package/dist/types/erp-types.js.map +1 -0
  172. package/dist/types/flattened-work-order.d.ts +99 -0
  173. package/dist/types/flattened-work-order.d.ts.map +1 -0
  174. package/dist/types/flattened-work-order.js +2 -0
  175. package/dist/types/flattened-work-order.js.map +1 -0
  176. package/dist/types/index.d.ts +3 -2
  177. package/dist/types/index.d.ts.map +1 -1
  178. package/dist/types/index.js +6 -0
  179. package/dist/types/index.js.map +1 -0
  180. package/dist/utils/application-initializer.js +55 -0
  181. package/dist/utils/application-initializer.js.map +1 -0
  182. package/dist/utils/cleanup-numbers.js +6 -0
  183. package/dist/utils/cleanup-numbers.js.map +1 -0
  184. package/dist/utils/connector-factory.d.ts +1 -1
  185. package/dist/utils/connector-factory.d.ts.map +1 -1
  186. package/dist/utils/connector-factory.js +34 -0
  187. package/dist/utils/connector-factory.js.map +1 -0
  188. package/dist/utils/connector-log/log-deduper.d.ts +1 -1
  189. package/dist/utils/connector-log/log-deduper.d.ts.map +1 -1
  190. package/dist/utils/connector-log/log-deduper.js +240 -0
  191. package/dist/utils/connector-log/log-deduper.js.map +1 -0
  192. package/dist/utils/connector-log/mm-connector-logger-example.d.ts +1 -0
  193. package/dist/utils/connector-log/mm-connector-logger-example.js +88 -0
  194. package/dist/utils/connector-log/mm-connector-logger-example.js.map +1 -0
  195. package/dist/utils/connector-log/mm-connector-logger.d.ts +1 -1
  196. package/dist/utils/connector-log/mm-connector-logger.d.ts.map +1 -1
  197. package/dist/utils/connector-log/mm-connector-logger.js +151 -0
  198. package/dist/utils/connector-log/mm-connector-logger.js.map +1 -0
  199. package/dist/utils/data-transformation.js +38 -0
  200. package/dist/utils/data-transformation.js.map +1 -0
  201. package/dist/utils/env.d.ts +8 -0
  202. package/dist/utils/env.d.ts.map +1 -0
  203. package/dist/utils/env.js +58 -0
  204. package/dist/utils/env.js.map +1 -0
  205. package/dist/utils/erp-timezone-utils.d.ts +20 -0
  206. package/dist/utils/erp-timezone-utils.d.ts.map +1 -0
  207. package/dist/utils/erp-timezone-utils.js +75 -0
  208. package/dist/utils/erp-timezone-utils.js.map +1 -0
  209. package/dist/utils/erp-type-from-entity.d.ts +1 -1
  210. package/dist/utils/erp-type-from-entity.d.ts.map +1 -1
  211. package/dist/utils/erp-type-from-entity.js +6 -0
  212. package/dist/utils/erp-type-from-entity.js.map +1 -0
  213. package/dist/utils/error-utils.js +21 -0
  214. package/dist/utils/error-utils.js.map +1 -0
  215. package/dist/utils/http-client.js +189 -0
  216. package/dist/utils/http-client.js.map +1 -0
  217. package/dist/utils/index.d.ts +34 -38
  218. package/dist/utils/index.d.ts.map +1 -1
  219. package/dist/utils/index.js +66 -0
  220. package/dist/utils/index.js.map +1 -0
  221. package/dist/utils/local-data-store/database-lock.js +68 -0
  222. package/dist/utils/local-data-store/database-lock.js.map +1 -0
  223. package/dist/utils/local-data-store/jobs-shared-data.d.ts +2 -0
  224. package/dist/utils/local-data-store/jobs-shared-data.d.ts.map +1 -1
  225. package/dist/utils/local-data-store/jobs-shared-data.js +118 -0
  226. package/dist/utils/local-data-store/jobs-shared-data.js.map +1 -0
  227. package/dist/utils/mm-labor-ticket-helpers.d.ts +4 -5
  228. package/dist/utils/mm-labor-ticket-helpers.d.ts.map +1 -1
  229. package/dist/utils/mm-labor-ticket-helpers.js +28 -0
  230. package/dist/utils/mm-labor-ticket-helpers.js.map +1 -0
  231. package/dist/utils/removeExtraneousFields.d.ts +1 -1
  232. package/dist/utils/removeExtraneousFields.d.ts.map +1 -1
  233. package/dist/utils/removeExtraneousFields.js +16 -0
  234. package/dist/utils/removeExtraneousFields.js.map +1 -0
  235. package/dist/utils/removeIdFieldFromPayload.d.ts +1 -1
  236. package/dist/utils/removeIdFieldFromPayload.d.ts.map +1 -1
  237. package/dist/utils/removeIdFieldFromPayload.js +16 -0
  238. package/dist/utils/removeIdFieldFromPayload.js.map +1 -0
  239. package/dist/utils/resource-group.d.ts +1 -1
  240. package/dist/utils/resource-group.d.ts.map +1 -1
  241. package/dist/utils/resource-group.js +59 -0
  242. package/dist/utils/resource-group.js.map +1 -0
  243. package/dist/utils/standard-process-drivers/error-processor.d.ts +3 -3
  244. package/dist/utils/standard-process-drivers/error-processor.d.ts.map +1 -1
  245. package/dist/utils/standard-process-drivers/error-processor.js +262 -0
  246. package/dist/utils/standard-process-drivers/error-processor.js.map +1 -0
  247. package/dist/utils/standard-process-drivers/index.d.ts +3 -3
  248. package/dist/utils/standard-process-drivers/index.d.ts.map +1 -1
  249. package/dist/utils/standard-process-drivers/index.js +4 -0
  250. package/dist/utils/standard-process-drivers/index.js.map +1 -0
  251. package/dist/utils/standard-process-drivers/labor-ticket-erp-synchronizer.d.ts +16 -1
  252. package/dist/utils/standard-process-drivers/labor-ticket-erp-synchronizer.d.ts.map +1 -1
  253. package/dist/utils/standard-process-drivers/labor-ticket-erp-synchronizer.js +299 -0
  254. package/dist/utils/standard-process-drivers/labor-ticket-erp-synchronizer.js.map +1 -0
  255. package/dist/utils/standard-process-drivers/mm-entity-processor.d.ts +11 -5
  256. package/dist/utils/standard-process-drivers/mm-entity-processor.d.ts.map +1 -1
  257. package/dist/utils/standard-process-drivers/mm-entity-processor.js +174 -0
  258. package/dist/utils/standard-process-drivers/mm-entity-processor.js.map +1 -0
  259. package/dist/utils/standard-process-drivers/standard-process-drivers.d.ts +12 -6
  260. package/dist/utils/standard-process-drivers/standard-process-drivers.d.ts.map +1 -1
  261. package/dist/utils/standard-process-drivers/standard-process-drivers.js +333 -0
  262. package/dist/utils/standard-process-drivers/standard-process-drivers.js.map +1 -0
  263. package/dist/utils/time-utils.d.ts.map +1 -1
  264. package/dist/utils/time-utils.js +103 -0
  265. package/dist/utils/time-utils.js.map +1 -0
  266. package/dist/utils/timezone.js +105 -0
  267. package/dist/utils/timezone.js.map +1 -0
  268. package/dist/utils/trimObjectValues.js +11 -0
  269. package/dist/utils/trimObjectValues.js.map +1 -0
  270. package/dist/utils/uniqueRows.js +35 -0
  271. package/dist/utils/uniqueRows.js.map +1 -0
  272. package/package.json +8 -10
  273. package/src/index.ts +42 -45
  274. package/src/knexfile.ts +1 -0
  275. package/src/services/caching-service/batch-cache-manager.ts +2 -2
  276. package/src/services/caching-service/hashed-cache-manager.ts +5 -5
  277. package/src/services/caching-service/index.ts +1 -1
  278. package/src/services/caching-service/record-tracking-manager.ts +2 -2
  279. package/src/services/data-sync-service/configuration-manager.ts +52 -39
  280. package/src/services/data-sync-service/data-sync-service.ts +10 -19
  281. package/src/services/data-sync-service/index.ts +3 -3
  282. package/src/services/data-sync-service/jobs/clean-up-expired-cache.ts +5 -4
  283. package/src/services/data-sync-service/jobs/from-erp.ts +12 -6
  284. package/src/services/data-sync-service/jobs/retry-failed-labor-tickets.ts +4 -3
  285. package/src/services/data-sync-service/jobs/run-migrations.ts +4 -3
  286. package/src/services/data-sync-service/jobs/to-erp.ts +5 -14
  287. package/src/services/erp-api-services/errors.ts +3 -3
  288. package/src/services/erp-api-services/graphql/graphql-service.ts +5 -5
  289. package/src/services/erp-api-services/index.ts +8 -8
  290. package/src/services/erp-api-services/rest/rest-api-service.ts +4 -4
  291. package/src/services/erp-api-services/types.ts +2 -2
  292. package/src/services/mm-api-service/index.ts +6 -14
  293. package/src/services/mm-api-service/mm-api-service.ts +13 -30
  294. package/src/services/mm-api-service/token-mgr.ts +4 -4
  295. package/src/services/mm-api-service/types/entity-transformer.ts +3 -3
  296. package/src/services/mm-api-service/types/receive-types.ts +0 -1
  297. package/src/services/psql-erp-service/index.ts +3 -3
  298. package/src/services/psql-erp-service/psql-service.ts +4 -4
  299. package/src/services/reporting-service/index.ts +1 -1
  300. package/src/services/reporting-service/logger.ts +116 -81
  301. package/src/services/sql-server-erp-service/index.ts +3 -3
  302. package/src/services/sql-server-erp-service/internal/sql-labor-ticket-operations.ts +2 -2
  303. package/src/services/sql-server-erp-service/internal/sql-transaction-manager.ts +1 -1
  304. package/src/services/sql-server-erp-service/sql-server-helpers.ts +6 -6
  305. package/src/services/sql-server-erp-service/sql-server-service.ts +4 -4
  306. package/src/services/sqlite-service/index.ts +1 -1
  307. package/src/services/sqlite-service/sqlite-coordinator.ts +2 -2
  308. package/src/types/erp-connector.ts +9 -2
  309. package/src/types/flattened-work-order.ts +108 -0
  310. package/src/types/index.ts +10 -2
  311. package/src/utils/application-initializer.ts +5 -5
  312. package/src/utils/connector-factory.ts +2 -2
  313. package/src/utils/connector-log/log-deduper.ts +2 -2
  314. package/src/utils/connector-log/mm-connector-logger.ts +3 -3
  315. package/src/utils/env.ts +75 -0
  316. package/src/utils/erp-timezone-utils.ts +99 -0
  317. package/src/utils/erp-type-from-entity.ts +1 -1
  318. package/src/utils/http-client.ts +5 -4
  319. package/src/utils/index.ts +38 -39
  320. package/src/utils/local-data-store/database-lock.ts +1 -1
  321. package/src/utils/local-data-store/jobs-shared-data.ts +2 -0
  322. package/src/utils/mm-labor-ticket-helpers.ts +12 -9
  323. package/src/utils/removeExtraneousFields.ts +1 -1
  324. package/src/utils/removeIdFieldFromPayload.ts +1 -1
  325. package/src/utils/resource-group.ts +2 -2
  326. package/src/utils/standard-process-drivers/error-processor.ts +5 -5
  327. package/src/utils/standard-process-drivers/index.ts +3 -3
  328. package/src/utils/standard-process-drivers/labor-ticket-erp-synchronizer.ts +225 -69
  329. package/src/utils/standard-process-drivers/mm-entity-processor.ts +14 -8
  330. package/src/utils/standard-process-drivers/standard-process-drivers.ts +39 -25
  331. package/src/utils/time-utils.ts +14 -3
  332. package/src/utils/timezone.ts +2 -2
  333. package/dist/config-CvA-mFWF.js +0 -418
  334. package/dist/config-CvA-mFWF.js.map +0 -1
  335. package/dist/connector-factory-BPm2GVVF.js +0 -30
  336. package/dist/connector-factory-BPm2GVVF.js.map +0 -1
  337. package/dist/hashed-cache-manager-B15NN8hK.js +0 -322
  338. package/dist/hashed-cache-manager-B15NN8hK.js.map +0 -1
  339. package/dist/index-D8qO1NyK.js +0 -192
  340. package/dist/index-D8qO1NyK.js.map +0 -1
  341. package/dist/knexfile-Bng2Ru9c.js +0 -20
  342. package/dist/knexfile-Bng2Ru9c.js.map +0 -1
  343. package/dist/logger-BWw0_z9q.js +0 -17557
  344. package/dist/logger-BWw0_z9q.js.map +0 -1
  345. package/dist/mm-erp-sdk.js +0 -4978
  346. package/dist/mm-erp-sdk.js.map +0 -1
  347. package/dist/services/data-sync-service/nats-labor-ticket-listener.d.ts +0 -30
  348. package/dist/services/data-sync-service/nats-labor-ticket-listener.d.ts.map +0 -1
  349. package/dist/services/mm-api-service/company-info.d.ts +0 -13
  350. package/dist/services/mm-api-service/company-info.d.ts.map +0 -1
  351. package/dist/services/nats-service/nats-service.d.ts +0 -114
  352. package/dist/services/nats-service/nats-service.d.ts.map +0 -1
  353. package/dist/services/nats-service/test-nats-subscriber.d.ts +0 -6
  354. package/dist/services/nats-service/test-nats-subscriber.d.ts.map +0 -1
  355. package/dist/utils/error-formatter.d.ts +0 -19
  356. package/dist/utils/error-formatter.d.ts.map +0 -1
  357. package/src/services/data-sync-service/nats-labor-ticket-listener.ts +0 -341
  358. package/src/services/mm-api-service/company-info.ts +0 -87
  359. package/src/services/nats-service/nats-service.ts +0 -351
  360. package/src/services/nats-service/test-nats-subscriber.ts +0 -96
  361. package/src/utils/error-formatter.ts +0 -205
@@ -1,14 +1,17 @@
1
- import { IERPLaborTicketHandler } from "../../types/erp-connector";
2
- import { MMApiClient } from "../../services/mm-api-service/mm-api-service";
3
- import { MMReceiveLaborTicket } from "../../services/mm-api-service/types/receive-types";
4
- import { convertLaborTicketToLocalTimezone } from "../mm-labor-ticket-helpers";
5
- import { getCachedTimezoneOffset } from "../local-data-store/jobs-shared-data";
6
- import logger from "../../services/reporting-service/logger";
1
+ import { IERPLaborTicketHandler } from "../../types/erp-connector.js";
2
+ import { MMApiClient } from "../../services/mm-api-service/mm-api-service.js";
3
+ import { MMReceiveLaborTicket } from "../../services/mm-api-service/types/receive-types.js";
4
+ import { convertLaborTicketToLocalTimezone } from "../mm-labor-ticket-helpers.js";
5
+ import logger from "../../services/reporting-service/logger.js";
7
6
 
8
7
  /**
9
8
  * Handles synchronization of labor tickets between MachineMetrics and ERP systems
10
9
  */
11
10
  export class LaborTicketERPSynchronizer {
11
+ // Small allowance to mitigate tiny clock offsets / timestamp granularity differences
12
+ // between the connector host and MM's timestamps.
13
+ private static readonly CHECKPOINT_SKEW_MS = 2_000;
14
+
12
15
  /**
13
16
  * Synchronizes updated labor tickets from MachineMetrics to an ERP system
14
17
  */
@@ -18,9 +21,9 @@ export class LaborTicketERPSynchronizer {
18
21
  ): Promise<void> {
19
22
  try {
20
23
  const mmApiClient = new MMApiClient();
21
- const failedLaborTicketRefs: string[] = [];
24
+ const failedLaborTicketRefs = new Set<string>();
25
+ const attemptedSignatures = new Set<string>();
22
26
 
23
- // Initialize and fetch checkpoint (quick operations, don't need prolonged lock)
24
27
  await mmApiClient.initializeCheckpoint({
25
28
  system: connectorType,
26
29
  table: "labor_tickets",
@@ -30,95 +33,168 @@ export class LaborTicketERPSynchronizer {
30
33
  },
31
34
  });
32
35
 
33
- const fallbackTimestamp = new Date().toISOString();
34
- const laborTicketsUpdates = await mmApiClient.fetchLaborTicketUpdates({
35
- system: connectorType,
36
- checkpointType: "export",
37
- });
36
+ /**
37
+ * We cannot safely checkpoint to "now" without draining, because updates can arrive mid-run.
38
+ * And we cannot checkpoint to "most recent updatedAt from the initial fetch" because we
39
+ * update MM (setting laborTicketId on creates), which bumps updatedAt and causes the same
40
+ * ticket to be re-pulled next cycle.
41
+ *
42
+ * We also cannot dedupe only by laborTicketRef, because the same ticket can legitimately
43
+ * change multiple times within a single run (parts counts, times, reasons, state, etc.).
44
+ * And we cannot dedupe by (laborTicketRef, updatedAt) because updatedAt is exactly what our
45
+ * own MM write-back (setting laborTicketId) mutates, creating a false "new version".
46
+ *
47
+ * Remedy: drain the window up to a moving barrier time (local "now"), re-fetching until MM
48
+ * reports no additional unattempted tickets in that window, and dedupe within the run by a
49
+ * stable business signature (operational fields only; excludes metadata like updatedAt and
50
+ * excludes SDK-mutated fields like laborTicketId). Then checkpoint to a value that is not
51
+ * meaningfully ahead of MM's own timestamps (small skew clamp).
52
+ */
53
+ const maxPasses = 10;
54
+ let pass = 0;
55
+ let barrierTime = new Date().toISOString();
56
+ let maxMmTimestampWithinBarrier: string | null = null;
38
57
 
39
- if (laborTicketsUpdates.length === 0) {
40
- logger.info("syncLaborTicketsToERP:No updated labor tickets found");
41
- return;
42
- }
58
+ while (pass < maxPasses) {
59
+ pass += 1;
60
+ barrierTime = new Date().toISOString();
43
61
 
44
- logger.info(
45
- `ToERP: Found ${laborTicketsUpdates.length} Labor Ticket Ids and Refs to process`,
46
- {
47
- laborTickets: laborTicketsUpdates.map(
48
- (ticket: MMReceiveLaborTicket) => ({
49
- ref: ticket.laborTicketRef,
50
- id: ticket.laborTicketId,
51
- })
52
- ),
62
+ const laborTicketsUpdates = await mmApiClient.fetchLaborTicketUpdates({
63
+ system: connectorType,
64
+ checkpointType: "export",
65
+ });
66
+
67
+ if (laborTicketsUpdates.length === 0) {
68
+ if (pass === 1) {
69
+ logger.info("syncLaborTicketsToERP:No updated labor tickets found");
70
+ }
71
+ break;
53
72
  }
54
- );
55
73
 
56
- // Find the most recent updatedAt timestamp from labor tickets. This will be used to update
57
- // the checkpoint to ensure there is no gap of time for the next sync.
58
- const mostRecentUpdate = laborTicketsUpdates.reduce(
59
- (latest: string | null, ticket: MMReceiveLaborTicket) => {
60
- if (!latest || !ticket.updatedAt) return latest;
61
- return new Date(ticket.updatedAt) > new Date(latest)
62
- ? ticket.updatedAt
63
- : latest;
64
- },
65
- null as string | null
66
- );
74
+ // Track the latest MM timestamp we see that is <= the current barrier.
75
+ for (const ticket of laborTicketsUpdates) {
76
+ const ts = this.getComparableTicketTimestamp(ticket);
77
+ if (!ts) continue;
78
+ if (new Date(ts) > new Date(barrierTime)) continue;
79
+ if (
80
+ !maxMmTimestampWithinBarrier ||
81
+ new Date(ts) > new Date(maxMmTimestampWithinBarrier)
82
+ ) {
83
+ maxMmTimestampWithinBarrier = ts;
84
+ }
85
+ }
67
86
 
68
- await Promise.all(
69
- laborTicketsUpdates.map(async (laborTicket: MMReceiveLaborTicket) => {
70
- if (!laborTicket.laborTicketRef) {
87
+ if (pass === 1) {
88
+ logger.info(
89
+ `ToERP: Found ${laborTicketsUpdates.length} Labor Ticket Ids and Refs to process`,
90
+ {
91
+ laborTickets: laborTicketsUpdates.map(
92
+ (ticket: MMReceiveLaborTicket) => ({
93
+ ref: ticket.laborTicketRef,
94
+ id: ticket.laborTicketId,
95
+ })
96
+ ),
97
+ }
98
+ );
99
+ }
100
+
101
+ // Build a unique pending list by a stable "business signature", and only consider tickets
102
+ // whose timestamps are <= the barrierTime (prevents checkpoint gaps if clocks differ).
103
+ const pending: Array<{ sig: string; ticket: MMReceiveLaborTicket }> = [];
104
+ const dedupeWithinFetch = new Set<string>();
105
+
106
+ for (const ticket of laborTicketsUpdates) {
107
+ if (!ticket.laborTicketRef) {
71
108
  logger.error(
72
109
  "syncLaborTicketsToERP: laborTicketRef is not set for laborTicket pulled from MM:",
73
- { laborTicket }
110
+ { laborTicket: ticket }
74
111
  );
75
- return undefined;
112
+ continue;
76
113
  }
77
114
 
78
- try {
79
- return await this.processLaborTicket(
80
- connector,
81
- mmApiClient,
82
- laborTicket
83
- );
84
- } catch (error) {
85
- failedLaborTicketRefs.push(laborTicket.laborTicketRef);
86
- logger.error(
87
- `syncLaborTicketsToERP: Error processing laborTicketRef ${laborTicket.laborTicketRef}:`,
88
- { error }
89
- );
90
- return undefined;
115
+ const ts = this.getComparableTicketTimestamp(ticket);
116
+ if (ts && new Date(ts) > new Date(barrierTime)) {
117
+ // Defer "future" tickets (relative to local wall clock) to a later run/pass.
118
+ continue;
91
119
  }
92
- })
93
- );
120
+
121
+ const sig = this.laborTicketBusinessSignature(ticket);
122
+ if (attemptedSignatures.has(sig) || dedupeWithinFetch.has(sig)) continue;
123
+ dedupeWithinFetch.add(sig);
124
+ pending.push({ sig, ticket });
125
+ }
126
+
127
+ if (pending.length === 0) {
128
+ // Nothing new to do in this barrier window; safe to checkpoint and exit.
129
+ break;
130
+ }
131
+
132
+ logger.info(
133
+ `syncLaborTicketsToERP: pass=${pass}/${maxPasses}, barrier=${barrierTime}, pending=${pending.length}`
134
+ );
135
+
136
+ await Promise.all(
137
+ pending.map(async ({ sig, ticket }) => {
138
+ // Mark attempted up-front so we don't re-attempt within this run even if MM reorders.
139
+ attemptedSignatures.add(sig);
140
+
141
+ try {
142
+ return await this.processLaborTicket(connector, mmApiClient, ticket);
143
+ } catch (error) {
144
+ failedLaborTicketRefs.add(ticket.laborTicketRef);
145
+ logger.error(
146
+ `syncLaborTicketsToERP: Error processing laborTicketRef ${ticket.laborTicketRef}:`,
147
+ { error }
148
+ );
149
+ return undefined;
150
+ }
151
+ })
152
+ );
153
+ }
154
+
155
+ if (pass >= maxPasses) {
156
+ logger.warn(
157
+ `syncLaborTicketsToERP: Reached max passes (${maxPasses}). Checkpointing anyway to avoid infinite loops.`
158
+ );
159
+ }
94
160
 
95
161
  logger.info(
96
- `syncLaborTicketsToERP: ${failedLaborTicketRefs.length} failed labor ticket ids`
162
+ `syncLaborTicketsToERP: ${failedLaborTicketRefs.size} failed labor ticket ids`
97
163
  );
98
- if (failedLaborTicketRefs.length > 0) {
164
+ if (failedLaborTicketRefs.size > 0) {
165
+ const failedTicketRefs = Array.from(failedLaborTicketRefs);
99
166
  logger.info(
100
- `syncLaborTicketsToERP: Reporting ${failedLaborTicketRefs.length} labor ticket failures:`,
167
+ `syncLaborTicketsToERP: Reporting ${failedTicketRefs.length} labor ticket failures:`,
101
168
  {
102
- failedLaborTicketRefs,
169
+ failedLaborTicketRefs: failedTicketRefs,
103
170
  }
104
171
  );
105
172
  const addFailedResult = await mmApiClient.addFailedLaborTicketRefs(
106
173
  connectorType,
107
- failedLaborTicketRefs
174
+ failedTicketRefs
108
175
  );
109
176
  logger.info("syncLaborTicketsToERP: addFailedResult:", {
110
177
  addFailedResult,
111
178
  });
112
179
  }
113
180
 
114
- mmApiClient.saveCheckpoint({
181
+ const checkpointTimestamp = this.computeCheckpointTimestamp({
182
+ barrierTime,
183
+ maxMmTimestampWithinBarrier,
184
+ skewMs: this.CHECKPOINT_SKEW_MS,
185
+ });
186
+
187
+ await mmApiClient.saveCheckpoint({
115
188
  system: connectorType,
116
189
  table: "labor_tickets",
117
190
  checkpointType: "export",
118
191
  checkpointValue: {
119
- timestamp: mostRecentUpdate || fallbackTimestamp,
192
+ timestamp: checkpointTimestamp,
120
193
  },
121
194
  });
195
+ logger.info("syncLaborTicketsToERP: Checkpoint saved:", {
196
+ checkpointTimestamp,
197
+ });
122
198
  } catch (error) {
123
199
  logger.error("syncLaborTicketsToERP: Error:", error);
124
200
  }
@@ -215,10 +291,10 @@ export class LaborTicketERPSynchronizer {
215
291
  ): Promise<MMReceiveLaborTicket> {
216
292
  let laborTicketResult: MMReceiveLaborTicket;
217
293
 
218
- laborTicketResult = convertLaborTicketToLocalTimezone(
219
- laborTicket,
220
- getCachedTimezoneOffset()
221
- );
294
+ // Convert MM's UTC timestamps into the ERP's local timezone before invoking connector code.
295
+ // Connector implementations should treat the incoming values as localized wall time and avoid
296
+ // applying any further timezone shifts.
297
+ laborTicketResult = convertLaborTicketToLocalTimezone(laborTicket);
222
298
 
223
299
  logger.info(
224
300
  `processing laborTicket, id=${laborTicket.laborTicketId}, ref=${laborTicket.laborTicketRef}`
@@ -258,4 +334,84 @@ export class LaborTicketERPSynchronizer {
258
334
 
259
335
  return laborTicketResult;
260
336
  }
337
+
338
+ /**
339
+ * A stable identity for "did the business-relevant contents of this labor ticket change?"
340
+ *
341
+ * IMPORTANT: Excludes fields that the SDK itself mutates (e.g. laborTicketId, updatedAt),
342
+ * otherwise we'd reprocess the write-back bump on the next cycle.
343
+ */
344
+ private static laborTicketBusinessSignature(ticket: MMReceiveLaborTicket): string {
345
+ const reasons = (ticket.reasons ?? [])
346
+ .map((r) => {
347
+ const reason: any = (r as any)?.reason ?? {};
348
+ return (
349
+ reason.reasonId ??
350
+ reason.code ??
351
+ reason.reasonRef ??
352
+ reason.rejectReasonRef ??
353
+ ""
354
+ );
355
+ })
356
+ .filter((v) => v !== "" && v !== null && v !== undefined)
357
+ .map(String)
358
+ .sort();
359
+
360
+ const signatureObject = {
361
+ laborTicketRef: ticket.laborTicketRef ?? null,
362
+ clockIn: ticket.clockIn ?? null,
363
+ clockOut: ticket.clockOut ?? null,
364
+ goodParts: ticket.goodParts ?? null,
365
+ badParts: ticket.badParts ?? null,
366
+ state: ticket.state ?? null,
367
+ type: ticket.type ?? null,
368
+ transactionDate: ticket.transactionDate ?? null,
369
+ workOrderId: ticket.workOrderId ?? null,
370
+ sequenceNumber: ticket.sequenceNumber ?? null,
371
+ personId: ticket.personId ?? null,
372
+ resourceId: ticket.resourceId ?? null,
373
+ lot: ticket.lot ?? null,
374
+ split: ticket.split ?? null,
375
+ sub: ticket.sub ?? null,
376
+ comment: ticket.comment ?? null,
377
+ workOrderOperationClosedDate: ticket.workOrderOperationClosedDate ?? null,
378
+ reasons,
379
+ };
380
+
381
+ return JSON.stringify(signatureObject);
382
+ }
383
+
384
+ /**
385
+ * Selects a comparable timestamp for windowing decisions.
386
+ * Prefer updatedAt; fall back to other stable timestamps if needed.
387
+ */
388
+ private static getComparableTicketTimestamp(
389
+ ticket: MMReceiveLaborTicket
390
+ ): string | null {
391
+ return (
392
+ ticket.updatedAt ??
393
+ ticket.createdAt ??
394
+ ticket.transactionDate ??
395
+ ticket.clockOut ??
396
+ ticket.clockIn ??
397
+ null
398
+ );
399
+ }
400
+
401
+ private static addMsToIso(iso: string, ms: number): string {
402
+ return new Date(new Date(iso).getTime() + ms).toISOString();
403
+ }
404
+
405
+ private static computeCheckpointTimestamp(options: {
406
+ barrierTime: string;
407
+ maxMmTimestampWithinBarrier: string | null;
408
+ skewMs: number;
409
+ }): string {
410
+ const { barrierTime, maxMmTimestampWithinBarrier, skewMs } = options;
411
+
412
+ if (!maxMmTimestampWithinBarrier) return barrierTime;
413
+
414
+ const mmPlusSkew = this.addMsToIso(maxMmTimestampWithinBarrier, skewMs);
415
+ return new Date(mmPlusSkew) < new Date(barrierTime) ? mmPlusSkew : barrierTime;
416
+ }
261
417
  }
@@ -1,5 +1,5 @@
1
- import { ERPObjType } from "../../types/erp-types";
2
- import { BatchCacheManager } from "../../services/caching-service/batch-cache-manager";
1
+ import { ERPObjType } from "../../types/erp-types.js";
2
+ import { BatchCacheManager } from "../../services/caching-service/batch-cache-manager.js";
3
3
  import {
4
4
  IToRESTApiObject,
5
5
  MMSendPerson,
@@ -15,21 +15,27 @@ import {
15
15
  MM200LaborTicketResponse,
16
16
  MM207NonLaborTicketResponse,
17
17
  MM207LaborTicketResponse,
18
- } from "../../services/mm-api-service";
19
- import { MMApiClient } from "../../services/mm-api-service/mm-api-service";
20
- import { HTTPError } from "../http-client";
18
+ } from "../../services/mm-api-service/index.js";
19
+ import { MMApiClient } from "../../services/mm-api-service/mm-api-service.js";
20
+ import { HTTPError } from "../http-client.js";
21
21
  import {
22
22
  WriteEntitiesToMMResult,
23
23
  MMBatchValidationError,
24
- } from "./standard-process-drivers";
25
- import { ErrorProcessor } from "./error-processor";
24
+ } from "./standard-process-drivers.js";
25
+ import { ErrorProcessor } from "./error-processor.js";
26
26
 
27
27
  /**
28
28
  * Handles processing of entities to the MachineMetrics API
29
29
  */
30
30
  export class MMEntityProcessor {
31
31
  /**
32
- * Writes entities to MM API with deduplication and caching
32
+ * Writes entities to MM API with deduplication and caching.
33
+ *
34
+ * IMPORTANT: All datetime fields on `mmRecords` MUST already be expressed as
35
+ * ISO-8601 UTC strings (either trailing `Z` or an explicit offset). The SDK
36
+ * does not apply timezone conversion on this path. It forwards values directly
37
+ * to MachineMetrics and only reserializes them for validation. Connector code
38
+ * is responsible for converting local ERP times to UTC before invoking this API.
33
39
  */
34
40
  static async writeEntities(
35
41
  entityType: ERPObjType,
@@ -1,6 +1,7 @@
1
- import { ERPObjType } from "../../types/erp-types";
2
- import { IERPLaborTicketHandler } from "../../types/erp-connector";
3
- import { BatchCacheManager } from "../../services/caching-service/batch-cache-manager";
1
+ import { ERPObjType } from "../../types/erp-types.js";
2
+ import { IERPLaborTicketHandler } from "../../types/erp-connector.js";
3
+ import type { FlattenedWorkOrderRow } from "../../types/flattened-work-order.js";
4
+ import { BatchCacheManager } from "../../services/caching-service/batch-cache-manager.js";
4
5
  import {
5
6
  IToRESTApiObject,
6
7
  MMSendWorkOrderBatch,
@@ -8,9 +9,9 @@ import {
8
9
  MMSendPartOperation,
9
10
  MMSendWorkOrder,
10
11
  MMSendWorkOrderOperation,
11
- } from "../../services/mm-api-service";
12
- import { LaborTicketERPSynchronizer } from "./labor-ticket-erp-synchronizer";
13
- import { MMEntityProcessor } from "./mm-entity-processor";
12
+ } from "../../services/mm-api-service/index.js";
13
+ import { LaborTicketERPSynchronizer } from "./labor-ticket-erp-synchronizer.js";
14
+ import { MMEntityProcessor } from "./mm-entity-processor.js";
14
15
 
15
16
  /**
16
17
  * The result of writing entities to the MachineMetrics API on complete success.
@@ -248,7 +249,12 @@ export class StandardProcessDrivers {
248
249
  * parts, part operations, work orders, and work order operations, then process them in the correct order
249
250
  * to maintain referential integrity.
250
251
  *
251
- * @param flattenedData Array of flattened rows containing both work order and operation data (camelCase fields)
252
+ * Timezone expectation: all datetime fields provided in `flattenedData` MUST already be expressed
253
+ * as ISO-8601 UTC strings (trailing `Z` or explicit offset). The SDK does not attempt to infer or
254
+ * convert local ERP timestamps on this path; it simply validates and forwards the values to MM.
255
+ * Connector implementations should convert ERP-local times to UTC before invoking this method.
256
+ *
257
+ * @param flattenedData Array of flattened rows containing both work order and operation data (see `FlattenedWorkOrderRow`)
252
258
  * @param batchCacheManager The batch cache manager instance; pass in null if caching is not desired
253
259
  *
254
260
  * @returns Combined results from all entity processing with detailed logging information
@@ -256,7 +262,7 @@ export class StandardProcessDrivers {
256
262
  * @throws Error on other underlying issues (network, authentication, etc.)
257
263
  */
258
264
  static async syncWorkOrderBatchFromFlattened(
259
- flattenedData: any[],
265
+ flattenedData: ReadonlyArray<FlattenedWorkOrderRow>,
260
266
  batchCacheManager: BatchCacheManager | null
261
267
  ): Promise<{
262
268
  parts: WriteEntitiesToMMResult;
@@ -268,6 +274,11 @@ export class StandardProcessDrivers {
268
274
  throw new Error("No flattened work order data provided");
269
275
  }
270
276
 
277
+ const toStringOrFallback = (
278
+ value: string | number | null | undefined,
279
+ fallback = ""
280
+ ): string => (value === undefined || value === null ? fallback : String(value));
281
+
271
282
  // Process the flattened data - each row contains both work order and operation info
272
283
  const uniqueParts = new Map();
273
284
  const uniquePartOperations = new Map();
@@ -297,8 +308,8 @@ export class StandardProcessDrivers {
297
308
  resourceId: row.resourceId, // → resourceId
298
309
  cycleTimeMs: row.cycleTimeMs, // → cycleTimeMs
299
310
  setupTimeMs: row.setupTimeMs, // → setupTimeMs
300
- description: row.operationDescription || "", // → description
301
- quantityPerPart: row.quantityPerPart || 1, // → quantityPerPart
311
+ operationDescription: row.operationDescription, // → description
312
+ quantityPerPart: row.quantityPerPart ?? 1, // → quantityPerPart
302
313
  });
303
314
  }
304
315
 
@@ -351,8 +362,8 @@ export class StandardProcessDrivers {
351
362
  const parts = Array.from(uniqueParts.values()).map(
352
363
  (item) =>
353
364
  new MMSendPart(
354
- item.partNumber || "", // partNumber
355
- item.partRevision || "", // partRevision
365
+ toStringOrFallback(item.partNumber), // partNumber
366
+ toStringOrFallback(item.partRevision), // partRevision
356
367
  item.method || "Standard" // method
357
368
  )
358
369
  );
@@ -360,14 +371,14 @@ export class StandardProcessDrivers {
360
371
  const partOperations = Array.from(uniquePartOperations.values()).map(
361
372
  (item) =>
362
373
  new MMSendPartOperation(
363
- item.partNumber || "", // partNumber
364
- item.partRevision || "", // partRevision
374
+ toStringOrFallback(item.partNumber), // partNumber
375
+ toStringOrFallback(item.partRevision), // partRevision
365
376
  item.method || "Standard", // method
366
377
  item.sequenceNumber?.toString() || "", // sequenceNumber
367
378
  item.resourceId?.toString() || "", // resourceId
368
379
  item.cycleTimeMs || 0, // cycleTimeMs
369
380
  item.setupTimeMs || 0, // setupTimeMs
370
- item.description || "", // description
381
+ item.operationDescription || "", // description
371
382
  item.quantityPerPart || 1 // quantityPerPart
372
383
  )
373
384
  );
@@ -376,10 +387,12 @@ export class StandardProcessDrivers {
376
387
  (item) =>
377
388
  new MMSendWorkOrder(
378
389
  item.workOrderId?.toString() || "", // workOrderId
379
- item.lot || "", // lot
380
- item.split || "", // split
381
- item.sub || "", // sub
390
+ toStringOrFallback(item.lot), // lot
391
+ toStringOrFallback(item.split), // split
392
+ toStringOrFallback(item.sub), // sub
382
393
  item.status || "Open", // status
394
+ // Datetimes are assumed to already be UTC (or include an explicit offset).
395
+ // We reserialize via Date solely to validate the ISO format before sending to MM.
383
396
  item.dueDate ? new Date(item.dueDate).toISOString() : null, // dueDate
384
397
  item.description || "", // description
385
398
  item.scheduledStartDate
@@ -390,8 +403,8 @@ export class StandardProcessDrivers {
390
403
  : null, // scheduledEndDate
391
404
  item.closedDate ? new Date(item.closedDate).toISOString() : null, // closedDate
392
405
  item.quantityRequired || 0, // quantityRequired
393
- item.partNumber || "", // partNumber
394
- item.partRevision || "", // partRevision
406
+ toStringOrFallback(item.partNumber), // partNumber
407
+ toStringOrFallback(item.partRevision), // partRevision
395
408
  item.method || "Standard" // method
396
409
  )
397
410
  );
@@ -400,14 +413,15 @@ export class StandardProcessDrivers {
400
413
  (item) =>
401
414
  new MMSendWorkOrderOperation(
402
415
  item.workOrderId?.toString() || "", // workOrderId
403
- item.lot || "", // lot
404
- item.split || "", // split
405
- item.sub || "", // sub
416
+ toStringOrFallback(item.lot), // lot
417
+ toStringOrFallback(item.split), // split
418
+ toStringOrFallback(item.sub), // sub
406
419
  item.sequenceNumber?.toString() || "", // sequenceNumber
407
420
  item.resourceId?.toString() || "", // resourceId
408
421
  item.startQuantity || 0, // startQuantity
409
422
  item.finishQuantity || 0, // finishQuantity
410
423
  item.expectedRejectRate || 0, // expectedRejectRate
424
+ // Same UTC expectation as above; reserialize to ensure valid ISO.
411
425
  item.scheduledStartDate
412
426
  ? new Date(item.scheduledStartDate).toISOString()
413
427
  : null, // scheduledStartDate
@@ -417,8 +431,8 @@ export class StandardProcessDrivers {
417
431
  item.closedDate ? new Date(item.closedDate).toISOString() : null, // closedDate
418
432
  item.cycleTimeMs || 0, // cycleTimeMs
419
433
  item.setupTimeMs || 0, // setupTimeMs
420
- parseFloat(item.productionburdenRateHourly || "0"), // productionburdenRateHourly
421
- parseFloat(item.setupburdenRatehourly || "0"), // setupburdenRatehourly
434
+ parseFloat(toStringOrFallback(item.productionburdenRateHourly, "0")), // productionburdenRateHourly
435
+ parseFloat(toStringOrFallback(item.setupburdenRatehourly, "0")), // setupburdenRatehourly
422
436
  item.operationType || "Production", // operationType
423
437
  item.quantityPerPart || 1, // quantityPerPart
424
438
  item.status || "Open" // status
@@ -1,13 +1,14 @@
1
- import logger from "../services/reporting-service/logger";
1
+ import { DateTime } from 'luxon';
2
+ import logger from "../services/reporting-service/logger.js";
2
3
  import {
3
4
  setTimezoneOffsetInCache,
4
5
  setTimezoneNameInCache,
5
- } from "./local-data-store/jobs-shared-data";
6
+ } from "./local-data-store/jobs-shared-data.js";
6
7
  import {
7
8
  convertToLocalTime,
8
9
  formatDateWithTZOffset,
9
10
  getTimezoneOffset,
10
- } from "./timezone";
11
+ } from "./timezone.js";
11
12
 
12
13
  /**
13
14
  * Calculates the difference in hours between two timestamps
@@ -117,6 +118,16 @@ export const getTimezoneOffsetAndPersist = async (
117
118
  const { offset, timezone } = await getTimezoneOffset();
118
119
  logger.info(`Timezone offset: ${offset} hours, timezone: ${timezone}`);
119
120
  setTimezoneOffsetInCache(offset);
121
+
122
+ const now = DateTime.now().setZone(timezone);
123
+ if (!now.isValid) {
124
+ throw new Error(
125
+ `Invalid timezone name from Company properties: "${timezone}". ` +
126
+ `Must be a valid IANA timezone name (e.g., "America/Chicago"). ` +
127
+ `See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones`
128
+ );
129
+ }
130
+
120
131
  setTimezoneNameInCache(timezone);
121
132
  success = true;
122
133
  } catch (error) {
@@ -1,5 +1,5 @@
1
- import { CoreConfiguration } from "../services/data-sync-service/configuration-manager";
2
- import { HTTPClientFactory } from "./http-client";
1
+ import { CoreConfiguration } from "../services/data-sync-service/configuration-manager.js";
2
+ import { HTTPClientFactory } from "./http-client.js";
3
3
 
4
4
  /**
5
5
  * Gets the timezone offset in hours and timezone name for the company's timezone