celerp 2.3.0__tar.gz → 2.3.2__tar.gz

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 (650) hide show
  1. {celerp-2.3.0 → celerp-2.3.2}/PKG-INFO +1 -1
  2. {celerp-2.3.0 → celerp-2.3.2}/celerp/events/schemas.py +43 -4
  3. celerp-2.3.2/celerp/inventory_codes.py +87 -0
  4. {celerp-2.3.0 → celerp-2.3.2}/celerp/main.py +9 -0
  5. celerp-2.3.2/celerp/migrations/versions/bc0d1e2f3a4b_barcode_unique_index.py +119 -0
  6. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/projections.py +16 -1
  7. {celerp-2.3.0 → celerp-2.3.2}/celerp/projections/engine.py +26 -2
  8. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/field_schema.py +65 -33
  9. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/fulfill.py +22 -0
  10. {celerp-2.3.0 → celerp-2.3.2}/celerp/tax_regimes.py +16 -0
  11. {celerp-2.3.0 → celerp-2.3.2}/celerp.egg-info/PKG-INFO +1 -1
  12. {celerp-2.3.0 → celerp-2.3.2}/celerp.egg-info/SOURCES.txt +18 -0
  13. {celerp-2.3.0 → celerp-2.3.2}/celerp.egg-info/scm_file_list.json +71 -0
  14. celerp-2.3.2/celerp.egg-info/scm_version.json +8 -0
  15. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/statement.html +56 -56
  16. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/celerp_ai/ui_routes.py +9 -8
  17. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-backup/celerp_backup/routes.py +1 -1
  18. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/routes.py +225 -90
  19. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_audits.py +326 -13
  20. celerp-2.3.2/default_modules/celerp-docs/tests/test_list_concurrency.py +178 -0
  21. celerp-2.3.2/default_modules/celerp-docs/tests/test_list_outcome_concurrency.py +364 -0
  22. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/celerp_inventory/routes.py +141 -59
  23. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/celerp_inventory/routes_scanning.py +3 -1
  24. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/celerp_inventory/services.py +96 -0
  25. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/__init__.py +19 -0
  26. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/am.json +11 -0
  27. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/ar.json +11 -0
  28. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/de.json +11 -0
  29. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/en.json +11 -0
  30. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/es.json +11 -0
  31. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/fr.json +11 -0
  32. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/id.json +11 -0
  33. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/it.json +11 -0
  34. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/ja.json +11 -0
  35. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/pt.json +11 -0
  36. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/th.json +11 -0
  37. celerp-2.3.2/default_modules/celerp-labels/celerp_labels/locales/vi.json +11 -0
  38. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/celerp_labels/ui_routes.py +10 -9
  39. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/celerp_manufacturing/routes.py +25 -0
  40. celerp-2.3.2/default_modules/celerp-manufacturing/tests/test_completion_lock_order.py +240 -0
  41. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_run_records.py +18 -0
  42. {celerp-2.3.0 → celerp-2.3.2}/default_modules/first_party.lock.json +7 -7
  43. {celerp-2.3.0 → celerp-2.3.2}/ui/api_client.py +18 -5
  44. {celerp-2.3.0 → celerp-2.3.2}/ui/app.py +10 -8
  45. {celerp-2.3.0 → celerp-2.3.2}/ui/components/activity.py +133 -178
  46. {celerp-2.3.0 → celerp-2.3.2}/ui/components/backup.py +13 -8
  47. {celerp-2.3.0 → celerp-2.3.2}/ui/components/cloud_gate.py +12 -9
  48. {celerp-2.3.0 → celerp-2.3.2}/ui/components/currency.py +1 -1
  49. {celerp-2.3.0 → celerp-2.3.2}/ui/components/files.py +10 -5
  50. {celerp-2.3.0 → celerp-2.3.2}/ui/components/notes.py +2 -2
  51. {celerp-2.3.0 → celerp-2.3.2}/ui/components/report_kit.py +7 -7
  52. {celerp-2.3.0 → celerp-2.3.2}/ui/components/shell.py +194 -69
  53. {celerp-2.3.0 → celerp-2.3.2}/ui/components/table.py +183 -63
  54. {celerp-2.3.0 → celerp-2.3.2}/ui/i18n.py +14 -0
  55. celerp-2.3.2/ui/locales/am.json +3056 -0
  56. celerp-2.3.2/ui/locales/ar.json +3056 -0
  57. celerp-2.3.2/ui/locales/de.json +3056 -0
  58. {celerp-2.3.0 → celerp-2.3.2}/ui/locales/en.json +1437 -2
  59. celerp-2.3.2/ui/locales/es.json +3056 -0
  60. celerp-2.3.2/ui/locales/fr.json +3056 -0
  61. celerp-2.3.2/ui/locales/id.json +3056 -0
  62. celerp-2.3.2/ui/locales/it.json +3056 -0
  63. celerp-2.3.2/ui/locales/ja.json +3056 -0
  64. celerp-2.3.2/ui/locales/pt.json +3056 -0
  65. celerp-2.3.2/ui/locales/th.json +3056 -0
  66. celerp-2.3.2/ui/locales/vi.json +3056 -0
  67. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/account.py +2 -4
  68. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/accounting.py +4 -4
  69. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/accounting_import.py +20 -19
  70. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/auth.py +70 -82
  71. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/contacts.py +125 -111
  72. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/csv_import.py +77 -52
  73. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/dashboard.py +175 -47
  74. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/docs_import.py +18 -18
  75. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/documents.py +627 -412
  76. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/financial_reports.py +24 -24
  77. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/inventory.py +381 -346
  78. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/lists_import.py +18 -18
  79. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/manufacturing.py +122 -110
  80. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/modules_page.py +2 -2
  81. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/reconciliation.py +40 -47
  82. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/reports.py +72 -66
  83. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/search.py +28 -10
  84. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings.py +169 -177
  85. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings_accounting.py +73 -71
  86. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings_cloud.py +22 -22
  87. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings_connectors.py +56 -29
  88. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings_contacts.py +12 -12
  89. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings_general.py +5 -5
  90. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings_import.py +53 -52
  91. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings_inventory.py +63 -70
  92. celerp-2.3.2/ui/routes/settings_manufacturing.py +153 -0
  93. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings_payments.py +6 -5
  94. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings_purchasing.py +6 -6
  95. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/settings_sales.py +48 -36
  96. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/setup.py +17 -18
  97. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/stars.py +12 -5
  98. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/subscriptions.py +24 -25
  99. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/subscriptions_import.py +18 -18
  100. {celerp-2.3.0 → celerp-2.3.2}/ui/static/app.css +3 -2
  101. celerp-2.3.0/celerp.egg-info/scm_version.json +0 -8
  102. celerp-2.3.0/ui/locales/ar.json +0 -1520
  103. celerp-2.3.0/ui/locales/de.json +0 -1520
  104. celerp-2.3.0/ui/locales/es.json +0 -1520
  105. celerp-2.3.0/ui/locales/fr.json +0 -1520
  106. celerp-2.3.0/ui/locales/id.json +0 -1520
  107. celerp-2.3.0/ui/locales/it.json +0 -1520
  108. celerp-2.3.0/ui/locales/ja.json +0 -1520
  109. celerp-2.3.0/ui/locales/pt.json +0 -1520
  110. celerp-2.3.0/ui/locales/th.json +0 -1520
  111. celerp-2.3.0/ui/locales/vi.json +0 -1520
  112. celerp-2.3.0/ui/routes/settings_manufacturing.py +0 -152
  113. {celerp-2.3.0 → celerp-2.3.2}/CLA.md +0 -0
  114. {celerp-2.3.0 → celerp-2.3.2}/CONTRIBUTING.md +0 -0
  115. {celerp-2.3.0 → celerp-2.3.2}/LICENSE +0 -0
  116. {celerp-2.3.0 → celerp-2.3.2}/LICENSING.md +0 -0
  117. {celerp-2.3.0 → celerp-2.3.2}/MANIFEST.in +0 -0
  118. {celerp-2.3.0 → celerp-2.3.2}/NOTICE +0 -0
  119. {celerp-2.3.0 → celerp-2.3.2}/README.md +0 -0
  120. {celerp-2.3.0 → celerp-2.3.2}/alembic.ini +0 -0
  121. {celerp-2.3.0 → celerp-2.3.2}/celerp/__init__.py +0 -0
  122. {celerp-2.3.0 → celerp-2.3.2}/celerp/__main__.py +0 -0
  123. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/__init__.py +0 -0
  124. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/batch.py +0 -0
  125. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/cleanup.py +0 -0
  126. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/commands.py +0 -0
  127. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/conversations.py +0 -0
  128. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/files.py +0 -0
  129. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/intent.py +0 -0
  130. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/llm.py +0 -0
  131. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/memory.py +0 -0
  132. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/models.py +0 -0
  133. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/page_count.py +0 -0
  134. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/quota.py +0 -0
  135. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/service.py +0 -0
  136. {celerp-2.3.0 → celerp-2.3.2}/celerp/ai/tools.py +0 -0
  137. {celerp-2.3.0 → celerp-2.3.2}/celerp/alembic.ini +0 -0
  138. {celerp-2.3.0 → celerp-2.3.2}/celerp/alembic_config.py +0 -0
  139. {celerp-2.3.0 → celerp-2.3.2}/celerp/cli.py +0 -0
  140. {celerp-2.3.0 → celerp-2.3.2}/celerp/compat.py +0 -0
  141. {celerp-2.3.0 → celerp-2.3.2}/celerp/compute/__init__.py +0 -0
  142. {celerp-2.3.0 → celerp-2.3.2}/celerp/compute/aggregations.py +0 -0
  143. {celerp-2.3.0 → celerp-2.3.2}/celerp/compute/valuation.py +0 -0
  144. {celerp-2.3.0 → celerp-2.3.2}/celerp/config.py +0 -0
  145. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/__init__.py +0 -0
  146. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/base.py +0 -0
  147. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/daily_scheduler.py +0 -0
  148. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/http.py +0 -0
  149. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/images.py +0 -0
  150. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/quickbooks.py +0 -0
  151. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/registry.py +0 -0
  152. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/relay_token.py +0 -0
  153. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/shopify.py +0 -0
  154. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/sync_runner.py +0 -0
  155. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/upsert.py +0 -0
  156. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/util.py +0 -0
  157. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/webhooks.py +0 -0
  158. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/woocommerce.py +0 -0
  159. {celerp-2.3.0 → celerp-2.3.2}/celerp/connectors/xero.py +0 -0
  160. {celerp-2.3.0 → celerp-2.3.2}/celerp/constants.py +0 -0
  161. {celerp-2.3.0 → celerp-2.3.2}/celerp/db.py +0 -0
  162. {celerp-2.3.0 → celerp-2.3.2}/celerp/embedded_pg.py +0 -0
  163. {celerp-2.3.0 → celerp-2.3.2}/celerp/events/__init__.py +0 -0
  164. {celerp-2.3.0 → celerp-2.3.2}/celerp/events/engine.py +0 -0
  165. {celerp-2.3.0 → celerp-2.3.2}/celerp/events/types.py +0 -0
  166. {celerp-2.3.0 → celerp-2.3.2}/celerp/gateway/__init__.py +0 -0
  167. {celerp-2.3.0 → celerp-2.3.2}/celerp/gateway/client.py +0 -0
  168. {celerp-2.3.0 → celerp-2.3.2}/celerp/gateway/state.py +0 -0
  169. {celerp-2.3.0 → celerp-2.3.2}/celerp/importers/__init__.py +0 -0
  170. {celerp-2.3.0 → celerp-2.3.2}/celerp/importers/importer.py +0 -0
  171. {celerp-2.3.0 → celerp-2.3.2}/celerp/importers/schema.py +0 -0
  172. {celerp-2.3.0 → celerp-2.3.2}/celerp/middleware.py +0 -0
  173. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/README.md +0 -0
  174. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/_auto_stamp.py +0 -0
  175. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/_data_reconcile.py +0 -0
  176. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/_json_compat.py +0 -0
  177. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/env.py +0 -0
  178. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/script.py.mako +0 -0
  179. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/a0b1c2d3e4f5_seed_landed_cost_clearing_accounts.py +0 -0
  180. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/a1b2c3d4e5f6_add_doc_share_tokens.py +0 -0
  181. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/b1c2d3e4f5a6_add_supporter_badges.py +0 -0
  182. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/b2c3d4e5f6a7_add_import_batches.py +0 -0
  183. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/b3c4d5e6f7a8_expand_role_permissions_to_role_grants.py +0 -0
  184. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/c1d2e3f4a5b6_add_marketplace.py +0 -0
  185. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/c2d3e4f5a6b7_add_is_sync_to_shopify.py +0 -0
  186. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/c4d5e6f7a8b9_account_cash_flow_category.py +0 -0
  187. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/d0e1f2a3b4c5_add_share_token_expiry.py +0 -0
  188. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/d2e3f4a5b6c7_add_password_reset_token.py +0 -0
  189. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/d5e6f7a8b9c0_rename_fx_rounding_to_fx_difference.py +0 -0
  190. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/e3f4a5b6c7d8_add_company_is_active.py +0 -0
  191. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/e4f5a6b7c8d9_backfill_connector_idempotency_key.py +0 -0
  192. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/e7c9a1b3d5f2_work_center_default_columns.py +0 -0
  193. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/f1a2b3c4d5e6_move_accounts_marketplace_to_modules.py +0 -0
  194. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/f6a7b8c9d0e1_seed_fx_rounding_account.py +0 -0
  195. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/f8a9b0c1d2e3_work_center_default_backfill.py +0 -0
  196. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/fd5de461e14e_initial_schema.py +0 -0
  197. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/g1h2i3j4k5l6_add_consignment_flag.py +0 -0
  198. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/h2i3j4k5l6m7_add_bank_accounts_and_reconciliation.py +0 -0
  199. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/j4k5l6m7n8o9_labels_db_persistence.py +0 -0
  200. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/k5l6m7n8o9p0_add_reconciliation_v2.py +0 -0
  201. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/l6m7n8o9p0q1_add_sync_runs_table.py +0 -0
  202. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/m7n8o9p0q1r2_add_connector_configs_and_outbound_queue.py +0 -0
  203. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/n8o9p0q1r2s3_backfill_payment_date.py +0 -0
  204. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/o9p0q1r2s3t4_backfill_item_price_fields.py +0 -0
  205. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/p1q2r3s4t5u6_add_session_registry_and_user_auth_state.py +0 -0
  206. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/q2r3s4t5u6v7_add_system_runtime_state.py +0 -0
  207. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/r3s4t5u6v7w8_add_projections_company_entity_type_index.py +0 -0
  208. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/s4t5u6v7w8x9_drop_user_company_id_role.py +0 -0
  209. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/t5u6v7w8x9y0_seed_inventory_sub_accounts.py +0 -0
  210. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/u6v7w8x9y0z1_backfill_item_prices_from_attributes.py +0 -0
  211. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/v7w8x9y0z1a2_backfill_purchase_unit_defaults.py +0 -0
  212. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/w8x9y0z1a2b3_backfill_category_unit_defaults.py +0 -0
  213. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/x7y8z9a0b1c2_add_projection_created_at.py +0 -0
  214. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/y8z9a0b1c2d3_per_company_ledger_idempotency.py +0 -0
  215. {celerp-2.3.0 → celerp-2.3.2}/celerp/migrations/versions/z9a0b1c2d3e4_work_centers.py +0 -0
  216. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/__init__.py +0 -0
  217. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/accounting.py +0 -0
  218. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/ai.py +0 -0
  219. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/auth.py +0 -0
  220. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/base.py +0 -0
  221. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/company.py +0 -0
  222. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/connector_config.py +0 -0
  223. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/import_batch.py +0 -0
  224. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/ledger.py +0 -0
  225. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/marketplace.py +0 -0
  226. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/notification.py +0 -0
  227. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/share.py +0 -0
  228. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/supporter.py +0 -0
  229. {celerp-2.3.0 → celerp-2.3.2}/celerp/models/sync_run.py +0 -0
  230. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/__init__.py +0 -0
  231. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/api.py +0 -0
  232. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/audit.py +0 -0
  233. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/demotion.py +0 -0
  234. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/importer.py +0 -0
  235. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/license.py +0 -0
  236. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/loader.py +0 -0
  237. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/meta.py +0 -0
  238. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/migrations_runner.py +0 -0
  239. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/references.py +0 -0
  240. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/registry.py +0 -0
  241. {celerp-2.3.0 → celerp-2.3.2}/celerp/modules/slots.py +0 -0
  242. {celerp-2.3.0 → celerp-2.3.2}/celerp/notifications/__init__.py +0 -0
  243. {celerp-2.3.0 → celerp-2.3.2}/celerp/notifications/service.py +0 -0
  244. {celerp-2.3.0 → celerp-2.3.2}/celerp/notifications/sse.py +0 -0
  245. {celerp-2.3.0 → celerp-2.3.2}/celerp/output/__init__.py +0 -0
  246. {celerp-2.3.0 → celerp-2.3.2}/celerp/output/branding.py +0 -0
  247. {celerp-2.3.0 → celerp-2.3.2}/celerp/output/doc_print.py +0 -0
  248. {celerp-2.3.0 → celerp-2.3.2}/celerp/output/pdf.py +0 -0
  249. {celerp-2.3.0 → celerp-2.3.2}/celerp/output/share_render.py +0 -0
  250. {celerp-2.3.0 → celerp-2.3.2}/celerp/projections/__init__.py +0 -0
  251. {celerp-2.3.0 → celerp-2.3.2}/celerp/projections/handlers/__init__.py +0 -0
  252. {celerp-2.3.0 → celerp-2.3.2}/celerp/projections/handlers/marketplace.py +0 -0
  253. {celerp-2.3.0 → celerp-2.3.2}/celerp/projections/handlers/scanning.py +0 -0
  254. {celerp-2.3.0 → celerp-2.3.2}/celerp/projections/handlers/shopify.py +0 -0
  255. {celerp-2.3.0 → celerp-2.3.2}/celerp/projections/handlers/system.py +0 -0
  256. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/__init__.py +0 -0
  257. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/auth.py +0 -0
  258. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/companies.py +0 -0
  259. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/debug.py +0 -0
  260. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/doctor.py +0 -0
  261. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/events.py +0 -0
  262. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/health.py +0 -0
  263. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/ledger.py +0 -0
  264. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/notifications.py +0 -0
  265. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/stars.py +0 -0
  266. {celerp-2.3.0 → celerp-2.3.2}/celerp/routers/system.py +0 -0
  267. {celerp-2.3.0 → celerp-2.3.2}/celerp/schemas/__init__.py +0 -0
  268. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/__init__.py +0 -0
  269. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/activity_redaction.py +0 -0
  270. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/attachments.py +0 -0
  271. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/auth.py +0 -0
  272. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/auto_je.py +0 -0
  273. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/backup.py +0 -0
  274. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/backup_export.py +0 -0
  275. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/backup_import.py +0 -0
  276. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/backup_repo.py +0 -0
  277. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/backup_scheduler.py +0 -0
  278. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/backup_state.py +0 -0
  279. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/cogs_backfill.py +0 -0
  280. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/cost_visibility.py +0 -0
  281. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/demo.py +0 -0
  282. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/dev_release_guard.py +0 -0
  283. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/email.py +0 -0
  284. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/holdings.py +0 -0
  285. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/je_keys.py +0 -0
  286. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/landed_cost.py +0 -0
  287. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/line_measures.py +0 -0
  288. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/list_behavior.py +0 -0
  289. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/money.py +0 -0
  290. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/payments.py +0 -0
  291. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/permissions.py +0 -0
  292. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/pick.py +0 -0
  293. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/pricing.py +0 -0
  294. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/relay_share.py +0 -0
  295. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/reorder.py +0 -0
  296. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/runtime_state.py +0 -0
  297. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/session_tracker.py +0 -0
  298. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/shipping.py +0 -0
  299. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/star_cta.py +0 -0
  300. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/status_doc_backfill.py +0 -0
  301. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/supporter_badge.py +0 -0
  302. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/system_health.py +0 -0
  303. {celerp-2.3.0 → celerp-2.3.2}/celerp/services/units.py +0 -0
  304. {celerp-2.3.0 → celerp-2.3.2}/celerp/session_gate.py +0 -0
  305. {celerp-2.3.0 → celerp-2.3.2}/celerp.egg-info/dependency_links.txt +0 -0
  306. {celerp-2.3.0 → celerp-2.3.2}/celerp.egg-info/entry_points.txt +0 -0
  307. {celerp-2.3.0 → celerp-2.3.2}/celerp.egg-info/requires.txt +0 -0
  308. {celerp-2.3.0 → celerp-2.3.2}/celerp.egg-info/top_level.txt +0 -0
  309. {celerp-2.3.0 → celerp-2.3.2}/conftest.py +0 -0
  310. {celerp-2.3.0 → celerp-2.3.2}/conftest_support.py +0 -0
  311. {celerp-2.3.0 → celerp-2.3.2}/default_modules/__init__.py +0 -0
  312. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/LICENSE +0 -0
  313. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/__init__.py +0 -0
  314. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/celerp_accounting/__init__.py +0 -0
  315. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/celerp_accounting/api_setup.py +0 -0
  316. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/celerp_accounting/csv_parser.py +0 -0
  317. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/celerp_accounting/matcher.py +0 -0
  318. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/celerp_accounting/models.py +0 -0
  319. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/celerp_accounting/projections.py +0 -0
  320. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/celerp_accounting/routes.py +0 -0
  321. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/celerp_accounting/ui_routes.py +0 -0
  322. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/balance-sheet.html +0 -0
  323. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/cash-flow.html +0 -0
  324. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/extended-journal-csv.csv +0 -0
  325. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/extended-journal-print.html +0 -0
  326. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/extended-journal.html +0 -0
  327. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/general-ledger.html +0 -0
  328. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/journal-csv.csv +0 -0
  329. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/journal-print.html +0 -0
  330. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/journal.html +0 -0
  331. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/ledger.html +0 -0
  332. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/pnl.html +0 -0
  333. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/report_goldens/trial-balance.html +0 -0
  334. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_accounting_banking.py +0 -0
  335. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_accounting_banking_routers.py +0 -0
  336. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_accounting_gaps.py +0 -0
  337. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_accounting_import_idempotency.py +0 -0
  338. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_cash_flow.py +0 -0
  339. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_financial_reports_ui.py +0 -0
  340. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_journal_gl_soa.py +0 -0
  341. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_journal_gl_soa_ui.py +0 -0
  342. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_reconciliation_v2.py +0 -0
  343. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_reports_end_to_end.py +0 -0
  344. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-accounting/tests/test_route_permissions.py +0 -0
  345. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-admin/__init__.py +0 -0
  346. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-admin/celerp_admin/__init__.py +0 -0
  347. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-admin/celerp_admin/routes.py +0 -0
  348. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-admin/celerp_admin/setup.py +0 -0
  349. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/__init__.py +0 -0
  350. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/celerp_ai/__init__.py +0 -0
  351. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/celerp_ai/routes.py +0 -0
  352. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/celerp_ai/setup.py +0 -0
  353. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/conftest.py +0 -0
  354. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_batch.py +0 -0
  355. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_cleanup.py +0 -0
  356. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_conversations.py +0 -0
  357. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_coverage_gaps.py +0 -0
  358. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_intent.py +0 -0
  359. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_llm.py +0 -0
  360. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_memory.py +0 -0
  361. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_models.py +0 -0
  362. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_page_count.py +0 -0
  363. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_quota.py +0 -0
  364. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_router.py +0 -0
  365. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_routes_coverage.py +0 -0
  366. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_service.py +0 -0
  367. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-ai/tests/test_tools.py +0 -0
  368. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-backup/__init__.py +0 -0
  369. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-backup/celerp_backup/__init__.py +0 -0
  370. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-backup/celerp_backup/setup.py +0 -0
  371. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/__init__.py +0 -0
  372. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/celerp_connectors/__init__.py +0 -0
  373. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/celerp_connectors/models.py +0 -0
  374. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/celerp_connectors/routes.py +0 -0
  375. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/__init__.py +0 -0
  376. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/conftest.py +0 -0
  377. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_compliance.py +0 -0
  378. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_connector_correctness.py +0 -0
  379. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_connectors.py +0 -0
  380. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_credentials_routes.py +0 -0
  381. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_images.py +0 -0
  382. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_outbound.py +0 -0
  383. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_quickbooks.py +0 -0
  384. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_rate_limiting.py +0 -0
  385. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_shopify.py +0 -0
  386. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_wiring.py +0 -0
  387. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_woocommerce.py +0 -0
  388. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_woocommerce_webhooks.py +0 -0
  389. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-connectors/tests/test_xero.py +0 -0
  390. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-contacts/LICENSE +0 -0
  391. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-contacts/__init__.py +0 -0
  392. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-contacts/celerp_contacts/__init__.py +0 -0
  393. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-contacts/celerp_contacts/migrations.py +0 -0
  394. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-contacts/celerp_contacts/projections.py +0 -0
  395. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-contacts/celerp_contacts/routes.py +0 -0
  396. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-contacts/celerp_contacts/services.py +0 -0
  397. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-contacts/celerp_contacts/ui_routes.py +0 -0
  398. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-dashboard/LICENSE +0 -0
  399. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-dashboard/__init__.py +0 -0
  400. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-dashboard/celerp_dashboard/__init__.py +0 -0
  401. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-dashboard/celerp_dashboard/routes.py +0 -0
  402. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-dashboard/celerp_dashboard/setup.py +0 -0
  403. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/LICENSE +0 -0
  404. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/__init__.py +0 -0
  405. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/__init__.py +0 -0
  406. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/api_setup.py +0 -0
  407. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/doc_constants.py +0 -0
  408. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/doc_email.py +0 -0
  409. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/doc_projections.py +0 -0
  410. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/doc_service.py +0 -0
  411. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/models_share.py +0 -0
  412. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/routes_payments.py +0 -0
  413. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/routes_share.py +0 -0
  414. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/sequences.py +0 -0
  415. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/taxes.py +0 -0
  416. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/celerp_docs/ui_routes.py +0 -0
  417. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/conftest.py +0 -0
  418. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_consolidate_lots.py +0 -0
  419. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_freight_je.py +0 -0
  420. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_freight_lines.py +0 -0
  421. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_fulfill_no_split.py +0 -0
  422. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_fulfillment_activity.py +0 -0
  423. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_inbound_je_lifecycle.py +0 -0
  424. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_inventory_account_reconciliation.py +0 -0
  425. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_landed_receive.py +0 -0
  426. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_line_delete_persist.py +0 -0
  427. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_line_identifier.py +0 -0
  428. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_payment_void_activity.py +0 -0
  429. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_receive_sku_batch.py +0 -0
  430. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_send_visibility.py +0 -0
  431. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_service_lines.py +0 -0
  432. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_void_guards.py +0 -0
  433. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-docs/tests/test_writeoffs.py +0 -0
  434. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/LICENSE +0 -0
  435. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/__init__.py +0 -0
  436. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/celerp_inventory/__init__.py +0 -0
  437. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/celerp_inventory/models_import_batch.py +0 -0
  438. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/celerp_inventory/projections.py +0 -0
  439. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/celerp_inventory/routes_attachments.py +0 -0
  440. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/celerp_inventory/ui_routes.py +0 -0
  441. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/tests/test_item_recipe_projection.py +0 -0
  442. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/tests/test_item_workflow_projection.py +0 -0
  443. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-inventory/tests/test_landed_cost_projection.py +0 -0
  444. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/LICENSE +0 -0
  445. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/celerp_labels/__init__.py +0 -0
  446. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/celerp_labels/models.py +0 -0
  447. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/celerp_labels/presets.py +0 -0
  448. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/celerp_labels/routes.py +0 -0
  449. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/celerp_labels/service.py +0 -0
  450. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/requirements.txt +0 -0
  451. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/tests/test_labels.py +0 -0
  452. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-labels/tests/test_labels_module.py +0 -0
  453. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/LICENSE +0 -0
  454. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/__init__.py +0 -0
  455. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/celerp_manufacturing/__init__.py +0 -0
  456. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/celerp_manufacturing/costing.py +0 -0
  457. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/celerp_manufacturing/expansion.py +0 -0
  458. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/celerp_manufacturing/labor.py +0 -0
  459. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/celerp_manufacturing/migrations.py +0 -0
  460. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/celerp_manufacturing/projection_handler.py +0 -0
  461. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/celerp_manufacturing/ui_routes.py +0 -0
  462. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/requirements.txt +0 -0
  463. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_auto_complete_on_finalize.py +0 -0
  464. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_bom_removed.py +0 -0
  465. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_build_api.py +0 -0
  466. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_item_recipe_api.py +0 -0
  467. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_item_workflow_api.py +0 -0
  468. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_labor_providers.py +0 -0
  469. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_manufacture_from_doc.py +0 -0
  470. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_manufacturing.py +0 -0
  471. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_manufacturing_import_idempotency.py +0 -0
  472. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_manufacturing_module.py +0 -0
  473. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_mfg_events.py +0 -0
  474. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_phase2_manufacturing_validations.py +0 -0
  475. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_production_order.py +0 -0
  476. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_recipe_costing.py +0 -0
  477. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_recipe_expansion.py +0 -0
  478. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_recost_api.py +0 -0
  479. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_to_make_allocation.py +0 -0
  480. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_where_used.py +0 -0
  481. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_work_centers_and_settings.py +0 -0
  482. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-manufacturing/tests/test_workflow_time.py +0 -0
  483. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-reports/LICENSE +0 -0
  484. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-reports/__init__.py +0 -0
  485. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-reports/celerp_reports/__init__.py +0 -0
  486. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-reports/celerp_reports/api_setup.py +0 -0
  487. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-reports/celerp_reports/routes.py +0 -0
  488. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-reports/celerp_reports/ui_routes.py +0 -0
  489. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-reports/tests/test_reports_full.py +0 -0
  490. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-reports/tests/test_reports_unit.py +0 -0
  491. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-subscriptions/LICENSE +0 -0
  492. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-subscriptions/__init__.py +0 -0
  493. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-subscriptions/celerp_subscriptions/__init__.py +0 -0
  494. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-subscriptions/celerp_subscriptions/routes.py +0 -0
  495. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-subscriptions/celerp_subscriptions/ui_routes.py +0 -0
  496. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-subscriptions/tests/test_subscriptions.py +0 -0
  497. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-subscriptions/tests/test_subscriptions_ui.py +0 -0
  498. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/LICENSE +0 -0
  499. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/__init__.py +0 -0
  500. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/__init__.py +0 -0
  501. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/accessory_fashion.json +0 -0
  502. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/activewear.json +0 -0
  503. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/art_photography.json +0 -0
  504. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/audio_equipment.json +0 -0
  505. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/bag_handbag.json +0 -0
  506. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/banknote.json +0 -0
  507. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/beauty_tool.json +0 -0
  508. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/bed_bedroom.json +0 -0
  509. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/beer.json +0 -0
  510. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/beverage_nonalc.json +0 -0
  511. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/body_part_auto.json +0 -0
  512. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/book.json +0 -0
  513. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/bottoms.json +0 -0
  514. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/brake_suspension.json +0 -0
  515. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/bullion_coin.json +0 -0
  516. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/camera.json +0 -0
  517. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/colored_stone.json +0 -0
  518. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/comic.json +0 -0
  519. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/commercial_space.json +0 -0
  520. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/component_part.json +0 -0
  521. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/confectionery.json +0 -0
  522. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/consulting_service.json +0 -0
  523. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/decorative_art.json +0 -0
  524. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/diamond.json +0 -0
  525. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/drawing.json +0 -0
  526. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/dress_jumpsuit.json +0 -0
  527. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_auto.json +0 -0
  528. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_component.json +0 -0
  529. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/emerald.json +0 -0
  530. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/engine_part.json +0 -0
  531. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/fastener.json +0 -0
  532. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/fertilizer_chemical.json +0 -0
  533. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/film_video.json +0 -0
  534. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/fine_writing_instrument.json +0 -0
  535. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/fluid_lubricant.json +0 -0
  536. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/footwear.json +0 -0
  537. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/fragrance.json +0 -0
  538. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_food.json +0 -0
  539. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_produce.json +0 -0
  540. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/frozen_food.json +0 -0
  541. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/gaming_console.json +0 -0
  542. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/gold_bullion.json +0 -0
  543. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/grain_cereal.json +0 -0
  544. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/haircare.json +0 -0
  545. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/hand_tool.json +0 -0
  546. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/ingredient_bulk.json +0 -0
  547. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/interior_part.json +0 -0
  548. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/jewelry.json +0 -0
  549. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/kitchen_dining.json +0 -0
  550. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/laptop.json +0 -0
  551. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/lighting.json +0 -0
  552. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/livestock_feed.json +0 -0
  553. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/makeup.json +0 -0
  554. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/measuring_instrument.json +0 -0
  555. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/medal_token.json +0 -0
  556. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/mineral_specimen.json +0 -0
  557. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/mobile_phone.json +0 -0
  558. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/music_cd.json +0 -0
  559. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/music_vinyl.json +0 -0
  560. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/nail.json +0 -0
  561. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/numismatic_coin.json +0 -0
  562. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/outdoor_furniture.json +0 -0
  563. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/outerwear.json +0 -0
  564. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/packaged_food.json +0 -0
  565. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/painting.json +0 -0
  566. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/parking_bay.json +0 -0
  567. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/pearl.json +0 -0
  568. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/personal_care.json +0 -0
  569. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/pipe_plumbing.json +0 -0
  570. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/platinum_bullion.json +0 -0
  571. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/power_tool.json +0 -0
  572. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/print_edition.json +0 -0
  573. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/residential_unit.json +0 -0
  574. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/rough_gemstone.json +0 -0
  575. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/ruby.json +0 -0
  576. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/saas_plan.json +0 -0
  577. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/safety_ppe.json +0 -0
  578. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/sapphire.json +0 -0
  579. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/sculpture.json +0 -0
  580. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/seating.json +0 -0
  581. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/seeds.json +0 -0
  582. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/silver_bullion.json +0 -0
  583. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/skincare.json +0 -0
  584. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/soft_furnishing.json +0 -0
  585. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/software_addon.json +0 -0
  586. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/software_license.json +0 -0
  587. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/spirit.json +0 -0
  588. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/storage_furniture.json +0 -0
  589. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/swimwear.json +0 -0
  590. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/table_desk.json +0 -0
  591. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/tablet.json +0 -0
  592. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/tire_wheel.json +0 -0
  593. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/tops.json +0 -0
  594. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/trading_card.json +0 -0
  595. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/tv_display.json +0 -0
  596. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/video_game.json +0 -0
  597. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/watch.json +0 -0
  598. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/watch_strap.json +0 -0
  599. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/categories/wine.json +0 -0
  600. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/agricultural.json +0 -0
  601. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/artwork.json +0 -0
  602. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/automotive.json +0 -0
  603. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/blank.json +0 -0
  604. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/books_media.json +0 -0
  605. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/coins_precious_metals.json +0 -0
  606. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/consulting.json +0 -0
  607. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/cosmetics.json +0 -0
  608. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/electronics.json +0 -0
  609. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/fashion.json +0 -0
  610. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/food_beverage.json +0 -0
  611. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/furniture.json +0 -0
  612. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/gemstones.json +0 -0
  613. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/hardware.json +0 -0
  614. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/property_rental.json +0 -0
  615. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/saas.json +0 -0
  616. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/watches.json +0 -0
  617. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/presets/wine_spirits.json +0 -0
  618. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/routes.py +0 -0
  619. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/celerp_verticals/ui_routes.py +0 -0
  620. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/tests/test_verticals.py +0 -0
  621. {celerp-2.3.0 → celerp-2.3.2}/default_modules/celerp-verticals/tests/test_verticals_routers.py +0 -0
  622. {celerp-2.3.0 → celerp-2.3.2}/legal/OFFICIAL-COMPONENTS.md +0 -0
  623. {celerp-2.3.0 → celerp-2.3.2}/legal/TRADEMARK.md +0 -0
  624. {celerp-2.3.0 → celerp-2.3.2}/packaging/winget/Celerp.Celerp.installer.yaml +0 -0
  625. {celerp-2.3.0 → celerp-2.3.2}/packaging/winget/Celerp.Celerp.locale.en-US.yaml +0 -0
  626. {celerp-2.3.0 → celerp-2.3.2}/packaging/winget/Celerp.Celerp.yaml +0 -0
  627. {celerp-2.3.0 → celerp-2.3.2}/packaging/winget/README.md +0 -0
  628. {celerp-2.3.0 → celerp-2.3.2}/pyproject.toml +0 -0
  629. {celerp-2.3.0 → celerp-2.3.2}/setup.cfg +0 -0
  630. {celerp-2.3.0 → celerp-2.3.2}/test_helpers.py +0 -0
  631. {celerp-2.3.0 → celerp-2.3.2}/ui/__init__.py +0 -0
  632. {celerp-2.3.0 → celerp-2.3.2}/ui/components/__init__.py +0 -0
  633. {celerp-2.3.0 → celerp-2.3.2}/ui/components/attrs.py +0 -0
  634. {celerp-2.3.0 → celerp-2.3.2}/ui/components/journal.py +0 -0
  635. {celerp-2.3.0 → celerp-2.3.2}/ui/components/phone.py +0 -0
  636. {celerp-2.3.0 → celerp-2.3.2}/ui/config.py +0 -0
  637. {celerp-2.3.0 → celerp-2.3.2}/ui/marketplace_catalog.py +0 -0
  638. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/__init__.py +0 -0
  639. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/events.py +0 -0
  640. {celerp-2.3.0 → celerp-2.3.2}/ui/routes/notifications.py +0 -0
  641. {celerp-2.3.0 → celerp-2.3.2}/ui/security.py +0 -0
  642. {celerp-2.3.0 → celerp-2.3.2}/ui/static/htmx.min.js +0 -0
  643. {celerp-2.3.0 → celerp-2.3.2}/ui/static/icon.png +0 -0
  644. {celerp-2.3.0 → celerp-2.3.2}/ui/static/logo.png +0 -0
  645. {celerp-2.3.0 → celerp-2.3.2}/ui/static/vendor/intl-tel-input/img/flags.webp +0 -0
  646. {celerp-2.3.0 → celerp-2.3.2}/ui/static/vendor/intl-tel-input/img/flags@2x.webp +0 -0
  647. {celerp-2.3.0 → celerp-2.3.2}/ui/static/vendor/intl-tel-input/intlTelInput.min.css +0 -0
  648. {celerp-2.3.0 → celerp-2.3.2}/ui/static/vendor/intl-tel-input/intlTelInput.min.js +0 -0
  649. {celerp-2.3.0 → celerp-2.3.2}/ui/static/vendor/intl-tel-input/intlTelInputWithUtils.min.js +0 -0
  650. {celerp-2.3.0 → celerp-2.3.2}/ui/static/vendor/intl-tel-input/utils.js +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: celerp
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Free, self-hosted ERP for small businesses
5
5
  License: Business Source License 1.1
6
6
 
@@ -5,7 +5,18 @@ from __future__ import annotations
5
5
 
6
6
  from typing import Any
7
7
 
8
- from pydantic import BaseModel, Field
8
+ from pydantic import BaseModel, Field, model_validator
9
+
10
+ # The SKU/barcode write-time predicates live in celerp.inventory_codes so the event
11
+ # boundary, the interactive routes, the allocation service, and the scanner share one
12
+ # source of truth. reject_comma_sku/SKU_COMMA_MESSAGE are re-exported here because
13
+ # celerp_inventory.routes imports them from this module.
14
+ from celerp.inventory_codes import ( # noqa: F401 - re-exported for celerp_inventory
15
+ SKU_COMMA_MESSAGE,
16
+ reject_comma_sku,
17
+ validate_barcode,
18
+ validate_sku,
19
+ )
9
20
 
10
21
 
11
22
  # -----------------
@@ -13,7 +24,27 @@ from pydantic import BaseModel, Field
13
24
  # -----------------
14
25
 
15
26
 
16
- class ItemCreated(BaseModel):
27
+ class _SkuGuard(BaseModel):
28
+ """Mixin: enforce the SKU and barcode invariants on any item event that sets them.
29
+
30
+ SKU: no comma (Celerp's OR operator in the SKU/search syntax) and a bounded length.
31
+ Barcode: digits only and a bounded length. These are the canonical write-time
32
+ predicates; interactive routes wrap them to surface a friendly 422, every other
33
+ emitter hits them here at the event boundary (imports, connector upserts, document
34
+ receiving). Replay never runs these schemas (the reducer does), so enforcing here
35
+ can never brick a historical projection.
36
+ """
37
+
38
+ @model_validator(mode="before")
39
+ @classmethod
40
+ def _guard_item_codes(cls, data: Any) -> Any:
41
+ if isinstance(data, dict):
42
+ validate_sku(data.get("sku"))
43
+ validate_barcode(data.get("barcode"))
44
+ return data
45
+
46
+
47
+ class ItemCreated(_SkuGuard):
17
48
  sku: str
18
49
  name: str
19
50
  quantity: float = 0
@@ -28,7 +59,7 @@ class ItemCreated(BaseModel):
28
59
  model_config = {"extra": "allow"}
29
60
 
30
61
 
31
- class ItemSnapshot(BaseModel):
62
+ class ItemSnapshot(_SkuGuard):
32
63
  """Snapshot of full item state - used for imports. sku/name optional (absent in some sources)."""
33
64
 
34
65
  sku: str | None = None
@@ -53,6 +84,14 @@ class ItemSnapshot(BaseModel):
53
84
  class ItemUpdated(BaseModel):
54
85
  fields_changed: dict[str, dict[str, Any]]
55
86
 
87
+ @model_validator(mode="after")
88
+ def _guard_item_codes(self) -> "ItemUpdated":
89
+ if "sku" in self.fields_changed:
90
+ validate_sku((self.fields_changed.get("sku") or {}).get("new"))
91
+ if "barcode" in self.fields_changed:
92
+ validate_barcode((self.fields_changed.get("barcode") or {}).get("new"))
93
+ return self
94
+
56
95
 
57
96
  class ItemPricingSet(BaseModel):
58
97
  price_type: str
@@ -188,7 +227,7 @@ class ItemMerged(BaseModel):
188
227
  source_entity_ids: list[str]
189
228
 
190
229
 
191
- class ItemPatched(BaseModel):
230
+ class ItemPatched(_SkuGuard):
192
231
  """CSV upsert patch: accepts any item data fields."""
193
232
  model_config = {"extra": "allow"}
194
233
 
@@ -0,0 +1,87 @@
1
+ # Copyright (c) 2026 Noah Severs
2
+ # SPDX-License-Identifier: BUSL-1.1
3
+
4
+ """Canonical inventory code limits and validation - one source of truth.
5
+
6
+ The SKU/barcode invariants live here so the event boundary (celerp.events.schemas),
7
+ the interactive inventory routes, the allocation service, and the scanner all share
8
+ the exact same rules. A comma is Celerp's OR operator in the SKU/search syntax, so a
9
+ SKU may never contain one (it would split into separate codes wherever SKUs are
10
+ matched). A barcode is a numeric physical-lot identifier and must be unique per
11
+ company - enforced at the event boundary (format) and by a partial unique index on
12
+ the projections table (uniqueness).
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from typing import Any
18
+
19
+ MAX_BARCODE_LEN = 64
20
+ MAX_SKU_LEN = 255
21
+ MAX_SCAN_CODE_LEN = max(MAX_BARCODE_LEN, MAX_SKU_LEN)
22
+
23
+ # Partial unique index enforcing at-most-one item per (company, barcode). Declared on
24
+ # the Projection model so create_all builds it for the test schema, and created on
25
+ # existing databases by the barcode-uniqueness migration. Named here so the applier
26
+ # can tell a barcode violation apart from the (company_id, entity_id) primary-key race.
27
+ BARCODE_UNIQUE_INDEX = "uq_projection_company_item_barcode"
28
+
29
+ SKU_COMMA_MESSAGE = "SKU cannot contain a comma"
30
+ SKU_TOO_LONG_MESSAGE = f"SKU cannot exceed {MAX_SKU_LEN} characters"
31
+ BARCODE_NOT_DIGITS_MESSAGE = "Barcode must contain only digits"
32
+ BARCODE_TOO_LONG_MESSAGE = f"Barcode cannot exceed {MAX_BARCODE_LEN} characters"
33
+ BARCODE_CONFLICT_MESSAGE = "Barcode '{barcode}' already exists"
34
+
35
+
36
+ def reject_comma_sku(sku: Any) -> Any:
37
+ """Reject a comma-bearing SKU. Returns the sku for chaining."""
38
+ if sku is not None and "," in str(sku):
39
+ raise ValueError(SKU_COMMA_MESSAGE)
40
+ return sku
41
+
42
+
43
+ def validate_sku(sku: Any) -> Any:
44
+ """Reject a comma-bearing or over-long SKU. Returns the sku for chaining."""
45
+ reject_comma_sku(sku)
46
+ if sku is not None and len(str(sku)) > MAX_SKU_LEN:
47
+ raise ValueError(SKU_TOO_LONG_MESSAGE)
48
+ return sku
49
+
50
+
51
+ def validate_barcode(barcode: Any) -> Any:
52
+ """Reject a non-digit or over-long barcode. An absent/empty barcode is allowed."""
53
+ if barcode is None:
54
+ return barcode
55
+ s = str(barcode)
56
+ if s == "":
57
+ return barcode
58
+ if not s.isdigit():
59
+ raise ValueError(BARCODE_NOT_DIGITS_MESSAGE)
60
+ if len(s) > MAX_BARCODE_LEN:
61
+ raise ValueError(BARCODE_TOO_LONG_MESSAGE)
62
+ return barcode
63
+
64
+
65
+ class BarcodeConflictError(Exception):
66
+ """A write violated the (company, item, barcode) uniqueness invariant.
67
+
68
+ Raised by the projection applier when the DB unique index rejects an insert - the
69
+ final defense for any writer that bypasses the application lock (imports,
70
+ connectors, a future writer). The API layer maps it to 409.
71
+ """
72
+
73
+ def __init__(self, barcode: str | None = None):
74
+ self.barcode = barcode
75
+ super().__init__(
76
+ BARCODE_CONFLICT_MESSAGE.format(barcode=barcode) if barcode else "Barcode already exists"
77
+ )
78
+
79
+
80
+ def is_barcode_unique_violation(exc: Exception) -> bool:
81
+ """True when an IntegrityError is the barcode unique-index violation (not the PK race)."""
82
+ orig = getattr(exc, "orig", None)
83
+ if getattr(orig, "constraint_name", None) == BARCODE_UNIQUE_INDEX:
84
+ return True
85
+ # Expression-index violations do not always populate constraint_name across drivers;
86
+ # the index name still appears in the server message.
87
+ return BARCODE_UNIQUE_INDEX in str(exc)
@@ -13,6 +13,7 @@ from slowapi.errors import RateLimitExceeded
13
13
  from slowapi.util import get_remote_address
14
14
 
15
15
  from celerp.db import engine, mask_db_credentials
16
+ from celerp.inventory_codes import BarcodeConflictError
16
17
  from celerp.config import settings, assert_secure_jwt, ensure_instance_id, load_cloud_config, load_backup_config
17
18
  load_cloud_config()
18
19
  load_backup_config()
@@ -447,6 +448,14 @@ async def rate_limit_handler(_request: Request, _exc: RateLimitExceeded):
447
448
  return JSONResponse(status_code=429, content={"detail": "Rate limit exceeded"})
448
449
 
449
450
 
451
+ @app.exception_handler(BarcodeConflictError)
452
+ async def barcode_conflict_handler(_request: Request, exc: BarcodeConflictError):
453
+ # The projection applier raises this when the barcode unique index rejects a write
454
+ # that bypassed the allocation lock (imports, connectors). A more specific handler
455
+ # than the Exception catch-all, so it maps to 409 instead of a masked 500.
456
+ return JSONResponse(status_code=409, content={"detail": str(exc)})
457
+
458
+
450
459
  # Kernel routes — always present regardless of module configuration
451
460
  app.include_router(health.router, tags=["system"])
452
461
  app.include_router(auth.router, prefix="/auth", tags=["auth"])
@@ -0,0 +1,119 @@
1
+ # Copyright (c) 2026 Noah Severs
2
+ # SPDX-License-Identifier: BUSL-1.1
3
+
4
+ """Enforce at-most-one item per (company, barcode) with a partial unique index.
5
+
6
+ Revision ID: bc0d1e2f3a4b
7
+ Revises: b3c4d5e6f7a8
8
+ Create Date: 2026-08-25
9
+
10
+ Context
11
+ -------
12
+ A barcode identifies at most one physical-lot item per company. Until now that was
13
+ only enforced by an application check under a lock; any writer bypassing the lock
14
+ (imports, connectors, a future writer) could create duplicates, and legacy databases
15
+ may already hold some.
16
+
17
+ This migration is the final defense: a PostgreSQL partial expression unique index on
18
+ ``(company_id, state ->> 'barcode')`` for item projections with a non-empty barcode.
19
+
20
+ It refuses to create the index while incompatible data exists rather than silently
21
+ renaming or clearing anything. A preflight scans for duplicate non-empty barcodes,
22
+ barcodes over the length limit, SKUs over the length limit, and comma-bearing SKUs,
23
+ and stops with an actionable report (company, value, affected entity ids) so an
24
+ operator can remediate and re-run.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import sqlalchemy as sa
30
+ from alembic import op
31
+
32
+ from celerp.inventory_codes import BARCODE_UNIQUE_INDEX, MAX_BARCODE_LEN, MAX_SKU_LEN
33
+
34
+ revision = "bc0d1e2f3a4b"
35
+ down_revision = "b3c4d5e6f7a8"
36
+ branch_labels = None
37
+ depends_on = None
38
+
39
+
40
+ def _preflight(conn) -> list[str]:
41
+ """Return a list of human-readable remediation problems; empty means clean."""
42
+ problems: list[str] = []
43
+
44
+ dups = conn.execute(
45
+ sa.text(
46
+ "SELECT company_id, state ->> 'barcode' AS barcode, "
47
+ " array_agg(entity_id ORDER BY entity_id) AS entities "
48
+ "FROM projections "
49
+ "WHERE entity_type = 'item' AND NULLIF(state ->> 'barcode', '') IS NOT NULL "
50
+ "GROUP BY company_id, state ->> 'barcode' "
51
+ "HAVING count(*) > 1"
52
+ )
53
+ ).fetchall()
54
+ for row in dups:
55
+ problems.append(
56
+ f"duplicate barcode {row.barcode!r} in company {row.company_id}: entities {list(row.entities)}"
57
+ )
58
+
59
+ long_barcodes = conn.execute(
60
+ sa.text(
61
+ "SELECT company_id, entity_id, state ->> 'barcode' AS barcode "
62
+ "FROM projections "
63
+ "WHERE entity_type = 'item' AND length(state ->> 'barcode') > :n"
64
+ ),
65
+ {"n": MAX_BARCODE_LEN},
66
+ ).fetchall()
67
+ for row in long_barcodes:
68
+ problems.append(
69
+ f"barcode {row.barcode!r} over {MAX_BARCODE_LEN} chars in company {row.company_id} entity {row.entity_id}"
70
+ )
71
+
72
+ long_skus = conn.execute(
73
+ sa.text(
74
+ "SELECT company_id, entity_id "
75
+ "FROM projections "
76
+ "WHERE entity_type = 'item' AND length(state ->> 'sku') > :n"
77
+ ),
78
+ {"n": MAX_SKU_LEN},
79
+ ).fetchall()
80
+ for row in long_skus:
81
+ problems.append(
82
+ f"SKU over {MAX_SKU_LEN} chars in company {row.company_id} entity {row.entity_id}"
83
+ )
84
+
85
+ comma_skus = conn.execute(
86
+ sa.text(
87
+ "SELECT company_id, entity_id, state ->> 'sku' AS sku "
88
+ "FROM projections "
89
+ "WHERE entity_type = 'item' AND position(',' in state ->> 'sku') > 0"
90
+ )
91
+ ).fetchall()
92
+ for row in comma_skus:
93
+ problems.append(
94
+ f"comma-bearing SKU {row.sku!r} in company {row.company_id} entity {row.entity_id}"
95
+ )
96
+
97
+ return problems
98
+
99
+
100
+ def upgrade() -> None:
101
+ conn = op.get_bind()
102
+
103
+ problems = _preflight(conn)
104
+ if problems:
105
+ raise RuntimeError(
106
+ "Cannot create the barcode uniqueness index: incompatible item data exists. "
107
+ "Resolve each of the following (rename or clear the barcode/SKU on the affected "
108
+ "items), then re-run the migration:\n - " + "\n - ".join(problems)
109
+ )
110
+
111
+ op.execute(
112
+ f"CREATE UNIQUE INDEX IF NOT EXISTS {BARCODE_UNIQUE_INDEX} "
113
+ "ON projections (company_id, (state ->> 'barcode')) "
114
+ "WHERE entity_type = 'item' AND NULLIF(state ->> 'barcode', '') IS NOT NULL"
115
+ )
116
+
117
+
118
+ def downgrade() -> None:
119
+ op.execute(f"DROP INDEX IF EXISTS {BARCODE_UNIQUE_INDEX}")
@@ -9,12 +9,27 @@ import sqlalchemy as sa
9
9
  from sqlalchemy import BigInteger, Boolean, DateTime, ForeignKey, PrimaryKeyConstraint, String, Text
10
10
  from sqlalchemy.orm import Mapped, mapped_column
11
11
 
12
+ from celerp.inventory_codes import BARCODE_UNIQUE_INDEX
12
13
  from celerp.models.base import Base
13
14
 
14
15
 
15
16
  class Projection(Base):
16
17
  __tablename__ = "projections"
17
- __table_args__ = (PrimaryKeyConstraint("company_id", "entity_id"),)
18
+ __table_args__ = (
19
+ PrimaryKeyConstraint("company_id", "entity_id"),
20
+ # At most one item per (company, non-empty barcode). The final defense behind
21
+ # the application allocation lock: imports, connectors, or a future writer that
22
+ # bypasses the lock still cannot create a duplicate barcode. Declared here so
23
+ # create_all builds it for the test schema; created on existing databases by the
24
+ # barcode-uniqueness migration.
25
+ sa.Index(
26
+ BARCODE_UNIQUE_INDEX,
27
+ "company_id",
28
+ sa.text("(state ->> 'barcode')"),
29
+ unique=True,
30
+ postgresql_where=sa.text("entity_type = 'item' AND NULLIF(state ->> 'barcode', '') IS NOT NULL"),
31
+ ),
32
+ )
18
33
 
19
34
  entity_id: Mapped[str] = mapped_column(Text, nullable=False)
20
35
  company_id: Mapped[uuid.UUID] = mapped_column(sa.Uuid(as_uuid=True), ForeignKey("companies.id"), nullable=False)
@@ -10,6 +10,7 @@ from datetime import datetime, timezone
10
10
  from sqlalchemy import delete, select
11
11
  from sqlalchemy.exc import IntegrityError
12
12
 
13
+ from celerp.inventory_codes import BarcodeConflictError, is_barcode_unique_violation
13
14
  from celerp.models.ledger import LedgerEntry
14
15
  from celerp.models.projections import Projection
15
16
 
@@ -130,10 +131,33 @@ class ProjectionEngine:
130
131
  )
131
132
  await session.flush()
132
133
  return
133
- except IntegrityError:
134
+ except IntegrityError as exc:
135
+ # Only the (company_id, entity_id) primary-key race is a benign
136
+ # concurrent-first-insert to retry as an update on the winner's row.
137
+ # A barcode unique-index violation is a real conflict - surface it so
138
+ # the API maps it to 409 rather than swallowing it as a PK race.
139
+ if is_barcode_unique_violation(exc):
140
+ raise BarcodeConflictError((fields.get("state") or {}).get("barcode")) from exc
141
+ constraint = getattr(getattr(exc, "orig", None), "constraint_name", None)
142
+ if constraint not in (None, "projections_pkey"):
143
+ raise
134
144
  projection = await ProjectionEngine._locked_projection(session, entry)
135
- for column, value in ProjectionEngine._next_fields(projection.state, entry, projection.version).items():
145
+ if projection is None:
146
+ raise
147
+ fields = ProjectionEngine._next_fields(projection.state, entry, projection.version)
148
+ for column, value in fields.items():
136
149
  setattr(projection, column, value)
150
+ # Flush inside a SAVEPOINT so a barcode unique-index violation on an UPDATE
151
+ # (not only a first insert) surfaces as BarcodeConflictError -> 409 instead
152
+ # of escaping to the outer commit masked as a 500. Unrelated integrity errors
153
+ # re-raise unchanged.
154
+ try:
155
+ async with session.begin_nested():
156
+ await session.flush()
157
+ except IntegrityError as exc:
158
+ if is_barcode_unique_violation(exc):
159
+ raise BarcodeConflictError((fields.get("state") or {}).get("barcode")) from exc
160
+ raise
137
161
 
138
162
  @staticmethod
139
163
  async def rebuild(session, company_id=None) -> None:
@@ -44,42 +44,74 @@ _DEFAULT_PRICE_LISTS: list[dict] = [
44
44
 
45
45
  # Base schema fields (without price columns - those are injected dynamically)
46
46
  _BASE_FIELDS: list[dict] = [
47
- {"key": "sku", "label": "SKU", "type": "text", "editable": True, "required": True, "options": [], "visible_to_roles": [], "position": 0, "show_in_table": True},
48
- {"key": "name", "label": "Name", "type": "text", "editable": True, "required": True, "options": [], "visible_to_roles": [], "position": 1, "show_in_table": True},
49
- {"key": "category", "label": "Category", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 2, "show_in_table": True},
50
- {"key": "quantity", "label": "Qty", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3, "show_in_table": True, "tooltip_key": "field.tooltip.quantity"},
51
- {"key": "sell_by", "label": "Sell Unit", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.05,"show_in_table": False, "tooltip_key": "field.tooltip.sell_by"},
52
- {"key": "weight", "label": "Net Weight", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.02, "show_in_table": True, "tooltip_key": "field.tooltip.weight"},
53
- {"key": "weight_unit", "label": "Net Weight Unit", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.15,"show_in_table": False, "tooltip_key": "field.tooltip.weight_unit"},
54
- {"key": "pieces", "label": "Pieces", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.06,"show_in_table": True, "tooltip_key": "field.tooltip.pieces"},
55
- {"key": "reorder_point", "label": "Reorder Point", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.7, "show_in_table": False, "tooltip_key": "field.tooltip.reorder_point"},
56
- {"key": "reorder_qty", "label": "Reorder Qty", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.72,"show_in_table": False, "tooltip_key": "field.tooltip.reorder_qty"},
57
- {"key": "gross_weight", "label": "Gross Weight", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.25,"show_in_table": False, "tooltip_key": "field.tooltip.gross_weight"},
58
- {"key": "gross_weight_unit", "label": "Gross Weight Unit", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.3, "show_in_table": False, "tooltip_key": "field.tooltip.gross_weight_unit"},
59
- {"key": "inventory_type", "label": "Inventory Type", "type": "select", "editable": True, "required": False, "options": ["stocked", "component", "non_stocked", "service", "freight"], "visible_to_roles": [], "position": 4.2, "show_in_table": False, "tooltip_key": "field.tooltip.inventory_type"},
60
- {"key": "allow_splitting", "label": "Allow Splitting", "type": "bool", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 4.5, "show_in_table": False, "tooltip_key": "field.tooltip.allow_splitting"},
61
- {"key": "pick_method", "label": "Stock Cutting", "type": "select", "editable": True, "required": False, "options": ["default", "fifo", "fefo", "lifo"], "visible_to_roles": [], "position": 4.6, "show_in_table": False, "tooltip_key": "field.tooltip.pick_method"},
62
- {"key": "location_name", "label": "Location", "type": "text", "editable": False, "required": False, "options": [], "visible_to_roles": [], "position": 5, "show_in_table": True, "tooltip_key": "field.tooltip.location_name"},
47
+ {"key": "sku", "label": "SKU", "type": "text", "editable": True, "required": True, "options": [], "visible_to_roles": [], "position": 0, "show_in_table": True, "label_key": "field.label.sku"},
48
+ {"key": "name", "label": "Name", "type": "text", "editable": True, "required": True, "options": [], "visible_to_roles": [], "position": 1, "show_in_table": True, "label_key": "field.label.name"},
49
+ {"key": "category", "label": "Category", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 2, "show_in_table": True, "label_key": "field.label.category"},
50
+ {"key": "quantity", "label": "Qty", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3, "show_in_table": True, "tooltip_key": "field.tooltip.quantity", "label_key": "field.label.quantity"},
51
+ {"key": "sell_by", "label": "Sell Unit", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.05,"show_in_table": False, "tooltip_key": "field.tooltip.sell_by", "label_key": "field.label.sell_by"},
52
+ {"key": "weight", "label": "Net Weight", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.02, "show_in_table": True, "tooltip_key": "field.tooltip.weight", "label_key": "field.label.weight"},
53
+ {"key": "weight_unit", "label": "Net Weight Unit", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.15,"show_in_table": False, "tooltip_key": "field.tooltip.weight_unit", "label_key": "field.label.weight_unit"},
54
+ {"key": "pieces", "label": "Pieces", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.06,"show_in_table": True, "tooltip_key": "field.tooltip.pieces", "label_key": "field.label.pieces"},
55
+ {"key": "reorder_point", "label": "Reorder Point", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.7, "show_in_table": False, "tooltip_key": "field.tooltip.reorder_point", "label_key": "field.label.reorder_point"},
56
+ {"key": "reorder_qty", "label": "Reorder Qty", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.72,"show_in_table": False, "tooltip_key": "field.tooltip.reorder_qty", "label_key": "field.label.reorder_qty"},
57
+ {"key": "gross_weight", "label": "Gross Weight", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.25,"show_in_table": False, "tooltip_key": "field.tooltip.gross_weight", "label_key": "field.label.gross_weight"},
58
+ {"key": "gross_weight_unit", "label": "Gross Weight Unit", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 3.3, "show_in_table": False, "tooltip_key": "field.tooltip.gross_weight_unit", "label_key": "field.label.gross_weight_unit"},
59
+ {"key": "inventory_type", "label": "Inventory Type", "type": "select", "editable": True, "required": False, "options": ["stocked", "component", "non_stocked", "service", "freight"], "visible_to_roles": [], "position": 4.2, "show_in_table": False, "tooltip_key": "field.tooltip.inventory_type", "label_key": "field.label.inventory_type"},
60
+ {"key": "allow_splitting", "label": "Allow Splitting", "type": "bool", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 4.5, "show_in_table": False, "tooltip_key": "field.tooltip.allow_splitting", "label_key": "field.label.allow_splitting"},
61
+ {"key": "pick_method", "label": "Stock Cutting", "type": "select", "editable": True, "required": False, "options": ["default", "fifo", "fefo", "lifo"], "visible_to_roles": [], "position": 4.6, "show_in_table": False, "tooltip_key": "field.tooltip.pick_method", "label_key": "field.label.pick_method"},
62
+ {"key": "location_name", "label": "Location", "type": "text", "editable": False, "required": False, "options": [], "visible_to_roles": [], "position": 5, "show_in_table": True, "tooltip_key": "field.tooltip.location_name", "label_key": "field.label.location_name"},
63
63
  # Price columns are injected dynamically at position 6+ by _inject_price_columns()
64
64
  # Read-only: status changes only through dedicated actions (Make Available, Revert
65
65
  # to Draft), never a free-form dropdown edit - same convention as document status.
66
- {"key": "status", "label": "Status", "type": "status", "editable": False, "required": False, "options": [], "visible_to_roles": [], "position": 100, "show_in_table": True},
67
- {"key": "short_description", "label": "Short Description", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 101, "show_in_table": False},
68
- {"key": "description", "label": "Description", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 102, "show_in_table": False},
69
- {"key": "notes", "label": "Notes", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 103, "show_in_table": False},
70
- {"key": "barcode", "label": "Barcode", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104, "show_in_table": True, "tooltip_key": "field.tooltip.barcode"},
71
- {"key": "hs_code", "label": "HS Code", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.5, "show_in_table": False, "tooltip_key": "field.tooltip.hs_code"},
72
- {"key": "country_of_origin", "label": "Country of Origin", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.52,"show_in_table": False, "tooltip_key": "field.tooltip.country_of_origin"},
73
- {"key": "preferred_supplier","label": "Preferred Supplier","type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.54,"show_in_table": False, "tooltip_key": "field.tooltip.preferred_supplier"},
74
- {"key": "batch_no", "label": "Batch / Lot No", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.55,"show_in_table": False, "tooltip_key": "field.tooltip.batch_no"},
75
- {"key": "purchase_sku", "label": "Purchase SKU", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.6, "show_in_table": False, "tooltip_key": "field.tooltip.purchase_sku"},
76
- {"key": "purchase_name", "label": "Purchase Name", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.7, "show_in_table": False, "tooltip_key": "field.tooltip.purchase_name"},
77
- {"key": "purchase_unit", "label": "Purchase Unit", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.8, "show_in_table": True, "tooltip_key": "field.tooltip.purchase_unit"},
78
- {"key": "purchase_conversion_factor","label": "Conversion Factor", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.9, "show_in_table": False, "tooltip_key": "field.tooltip.purchase_conversion_factor"},
79
- {"key": "created_at", "label": "Created", "type": "date", "editable": False, "required": False, "options": [], "visible_to_roles": [], "position": 107, "show_in_table": False},
80
- {"key": "updated_at", "label": "Updated", "type": "date", "editable": False, "required": False, "options": [], "visible_to_roles": [], "position": 108, "show_in_table": False},
66
+ {"key": "status", "label": "Status", "type": "status", "editable": False, "required": False, "options": [], "visible_to_roles": [], "position": 100, "show_in_table": True, "label_key": "field.label.status"},
67
+ {"key": "short_description", "label": "Short Description", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 101, "show_in_table": False, "label_key": "field.label.short_description"},
68
+ {"key": "description", "label": "Description", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 102, "show_in_table": False, "label_key": "field.label.description"},
69
+ {"key": "notes", "label": "Notes", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 103, "show_in_table": False, "label_key": "field.label.notes"},
70
+ {"key": "barcode", "label": "Barcode", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104, "show_in_table": True, "tooltip_key": "field.tooltip.barcode", "label_key": "field.label.barcode"},
71
+ {"key": "hs_code", "label": "HS Code", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.5, "show_in_table": False, "tooltip_key": "field.tooltip.hs_code", "label_key": "field.label.hs_code"},
72
+ {"key": "country_of_origin", "label": "Country of Origin", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.52,"show_in_table": False, "tooltip_key": "field.tooltip.country_of_origin", "label_key": "field.label.country_of_origin"},
73
+ {"key": "preferred_supplier","label": "Preferred Supplier","type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.54,"show_in_table": False, "tooltip_key": "field.tooltip.preferred_supplier", "label_key": "field.label.preferred_supplier"},
74
+ {"key": "batch_no", "label": "Batch / Lot No", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.55,"show_in_table": False, "tooltip_key": "field.tooltip.batch_no", "label_key": "field.label.batch_no"},
75
+ {"key": "purchase_sku", "label": "Purchase SKU", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.6, "show_in_table": False, "tooltip_key": "field.tooltip.purchase_sku", "label_key": "field.label.purchase_sku"},
76
+ {"key": "purchase_name", "label": "Purchase Name", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.7, "show_in_table": False, "tooltip_key": "field.tooltip.purchase_name", "label_key": "field.label.purchase_name"},
77
+ {"key": "purchase_unit", "label": "Purchase Unit", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.8, "show_in_table": True, "tooltip_key": "field.tooltip.purchase_unit", "label_key": "field.label.purchase_unit"},
78
+ {"key": "purchase_conversion_factor","label": "Conversion Factor", "type": "number", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 104.9, "show_in_table": False, "tooltip_key": "field.tooltip.purchase_conversion_factor", "label_key": "field.label.purchase_conversion_factor"},
79
+ {"key": "created_at", "label": "Created", "type": "date", "editable": False, "required": False, "options": [], "visible_to_roles": [], "position": 107, "show_in_table": False, "label_key": "field.label.created_at"},
80
+ {"key": "updated_at", "label": "Updated", "type": "date", "editable": False, "required": False, "options": [], "visible_to_roles": [], "position": 108, "show_in_table": False, "label_key": "field.label.updated_at"},
81
81
  ]
82
82
 
83
+ # Built-in fields keyed for O(1) lookup when rehydrating stripped metadata.
84
+ _BASE_FIELD_BY_KEY: dict[str, dict] = {f["key"]: f for f in _BASE_FIELDS}
85
+
86
+
87
+ def _rehydrate_builtin_metadata(schema: list[dict]) -> list[dict]:
88
+ """Reattach canonical label_key/tooltip_key to built-in fields.
89
+
90
+ The item schema PATCH model does not carry label_key or tooltip_key, so a
91
+ company that customizes its schema stores built-in fields stripped of both.
92
+ Reattach them from _BASE_FIELDS, keyed strictly on built-in membership so
93
+ custom fields and dynamic price columns are never touched. label_key is
94
+ restored only when the stored label still equals the canonical English label
95
+ (a user-renamed built-in keeps its literal label and is never translated);
96
+ tooltip_key is restored for every built-in key, since there is no
97
+ custom-tooltip edit path. Idempotent: a field that already carries a key is
98
+ left as-is."""
99
+ out: list[dict] = []
100
+ for f in schema:
101
+ base = _BASE_FIELD_BY_KEY.get(f.get("key"))
102
+ if base is None:
103
+ out.append(f)
104
+ continue
105
+ updated = dict(f)
106
+ if ("label_key" not in updated and base.get("label_key")
107
+ and updated.get("label") == base.get("label")):
108
+ updated["label_key"] = base["label_key"]
109
+ if "tooltip_key" not in updated and base.get("tooltip_key"):
110
+ updated["tooltip_key"] = base["tooltip_key"]
111
+ out.append(updated)
112
+ return out
113
+
114
+
83
115
  def _inject_price_columns(base: list[dict], price_lists: list[dict]) -> list[dict]:
84
116
  """Insert a money column for each price list after position 5 (location).
85
117
 
@@ -190,5 +222,5 @@ async def get_effective_field_schema(
190
222
  keys_in_cat = {f["key"] for f in cat_fields}
191
223
  merged = [f for f in base_schema if f["key"] not in keys_in_cat]
192
224
  merged.extend(cat_fields)
193
- return merged
194
- return base_schema
225
+ return _rehydrate_builtin_metadata(merged)
226
+ return _rehydrate_builtin_metadata(base_schema)
@@ -10,6 +10,7 @@ and by the fulfillment module's toggle/pick screen.
10
10
  from __future__ import annotations
11
11
 
12
12
  import uuid as _uuid
13
+ from collections.abc import Awaitable, Callable
13
14
  from datetime import datetime, timezone
14
15
  from typing import Any
15
16
 
@@ -42,16 +43,36 @@ async def execute_fulfill(
42
43
  company_id,
43
44
  user_id,
44
45
  doc_type: str = "",
46
+ allocate_barcodes: Callable[[int], Awaitable[list[str]]] | None = None,
45
47
  ) -> dict[str, Any]:
46
48
  """Execute fulfillment: emit item events, doc event, and COGS JE.
47
49
 
48
50
  Returns: {fulfillment_status, fulfilled_items, total_cogs}
51
+
52
+ A split pick carves a new child parcel off its parent lot; that child is a
53
+ fresh physical item and needs its own barcode. Core must not depend on the
54
+ inventory module, so the calling module injects allocation through
55
+ ``allocate_barcodes(count) -> list[str]`` (celerp_inventory allocates under
56
+ its code-namespace lock). When any split is planned and no allocator is
57
+ supplied, this fails before emitting a single event rather than minting a
58
+ barcodeless child.
49
59
  """
50
60
  now = datetime.now(timezone.utc).isoformat()
51
61
  fulfilled_items: list[dict] = []
52
62
  total_cogs = 0.0
53
63
  cid = _to_uuid(company_id)
54
64
  uid = _to_uuid(user_id)
65
+
66
+ # Allocate every split child's barcode up front, under the caller's lock, and
67
+ # fail clearly before any event is emitted if the allocator is missing.
68
+ split_picks = [p for p in pick_result.picks if p.action == "split"]
69
+ if split_picks and allocate_barcodes is None:
70
+ raise ValueError(
71
+ "Fulfillment must split a lot into a new child parcel that needs a "
72
+ "freshly allocated barcode, but no allocate_barcodes callback was "
73
+ "supplied. The calling module must inject inventory code allocation."
74
+ )
75
+ split_barcodes = iter(await allocate_barcodes(len(split_picks))) if split_picks else iter(())
55
76
  # Stable human doc number for the item's history (the entity_id suffix can diverge on
56
77
  # finalize/renumber, e.g. PF-... -> INV-...), so capture it from the doc at emit time.
57
78
  doc_number = doc_state.get("doc_number") or doc_state.get("ref_id") or ""
@@ -96,6 +117,7 @@ async def execute_fulfill(
96
117
  "sku": pick.sku, # child keeps the parent SKU (distinct lot by entity_id)
97
118
  "name": pick.sku,
98
119
  "quantity": pick.pick_qty,
120
+ "barcode": next(split_barcodes), # fresh per-lot barcode from the injected allocator
99
121
  },
100
122
  actor_id=uid,
101
123
  location_id=None,
@@ -198,6 +198,22 @@ TAX_REGIMES: dict[str, _T] = {
198
198
  "description": "Tax-exempt", "is_compound": False, "default_order": 0},
199
199
  ],
200
200
  },
201
+ # ── Africa ────────────────────────────────────────────────────────────
202
+ "ET": {
203
+ "currency": "ETB",
204
+ "taxes": [
205
+ {"name": "VAT 15%", "rate": 15.0, "tax_type": "both", "is_default": True,
206
+ "description": "Ethiopia standard VAT", "is_compound": False, "default_order": 0},
207
+ {"name": "TOT 2%", "rate": 2.0, "tax_type": "sales", "is_default": False,
208
+ "description": "Turnover tax on goods (non-VAT-registered)", "is_compound": False, "default_order": 0},
209
+ {"name": "TOT 10%", "rate": 10.0, "tax_type": "sales", "is_default": False,
210
+ "description": "Turnover tax on services (non-VAT-registered)", "is_compound": False, "default_order": 0},
211
+ {"name": "Exempt", "rate": 0.0, "tax_type": "both", "is_default": False,
212
+ "description": "VAT-exempt", "is_compound": False, "default_order": 0},
213
+ {"name": "WHT 2%", "rate": -2.0, "tax_type": "purchase", "is_default": False,
214
+ "description": "Withholding tax on supply of goods", "is_compound": False, "default_order": 1},
215
+ ],
216
+ },
201
217
  # ── Fallback ──────────────────────────────────────────────────────────
202
218
  "_default": {
203
219
  "currency": "USD",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: celerp
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Free, self-hosted ERP for small businesses
5
5
  License: Business Source License 1.1
6
6