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,235 @@
1
+ from datetime import date, datetime, timezone
2
+ from decimal import Decimal
3
+ from typing import Optional
4
+ from uuid import UUID
5
+
6
+ from motor.motor_asyncio import AsyncIOMotorDatabase
7
+ from pymongo import ReturnDocument
8
+
9
+ from services.procurement.models.quality_control import (
10
+ InspectionChecklistCreate,
11
+ InspectionChecklistUpdate,
12
+ MaterialSpecificationCreate,
13
+ MaterialSpecificationUpdate,
14
+ NonConformanceReportCreate,
15
+ NonConformanceReportUpdate,
16
+ QCInspectionCreate,
17
+ QCInspectionUpdate,
18
+ ReInspectionRecordCreate,
19
+ ReInspectionRecordUpdate,
20
+ )
21
+
22
+ MATERIAL_SPECS_COLLECTION = "material_specifications"
23
+ INSPECTION_CHECKLISTS_COLLECTION = "inspection_checklists"
24
+ QC_INSPECTIONS_COLLECTION = "qc_inspections"
25
+ REINSPECTIONS_COLLECTION = "reinspection_records"
26
+ NCR_COLLECTION = "non_conformance_reports"
27
+
28
+
29
+ def _serialize(doc: Optional[dict]) -> Optional[dict]:
30
+ if not doc:
31
+ return None
32
+ doc = dict(doc)
33
+ doc.pop("_id", None)
34
+ return doc
35
+
36
+
37
+ def _prepare(value):
38
+ if isinstance(value, UUID):
39
+ return str(value)
40
+ if isinstance(value, Decimal):
41
+ return float(value)
42
+ if isinstance(value, datetime):
43
+ if value.tzinfo is None:
44
+ return value.replace(tzinfo=timezone.utc)
45
+ return value.astimezone(timezone.utc)
46
+ if isinstance(value, date):
47
+ return datetime(value.year, value.month, value.day, tzinfo=timezone.utc)
48
+ if isinstance(value, dict):
49
+ return {key: _prepare(item) for key, item in value.items()}
50
+ if isinstance(value, list):
51
+ return [_prepare(item) for item in value]
52
+ return value
53
+
54
+
55
+ async def _get_all(db: AsyncIOMotorDatabase, collection: str, page: int, page_size: int):
56
+ query: dict = {}
57
+ total = await db[collection].count_documents(query)
58
+ cursor = db[collection].find(query).skip((page - 1) * page_size).limit(page_size)
59
+ return [_serialize(doc) async for doc in cursor], total
60
+
61
+
62
+ async def _get_by_id(db: AsyncIOMotorDatabase, collection: str, id_field: str, value: str):
63
+ return _serialize(await db[collection].find_one({id_field: value}))
64
+
65
+
66
+ async def _get_many(db: AsyncIOMotorDatabase, collection: str, query: dict):
67
+ cursor = db[collection].find(query)
68
+ return [_serialize(doc) async for doc in cursor]
69
+
70
+
71
+ async def _create(db: AsyncIOMotorDatabase, collection: str, data) -> dict:
72
+ doc = _prepare(data.model_dump())
73
+ await db[collection].insert_one(doc)
74
+ return _serialize(doc)
75
+
76
+
77
+ async def _update(db: AsyncIOMotorDatabase, collection: str, id_field: str, value: str, data):
78
+ fields = _prepare(data.model_dump(exclude_unset=True))
79
+ if not fields:
80
+ return await _get_by_id(db, collection, id_field, value)
81
+ result = await db[collection].find_one_and_update(
82
+ {id_field: value},
83
+ {"$set": fields},
84
+ return_document=ReturnDocument.AFTER,
85
+ )
86
+ return _serialize(result)
87
+
88
+
89
+ async def _delete(db: AsyncIOMotorDatabase, collection: str, id_field: str, value: str) -> bool:
90
+ result = await db[collection].delete_one({id_field: value})
91
+ return result.deleted_count == 1
92
+
93
+
94
+ async def get_all_material_specs(db, page=1, page_size=20):
95
+ return await _get_all(db, MATERIAL_SPECS_COLLECTION, page, page_size)
96
+
97
+
98
+ async def get_material_spec_by_id(db, spec_id: str):
99
+ return await _get_by_id(db, MATERIAL_SPECS_COLLECTION, "spec_id", spec_id)
100
+
101
+
102
+ async def get_material_spec_by_code(db, spec_code: str):
103
+ return await _get_by_id(db, MATERIAL_SPECS_COLLECTION, "spec_code", spec_code)
104
+
105
+
106
+ async def get_material_specs_by_material(db, material_code: str):
107
+ return await _get_many(db, MATERIAL_SPECS_COLLECTION, {"material_code": material_code})
108
+
109
+
110
+ async def create_material_spec(db, data: MaterialSpecificationCreate):
111
+ return await _create(db, MATERIAL_SPECS_COLLECTION, data)
112
+
113
+
114
+ async def update_material_spec(db, spec_id: str, data: MaterialSpecificationUpdate):
115
+ return await _update(db, MATERIAL_SPECS_COLLECTION, "spec_id", spec_id, data)
116
+
117
+
118
+ async def delete_material_spec(db, spec_id: str):
119
+ return await _delete(db, MATERIAL_SPECS_COLLECTION, "spec_id", spec_id)
120
+
121
+
122
+ async def get_all_inspection_checklists(db, page=1, page_size=20):
123
+ return await _get_all(db, INSPECTION_CHECKLISTS_COLLECTION, page, page_size)
124
+
125
+
126
+ async def get_inspection_checklist_by_id(db, checklist_id: str):
127
+ return await _get_by_id(db, INSPECTION_CHECKLISTS_COLLECTION, "checklist_id", checklist_id)
128
+
129
+
130
+ async def get_inspection_checklists_by_material(db, material_code: str):
131
+ return await _get_many(db, INSPECTION_CHECKLISTS_COLLECTION, {"material_code": material_code})
132
+
133
+
134
+ async def get_inspection_checklists_by_type(db, inspection_type: str):
135
+ return await _get_many(db, INSPECTION_CHECKLISTS_COLLECTION, {"inspection_type": inspection_type})
136
+
137
+
138
+ async def create_inspection_checklist(db, data: InspectionChecklistCreate):
139
+ return await _create(db, INSPECTION_CHECKLISTS_COLLECTION, data)
140
+
141
+
142
+ async def update_inspection_checklist(db, checklist_id: str, data: InspectionChecklistUpdate):
143
+ return await _update(db, INSPECTION_CHECKLISTS_COLLECTION, "checklist_id", checklist_id, data)
144
+
145
+
146
+ async def delete_inspection_checklist(db, checklist_id: str):
147
+ return await _delete(db, INSPECTION_CHECKLISTS_COLLECTION, "checklist_id", checklist_id)
148
+
149
+
150
+ async def get_all_qc_inspections(db, page=1, page_size=20):
151
+ return await _get_all(db, QC_INSPECTIONS_COLLECTION, page, page_size)
152
+
153
+
154
+ async def get_qc_inspection_by_id(db, inspection_id: str):
155
+ return await _get_by_id(db, QC_INSPECTIONS_COLLECTION, "inspection_id", inspection_id)
156
+
157
+
158
+ async def get_qc_inspection_by_code(db, inspection_code: str):
159
+ return await _get_by_id(db, QC_INSPECTIONS_COLLECTION, "inspection_code", inspection_code)
160
+
161
+
162
+ async def get_qc_inspections_by_gr(db, gr_id: str):
163
+ return await _get_many(db, QC_INSPECTIONS_COLLECTION, {"gr_id": gr_id})
164
+
165
+
166
+ async def get_qc_inspections_by_status(db, status: str):
167
+ return await _get_many(db, QC_INSPECTIONS_COLLECTION, {"status": status})
168
+
169
+
170
+ async def create_qc_inspection(db, data: QCInspectionCreate):
171
+ return await _create(db, QC_INSPECTIONS_COLLECTION, data)
172
+
173
+
174
+ async def update_qc_inspection(db, inspection_id: str, data: QCInspectionUpdate):
175
+ return await _update(db, QC_INSPECTIONS_COLLECTION, "inspection_id", inspection_id, data)
176
+
177
+
178
+ async def delete_qc_inspection(db, inspection_id: str):
179
+ return await _delete(db, QC_INSPECTIONS_COLLECTION, "inspection_id", inspection_id)
180
+
181
+
182
+ async def get_all_reinspections(db, page=1, page_size=20):
183
+ return await _get_all(db, REINSPECTIONS_COLLECTION, page, page_size)
184
+
185
+
186
+ async def get_reinspection_by_id(db, reinspection_id: str):
187
+ return await _get_by_id(db, REINSPECTIONS_COLLECTION, "reinspection_id", reinspection_id)
188
+
189
+
190
+ async def get_reinspections_by_original(db, original_inspection_id: str):
191
+ return await _get_many(db, REINSPECTIONS_COLLECTION, {"original_inspection_id": original_inspection_id})
192
+
193
+
194
+ async def create_reinspection(db, data: ReInspectionRecordCreate):
195
+ return await _create(db, REINSPECTIONS_COLLECTION, data)
196
+
197
+
198
+ async def update_reinspection(db, reinspection_id: str, data: ReInspectionRecordUpdate):
199
+ return await _update(db, REINSPECTIONS_COLLECTION, "reinspection_id", reinspection_id, data)
200
+
201
+
202
+ async def delete_reinspection(db, reinspection_id: str):
203
+ return await _delete(db, REINSPECTIONS_COLLECTION, "reinspection_id", reinspection_id)
204
+
205
+
206
+ async def get_all_ncrs(db, page=1, page_size=20):
207
+ return await _get_all(db, NCR_COLLECTION, page, page_size)
208
+
209
+
210
+ async def get_ncr_by_id(db, ncr_id: str):
211
+ return await _get_by_id(db, NCR_COLLECTION, "ncr_id", ncr_id)
212
+
213
+
214
+ async def get_ncr_by_number(db, ncr_number: str):
215
+ return await _get_by_id(db, NCR_COLLECTION, "ncr_number", ncr_number)
216
+
217
+
218
+ async def get_ncrs_by_gr(db, gr_id: str):
219
+ return await _get_many(db, NCR_COLLECTION, {"gr_id": gr_id})
220
+
221
+
222
+ async def get_ncrs_by_status(db, status: str):
223
+ return await _get_many(db, NCR_COLLECTION, {"status": status})
224
+
225
+
226
+ async def create_ncr(db, data: NonConformanceReportCreate):
227
+ return await _create(db, NCR_COLLECTION, data)
228
+
229
+
230
+ async def update_ncr(db, ncr_id: str, data: NonConformanceReportUpdate):
231
+ return await _update(db, NCR_COLLECTION, "ncr_id", ncr_id, data)
232
+
233
+
234
+ async def delete_ncr(db, ncr_id: str):
235
+ return await _delete(db, NCR_COLLECTION, "ncr_id", ncr_id)
@@ -0,0 +1,404 @@
1
+ from datetime import date, datetime, timezone
2
+ from decimal import Decimal
3
+ from typing import Optional
4
+ from uuid import UUID
5
+
6
+ from motor.motor_asyncio import AsyncIOMotorDatabase
7
+ from pymongo import ReturnDocument
8
+
9
+ from services.procurement.models.sampling import (
10
+ ChainOfCustodyEntry,
11
+ ResamplingRecordCreate,
12
+ ResamplingRecordResponse,
13
+ ResamplingRecordUpdate,
14
+ SampleCreate,
15
+ SampleResponse,
16
+ SampleStatus,
17
+ SampleType,
18
+ SampleUpdate,
19
+ SamplingPlanCreate,
20
+ SamplingPlanResponse,
21
+ SamplingPlanUpdate,
22
+ utc_now,
23
+ )
24
+
25
+ SAMPLING_PLANS_COLLECTION = "sampling_plans"
26
+ SAMPLES_COLLECTION = "samples"
27
+ RESAMPLING_RECORDS_COLLECTION = "resampling_records"
28
+
29
+
30
+ def _serialize(doc: Optional[dict]) -> Optional[dict]:
31
+ if not doc:
32
+ return None
33
+ doc = dict(doc)
34
+ doc.pop("_id", None)
35
+ return doc
36
+
37
+
38
+ def _prepare(value):
39
+ if isinstance(value, UUID):
40
+ return str(value)
41
+ if isinstance(value, Decimal):
42
+ return float(value)
43
+ if isinstance(value, datetime):
44
+ if value.tzinfo is None:
45
+ return value.replace(tzinfo=timezone.utc)
46
+ return value.astimezone(timezone.utc)
47
+ if isinstance(value, date):
48
+ return datetime(value.year, value.month, value.day, tzinfo=timezone.utc)
49
+ if isinstance(value, dict):
50
+ return {key: _prepare(item) for key, item in value.items()}
51
+ if isinstance(value, list):
52
+ return [_prepare(item) for item in value]
53
+ return value
54
+
55
+
56
+ def _normalize_sampling_method(value: object) -> str:
57
+ if isinstance(value, str):
58
+ normalized = value.strip().lower().replace("_", " ").replace("-", " ")
59
+ aliases = {
60
+ "aql": "AQL Standard",
61
+ "aql standard": "AQL Standard",
62
+ "fixed": "Fixed Quantity",
63
+ "fixed quantity": "Fixed Quantity",
64
+ "percentage": "Percentage Based",
65
+ "percentage based": "Percentage Based",
66
+ "skip lot": "Skip Lot",
67
+ "zero defect": "Zero Defect",
68
+ }
69
+ if normalized in aliases:
70
+ return aliases[normalized]
71
+ return "AQL Standard"
72
+
73
+
74
+ def _normalize_risk(value: object) -> str:
75
+ if isinstance(value, str):
76
+ normalized = value.strip().lower()
77
+ aliases = {"high": "High", "medium": "Medium", "med": "Medium", "low": "Low"}
78
+ if normalized in aliases:
79
+ return aliases[normalized]
80
+ return "Medium"
81
+
82
+
83
+ def _normalize_aql(value: object) -> str:
84
+ if isinstance(value, str):
85
+ normalized = value.strip().upper()
86
+ aliases = {
87
+ "1": "I",
88
+ "I": "I",
89
+ "2": "II",
90
+ "II": "II",
91
+ "3": "III",
92
+ "III": "III",
93
+ "S1": "S-1",
94
+ "S-1": "S-1",
95
+ "S2": "S-2",
96
+ "S-2": "S-2",
97
+ "S3": "S-3",
98
+ "S-3": "S-3",
99
+ "S4": "S-4",
100
+ "S-4": "S-4",
101
+ }
102
+ if normalized in aliases:
103
+ return aliases[normalized]
104
+ return "II"
105
+
106
+
107
+ def _normalize_plan_version(value: object, plan_code: str, created_at: object = None) -> dict:
108
+ version = dict(value) if isinstance(value, dict) else {}
109
+ version.setdefault("version_number", str(version.get("version") or "1.0"))
110
+ version.setdefault("effective_date", created_at or utc_now())
111
+ version.setdefault("change_summary", f"Initial version for {plan_code}")
112
+ version.setdefault("approved_by", "QA Manager")
113
+ version.setdefault("status", "Approved")
114
+ return version
115
+
116
+
117
+ def _normalize_sample_type(value: object) -> str:
118
+ if isinstance(value, str):
119
+ normalized = value.strip().lower().replace("_", " ").replace("-", " ")
120
+ aliases = {
121
+ "retain": "Retain Sample",
122
+ "retain sample": "Retain Sample",
123
+ "lab": "Send-to-Lab Sample",
124
+ "send to lab": "Send-to-Lab Sample",
125
+ "send to lab sample": "Send-to-Lab Sample",
126
+ "in house": "In-House Test Sample",
127
+ "in house test sample": "In-House Test Sample",
128
+ }
129
+ if normalized in aliases:
130
+ return aliases[normalized]
131
+ return SampleType.IN_HOUSE.value
132
+
133
+
134
+ def _normalize_sample_status(value: object) -> str:
135
+ if isinstance(value, str):
136
+ normalized = value.strip().lower().replace("_", " ").replace("-", " ")
137
+ aliases = {
138
+ "pending": "Pending Collection",
139
+ "pending collection": "Pending Collection",
140
+ "collected": "Collected",
141
+ "in transit": "In Transit to Lab",
142
+ "in transit to lab": "In Transit to Lab",
143
+ "testing": "In Testing",
144
+ "in testing": "In Testing",
145
+ "results": "Results Received",
146
+ "results received": "Results Received",
147
+ "disposed": "Disposed",
148
+ }
149
+ if normalized in aliases:
150
+ return aliases[normalized]
151
+ return SampleStatus.PENDING.value
152
+
153
+
154
+ def _normalize_sampling_plan_record(doc: Optional[dict]) -> Optional[dict]:
155
+ if not doc:
156
+ return None
157
+
158
+ record = _serialize(doc)
159
+ plan_id = str(record.get("plan_id") or record.get("id") or record.get("plan_code") or "SAMPLING-PLAN")
160
+ plan_code = str(record.get("plan_code") or plan_id)
161
+ record["plan_id"] = plan_id
162
+ record["plan_code"] = plan_code
163
+ record.setdefault("name", record.get("description") or f"{plan_code} Sampling Plan")
164
+ record["risk_classification"] = _normalize_risk(record.get("risk_classification") or record.get("risk"))
165
+ record["sampling_method"] = _normalize_sampling_method(record.get("sampling_method") or record.get("method"))
166
+
167
+ if record["sampling_method"] == "AQL Standard":
168
+ record["aql_level"] = _normalize_aql(record.get("aql_level"))
169
+ elif record["sampling_method"] == "Fixed Quantity":
170
+ record["fixed_sample_qty"] = int(record.get("fixed_sample_qty") or record.get("sample_qty") or record.get("min_sample_qty") or 1)
171
+ elif record["sampling_method"] == "Percentage Based":
172
+ record["percentage"] = float(record.get("percentage") or 1)
173
+ elif record["sampling_method"] == "Skip Lot":
174
+ record["skip_lot_frequency"] = int(record.get("skip_lot_frequency") or 1)
175
+
176
+ record["current_version"] = _normalize_plan_version(
177
+ record.get("current_version"),
178
+ plan_code,
179
+ record.get("created_at"),
180
+ )
181
+ history = record.get("history")
182
+ record["history"] = history if isinstance(history, list) else []
183
+
184
+ return SamplingPlanResponse.model_validate(record).model_dump()
185
+
186
+
187
+ def _normalize_sample_record(doc: Optional[dict]) -> Optional[dict]:
188
+ if not doc:
189
+ return None
190
+
191
+ record = _serialize(doc)
192
+ sample_id = str(record.get("sample_id") or record.get("id") or record.get("sample_code") or "SAMPLE")
193
+ record["sample_id"] = sample_id
194
+ record["sample_code"] = str(record.get("sample_code") or sample_id)
195
+ record["gr_id"] = str(record["gr_id"]) if record.get("gr_id") is not None else None
196
+ record["gr_line_id"] = str(record["gr_line_id"]) if record.get("gr_line_id") is not None else None
197
+ record["sampling_plan_id"] = (
198
+ str(record["sampling_plan_id"]) if record.get("sampling_plan_id") is not None else None
199
+ )
200
+ record["sample_type"] = _normalize_sample_type(record.get("sample_type") or record.get("type"))
201
+ record["status"] = _normalize_sample_status(record.get("status"))
202
+ record["chain_of_custody"] = record.get("chain_of_custody") if isinstance(record.get("chain_of_custody"), list) else []
203
+ record["attachments"] = record.get("attachments") if isinstance(record.get("attachments"), list) else []
204
+ return SampleResponse.model_validate(record).model_dump()
205
+
206
+
207
+ def _normalize_resampling_record(doc: Optional[dict]) -> Optional[dict]:
208
+ if not doc:
209
+ return None
210
+
211
+ record = _serialize(doc)
212
+ resample_id = str(record.get("resample_id") or record.get("id") or "RESAMPLE")
213
+ record["resample_id"] = resample_id
214
+ record["original_sample_id"] = (
215
+ str(record["original_sample_id"]) if record.get("original_sample_id") is not None else None
216
+ )
217
+ record["new_sample_id"] = str(record["new_sample_id"]) if record.get("new_sample_id") is not None else None
218
+ record["reason_code"] = str(record.get("reason_code") or record.get("reason") or "Resampling")
219
+ record["reason_detail"] = str(record.get("reason_detail") or record.get("reason") or "Resampling requested")
220
+ record["requested_by"] = str(record.get("requested_by") or "System")
221
+ record["approved_by"] = str(record.get("approved_by") or "System")
222
+ record["approved_at"] = record.get("approved_at") or record.get("updated_at") or record.get("created_at") or utc_now()
223
+ return ResamplingRecordResponse.model_validate(record).model_dump()
224
+
225
+
226
+ async def get_all_sampling_plans(
227
+ db: AsyncIOMotorDatabase,
228
+ page: int = 1,
229
+ page_size: int = 20,
230
+ ) -> tuple[list[dict], int]:
231
+ query: dict = {}
232
+ total = await db[SAMPLING_PLANS_COLLECTION].count_documents(query)
233
+ cursor = db[SAMPLING_PLANS_COLLECTION].find(query).skip((page - 1) * page_size).limit(page_size)
234
+ return [_normalize_sampling_plan_record(doc) async for doc in cursor], total
235
+
236
+
237
+ async def get_sampling_plan_by_id(db: AsyncIOMotorDatabase, plan_id: str) -> Optional[dict]:
238
+ return _normalize_sampling_plan_record(await db[SAMPLING_PLANS_COLLECTION].find_one({"plan_id": plan_id}))
239
+
240
+
241
+ async def get_sampling_plan_by_code(db: AsyncIOMotorDatabase, plan_code: str) -> Optional[dict]:
242
+ return _normalize_sampling_plan_record(await db[SAMPLING_PLANS_COLLECTION].find_one({"plan_code": plan_code}))
243
+
244
+
245
+ async def get_sampling_plans_by_material(db: AsyncIOMotorDatabase, material_code: str) -> list[dict]:
246
+ cursor = db[SAMPLING_PLANS_COLLECTION].find({"material_code": material_code})
247
+ return [_normalize_sampling_plan_record(doc) async for doc in cursor]
248
+
249
+
250
+ async def get_sampling_plans_by_supplier(db: AsyncIOMotorDatabase, supplier_id: str) -> list[dict]:
251
+ cursor = db[SAMPLING_PLANS_COLLECTION].find({"supplier_id": supplier_id})
252
+ return [_normalize_sampling_plan_record(doc) async for doc in cursor]
253
+
254
+
255
+ async def create_sampling_plan(db: AsyncIOMotorDatabase, data: SamplingPlanCreate) -> dict:
256
+ doc = _prepare(data.model_dump())
257
+ await db[SAMPLING_PLANS_COLLECTION].insert_one(doc)
258
+ return _normalize_sampling_plan_record(doc)
259
+
260
+
261
+ async def update_sampling_plan(
262
+ db: AsyncIOMotorDatabase,
263
+ plan_id: str,
264
+ data: SamplingPlanUpdate,
265
+ ) -> Optional[dict]:
266
+ fields = _prepare(data.model_dump(exclude_unset=True))
267
+ if not fields:
268
+ return await get_sampling_plan_by_id(db, plan_id)
269
+ result = await db[SAMPLING_PLANS_COLLECTION].find_one_and_update(
270
+ {"plan_id": plan_id},
271
+ {"$set": fields},
272
+ return_document=ReturnDocument.AFTER,
273
+ )
274
+ return _normalize_sampling_plan_record(result)
275
+
276
+
277
+ async def delete_sampling_plan(db: AsyncIOMotorDatabase, plan_id: str) -> bool:
278
+ result = await db[SAMPLING_PLANS_COLLECTION].delete_one({"plan_id": plan_id})
279
+ return result.deleted_count == 1
280
+
281
+
282
+ async def get_all_samples(
283
+ db: AsyncIOMotorDatabase,
284
+ page: int = 1,
285
+ page_size: int = 20,
286
+ ) -> tuple[list[dict], int]:
287
+ query: dict = {}
288
+ total = await db[SAMPLES_COLLECTION].count_documents(query)
289
+ cursor = db[SAMPLES_COLLECTION].find(query).skip((page - 1) * page_size).limit(page_size)
290
+ return [_normalize_sample_record(doc) async for doc in cursor], total
291
+
292
+
293
+ async def get_sample_by_id(db: AsyncIOMotorDatabase, sample_id: str) -> Optional[dict]:
294
+ return _normalize_sample_record(await db[SAMPLES_COLLECTION].find_one({"sample_id": sample_id}))
295
+
296
+
297
+ async def get_sample_by_code(db: AsyncIOMotorDatabase, sample_code: str) -> Optional[dict]:
298
+ return _normalize_sample_record(await db[SAMPLES_COLLECTION].find_one({"sample_code": sample_code}))
299
+
300
+
301
+ async def get_samples_by_gr_id(db: AsyncIOMotorDatabase, gr_id: str) -> list[dict]:
302
+ cursor = db[SAMPLES_COLLECTION].find({"gr_id": gr_id})
303
+ return [_normalize_sample_record(doc) async for doc in cursor]
304
+
305
+
306
+ async def get_samples_by_status(db: AsyncIOMotorDatabase, status: str) -> list[dict]:
307
+ cursor = db[SAMPLES_COLLECTION].find({"status": status})
308
+ return [_normalize_sample_record(doc) async for doc in cursor]
309
+
310
+
311
+ async def create_sample(db: AsyncIOMotorDatabase, data: SampleCreate) -> dict:
312
+ doc = _prepare(data.model_dump())
313
+ await db[SAMPLES_COLLECTION].insert_one(doc)
314
+ return _normalize_sample_record(doc)
315
+
316
+
317
+ async def update_sample(
318
+ db: AsyncIOMotorDatabase,
319
+ sample_id: str,
320
+ data: SampleUpdate,
321
+ ) -> Optional[dict]:
322
+ fields = _prepare(data.model_dump(exclude_unset=True))
323
+ if not fields:
324
+ return await get_sample_by_id(db, sample_id)
325
+ result = await db[SAMPLES_COLLECTION].find_one_and_update(
326
+ {"sample_id": sample_id},
327
+ {"$set": fields},
328
+ return_document=ReturnDocument.AFTER,
329
+ )
330
+ return _normalize_sample_record(result)
331
+
332
+
333
+ async def add_custody_entry(
334
+ db: AsyncIOMotorDatabase,
335
+ sample_id: str,
336
+ entry: ChainOfCustodyEntry,
337
+ ) -> Optional[dict]:
338
+ result = await db[SAMPLES_COLLECTION].find_one_and_update(
339
+ {"sample_id": sample_id},
340
+ {"$push": {"chain_of_custody": _prepare(entry.model_dump())}},
341
+ return_document=ReturnDocument.AFTER,
342
+ )
343
+ return _normalize_sample_record(result)
344
+
345
+
346
+ async def delete_sample(db: AsyncIOMotorDatabase, sample_id: str) -> bool:
347
+ result = await db[SAMPLES_COLLECTION].delete_one({"sample_id": sample_id})
348
+ return result.deleted_count == 1
349
+
350
+
351
+ async def get_all_resampling_records(
352
+ db: AsyncIOMotorDatabase,
353
+ page: int = 1,
354
+ page_size: int = 20,
355
+ ) -> tuple[list[dict], int]:
356
+ query: dict = {}
357
+ total = await db[RESAMPLING_RECORDS_COLLECTION].count_documents(query)
358
+ cursor = db[RESAMPLING_RECORDS_COLLECTION].find(query).skip((page - 1) * page_size).limit(page_size)
359
+ return [_normalize_resampling_record(doc) async for doc in cursor], total
360
+
361
+
362
+ async def get_resampling_record_by_id(
363
+ db: AsyncIOMotorDatabase,
364
+ resample_id: str,
365
+ ) -> Optional[dict]:
366
+ return _normalize_resampling_record(await db[RESAMPLING_RECORDS_COLLECTION].find_one({"resample_id": resample_id}))
367
+
368
+
369
+ async def get_resampling_records_by_original_sample(
370
+ db: AsyncIOMotorDatabase,
371
+ original_sample_id: str,
372
+ ) -> list[dict]:
373
+ cursor = db[RESAMPLING_RECORDS_COLLECTION].find({"original_sample_id": original_sample_id})
374
+ return [_normalize_resampling_record(doc) async for doc in cursor]
375
+
376
+
377
+ async def create_resampling_record(
378
+ db: AsyncIOMotorDatabase,
379
+ data: ResamplingRecordCreate,
380
+ ) -> dict:
381
+ doc = _prepare(data.model_dump())
382
+ await db[RESAMPLING_RECORDS_COLLECTION].insert_one(doc)
383
+ return _normalize_resampling_record(doc)
384
+
385
+
386
+ async def update_resampling_record(
387
+ db: AsyncIOMotorDatabase,
388
+ resample_id: str,
389
+ data: ResamplingRecordUpdate,
390
+ ) -> Optional[dict]:
391
+ fields = _prepare(data.model_dump(exclude_unset=True))
392
+ if not fields:
393
+ return await get_resampling_record_by_id(db, resample_id)
394
+ result = await db[RESAMPLING_RECORDS_COLLECTION].find_one_and_update(
395
+ {"resample_id": resample_id},
396
+ {"$set": fields},
397
+ return_document=ReturnDocument.AFTER,
398
+ )
399
+ return _normalize_resampling_record(result)
400
+
401
+
402
+ async def delete_resampling_record(db: AsyncIOMotorDatabase, resample_id: str) -> bool:
403
+ result = await db[RESAMPLING_RECORDS_COLLECTION].delete_one({"resample_id": resample_id})
404
+ return result.deleted_count == 1
@@ -0,0 +1,52 @@
1
+ from contextlib import asynccontextmanager
2
+
3
+ from fastapi import FastAPI
4
+ from fastapi.middleware.cors import CORSMiddleware
5
+
6
+ from services.common.logging import configure_service_logging, install_request_logging
7
+ from services.common.tracing import install_route_tracing
8
+
9
+ from services.common.db import close_db, connect_db
10
+ from services.procurement.routers.goods_receipts import router as goods_receipts_router
11
+ from services.procurement.routers.purchase_orders import router as purchase_orders_router
12
+ from services.procurement.routers.shipping_information import router as purchase_order_shipping_router
13
+ from services.procurement.routers.quality_control import router as quality_control_router
14
+ from services.procurement.routers.sampling import router as sampling_router
15
+
16
+
17
+ logger = configure_service_logging("procurement")
18
+
19
+ @asynccontextmanager
20
+ async def lifespan(app: FastAPI):
21
+ await connect_db()
22
+ yield
23
+ await close_db()
24
+
25
+
26
+ app = FastAPI(
27
+ title="Procurement Service",
28
+ description="Microservice for procurement service.",
29
+ version="1.0.0",
30
+ lifespan=lifespan,
31
+ )
32
+ install_request_logging(app, "procurement")
33
+ install_route_tracing(app, "procurement")
34
+
35
+ app.add_middleware(
36
+ CORSMiddleware,
37
+ allow_origins=["*"],
38
+ allow_credentials=True,
39
+ allow_methods=["*"],
40
+ allow_headers=["*"],
41
+ )
42
+
43
+ app.include_router(purchase_orders_router, prefix="/api/v1/purchase-orders", tags=["Purchase Orders"])
44
+ app.include_router(purchase_order_shipping_router, prefix="/api/v1/purchase-order-shipping-information", tags=["Purchase Order Shipping Information"])
45
+ app.include_router(goods_receipts_router, prefix="/api/v1/goods-receipts", tags=["Goods Receipts"])
46
+ app.include_router(sampling_router, prefix="/api/v1/sampling", tags=["Sampling"])
47
+ app.include_router(quality_control_router, prefix="/api/v1/quality-control", tags=["Quality Control"])
48
+
49
+
50
+ @app.get("/health", tags=["Health"])
51
+ async def health_check():
52
+ return {"status": "healthy"}