@open-mercato/core 0.6.8-develop.6925.1.cefa200fa4 → 0.6.8-develop.6930.1.1e5976efc3

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 (402) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/eudr_due_diligence_statement/index.js +47 -0
  3. package/dist/generated/entities/eudr_due_diligence_statement/index.js.map +7 -0
  4. package/dist/generated/entities/eudr_evidence_submission/index.js +51 -0
  5. package/dist/generated/entities/eudr_evidence_submission/index.js.map +7 -0
  6. package/dist/generated/entities/eudr_mitigation_action/index.js +31 -0
  7. package/dist/generated/entities/eudr_mitigation_action/index.js.map +7 -0
  8. package/dist/generated/entities/eudr_plot/index.js +39 -0
  9. package/dist/generated/entities/eudr_plot/index.js.map +7 -0
  10. package/dist/generated/entities/eudr_product_mapping/index.js +31 -0
  11. package/dist/generated/entities/eudr_product_mapping/index.js.map +7 -0
  12. package/dist/generated/entities/eudr_risk_assessment/index.js +35 -0
  13. package/dist/generated/entities/eudr_risk_assessment/index.js.map +7 -0
  14. package/dist/generated/entities.ids.generated.js +9 -0
  15. package/dist/generated/entities.ids.generated.js.map +2 -2
  16. package/dist/generated/entity-fields-registry.js +120 -0
  17. package/dist/generated/entity-fields-registry.js.map +2 -2
  18. package/dist/modules/attachments/fields/attachment.js +5 -1
  19. package/dist/modules/attachments/fields/attachment.js.map +2 -2
  20. package/dist/modules/attachments/lib/crud.js +3 -1
  21. package/dist/modules/attachments/lib/crud.js.map +2 -2
  22. package/dist/modules/eudr/acl.js +43 -0
  23. package/dist/modules/eudr/acl.js.map +7 -0
  24. package/dist/modules/eudr/ai-agents.js +205 -0
  25. package/dist/modules/eudr/ai-agents.js.map +7 -0
  26. package/dist/modules/eudr/ai-tools/compliance-pack.js +495 -0
  27. package/dist/modules/eudr/ai-tools/compliance-pack.js.map +7 -0
  28. package/dist/modules/eudr/ai-tools/types.js +10 -0
  29. package/dist/modules/eudr/ai-tools/types.js.map +7 -0
  30. package/dist/modules/eudr/ai-tools.js +10 -0
  31. package/dist/modules/eudr/ai-tools.js.map +7 -0
  32. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js +386 -0
  33. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js.map +7 -0
  34. package/dist/modules/eudr/api/evidence-submissions/route.js +318 -0
  35. package/dist/modules/eudr/api/evidence-submissions/route.js.map +7 -0
  36. package/dist/modules/eudr/api/mitigation-actions/route.js +249 -0
  37. package/dist/modules/eudr/api/mitigation-actions/route.js.map +7 -0
  38. package/dist/modules/eudr/api/openapi.js +27 -0
  39. package/dist/modules/eudr/api/openapi.js.map +7 -0
  40. package/dist/modules/eudr/api/plots/import/route.js +294 -0
  41. package/dist/modules/eudr/api/plots/import/route.js.map +7 -0
  42. package/dist/modules/eudr/api/plots/route.js +279 -0
  43. package/dist/modules/eudr/api/plots/route.js.map +7 -0
  44. package/dist/modules/eudr/api/product-mappings/route.js +257 -0
  45. package/dist/modules/eudr/api/product-mappings/route.js.map +7 -0
  46. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js +298 -0
  47. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js.map +7 -0
  48. package/dist/modules/eudr/api/product-mappings/suggestions/route.js +132 -0
  49. package/dist/modules/eudr/api/product-mappings/suggestions/route.js.map +7 -0
  50. package/dist/modules/eudr/api/reports/annual/route.js +266 -0
  51. package/dist/modules/eudr/api/reports/annual/route.js.map +7 -0
  52. package/dist/modules/eudr/api/risk-assessments/route.js +300 -0
  53. package/dist/modules/eudr/api/risk-assessments/route.js.map +7 -0
  54. package/dist/modules/eudr/api/statements/[id]/export/route.js +631 -0
  55. package/dist/modules/eudr/api/statements/[id]/export/route.js.map +7 -0
  56. package/dist/modules/eudr/api/statements/[id]/readiness/route.js +111 -0
  57. package/dist/modules/eudr/api/statements/[id]/readiness/route.js.map +7 -0
  58. package/dist/modules/eudr/api/statements/route.js +314 -0
  59. package/dist/modules/eudr/api/statements/route.js.map +7 -0
  60. package/dist/modules/eudr/api/suppliers/compliance/route.js +173 -0
  61. package/dist/modules/eudr/api/suppliers/compliance/route.js.map +7 -0
  62. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js +468 -0
  63. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.js.map +7 -0
  64. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js +16 -0
  65. package/dist/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.js.map +7 -0
  66. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js +351 -0
  67. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.js.map +7 -0
  68. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js +17 -0
  69. package/dist/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.js.map +7 -0
  70. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +313 -0
  71. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +7 -0
  72. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js +16 -0
  73. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.meta.js.map +7 -0
  74. package/dist/modules/eudr/backend/eudr/page.js +360 -0
  75. package/dist/modules/eudr/backend/eudr/page.js.map +7 -0
  76. package/dist/modules/eudr/backend/eudr/page.meta.js +16 -0
  77. package/dist/modules/eudr/backend/eudr/page.meta.js.map +7 -0
  78. package/dist/modules/eudr/backend/eudr/plots/[id]/page.js +346 -0
  79. package/dist/modules/eudr/backend/eudr/plots/[id]/page.js.map +7 -0
  80. package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js +16 -0
  81. package/dist/modules/eudr/backend/eudr/plots/[id]/page.meta.js.map +7 -0
  82. package/dist/modules/eudr/backend/eudr/plots/create/page.js +253 -0
  83. package/dist/modules/eudr/backend/eudr/plots/create/page.js.map +7 -0
  84. package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js +17 -0
  85. package/dist/modules/eudr/backend/eudr/plots/create/page.meta.js.map +7 -0
  86. package/dist/modules/eudr/backend/eudr/plots/page.js +386 -0
  87. package/dist/modules/eudr/backend/eudr/plots/page.js.map +7 -0
  88. package/dist/modules/eudr/backend/eudr/plots/page.meta.js +16 -0
  89. package/dist/modules/eudr/backend/eudr/plots/page.meta.js.map +7 -0
  90. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js +253 -0
  91. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.js.map +7 -0
  92. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js +16 -0
  93. package/dist/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.js.map +7 -0
  94. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js +174 -0
  95. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.js.map +7 -0
  96. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js +17 -0
  97. package/dist/modules/eudr/backend/eudr/product-mappings/create/page.meta.js.map +7 -0
  98. package/dist/modules/eudr/backend/eudr/product-mappings/page.js +306 -0
  99. package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +7 -0
  100. package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js +16 -0
  101. package/dist/modules/eudr/backend/eudr/product-mappings/page.meta.js.map +7 -0
  102. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js +335 -0
  103. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.js.map +7 -0
  104. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js +16 -0
  105. package/dist/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.js.map +7 -0
  106. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js +220 -0
  107. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.js.map +7 -0
  108. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js +17 -0
  109. package/dist/modules/eudr/backend/eudr/risk-assessments/create/page.meta.js.map +7 -0
  110. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +324 -0
  111. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +7 -0
  112. package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js +16 -0
  113. package/dist/modules/eudr/backend/eudr/risk-assessments/page.meta.js.map +7 -0
  114. package/dist/modules/eudr/backend/eudr/statements/[id]/page.js +648 -0
  115. package/dist/modules/eudr/backend/eudr/statements/[id]/page.js.map +7 -0
  116. package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js +16 -0
  117. package/dist/modules/eudr/backend/eudr/statements/[id]/page.meta.js.map +7 -0
  118. package/dist/modules/eudr/backend/eudr/statements/create/page.js +432 -0
  119. package/dist/modules/eudr/backend/eudr/statements/create/page.js.map +7 -0
  120. package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js +17 -0
  121. package/dist/modules/eudr/backend/eudr/statements/create/page.meta.js.map +7 -0
  122. package/dist/modules/eudr/backend/eudr/statements/page.js +309 -0
  123. package/dist/modules/eudr/backend/eudr/statements/page.js.map +7 -0
  124. package/dist/modules/eudr/backend/eudr/statements/page.meta.js +16 -0
  125. package/dist/modules/eudr/backend/eudr/statements/page.meta.js.map +7 -0
  126. package/dist/modules/eudr/ce.js +56 -0
  127. package/dist/modules/eudr/ce.js.map +7 -0
  128. package/dist/modules/eudr/commands/evidence-submissions.js +571 -0
  129. package/dist/modules/eudr/commands/evidence-submissions.js.map +7 -0
  130. package/dist/modules/eudr/commands/index.js +7 -0
  131. package/dist/modules/eudr/commands/index.js.map +7 -0
  132. package/dist/modules/eudr/commands/lifecycle-events.js +19 -0
  133. package/dist/modules/eudr/commands/lifecycle-events.js.map +7 -0
  134. package/dist/modules/eudr/commands/mitigation-actions.js +488 -0
  135. package/dist/modules/eudr/commands/mitigation-actions.js.map +7 -0
  136. package/dist/modules/eudr/commands/plots.js +517 -0
  137. package/dist/modules/eudr/commands/plots.js.map +7 -0
  138. package/dist/modules/eudr/commands/product-mappings.js +468 -0
  139. package/dist/modules/eudr/commands/product-mappings.js.map +7 -0
  140. package/dist/modules/eudr/commands/risk-assessments.js +599 -0
  141. package/dist/modules/eudr/commands/risk-assessments.js.map +7 -0
  142. package/dist/modules/eudr/commands/statements.js +747 -0
  143. package/dist/modules/eudr/commands/statements.js.map +7 -0
  144. package/dist/modules/eudr/components/CountrySelectField.js +64 -0
  145. package/dist/modules/eudr/components/CountrySelectField.js.map +7 -0
  146. package/dist/modules/eudr/components/GeometryInput.js +133 -0
  147. package/dist/modules/eudr/components/GeometryInput.js.map +7 -0
  148. package/dist/modules/eudr/components/MappingSuggestionsDialog.js +307 -0
  149. package/dist/modules/eudr/components/MappingSuggestionsDialog.js.map +7 -0
  150. package/dist/modules/eudr/components/MitigationActionsSection.js +345 -0
  151. package/dist/modules/eudr/components/MitigationActionsSection.js.map +7 -0
  152. package/dist/modules/eudr/components/OrderSelectField.js +88 -0
  153. package/dist/modules/eudr/components/OrderSelectField.js.map +7 -0
  154. package/dist/modules/eudr/components/PlotImportDialog.js +229 -0
  155. package/dist/modules/eudr/components/PlotImportDialog.js.map +7 -0
  156. package/dist/modules/eudr/components/PlotMapPreview.js +35 -0
  157. package/dist/modules/eudr/components/PlotMapPreview.js.map +7 -0
  158. package/dist/modules/eudr/components/PlotMapPreviewImpl.js +97 -0
  159. package/dist/modules/eudr/components/PlotMapPreviewImpl.js.map +7 -0
  160. package/dist/modules/eudr/components/PlotMultiSelectField.js +198 -0
  161. package/dist/modules/eudr/components/PlotMultiSelectField.js.map +7 -0
  162. package/dist/modules/eudr/components/RiskCriteriaField.js +128 -0
  163. package/dist/modules/eudr/components/RiskCriteriaField.js.map +7 -0
  164. package/dist/modules/eudr/components/StatementLifecycleBar.js +274 -0
  165. package/dist/modules/eudr/components/StatementLifecycleBar.js.map +7 -0
  166. package/dist/modules/eudr/components/StatementReadinessChecklist.js +56 -0
  167. package/dist/modules/eudr/components/StatementReadinessChecklist.js.map +7 -0
  168. package/dist/modules/eudr/components/StatementRiskSection.js +179 -0
  169. package/dist/modules/eudr/components/StatementRiskSection.js.map +7 -0
  170. package/dist/modules/eudr/components/crudErrorI18n.js +31 -0
  171. package/dist/modules/eudr/components/crudErrorI18n.js.map +7 -0
  172. package/dist/modules/eudr/components/formConfig.js +593 -0
  173. package/dist/modules/eudr/components/formConfig.js.map +7 -0
  174. package/dist/modules/eudr/components/plotForm.js +68 -0
  175. package/dist/modules/eudr/components/plotForm.js.map +7 -0
  176. package/dist/modules/eudr/data/enrichers.js +62 -0
  177. package/dist/modules/eudr/data/enrichers.js.map +7 -0
  178. package/dist/modules/eudr/data/entities.js +437 -0
  179. package/dist/modules/eudr/data/entities.js.map +7 -0
  180. package/dist/modules/eudr/data/validators.js +271 -0
  181. package/dist/modules/eudr/data/validators.js.map +7 -0
  182. package/dist/modules/eudr/encryption.js +33 -0
  183. package/dist/modules/eudr/encryption.js.map +7 -0
  184. package/dist/modules/eudr/events.js +38 -0
  185. package/dist/modules/eudr/events.js.map +7 -0
  186. package/dist/modules/eudr/index.js +15 -0
  187. package/dist/modules/eudr/index.js.map +7 -0
  188. package/dist/modules/eudr/lib/annual-report.js +104 -0
  189. package/dist/modules/eudr/lib/annual-report.js.map +7 -0
  190. package/dist/modules/eudr/lib/completeness.js +64 -0
  191. package/dist/modules/eudr/lib/completeness.js.map +7 -0
  192. package/dist/modules/eudr/lib/detail-read-scope.js +16 -0
  193. package/dist/modules/eudr/lib/detail-read-scope.js.map +7 -0
  194. package/dist/modules/eudr/lib/geometry.js +142 -0
  195. package/dist/modules/eudr/lib/geometry.js.map +7 -0
  196. package/dist/modules/eudr/lib/notifications.js +56 -0
  197. package/dist/modules/eudr/lib/notifications.js.map +7 -0
  198. package/dist/modules/eudr/lib/plural.js +26 -0
  199. package/dist/modules/eudr/lib/plural.js.map +7 -0
  200. package/dist/modules/eudr/lib/reference-data.js +240 -0
  201. package/dist/modules/eudr/lib/reference-data.js.map +7 -0
  202. package/dist/modules/eudr/lib/species.js +10 -0
  203. package/dist/modules/eudr/lib/species.js.map +7 -0
  204. package/dist/modules/eudr/lib/statement-lifecycle.js +84 -0
  205. package/dist/modules/eudr/lib/statement-lifecycle.js.map +7 -0
  206. package/dist/modules/eudr/lib/statement-seeding.js +49 -0
  207. package/dist/modules/eudr/lib/statement-seeding.js.map +7 -0
  208. package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js +15 -0
  209. package/dist/modules/eudr/migrations/Migration20260706102002_eudr.js.map +7 -0
  210. package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js +24 -0
  211. package/dist/modules/eudr/migrations/Migration20260706152612_eudr.js.map +7 -0
  212. package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js +15 -0
  213. package/dist/modules/eudr/migrations/Migration20260722100000_eudr.js.map +7 -0
  214. package/dist/modules/eudr/notifications.js +58 -0
  215. package/dist/modules/eudr/notifications.js.map +7 -0
  216. package/dist/modules/eudr/search.js +186 -0
  217. package/dist/modules/eudr/search.js.map +7 -0
  218. package/dist/modules/eudr/setup.js +12 -0
  219. package/dist/modules/eudr/setup.js.map +7 -0
  220. package/dist/modules/eudr/subscribers/notify-mitigation-completed.js +34 -0
  221. package/dist/modules/eudr/subscribers/notify-mitigation-completed.js.map +7 -0
  222. package/dist/modules/eudr/subscribers/notify-risk-concluded.js +35 -0
  223. package/dist/modules/eudr/subscribers/notify-risk-concluded.js.map +7 -0
  224. package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js +37 -0
  225. package/dist/modules/eudr/subscribers/notify-statement-reference-issued.js.map +7 -0
  226. package/dist/modules/eudr/subscribers/notify-statement-submitted.js +34 -0
  227. package/dist/modules/eudr/subscribers/notify-statement-submitted.js.map +7 -0
  228. package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js +34 -0
  229. package/dist/modules/eudr/subscribers/notify-statement-withdrawn.js.map +7 -0
  230. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js +124 -0
  231. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-created.js.map +7 -0
  232. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js +22 -0
  233. package/dist/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.js.map +7 -0
  234. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js +203 -0
  235. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.client.js.map +7 -0
  236. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js +23 -0
  237. package/dist/modules/eudr/widgets/dashboard/compliance-overview/widget.js.map +7 -0
  238. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js +19 -0
  239. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.client.js.map +7 -0
  240. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js +31 -0
  241. package/dist/modules/eudr/widgets/injection/eudr-product-column/widget.js.map +7 -0
  242. package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js +100 -0
  243. package/dist/modules/eudr/widgets/injection/order-compliance/widget.client.js.map +7 -0
  244. package/dist/modules/eudr/widgets/injection/order-compliance/widget.js +17 -0
  245. package/dist/modules/eudr/widgets/injection/order-compliance/widget.js.map +7 -0
  246. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js +116 -0
  247. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.client.js.map +7 -0
  248. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js +17 -0
  249. package/dist/modules/eudr/widgets/injection/supplier-compliance/widget.js.map +7 -0
  250. package/dist/modules/eudr/widgets/injection-table.js +32 -0
  251. package/dist/modules/eudr/widgets/injection-table.js.map +7 -0
  252. package/dist/modules/notifications/lib/notificationService.js +67 -3
  253. package/dist/modules/notifications/lib/notificationService.js.map +2 -2
  254. package/dist/modules/query_index/lib/engine.js +121 -48
  255. package/dist/modules/query_index/lib/engine.js.map +2 -2
  256. package/dist/modules/sales/api/documents/factory.js +17 -0
  257. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  258. package/dist/modules/sales/commands/documents.js +32 -18
  259. package/dist/modules/sales/commands/documents.js.map +2 -2
  260. package/dist/modules/sales/data/entities.js +1 -0
  261. package/dist/modules/sales/data/entities.js.map +2 -2
  262. package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js +17 -0
  263. package/dist/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.js.map +7 -0
  264. package/generated/entities/eudr_due_diligence_statement/index.ts +22 -0
  265. package/generated/entities/eudr_evidence_submission/index.ts +24 -0
  266. package/generated/entities/eudr_mitigation_action/index.ts +14 -0
  267. package/generated/entities/eudr_plot/index.ts +18 -0
  268. package/generated/entities/eudr_product_mapping/index.ts +14 -0
  269. package/generated/entities/eudr_risk_assessment/index.ts +16 -0
  270. package/generated/entities.ids.generated.ts +9 -0
  271. package/generated/entity-fields-registry.ts +120 -0
  272. package/package.json +7 -7
  273. package/src/modules/attachments/fields/attachment.tsx +5 -0
  274. package/src/modules/attachments/lib/crud.ts +2 -0
  275. package/src/modules/eudr/acl.ts +39 -0
  276. package/src/modules/eudr/ai-agents.ts +258 -0
  277. package/src/modules/eudr/ai-tools/compliance-pack.ts +618 -0
  278. package/src/modules/eudr/ai-tools/types.ts +44 -0
  279. package/src/modules/eudr/ai-tools.ts +15 -0
  280. package/src/modules/eudr/api/dashboard/widgets/compliance-overview/route.ts +481 -0
  281. package/src/modules/eudr/api/evidence-submissions/route.ts +335 -0
  282. package/src/modules/eudr/api/mitigation-actions/route.ts +263 -0
  283. package/src/modules/eudr/api/openapi.ts +28 -0
  284. package/src/modules/eudr/api/plots/import/route.ts +369 -0
  285. package/src/modules/eudr/api/plots/route.ts +296 -0
  286. package/src/modules/eudr/api/product-mappings/route.ts +269 -0
  287. package/src/modules/eudr/api/product-mappings/suggestions/apply/route.ts +382 -0
  288. package/src/modules/eudr/api/product-mappings/suggestions/route.ts +169 -0
  289. package/src/modules/eudr/api/reports/annual/route.ts +457 -0
  290. package/src/modules/eudr/api/risk-assessments/route.ts +323 -0
  291. package/src/modules/eudr/api/statements/[id]/export/route.ts +713 -0
  292. package/src/modules/eudr/api/statements/[id]/readiness/route.ts +129 -0
  293. package/src/modules/eudr/api/statements/route.ts +329 -0
  294. package/src/modules/eudr/api/suppliers/compliance/route.ts +241 -0
  295. package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.meta.ts +12 -0
  296. package/src/modules/eudr/backend/eudr/evidence-submissions/[id]/page.tsx +545 -0
  297. package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.meta.ts +13 -0
  298. package/src/modules/eudr/backend/eudr/evidence-submissions/create/page.tsx +383 -0
  299. package/src/modules/eudr/backend/eudr/evidence-submissions/page.meta.ts +12 -0
  300. package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +379 -0
  301. package/src/modules/eudr/backend/eudr/page.meta.ts +12 -0
  302. package/src/modules/eudr/backend/eudr/page.tsx +477 -0
  303. package/src/modules/eudr/backend/eudr/plots/[id]/page.meta.ts +12 -0
  304. package/src/modules/eudr/backend/eudr/plots/[id]/page.tsx +404 -0
  305. package/src/modules/eudr/backend/eudr/plots/create/page.meta.ts +13 -0
  306. package/src/modules/eudr/backend/eudr/plots/create/page.tsx +267 -0
  307. package/src/modules/eudr/backend/eudr/plots/page.meta.ts +12 -0
  308. package/src/modules/eudr/backend/eudr/plots/page.tsx +442 -0
  309. package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.meta.ts +12 -0
  310. package/src/modules/eudr/backend/eudr/product-mappings/[id]/page.tsx +311 -0
  311. package/src/modules/eudr/backend/eudr/product-mappings/create/page.meta.ts +13 -0
  312. package/src/modules/eudr/backend/eudr/product-mappings/create/page.tsx +190 -0
  313. package/src/modules/eudr/backend/eudr/product-mappings/page.meta.ts +12 -0
  314. package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +344 -0
  315. package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.meta.ts +12 -0
  316. package/src/modules/eudr/backend/eudr/risk-assessments/[id]/page.tsx +421 -0
  317. package/src/modules/eudr/backend/eudr/risk-assessments/create/page.meta.ts +13 -0
  318. package/src/modules/eudr/backend/eudr/risk-assessments/create/page.tsx +247 -0
  319. package/src/modules/eudr/backend/eudr/risk-assessments/page.meta.ts +12 -0
  320. package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +383 -0
  321. package/src/modules/eudr/backend/eudr/statements/[id]/page.meta.ts +12 -0
  322. package/src/modules/eudr/backend/eudr/statements/[id]/page.tsx +777 -0
  323. package/src/modules/eudr/backend/eudr/statements/create/page.meta.ts +13 -0
  324. package/src/modules/eudr/backend/eudr/statements/create/page.tsx +511 -0
  325. package/src/modules/eudr/backend/eudr/statements/page.meta.ts +12 -0
  326. package/src/modules/eudr/backend/eudr/statements/page.tsx +372 -0
  327. package/src/modules/eudr/ce.ts +52 -0
  328. package/src/modules/eudr/commands/evidence-submissions.ts +699 -0
  329. package/src/modules/eudr/commands/index.ts +6 -0
  330. package/src/modules/eudr/commands/lifecycle-events.ts +28 -0
  331. package/src/modules/eudr/commands/mitigation-actions.ts +574 -0
  332. package/src/modules/eudr/commands/plots.ts +627 -0
  333. package/src/modules/eudr/commands/product-mappings.ts +556 -0
  334. package/src/modules/eudr/commands/risk-assessments.ts +728 -0
  335. package/src/modules/eudr/commands/statements.ts +933 -0
  336. package/src/modules/eudr/components/CountrySelectField.tsx +77 -0
  337. package/src/modules/eudr/components/GeometryInput.tsx +170 -0
  338. package/src/modules/eudr/components/MappingSuggestionsDialog.tsx +385 -0
  339. package/src/modules/eudr/components/MitigationActionsSection.tsx +417 -0
  340. package/src/modules/eudr/components/OrderSelectField.tsx +116 -0
  341. package/src/modules/eudr/components/PlotImportDialog.tsx +277 -0
  342. package/src/modules/eudr/components/PlotMapPreview.tsx +46 -0
  343. package/src/modules/eudr/components/PlotMapPreviewImpl.tsx +111 -0
  344. package/src/modules/eudr/components/PlotMultiSelectField.tsx +238 -0
  345. package/src/modules/eudr/components/RiskCriteriaField.tsx +173 -0
  346. package/src/modules/eudr/components/StatementLifecycleBar.tsx +363 -0
  347. package/src/modules/eudr/components/StatementReadinessChecklist.tsx +82 -0
  348. package/src/modules/eudr/components/StatementRiskSection.tsx +242 -0
  349. package/src/modules/eudr/components/crudErrorI18n.ts +36 -0
  350. package/src/modules/eudr/components/formConfig.tsx +717 -0
  351. package/src/modules/eudr/components/plotForm.ts +75 -0
  352. package/src/modules/eudr/data/enrichers.ts +82 -0
  353. package/src/modules/eudr/data/entities.ts +369 -0
  354. package/src/modules/eudr/data/validators.ts +357 -0
  355. package/src/modules/eudr/encryption.ts +31 -0
  356. package/src/modules/eudr/events.ts +38 -0
  357. package/src/modules/eudr/i18n/de.json +747 -0
  358. package/src/modules/eudr/i18n/en.json +747 -0
  359. package/src/modules/eudr/i18n/es.json +747 -0
  360. package/src/modules/eudr/i18n/ko.json +747 -0
  361. package/src/modules/eudr/i18n/pl.json +747 -0
  362. package/src/modules/eudr/index.ts +13 -0
  363. package/src/modules/eudr/lib/annual-report.ts +120 -0
  364. package/src/modules/eudr/lib/completeness.ts +90 -0
  365. package/src/modules/eudr/lib/detail-read-scope.ts +44 -0
  366. package/src/modules/eudr/lib/geometry.ts +191 -0
  367. package/src/modules/eudr/lib/notifications.ts +85 -0
  368. package/src/modules/eudr/lib/plural.ts +36 -0
  369. package/src/modules/eudr/lib/reference-data.ts +128 -0
  370. package/src/modules/eudr/lib/species.ts +12 -0
  371. package/src/modules/eudr/lib/statement-lifecycle.ts +109 -0
  372. package/src/modules/eudr/lib/statement-seeding.ts +86 -0
  373. package/src/modules/eudr/migrations/.snapshot-open-mercato.json +2046 -0
  374. package/src/modules/eudr/migrations/Migration20260706102002_eudr.ts +16 -0
  375. package/src/modules/eudr/migrations/Migration20260706152612_eudr.ts +30 -0
  376. package/src/modules/eudr/migrations/Migration20260722100000_eudr.ts +17 -0
  377. package/src/modules/eudr/notifications.ts +56 -0
  378. package/src/modules/eudr/search.ts +212 -0
  379. package/src/modules/eudr/setup.ts +10 -0
  380. package/src/modules/eudr/subscribers/notify-mitigation-completed.ts +56 -0
  381. package/src/modules/eudr/subscribers/notify-risk-concluded.ts +58 -0
  382. package/src/modules/eudr/subscribers/notify-statement-reference-issued.ts +59 -0
  383. package/src/modules/eudr/subscribers/notify-statement-submitted.ts +49 -0
  384. package/src/modules/eudr/subscribers/notify-statement-withdrawn.ts +49 -0
  385. package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-created.ts +189 -0
  386. package/src/modules/eudr/subscribers/recompute-completeness-on-attachment-deleted.ts +31 -0
  387. package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.client.tsx +271 -0
  388. package/src/modules/eudr/widgets/dashboard/compliance-overview/widget.ts +24 -0
  389. package/src/modules/eudr/widgets/injection/eudr-product-column/widget.client.tsx +37 -0
  390. package/src/modules/eudr/widgets/injection/eudr-product-column/widget.ts +30 -0
  391. package/src/modules/eudr/widgets/injection/order-compliance/widget.client.tsx +131 -0
  392. package/src/modules/eudr/widgets/injection/order-compliance/widget.ts +16 -0
  393. package/src/modules/eudr/widgets/injection/supplier-compliance/widget.client.tsx +168 -0
  394. package/src/modules/eudr/widgets/injection/supplier-compliance/widget.ts +16 -0
  395. package/src/modules/eudr/widgets/injection-table.ts +31 -0
  396. package/src/modules/notifications/lib/notificationService.ts +83 -4
  397. package/src/modules/query_index/lib/engine.ts +139 -51
  398. package/src/modules/sales/api/documents/factory.ts +29 -0
  399. package/src/modules/sales/commands/documents.ts +65 -18
  400. package/src/modules/sales/data/entities.ts +1 -0
  401. package/src/modules/sales/migrations/.snapshot-open-mercato.json +10 -0
  402. package/src/modules/sales/migrations/Migration20260806120000_sales_tag_assignment_document_idx.ts +59 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/eudr/lib/completeness.ts"],
4
+ "sourcesContent": ["import { GEOJSON_TYPES } from '../data/validators'\n\nexport const COMPLETENESS_DIMENSIONS = ['origin_country', 'geolocation', 'quantity', 'harvest_period', 'producer', 'documents'] as const\nexport const REQUIRED_DIMENSIONS = COMPLETENESS_DIMENSIONS\nexport type CompletenessDimension = (typeof COMPLETENESS_DIMENSIONS)[number]\n\nexport type CompletenessInput = {\n originCountry?: string | null\n geolocation?: unknown\n quantityKg?: string | number | null\n harvestFrom?: Date | string | null\n harvestTo?: Date | string | null\n producerName?: string | null\n attachmentIds?: string[] | null\n}\n\nexport type CompletenessContext = {\n linkedAttachmentCount?: number\n activePlotCount?: number\n}\n\nexport type CompletenessResult = { score: number; missingFields: CompletenessDimension[] }\n\nfunction isOriginCountryComplete(value: string | null | undefined): boolean {\n return typeof value === 'string' && /^[A-Za-z]{2}$/.test(value.trim())\n}\n\nfunction isGeolocationComplete(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false\n const candidate = value as { type?: unknown }\n return typeof candidate.type === 'string' && GEOJSON_TYPES.includes(candidate.type as (typeof GEOJSON_TYPES)[number])\n}\n\nfunction isQuantityComplete(value: string | number | null | undefined): boolean {\n if (typeof value !== 'string' && typeof value !== 'number') return false\n const quantity = Number(value)\n return Number.isFinite(quantity) && quantity > 0\n}\n\nfunction parseDate(value: Date | string | null | undefined): Date | null {\n if (value == null) return null\n const date = value instanceof Date ? value : new Date(value)\n return Number.isNaN(date.getTime()) ? null : date\n}\n\nfunction isHarvestPeriodComplete(harvestFrom: Date | string | null | undefined, harvestTo: Date | string | null | undefined): boolean {\n const parsedHarvestFrom = parseDate(harvestFrom)\n const parsedHarvestTo = parseDate(harvestTo)\n return parsedHarvestFrom !== null && parsedHarvestTo !== null && parsedHarvestFrom <= parsedHarvestTo\n}\n\nfunction isProducerComplete(value: string | null | undefined): boolean {\n return typeof value === 'string' && value.trim().length > 0\n}\n\nfunction isDocumentsComplete(value: string[] | null | undefined): boolean {\n return Array.isArray(value) && value.length >= 1\n}\n\nexport function computeCompleteness(input: CompletenessInput, context: CompletenessContext = {}): CompletenessResult {\n const completionByDimension: Record<CompletenessDimension, boolean> = {\n origin_country: isOriginCountryComplete(input.originCountry),\n geolocation: isGeolocationComplete(input.geolocation) || (context.activePlotCount ?? 0) > 0,\n quantity: isQuantityComplete(input.quantityKg),\n harvest_period: isHarvestPeriodComplete(input.harvestFrom, input.harvestTo),\n producer: isProducerComplete(input.producerName),\n documents: isDocumentsComplete(input.attachmentIds) || (context.linkedAttachmentCount ?? 0) > 0,\n }\n\n const missingFields = COMPLETENESS_DIMENSIONS.filter((dimension) => !completionByDimension[dimension])\n const metCount = COMPLETENESS_DIMENSIONS.length - missingFields.length\n const score = Math.round((metCount / COMPLETENESS_DIMENSIONS.length) * 100)\n\n return { score, missingFields }\n}\n\nexport function computeSubmissionCompleteness(input: CompletenessInput, context?: CompletenessContext): CompletenessResult {\n return computeCompleteness(input, context)\n}\n\nexport const HARVEST_CUTOFF_DATE = new Date('2020-12-31T23:59:59.999Z')\n\nexport function computeHarvestCutoffWarning(\n harvestFrom: Date | string | null | undefined,\n harvestTo: Date | string | null | undefined,\n): 'harvest_before_cutoff' | null {\n const windowEnd = parseDate(harvestTo) ?? parseDate(harvestFrom)\n if (!windowEnd) return null\n return windowEnd.getTime() <= HARVEST_CUTOFF_DATE.getTime() ? 'harvest_before_cutoff' : null\n}\n"],
5
+ "mappings": "AAAA,SAAS,qBAAqB;AAEvB,MAAM,0BAA0B,CAAC,kBAAkB,eAAe,YAAY,kBAAkB,YAAY,WAAW;AACvH,MAAM,sBAAsB;AAoBnC,SAAS,wBAAwB,OAA2C;AAC1E,SAAO,OAAO,UAAU,YAAY,gBAAgB,KAAK,MAAM,KAAK,CAAC;AACvE;AAEA,SAAS,sBAAsB,OAAyB;AACtD,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,QAAM,YAAY;AAClB,SAAO,OAAO,UAAU,SAAS,YAAY,cAAc,SAAS,UAAU,IAAsC;AACtH;AAEA,SAAS,mBAAmB,OAAoD;AAC9E,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,SAAU,QAAO;AACnE,QAAM,WAAW,OAAO,KAAK;AAC7B,SAAO,OAAO,SAAS,QAAQ,KAAK,WAAW;AACjD;AAEA,SAAS,UAAU,OAAsD;AACvE,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,OAAO,iBAAiB,OAAO,QAAQ,IAAI,KAAK,KAAK;AAC3D,SAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,IAAI,OAAO;AAC/C;AAEA,SAAS,wBAAwB,aAA+C,WAAsD;AACpI,QAAM,oBAAoB,UAAU,WAAW;AAC/C,QAAM,kBAAkB,UAAU,SAAS;AAC3C,SAAO,sBAAsB,QAAQ,oBAAoB,QAAQ,qBAAqB;AACxF;AAEA,SAAS,mBAAmB,OAA2C;AACrE,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS;AAC5D;AAEA,SAAS,oBAAoB,OAA6C;AACxE,SAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,UAAU;AACjD;AAEO,SAAS,oBAAoB,OAA0B,UAA+B,CAAC,GAAuB;AACnH,QAAM,wBAAgE;AAAA,IACpE,gBAAgB,wBAAwB,MAAM,aAAa;AAAA,IAC3D,aAAa,sBAAsB,MAAM,WAAW,MAAM,QAAQ,mBAAmB,KAAK;AAAA,IAC1F,UAAU,mBAAmB,MAAM,UAAU;AAAA,IAC7C,gBAAgB,wBAAwB,MAAM,aAAa,MAAM,SAAS;AAAA,IAC1E,UAAU,mBAAmB,MAAM,YAAY;AAAA,IAC/C,WAAW,oBAAoB,MAAM,aAAa,MAAM,QAAQ,yBAAyB,KAAK;AAAA,EAChG;AAEA,QAAM,gBAAgB,wBAAwB,OAAO,CAAC,cAAc,CAAC,sBAAsB,SAAS,CAAC;AACrG,QAAM,WAAW,wBAAwB,SAAS,cAAc;AAChE,QAAM,QAAQ,KAAK,MAAO,WAAW,wBAAwB,SAAU,GAAG;AAE1E,SAAO,EAAE,OAAO,cAAc;AAChC;AAEO,SAAS,8BAA8B,OAA0B,SAAmD;AACzH,SAAO,oBAAoB,OAAO,OAAO;AAC3C;AAEO,MAAM,sBAAsB,oBAAI,KAAK,0BAA0B;AAE/D,SAAS,4BACd,aACA,WACgC;AAChC,QAAM,YAAY,UAAU,SAAS,KAAK,UAAU,WAAW;AAC/D,MAAI,CAAC,UAAW,QAAO;AACvB,SAAO,UAAU,QAAQ,KAAK,oBAAoB,QAAQ,IAAI,0BAA0B;AAC1F;",
6
+ "names": []
7
+ }
@@ -0,0 +1,16 @@
1
+ function resolveDetailReadScope(ctx) {
2
+ const tenantId = ctx.auth?.tenantId ?? null;
3
+ if (!tenantId) return null;
4
+ const scopedOrganizationIds = Array.isArray(ctx.organizationIds) && ctx.organizationIds.length ? Array.from(new Set(ctx.organizationIds)) : null;
5
+ const singleOrganizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null;
6
+ if (!scopedOrganizationIds && !singleOrganizationId) return null;
7
+ return {
8
+ tenantId,
9
+ organizationFilter: scopedOrganizationIds ? { $in: scopedOrganizationIds } : singleOrganizationId,
10
+ decryptionOrganizationId: singleOrganizationId
11
+ };
12
+ }
13
+ export {
14
+ resolveDetailReadScope
15
+ };
16
+ //# sourceMappingURL=detail-read-scope.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/eudr/lib/detail-read-scope.ts"],
4
+ "sourcesContent": ["export type DetailReadScope = {\n tenantId: string\n /** Matches the organization scope the list query itself used. */\n organizationFilter: string | { $in: string[] }\n /**\n * Fallback organization for decryption only. `decryptEntitiesWithFallbackScope`\n * prefers each record's own tenant/organization and consults this only when the\n * record carries none, so a single value stays correct for multi-org reads.\n */\n decryptionOrganizationId: string | null\n}\n\ntype DetailReadScopeContext = {\n auth?: { tenantId?: string | null; orgId?: string | null } | null\n organizationIds?: string[] | null\n selectedOrganizationId?: string | null\n}\n\n/**\n * Resolves the scope for an `afterList` detail re-fetch (the decryption pass).\n *\n * The list query is scoped by the full `organizationIds` array, so re-fetching by\n * a single organization silently drops decrypted fields for a multi-org user who\n * has not selected one. Returns null when no scope can be established, so callers\n * fail closed rather than reading across the tenant.\n */\nexport function resolveDetailReadScope(ctx: DetailReadScopeContext): DetailReadScope | null {\n const tenantId = ctx.auth?.tenantId ?? null\n if (!tenantId) return null\n\n const scopedOrganizationIds = Array.isArray(ctx.organizationIds) && ctx.organizationIds.length\n ? Array.from(new Set(ctx.organizationIds))\n : null\n const singleOrganizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n if (!scopedOrganizationIds && !singleOrganizationId) return null\n\n return {\n tenantId,\n organizationFilter: scopedOrganizationIds\n ? { $in: scopedOrganizationIds }\n : (singleOrganizationId as string),\n decryptionOrganizationId: singleOrganizationId,\n }\n}\n"],
5
+ "mappings": "AA0BO,SAAS,uBAAuB,KAAqD;AAC1F,QAAM,WAAW,IAAI,MAAM,YAAY;AACvC,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,wBAAwB,MAAM,QAAQ,IAAI,eAAe,KAAK,IAAI,gBAAgB,SACpF,MAAM,KAAK,IAAI,IAAI,IAAI,eAAe,CAAC,IACvC;AACJ,QAAM,uBAAuB,IAAI,0BAA0B,IAAI,MAAM,SAAS;AAC9E,MAAI,CAAC,yBAAyB,CAAC,qBAAsB,QAAO;AAE5D,SAAO;AAAA,IACL;AAAA,IACA,oBAAoB,wBAChB,EAAE,KAAK,sBAAsB,IAC5B;AAAA,IACL,0BAA0B;AAAA,EAC5B;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,142 @@
1
+ const MAX_GEOMETRY_SIZE = 262144;
2
+ const MAX_IMPORT_SIZE = 1048576;
3
+ const MAX_FEATURE_COLLECTION_FEATURES = 500;
4
+ const EARTH_RADIUS_METERS = 63710088e-1;
5
+ const POINT_MAX_AREA_HA = 4;
6
+ function isRecord(value) {
7
+ return value !== null && typeof value === "object" && !Array.isArray(value);
8
+ }
9
+ function serializedLength(value) {
10
+ try {
11
+ const serialized = JSON.stringify(value);
12
+ return typeof serialized === "string" ? serialized.length : null;
13
+ } catch {
14
+ return null;
15
+ }
16
+ }
17
+ function decimalPlaces(value) {
18
+ const decimal = String(value).split(/[eE]/)[0]?.split(".")[1];
19
+ return decimal?.length ?? 0;
20
+ }
21
+ function validatePosition(input) {
22
+ if (!Array.isArray(input) || input.length < 2) return { ok: false, errorKey: "geometryOutOfRange" };
23
+ const [longitude, latitude] = input;
24
+ if (typeof longitude !== "number" || typeof latitude !== "number") return { ok: false, errorKey: "geometryOutOfRange" };
25
+ if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) return { ok: false, errorKey: "geometryOutOfRange" };
26
+ if (longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90) return { ok: false, errorKey: "geometryOutOfRange" };
27
+ return {
28
+ ok: true,
29
+ position: [longitude, latitude],
30
+ lowPrecision: decimalPlaces(longitude) < 6 || decimalPlaces(latitude) < 6
31
+ };
32
+ }
33
+ function positionsEqual(left, right) {
34
+ return left[0] === right[0] && left[1] === right[1];
35
+ }
36
+ function validateRing(input) {
37
+ if (!Array.isArray(input)) return { ok: false, errorKey: "geometryInvalid" };
38
+ if (input.length < 4) return { ok: false, errorKey: "geometryRingNotClosed" };
39
+ const ring = [];
40
+ let lowPrecision = false;
41
+ for (const candidate of input) {
42
+ const result = validatePosition(candidate);
43
+ if (!result.ok) return result;
44
+ ring.push(result.position);
45
+ lowPrecision = lowPrecision || result.lowPrecision;
46
+ }
47
+ if (!positionsEqual(ring[0], ring[ring.length - 1])) return { ok: false, errorKey: "geometryRingNotClosed" };
48
+ return { ok: true, ring, lowPrecision };
49
+ }
50
+ function validatePolygonCoordinates(input) {
51
+ if (!Array.isArray(input) || input.length === 0) return { ok: false, errorKey: "geometryInvalid" };
52
+ const rings = [];
53
+ let lowPrecision = false;
54
+ for (const candidate of input) {
55
+ const result = validateRing(candidate);
56
+ if (!result.ok) return result;
57
+ rings.push(result.ring);
58
+ lowPrecision = lowPrecision || result.lowPrecision;
59
+ }
60
+ return { ok: true, rings, lowPrecision };
61
+ }
62
+ function validateGeometry(input) {
63
+ if (!isRecord(input) || typeof input.type !== "string") return { ok: false, errorKey: "geometryInvalid" };
64
+ if (input.type === "Point") {
65
+ const result = validatePosition(input.coordinates);
66
+ if (!result.ok) return result;
67
+ return { ok: true, geometry: { type: "Point", coordinates: result.position }, lowPrecision: result.lowPrecision };
68
+ }
69
+ if (input.type === "Polygon") {
70
+ const result = validatePolygonCoordinates(input.coordinates);
71
+ if (!result.ok) return result;
72
+ return { ok: true, geometry: { type: "Polygon", coordinates: result.rings }, lowPrecision: result.lowPrecision };
73
+ }
74
+ if (input.type === "MultiPolygon") {
75
+ if (!Array.isArray(input.coordinates) || input.coordinates.length === 0) return { ok: false, errorKey: "geometryInvalid" };
76
+ const polygons = [];
77
+ let lowPrecision = false;
78
+ for (const candidate of input.coordinates) {
79
+ const result = validatePolygonCoordinates(candidate);
80
+ if (!result.ok) return result;
81
+ polygons.push(result.rings);
82
+ lowPrecision = lowPrecision || result.lowPrecision;
83
+ }
84
+ return { ok: true, geometry: { type: "MultiPolygon", coordinates: polygons }, lowPrecision };
85
+ }
86
+ return { ok: false, errorKey: "geometryInvalid" };
87
+ }
88
+ function toRadians(value) {
89
+ return value * Math.PI / 180;
90
+ }
91
+ function ringAreaSquareMeters(ring) {
92
+ let total = 0;
93
+ for (let index = 0; index < ring.length - 1; index += 1) {
94
+ const [longitude1, latitude1] = ring[index];
95
+ const [longitude2, latitude2] = ring[index + 1];
96
+ total += (toRadians(longitude2) - toRadians(longitude1)) * (2 + Math.sin(toRadians(latitude1)) + Math.sin(toRadians(latitude2)));
97
+ }
98
+ return Math.abs(total * EARTH_RADIUS_METERS * EARTH_RADIUS_METERS / 2);
99
+ }
100
+ function polygonAreaSquareMeters(rings) {
101
+ const [exterior, ...holes] = rings;
102
+ const holesArea = holes.reduce((sum, ring) => sum + ringAreaSquareMeters(ring), 0);
103
+ return Math.max(0, ringAreaSquareMeters(exterior) - holesArea);
104
+ }
105
+ function areaHa(geometry) {
106
+ const squareMeters = geometry.type === "Polygon" ? polygonAreaSquareMeters(geometry.coordinates) : geometry.coordinates.reduce((sum, polygon) => sum + polygonAreaSquareMeters(polygon), 0);
107
+ return Math.round(squareMeters / 1e4 * 1e4) / 1e4;
108
+ }
109
+ function validatePlotGeometry(input) {
110
+ const length = serializedLength(input);
111
+ if (length === null) return { ok: false, errorKey: "geometryInvalid" };
112
+ if (length > MAX_GEOMETRY_SIZE) return { ok: false, errorKey: "geometryTooLarge" };
113
+ const isFeature = isRecord(input) && input.type === "Feature";
114
+ const geometryInput = isFeature ? input.geometry : input;
115
+ const properties = isFeature && isRecord(input.properties) ? input.properties : {};
116
+ const result = validateGeometry(geometryInput);
117
+ if (!result.ok) return result;
118
+ const plotType = result.geometry.type === "Point" ? "point" : "polygon";
119
+ return {
120
+ ok: true,
121
+ feature: { type: "Feature", properties, geometry: result.geometry },
122
+ plotType,
123
+ computedAreaHa: result.geometry.type === "Point" ? null : areaHa(result.geometry),
124
+ warnings: result.lowPrecision ? ["low_precision"] : []
125
+ };
126
+ }
127
+ function collectFeatures(featureCollection) {
128
+ const length = serializedLength(featureCollection);
129
+ if (length === null) return { ok: false, errorKey: "geometryInvalid" };
130
+ if (length > MAX_IMPORT_SIZE) return { ok: false, errorKey: "importTooLarge" };
131
+ if (!isRecord(featureCollection) || featureCollection.type !== "FeatureCollection" || !Array.isArray(featureCollection.features)) {
132
+ return { ok: false, errorKey: "geometryInvalid" };
133
+ }
134
+ if (featureCollection.features.length > MAX_FEATURE_COLLECTION_FEATURES) return { ok: false, errorKey: "importTooManyFeatures" };
135
+ return { ok: true, features: featureCollection.features };
136
+ }
137
+ export {
138
+ POINT_MAX_AREA_HA,
139
+ collectFeatures,
140
+ validatePlotGeometry
141
+ };
142
+ //# sourceMappingURL=geometry.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/eudr/lib/geometry.ts"],
4
+ "sourcesContent": ["export type EudrPlotGeometryType = 'point' | 'polygon'\n\ntype GeoJsonPosition = [number, number]\ntype GeoJsonPoint = { type: 'Point'; coordinates: GeoJsonPosition }\ntype GeoJsonPolygon = { type: 'Polygon'; coordinates: GeoJsonPosition[][] }\ntype GeoJsonMultiPolygon = { type: 'MultiPolygon'; coordinates: GeoJsonPosition[][][] }\ntype GeoJsonSupportedGeometry = GeoJsonPoint | GeoJsonPolygon | GeoJsonMultiPolygon\n\nexport type GeoJsonFeature = {\n type: 'Feature'\n properties: Record<string, unknown>\n geometry: GeoJsonSupportedGeometry\n}\n\nexport type GeometryValidationResult =\n | { ok: true; feature: GeoJsonFeature; plotType: EudrPlotGeometryType; computedAreaHa: number | null; warnings: string[] }\n | { ok: false; errorKey: string }\n\ntype PositionValidationResult =\n | { ok: true; position: GeoJsonPosition; lowPrecision: boolean }\n | { ok: false; errorKey: 'geometryOutOfRange' }\n\nconst MAX_GEOMETRY_SIZE = 262_144\nconst MAX_IMPORT_SIZE = 1_048_576\nconst MAX_FEATURE_COLLECTION_FEATURES = 500\nconst EARTH_RADIUS_METERS = 6_371_008.8\n\nexport const POINT_MAX_AREA_HA = 4\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction serializedLength(value: unknown): number | null {\n try {\n const serialized = JSON.stringify(value)\n return typeof serialized === 'string' ? serialized.length : null\n } catch {\n return null\n }\n}\n\nfunction decimalPlaces(value: number): number {\n const decimal = String(value).split(/[eE]/)[0]?.split('.')[1]\n return decimal?.length ?? 0\n}\n\nfunction validatePosition(input: unknown): PositionValidationResult {\n if (!Array.isArray(input) || input.length < 2) return { ok: false, errorKey: 'geometryOutOfRange' }\n const [longitude, latitude] = input\n if (typeof longitude !== 'number' || typeof latitude !== 'number') return { ok: false, errorKey: 'geometryOutOfRange' }\n if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) return { ok: false, errorKey: 'geometryOutOfRange' }\n if (longitude < -180 || longitude > 180 || latitude < -90 || latitude > 90) return { ok: false, errorKey: 'geometryOutOfRange' }\n\n return {\n ok: true,\n position: [longitude, latitude],\n lowPrecision: decimalPlaces(longitude) < 6 || decimalPlaces(latitude) < 6,\n }\n}\n\nfunction positionsEqual(left: GeoJsonPosition, right: GeoJsonPosition): boolean {\n return left[0] === right[0] && left[1] === right[1]\n}\n\nfunction validateRing(input: unknown): { ok: true; ring: GeoJsonPosition[]; lowPrecision: boolean } | { ok: false; errorKey: string } {\n if (!Array.isArray(input)) return { ok: false, errorKey: 'geometryInvalid' }\n if (input.length < 4) return { ok: false, errorKey: 'geometryRingNotClosed' }\n\n const ring: GeoJsonPosition[] = []\n let lowPrecision = false\n for (const candidate of input) {\n const result = validatePosition(candidate)\n if (!result.ok) return result\n ring.push(result.position)\n lowPrecision = lowPrecision || result.lowPrecision\n }\n\n if (!positionsEqual(ring[0], ring[ring.length - 1])) return { ok: false, errorKey: 'geometryRingNotClosed' }\n return { ok: true, ring, lowPrecision }\n}\n\nfunction validatePolygonCoordinates(input: unknown): { ok: true; rings: GeoJsonPosition[][]; lowPrecision: boolean } | { ok: false; errorKey: string } {\n if (!Array.isArray(input) || input.length === 0) return { ok: false, errorKey: 'geometryInvalid' }\n\n const rings: GeoJsonPosition[][] = []\n let lowPrecision = false\n for (const candidate of input) {\n const result = validateRing(candidate)\n if (!result.ok) return result\n rings.push(result.ring)\n lowPrecision = lowPrecision || result.lowPrecision\n }\n\n return { ok: true, rings, lowPrecision }\n}\n\nfunction validateGeometry(input: unknown): { ok: true; geometry: GeoJsonSupportedGeometry; lowPrecision: boolean } | { ok: false; errorKey: string } {\n if (!isRecord(input) || typeof input.type !== 'string') return { ok: false, errorKey: 'geometryInvalid' }\n\n if (input.type === 'Point') {\n const result = validatePosition(input.coordinates)\n if (!result.ok) return result\n return { ok: true, geometry: { type: 'Point', coordinates: result.position }, lowPrecision: result.lowPrecision }\n }\n\n if (input.type === 'Polygon') {\n const result = validatePolygonCoordinates(input.coordinates)\n if (!result.ok) return result\n return { ok: true, geometry: { type: 'Polygon', coordinates: result.rings }, lowPrecision: result.lowPrecision }\n }\n\n if (input.type === 'MultiPolygon') {\n if (!Array.isArray(input.coordinates) || input.coordinates.length === 0) return { ok: false, errorKey: 'geometryInvalid' }\n const polygons: GeoJsonPosition[][][] = []\n let lowPrecision = false\n for (const candidate of input.coordinates) {\n const result = validatePolygonCoordinates(candidate)\n if (!result.ok) return result\n polygons.push(result.rings)\n lowPrecision = lowPrecision || result.lowPrecision\n }\n return { ok: true, geometry: { type: 'MultiPolygon', coordinates: polygons }, lowPrecision }\n }\n\n return { ok: false, errorKey: 'geometryInvalid' }\n}\n\nfunction toRadians(value: number): number {\n return (value * Math.PI) / 180\n}\n\nfunction ringAreaSquareMeters(ring: GeoJsonPosition[]): number {\n let total = 0\n for (let index = 0; index < ring.length - 1; index += 1) {\n const [longitude1, latitude1] = ring[index]\n const [longitude2, latitude2] = ring[index + 1]\n total += (toRadians(longitude2) - toRadians(longitude1)) * (2 + Math.sin(toRadians(latitude1)) + Math.sin(toRadians(latitude2)))\n }\n return Math.abs((total * EARTH_RADIUS_METERS * EARTH_RADIUS_METERS) / 2)\n}\n\nfunction polygonAreaSquareMeters(rings: GeoJsonPosition[][]): number {\n const [exterior, ...holes] = rings\n const holesArea = holes.reduce((sum, ring) => sum + ringAreaSquareMeters(ring), 0)\n return Math.max(0, ringAreaSquareMeters(exterior) - holesArea)\n}\n\nfunction areaHa(geometry: GeoJsonPolygon | GeoJsonMultiPolygon): number {\n // Spherical-excess area is approximate, but is within about 0.5% at normal\n // plot scale and sufficient for the 4-ha EUDR threshold hinting flow.\n const squareMeters = geometry.type === 'Polygon'\n ? polygonAreaSquareMeters(geometry.coordinates)\n : geometry.coordinates.reduce((sum, polygon) => sum + polygonAreaSquareMeters(polygon), 0)\n\n return Math.round((squareMeters / 10_000) * 10_000) / 10_000\n}\n\nexport function validatePlotGeometry(input: unknown): GeometryValidationResult {\n const length = serializedLength(input)\n if (length === null) return { ok: false, errorKey: 'geometryInvalid' }\n if (length > MAX_GEOMETRY_SIZE) return { ok: false, errorKey: 'geometryTooLarge' }\n\n const isFeature = isRecord(input) && input.type === 'Feature'\n const geometryInput = isFeature ? input.geometry : input\n const properties = isFeature && isRecord(input.properties) ? input.properties : {}\n const result = validateGeometry(geometryInput)\n if (!result.ok) return result\n\n const plotType: EudrPlotGeometryType = result.geometry.type === 'Point' ? 'point' : 'polygon'\n return {\n ok: true,\n feature: { type: 'Feature', properties, geometry: result.geometry },\n plotType,\n computedAreaHa: result.geometry.type === 'Point' ? null : areaHa(result.geometry),\n warnings: result.lowPrecision ? ['low_precision'] : [],\n }\n}\n\nexport function collectFeatures(featureCollection: unknown): { ok: true; features: unknown[] } | { ok: false; errorKey: string } {\n const length = serializedLength(featureCollection)\n if (length === null) return { ok: false, errorKey: 'geometryInvalid' }\n if (length > MAX_IMPORT_SIZE) return { ok: false, errorKey: 'importTooLarge' }\n\n if (!isRecord(featureCollection) || featureCollection.type !== 'FeatureCollection' || !Array.isArray(featureCollection.features)) {\n return { ok: false, errorKey: 'geometryInvalid' }\n }\n\n if (featureCollection.features.length > MAX_FEATURE_COLLECTION_FEATURES) return { ok: false, errorKey: 'importTooManyFeatures' }\n return { ok: true, features: featureCollection.features }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,56 @@
1
+ import { createLogger } from "@open-mercato/shared/lib/logger";
2
+ import { buildFeatureNotificationFromType } from "../../notifications/lib/notificationBuilder.js";
3
+ import { resolveNotificationService } from "../../notifications/lib/notificationService.js";
4
+ import { notificationTypes } from "../notifications.js";
5
+ const logger = createLogger("eudr").child({ component: "notifications" });
6
+ const REQUIRED_FEATURE_BY_TYPE = {
7
+ "eudr.statement.submitted": "eudr.statements.manage",
8
+ "eudr.statement.reference_issued": "eudr.statements.manage",
9
+ "eudr.statement.withdrawn": "eudr.statements.manage",
10
+ "eudr.risk.non_negligible": "eudr.risk.manage",
11
+ "eudr.mitigation.completed": "eudr.risk.manage"
12
+ };
13
+ async function deliverEudrNotification({
14
+ container,
15
+ typeId,
16
+ payload
17
+ }) {
18
+ let notificationService;
19
+ try {
20
+ notificationService = resolveNotificationService(container);
21
+ } catch (err) {
22
+ logger.debug("Notification service unavailable; skipping EUDR notification", {
23
+ typeId,
24
+ entityId: payload.entityId,
25
+ err
26
+ });
27
+ return;
28
+ }
29
+ const typeDef = notificationTypes.find((candidate) => candidate.type === typeId);
30
+ if (!typeDef) {
31
+ throw new Error(`[internal] EUDR notification type is not registered: ${typeId}`);
32
+ }
33
+ const requiredFeature = REQUIRED_FEATURE_BY_TYPE[typeId];
34
+ const content = buildFeatureNotificationFromType(typeDef, {
35
+ requiredFeature,
36
+ bodyVariables: payload.bodyVariables,
37
+ sourceEntityType: payload.sourceEntityType,
38
+ sourceEntityId: payload.entityId,
39
+ linkHref: payload.linkHref,
40
+ groupKey: `${typeId}:${payload.entityId}:${payload.occurredAt}`
41
+ });
42
+ await notificationService.createForFeature(
43
+ {
44
+ ...content,
45
+ restrictRecipientsToOrganization: true
46
+ },
47
+ {
48
+ tenantId: payload.tenantId,
49
+ organizationId: payload.organizationId
50
+ }
51
+ );
52
+ }
53
+ export {
54
+ deliverEudrNotification
55
+ };
56
+ //# sourceMappingURL=notifications.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/eudr/lib/notifications.ts"],
4
+ "sourcesContent": ["import { createLogger } from '@open-mercato/shared/lib/logger'\nimport { buildFeatureNotificationFromType } from '../../notifications/lib/notificationBuilder'\nimport { resolveNotificationService } from '../../notifications/lib/notificationService'\nimport { notificationTypes } from '../notifications'\n\nconst logger = createLogger('eudr').child({ component: 'notifications' })\n\nexport type EudrNotificationTypeId =\n | 'eudr.statement.submitted'\n | 'eudr.statement.reference_issued'\n | 'eudr.statement.withdrawn'\n | 'eudr.risk.non_negligible'\n | 'eudr.mitigation.completed'\n\nexport type EudrNotificationContainer = {\n resolve: (name: string) => unknown\n}\n\ntype EudrNotificationPayload = {\n tenantId: string\n organizationId: string | null\n entityId: string\n occurredAt: string\n bodyVariables: Record<string, string>\n linkHref: string\n sourceEntityType: string\n}\n\ntype DeliverEudrNotificationInput = {\n container: EudrNotificationContainer\n typeId: EudrNotificationTypeId\n payload: EudrNotificationPayload\n}\n\nconst REQUIRED_FEATURE_BY_TYPE: Record<EudrNotificationTypeId, string> = {\n 'eudr.statement.submitted': 'eudr.statements.manage',\n 'eudr.statement.reference_issued': 'eudr.statements.manage',\n 'eudr.statement.withdrawn': 'eudr.statements.manage',\n 'eudr.risk.non_negligible': 'eudr.risk.manage',\n 'eudr.mitigation.completed': 'eudr.risk.manage',\n}\n\nexport async function deliverEudrNotification({\n container,\n typeId,\n payload,\n}: DeliverEudrNotificationInput): Promise<void> {\n let notificationService: ReturnType<typeof resolveNotificationService>\n try {\n notificationService = resolveNotificationService(container)\n } catch (err) {\n logger.debug('Notification service unavailable; skipping EUDR notification', {\n typeId,\n entityId: payload.entityId,\n err,\n })\n return\n }\n\n const typeDef = notificationTypes.find((candidate) => candidate.type === typeId)\n if (!typeDef) {\n throw new Error(`[internal] EUDR notification type is not registered: ${typeId}`)\n }\n\n const requiredFeature = REQUIRED_FEATURE_BY_TYPE[typeId]\n const content = buildFeatureNotificationFromType(typeDef, {\n requiredFeature,\n bodyVariables: payload.bodyVariables,\n sourceEntityType: payload.sourceEntityType,\n sourceEntityId: payload.entityId,\n linkHref: payload.linkHref,\n groupKey: `${typeId}:${payload.entityId}:${payload.occurredAt}`,\n })\n\n await notificationService.createForFeature(\n {\n ...content,\n restrictRecipientsToOrganization: true,\n },\n {\n tenantId: payload.tenantId,\n organizationId: payload.organizationId,\n },\n )\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,wCAAwC;AACjD,SAAS,kCAAkC;AAC3C,SAAS,yBAAyB;AAElC,MAAM,SAAS,aAAa,MAAM,EAAE,MAAM,EAAE,WAAW,gBAAgB,CAAC;AA6BxE,MAAM,2BAAmE;AAAA,EACvE,4BAA4B;AAAA,EAC5B,mCAAmC;AAAA,EACnC,4BAA4B;AAAA,EAC5B,4BAA4B;AAAA,EAC5B,6BAA6B;AAC/B;AAEA,eAAsB,wBAAwB;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AACF,GAAgD;AAC9C,MAAI;AACJ,MAAI;AACF,0BAAsB,2BAA2B,SAAS;AAAA,EAC5D,SAAS,KAAK;AACZ,WAAO,MAAM,gEAAgE;AAAA,MAC3E;AAAA,MACA,UAAU,QAAQ;AAAA,MAClB;AAAA,IACF,CAAC;AACD;AAAA,EACF;AAEA,QAAM,UAAU,kBAAkB,KAAK,CAAC,cAAc,UAAU,SAAS,MAAM;AAC/E,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,wDAAwD,MAAM,EAAE;AAAA,EAClF;AAEA,QAAM,kBAAkB,yBAAyB,MAAM;AACvD,QAAM,UAAU,iCAAiC,SAAS;AAAA,IACxD;AAAA,IACA,eAAe,QAAQ;AAAA,IACvB,kBAAkB,QAAQ;AAAA,IAC1B,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ;AAAA,IAClB,UAAU,GAAG,MAAM,IAAI,QAAQ,QAAQ,IAAI,QAAQ,UAAU;AAAA,EAC/D,CAAC;AAED,QAAM,oBAAoB;AAAA,IACxB;AAAA,MACE,GAAG;AAAA,MACH,kCAAkC;AAAA,IACpC;AAAA,IACA;AAAA,MACE,UAAU,QAAQ;AAAA,MAClB,gBAAgB,QAAQ;AAAA,IAC1B;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ const pluralRulesCache = /* @__PURE__ */ new Map();
2
+ function pluralRulesFor(locale) {
3
+ const cached = pluralRulesCache.get(locale);
4
+ if (cached) return cached;
5
+ let rules;
6
+ try {
7
+ rules = new Intl.PluralRules(locale);
8
+ } catch {
9
+ rules = new Intl.PluralRules("en");
10
+ }
11
+ pluralRulesCache.set(locale, rules);
12
+ return rules;
13
+ }
14
+ function translatePlural(translate, locale, baseKey, count, params) {
15
+ const category = pluralRulesFor(locale).select(count);
16
+ const mergedParams = { count, ...params ?? {} };
17
+ for (const key of [`${baseKey}.${category}`, `${baseKey}.other`, baseKey]) {
18
+ const result = translate(key, mergedParams);
19
+ if (result !== key) return result;
20
+ }
21
+ return translate(baseKey, mergedParams);
22
+ }
23
+ export {
24
+ translatePlural
25
+ };
26
+ //# sourceMappingURL=plural.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/eudr/lib/plural.ts"],
4
+ "sourcesContent": ["type Translator = (\n key: string,\n fallbackOrParams?: string | Record<string, string | number>,\n params?: Record<string, string | number>,\n) => string\n\nconst pluralRulesCache = new Map<string, Intl.PluralRules>()\n\nfunction pluralRulesFor(locale: string): Intl.PluralRules {\n const cached = pluralRulesCache.get(locale)\n if (cached) return cached\n let rules: Intl.PluralRules\n try {\n rules = new Intl.PluralRules(locale)\n } catch {\n rules = new Intl.PluralRules('en')\n }\n pluralRulesCache.set(locale, rules)\n return rules\n}\n\nexport function translatePlural(\n translate: Translator,\n locale: string,\n baseKey: string,\n count: number,\n params?: Record<string, string | number>,\n): string {\n const category = pluralRulesFor(locale).select(count)\n const mergedParams = { count, ...(params ?? {}) }\n for (const key of [`${baseKey}.${category}`, `${baseKey}.other`, baseKey]) {\n const result = translate(key, mergedParams)\n if (result !== key) return result\n }\n return translate(baseKey, mergedParams)\n}\n"],
5
+ "mappings": "AAMA,MAAM,mBAAmB,oBAAI,IAA8B;AAE3D,SAAS,eAAe,QAAkC;AACxD,QAAM,SAAS,iBAAiB,IAAI,MAAM;AAC1C,MAAI,OAAQ,QAAO;AACnB,MAAI;AACJ,MAAI;AACF,YAAQ,IAAI,KAAK,YAAY,MAAM;AAAA,EACrC,QAAQ;AACN,YAAQ,IAAI,KAAK,YAAY,IAAI;AAAA,EACnC;AACA,mBAAiB,IAAI,QAAQ,KAAK;AAClC,SAAO;AACT;AAEO,SAAS,gBACd,WACA,QACA,SACA,OACA,QACQ;AACR,QAAM,WAAW,eAAe,MAAM,EAAE,OAAO,KAAK;AACpD,QAAM,eAAe,EAAE,OAAO,GAAI,UAAU,CAAC,EAAG;AAChD,aAAW,OAAO,CAAC,GAAG,OAAO,IAAI,QAAQ,IAAI,GAAG,OAAO,UAAU,OAAO,GAAG;AACzE,UAAM,SAAS,UAAU,KAAK,YAAY;AAC1C,QAAI,WAAW,IAAK,QAAO;AAAA,EAC7B;AACA,SAAO,UAAU,SAAS,YAAY;AACxC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,240 @@
1
+ const EUDR_HIGH_RISK_COUNTRIES = ["BY", "KP", "MM", "RU"];
2
+ const EUDR_LOW_RISK_COUNTRIES = [
3
+ "AD",
4
+ "AE",
5
+ "AF",
6
+ "AG",
7
+ "AL",
8
+ "AM",
9
+ "AT",
10
+ "AU",
11
+ "AZ",
12
+ "BA",
13
+ "BB",
14
+ "BD",
15
+ "BE",
16
+ "BG",
17
+ "BH",
18
+ "BI",
19
+ "BN",
20
+ "BS",
21
+ "BT",
22
+ "CA",
23
+ "CF",
24
+ "CG",
25
+ "CH",
26
+ "CL",
27
+ "CN",
28
+ "CR",
29
+ "CU",
30
+ "CV",
31
+ "CY",
32
+ "CZ",
33
+ "DE",
34
+ "DJ",
35
+ "DK",
36
+ "DM",
37
+ "DO",
38
+ "DZ",
39
+ "EE",
40
+ "EG",
41
+ "ES",
42
+ "FI",
43
+ "FJ",
44
+ "FM",
45
+ "FR",
46
+ "GA",
47
+ "GB",
48
+ "GD",
49
+ "GE",
50
+ "GH",
51
+ "GR",
52
+ "GY",
53
+ "HR",
54
+ "HU",
55
+ "IE",
56
+ "IN",
57
+ "IQ",
58
+ "IR",
59
+ "IS",
60
+ "IT",
61
+ "JM",
62
+ "JO",
63
+ "JP",
64
+ "KE",
65
+ "KG",
66
+ "KI",
67
+ "KM",
68
+ "KN",
69
+ "KR",
70
+ "KW",
71
+ "KZ",
72
+ "LA",
73
+ "LB",
74
+ "LC",
75
+ "LI",
76
+ "LK",
77
+ "LS",
78
+ "LT",
79
+ "LU",
80
+ "LV",
81
+ "LY",
82
+ "MA",
83
+ "MC",
84
+ "MD",
85
+ "ME",
86
+ "MG",
87
+ "MH",
88
+ "MK",
89
+ "ML",
90
+ "MN",
91
+ "MT",
92
+ "MU",
93
+ "MV",
94
+ "NL",
95
+ "NO",
96
+ "NP",
97
+ "NR",
98
+ "NZ",
99
+ "OM",
100
+ "PG",
101
+ "PH",
102
+ "PL",
103
+ "PS",
104
+ "PT",
105
+ "PW",
106
+ "QA",
107
+ "RO",
108
+ "RS",
109
+ "RW",
110
+ "SA",
111
+ "SB",
112
+ "SC",
113
+ "SE",
114
+ "SG",
115
+ "SI",
116
+ "SK",
117
+ "SM",
118
+ "SR",
119
+ "SS",
120
+ "ST",
121
+ "SY",
122
+ "SZ",
123
+ "TG",
124
+ "TH",
125
+ "TJ",
126
+ "TL",
127
+ "TM",
128
+ "TN",
129
+ "TO",
130
+ "TR",
131
+ "TT",
132
+ "TV",
133
+ "UA",
134
+ "UG",
135
+ "US",
136
+ "UY",
137
+ "UZ",
138
+ "VC",
139
+ "VN",
140
+ "VU",
141
+ "WS",
142
+ "YE",
143
+ "ZA"
144
+ ];
145
+ function getCountryRiskTier(code) {
146
+ const normalized = code?.trim().toUpperCase() ?? "";
147
+ if (!/^[A-Z]{2}$/.test(normalized)) return "unknown";
148
+ if (EUDR_HIGH_RISK_COUNTRIES.includes(normalized)) return "high";
149
+ if (EUDR_LOW_RISK_COUNTRIES.includes(normalized)) return "low";
150
+ return "standard";
151
+ }
152
+ const EUDR_APPLICATION_DATES = {
153
+ largeAndMedium: "2026-12-30",
154
+ microAndSmallNonTimber: "2027-06-30"
155
+ };
156
+ const EUDR_SUPPLEMENTARY_UNIT_HS_PREFIXES = [
157
+ "4011",
158
+ "4013",
159
+ "4104",
160
+ "4403",
161
+ "4406",
162
+ "4408",
163
+ "4410",
164
+ "4411",
165
+ "4412",
166
+ "4413",
167
+ "4701",
168
+ "4702",
169
+ "4704",
170
+ "4705"
171
+ ];
172
+ const EUDR_ANNEX1_HS_PREFIXES = {
173
+ cattle: ["0102", "0201", "0202", "0206", "1602"],
174
+ cocoa: ["1801", "1802", "1803", "1804", "1805", "1806"],
175
+ coffee: ["0901", "2101"],
176
+ oil_palm: ["1511", "1513", "2306", "1207", "3823", "2905"],
177
+ rubber: ["4001", "4005", "4006", "4007", "4008", "4009", "4010", "4011", "4012", "4013", "4015", "4016", "4017"],
178
+ soya: ["1201", "1208", "1507", "2304"],
179
+ wood: [
180
+ "4401",
181
+ "4402",
182
+ "4403",
183
+ "4404",
184
+ "4405",
185
+ "4406",
186
+ "4407",
187
+ "4408",
188
+ "4409",
189
+ "4410",
190
+ "4411",
191
+ "4412",
192
+ "4413",
193
+ "4414",
194
+ "4415",
195
+ "4416",
196
+ "4417",
197
+ "4418",
198
+ "4419",
199
+ "4420",
200
+ "4421",
201
+ "9401",
202
+ "9403",
203
+ "9406",
204
+ "44",
205
+ "47",
206
+ "48"
207
+ ]
208
+ };
209
+ function suggestCommodityForHsCode(hsCode) {
210
+ const digits = hsCode?.replace(/\D/g, "") ?? "";
211
+ if (digits.length === 0) return null;
212
+ let match = null;
213
+ for (const [commodity, prefixes] of Object.entries(EUDR_ANNEX1_HS_PREFIXES)) {
214
+ for (const prefix of prefixes) {
215
+ if (!digits.startsWith(prefix)) continue;
216
+ if (match !== null && prefix.length <= match.prefixLength) continue;
217
+ match = { commodity, prefixLength: prefix.length };
218
+ }
219
+ }
220
+ return match?.commodity ?? null;
221
+ }
222
+ const EUDR_RISK_CRITERIA_GROUPS = [
223
+ { key: "country", criteria: ["deforestation_trend", "environmental_governance", "corruption_land_use"] },
224
+ { key: "supply_chain", criteria: ["chain_complexity", "intermediaries_count", "mixing_risk", "prior_noncompliance"] },
225
+ { key: "plot_supplier", criteria: ["land_title_permits", "indigenous_rights", "protected_areas", "labor_human_rights", "plot_deforestation_history"] },
226
+ { key: "documentation", criteria: ["document_completeness", "document_verifiability", "supplier_transparency"] }
227
+ ];
228
+ const EUDR_RISK_CRITERIA_KEYS = EUDR_RISK_CRITERIA_GROUPS.flatMap((group) => [...group.criteria]);
229
+ export {
230
+ EUDR_ANNEX1_HS_PREFIXES,
231
+ EUDR_APPLICATION_DATES,
232
+ EUDR_HIGH_RISK_COUNTRIES,
233
+ EUDR_LOW_RISK_COUNTRIES,
234
+ EUDR_RISK_CRITERIA_GROUPS,
235
+ EUDR_RISK_CRITERIA_KEYS,
236
+ EUDR_SUPPLEMENTARY_UNIT_HS_PREFIXES,
237
+ getCountryRiskTier,
238
+ suggestCommodityForHsCode
239
+ };
240
+ //# sourceMappingURL=reference-data.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/eudr/lib/reference-data.ts"],
4
+ "sourcesContent": ["import type { EudrCommodity } from '../data/validators'\n\n/**\n * EUDR reference data.\n *\n * Source: Commission Implementing Regulation (EU) 2025/1093 country\n * benchmarking (22 May 2025; in force \u2014 the July 2025 EP objection was\n * non-binding \u2014 subject to the Commission's 2026 review), the Commission\n * Green Forum country-classification list (cross-checked against independent\n * reproductions; 141 low-risk + 4 high-risk entries), EUDR application dates,\n * and Annex-I/Appendix-I HS data. Effective as of 2026-07. Keep this file as\n * the single update point when the legal reference data changes. Unlisted\n * countries (~48 standard-risk, e.g. BR, ID, MY, and IL per corroborated\n * sources) default to `standard` so full due diligence remains the\n * conservative fallback. Note: CD (DR Congo) is standard; CG (Congo) is low.\n */\n\nexport type EudrCountryRiskTier = 'low' | 'standard' | 'high' | 'unknown'\n\nexport const EUDR_HIGH_RISK_COUNTRIES = ['BY', 'KP', 'MM', 'RU'] as const\n\nexport const EUDR_LOW_RISK_COUNTRIES = [\n 'AD', 'AE', 'AF', 'AG', 'AL', 'AM', 'AT', 'AU', 'AZ', 'BA', 'BB', 'BD',\n 'BE', 'BG', 'BH', 'BI', 'BN', 'BS', 'BT', 'CA', 'CF', 'CG', 'CH', 'CL',\n 'CN', 'CR', 'CU', 'CV', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ',\n 'EE', 'EG', 'ES', 'FI', 'FJ', 'FM', 'FR', 'GA', 'GB', 'GD', 'GE', 'GH',\n 'GR', 'GY', 'HR', 'HU', 'IE', 'IN', 'IQ', 'IR', 'IS', 'IT', 'JM', 'JO',\n 'JP', 'KE', 'KG', 'KI', 'KM', 'KN', 'KR', 'KW', 'KZ', 'LA', 'LB', 'LC',\n 'LI', 'LK', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MG',\n 'MH', 'MK', 'ML', 'MN', 'MT', 'MU', 'MV', 'NL', 'NO', 'NP', 'NR', 'NZ',\n 'OM', 'PG', 'PH', 'PL', 'PS', 'PT', 'PW', 'QA', 'RO', 'RS', 'RW', 'SA',\n 'SB', 'SC', 'SE', 'SG', 'SI', 'SK', 'SM', 'SR', 'SS', 'ST', 'SY', 'SZ',\n 'TG', 'TH', 'TJ', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'UA', 'UG',\n 'US', 'UY', 'UZ', 'VC', 'VN', 'VU', 'WS', 'YE', 'ZA',\n] as const\n\nexport function getCountryRiskTier(code: string | null | undefined): EudrCountryRiskTier {\n const normalized = code?.trim().toUpperCase() ?? ''\n if (!/^[A-Z]{2}$/.test(normalized)) return 'unknown'\n if ((EUDR_HIGH_RISK_COUNTRIES as readonly string[]).includes(normalized)) return 'high'\n if ((EUDR_LOW_RISK_COUNTRIES as readonly string[]).includes(normalized)) return 'low'\n return 'standard'\n}\n\nexport const EUDR_APPLICATION_DATES = {\n largeAndMedium: '2026-12-30',\n microAndSmallNonTimber: '2027-06-30',\n} as const\n\nexport const EUDR_SUPPLEMENTARY_UNIT_HS_PREFIXES = [\n '4011',\n '4013',\n '4104',\n '4403',\n '4406',\n '4408',\n '4410',\n '4411',\n '4412',\n '4413',\n '4701',\n '4702',\n '4704',\n '4705',\n] as const\n\nexport const EUDR_ANNEX1_HS_PREFIXES: Record<EudrCommodity, readonly string[]> = {\n cattle: ['0102', '0201', '0202', '0206', '1602'],\n cocoa: ['1801', '1802', '1803', '1804', '1805', '1806'],\n coffee: ['0901', '2101'],\n oil_palm: ['1511', '1513', '2306', '1207', '3823', '2905'],\n rubber: ['4001', '4005', '4006', '4007', '4008', '4009', '4010', '4011', '4012', '4013', '4015', '4016', '4017'],\n soya: ['1201', '1208', '1507', '2304'],\n wood: [\n '4401',\n '4402',\n '4403',\n '4404',\n '4405',\n '4406',\n '4407',\n '4408',\n '4409',\n '4410',\n '4411',\n '4412',\n '4413',\n '4414',\n '4415',\n '4416',\n '4417',\n '4418',\n '4419',\n '4420',\n '4421',\n '9401',\n '9403',\n '9406',\n '44',\n '47',\n '48',\n ],\n} as const\n\nexport function suggestCommodityForHsCode(hsCode: string | null | undefined): EudrCommodity | null {\n const digits = hsCode?.replace(/\\D/g, '') ?? ''\n if (digits.length === 0) return null\n\n let match: { commodity: EudrCommodity; prefixLength: number } | null = null\n for (const [commodity, prefixes] of Object.entries(EUDR_ANNEX1_HS_PREFIXES) as Array<[EudrCommodity, readonly string[]]>) {\n for (const prefix of prefixes) {\n if (!digits.startsWith(prefix)) continue\n if (match !== null && prefix.length <= match.prefixLength) continue\n match = { commodity, prefixLength: prefix.length }\n }\n }\n\n return match?.commodity ?? null\n}\n\nexport const EUDR_RISK_CRITERIA_GROUPS = [\n { key: 'country', criteria: ['deforestation_trend', 'environmental_governance', 'corruption_land_use'] },\n { key: 'supply_chain', criteria: ['chain_complexity', 'intermediaries_count', 'mixing_risk', 'prior_noncompliance'] },\n { key: 'plot_supplier', criteria: ['land_title_permits', 'indigenous_rights', 'protected_areas', 'labor_human_rights', 'plot_deforestation_history'] },\n { key: 'documentation', criteria: ['document_completeness', 'document_verifiability', 'supplier_transparency'] },\n] as const\n\nexport const EUDR_RISK_CRITERIA_KEYS: readonly string[] = EUDR_RISK_CRITERIA_GROUPS.flatMap((group) => [...group.criteria])\n"],
5
+ "mappings": "AAmBO,MAAM,2BAA2B,CAAC,MAAM,MAAM,MAAM,IAAI;AAExD,MAAM,0BAA0B;AAAA,EACrC;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAClE;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAClD;AAEO,SAAS,mBAAmB,MAAsD;AACvF,QAAM,aAAa,MAAM,KAAK,EAAE,YAAY,KAAK;AACjD,MAAI,CAAC,aAAa,KAAK,UAAU,EAAG,QAAO;AAC3C,MAAK,yBAA+C,SAAS,UAAU,EAAG,QAAO;AACjF,MAAK,wBAA8C,SAAS,UAAU,EAAG,QAAO;AAChF,SAAO;AACT;AAEO,MAAM,yBAAyB;AAAA,EACpC,gBAAgB;AAAA,EAChB,wBAAwB;AAC1B;AAEO,MAAM,sCAAsC;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,MAAM,0BAAoE;AAAA,EAC/E,QAAQ,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EAC/C,OAAO,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EACtD,QAAQ,CAAC,QAAQ,MAAM;AAAA,EACvB,UAAU,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EACzD,QAAQ,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EAC/G,MAAM,CAAC,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EACrC,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,0BAA0B,QAAyD;AACjG,QAAM,SAAS,QAAQ,QAAQ,OAAO,EAAE,KAAK;AAC7C,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,MAAI,QAAmE;AACvE,aAAW,CAAC,WAAW,QAAQ,KAAK,OAAO,QAAQ,uBAAuB,GAAgD;AACxH,eAAW,UAAU,UAAU;AAC7B,UAAI,CAAC,OAAO,WAAW,MAAM,EAAG;AAChC,UAAI,UAAU,QAAQ,OAAO,UAAU,MAAM,aAAc;AAC3D,cAAQ,EAAE,WAAW,cAAc,OAAO,OAAO;AAAA,IACnD;AAAA,EACF;AAEA,SAAO,OAAO,aAAa;AAC7B;AAEO,MAAM,4BAA4B;AAAA,EACvC,EAAE,KAAK,WAAW,UAAU,CAAC,uBAAuB,4BAA4B,qBAAqB,EAAE;AAAA,EACvG,EAAE,KAAK,gBAAgB,UAAU,CAAC,oBAAoB,wBAAwB,eAAe,qBAAqB,EAAE;AAAA,EACpH,EAAE,KAAK,iBAAiB,UAAU,CAAC,sBAAsB,qBAAqB,mBAAmB,sBAAsB,4BAA4B,EAAE;AAAA,EACrJ,EAAE,KAAK,iBAAiB,UAAU,CAAC,yBAAyB,0BAA0B,uBAAuB,EAAE;AACjH;AAEO,MAAM,0BAA6C,0BAA0B,QAAQ,CAAC,UAAU,CAAC,GAAG,MAAM,QAAQ,CAAC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,10 @@
1
+ const WOOD_COMMODITY = "wood";
2
+ function hasMissingSpecies(mapping) {
3
+ if (mapping.commodity !== WOOD_COMMODITY) return false;
4
+ return !mapping.speciesScientificName?.trim() || !mapping.speciesCommonName?.trim();
5
+ }
6
+ export {
7
+ WOOD_COMMODITY,
8
+ hasMissingSpecies
9
+ };
10
+ //# sourceMappingURL=species.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/eudr/lib/species.ts"],
4
+ "sourcesContent": ["import type { EudrCommodity } from '../data/validators'\n\nexport const WOOD_COMMODITY = 'wood' satisfies EudrCommodity\n\nexport function hasMissingSpecies(mapping: {\n commodity: string\n speciesScientificName?: string | null\n speciesCommonName?: string | null\n}): boolean {\n if (mapping.commodity !== WOOD_COMMODITY) return false\n return !mapping.speciesScientificName?.trim() || !mapping.speciesCommonName?.trim()\n}\n"],
5
+ "mappings": "AAEO,MAAM,iBAAiB;AAEvB,SAAS,kBAAkB,SAItB;AACV,MAAI,QAAQ,cAAc,eAAgB,QAAO;AACjD,SAAO,CAAC,QAAQ,uBAAuB,KAAK,KAAK,CAAC,QAAQ,mBAAmB,KAAK;AACpF;",
6
+ "names": []
7
+ }