monkeybrain-runtime 1.0.0__py3-none-any.whl

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 (838) hide show
  1. monkeybrain_runtime-1.0.0.dist-info/METADATA +76 -0
  2. monkeybrain_runtime-1.0.0.dist-info/RECORD +838 -0
  3. monkeybrain_runtime-1.0.0.dist-info/WHEEL +5 -0
  4. monkeybrain_runtime-1.0.0.dist-info/entry_points.txt +3 -0
  5. monkeybrain_runtime-1.0.0.dist-info/top_level.txt +2 -0
  6. services/__init__.py +8 -0
  7. services/agentos/__init__.py +0 -0
  8. services/agentos/main.py +1 -0
  9. services/assets/helpers/__init__.py +12 -0
  10. services/assets/helpers/device.py +59 -0
  11. services/assets/helpers/equipment.py +179 -0
  12. services/assets/helpers/instruments.py +72 -0
  13. services/assets/helpers/machines.py +183 -0
  14. services/assets/helpers/materials.py +76 -0
  15. services/assets/helpers/parts.py +116 -0
  16. services/assets/helpers/plc.py +134 -0
  17. services/assets/helpers/tags.py +108 -0
  18. services/assets/helpers/tools.py +101 -0
  19. services/assets/main.py +75 -0
  20. services/assets/models/__init__.py +12 -0
  21. services/assets/models/device.py +79 -0
  22. services/assets/models/equipment.py +222 -0
  23. services/assets/models/instruments.py +85 -0
  24. services/assets/models/machines.py +230 -0
  25. services/assets/models/material.py +266 -0
  26. services/assets/models/parts.py +96 -0
  27. services/assets/models/plc.py +264 -0
  28. services/assets/models/tags.py +76 -0
  29. services/assets/models/tools.py +179 -0
  30. services/assets/routers/__init__.py +12 -0
  31. services/assets/routers/classes.py +65 -0
  32. services/assets/routers/device.py +86 -0
  33. services/assets/routers/equipment.py +145 -0
  34. services/assets/routers/families.py +61 -0
  35. services/assets/routers/instruments.py +70 -0
  36. services/assets/routers/machines.py +136 -0
  37. services/assets/routers/materials.py +105 -0
  38. services/assets/routers/parts.py +130 -0
  39. services/assets/routers/plc.py +94 -0
  40. services/assets/routers/subclasses.py +68 -0
  41. services/assets/routers/tags.py +138 -0
  42. services/assets/routers/tools.py +113 -0
  43. services/auth/helpers/__init__.py +13 -0
  44. services/auth/helpers/approval_decisions.py +261 -0
  45. services/auth/helpers/audit_elasticsearch_sync.py +350 -0
  46. services/auth/helpers/departments.py +53 -0
  47. services/auth/helpers/graph_store.py +848 -0
  48. services/auth/helpers/influx_store.py +280 -0
  49. services/auth/helpers/me.py +33 -0
  50. services/auth/helpers/nats_consumer.py +618 -0
  51. services/auth/helpers/nats_store.py +242 -0
  52. services/auth/helpers/permissions.py +62 -0
  53. services/auth/helpers/roles.py +87 -0
  54. services/auth/helpers/store.py +54 -0
  55. services/auth/helpers/team_members.py +155 -0
  56. services/auth/helpers/teams.py +87 -0
  57. services/auth/helpers/tokens.py +71 -0
  58. services/auth/helpers/users.py +119 -0
  59. services/auth/helpers/websocket_broadcast.py +41 -0
  60. services/auth/main.py +88 -0
  61. services/auth/models/__init__.py +12 -0
  62. services/auth/models/departments.py +55 -0
  63. services/auth/models/login.py +20 -0
  64. services/auth/models/permissions.py +61 -0
  65. services/auth/models/roles.py +53 -0
  66. services/auth/models/session.py +26 -0
  67. services/auth/models/teamMembers.py +59 -0
  68. services/auth/models/teams.py +56 -0
  69. services/auth/models/users.py +77 -0
  70. services/auth/routers/__init__.py +14 -0
  71. services/auth/routers/auth.py +3839 -0
  72. services/auth/routers/departments.py +84 -0
  73. services/auth/routers/integration_config.py +703 -0
  74. services/auth/routers/me.py +28 -0
  75. services/auth/routers/permissions.py +96 -0
  76. services/auth/routers/roles.py +139 -0
  77. services/auth/routers/session.py +224 -0
  78. services/auth/routers/team_members.py +152 -0
  79. services/auth/routers/teams.py +112 -0
  80. services/auth/routers/users.py +131 -0
  81. services/auth/routers/websocket_events.py +247 -0
  82. services/batch_execution/__init__.py +19 -0
  83. services/batch_execution/pipeline_triggers/__init__.py +53 -0
  84. services/batch_execution/pipeline_triggers/pipeline_parameter_adjuster.py +440 -0
  85. services/batch_execution/pipeline_triggers/pipeline_trigger_engine.py +445 -0
  86. services/batch_execution/pipeline_triggers/re_evaluation_queue.py +341 -0
  87. services/batch_execution/pipeline_triggers/test_phase3_implementation.py +553 -0
  88. services/batch_execution/pipeline_triggers/workflow_reevaluator.py +367 -0
  89. services/batch_execution/smoke_test_e2e_feedback_loop.py +704 -0
  90. services/batch_execution/workflow_executor.py +478 -0
  91. services/changeover/helpers/__init__.py +11 -0
  92. services/changeover/helpers/changeover.py +87 -0
  93. services/changeover/helpers/changeover_common.py +55 -0
  94. services/changeover/helpers/changeover_events.py +66 -0
  95. services/changeover/helpers/changeover_kpis.py +33 -0
  96. services/changeover/helpers/changeover_matrix.py +60 -0
  97. services/changeover/helpers/changeover_procedures.py +164 -0
  98. services/changeover/helpers/changeover_windows.py +96 -0
  99. services/changeover/main.py +52 -0
  100. services/changeover/models/__init__.py +11 -0
  101. services/changeover/models/changeover.py +73 -0
  102. services/changeover/models/changeover_events.py +142 -0
  103. services/changeover/models/changeover_kpis.py +75 -0
  104. services/changeover/models/changeover_matrix.py +63 -0
  105. services/changeover/models/changeover_procedures.py +108 -0
  106. services/changeover/models/changeover_tasks.py +87 -0
  107. services/changeover/models/changeover_windows.py +72 -0
  108. services/changeover/routers/__init__.py +9 -0
  109. services/changeover/routers/changeover_events.py +127 -0
  110. services/changeover/routers/changeover_kpis.py +80 -0
  111. services/changeover/routers/changeover_matrix.py +80 -0
  112. services/changeover/routers/changeover_procedures.py +118 -0
  113. services/changeover/routers/changeover_windows.py +98 -0
  114. services/common/__init__.py +2 -0
  115. services/common/approval_chains.py +648 -0
  116. services/common/auth.py +56 -0
  117. services/common/cdc.py +52 -0
  118. services/common/compat.py +217 -0
  119. services/common/compliance.py +562 -0
  120. services/common/config.py +134 -0
  121. services/common/cors.py +17 -0
  122. services/common/data_transformation.py +195 -0
  123. services/common/db.py +577 -0
  124. services/common/embeddings.py +97 -0
  125. services/common/event_reducers.py +194 -0
  126. services/common/event_types.py +51 -0
  127. services/common/integration_ingestion.py +169 -0
  128. services/common/logging.py +204 -0
  129. services/common/models/__init__.py +2 -0
  130. services/common/models/databricks.py +25 -0
  131. services/common/models/enums.py +64 -0
  132. services/common/module_control.py +422 -0
  133. services/common/mongo_cdc_watcher.py +106 -0
  134. services/common/n8n_auth.py +22 -0
  135. services/common/neo4j_mirror.py +1087 -0
  136. services/common/ontology_registry.py +110 -0
  137. services/common/reasoning_traces.py +52 -0
  138. services/common/supply_chain_cdc.py +555 -0
  139. services/common/tracing.py +159 -0
  140. services/common/utils.py +30 -0
  141. services/customers/helpers/__init__.py +8 -0
  142. services/customers/helpers/customer_details.py +64 -0
  143. services/customers/helpers/customer_metadata.py +64 -0
  144. services/customers/helpers/customer_order_metrics.py +67 -0
  145. services/customers/helpers/customer_payment_data.py +67 -0
  146. services/customers/main.py +50 -0
  147. services/customers/models/__init__.py +8 -0
  148. services/customers/models/customer_details.py +42 -0
  149. services/customers/models/customer_metadata.py +97 -0
  150. services/customers/models/customer_order_metrics.py +86 -0
  151. services/customers/models/customer_payment_data.py +60 -0
  152. services/customers/routers/__init__.py +8 -0
  153. services/customers/routers/customer_details.py +88 -0
  154. services/customers/routers/customer_metadata.py +88 -0
  155. services/customers/routers/customer_order_metrics.py +88 -0
  156. services/customers/routers/customer_payment_data.py +88 -0
  157. services/documents/__init__.py +1 -0
  158. services/documents/helpers/__init__.py +6 -0
  159. services/documents/helpers/document_metadata.py +569 -0
  160. services/documents/helpers/document_workflows.py +215 -0
  161. services/documents/helpers/report_templates.py +113 -0
  162. services/documents/main.py +49 -0
  163. services/documents/models/__init__.py +6 -0
  164. services/documents/models/document_metadata.py +215 -0
  165. services/documents/models/document_workflows.py +136 -0
  166. services/documents/models/report_templates.py +132 -0
  167. services/documents/routers/__init__.py +6 -0
  168. services/documents/routers/document_metadata.py +654 -0
  169. services/documents/routers/document_workflows.py +146 -0
  170. services/documents/routers/report_templates.py +86 -0
  171. services/events/helpers/__init__.py +5 -0
  172. services/events/helpers/events.py +394 -0
  173. services/events/main.py +40 -0
  174. services/events/models/__init__.py +5 -0
  175. services/events/models/events.py +50 -0
  176. services/events/routers/__init__.py +6 -0
  177. services/events/routers/count_events.py +109 -0
  178. services/events/routers/events.py +75 -0
  179. services/events/seed_events.py +196 -0
  180. services/facilities/helpers/__init__.py +8 -0
  181. services/facilities/helpers/lines.py +74 -0
  182. services/facilities/helpers/locations.py +231 -0
  183. services/facilities/helpers/plants.py +59 -0
  184. services/facilities/helpers/stages.py +110 -0
  185. services/facilities/helpers/workstation.py +213 -0
  186. services/facilities/main.py +60 -0
  187. services/facilities/models/__init__.py +10 -0
  188. services/facilities/models/industrialLine.py +72 -0
  189. services/facilities/models/industrialPlant.py +164 -0
  190. services/facilities/models/locations.py +74 -0
  191. services/facilities/models/stages.py +92 -0
  192. services/facilities/models/worker.py +73 -0
  193. services/facilities/models/workstation.py +117 -0
  194. services/facilities/models/workstation_live_state.py +59 -0
  195. services/facilities/routers/__init__.py +8 -0
  196. services/facilities/routers/bays.py +81 -0
  197. services/facilities/routers/buildings.py +92 -0
  198. services/facilities/routers/floors.py +81 -0
  199. services/facilities/routers/lines.py +154 -0
  200. services/facilities/routers/locations.py +208 -0
  201. services/facilities/routers/plant.py +203 -0
  202. services/facilities/routers/rooms.py +81 -0
  203. services/facilities/routers/stages.py +152 -0
  204. services/facilities/routers/workstation.py +173 -0
  205. services/file/backup.py +71 -0
  206. services/file/main.py +45 -0
  207. services/file/recieve.py +54 -0
  208. services/file/send.py +55 -0
  209. services/file/src/core/config.py +90 -0
  210. services/file/src/core/keycloak.py +152 -0
  211. services/file/src/core/logging_config.py +9 -0
  212. services/file/src/core/security.py +33 -0
  213. services/file/src/helpers/cad_conversion.py +331 -0
  214. services/file/src/helpers/helpers.py +825 -0
  215. services/file/src/routes/cad_conversion.py +26 -0
  216. services/file/src/routes/files.py +136 -0
  217. services/file/src/routes/presigned.py +154 -0
  218. services/file/src/services/websocket.py +293 -0
  219. services/floor_layout/helpers/__init__.py +8 -0
  220. services/floor_layout/helpers/bays.py +92 -0
  221. services/floor_layout/helpers/buildings.py +54 -0
  222. services/floor_layout/helpers/floors.py +65 -0
  223. services/floor_layout/helpers/rooms.py +76 -0
  224. services/floor_layout/main.py +52 -0
  225. services/floor_layout/models/__init__.py +8 -0
  226. services/floor_layout/models/bays.py +65 -0
  227. services/floor_layout/models/buildings.py +52 -0
  228. services/floor_layout/models/floors.py +45 -0
  229. services/floor_layout/models/rooms.py +61 -0
  230. services/floor_layout/routers/__init__.py +9 -0
  231. services/floor_layout/routers/bays.py +143 -0
  232. services/floor_layout/routers/buildings.py +116 -0
  233. services/floor_layout/routers/floors.py +89 -0
  234. services/floor_layout/routers/locations.py +80 -0
  235. services/floor_layout/routers/rooms.py +134 -0
  236. services/inventory/helpers/__init__.py +13 -0
  237. services/inventory/helpers/cycle_counts.py +124 -0
  238. services/inventory/helpers/inventory_allocations.py +134 -0
  239. services/inventory/helpers/inventory_item_counts.py +114 -0
  240. services/inventory/helpers/inventory_item_quantities.py +114 -0
  241. services/inventory/helpers/inventory_items.py +103 -0
  242. services/inventory/helpers/inventory_stage_outputs.py +134 -0
  243. services/inventory/helpers/inventory_transactions.py +112 -0
  244. services/inventory/helpers/stock_adjustment_requests.py +101 -0
  245. services/inventory/helpers/warehouse_cycle_counts.py +133 -0
  246. services/inventory/helpers/warehouse_locations.py +213 -0
  247. services/inventory/helpers/warehouse_regulated_records.py +123 -0
  248. services/inventory/main.py +62 -0
  249. services/inventory/models/__init__.py +17 -0
  250. services/inventory/models/cycle_counts.py +99 -0
  251. services/inventory/models/inventory_allocations.py +121 -0
  252. services/inventory/models/inventory_common.py +65 -0
  253. services/inventory/models/inventory_enums.py +21 -0
  254. services/inventory/models/inventory_item_count.py +65 -0
  255. services/inventory/models/inventory_item_quantity.py +82 -0
  256. services/inventory/models/inventory_items.py +168 -0
  257. services/inventory/models/inventory_responses.py +44 -0
  258. services/inventory/models/inventory_stage_outputs.py +96 -0
  259. services/inventory/models/inventory_state.py +15 -0
  260. services/inventory/models/inventory_transactions.py +80 -0
  261. services/inventory/models/stock_adjustment_requests.py +109 -0
  262. services/inventory/models/warehouse_cycle_counts.py +119 -0
  263. services/inventory/models/warehouse_location_models.py +708 -0
  264. services/inventory/models/warehouse_regulated_records.py +358 -0
  265. services/inventory/routers/__init__.py +13 -0
  266. services/inventory/routers/cycle_counts.py +106 -0
  267. services/inventory/routers/inventory_allocations.py +125 -0
  268. services/inventory/routers/inventory_item_counts.py +105 -0
  269. services/inventory/routers/inventory_item_quantities.py +105 -0
  270. services/inventory/routers/inventory_items.py +109 -0
  271. services/inventory/routers/inventory_stage_outputs.py +122 -0
  272. services/inventory/routers/inventory_transactions.py +96 -0
  273. services/inventory/routers/stock_adjustment_requests.py +124 -0
  274. services/inventory/routers/warehouse_cycle_counts.py +124 -0
  275. services/inventory/routers/warehouse_locations.py +426 -0
  276. services/inventory/routers/warehouse_regulated_records.py +273 -0
  277. services/iot/helpers/__init__.py +8 -0
  278. services/iot/helpers/ble_device.py +87 -0
  279. services/iot/helpers/mqtt_bridge.py +115 -0
  280. services/iot/helpers/sensor_readings.py +63 -0
  281. services/iot/helpers/sensors.py +77 -0
  282. services/iot/helpers/servers.py +72 -0
  283. services/iot/helpers/uwb_device.py +95 -0
  284. services/iot/main.py +53 -0
  285. services/iot/models/__init__.py +8 -0
  286. services/iot/models/ble_device.py +118 -0
  287. services/iot/models/sensors.py +256 -0
  288. services/iot/models/servers.py +206 -0
  289. services/iot/models/uwb_device.py +106 -0
  290. services/iot/routers/__init__.py +8 -0
  291. services/iot/routers/ble_device.py +110 -0
  292. services/iot/routers/sensors.py +144 -0
  293. services/iot/routers/servers.py +141 -0
  294. services/iot/routers/uwb_device.py +148 -0
  295. services/module_control/__init__.py +1 -0
  296. services/module_control/helpers/__init__.py +1 -0
  297. services/module_control/helpers/integration_config.py +243 -0
  298. services/module_control/helpers/security.py +104 -0
  299. services/module_control/main.py +44 -0
  300. services/module_control/models/__init__.py +1 -0
  301. services/module_control/models/module_control.py +65 -0
  302. services/module_control/routers/__init__.py +1 -0
  303. services/module_control/routers/module_control.py +219 -0
  304. services/orders/helpers/__init__.py +11 -0
  305. services/orders/helpers/invoices.py +123 -0
  306. services/orders/helpers/order_customer_metrics.py +61 -0
  307. services/orders/helpers/order_details.py +71 -0
  308. services/orders/helpers/order_metadata.py +61 -0
  309. services/orders/helpers/order_payment_metadata.py +74 -0
  310. services/orders/helpers/orders.py +119 -0
  311. services/orders/helpers/sales_orders.py +136 -0
  312. services/orders/main.py +56 -0
  313. services/orders/models/__init__.py +11 -0
  314. services/orders/models/invoices.py +415 -0
  315. services/orders/models/order_customer_metrics.py +78 -0
  316. services/orders/models/order_details.py +46 -0
  317. services/orders/models/order_metadata.py +60 -0
  318. services/orders/models/order_payment_metadata.py +63 -0
  319. services/orders/models/orders.py +64 -0
  320. services/orders/models/sales_orders.py +130 -0
  321. services/orders/routers/__init__.py +11 -0
  322. services/orders/routers/invoices.py +111 -0
  323. services/orders/routers/order_customer_metrics.py +87 -0
  324. services/orders/routers/order_details.py +87 -0
  325. services/orders/routers/order_metadata.py +87 -0
  326. services/orders/routers/order_payment_metadata.py +87 -0
  327. services/orders/routers/orders.py +74 -0
  328. services/orders/routers/sales_orders.py +111 -0
  329. services/pm/helpers/__init__.py +14 -0
  330. services/pm/helpers/calendar_bookings.py +114 -0
  331. services/pm/helpers/calibration_point.py +110 -0
  332. services/pm/helpers/calibrations.py +196 -0
  333. services/pm/helpers/checklists.py +318 -0
  334. services/pm/helpers/cleaning.py +333 -0
  335. services/pm/helpers/downtime.py +376 -0
  336. services/pm/helpers/kanban_boards.py +186 -0
  337. services/pm/helpers/maintainance.py +177 -0
  338. services/pm/helpers/sop.py +1155 -0
  339. services/pm/helpers/sop_cdc.py +324 -0
  340. services/pm/helpers/weekly_schedules.py +79 -0
  341. services/pm/main.py +62 -0
  342. services/pm/models/__init__.py +14 -0
  343. services/pm/models/calendar_booking.py +82 -0
  344. services/pm/models/calibration_point.py +44 -0
  345. services/pm/models/calibrations.py +167 -0
  346. services/pm/models/checklists.py +117 -0
  347. services/pm/models/cleaning.py +203 -0
  348. services/pm/models/downtime.py +109 -0
  349. services/pm/models/kanban_board.py +178 -0
  350. services/pm/models/maintainanceLog.py +148 -0
  351. services/pm/models/sop.py +152 -0
  352. services/pm/models/weekly_schedule.py +91 -0
  353. services/pm/routers/__init__.py +14 -0
  354. services/pm/routers/calendar_bookings.py +143 -0
  355. services/pm/routers/calibration_point.py +94 -0
  356. services/pm/routers/calibrations.py +232 -0
  357. services/pm/routers/checklists.py +188 -0
  358. services/pm/routers/cleaning.py +127 -0
  359. services/pm/routers/downtime.py +143 -0
  360. services/pm/routers/kanban_boards.py +283 -0
  361. services/pm/routers/maintainance.py +241 -0
  362. services/pm/routers/sop.py +437 -0
  363. services/pm/routers/weekly_schedules.py +108 -0
  364. services/process_definitions/helpers/__init__.py +11 -0
  365. services/process_definitions/helpers/cpp_cqa_registry.py +120 -0
  366. services/process_definitions/helpers/mbmr_templates.py +107 -0
  367. services/process_definitions/helpers/packing_instructions.py +113 -0
  368. services/process_definitions/helpers/process_constraints.py +495 -0
  369. services/process_definitions/helpers/process_corrections.py +279 -0
  370. services/process_definitions/helpers/process_definition.py +996 -0
  371. services/process_definitions/helpers/process_node_catalog.py +786 -0
  372. services/process_definitions/helpers/process_post_checks.py +441 -0
  373. services/process_definitions/helpers/process_pre_checks.py +351 -0
  374. services/process_definitions/helpers/process_steps.py +220 -0
  375. services/process_definitions/main.py +71 -0
  376. services/process_definitions/models/__init__.py +13 -0
  377. services/process_definitions/models/cpp_cqa_registry.py +145 -0
  378. services/process_definitions/models/gxp_change_controls.py +38 -0
  379. services/process_definitions/models/gxp_risk_assessments.py +30 -0
  380. services/process_definitions/models/gxp_validation_evidence.py +33 -0
  381. services/process_definitions/models/mbmr_templates.py +173 -0
  382. services/process_definitions/models/packing_instructions.py +176 -0
  383. services/process_definitions/models/process_constraints.py +159 -0
  384. services/process_definitions/models/process_corrections.py +118 -0
  385. services/process_definitions/models/process_definition.py +685 -0
  386. services/process_definitions/models/process_definition_common.py +48 -0
  387. services/process_definitions/models/process_node_catalog.py +25 -0
  388. services/process_definitions/models/process_post_checks.py +171 -0
  389. services/process_definitions/models/process_pre_checks.py +168 -0
  390. services/process_definitions/models/process_steps.py +170 -0
  391. services/process_definitions/node_services/__init__.py +8 -0
  392. services/process_definitions/node_services/common.py +95 -0
  393. services/process_definitions/node_services/executor.py +499 -0
  394. services/process_definitions/node_services/flow_simulator.py +733 -0
  395. services/process_definitions/node_services/functions.py +193 -0
  396. services/process_definitions/node_services/messaging.py +44 -0
  397. services/process_definitions/node_services/models.py +221 -0
  398. services/process_definitions/node_services/network.py +161 -0
  399. services/process_definitions/node_services/parsers.py +87 -0
  400. services/process_definitions/node_services/sequence.py +95 -0
  401. services/process_definitions/node_services/storage.py +50 -0
  402. services/process_definitions/node_services/webhooks.py +52 -0
  403. services/process_definitions/routers/__init__.py +10 -0
  404. services/process_definitions/routers/cpp_cqa_registry.py +86 -0
  405. services/process_definitions/routers/mbmr_templates.py +84 -0
  406. services/process_definitions/routers/packing_instructions.py +84 -0
  407. services/process_definitions/routers/process_constraints.py +564 -0
  408. services/process_definitions/routers/process_corrections.py +343 -0
  409. services/process_definitions/routers/process_definition.py +992 -0
  410. services/process_definitions/routers/process_post_checks.py +529 -0
  411. services/process_definitions/routers/process_pre_checks.py +435 -0
  412. services/process_definitions/routers/process_steps.py +274 -0
  413. services/procurement/helpers/__init__.py +9 -0
  414. services/procurement/helpers/goods_receipts.py +240 -0
  415. services/procurement/helpers/purchase_order_shipping_information.py +85 -0
  416. services/procurement/helpers/purchase_orders.py +68 -0
  417. services/procurement/helpers/quality_control.py +235 -0
  418. services/procurement/helpers/sampling.py +404 -0
  419. services/procurement/main.py +52 -0
  420. services/procurement/models/__init__.py +9 -0
  421. services/procurement/models/goods_receipts.py +165 -0
  422. services/procurement/models/purchase_orders.py +54 -0
  423. services/procurement/models/quality_control.py +464 -0
  424. services/procurement/models/reinspection_records.py +28 -0
  425. services/procurement/models/sampling.py +262 -0
  426. services/procurement/models/shipping_information.py +51 -0
  427. services/procurement/routers/__init__.py +9 -0
  428. services/procurement/routers/goods_receipts.py +201 -0
  429. services/procurement/routers/purchase_orders.py +106 -0
  430. services/procurement/routers/quality_control.py +386 -0
  431. services/procurement/routers/sampling.py +296 -0
  432. services/procurement/routers/shipping_information.py +97 -0
  433. services/production/__init__.py +1 -0
  434. services/production/agents/__init__.py +5 -0
  435. services/production/agents/batch_planning_agent.py +815 -0
  436. services/production/models/__init__.py +25 -0
  437. services/production/models/batch.py +253 -0
  438. services/products/helpers/__init__.py +10 -0
  439. services/products/helpers/boms.py +100 -0
  440. services/products/helpers/drug_research.py +644 -0
  441. services/products/helpers/product_component.py +168 -0
  442. services/products/helpers/product_inventory.py +221 -0
  443. services/products/helpers/product_pricing.py +123 -0
  444. services/products/helpers/product_utils.py +32 -0
  445. services/products/helpers/products.py +81 -0
  446. services/products/main.py +59 -0
  447. services/products/models/__init__.py +9 -0
  448. services/products/models/drug_research.py +138 -0
  449. services/products/models/product_common.py +60 -0
  450. services/products/models/product_component.py +1028 -0
  451. services/products/models/product_inventory.py +118 -0
  452. services/products/models/product_pricing.py +73 -0
  453. services/products/models/products.py +151 -0
  454. services/products/routers/__init__.py +9 -0
  455. services/products/routers/boms.py +116 -0
  456. services/products/routers/drug_research.py +115 -0
  457. services/products/routers/product_components.py +123 -0
  458. services/products/routers/product_inventory.py +185 -0
  459. services/products/routers/product_pricing.py +136 -0
  460. services/products/routers/products.py +165 -0
  461. services/replenishment/__init__.py +1 -0
  462. services/replenishment/main.py +46 -0
  463. services/replenishment/routers/__init__.py +1 -0
  464. services/replenishment/routers/replenishment.py +20 -0
  465. services/shifts/helpers/__init__.py +7 -0
  466. services/shifts/helpers/shift_templates.py +124 -0
  467. services/shifts/helpers/shifts.py +79 -0
  468. services/shifts/helpers/timesheets.py +137 -0
  469. services/shifts/main.py +48 -0
  470. services/shifts/models/__init__.py +8 -0
  471. services/shifts/models/shift.py +62 -0
  472. services/shifts/models/shift_template.py +82 -0
  473. services/shifts/models/time_range.py +31 -0
  474. services/shifts/models/timesheet.py +196 -0
  475. services/shifts/routers/__init__.py +7 -0
  476. services/shifts/routers/shift_templates.py +97 -0
  477. services/shifts/routers/shifts.py +117 -0
  478. services/shifts/routers/timesheets.py +117 -0
  479. services/shipping/helpers/__init__.py +15 -0
  480. services/shipping/helpers/carrier.py +78 -0
  481. services/shipping/helpers/customs_declaration.py +104 -0
  482. services/shipping/helpers/delivery_note.py +99 -0
  483. services/shipping/helpers/package.py +95 -0
  484. services/shipping/helpers/pallet.py +85 -0
  485. services/shipping/helpers/route.py +93 -0
  486. services/shipping/helpers/shipping_information.py +82 -0
  487. services/shipping/helpers/shipping_provider_details.py +59 -0
  488. services/shipping/helpers/shipping_provider_metadata.py +59 -0
  489. services/shipping/helpers/vehicle.py +85 -0
  490. services/shipping/helpers/waybill.py +86 -0
  491. services/shipping/main.py +64 -0
  492. services/shipping/models/__init__.py +15 -0
  493. services/shipping/models/carrier.py +97 -0
  494. services/shipping/models/customs_declaration.py +138 -0
  495. services/shipping/models/delivery_note.py +163 -0
  496. services/shipping/models/package.py +152 -0
  497. services/shipping/models/pallet.py +137 -0
  498. services/shipping/models/route.py +120 -0
  499. services/shipping/models/shipping_information.py +55 -0
  500. services/shipping/models/shipping_provider_details.py +42 -0
  501. services/shipping/models/shipping_provider_metadata.py +54 -0
  502. services/shipping/models/vehicle.py +129 -0
  503. services/shipping/models/waybill.py +189 -0
  504. services/shipping/routers/__init__.py +15 -0
  505. services/shipping/routers/carrier.py +99 -0
  506. services/shipping/routers/customs_declaration.py +132 -0
  507. services/shipping/routers/delivery_note.py +150 -0
  508. services/shipping/routers/package.py +141 -0
  509. services/shipping/routers/pallet.py +108 -0
  510. services/shipping/routers/route.py +128 -0
  511. services/shipping/routers/shipping_information.py +97 -0
  512. services/shipping/routers/shipping_provider_details.py +80 -0
  513. services/shipping/routers/shipping_provider_metadata.py +80 -0
  514. services/shipping/routers/vehicle.py +117 -0
  515. services/shipping/routers/waybill.py +119 -0
  516. services/suppliers/helpers/__init__.py +13 -0
  517. services/suppliers/helpers/supplier_capabilities.py +58 -0
  518. services/suppliers/helpers/supplier_certifications.py +67 -0
  519. services/suppliers/helpers/supplier_details.py +58 -0
  520. services/suppliers/helpers/supplier_financials.py +58 -0
  521. services/suppliers/helpers/supplier_inventory.py +74 -0
  522. services/suppliers/helpers/supplier_locations.py +60 -0
  523. services/suppliers/helpers/supplier_pricing.py +69 -0
  524. services/suppliers/helpers/supplier_quality.py +69 -0
  525. services/suppliers/helpers/supplier_shipping.py +69 -0
  526. services/suppliers/main.py +60 -0
  527. services/suppliers/models/__init__.py +13 -0
  528. services/suppliers/models/supplier_capabilities.py +70 -0
  529. services/suppliers/models/supplier_certifications.py +64 -0
  530. services/suppliers/models/supplier_details.py +75 -0
  531. services/suppliers/models/supplier_financials.py +69 -0
  532. services/suppliers/models/supplier_inventory.py +76 -0
  533. services/suppliers/models/supplier_locations.py +70 -0
  534. services/suppliers/models/supplier_pricing.py +74 -0
  535. services/suppliers/models/supplier_quality.py +74 -0
  536. services/suppliers/models/supplier_shipping.py +76 -0
  537. services/suppliers/routers/__init__.py +13 -0
  538. services/suppliers/routers/supplier_capabilities.py +88 -0
  539. services/suppliers/routers/supplier_certifications.py +87 -0
  540. services/suppliers/routers/supplier_details.py +83 -0
  541. services/suppliers/routers/supplier_financials.py +83 -0
  542. services/suppliers/routers/supplier_inventory.py +105 -0
  543. services/suppliers/routers/supplier_locations.py +89 -0
  544. services/suppliers/routers/supplier_pricing.py +96 -0
  545. services/suppliers/routers/supplier_quality.py +96 -0
  546. services/suppliers/routers/supplier_shipping.py +96 -0
  547. services/supply_allocation/main.py +46 -0
  548. services/supply_allocation/routers/__init__.py +1 -0
  549. services/supply_allocation/routers/allocation.py +20 -0
  550. services/taxonomy/helpers/__init__.py +7 -0
  551. services/taxonomy/helpers/classes.py +48 -0
  552. services/taxonomy/helpers/family.py +53 -0
  553. services/taxonomy/helpers/subclass.py +58 -0
  554. services/taxonomy/main.py +48 -0
  555. services/taxonomy/models/__init__.py +7 -0
  556. services/taxonomy/models/classes.py +52 -0
  557. services/taxonomy/models/family.py +60 -0
  558. services/taxonomy/models/subclass.py +50 -0
  559. services/taxonomy/routers/__init__.py +7 -0
  560. services/taxonomy/routers/classes.py +78 -0
  561. services/taxonomy/routers/family.py +77 -0
  562. services/taxonomy/routers/subclass.py +82 -0
  563. services/warehouse_execution/__init__.py +1 -0
  564. services/warehouse_execution/main.py +46 -0
  565. services/warehouse_execution/routers/__init__.py +1 -0
  566. services/warehouse_execution/routers/execution.py +21 -0
  567. services/work_order_agent/__init__.py +17 -0
  568. services/work_order_agent/agent/__init__.py +17 -0
  569. services/work_order_agent/agent/work_order_agent.py +658 -0
  570. services/work_order_agent/tracking/__init__.py +101 -0
  571. services/work_order_agent/tracking/event_system.py +182 -0
  572. services/work_order_agent/tracking/state_machine.py +163 -0
  573. services/work_order_agent/tracking/state_machine_integrator.py +295 -0
  574. services/work_order_agent/tracking/test_phase2_implementation.py +302 -0
  575. services/work_order_agent/tracking/time_analysis.py +301 -0
  576. services/work_order_agent/tracking/tracked_work_order.py +255 -0
  577. services/work_order_agent/tracking/work_order_adapter.py +367 -0
  578. services/work_order_agent/tracking/work_order_batch_manager.py +406 -0
  579. services/work_order_agent/tracking/work_order_repository.py +431 -0
  580. services/workorders/helpers/__init__.py +5 -0
  581. services/workorders/helpers/area_room_usage_ledger.py +139 -0
  582. services/workorders/helpers/batch_execution_records.py +265 -0
  583. services/workorders/helpers/batch_release_workflows.py +158 -0
  584. services/workorders/helpers/batch_step_executions.py +145 -0
  585. services/workorders/helpers/equipment_usage_ledger.py +209 -0
  586. services/workorders/helpers/executed_bmr_records.py +170 -0
  587. services/workorders/helpers/executed_bpr_records.py +170 -0
  588. services/workorders/helpers/executed_instruction_evidence.py +155 -0
  589. services/workorders/helpers/ipc_result_records.py +134 -0
  590. services/workorders/helpers/production_batches.py +117 -0
  591. services/workorders/helpers/work_orders.py +367 -0
  592. services/workorders/helpers/yield_reconciliation_records.py +158 -0
  593. services/workorders/main.py +110 -0
  594. services/workorders/models/__init__.py +5 -0
  595. services/workorders/models/area_room_usage_ledger.py +154 -0
  596. services/workorders/models/batch_execution_records.py +575 -0
  597. services/workorders/models/batch_release_workflows.py +190 -0
  598. services/workorders/models/batch_step_executions.py +142 -0
  599. services/workorders/models/equipment_usage_ledger.py +144 -0
  600. services/workorders/models/executed_bmr_records.py +220 -0
  601. services/workorders/models/executed_bpr_records.py +220 -0
  602. services/workorders/models/executed_instruction_evidence.py +128 -0
  603. services/workorders/models/ipc_result_records.py +164 -0
  604. services/workorders/models/production_batches.py +181 -0
  605. services/workorders/models/work_orders.py +255 -0
  606. services/workorders/models/yield_reconciliation_records.py +175 -0
  607. services/workorders/routers/__init__.py +5 -0
  608. services/workorders/routers/area_room_usage_ledger.py +117 -0
  609. services/workorders/routers/batch_execution_records.py +103 -0
  610. services/workorders/routers/batch_release_workflows.py +86 -0
  611. services/workorders/routers/batch_step_executions.py +88 -0
  612. services/workorders/routers/equipment_usage_ledger.py +115 -0
  613. services/workorders/routers/executed_bmr_records.py +86 -0
  614. services/workorders/routers/executed_bpr_records.py +86 -0
  615. services/workorders/routers/executed_instruction_evidence.py +86 -0
  616. services/workorders/routers/ipc_result_records.py +86 -0
  617. services/workorders/routers/production_batches.py +86 -0
  618. services/workorders/routers/work_orders.py +257 -0
  619. services/workorders/routers/yield_reconciliation_records.py +86 -0
  620. src/broca/__init__.py +5 -0
  621. src/broca/agent.py +201 -0
  622. src/cerebellum/__init__.py +0 -0
  623. src/cerebellum/adapter.py +84 -0
  624. src/cerebellum/capabilities/__init__.py +0 -0
  625. src/cerebellum/capabilities/agent/__init__.py +0 -0
  626. src/cerebellum/capabilities/agent/agents.py +65 -0
  627. src/cerebellum/capabilities/ai/__init__.py +0 -0
  628. src/cerebellum/capabilities/ai/providers.py +106 -0
  629. src/cerebellum/capabilities/api/__init__.py +0 -0
  630. src/cerebellum/capabilities/api/graphql.py +35 -0
  631. src/cerebellum/capabilities/api/rest_api.py +45 -0
  632. src/cerebellum/capabilities/api/webhook.py +30 -0
  633. src/cerebellum/capabilities/browser/__init__.py +0 -0
  634. src/cerebellum/capabilities/browser/browsers.py +27 -0
  635. src/cerebellum/capabilities/cloud/__init__.py +0 -0
  636. src/cerebellum/capabilities/cloud/cloud.py +46 -0
  637. src/cerebellum/capabilities/communication/__init__.py +0 -0
  638. src/cerebellum/capabilities/communication/communication.py +62 -0
  639. src/cerebellum/capabilities/database/__init__.py +0 -0
  640. src/cerebellum/capabilities/database/elasticsearch.py +40 -0
  641. src/cerebellum/capabilities/database/influxdb.py +37 -0
  642. src/cerebellum/capabilities/database/mongodb.py +50 -0
  643. src/cerebellum/capabilities/database/neo4j.py +32 -0
  644. src/cerebellum/capabilities/database/redis.py +44 -0
  645. src/cerebellum/capabilities/enterprise/__init__.py +0 -0
  646. src/cerebellum/capabilities/enterprise/opensource.py +180 -0
  647. src/cerebellum/capabilities/enterprise/proprietary.py +313 -0
  648. src/cerebellum/capabilities/event_streaming/__init__.py +0 -0
  649. src/cerebellum/capabilities/event_streaming/streaming.py +38 -0
  650. src/cerebellum/capabilities/infrastructure/__init__.py +0 -0
  651. src/cerebellum/capabilities/infrastructure/infrastructure.py +30 -0
  652. src/cerebellum/capabilities/productivity/__init__.py +0 -0
  653. src/cerebellum/capabilities/productivity/productivity.py +158 -0
  654. src/cerebellum/capabilities/robotics/__init__.py +0 -0
  655. src/cerebellum/capabilities/robotics/robotics.py +124 -0
  656. src/cerebellum/capabilities/runtime/__init__.py +0 -0
  657. src/cerebellum/capabilities/runtime/runtimes.py +92 -0
  658. src/cerebellum/capabilities/search/__init__.py +0 -0
  659. src/cerebellum/capabilities/search/search.py +63 -0
  660. src/cerebellum/capabilities/source_control/__init__.py +0 -0
  661. src/cerebellum/capabilities/source_control/source_control.py +113 -0
  662. src/cerebellum/capabilities/storage/__init__.py +0 -0
  663. src/cerebellum/capabilities/storage/storage.py +94 -0
  664. src/cerebellum/capabilities/workflow/__init__.py +0 -0
  665. src/cerebellum/capabilities/workflow/workflows.py +49 -0
  666. src/cerebellum/capability.py +108 -0
  667. src/cerebellum/config.py +157 -0
  668. src/cerebellum/fallback.py +147 -0
  669. src/cerebellum/fallback_engine.py +121 -0
  670. src/cerebellum/key_manager.py +129 -0
  671. src/cerebellum/keystore.py +179 -0
  672. src/cerebellum/lifecycle.py +54 -0
  673. src/cerebellum/metadata.py +61 -0
  674. src/cerebellum/operator/base.py +25 -0
  675. src/cerebellum/peripheral.py +92 -0
  676. src/cerebellum/registry.py +98 -0
  677. src/cerebellum/resolve_entity_capability.py +259 -0
  678. src/cingulate/benchmark/__init__.py +23 -0
  679. src/cingulate/benchmark/reporter.py +102 -0
  680. src/cingulate/benchmark/runner.py +159 -0
  681. src/cingulate/benchmark/scenario_runner.py +150 -0
  682. src/cingulate/benchmark/validator.py +102 -0
  683. src/cingulate/governance/__init__.py +21 -0
  684. src/cingulate/governance/architecture_validator.py +194 -0
  685. src/cingulate/governance/compliance.py +104 -0
  686. src/cingulate/governance/governance.py +77 -0
  687. src/cingulate/governance/policy_registry.py +91 -0
  688. src/cortex/__init__.py +33 -0
  689. src/cortex/cost.py +71 -0
  690. src/cortex/counterfactual.py +162 -0
  691. src/cortex/digital_twin.py +90 -0
  692. src/cortex/experience.py +83 -0
  693. src/cortex/feedback.py +144 -0
  694. src/cortex/loss.py +116 -0
  695. src/cortex/prediction.py +142 -0
  696. src/cortex/replay.py +130 -0
  697. src/cortex/reward.py +113 -0
  698. src/cortex/simulator.py +102 -0
  699. src/cortex/world_model.py +180 -0
  700. src/cortex/world_model_simulation.py +1591 -0
  701. src/cortex/world_state.py +121 -0
  702. src/cortex/xavier.py +250 -0
  703. src/deepdive/__init__.py +29 -0
  704. src/deepdive/aggregation.py +113 -0
  705. src/deepdive/digital_twin_aggregator.py +128 -0
  706. src/deepdive/elasticsearch_adapter.py +110 -0
  707. src/deepdive/fleet_analytics.py +131 -0
  708. src/deepdive/knowledge_aggregator.py +130 -0
  709. src/homeostasis/__init__.py +19 -0
  710. src/homeostasis/control_plane.py +159 -0
  711. src/introspection/__init__.py +38 -0
  712. src/introspection/alerting.py +142 -0
  713. src/introspection/health.py +101 -0
  714. src/introspection/lemon.py +243 -0
  715. src/introspection/logging.py +147 -0
  716. src/introspection/metrics.py +106 -0
  717. src/introspection/tracing.py +162 -0
  718. src/monkey_brain/__init__.py +1 -0
  719. src/monkey_brain/api/main.py +148 -0
  720. src/monkey_brain/api/models.py +81 -0
  721. src/monkey_brain/api/routes/routes/keys.py +106 -0
  722. src/monkey_brain/api/routes/routes/run.py +169 -0
  723. src/monkey_brain/api/routes/routes/simulate.py +485 -0
  724. src/monkey_brain/dlm/__init__.py +44 -0
  725. src/monkey_brain/dlm/dlm.py +139 -0
  726. src/monkey_brain/dlm/gc.py +115 -0
  727. src/monkey_brain/dlm/lifecycle.py +149 -0
  728. src/monkey_brain/dlm/orphans.py +99 -0
  729. src/monkey_brain/dlm/storage.py +149 -0
  730. src/monkey_brain/dlm/ttl.py +140 -0
  731. src/monkey_brain/documents/__init__.py +0 -0
  732. src/monkey_brain/documents/document_ocr.py +6 -0
  733. src/monkey_brain/kernel/__init__.py +53 -0
  734. src/monkey_brain/kernel/capability_interface.py +144 -0
  735. src/monkey_brain/kernel/classifier/__init__.py +1 -0
  736. src/monkey_brain/kernel/classifier/embed_classifier.py +125 -0
  737. src/monkey_brain/kernel/classifier/intent_examples.py +106 -0
  738. src/monkey_brain/kernel/dag.py +23 -0
  739. src/monkey_brain/kernel/execution_state.py +257 -0
  740. src/monkey_brain/kernel/goal_planner.py +85 -0
  741. src/monkey_brain/kernel/goal_router.py +20 -0
  742. src/monkey_brain/kernel/goals/__init__.py +1 -0
  743. src/monkey_brain/kernel/goals/goal.py +130 -0
  744. src/monkey_brain/kernel/goals/goal_bootstrap.py +38 -0
  745. src/monkey_brain/kernel/goals/goal_classifier.py +132 -0
  746. src/monkey_brain/kernel/goals/goal_registry.py +75 -0
  747. src/monkey_brain/kernel/intents/__init__.py +1 -0
  748. src/monkey_brain/kernel/intents/event_adapter.py +246 -0
  749. src/monkey_brain/kernel/intents/helpers.py +13 -0
  750. src/monkey_brain/kernel/intents/intent_registry.py +705 -0
  751. src/monkey_brain/kernel/intents/intent_router.py +102 -0
  752. src/monkey_brain/kernel/intents/predicates/approval_create.py +9 -0
  753. src/monkey_brain/kernel/intents/predicates/approval_decision.py +9 -0
  754. src/monkey_brain/kernel/intents/predicates/approval_hold.py +9 -0
  755. src/monkey_brain/kernel/intents/predicates/approval_query.py +9 -0
  756. src/monkey_brain/kernel/intents/predicates/batch_close.py +9 -0
  757. src/monkey_brain/kernel/intents/predicates/batch_creation.py +9 -0
  758. src/monkey_brain/kernel/intents/predicates/batch_delete.py +9 -0
  759. src/monkey_brain/kernel/intents/predicates/batch_hold.py +9 -0
  760. src/monkey_brain/kernel/intents/predicates/batch_record.py +9 -0
  761. src/monkey_brain/kernel/intents/predicates/batch_update.py +9 -0
  762. src/monkey_brain/kernel/intents/predicates/change_control.py +49 -0
  763. src/monkey_brain/kernel/intents/predicates/compliance_audit.py +14 -0
  764. src/monkey_brain/kernel/intents/predicates/decision_intelligence.py +9 -0
  765. src/monkey_brain/kernel/intents/predicates/drug_research.py +9 -0
  766. src/monkey_brain/kernel/intents/predicates/fuzzy_match.py +19 -0
  767. src/monkey_brain/kernel/intents/predicates/production_kpi.py +9 -0
  768. src/monkey_brain/kernel/intents/predicates/sop_create.py +9 -0
  769. src/monkey_brain/kernel/intents/predicates/sop_query.py +9 -0
  770. src/monkey_brain/kernel/intents/predicates/sop_update.py +9 -0
  771. src/monkey_brain/kernel/intents/predicates/warehouse_shipping.py +9 -0
  772. src/monkey_brain/kernel/intents/predicates/work_order_create.py +9 -0
  773. src/monkey_brain/kernel/intents/predicates/work_order_delete.py +9 -0
  774. src/monkey_brain/kernel/intents/predicates/work_order_hold.py +9 -0
  775. src/monkey_brain/kernel/intents/predicates/work_order_query.py +9 -0
  776. src/monkey_brain/kernel/intents/predicates/work_order_status.py +9 -0
  777. src/monkey_brain/kernel/intents/predicates/work_order_update.py +9 -0
  778. src/monkey_brain/kernel/intents/predicates/worker.py +9 -0
  779. src/monkey_brain/kernel/intents/telemetry_adapter.py +274 -0
  780. src/monkey_brain/kernel/intents/utils.py +68 -0
  781. src/monkey_brain/kernel/learning.py +98 -0
  782. src/monkey_brain/kernel/llm_explorer.py +188 -0
  783. src/monkey_brain/kernel/loss.py +81 -0
  784. src/monkey_brain/kernel/nlp/__init__.py +1 -0
  785. src/monkey_brain/kernel/nlp/compat.py +23 -0
  786. src/monkey_brain/kernel/nlp/models.py +10 -0
  787. src/monkey_brain/kernel/nlp/question_analyzer.py +203 -0
  788. src/monkey_brain/kernel/nlp/spacy_parser.py +53 -0
  789. src/monkey_brain/kernel/observer.py +97 -0
  790. src/monkey_brain/kernel/parser/__init__.py +3 -0
  791. src/monkey_brain/kernel/parser/ast.py +28 -0
  792. src/monkey_brain/kernel/parser/extractors/__init__.py +11 -0
  793. src/monkey_brain/kernel/parser/extractors/entities.py +21 -0
  794. src/monkey_brain/kernel/parser/extractors/filters.py +16 -0
  795. src/monkey_brain/kernel/parser/extractors/projections.py +36 -0
  796. src/monkey_brain/kernel/parser/extractors/verbs.py +31 -0
  797. src/monkey_brain/kernel/parser/parser.py +57 -0
  798. src/monkey_brain/kernel/parser/rules.py +75 -0
  799. src/monkey_brain/kernel/pipeline.py +44 -0
  800. src/monkey_brain/kernel/planner.py +57 -0
  801. src/monkey_brain/kernel/rl/__init__.py +33 -0
  802. src/monkey_brain/kernel/rl/learner.py +98 -0
  803. src/monkey_brain/kernel/rl/policy.py +254 -0
  804. src/monkey_brain/kernel/rl/reward.py +117 -0
  805. src/monkey_brain/kernel/rl/transition.py +112 -0
  806. src/monkey_brain/persistence/__init__.py +47 -0
  807. src/monkey_brain/persistence/adapters.py +49 -0
  808. src/monkey_brain/persistence/events.py +105 -0
  809. src/monkey_brain/persistence/manager.py +124 -0
  810. src/monkey_brain/persistence/mongodb_adapter.py +91 -0
  811. src/monkey_brain/persistence/redis_adapter.py +93 -0
  812. src/monkey_brain/persistence/reducer.py +111 -0
  813. src/monkey_brain/runtime/__init__.py +49 -0
  814. src/monkey_brain/runtime/depedencies.py +8 -0
  815. src/monkey_brain/runtime/engine.py +183 -0
  816. src/monkey_brain/runtime/message_bus.py +82 -0
  817. src/monkey_brain/runtime/process.py +144 -0
  818. src/monkey_brain/runtime/resource_manager.py +100 -0
  819. src/monkey_brain/runtime/routers.py +8 -0
  820. src/monkey_brain/runtime/runtime.py +199 -0
  821. src/monkey_brain/runtime/scheduler.py +165 -0
  822. src/monkey_brain/runtime/supervisor.py +133 -0
  823. src/monkey_brain/runtime/worker_pool.py +111 -0
  824. src/plasticity/seed/__init__.py +30 -0
  825. src/plasticity/seed/benchmark_generator.py +105 -0
  826. src/plasticity/seed/event_generator.py +122 -0
  827. src/plasticity/seed/scenario_builder.py +134 -0
  828. src/plasticity/seed/seed_data.py +206 -0
  829. src/plasticity/seed/seeder.py +122 -0
  830. src/plasticity/testing/__init__.py +28 -0
  831. src/plasticity/testing/performance.py +131 -0
  832. src/plasticity/testing/profiler.py +255 -0
  833. src/plasticity/testing/reporter.py +84 -0
  834. src/plasticity/testing/runner.py +209 -0
  835. src/sync/__init__.py +12 -0
  836. src/sync/cloud_aggregator.py +63 -0
  837. src/sync/edge_node.py +51 -0
  838. src/sync/sync_manager.py +74 -0
@@ -0,0 +1,9 @@
1
+ """procurement service models package."""
2
+
3
+ __all__ = [
4
+ "goods_receipts",
5
+ "purchase_order_shipping_information",
6
+ "purchase_orders",
7
+ "quality_control",
8
+ "sampling",
9
+ ]
@@ -0,0 +1,165 @@
1
+ from datetime import datetime, timezone
2
+ from decimal import Decimal
3
+ from enum import Enum
4
+ from typing import Any, Optional
5
+ from uuid import UUID, uuid4
6
+
7
+ from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
8
+
9
+ from services.procurement.models.purchase_orders import PurchaseOrder
10
+ from services.products.models.product_common import UnitOfMeasure
11
+
12
+
13
+ class GoodsReceiptStatus(str, Enum):
14
+ DRAFT = "Draft"
15
+ SUBMITTED = "Submitted"
16
+ QC_HOLD = "QC Hold"
17
+ RELEASED = "Released"
18
+ REJECTED = "Rejected"
19
+ PARTIAL = "Partial"
20
+
21
+
22
+ class Attachment(BaseModel):
23
+ attachment_id: UUID = Field(default_factory=uuid4)
24
+ file_name: str
25
+ file_url: str | None = None
26
+ content_type: str | None = None
27
+ uploaded_by: str | None = None
28
+ uploaded_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
29
+
30
+
31
+ class AuditInfo(BaseModel):
32
+ created_by: str | None = None
33
+ updated_by: str | None = None
34
+ created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
35
+ updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
36
+
37
+
38
+ class ReceivedLineItem(BaseModel):
39
+ """One line of a Goods Receipt, linked to a PO line."""
40
+
41
+ gr_line_id: str = Field(default_factory=lambda: str(uuid4()))
42
+ po_line_id: str
43
+ material_code: str
44
+ received_qty: Decimal
45
+ unit_of_measure: UnitOfMeasure
46
+ batch_lot_number: Optional[str] = None
47
+ expiry_date: Optional[datetime] = None
48
+ manufacture_date: Optional[datetime] = None
49
+ storage_location: Optional[str] = None
50
+ pallet_ids: list[str] = Field(default_factory=list)
51
+ barcode_scanned: Optional[str] = None
52
+ qty_discrepancy: Optional[Decimal] = None
53
+ damage_noted: bool = False
54
+ damage_photos: list[Attachment] = Field(default_factory=list)
55
+ notes: Optional[str] = None
56
+
57
+
58
+ class GoodsReceipt(BaseModel):
59
+ """
60
+ Inbound goods receipt transaction.
61
+ Created when physical goods arrive at the facility.
62
+ """
63
+
64
+ gr_number: str
65
+ gr_id: str = Field(default_factory=lambda: str(uuid4()))
66
+ po: PurchaseOrder
67
+ delivery_note_no: Optional[str] = None
68
+ carrier_id: Optional[str] = None
69
+ vehicle_id: Optional[str] = None
70
+ received_by: str
71
+ received_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
72
+ dock_location: Optional[str] = None
73
+ status: GoodsReceiptStatus = GoodsReceiptStatus.DRAFT
74
+ lines: list[ReceivedLineItem]
75
+ quarantine_label_printed: bool = False
76
+ qc_notification_sent: bool = False
77
+ attachments: list[Attachment] = Field(default_factory=list)
78
+ audit: AuditInfo = Field(default_factory=AuditInfo)
79
+ metadata: dict[str, Any] | None = None
80
+
81
+ @field_validator("lines")
82
+ @classmethod
83
+ def at_least_one_line(cls, value: list) -> list:
84
+ if not value:
85
+ raise ValueError("A Goods Receipt must have at least one line item.")
86
+ return value
87
+
88
+
89
+ class GoodsReceiptCreate(GoodsReceipt):
90
+ """Schema for creating goods receipts."""
91
+
92
+
93
+ class GoodsReceiptUpdate(BaseModel):
94
+ delivery_note_no: Optional[str] = None
95
+ carrier_id: Optional[str] = None
96
+ vehicle_id: Optional[str] = None
97
+ received_by: Optional[str] = None
98
+ received_at: Optional[datetime] = None
99
+ dock_location: Optional[str] = None
100
+ status: Optional[GoodsReceiptStatus] = None
101
+ lines: Optional[list[ReceivedLineItem]] = None
102
+ quarantine_label_printed: Optional[bool] = None
103
+ qc_notification_sent: Optional[bool] = None
104
+ attachments: Optional[list[Attachment]] = None
105
+ audit: Optional[AuditInfo] = None
106
+ metadata: dict[str, Any] | None = None
107
+
108
+
109
+ class GoodsReceiptResponse(GoodsReceipt):
110
+ model_config = ConfigDict(from_attributes=True)
111
+
112
+
113
+ class PaginatedGoodsReceiptResponse(BaseModel):
114
+ total: int
115
+ page: int
116
+ page_size: int
117
+ results: list[GoodsReceiptResponse]
118
+
119
+
120
+ class QuarantineHold(BaseModel):
121
+ """Quarantine record placed automatically on GR, lifted after QC clearance."""
122
+
123
+ hold_id: UUID = Field(default_factory=uuid4)
124
+ gr_id: UUID
125
+ material_code: str
126
+ batch_lot_no: str
127
+ qty_on_hold: Decimal
128
+ uom: UnitOfMeasure
129
+ hold_location: str
130
+ held_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
131
+ released_at: Optional[datetime] = None
132
+ released_by: Optional[str] = None
133
+ release_reason: Optional[str] = None
134
+ is_active: bool = True
135
+
136
+ @model_validator(mode="after")
137
+ def deactivate_when_released(self):
138
+ if self.released_at is not None:
139
+ self.is_active = False
140
+ return self
141
+
142
+
143
+ class QuarantineHoldCreate(QuarantineHold):
144
+ """Schema for creating quarantine holds."""
145
+
146
+
147
+ class QuarantineHoldUpdate(BaseModel):
148
+ qty_on_hold: Optional[Decimal] = None
149
+ uom: Optional[UnitOfMeasure] = None
150
+ hold_location: Optional[str] = None
151
+ released_at: Optional[datetime] = None
152
+ released_by: Optional[str] = None
153
+ release_reason: Optional[str] = None
154
+ is_active: Optional[bool] = None
155
+
156
+
157
+ class QuarantineHoldResponse(QuarantineHold):
158
+ model_config = ConfigDict(from_attributes=True)
159
+
160
+
161
+ class PaginatedQuarantineHoldResponse(BaseModel):
162
+ total: int
163
+ page: int
164
+ page_size: int
165
+ results: list[QuarantineHoldResponse]
@@ -0,0 +1,54 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+ class PurchaseOrder(BaseModel):
7
+ po_number: str = Field(..., description="Unique identifier for the purchase order.")
8
+ po_date: str = Field(..., description="The date when the purchase order was created.")
9
+ supplier_id: str = Field(..., description="Unique identifier for the supplier associated with the PO.")
10
+ supplier_name: str = Field(..., description="Name of the supplier.")
11
+ buyer_id: str = Field(..., description="Unique identifier for the buyer organization.")
12
+ buyer_name: str = Field(..., description="Name of the buyer organization.")
13
+ total_amount: float = Field(..., description="The total monetary value of the purchase order.")
14
+ currency: str = Field(..., description="Currency in which the transaction is conducted.")
15
+ payment_terms: str = Field(..., description="Terms of payment agreed upon with the supplier.")
16
+ delivery_date: str = Field(..., description="The expected delivery date for the items in the order.")
17
+ shipping_address: str = Field(..., description="The address where the items should be delivered.")
18
+ billing_address: str = Field(..., description="The address where the invoice will be sent.")
19
+ status: str = Field(..., description="The current status of the PO, for example Open, Approved, or Closed.")
20
+ approval_date: Optional[str] = Field(None, description="The date when the PO was approved, null if not yet approved.")
21
+ remarks: Optional[str] = Field(None, description="Additional comments or notes about the purchase order.")
22
+
23
+
24
+ class PurchaseOrderCreate(PurchaseOrder):
25
+ pass
26
+
27
+
28
+ class PurchaseOrderUpdate(BaseModel):
29
+ po_date: Optional[str] = None
30
+ supplier_id: Optional[str] = None
31
+ supplier_name: Optional[str] = None
32
+ buyer_id: Optional[str] = None
33
+ buyer_name: Optional[str] = None
34
+ total_amount: Optional[float] = None
35
+ currency: Optional[str] = None
36
+ payment_terms: Optional[str] = None
37
+ delivery_date: Optional[str] = None
38
+ shipping_address: Optional[str] = None
39
+ billing_address: Optional[str] = None
40
+ status: Optional[str] = None
41
+ approval_date: Optional[str] = None
42
+ remarks: Optional[str] = None
43
+
44
+
45
+ class PurchaseOrderResponse(PurchaseOrder):
46
+ class Config:
47
+ from_attributes = True
48
+
49
+
50
+ class PaginatedPurchaseOrderResponse(BaseModel):
51
+ total: int
52
+ page: int
53
+ page_size: int
54
+ results: list[PurchaseOrderResponse]
@@ -0,0 +1,464 @@
1
+ from datetime import datetime, timezone
2
+ from decimal import Decimal
3
+ from enum import Enum
4
+ from typing import Optional
5
+ from uuid import UUID, uuid4
6
+
7
+ from pydantic import BaseModel, ConfigDict, Field, computed_field, model_validator
8
+
9
+ from services.procurement.models.goods_receipts import Attachment, AuditInfo
10
+ from services.procurement.models.sampling import DocumentStatus
11
+ from services.products.models.product_common import UnitOfMeasure
12
+
13
+
14
+ class InspectionType(str, Enum):
15
+ INCOMING = "Incoming"
16
+ IN_PROCESS = "In-Process"
17
+ FINAL = "Final"
18
+ AUDIT = "Audit"
19
+
20
+
21
+ class TestResultType(str, Enum):
22
+ QUANTITATIVE = "Quantitative"
23
+ QUALITATIVE = "Qualitative"
24
+ VISUAL = "Visual"
25
+ DIMENSIONAL = "Dimensional"
26
+
27
+
28
+ class QCDisposition(str, Enum):
29
+ ACCEPT = "Accept"
30
+ REJECT = "Reject"
31
+ CONDITIONAL_ACCEPT = "Conditional Accept"
32
+ PENDING = "Pending"
33
+
34
+
35
+ class NCRStatus(str, Enum):
36
+ OPEN = "Open"
37
+ IN_REVIEW = "In Review"
38
+ PENDING_SUPPLIER_RESPONSE = "Pending Supplier Response"
39
+ CLOSED = "Closed"
40
+
41
+
42
+ class NCRDisposition(str, Enum):
43
+ RETURN_TO_SUPPLIER = "Return to Supplier"
44
+ REWORK = "Rework"
45
+ SCRAP = "Scrap"
46
+ USE_AS_IS = "Use As Is"
47
+ RE_INSPECT = "Re-inspect"
48
+
49
+
50
+ class DefectSeverity(str, Enum):
51
+ CRITICAL = "Critical"
52
+ MAJOR = "Major"
53
+ MINOR = "Minor"
54
+
55
+
56
+ class SpecificationLimit(BaseModel):
57
+ """Acceptance limits for a single test parameter."""
58
+
59
+ parameter_name: str
60
+ unit: Optional[str] = None
61
+ lower_spec_limit: Optional[Decimal] = None
62
+ upper_spec_limit: Optional[Decimal] = None
63
+ target: Optional[Decimal] = None
64
+ acceptable_values: list[str] = Field(
65
+ default_factory=list,
66
+ description="For qualitative/enumerated parameters, e.g. ['Green', 'Yellow']",
67
+ )
68
+
69
+
70
+ class MaterialSpecification(BaseModel):
71
+ """Version-controlled specification for a material / product."""
72
+
73
+ spec_id: UUID = Field(default_factory=uuid4)
74
+ spec_code: str
75
+ material_code: str
76
+ version: str
77
+ effective_date: datetime
78
+ approved_by: str
79
+ status: DocumentStatus = DocumentStatus.APPROVED
80
+ parameters: list[SpecificationLimit]
81
+ documents: list[Attachment] = Field(default_factory=list)
82
+ audit: AuditInfo = Field(default_factory=AuditInfo)
83
+
84
+
85
+ class MaterialSpecificationCreate(MaterialSpecification):
86
+ """Schema for creating material specifications."""
87
+
88
+
89
+ class MaterialSpecificationUpdate(BaseModel):
90
+ spec_code: Optional[str] = None
91
+ material_code: Optional[str] = None
92
+ version: Optional[str] = None
93
+ effective_date: Optional[datetime] = None
94
+ approved_by: Optional[str] = None
95
+ status: Optional[DocumentStatus] = None
96
+ parameters: Optional[list[SpecificationLimit]] = None
97
+ documents: Optional[list[Attachment]] = None
98
+ audit: Optional[AuditInfo] = None
99
+
100
+
101
+ class MaterialSpecificationResponse(MaterialSpecification):
102
+ model_config = ConfigDict(from_attributes=True)
103
+
104
+
105
+ class PaginatedMaterialSpecificationResponse(BaseModel):
106
+ total: int
107
+ page: int
108
+ page_size: int
109
+ results: list[MaterialSpecificationResponse]
110
+
111
+
112
+ class InspectionChecklistItem(BaseModel):
113
+ """Single test/check within an inspection checklist template."""
114
+
115
+ item_id: UUID = Field(default_factory=uuid4)
116
+ sequence: int
117
+ parameter_name: str
118
+ test_method: Optional[str] = None
119
+ result_type: TestResultType
120
+ spec_limit: Optional[SpecificationLimit] = None
121
+ mandatory: bool = True
122
+ instrument_required: Optional[str] = None
123
+
124
+
125
+ class InspectionChecklist(BaseModel):
126
+ """Template checklist assigned to a material type + inspection type."""
127
+
128
+ checklist_id: UUID = Field(default_factory=uuid4)
129
+ name: str
130
+ material_code: Optional[str] = None
131
+ inspection_type: InspectionType
132
+ version: str
133
+ items: list[InspectionChecklistItem]
134
+ approved_by: str
135
+ effective_from: datetime
136
+ status: DocumentStatus = DocumentStatus.APPROVED
137
+
138
+
139
+ class InspectionChecklistCreate(InspectionChecklist):
140
+ """Schema for creating inspection checklists."""
141
+
142
+
143
+ class InspectionChecklistUpdate(BaseModel):
144
+ name: Optional[str] = None
145
+ material_code: Optional[str] = None
146
+ inspection_type: Optional[InspectionType] = None
147
+ version: Optional[str] = None
148
+ items: Optional[list[InspectionChecklistItem]] = None
149
+ approved_by: Optional[str] = None
150
+ effective_from: Optional[datetime] = None
151
+ status: Optional[DocumentStatus] = None
152
+
153
+
154
+ class InspectionChecklistResponse(InspectionChecklist):
155
+ model_config = ConfigDict(from_attributes=True)
156
+
157
+
158
+ class PaginatedInspectionChecklistResponse(BaseModel):
159
+ total: int
160
+ page: int
161
+ page_size: int
162
+ results: list[InspectionChecklistResponse]
163
+
164
+
165
+ class TestResult(BaseModel):
166
+ """Result recorded for one checklist item during a QC inspection."""
167
+
168
+ result_id: UUID = Field(default_factory=uuid4)
169
+ checklist_item_id: UUID
170
+ parameter_name: str
171
+ result_type: TestResultType
172
+ numeric_value: Optional[Decimal] = None
173
+ unit: Optional[str] = None
174
+ lower_spec_limit: Optional[Decimal] = None
175
+ upper_spec_limit: Optional[Decimal] = None
176
+ text_value: Optional[str] = None
177
+ is_oos: bool = False
178
+ instrument_id: Optional[str] = None
179
+ calibration_due: Optional[datetime] = None
180
+ notes: Optional[str] = None
181
+
182
+ @model_validator(mode="after")
183
+ def flag_oos(self) -> "TestResult":
184
+ if self.numeric_value is not None:
185
+ lsl_breach = self.lower_spec_limit is not None and self.numeric_value < self.lower_spec_limit
186
+ usl_breach = self.upper_spec_limit is not None and self.numeric_value > self.upper_spec_limit
187
+ self.is_oos = lsl_breach or usl_breach
188
+ return self
189
+
190
+
191
+ class InspectionStatus(str, Enum):
192
+ SCHEDULED = "Scheduled"
193
+ IN_PROGRESS = "In Progress"
194
+ COMPLETED = "Completed"
195
+ RE_INSPECT = "Re-Inspection Required"
196
+
197
+
198
+ class QCInspection(BaseModel):
199
+ """A complete QC inspection event for a received lot / sample."""
200
+
201
+ inspection_id: UUID = Field(default_factory=uuid4)
202
+ inspection_code: str
203
+ inspection_type: InspectionType
204
+ gr_id: UUID
205
+ sample_id: Optional[UUID] = None
206
+ material_code: str
207
+ batch_lot_number: Optional[str] = None
208
+ spec_id: UUID
209
+ checklist_id: UUID
210
+ inspector_id: str
211
+ inspector_name: str
212
+ inspected_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
213
+ completed_at: Optional[datetime] = None
214
+ status: InspectionStatus = InspectionStatus.IN_PROGRESS
215
+ results: list[TestResult] = Field(default_factory=list)
216
+ oos_count: int = 0
217
+ disposition: QCDisposition = QCDisposition.PENDING
218
+ disposition_reason: Optional[str] = None
219
+ disposition_by: Optional[str] = None
220
+ disposition_at: Optional[datetime] = None
221
+ digital_signature: Optional[str] = Field(
222
+ default=None,
223
+ description="21 CFR Part 11 compliant e-signature token",
224
+ )
225
+ supporting_docs: list[Attachment] = Field(default_factory=list)
226
+ notes: Optional[str] = None
227
+ audit: AuditInfo = Field(default_factory=AuditInfo)
228
+
229
+ @model_validator(mode="after")
230
+ def compute_oos_count(self) -> "QCInspection":
231
+ self.oos_count = sum(1 for result in self.results if result.is_oos)
232
+ return self
233
+
234
+ def finalize_disposition(
235
+ self,
236
+ disposition: QCDisposition,
237
+ by: str,
238
+ reason: Optional[str] = None,
239
+ ) -> None:
240
+ now = datetime.now(timezone.utc)
241
+ self.disposition = disposition
242
+ self.disposition_by = by
243
+ self.disposition_at = now
244
+ self.disposition_reason = reason
245
+ self.status = InspectionStatus.COMPLETED
246
+ self.completed_at = now
247
+
248
+
249
+ class QCInspectionCreate(QCInspection):
250
+ """Schema for creating QC inspections."""
251
+
252
+
253
+ class QCInspectionUpdate(BaseModel):
254
+ inspection_code: Optional[str] = None
255
+ inspection_type: Optional[InspectionType] = None
256
+ sample_id: Optional[UUID] = None
257
+ material_code: Optional[str] = None
258
+ batch_lot_number: Optional[str] = None
259
+ spec_id: Optional[UUID] = None
260
+ checklist_id: Optional[UUID] = None
261
+ inspector_id: Optional[str] = None
262
+ inspector_name: Optional[str] = None
263
+ inspected_at: Optional[datetime] = None
264
+ completed_at: Optional[datetime] = None
265
+ status: Optional[InspectionStatus] = None
266
+ results: Optional[list[TestResult]] = None
267
+ disposition: Optional[QCDisposition] = None
268
+ disposition_reason: Optional[str] = None
269
+ disposition_by: Optional[str] = None
270
+ disposition_at: Optional[datetime] = None
271
+ digital_signature: Optional[str] = None
272
+ supporting_docs: Optional[list[Attachment]] = None
273
+ notes: Optional[str] = None
274
+ audit: Optional[AuditInfo] = None
275
+
276
+
277
+ class QCInspectionResponse(QCInspection):
278
+ model_config = ConfigDict(from_attributes=True)
279
+
280
+
281
+ class PaginatedQCInspectionResponse(BaseModel):
282
+ total: int
283
+ page: int
284
+ page_size: int
285
+ results: list[QCInspectionResponse]
286
+
287
+
288
+ class ReInspectionRecord(BaseModel):
289
+ """Links a follow-up inspection to the original."""
290
+
291
+ reinspection_id: UUID = Field(default_factory=uuid4)
292
+ original_inspection_id: UUID
293
+ new_inspection_id: UUID
294
+ reason: str
295
+ authorised_by: str
296
+ created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
297
+
298
+
299
+ class ReInspectionRecordCreate(ReInspectionRecord):
300
+ """Schema for creating re-inspection links."""
301
+
302
+
303
+ class ReInspectionRecordUpdate(BaseModel):
304
+ new_inspection_id: Optional[UUID] = None
305
+ reason: Optional[str] = None
306
+ authorised_by: Optional[str] = None
307
+
308
+
309
+ class ReInspectionRecordResponse(ReInspectionRecord):
310
+ model_config = ConfigDict(from_attributes=True)
311
+
312
+
313
+ class PaginatedReInspectionRecordResponse(BaseModel):
314
+ total: int
315
+ page: int
316
+ page_size: int
317
+ results: list[ReInspectionRecordResponse]
318
+
319
+
320
+ class DefectClassification(str, Enum):
321
+ CRITICAL = "Critical"
322
+ MAJOR = "Major"
323
+ MINOR = "Minor"
324
+
325
+
326
+ class RootCauseCategory(str, Enum):
327
+ SUPPLIER_PROCESS = "Supplier Process"
328
+ TRANSPORT_DAMAGE = "Transport / Damage"
329
+ STORAGE = "Storage Condition"
330
+ DOCUMENTATION = "Documentation Error"
331
+ MEASUREMENT = "Measurement / Instrument"
332
+ SPECIFICATION = "Specification Error"
333
+ UNKNOWN = "Unknown"
334
+
335
+
336
+ class CAPARecord(BaseModel):
337
+ """Corrective Action / Preventive Action record linked to an NCR."""
338
+
339
+ capa_id: UUID = Field(default_factory=uuid4)
340
+ ncr_id: UUID
341
+ capa_type: str
342
+ description: str
343
+ assigned_to: str
344
+ due_date: datetime
345
+ completed_at: Optional[datetime] = None
346
+ effectiveness_verified: bool = False
347
+ verified_by: Optional[str] = None
348
+ notes: Optional[str] = None
349
+ audit: AuditInfo = Field(default_factory=AuditInfo)
350
+
351
+
352
+ class SupplierDebitNote(BaseModel):
353
+ """Formal debit note issued to supplier for attributable non-conformance."""
354
+
355
+ debit_note_id: UUID = Field(default_factory=uuid4)
356
+ ncr_id: UUID
357
+ supplier_id: str
358
+ amount: Decimal
359
+ currency: str = Field(max_length=3)
360
+ reason: str
361
+ issued_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
362
+ issued_by: str
363
+ acknowledged_by_supplier: bool = False
364
+ acknowledged_at: Optional[datetime] = None
365
+ notes: Optional[str] = None
366
+
367
+
368
+ class NonConformanceReport(BaseModel):
369
+ """
370
+ NCR: raised automatically on OOS / Reject disposition,
371
+ or manually by authorised QA personnel.
372
+ """
373
+
374
+ ncr_id: UUID = Field(default_factory=uuid4)
375
+ ncr_number: str
376
+ inspection_id: Optional[UUID] = None
377
+ gr_id: UUID
378
+ material_code: str
379
+ batch_lot_number: Optional[str] = None
380
+ supplier_id: str
381
+ defect_description: str
382
+ defect_classification: DefectClassification
383
+ root_cause_category: RootCauseCategory = RootCauseCategory.UNKNOWN
384
+ qty_affected: Decimal
385
+ uom: UnitOfMeasure
386
+ financial_value: Optional[Decimal] = None
387
+ currency: Optional[str] = Field(default=None, max_length=3)
388
+ status: NCRStatus = NCRStatus.OPEN
389
+ disposition: Optional[NCRDisposition] = None
390
+ disposition_approver: Optional[str] = None
391
+ disposition_approved_at: Optional[datetime] = None
392
+ opened_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
393
+ assigned_to: Optional[str] = None
394
+ escalated_to: Optional[str] = None
395
+ escalated_at: Optional[datetime] = None
396
+ supplier_notified_at: Optional[datetime] = None
397
+ closed_at: Optional[datetime] = None
398
+ closed_by: Optional[str] = None
399
+ capas: list[CAPARecord] = Field(default_factory=list)
400
+ debit_notes: list[SupplierDebitNote] = Field(default_factory=list)
401
+ attachments: list[Attachment] = Field(default_factory=list)
402
+ notes: Optional[str] = None
403
+ audit: AuditInfo = Field(default_factory=AuditInfo)
404
+
405
+ @computed_field
406
+ @property
407
+ def age_days(self) -> Optional[float]:
408
+ """Days the NCR has been open."""
409
+ end = self.closed_at or datetime.now(timezone.utc)
410
+ opened = self.opened_at
411
+ if opened.tzinfo is None:
412
+ opened = opened.replace(tzinfo=timezone.utc)
413
+ return (end - opened).total_seconds() / 86400
414
+
415
+ def close(self, closed_by: str, notes: Optional[str] = None) -> None:
416
+ self.status = NCRStatus.CLOSED
417
+ self.closed_by = closed_by
418
+ self.closed_at = datetime.now(timezone.utc)
419
+ if notes:
420
+ self.notes = (self.notes or "") + f"\n[CLOSE] {notes}"
421
+
422
+
423
+ class NonConformanceReportCreate(NonConformanceReport):
424
+ """Schema for creating NCRs."""
425
+
426
+
427
+ class NonConformanceReportUpdate(BaseModel):
428
+ inspection_id: Optional[UUID] = None
429
+ material_code: Optional[str] = None
430
+ batch_lot_number: Optional[str] = None
431
+ supplier_id: Optional[str] = None
432
+ defect_description: Optional[str] = None
433
+ defect_classification: Optional[DefectClassification] = None
434
+ root_cause_category: Optional[RootCauseCategory] = None
435
+ qty_affected: Optional[Decimal] = None
436
+ uom: Optional[UnitOfMeasure] = None
437
+ financial_value: Optional[Decimal] = None
438
+ currency: Optional[str] = Field(default=None, max_length=3)
439
+ status: Optional[NCRStatus] = None
440
+ disposition: Optional[NCRDisposition] = None
441
+ disposition_approver: Optional[str] = None
442
+ disposition_approved_at: Optional[datetime] = None
443
+ assigned_to: Optional[str] = None
444
+ escalated_to: Optional[str] = None
445
+ escalated_at: Optional[datetime] = None
446
+ supplier_notified_at: Optional[datetime] = None
447
+ closed_at: Optional[datetime] = None
448
+ closed_by: Optional[str] = None
449
+ capas: Optional[list[CAPARecord]] = None
450
+ debit_notes: Optional[list[SupplierDebitNote]] = None
451
+ attachments: Optional[list[Attachment]] = None
452
+ notes: Optional[str] = None
453
+ audit: Optional[AuditInfo] = None
454
+
455
+
456
+ class NonConformanceReportResponse(NonConformanceReport):
457
+ model_config = ConfigDict(from_attributes=True)
458
+
459
+
460
+ class PaginatedNonConformanceReportResponse(BaseModel):
461
+ total: int
462
+ page: int
463
+ page_size: int
464
+ results: list[NonConformanceReportResponse]