pyarchinit-mini 1.9.28__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 (281) hide show
  1. pyarchinit_mini/__init__.py +40 -0
  2. pyarchinit_mini/api/__init__.py +92 -0
  3. pyarchinit_mini/api/auth.py +312 -0
  4. pyarchinit_mini/api/dependencies.py +63 -0
  5. pyarchinit_mini/api/graphml.py +160 -0
  6. pyarchinit_mini/api/inventario.py +107 -0
  7. pyarchinit_mini/api/schemas.py +186 -0
  8. pyarchinit_mini/api/site.py +220 -0
  9. pyarchinit_mini/api/us.py +107 -0
  10. pyarchinit_mini/cli/__init__.py +7 -0
  11. pyarchinit_mini/cli/export_import_cli.py +289 -0
  12. pyarchinit_mini/cli/extended_matrix_import.py +101 -0
  13. pyarchinit_mini/cli/graphml_cli.py +219 -0
  14. pyarchinit_mini/cli/harris_import.py +574 -0
  15. pyarchinit_mini/cli/harris_template.py +323 -0
  16. pyarchinit_mini/cli/migrate.py +202 -0
  17. pyarchinit_mini/cli/pyarchinit_import_export_cli.py +428 -0
  18. pyarchinit_mini/cli_interface/__init__.py +1 -0
  19. pyarchinit_mini/cli_interface/cli_app.py +529 -0
  20. pyarchinit_mini/config/__init__.py +0 -0
  21. pyarchinit_mini/config/connection_manager.py +286 -0
  22. pyarchinit_mini/config/em_node_config_manager.py +452 -0
  23. pyarchinit_mini/config/em_node_types.yaml +349 -0
  24. pyarchinit_mini/database/__init__.py +13 -0
  25. pyarchinit_mini/database/connection.py +168 -0
  26. pyarchinit_mini/database/database_creator.py +290 -0
  27. pyarchinit_mini/database/manager.py +231 -0
  28. pyarchinit_mini/database/migration_scripts/__init__.py +7 -0
  29. pyarchinit_mini/database/migration_scripts/add_file_path.py +152 -0
  30. pyarchinit_mini/database/migration_scripts/add_i18n_columns.py +312 -0
  31. pyarchinit_mini/database/migration_scripts/add_tipo_documento.py +154 -0
  32. pyarchinit_mini/database/migration_scripts/change_us_area_to_text.py +321 -0
  33. pyarchinit_mini/database/migration_scripts/change_us_area_to_text_simple.py +230 -0
  34. pyarchinit_mini/database/migrations.py +232 -0
  35. pyarchinit_mini/database/postgres_installer.py +375 -0
  36. pyarchinit_mini/database/schemas.py +177 -0
  37. pyarchinit_mini/desktop_gui/__init__.py +51 -0
  38. pyarchinit_mini/desktop_gui/analytics_dialog.py +228 -0
  39. pyarchinit_mini/desktop_gui/assets/logo.png +0 -0
  40. pyarchinit_mini/desktop_gui/dialogs.py +1984 -0
  41. pyarchinit_mini/desktop_gui/excel_import_dialog.py +380 -0
  42. pyarchinit_mini/desktop_gui/export_import_dialog.py +313 -0
  43. pyarchinit_mini/desktop_gui/graphml_export_dialog.py +221 -0
  44. pyarchinit_mini/desktop_gui/gui_app.py +106 -0
  45. pyarchinit_mini/desktop_gui/harris_matrix_editor.py +970 -0
  46. pyarchinit_mini/desktop_gui/i18n.py +191 -0
  47. pyarchinit_mini/desktop_gui/icons.py +70 -0
  48. pyarchinit_mini/desktop_gui/inventario_dialog_extended.py +966 -0
  49. pyarchinit_mini/desktop_gui/main_window.py +1826 -0
  50. pyarchinit_mini/desktop_gui/media_manager_advanced.py +141 -0
  51. pyarchinit_mini/desktop_gui/postgres_installer_dialog.py +357 -0
  52. pyarchinit_mini/desktop_gui/pyarchinit_import_export_dialog.py +585 -0
  53. pyarchinit_mini/desktop_gui/thesaurus_dialog.py +463 -0
  54. pyarchinit_mini/desktop_gui/us_dialog_extended.py +2122 -0
  55. pyarchinit_mini/dto/__init__.py +16 -0
  56. pyarchinit_mini/dto/inventario_dto.py +57 -0
  57. pyarchinit_mini/dto/site_dto.py +62 -0
  58. pyarchinit_mini/dto/us_dto.py +237 -0
  59. pyarchinit_mini/exceptions.py +23 -0
  60. pyarchinit_mini/graphml_converter/__init__.py +47 -0
  61. pyarchinit_mini/graphml_converter/converter.py +343 -0
  62. pyarchinit_mini/graphml_converter/dot_parser.py +1331 -0
  63. pyarchinit_mini/graphml_converter/em_palette.py +355 -0
  64. pyarchinit_mini/graphml_converter/graphml_builder.py +657 -0
  65. pyarchinit_mini/graphml_converter/graphml_exporter.py +1048 -0
  66. pyarchinit_mini/graphml_converter/pure_networkx_exporter.py +719 -0
  67. pyarchinit_mini/graphml_converter/svg_resources.py +244 -0
  68. pyarchinit_mini/graphml_converter/templates/EM_palette.graphml +658 -0
  69. pyarchinit_mini/graphml_converter/x11_colors.py +678 -0
  70. pyarchinit_mini/graphml_converter/yed_template.py +365 -0
  71. pyarchinit_mini/harris_matrix/__init__.py +11 -0
  72. pyarchinit_mini/harris_matrix/enhanced_visualizer.py +465 -0
  73. pyarchinit_mini/harris_matrix/matrix_generator.py +1244 -0
  74. pyarchinit_mini/harris_matrix/matrix_visualizer.py +368 -0
  75. pyarchinit_mini/harris_matrix/pyarchinit_visualizer.py +581 -0
  76. pyarchinit_mini/i18n/__init__.py +15 -0
  77. pyarchinit_mini/i18n/flask_babel_config.py +94 -0
  78. pyarchinit_mini/i18n/locale_manager.py +142 -0
  79. pyarchinit_mini/mcp_server/__init__.py +22 -0
  80. pyarchinit_mini/mcp_server/__main__.py +45 -0
  81. pyarchinit_mini/mcp_server/blender_client.py +525 -0
  82. pyarchinit_mini/mcp_server/config.py +181 -0
  83. pyarchinit_mini/mcp_server/event_stream.py +282 -0
  84. pyarchinit_mini/mcp_server/graphml_parser.py +612 -0
  85. pyarchinit_mini/mcp_server/http_server.py +501 -0
  86. pyarchinit_mini/mcp_server/period_filter.py +362 -0
  87. pyarchinit_mini/mcp_server/prompts/__init__.py +18 -0
  88. pyarchinit_mini/mcp_server/prompts/base_prompt.py +23 -0
  89. pyarchinit_mini/mcp_server/prompts/period_visualization_prompt.py +25 -0
  90. pyarchinit_mini/mcp_server/prompts/stratigraphic_model_prompt.py +25 -0
  91. pyarchinit_mini/mcp_server/prompts/us_description_prompt.py +25 -0
  92. pyarchinit_mini/mcp_server/proxy_generator.py +470 -0
  93. pyarchinit_mini/mcp_server/resources/__init__.py +24 -0
  94. pyarchinit_mini/mcp_server/resources/base_resource.py +79 -0
  95. pyarchinit_mini/mcp_server/resources/graphml_resource.py +382 -0
  96. pyarchinit_mini/mcp_server/resources/periods_resource.py +52 -0
  97. pyarchinit_mini/mcp_server/resources/relationships_resource.py +52 -0
  98. pyarchinit_mini/mcp_server/resources/sites_resource.py +52 -0
  99. pyarchinit_mini/mcp_server/resources/us_resource.py +52 -0
  100. pyarchinit_mini/mcp_server/server.py +564 -0
  101. pyarchinit_mini/mcp_server/tools/__init__.py +24 -0
  102. pyarchinit_mini/mcp_server/tools/base_tool.py +119 -0
  103. pyarchinit_mini/mcp_server/tools/batch_insert_tool.py +393 -0
  104. pyarchinit_mini/mcp_server/tools/build_3d_tool.py +524 -0
  105. pyarchinit_mini/mcp_server/tools/chatgpt_fetch_tool.py +183 -0
  106. pyarchinit_mini/mcp_server/tools/chatgpt_search_tool.py +130 -0
  107. pyarchinit_mini/mcp_server/tools/configure_em_nodes_tool.py +427 -0
  108. pyarchinit_mini/mcp_server/tools/create_database_tool.py +118 -0
  109. pyarchinit_mini/mcp_server/tools/create_harris_matrix_tool.py +421 -0
  110. pyarchinit_mini/mcp_server/tools/data_import_parser_tool.py +695 -0
  111. pyarchinit_mini/mcp_server/tools/data_management_tool.py +262 -0
  112. pyarchinit_mini/mcp_server/tools/database_manager_tool.py +200 -0
  113. pyarchinit_mini/mcp_server/tools/delete_data_tool.py +288 -0
  114. pyarchinit_mini/mcp_server/tools/export_harris_matrix_graphml_tool.py +184 -0
  115. pyarchinit_mini/mcp_server/tools/export_tool.py +32 -0
  116. pyarchinit_mini/mcp_server/tools/filter_tool.py +32 -0
  117. pyarchinit_mini/mcp_server/tools/generate_report_tool.py +679 -0
  118. pyarchinit_mini/mcp_server/tools/get_schema_tool.py +224 -0
  119. pyarchinit_mini/mcp_server/tools/import_excel_tool.py +270 -0
  120. pyarchinit_mini/mcp_server/tools/insert_data_tool.py +390 -0
  121. pyarchinit_mini/mcp_server/tools/manage_services_tool.py +507 -0
  122. pyarchinit_mini/mcp_server/tools/material_tool.py +32 -0
  123. pyarchinit_mini/mcp_server/tools/media_management_tool.py +494 -0
  124. pyarchinit_mini/mcp_server/tools/position_tool.py +32 -0
  125. pyarchinit_mini/mcp_server/tools/pyarchinit_sync_tool.py +172 -0
  126. pyarchinit_mini/mcp_server/tools/resolve_conflicts_tool.py +377 -0
  127. pyarchinit_mini/mcp_server/tools/service_management_tool.py +104 -0
  128. pyarchinit_mini/mcp_server/tools/thesaurus_management_tool.py +420 -0
  129. pyarchinit_mini/mcp_server/tools/update_data_tool.py +360 -0
  130. pyarchinit_mini/mcp_server/tools/upload_file_tool.py +112 -0
  131. pyarchinit_mini/mcp_server/tools/validate_relationship_format_tool.py +327 -0
  132. pyarchinit_mini/mcp_server/tools/validate_relationship_integrity_tool.py +532 -0
  133. pyarchinit_mini/mcp_server/tools/validate_stratigraphic_relationships_tool.py +261 -0
  134. pyarchinit_mini/mcp_server/tools/validate_stratigraphy_tool.py +363 -0
  135. pyarchinit_mini/media_manager/__init__.py +9 -0
  136. pyarchinit_mini/media_manager/media_handler.py +322 -0
  137. pyarchinit_mini/models/__init__.py +35 -0
  138. pyarchinit_mini/models/base.py +32 -0
  139. pyarchinit_mini/models/datazione.py +68 -0
  140. pyarchinit_mini/models/extended_matrix.py +44 -0
  141. pyarchinit_mini/models/harris_matrix.py +117 -0
  142. pyarchinit_mini/models/inventario_materiali.py +238 -0
  143. pyarchinit_mini/models/media.py +109 -0
  144. pyarchinit_mini/models/site.py +96 -0
  145. pyarchinit_mini/models/thesaurus.py +179 -0
  146. pyarchinit_mini/models/us.py +291 -0
  147. pyarchinit_mini/models/user.py +78 -0
  148. pyarchinit_mini/pdf_export/__init__.py +9 -0
  149. pyarchinit_mini/pdf_export/pdf_generator.py +1048 -0
  150. pyarchinit_mini/pdf_export/pdf_generator_backup.py +1013 -0
  151. pyarchinit_mini/pdf_export/pyarchinit_finds_template.py +404 -0
  152. pyarchinit_mini/pdf_export/pyarchinit_inventory_template.py +353 -0
  153. pyarchinit_mini/pdf_export/usm_implementation.py +465 -0
  154. pyarchinit_mini/s3d_integration/__init__.py +9 -0
  155. pyarchinit_mini/s3d_integration/model_manager.py +234 -0
  156. pyarchinit_mini/s3d_integration/s3d_converter.py +848 -0
  157. pyarchinit_mini/scripts/__init__.py +3 -0
  158. pyarchinit_mini/scripts/auto_translate.py +679 -0
  159. pyarchinit_mini/scripts/configure_claude_desktop.py +277 -0
  160. pyarchinit_mini/scripts/create_admin_user.py +152 -0
  161. pyarchinit_mini/scripts/create_correct_stratigraphy_sample.py +373 -0
  162. pyarchinit_mini/scripts/create_italian_sample_database.py +302 -0
  163. pyarchinit_mini/scripts/create_sample_for_webapp.py +463 -0
  164. pyarchinit_mini/scripts/create_sample_with_50_us.py +353 -0
  165. pyarchinit_mini/scripts/generate_test_3d_model.py +323 -0
  166. pyarchinit_mini/scripts/load_italian_as_main.py +39 -0
  167. pyarchinit_mini/scripts/load_sample_as_main.py +73 -0
  168. pyarchinit_mini/scripts/migrate_relationships.py +165 -0
  169. pyarchinit_mini/scripts/populate_sample_data.py +498 -0
  170. pyarchinit_mini/scripts/populate_simple_data.py +213 -0
  171. pyarchinit_mini/scripts/setup_auth.py +112 -0
  172. pyarchinit_mini/scripts/setup_user_env.py +316 -0
  173. pyarchinit_mini/scripts/test_cascade_delete.py +91 -0
  174. pyarchinit_mini/scripts/test_relationship_fix.py +128 -0
  175. pyarchinit_mini/scripts/update_sample_relationships.py +136 -0
  176. pyarchinit_mini/scripts/update_urls_and_versions.py +312 -0
  177. pyarchinit_mini/scripts/verify_docs.py +312 -0
  178. pyarchinit_mini/services/__init__.py +19 -0
  179. pyarchinit_mini/services/analytics_service.py +242 -0
  180. pyarchinit_mini/services/command_parser.py +159 -0
  181. pyarchinit_mini/services/datazione_service.py +244 -0
  182. pyarchinit_mini/services/export_import_service.py +430 -0
  183. pyarchinit_mini/services/extended_matrix_excel_parser.py +708 -0
  184. pyarchinit_mini/services/import_export_service.py +2381 -0
  185. pyarchinit_mini/services/inventario_service.py +347 -0
  186. pyarchinit_mini/services/mcp_executor.py +206 -0
  187. pyarchinit_mini/services/media_service.py +458 -0
  188. pyarchinit_mini/services/periodizzazione_service.py +417 -0
  189. pyarchinit_mini/services/relationship_sync_service.py +400 -0
  190. pyarchinit_mini/services/site_service.py +328 -0
  191. pyarchinit_mini/services/thesaurus_service.py +358 -0
  192. pyarchinit_mini/services/us_service.py +446 -0
  193. pyarchinit_mini/services/user_service.py +293 -0
  194. pyarchinit_mini/translations/en/LC_MESSAGES/messages.mo +0 -0
  195. pyarchinit_mini/translations/en/LC_MESSAGES/messages.po +5110 -0
  196. pyarchinit_mini/translations/it/LC_MESSAGES/messages.mo +0 -0
  197. pyarchinit_mini/translations/it/LC_MESSAGES/messages.po +4798 -0
  198. pyarchinit_mini/translations/messages.pot +0 -0
  199. pyarchinit_mini/utils/__init__.py +27 -0
  200. pyarchinit_mini/utils/auth.py +143 -0
  201. pyarchinit_mini/utils/exceptions.py +38 -0
  202. pyarchinit_mini/utils/relationship_validator.py +388 -0
  203. pyarchinit_mini/utils/stratigraphic_validator.py +613 -0
  204. pyarchinit_mini/utils/validators.py +230 -0
  205. pyarchinit_mini/web_interface/app.py +4152 -0
  206. pyarchinit_mini/web_interface/auth_routes.py +263 -0
  207. pyarchinit_mini/web_interface/em_node_config_routes.py +280 -0
  208. pyarchinit_mini/web_interface/excel_import_routes.py +336 -0
  209. pyarchinit_mini/web_interface/harris_creator_routes.py +568 -0
  210. pyarchinit_mini/web_interface/pyarchinit_import_export_routes.py +888 -0
  211. pyarchinit_mini/web_interface/s3d_routes.py +361 -0
  212. pyarchinit_mini/web_interface/socketio_events.py +537 -0
  213. pyarchinit_mini/web_interface/static/css/style.css +4 -0
  214. pyarchinit_mini/web_interface/static/images/favicon.ico +0 -0
  215. pyarchinit_mini/web_interface/static/images/logo.png +0 -0
  216. pyarchinit_mini/web_interface/static/images/pyarchinit-mini-logo.png +0 -0
  217. pyarchinit_mini/web_interface/static/js/OrbitControls.js +1045 -0
  218. pyarchinit_mini/web_interface/static/js/harris_creator_editor.js +989 -0
  219. pyarchinit_mini/web_interface/static/js/stratigraphic_layout.js +782 -0
  220. pyarchinit_mini/web_interface/static/js/three-d-viewer.js +670 -0
  221. pyarchinit_mini/web_interface/static/js/three.min.js +6 -0
  222. pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.bin +0 -0
  223. pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.gltf +92 -0
  224. pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.mtl +71 -0
  225. pyarchinit_mini/web_interface/static/uploads/3d_models/Sito Archeologico di Esempio/site/stratigraphy_test.obj +244 -0
  226. pyarchinit_mini/web_interface/templates/3d_builder/index.html +2092 -0
  227. pyarchinit_mini/web_interface/templates/3d_viewer/viewer.html +259 -0
  228. pyarchinit_mini/web_interface/templates/admin/database.html +1140 -0
  229. pyarchinit_mini/web_interface/templates/admin/database_connect.html +188 -0
  230. pyarchinit_mini/web_interface/templates/admin/database_info.html +171 -0
  231. pyarchinit_mini/web_interface/templates/admin/database_upload.html +112 -0
  232. pyarchinit_mini/web_interface/templates/analytics/dashboard.html +414 -0
  233. pyarchinit_mini/web_interface/templates/auth/login.html +52 -0
  234. pyarchinit_mini/web_interface/templates/auth/users.html +217 -0
  235. pyarchinit_mini/web_interface/templates/base.html +765 -0
  236. pyarchinit_mini/web_interface/templates/blender_viewer.html +1285 -0
  237. pyarchinit_mini/web_interface/templates/components/language_switcher.html +47 -0
  238. pyarchinit_mini/web_interface/templates/dashboard.html +226 -0
  239. pyarchinit_mini/web_interface/templates/datazioni/list.html +62 -0
  240. pyarchinit_mini/web_interface/templates/em_node_config/index.html +430 -0
  241. pyarchinit_mini/web_interface/templates/excel_import/index.html +391 -0
  242. pyarchinit_mini/web_interface/templates/export/export_import.html +240 -0
  243. pyarchinit_mini/web_interface/templates/harris_creator/editor.html +373 -0
  244. pyarchinit_mini/web_interface/templates/harris_creator/index.html +196 -0
  245. pyarchinit_mini/web_interface/templates/harris_matrix/graphml_export.html +300 -0
  246. pyarchinit_mini/web_interface/templates/harris_matrix/large_graph_message.html +108 -0
  247. pyarchinit_mini/web_interface/templates/harris_matrix/stratigraph_viewer.html +474 -0
  248. pyarchinit_mini/web_interface/templates/harris_matrix/view.html +97 -0
  249. pyarchinit_mini/web_interface/templates/harris_matrix/view_graphviz.html +202 -0
  250. pyarchinit_mini/web_interface/templates/harris_matrix/viewer_3d_integrated.html +1288 -0
  251. pyarchinit_mini/web_interface/templates/inventario/form.html +605 -0
  252. pyarchinit_mini/web_interface/templates/inventario/list.html +109 -0
  253. pyarchinit_mini/web_interface/templates/media/list.html +293 -0
  254. pyarchinit_mini/web_interface/templates/media/upload.html +125 -0
  255. pyarchinit_mini/web_interface/templates/periodizzazione/form.html +81 -0
  256. pyarchinit_mini/web_interface/templates/periodizzazione/list.html +102 -0
  257. pyarchinit_mini/web_interface/templates/periodizzazione/periods.html +107 -0
  258. pyarchinit_mini/web_interface/templates/pyarchinit_import_export/index.html +928 -0
  259. pyarchinit_mini/web_interface/templates/sites/detail.html +128 -0
  260. pyarchinit_mini/web_interface/templates/sites/form.html +315 -0
  261. pyarchinit_mini/web_interface/templates/sites/list.html +273 -0
  262. pyarchinit_mini/web_interface/templates/thesaurus/list.html +290 -0
  263. pyarchinit_mini/web_interface/templates/us/form.html +788 -0
  264. pyarchinit_mini/web_interface/templates/us/list.html +165 -0
  265. pyarchinit_mini/web_interface/templates/validation/report.html +253 -0
  266. pyarchinit_mini/web_interface/test_prova_extended_matrix.graphml +177 -0
  267. pyarchinit_mini/web_interface/three_d_builder_routes.py +1554 -0
  268. pyarchinit_mini/web_interface/uploads/graphml/Sito Archeologico di Esempio_stratigraphy.graphml +1792 -0
  269. pyarchinit_mini/web_interface/uploads/graphml/Sito Archeologico di Esempio_stratigraphy.json +2115 -0
  270. pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Scavo archeologico_heriverse.json +2132 -0
  271. pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Scavo archeologico_stratigraphy.graphml +2001 -0
  272. pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Scavo archeologico_stratigraphy.json +1782 -0
  273. pyarchinit_mini/web_interface/web_interface/static/uploads/graphml/Sito Archeologico di Esempio_stratigraphy.json +1457 -0
  274. pyarchinit_mini-1.9.28.dist-info/METADATA +2141 -0
  275. pyarchinit_mini-1.9.28.dist-info/RECORD +281 -0
  276. pyarchinit_mini-1.9.28.dist-info/WHEEL +5 -0
  277. pyarchinit_mini-1.9.28.dist-info/entry_points.txt +18 -0
  278. pyarchinit_mini-1.9.28.dist-info/top_level.txt +2 -0
  279. tests/__init__.py +1 -0
  280. tests/conftest.py +88 -0
  281. tests/unit/test_site_service.py +106 -0
@@ -0,0 +1,107 @@
1
+ """
2
+ Inventario Materiali API endpoints
3
+ """
4
+
5
+ from typing import List, Optional
6
+ from fastapi import APIRouter, Depends, HTTPException, Query
7
+
8
+ from .schemas import InventarioCreate, InventarioUpdate, InventarioResponse, PaginatedResponse
9
+ from .dependencies import get_inventario_service
10
+ from ..services.inventario_service import InventarioService
11
+ from ..utils.exceptions import ValidationError, RecordNotFoundError
12
+
13
+ router = APIRouter()
14
+
15
+ @router.get("/", response_model=PaginatedResponse)
16
+ async def get_inventario_list(
17
+ page: int = Query(1, ge=1),
18
+ size: int = Query(10, ge=1, le=100),
19
+ sito: Optional[str] = Query(None, description="Filter by site"),
20
+ tipo_reperto: Optional[str] = Query(None, description="Filter by find type"),
21
+ inventario_service: InventarioService = Depends(get_inventario_service)
22
+ ):
23
+ """Get paginated list of inventory items"""
24
+ try:
25
+ filters = {}
26
+ if sito:
27
+ filters['sito'] = sito
28
+ if tipo_reperto:
29
+ filters['tipo_reperto'] = tipo_reperto
30
+
31
+ items = inventario_service.get_all_inventario(page=page, size=size, filters=filters)
32
+ total = inventario_service.count_inventario(filters=filters)
33
+
34
+ return PaginatedResponse(
35
+ items=[InventarioResponse.from_orm(item) for item in items],
36
+ total=total,
37
+ page=page,
38
+ size=size,
39
+ pages=(total + size - 1) // size
40
+ )
41
+ except Exception as e:
42
+ raise HTTPException(status_code=500, detail=str(e))
43
+
44
+ @router.get("/{item_id}", response_model=InventarioResponse)
45
+ async def get_inventario_item(
46
+ item_id: int,
47
+ inventario_service: InventarioService = Depends(get_inventario_service)
48
+ ):
49
+ """Get inventory item by ID"""
50
+ try:
51
+ item = inventario_service.get_inventario_by_id(item_id)
52
+ if not item:
53
+ raise HTTPException(status_code=404, detail="Inventory item not found")
54
+ return InventarioResponse.from_orm(item)
55
+ except RecordNotFoundError:
56
+ raise HTTPException(status_code=404, detail="Inventory item not found")
57
+ except Exception as e:
58
+ raise HTTPException(status_code=500, detail=str(e))
59
+
60
+ @router.post("/", response_model=InventarioResponse, status_code=201)
61
+ async def create_inventario_item(
62
+ item_data: InventarioCreate,
63
+ inventario_service: InventarioService = Depends(get_inventario_service)
64
+ ):
65
+ """Create a new inventory item"""
66
+ try:
67
+ item = inventario_service.create_inventario(item_data.dict())
68
+ return InventarioResponse.from_orm(item)
69
+ except ValidationError as e:
70
+ raise HTTPException(status_code=400, detail=str(e))
71
+ except Exception as e:
72
+ raise HTTPException(status_code=500, detail=str(e))
73
+
74
+ @router.put("/{item_id}", response_model=InventarioResponse)
75
+ async def update_inventario_item(
76
+ item_id: int,
77
+ item_data: InventarioUpdate,
78
+ inventario_service: InventarioService = Depends(get_inventario_service)
79
+ ):
80
+ """Update an existing inventory item"""
81
+ try:
82
+ update_data = {k: v for k, v in item_data.dict().items() if v is not None}
83
+ item = inventario_service.update_inventario(item_id, update_data)
84
+ return InventarioResponse.from_orm(item)
85
+ except RecordNotFoundError:
86
+ raise HTTPException(status_code=404, detail="Inventory item not found")
87
+ except ValidationError as e:
88
+ raise HTTPException(status_code=400, detail=str(e))
89
+ except Exception as e:
90
+ raise HTTPException(status_code=500, detail=str(e))
91
+
92
+ @router.delete("/{item_id}")
93
+ async def delete_inventario_item(
94
+ item_id: int,
95
+ inventario_service: InventarioService = Depends(get_inventario_service)
96
+ ):
97
+ """Delete an inventory item"""
98
+ try:
99
+ success = inventario_service.delete_inventario(item_id)
100
+ if success:
101
+ return {"message": "Inventory item deleted successfully"}
102
+ else:
103
+ raise HTTPException(status_code=404, detail="Inventory item not found")
104
+ except RecordNotFoundError:
105
+ raise HTTPException(status_code=404, detail="Inventory item not found")
106
+ except Exception as e:
107
+ raise HTTPException(status_code=500, detail=str(e))
@@ -0,0 +1,186 @@
1
+ """
2
+ Pydantic schemas for API request/response validation
3
+ """
4
+
5
+ from datetime import datetime
6
+ from typing import Optional, List
7
+ from pydantic import BaseModel, Field, validator
8
+
9
+ # Base schemas
10
+
11
+ class BaseSchema(BaseModel):
12
+ """Base schema with common fields"""
13
+ created_at: Optional[datetime] = None
14
+ updated_at: Optional[datetime] = None
15
+
16
+ class Config:
17
+ from_attributes = True
18
+
19
+ # Site schemas
20
+
21
+ class SiteBase(BaseModel):
22
+ """Base site schema"""
23
+ sito: str = Field(..., min_length=1, max_length=350, description="Site name")
24
+ nazione: Optional[str] = Field(None, max_length=250, description="Country")
25
+ regione: Optional[str] = Field(None, max_length=250, description="Region")
26
+ comune: Optional[str] = Field(None, max_length=250, description="Municipality")
27
+ provincia: Optional[str] = Field(None, max_length=10, description="Province")
28
+ definizione_sito: Optional[str] = Field(None, max_length=250, description="Site definition")
29
+ descrizione: Optional[str] = Field(None, description="Description")
30
+ sito_path: Optional[str] = Field(None, max_length=500, description="Site path")
31
+ find_check: Optional[bool] = Field(False, description="Find check flag")
32
+
33
+ class SiteCreate(SiteBase):
34
+ """Schema for creating a site"""
35
+ pass
36
+
37
+ class SiteUpdate(BaseModel):
38
+ """Schema for updating a site"""
39
+ sito: Optional[str] = Field(None, min_length=1, max_length=350)
40
+ nazione: Optional[str] = Field(None, max_length=250)
41
+ regione: Optional[str] = Field(None, max_length=250)
42
+ comune: Optional[str] = Field(None, max_length=250)
43
+ provincia: Optional[str] = Field(None, max_length=10)
44
+ definizione_sito: Optional[str] = Field(None, max_length=250)
45
+ descrizione: Optional[str] = None
46
+ sito_path: Optional[str] = Field(None, max_length=500)
47
+ find_check: Optional[bool] = None
48
+
49
+ class SiteResponse(SiteBase, BaseSchema):
50
+ """Schema for site response"""
51
+ id_sito: int = Field(..., description="Site ID")
52
+
53
+ # US (Stratigraphic Unit) schemas
54
+
55
+ class USBase(BaseModel):
56
+ """Base US schema"""
57
+ sito: str = Field(..., max_length=350, description="Site name")
58
+ area: Optional[str] = Field(None, max_length=20, description="Area")
59
+ us: int = Field(..., gt=0, description="US number")
60
+ d_stratigrafica: Optional[str] = Field(None, max_length=350, description="Stratigraphic description")
61
+ d_interpretativa: Optional[str] = Field(None, max_length=350, description="Interpretative description")
62
+ descrizione: Optional[str] = Field(None, description="Description")
63
+ interpretazione: Optional[str] = Field(None, description="Interpretation")
64
+ periodo_iniziale: Optional[str] = Field(None, max_length=300, description="Initial period")
65
+ fase_iniziale: Optional[str] = Field(None, max_length=300, description="Initial phase")
66
+ periodo_finale: Optional[str] = Field(None, max_length=300, description="Final period")
67
+ fase_finale: Optional[str] = Field(None, max_length=300, description="Final phase")
68
+ scavato: Optional[str] = Field(None, max_length=20, description="Excavated")
69
+ attivita: Optional[str] = Field(None, max_length=30, description="Activity")
70
+ anno_scavo: Optional[int] = Field(None, ge=1800, le=2100, description="Excavation year")
71
+ metodo_di_scavo: Optional[str] = Field(None, max_length=20, description="Excavation method")
72
+ schedatore: Optional[str] = Field(None, max_length=100, description="Recorder")
73
+ formazione: Optional[str] = Field(None, max_length=20, description="Formation")
74
+ stato_di_conservazione: Optional[str] = Field(None, max_length=20, description="Conservation state")
75
+ colore: Optional[str] = Field(None, max_length=20, description="Color")
76
+ consistenza: Optional[str] = Field(None, max_length=20, description="Consistency")
77
+ struttura: Optional[str] = Field(None, max_length=30, description="Structure")
78
+
79
+ # Measurements
80
+ quota_relativa: Optional[float] = Field(None, ge=0, description="Relative elevation")
81
+ quota_abs: Optional[float] = Field(None, ge=0, description="Absolute elevation")
82
+ lunghezza_max: Optional[float] = Field(None, ge=0, description="Maximum length")
83
+ altezza_max: Optional[float] = Field(None, ge=0, description="Maximum height")
84
+ altezza_min: Optional[float] = Field(None, ge=0, description="Minimum height")
85
+ profondita_max: Optional[float] = Field(None, ge=0, description="Maximum depth")
86
+ profondita_min: Optional[float] = Field(None, ge=0, description="Minimum depth")
87
+ larghezza_media: Optional[float] = Field(None, ge=0, description="Average width")
88
+
89
+ # Additional fields
90
+ osservazioni: Optional[str] = Field(None, description="Observations")
91
+ datazione: Optional[str] = Field(None, max_length=100, description="Dating")
92
+ direttore_us: Optional[str] = Field(None, max_length=100, description="US director")
93
+ responsabile_us: Optional[str] = Field(None, max_length=100, description="US responsible")
94
+
95
+ class USCreate(USBase):
96
+ """Schema for creating a US"""
97
+ pass
98
+
99
+ class USUpdate(BaseModel):
100
+ """Schema for updating a US"""
101
+ sito: Optional[str] = Field(None, max_length=350)
102
+ area: Optional[str] = Field(None, max_length=20)
103
+ us: Optional[int] = Field(None, gt=0)
104
+ d_stratigrafica: Optional[str] = Field(None, max_length=350)
105
+ d_interpretativa: Optional[str] = Field(None, max_length=350)
106
+ descrizione: Optional[str] = None
107
+ interpretazione: Optional[str] = None
108
+ anno_scavo: Optional[int] = Field(None, ge=1800, le=2100)
109
+ schedatore: Optional[str] = Field(None, max_length=100)
110
+ # ... other optional fields
111
+
112
+ class USResponse(USBase, BaseSchema):
113
+ """Schema for US response"""
114
+ id_us: int = Field(..., description="US ID")
115
+
116
+ # Inventario Materiali schemas
117
+
118
+ class InventarioBase(BaseModel):
119
+ """Base inventory schema"""
120
+ sito: str = Field(..., max_length=350, description="Site name")
121
+ numero_inventario: int = Field(..., gt=0, description="Inventory number")
122
+ tipo_reperto: Optional[str] = Field(None, max_length=20, description="Find type")
123
+ criterio_schedatura: Optional[str] = Field(None, max_length=20, description="Recording criteria")
124
+ definizione: Optional[str] = Field(None, max_length=20, description="Definition")
125
+ descrizione: Optional[str] = Field(None, description="Description")
126
+ area: Optional[str] = Field(None, max_length=20, description="Area")
127
+ us: Optional[int] = Field(None, gt=0, description="US number")
128
+ lavato: Optional[str] = Field(None, max_length=5, description="Washed")
129
+ nr_cassa: Optional[str] = Field(None, max_length=20, description="Box number")
130
+ luogo_conservazione: Optional[str] = Field(None, max_length=350, description="Conservation location")
131
+ stato_conservazione: Optional[str] = Field(None, max_length=200, description="Conservation state")
132
+ datazione_reperto: Optional[str] = Field(None, max_length=100, description="Find dating")
133
+
134
+ # Technical characteristics
135
+ forme_minime: Optional[int] = Field(None, ge=0, description="Minimum forms")
136
+ forme_massime: Optional[int] = Field(None, ge=0, description="Maximum forms")
137
+ totale_frammenti: Optional[int] = Field(None, ge=0, description="Total fragments")
138
+ peso: Optional[float] = Field(None, ge=0, description="Weight")
139
+ diametro_orlo: Optional[float] = Field(None, ge=0, description="Rim diameter")
140
+ eve_orlo: Optional[float] = Field(None, ge=0, le=100, description="Rim EVE")
141
+
142
+ # Classification
143
+ corpo_ceramico: Optional[str] = Field(None, max_length=20, description="Ceramic body")
144
+ rivestimento: Optional[str] = Field(None, max_length=20, description="Surface treatment")
145
+ tipo: Optional[str] = Field(None, max_length=300, description="Type")
146
+ repertato: Optional[str] = Field(None, max_length=2, description="Catalogued")
147
+ diagnostico: Optional[str] = Field(None, max_length=2, description="Diagnostic")
148
+
149
+ @validator('lavato', 'repertato', 'diagnostico')
150
+ def validate_yes_no_fields(cls, v):
151
+ if v is not None and v.upper() not in ['SI', 'NO', 'S', 'N']:
152
+ raise ValueError('Must be SI/NO or S/N')
153
+ return v
154
+
155
+ class InventarioCreate(InventarioBase):
156
+ """Schema for creating inventory item"""
157
+ pass
158
+
159
+ class InventarioUpdate(BaseModel):
160
+ """Schema for updating inventory item"""
161
+ sito: Optional[str] = Field(None, max_length=350)
162
+ numero_inventario: Optional[int] = Field(None, gt=0)
163
+ tipo_reperto: Optional[str] = Field(None, max_length=20)
164
+ # ... other optional fields
165
+
166
+ class InventarioResponse(InventarioBase, BaseSchema):
167
+ """Schema for inventory response"""
168
+ id_invmat: int = Field(..., description="Inventory ID")
169
+
170
+ # Pagination schemas
171
+
172
+ class PaginationParams(BaseModel):
173
+ """Pagination parameters"""
174
+ page: int = Field(1, ge=1, description="Page number")
175
+ size: int = Field(10, ge=1, le=100, description="Page size")
176
+
177
+ class PaginatedResponse(BaseModel):
178
+ """Paginated response wrapper"""
179
+ items: List[BaseModel]
180
+ total: int = Field(..., description="Total number of items")
181
+ page: int = Field(..., description="Current page")
182
+ size: int = Field(..., description="Page size")
183
+ pages: int = Field(..., description="Total number of pages")
184
+
185
+ class Config:
186
+ from_attributes = True
@@ -0,0 +1,220 @@
1
+ """
2
+ Site API endpoints
3
+ """
4
+
5
+ from typing import List, Optional
6
+ from fastapi import APIRouter, Depends, HTTPException, Query
7
+ from fastapi.responses import JSONResponse
8
+
9
+ from .schemas import SiteCreate, SiteUpdate, SiteResponse, PaginatedResponse
10
+ from .dependencies import get_site_service
11
+ from ..services.site_service import SiteService
12
+ from ..utils.exceptions import ValidationError, RecordNotFoundError, DuplicateRecordError
13
+
14
+ router = APIRouter()
15
+
16
+ @router.get("/", response_model=PaginatedResponse)
17
+ async def get_sites(
18
+ page: int = Query(1, ge=1, description="Page number"),
19
+ size: int = Query(10, ge=1, le=100, description="Page size"),
20
+ search: Optional[str] = Query(None, description="Search term"),
21
+ nazione: Optional[str] = Query(None, description="Filter by country"),
22
+ regione: Optional[str] = Query(None, description="Filter by region"),
23
+ comune: Optional[str] = Query(None, description="Filter by municipality"),
24
+ site_service: SiteService = Depends(get_site_service)
25
+ ):
26
+ """
27
+ Get paginated list of sites with optional filtering and search
28
+ """
29
+ try:
30
+ # Build filters
31
+ filters = {}
32
+ if nazione:
33
+ filters['nazione'] = nazione
34
+ if regione:
35
+ filters['regione'] = regione
36
+ if comune:
37
+ filters['comune'] = comune
38
+
39
+ # Get sites
40
+ if search:
41
+ sites = site_service.search_sites(search, page=page, size=size, filters=filters)
42
+ else:
43
+ sites = site_service.get_all_sites(page=page, size=size, filters=filters)
44
+
45
+ # Get total count for pagination
46
+ total = site_service.count_sites(filters=filters)
47
+
48
+ return PaginatedResponse(
49
+ items=[SiteResponse.from_orm(site) for site in sites],
50
+ total=total,
51
+ page=page,
52
+ size=size,
53
+ pages=(total + size - 1) // size
54
+ )
55
+
56
+ except Exception as e:
57
+ raise HTTPException(status_code=500, detail=str(e))
58
+
59
+ @router.get("/{site_id}", response_model=SiteResponse)
60
+ async def get_site(
61
+ site_id: int,
62
+ site_service: SiteService = Depends(get_site_service)
63
+ ):
64
+ """
65
+ Get site by ID
66
+ """
67
+ try:
68
+ site = site_service.get_site_by_id(site_id)
69
+ if not site:
70
+ raise HTTPException(status_code=404, detail="Site not found")
71
+ return SiteResponse.from_orm(site)
72
+
73
+ except RecordNotFoundError:
74
+ raise HTTPException(status_code=404, detail="Site not found")
75
+ except Exception as e:
76
+ raise HTTPException(status_code=500, detail=str(e))
77
+
78
+ @router.get("/by-name/{site_name}", response_model=SiteResponse)
79
+ async def get_site_by_name(
80
+ site_name: str,
81
+ site_service: SiteService = Depends(get_site_service)
82
+ ):
83
+ """
84
+ Get site by name
85
+ """
86
+ try:
87
+ site = site_service.get_site_by_name(site_name)
88
+ if not site:
89
+ raise HTTPException(status_code=404, detail="Site not found")
90
+ return SiteResponse.from_orm(site)
91
+
92
+ except RecordNotFoundError:
93
+ raise HTTPException(status_code=404, detail="Site not found")
94
+ except Exception as e:
95
+ raise HTTPException(status_code=500, detail=str(e))
96
+
97
+ @router.post("/", response_model=SiteResponse, status_code=201)
98
+ async def create_site(
99
+ site_data: SiteCreate,
100
+ site_service: SiteService = Depends(get_site_service)
101
+ ):
102
+ """
103
+ Create a new site
104
+ """
105
+ try:
106
+ site = site_service.create_site(site_data.dict())
107
+ return SiteResponse.from_orm(site)
108
+
109
+ except ValidationError as e:
110
+ raise HTTPException(status_code=400, detail=str(e))
111
+ except DuplicateRecordError as e:
112
+ raise HTTPException(status_code=409, detail=str(e))
113
+ except Exception as e:
114
+ raise HTTPException(status_code=500, detail=str(e))
115
+
116
+ @router.put("/{site_id}", response_model=SiteResponse)
117
+ async def update_site(
118
+ site_id: int,
119
+ site_data: SiteUpdate,
120
+ site_service: SiteService = Depends(get_site_service)
121
+ ):
122
+ """
123
+ Update an existing site
124
+ """
125
+ try:
126
+ # Only include non-None values in update
127
+ update_data = {k: v for k, v in site_data.dict().items() if v is not None}
128
+ site = site_service.update_site(site_id, update_data)
129
+ return SiteResponse.from_orm(site)
130
+
131
+ except RecordNotFoundError:
132
+ raise HTTPException(status_code=404, detail="Site not found")
133
+ except ValidationError as e:
134
+ raise HTTPException(status_code=400, detail=str(e))
135
+ except DuplicateRecordError as e:
136
+ raise HTTPException(status_code=409, detail=str(e))
137
+ except Exception as e:
138
+ raise HTTPException(status_code=500, detail=str(e))
139
+
140
+ @router.delete("/{site_id}")
141
+ async def delete_site(
142
+ site_id: int,
143
+ site_service: SiteService = Depends(get_site_service)
144
+ ):
145
+ """
146
+ Delete a site
147
+ """
148
+ try:
149
+ success = site_service.delete_site(site_id)
150
+ if success:
151
+ return JSONResponse(
152
+ status_code=200,
153
+ content={"message": "Site deleted successfully"}
154
+ )
155
+ else:
156
+ raise HTTPException(status_code=404, detail="Site not found")
157
+
158
+ except RecordNotFoundError:
159
+ raise HTTPException(status_code=404, detail="Site not found")
160
+ except Exception as e:
161
+ raise HTTPException(status_code=500, detail=str(e))
162
+
163
+ @router.get("/{site_id}/stats")
164
+ async def get_site_stats(
165
+ site_id: int,
166
+ site_service: SiteService = Depends(get_site_service)
167
+ ):
168
+ """
169
+ Get statistics for a site (US count, inventory count, etc.)
170
+ """
171
+ try:
172
+ stats = site_service.get_site_statistics(site_id)
173
+ return stats
174
+
175
+ except RecordNotFoundError:
176
+ raise HTTPException(status_code=404, detail="Site not found")
177
+ except Exception as e:
178
+ raise HTTPException(status_code=500, detail=str(e))
179
+
180
+ @router.get("/locations/countries")
181
+ async def get_countries(
182
+ site_service: SiteService = Depends(get_site_service)
183
+ ):
184
+ """
185
+ Get list of unique countries from sites
186
+ """
187
+ try:
188
+ countries = site_service.get_unique_countries()
189
+ return {"countries": countries}
190
+ except Exception as e:
191
+ raise HTTPException(status_code=500, detail=str(e))
192
+
193
+ @router.get("/locations/regions")
194
+ async def get_regions(
195
+ nazione: Optional[str] = Query(None, description="Filter by country"),
196
+ site_service: SiteService = Depends(get_site_service)
197
+ ):
198
+ """
199
+ Get list of unique regions, optionally filtered by country
200
+ """
201
+ try:
202
+ regions = site_service.get_unique_regions(nazione)
203
+ return {"regions": regions}
204
+ except Exception as e:
205
+ raise HTTPException(status_code=500, detail=str(e))
206
+
207
+ @router.get("/locations/municipalities")
208
+ async def get_municipalities(
209
+ nazione: Optional[str] = Query(None, description="Filter by country"),
210
+ regione: Optional[str] = Query(None, description="Filter by region"),
211
+ site_service: SiteService = Depends(get_site_service)
212
+ ):
213
+ """
214
+ Get list of unique municipalities, optionally filtered by country and region
215
+ """
216
+ try:
217
+ municipalities = site_service.get_unique_municipalities(nazione, regione)
218
+ return {"municipalities": municipalities}
219
+ except Exception as e:
220
+ raise HTTPException(status_code=500, detail=str(e))
@@ -0,0 +1,107 @@
1
+ """
2
+ US (Stratigraphic Unit) API endpoints
3
+ """
4
+
5
+ from typing import List, Optional
6
+ from fastapi import APIRouter, Depends, HTTPException, Query
7
+
8
+ from .schemas import USCreate, USUpdate, USResponse, PaginatedResponse
9
+ from .dependencies import get_us_service
10
+ from ..services.us_service import USService
11
+ from ..utils.exceptions import ValidationError, RecordNotFoundError
12
+
13
+ router = APIRouter()
14
+
15
+ @router.get("/", response_model=PaginatedResponse)
16
+ async def get_us_list(
17
+ page: int = Query(1, ge=1),
18
+ size: int = Query(10, ge=1, le=100),
19
+ sito: Optional[str] = Query(None, description="Filter by site"),
20
+ area: Optional[str] = Query(None, description="Filter by area"),
21
+ us_service: USService = Depends(get_us_service)
22
+ ):
23
+ """Get paginated list of stratigraphic units"""
24
+ try:
25
+ filters = {}
26
+ if sito:
27
+ filters['sito'] = sito
28
+ if area:
29
+ filters['area'] = area
30
+
31
+ us_list = us_service.get_all_us(page=page, size=size, filters=filters)
32
+ total = us_service.count_us(filters=filters)
33
+
34
+ return PaginatedResponse(
35
+ items=[USResponse.from_orm(us) for us in us_list],
36
+ total=total,
37
+ page=page,
38
+ size=size,
39
+ pages=(total + size - 1) // size
40
+ )
41
+ except Exception as e:
42
+ raise HTTPException(status_code=500, detail=str(e))
43
+
44
+ @router.get("/{us_id}", response_model=USResponse)
45
+ async def get_us(
46
+ us_id: int,
47
+ us_service: USService = Depends(get_us_service)
48
+ ):
49
+ """Get US by ID"""
50
+ try:
51
+ us = us_service.get_us_by_id(us_id)
52
+ if not us:
53
+ raise HTTPException(status_code=404, detail="US not found")
54
+ return USResponse.from_orm(us)
55
+ except RecordNotFoundError:
56
+ raise HTTPException(status_code=404, detail="US not found")
57
+ except Exception as e:
58
+ raise HTTPException(status_code=500, detail=str(e))
59
+
60
+ @router.post("/", response_model=USResponse, status_code=201)
61
+ async def create_us(
62
+ us_data: USCreate,
63
+ us_service: USService = Depends(get_us_service)
64
+ ):
65
+ """Create a new stratigraphic unit"""
66
+ try:
67
+ us = us_service.create_us(us_data.dict())
68
+ return USResponse.from_orm(us)
69
+ except ValidationError as e:
70
+ raise HTTPException(status_code=400, detail=str(e))
71
+ except Exception as e:
72
+ raise HTTPException(status_code=500, detail=str(e))
73
+
74
+ @router.put("/{us_id}", response_model=USResponse)
75
+ async def update_us(
76
+ us_id: int,
77
+ us_data: USUpdate,
78
+ us_service: USService = Depends(get_us_service)
79
+ ):
80
+ """Update an existing stratigraphic unit"""
81
+ try:
82
+ update_data = {k: v for k, v in us_data.dict().items() if v is not None}
83
+ us = us_service.update_us(us_id, update_data)
84
+ return USResponse.from_orm(us)
85
+ except RecordNotFoundError:
86
+ raise HTTPException(status_code=404, detail="US not found")
87
+ except ValidationError as e:
88
+ raise HTTPException(status_code=400, detail=str(e))
89
+ except Exception as e:
90
+ raise HTTPException(status_code=500, detail=str(e))
91
+
92
+ @router.delete("/{us_id}")
93
+ async def delete_us(
94
+ us_id: int,
95
+ us_service: USService = Depends(get_us_service)
96
+ ):
97
+ """Delete a stratigraphic unit"""
98
+ try:
99
+ success = us_service.delete_us(us_id)
100
+ if success:
101
+ return {"message": "US deleted successfully"}
102
+ else:
103
+ raise HTTPException(status_code=404, detail="US not found")
104
+ except RecordNotFoundError:
105
+ raise HTTPException(status_code=404, detail="US not found")
106
+ except Exception as e:
107
+ raise HTTPException(status_code=500, detail=str(e))
@@ -0,0 +1,7 @@
1
+ """
2
+ CLI commands for PyArchInit-Mini
3
+ """
4
+
5
+ from .export_import_cli import export_import
6
+
7
+ __all__ = ['export_import']