celerp 2.3.6__tar.gz → 2.5.0__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.
- {celerp-2.3.6 → celerp-2.5.0}/PKG-INFO +2 -1
- celerp-2.5.0/celerp/ai/batch.py +348 -0
- celerp-2.5.0/celerp/ai/conversations.py +665 -0
- celerp-2.5.0/celerp/ai/files.py +77 -0
- celerp-2.5.0/celerp/ai/llm.py +236 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/ai/memory.py +1 -1
- celerp-2.5.0/celerp/ai/page_count.py +43 -0
- celerp-2.5.0/celerp/ai/quota.py +62 -0
- celerp-2.5.0/celerp/ai/service.py +483 -0
- celerp-2.5.0/celerp/ai/tools.py +434 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/cli.py +6 -3
- celerp-2.5.0/celerp/config.py +801 -0
- celerp-2.5.0/celerp/config_store.py +203 -0
- celerp-2.5.0/celerp/entitlement_preflight.py +168 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/events/engine.py +17 -0
- celerp-2.5.0/celerp/gateway/bootstrap.py +104 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/gateway/client.py +41 -27
- celerp-2.5.0/celerp/gateway/fixtures/entitlement_flags_fixture.json +43 -0
- celerp-2.5.0/celerp/gateway/state.py +1034 -0
- celerp-2.5.0/celerp/importers/tabular.py +588 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/main.py +115 -84
- {celerp-2.3.6 → celerp-2.5.0}/celerp/middleware.py +51 -51
- celerp-2.5.0/celerp/migrations/versions/f3a4b5c6d7e8_purge_session_registry.py +41 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/api.py +3 -3
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/license.py +3 -1
- {celerp-2.3.6 → celerp-2.5.0}/celerp/output/doc_print.py +3 -1
- celerp-2.5.0/celerp/routers/attachments.py +42 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/auth.py +252 -129
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/companies.py +155 -114
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/events.py +38 -49
- celerp-2.5.0/celerp/routers/health.py +1208 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/search.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/attachments.py +37 -9
- celerp-2.5.0/celerp/services/auth.py +358 -0
- celerp-2.5.0/celerp/services/background.py +22 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/backup_repo.py +16 -7
- celerp-2.5.0/celerp/services/cloud_entitlement.py +229 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/payments.py +25 -28
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/session_tracker.py +122 -96
- {celerp-2.3.6 → celerp-2.5.0}/celerp/session_gate.py +13 -9
- {celerp-2.3.6 → celerp-2.5.0}/celerp.egg-info/PKG-INFO +2 -1
- {celerp-2.3.6 → celerp-2.5.0}/celerp.egg-info/SOURCES.txt +28 -3
- {celerp-2.3.6 → celerp-2.5.0}/celerp.egg-info/requires.txt +1 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp.egg-info/scm_file_list.json +81 -3
- celerp-2.5.0/celerp.egg-info/scm_version.json +8 -0
- {celerp-2.3.6 → celerp-2.5.0}/conftest.py +24 -5
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/celerp_accounting/routes.py +442 -154
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_accounting_banking_routers.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_accounting_gaps.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_accounting_import_idempotency.py +2 -2
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_cash_flow.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_journal_gl_soa.py +1 -1
- celerp-2.5.0/default_modules/celerp-accounting/tests/test_reconciliation_agent.py +330 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_route_permissions.py +12 -13
- celerp-2.5.0/default_modules/celerp-ai/celerp_ai/routes.py +1529 -0
- celerp-2.5.0/default_modules/celerp-ai/celerp_ai/ui_routes.py +2170 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/_fixtures.py +91 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/fixtures/relay/error_402.json +6 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/fixtures/relay/error_409.json +6 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/fixtures/relay/error_429.json +6 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/fixtures/relay/mutation_tool_call.json +25 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/fixtures/relay/read_tool_call.json +25 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/fixtures/relay/text_completion.json +15 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/test_agent_loop.py +560 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/tests/test_batch.py +164 -37
- celerp-2.5.0/default_modules/celerp-ai/tests/test_commercial_routing.py +203 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/test_confirm_race_pg.py +155 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/test_conversations.py +779 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/test_coverage_gaps.py +409 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/test_live_agent.py +161 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/test_llm.py +271 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/tests/test_page_count.py +2 -59
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/tests/test_quota.py +55 -36
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/tests/test_router.py +69 -73
- celerp-2.5.0/default_modules/celerp-ai/tests/test_routes_coverage.py +958 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/test_showcase_claims.py +80 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/test_ui_routes.py +785 -0
- celerp-2.5.0/default_modules/celerp-ai/tests/test_workflows.py +409 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-backup/celerp_backup/routes.py +5 -3
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-contacts/celerp_contacts/routes.py +65 -22
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/routes.py +296 -123
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/routes_payments.py +2 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_audits.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_cross_lot_settlement.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_freight_je.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_freight_lines.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_fulfill_no_split.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_fulfillment_activity.py +3 -3
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_inbound_je_lifecycle.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_inventory_account_reconciliation.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_landed_receive.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_line_delete_persist.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_line_identifier.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_line_page_patch_truncate.py +1 -1
- celerp-2.5.0/default_modules/celerp-docs/tests/test_list_ids_filter.py +44 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_list_page_no_full_state.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_list_quantity_integrity.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_list_query_pushdown.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_list_sell_by_and_reference.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_memo_close.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_memo_close_review_fixes.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_memo_line_labels.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_memo_unfulfilled_filter.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_payment_void_activity.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_receive_sku_batch.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_send_visibility.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_service_lines.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_sold_label_ordering.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_void_guards.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_writeoffs.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/celerp_inventory/routes.py +352 -272
- celerp-2.5.0/default_modules/celerp-inventory/celerp_inventory/services.py +1181 -0
- celerp-2.5.0/default_modules/celerp-inventory/tests/test_import_agent_routes.py +242 -0
- celerp-2.5.0/default_modules/celerp-inventory/tests/test_import_service.py +451 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/celerp_manufacturing/routes.py +10 -2
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_auto_complete_on_finalize.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_bom_removed.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_build_api.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_item_recipe_api.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_item_workflow_api.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_manufacture_from_doc.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_manufacturing.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_manufacturing_import_idempotency.py +2 -2
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_manufacturing_module.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_phase2_manufacturing_validations.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_production_order.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_recost_api.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_run_records.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_to_make_allocation.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_work_centers_and_settings.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-reports/tests/test_reports_full.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-subscriptions/tests/test_subscriptions.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/routes.py +2 -1
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/tests/test_verticals_routers.py +1 -1
- celerp-2.5.0/default_modules/first_party.lock.json +16 -0
- {celerp-2.3.6 → celerp-2.5.0}/pyproject.toml +1 -0
- {celerp-2.3.6 → celerp-2.5.0}/test_helpers.py +54 -6
- {celerp-2.3.6 → celerp-2.5.0}/ui/api_client.py +233 -49
- {celerp-2.3.6 → celerp-2.5.0}/ui/app.py +67 -29
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/activity.py +8 -3
- celerp-2.5.0/ui/components/cloud_gate.py +236 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/shell.py +98 -21
- {celerp-2.3.6 → celerp-2.5.0}/ui/config.py +66 -11
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/am.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/ar.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/de.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/en.json +102 -17
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/es.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/fr.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/id.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/it.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/ja.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/pt.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/th.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/locales/vi.json +97 -12
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/account.py +39 -40
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/auth.py +59 -23
- celerp-2.5.0/ui/routes/commercial.py +144 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/contacts.py +2 -2
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/csv_import.py +19 -359
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/dashboard.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/documents.py +16 -9
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/inventory.py +39 -353
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/modules_page.py +3 -4
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings.py +222 -172
- celerp-2.5.0/ui/routes/settings_cloud.py +1520 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings_connectors.py +9 -22
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings_inventory.py +4 -1
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings_payments.py +14 -7
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/setup.py +26 -20
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/subscriptions.py +1 -1
- {celerp-2.3.6 → celerp-2.5.0}/ui/static/app.css +64 -21
- celerp-2.3.6/celerp/ai/batch.py +0 -228
- celerp-2.3.6/celerp/ai/commands.py +0 -184
- celerp-2.3.6/celerp/ai/conversations.py +0 -234
- celerp-2.3.6/celerp/ai/files.py +0 -49
- celerp-2.3.6/celerp/ai/llm.py +0 -110
- celerp-2.3.6/celerp/ai/page_count.py +0 -67
- celerp-2.3.6/celerp/ai/quota.py +0 -63
- celerp-2.3.6/celerp/ai/service.py +0 -272
- celerp-2.3.6/celerp/ai/tools.py +0 -287
- celerp-2.3.6/celerp/config.py +0 -447
- celerp-2.3.6/celerp/gateway/state.py +0 -178
- celerp-2.3.6/celerp/routers/health.py +0 -749
- celerp-2.3.6/celerp/services/auth.py +0 -174
- celerp-2.3.6/celerp.egg-info/scm_version.json +0 -8
- celerp-2.3.6/default_modules/celerp-ai/celerp_ai/routes.py +0 -747
- celerp-2.3.6/default_modules/celerp-ai/celerp_ai/ui_routes.py +0 -1086
- celerp-2.3.6/default_modules/celerp-ai/tests/test_conversations.py +0 -324
- celerp-2.3.6/default_modules/celerp-ai/tests/test_coverage_gaps.py +0 -595
- celerp-2.3.6/default_modules/celerp-ai/tests/test_llm.py +0 -158
- celerp-2.3.6/default_modules/celerp-ai/tests/test_routes_coverage.py +0 -394
- celerp-2.3.6/default_modules/celerp-ai/tests/test_service.py +0 -217
- celerp-2.3.6/default_modules/celerp-ai/tests/test_tools.py +0 -354
- celerp-2.3.6/default_modules/celerp-inventory/celerp_inventory/services.py +0 -289
- celerp-2.3.6/default_modules/first_party.lock.json +0 -16
- celerp-2.3.6/ui/components/cloud_gate.py +0 -127
- celerp-2.3.6/ui/routes/settings_cloud.py +0 -751
- {celerp-2.3.6 → celerp-2.5.0}/CLA.md +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/CONTRIBUTING.md +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/LICENSING.md +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/MANIFEST.in +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/NOTICE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/README.md +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/alembic.ini +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/__main__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/ai/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/ai/cleanup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/ai/intent.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/ai/models.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/alembic.ini +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/alembic_config.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/capacity.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/compat.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/compute/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/compute/aggregations.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/compute/valuation.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/base.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/daily_scheduler.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/http.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/images.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/quickbooks.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/registry.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/relay_token.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/shopify.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/sync_runner.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/upsert.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/util.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/webhooks.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/woocommerce.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/connectors/xero.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/constants.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/db.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/embedded_pg.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/events/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/events/schemas.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/events/types.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/gateway/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/importers/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/importers/importer.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/importers/schema.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/inventory_codes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/README.md +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/_auto_stamp.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/_data_reconcile.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/_json_compat.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/env.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/script.py.mako +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/a0b1c2d3e4f5_seed_landed_cost_clearing_accounts.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/a1b2c3d4e5f6_add_doc_share_tokens.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/b1c2d3e4f5a6_add_supporter_badges.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/b2c3d4e5f6a7_add_import_batches.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/b3c4d5e6f7a8_expand_role_permissions_to_role_grants.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/bc0d1e2f3a4b_barcode_unique_index.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/c1d2e3f4a5b6_add_marketplace.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/c2d3e4f5a6b7_add_is_sync_to_shopify.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/c4d5e6f7a8b9_account_cash_flow_category.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/c9d8e7f6a5b4_seed_shrinkage_writeoff_account.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/d0e1f2a3b4c5_add_share_token_expiry.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/d1e2f3a4b5c6_rfid_epc_unique_index.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/d2e3f4a5b6c7_add_password_reset_token.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/d5e6f7a8b9c0_rename_fx_rounding_to_fx_difference.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/e3f4a5b6c7d8_add_company_is_active.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/e4f5a6b7c8d9_backfill_connector_idempotency_key.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/e7c9a1b3d5f2_work_center_default_columns.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/f1a2b3c4d5e6_move_accounts_marketplace_to_modules.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/f6a7b8c9d0e1_seed_fx_rounding_account.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/f8a9b0c1d2e3_work_center_default_backfill.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/fd5de461e14e_initial_schema.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/g1h2i3j4k5l6_add_consignment_flag.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/h2i3j4k5l6m7_add_bank_accounts_and_reconciliation.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/j4k5l6m7n8o9_labels_db_persistence.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/k5l6m7n8o9p0_add_reconciliation_v2.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/l6m7n8o9p0q1_add_sync_runs_table.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/m7n8o9p0q1r2_add_connector_configs_and_outbound_queue.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/n8o9p0q1r2s3_backfill_payment_date.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/o9p0q1r2s3t4_backfill_item_price_fields.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/p1q2r3s4t5u6_add_session_registry_and_user_auth_state.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/q2r3s4t5u6v7_add_system_runtime_state.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/r3s4t5u6v7w8_add_projections_company_entity_type_index.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/s4t5u6v7w8x9_drop_user_company_id_role.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/t5u6v7w8x9y0_seed_inventory_sub_accounts.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/u6v7w8x9y0z1_backfill_item_prices_from_attributes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/v7w8x9y0z1a2_backfill_purchase_unit_defaults.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/w8x9y0z1a2b3_backfill_category_unit_defaults.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/x7y8z9a0b1c2_add_projection_created_at.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/y8z9a0b1c2d3_per_company_ledger_idempotency.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/migrations/versions/z9a0b1c2d3e4_work_centers.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/accounting.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/ai.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/auth.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/base.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/company.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/connector_config.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/import_batch.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/ledger.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/marketplace.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/notification.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/projections.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/share.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/supporter.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/models/sync_run.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/audit.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/demotion.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/importer.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/loader.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/meta.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/migrations_runner.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/references.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/registry.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/modules/slots.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/notifications/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/notifications/service.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/notifications/sse.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/output/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/output/branding.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/output/pdf.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/output/share_render.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/projections/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/projections/engine.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/projections/handlers/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/projections/handlers/marketplace.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/projections/handlers/scanning.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/projections/handlers/shopify.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/projections/handlers/system.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/debug.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/doctor.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/ledger.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/notifications.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/stars.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/routers/system.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/schemas/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/activity_redaction.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/auto_je.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/backup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/backup_export.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/backup_import.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/backup_scheduler.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/backup_state.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/cogs_backfill.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/cost_visibility.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/demo.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/dev_release_guard.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/document_lines.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/email.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/field_schema.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/fulfill.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/holdings.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/je_keys.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/landed_cost.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/line_measures.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/list_behavior.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/money.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/permissions.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/pick.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/pricing.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/relay_share.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/reorder.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/runtime_state.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/shipping.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/star_cta.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/status_doc_backfill.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/supporter_badge.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/system_health.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/services/units.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp/tax_regimes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp.egg-info/dependency_links.txt +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp.egg-info/entry_points.txt +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/celerp.egg-info/top_level.txt +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/conftest_support.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/celerp_accounting/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/celerp_accounting/api_setup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/celerp_accounting/csv_parser.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/celerp_accounting/matcher.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/celerp_accounting/models.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/celerp_accounting/projections.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/celerp_accounting/search.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/celerp_accounting/ui_routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/balance-sheet.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/cash-flow.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/extended-journal-csv.csv +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/extended-journal-print.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/extended-journal.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/general-ledger.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/journal-csv.csv +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/journal-print.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/journal.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/ledger.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/pnl.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/statement.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/report_goldens/trial-balance.html +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_accounting_banking.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_financial_reports_ui.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_journal_gl_soa_ui.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_reconciliation_v2.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-accounting/tests/test_reports_end_to_end.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-admin/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-admin/celerp_admin/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-admin/celerp_admin/routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-admin/celerp_admin/setup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/celerp_ai/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/celerp_ai/setup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/tests/conftest.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/tests/test_cleanup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/tests/test_intent.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/tests/test_memory.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-ai/tests/test_models.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-backup/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-backup/celerp_backup/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-backup/celerp_backup/setup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/celerp_connectors/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/celerp_connectors/models.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/celerp_connectors/routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/conftest.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_compliance.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_connector_correctness.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_connectors.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_credentials_routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_images.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_outbound.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_quickbooks.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_rate_limiting.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_shopify.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_wiring.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_woocommerce.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_woocommerce_webhooks.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-connectors/tests/test_xero.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-contacts/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-contacts/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-contacts/celerp_contacts/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-contacts/celerp_contacts/migrations.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-contacts/celerp_contacts/projections.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-contacts/celerp_contacts/search.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-contacts/celerp_contacts/services.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-contacts/celerp_contacts/ui_routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-dashboard/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-dashboard/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-dashboard/celerp_dashboard/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-dashboard/celerp_dashboard/routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-dashboard/celerp_dashboard/setup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/api_setup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/doc_constants.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/doc_email.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/doc_projections.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/doc_service.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/models_share.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/routes_share.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/search.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/sequences.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/taxes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/celerp_docs/ui_routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/conftest.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_bulk_payment_alloc_lock.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_consolidate_lots.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_list_concurrency.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_list_outcome_concurrency.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_memo_close_projection.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-docs/tests/test_memo_lifecycle_concurrency.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/celerp_inventory/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/celerp_inventory/models_import_batch.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/celerp_inventory/projections.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/celerp_inventory/routes_attachments.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/celerp_inventory/routes_scanning.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/celerp_inventory/search.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/celerp_inventory/ui_routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/tests/test_item_recipe_projection.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/tests/test_item_workflow_projection.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-inventory/tests/test_landed_cost_projection.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/am.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/ar.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/de.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/en.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/es.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/fr.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/id.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/it.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/ja.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/pt.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/th.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/locales/vi.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/models.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/presets.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/service.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/celerp_labels/ui_routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/requirements.txt +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/tests/test_labels.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-labels/tests/test_labels_module.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/celerp_manufacturing/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/celerp_manufacturing/costing.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/celerp_manufacturing/expansion.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/celerp_manufacturing/labor.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/celerp_manufacturing/migrations.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/celerp_manufacturing/projection_handler.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/celerp_manufacturing/search.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/celerp_manufacturing/ui_routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/requirements.txt +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_completion_lock_order.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_labor_providers.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_mfg_events.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_recipe_costing.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_recipe_expansion.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_where_used.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-manufacturing/tests/test_workflow_time.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-reports/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-reports/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-reports/celerp_reports/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-reports/celerp_reports/api_setup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-reports/celerp_reports/routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-reports/celerp_reports/ui_routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-reports/tests/test_reports_unit.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-subscriptions/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-subscriptions/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-subscriptions/celerp_subscriptions/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-subscriptions/celerp_subscriptions/routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-subscriptions/celerp_subscriptions/search.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-subscriptions/celerp_subscriptions/ui_routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-subscriptions/tests/test_subscriptions_ui.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/LICENSE +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/accessory_fashion.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/activewear.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/art_photography.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/audio_equipment.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/bag_handbag.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/banknote.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/beauty_tool.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/bed_bedroom.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/beer.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/beverage_nonalc.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/body_part_auto.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/book.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/bottoms.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/brake_suspension.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/bullion_coin.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/camera.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/colored_stone.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/comic.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/commercial_space.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/component_part.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/confectionery.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/consulting_service.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/decorative_art.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/diamond.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/drawing.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/dress_jumpsuit.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_auto.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_component.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/emerald.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/engine_part.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/fastener.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/fertilizer_chemical.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/film_video.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/fine_writing_instrument.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/fluid_lubricant.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/footwear.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/fragrance.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_food.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_produce.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/frozen_food.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/gaming_console.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/gold_bullion.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/grain_cereal.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/haircare.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/hand_tool.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/ingredient_bulk.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/interior_part.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/jewelry.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/kitchen_dining.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/laptop.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/lighting.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/livestock_feed.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/makeup.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/measuring_instrument.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/medal_token.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/mineral_specimen.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/mobile_phone.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/music_cd.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/music_vinyl.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/nail.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/numismatic_coin.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/outdoor_furniture.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/outerwear.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/packaged_food.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/painting.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/parking_bay.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/pearl.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/personal_care.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/pipe_plumbing.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/platinum_bullion.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/power_tool.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/print_edition.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/residential_unit.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/rough_gemstone.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/ruby.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/saas_plan.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/safety_ppe.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/sapphire.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/sculpture.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/seating.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/seeds.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/silver_bullion.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/skincare.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/soft_furnishing.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/software_addon.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/software_license.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/spirit.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/storage_furniture.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/swimwear.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/table_desk.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/tablet.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/tire_wheel.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/tops.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/trading_card.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/tv_display.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/video_game.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/watch.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/watch_strap.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/categories/wine.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/agricultural.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/artwork.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/automotive.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/blank.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/books_media.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/coins_precious_metals.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/consulting.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/cosmetics.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/electronics.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/fashion.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/food_beverage.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/furniture.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/gemstones.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/hardware.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/property_rental.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/saas.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/watches.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/presets/wine_spirits.json +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/celerp_verticals/ui_routes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/default_modules/celerp-verticals/tests/test_verticals.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/legal/OFFICIAL-COMPONENTS.md +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/legal/TRADEMARK.md +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/packaging/winget/Celerp.Celerp.installer.yaml +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/packaging/winget/Celerp.Celerp.locale.en-US.yaml +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/packaging/winget/Celerp.Celerp.yaml +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/packaging/winget/README.md +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/setup.cfg +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/attrs.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/backup.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/currency.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/files.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/journal.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/notes.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/phone.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/report_kit.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/components/table.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/i18n.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/marketplace_catalog.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/__init__.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/accounting.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/accounting_import.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/docs_import.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/events.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/financial_reports.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/lists_import.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/manufacturing.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/notifications.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/reconciliation.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/reports.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/search.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings_accounting.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings_contacts.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings_general.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings_import.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings_manufacturing.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings_purchasing.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/settings_sales.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/stars.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/routes/subscriptions_import.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/security.py +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/static/htmx.min.js +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/static/icon.png +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/static/logo.png +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/static/vendor/intl-tel-input/img/flags.webp +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/static/vendor/intl-tel-input/img/flags@2x.webp +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/static/vendor/intl-tel-input/intlTelInput.min.css +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/static/vendor/intl-tel-input/intlTelInput.min.js +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/ui/static/vendor/intl-tel-input/intlTelInputWithUtils.min.js +0 -0
- {celerp-2.3.6 → celerp-2.5.0}/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
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Free, self-hosted ERP for small businesses
|
|
5
5
|
License: Business Source License 1.1
|
|
6
6
|
|
|
@@ -141,6 +141,7 @@ Requires-Dist: numpy>=1.26
|
|
|
141
141
|
Requires-Dist: python-multipart>=0.0.9
|
|
142
142
|
Requires-Dist: aiofiles>=23.0
|
|
143
143
|
Requires-Dist: httpx>=0.27
|
|
144
|
+
Requires-Dist: openpyxl<4,>=3.1
|
|
144
145
|
Requires-Dist: slowapi>=0.1.9
|
|
145
146
|
Requires-Dist: reportlab>=4.0
|
|
146
147
|
Requires-Dist: python-fasthtml>=0.14
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# Copyright (c) 2026 Noah Severs
|
|
2
|
+
# SPDX-License-Identifier: LicenseRef-Proprietary
|
|
3
|
+
|
|
4
|
+
"""AI batch processing - the extraction stage for attached receipts and invoices.
|
|
5
|
+
|
|
6
|
+
A batch job reads 1 to MAX_BATCH_FILES files in parallel (at most
|
|
7
|
+
BATCH_CONCURRENCY model calls at once). Each file gets its own model call that
|
|
8
|
+
returns a structured extraction. Nothing is written to the books here: the
|
|
9
|
+
extractions feed the proposal step, and every document is created only after
|
|
10
|
+
the user confirms it.
|
|
11
|
+
|
|
12
|
+
Credits are metered per file from the gateway's usage report, so a job that
|
|
13
|
+
fails halfway charges only for the files it actually read.
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
job = await create_batch_job(session, company_id, user_id, query, file_ids)
|
|
17
|
+
# run_batch runs in the background, reports per-file progress through
|
|
18
|
+
# on_progress, and creates a notification when it finishes.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import asyncio
|
|
24
|
+
import json
|
|
25
|
+
import logging
|
|
26
|
+
import re
|
|
27
|
+
import uuid
|
|
28
|
+
from datetime import datetime, timezone
|
|
29
|
+
|
|
30
|
+
from fastapi import HTTPException
|
|
31
|
+
from sqlalchemy import select
|
|
32
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
33
|
+
|
|
34
|
+
from celerp.ai.files import load_file_for_llm
|
|
35
|
+
from celerp.ai.llm import RelayError, call_llm
|
|
36
|
+
from celerp.ai.models import BULK_EXTRACTION
|
|
37
|
+
from celerp.models.ai import AIBatchJob
|
|
38
|
+
|
|
39
|
+
log = logging.getLogger(__name__)
|
|
40
|
+
|
|
41
|
+
# Keep file decoding/base64 residency aligned with the transport's process-wide
|
|
42
|
+
# model-call concurrency. A larger batch semaphore only lets extra 10 MB files sit
|
|
43
|
+
# expanded in memory while call_llm waits on its own three-call gate.
|
|
44
|
+
BATCH_CONCURRENCY = 3
|
|
45
|
+
MAX_BATCH_FILES = 100
|
|
46
|
+
|
|
47
|
+
INTERRUPTED_ERROR = "This job was interrupted by a restart. Completed file results were kept; resend only files that did not finish."
|
|
48
|
+
|
|
49
|
+
_BATCH_SYSTEM_PROMPT = """\
|
|
50
|
+
You are reading one business document: a receipt, a supplier invoice, a bank or \
|
|
51
|
+
card statement, or something else.
|
|
52
|
+
Extract what is printed on it. Never guess a value that is not on the document; \
|
|
53
|
+
leave it null instead.
|
|
54
|
+
|
|
55
|
+
Output a JSON block:
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"document_kind": "receipt|invoice|statement|other",
|
|
59
|
+
"vendor_name": "string or null",
|
|
60
|
+
"date": "YYYY-MM-DD or null",
|
|
61
|
+
"currency": "ISO 4217 code or null",
|
|
62
|
+
"total": 0.00,
|
|
63
|
+
"tax": 0.00,
|
|
64
|
+
"reference": "invoice or receipt number, or null",
|
|
65
|
+
"line_items": [
|
|
66
|
+
{"description": "string", "quantity": 1, "unit_price": 0.00}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
If the document is unreadable, return a one-sentence explanation instead of JSON.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
_FENCED_JSON = re.compile(r"```(?:json)?\s*(\{.*?\})\s*```", re.DOTALL)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def parse_extraction(answer: str) -> dict | None:
|
|
78
|
+
"""Return the JSON object in a model answer, or None when there is none.
|
|
79
|
+
|
|
80
|
+
Tries a fenced ```json block first, then the whole answer, then the first
|
|
81
|
+
balanced object in the text. Anything that is not a JSON object is None.
|
|
82
|
+
"""
|
|
83
|
+
candidates: list[str] = []
|
|
84
|
+
fenced = _FENCED_JSON.search(answer)
|
|
85
|
+
if fenced:
|
|
86
|
+
candidates.append(fenced.group(1))
|
|
87
|
+
candidates.append(answer.strip())
|
|
88
|
+
start = answer.find("{")
|
|
89
|
+
if start != -1:
|
|
90
|
+
depth = 0
|
|
91
|
+
for i in range(start, len(answer)):
|
|
92
|
+
if answer[i] == "{":
|
|
93
|
+
depth += 1
|
|
94
|
+
elif answer[i] == "}":
|
|
95
|
+
depth -= 1
|
|
96
|
+
if depth == 0:
|
|
97
|
+
candidates.append(answer[start:i + 1])
|
|
98
|
+
break
|
|
99
|
+
for text in candidates:
|
|
100
|
+
try:
|
|
101
|
+
parsed = json.loads(text)
|
|
102
|
+
except (ValueError, TypeError):
|
|
103
|
+
continue
|
|
104
|
+
if isinstance(parsed, dict):
|
|
105
|
+
return parsed
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _file_error(exc: BaseException) -> str:
|
|
110
|
+
"""The user-facing reason a single file could not be read."""
|
|
111
|
+
if isinstance(exc, HTTPException) and exc.status_code == 402:
|
|
112
|
+
return "You are out of AI credits. Add credits and resend this file."
|
|
113
|
+
if isinstance(exc, RelayError):
|
|
114
|
+
return str(exc)
|
|
115
|
+
if isinstance(exc, asyncio.TimeoutError):
|
|
116
|
+
return "The model did not answer in time for this file. Resend it to try again."
|
|
117
|
+
return "This file could not be read. Check that it is a clear image or PDF and resend it."
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
async def _process_single_file(
|
|
121
|
+
file_id: str,
|
|
122
|
+
query: str,
|
|
123
|
+
company_id: uuid.UUID,
|
|
124
|
+
user_id: uuid.UUID,
|
|
125
|
+
semaphore: asyncio.Semaphore,
|
|
126
|
+
) -> dict:
|
|
127
|
+
"""Read one file through the model. Never raises; the result dict carries the outcome.
|
|
128
|
+
|
|
129
|
+
File loading/base64 encoding happens inside the concurrency bound so a large
|
|
130
|
+
batch cannot hold every encoded attachment in memory at once.
|
|
131
|
+
"""
|
|
132
|
+
async with semaphore:
|
|
133
|
+
try:
|
|
134
|
+
file = load_file_for_llm(file_id, company_id, user_id)
|
|
135
|
+
except (FileNotFoundError, PermissionError):
|
|
136
|
+
return {
|
|
137
|
+
"file_id": file_id,
|
|
138
|
+
"filename": file_id,
|
|
139
|
+
"status": "error",
|
|
140
|
+
"error": "This file is no longer available. Attach it again and resend.",
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
filename = file["filename"]
|
|
144
|
+
files = [file]
|
|
145
|
+
prompt = f"{query}\n\nRead the attached document." if query else "Read the attached document."
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
result = await call_llm(BULK_EXTRACTION, _BATCH_SYSTEM_PROMPT, prompt, files=files)
|
|
149
|
+
except Exception as exc:
|
|
150
|
+
log.warning("Batch file %s failed: %s", file_id, exc)
|
|
151
|
+
return {
|
|
152
|
+
"file_id": file_id,
|
|
153
|
+
"filename": filename,
|
|
154
|
+
"status": "error",
|
|
155
|
+
"error": _file_error(exc),
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
answer = result.message.get("content") or ""
|
|
159
|
+
return {
|
|
160
|
+
"file_id": file_id,
|
|
161
|
+
"filename": filename,
|
|
162
|
+
"status": "success",
|
|
163
|
+
"answer": answer,
|
|
164
|
+
"extraction": parse_extraction(answer),
|
|
165
|
+
"credits": int(result.usage.get("credits") or 0),
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
async def create_batch_job(
|
|
170
|
+
session: AsyncSession,
|
|
171
|
+
company_id: uuid.UUID,
|
|
172
|
+
user_id: uuid.UUID,
|
|
173
|
+
query: str,
|
|
174
|
+
file_ids: list[str],
|
|
175
|
+
conversation_id: uuid.UUID | None = None,
|
|
176
|
+
) -> AIBatchJob:
|
|
177
|
+
"""Create a pending batch job record. Credits accrue per file as it runs."""
|
|
178
|
+
file_ids = list(dict.fromkeys(file_ids))
|
|
179
|
+
if not file_ids:
|
|
180
|
+
raise ValueError("Attach at least one file")
|
|
181
|
+
if len(file_ids) > MAX_BATCH_FILES:
|
|
182
|
+
raise ValueError(f"Maximum {MAX_BATCH_FILES} files per batch")
|
|
183
|
+
|
|
184
|
+
job = AIBatchJob(
|
|
185
|
+
company_id=company_id,
|
|
186
|
+
user_id=user_id,
|
|
187
|
+
conversation_id=conversation_id,
|
|
188
|
+
query=query,
|
|
189
|
+
file_ids=file_ids,
|
|
190
|
+
total_files=len(file_ids),
|
|
191
|
+
credits_consumed=0,
|
|
192
|
+
status="pending",
|
|
193
|
+
)
|
|
194
|
+
session.add(job)
|
|
195
|
+
await session.flush()
|
|
196
|
+
return job
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
async def run_batch(
|
|
200
|
+
job_id: uuid.UUID,
|
|
201
|
+
company_id: uuid.UUID,
|
|
202
|
+
user_id: uuid.UUID,
|
|
203
|
+
query: str,
|
|
204
|
+
file_ids: list[str],
|
|
205
|
+
db_factory,
|
|
206
|
+
on_progress=None,
|
|
207
|
+
) -> None:
|
|
208
|
+
"""Execute a batch job: parallel file extraction with per-file progress.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
db_factory: Callable that returns an AsyncSession context manager.
|
|
212
|
+
on_progress: Optional async callback(job_id, completed, failed, total, result).
|
|
213
|
+
"""
|
|
214
|
+
semaphore = asyncio.Semaphore(BATCH_CONCURRENCY)
|
|
215
|
+
results: list[dict] = []
|
|
216
|
+
conversation_id: uuid.UUID | None = None
|
|
217
|
+
completed = 0
|
|
218
|
+
failed = 0
|
|
219
|
+
credits = 0
|
|
220
|
+
|
|
221
|
+
async with db_factory() as session:
|
|
222
|
+
job = await session.get(AIBatchJob, job_id)
|
|
223
|
+
if job:
|
|
224
|
+
conversation_id = job.conversation_id
|
|
225
|
+
job.status = "running"
|
|
226
|
+
session.add(job)
|
|
227
|
+
await session.commit()
|
|
228
|
+
|
|
229
|
+
tasks = [
|
|
230
|
+
_process_single_file(fid, query, company_id, user_id, semaphore)
|
|
231
|
+
for fid in file_ids
|
|
232
|
+
]
|
|
233
|
+
|
|
234
|
+
for coro in asyncio.as_completed(tasks):
|
|
235
|
+
result = await coro
|
|
236
|
+
results.append(result)
|
|
237
|
+
|
|
238
|
+
if result["status"] == "success":
|
|
239
|
+
completed += 1
|
|
240
|
+
else:
|
|
241
|
+
failed += 1
|
|
242
|
+
credits += result.get("credits", 0)
|
|
243
|
+
|
|
244
|
+
async with db_factory() as session:
|
|
245
|
+
job = await session.get(AIBatchJob, job_id)
|
|
246
|
+
if job:
|
|
247
|
+
persisted = list(((job.results or {}).get("files") or []))
|
|
248
|
+
persisted.append(result)
|
|
249
|
+
# Preserve the user's attachment order even though extraction finishes
|
|
250
|
+
# concurrently. File ids are upload identities; repeated ids, if any,
|
|
251
|
+
# retain their completion order after the first matching position.
|
|
252
|
+
order = {file_id: index for index, file_id in enumerate(file_ids)}
|
|
253
|
+
persisted.sort(key=lambda item: order.get(item.get("file_id"), len(order)))
|
|
254
|
+
job.results = {**(job.results or {}), "files": persisted}
|
|
255
|
+
job.completed_files = completed
|
|
256
|
+
job.failed_files = failed
|
|
257
|
+
job.credits_consumed = credits
|
|
258
|
+
session.add(job)
|
|
259
|
+
await session.commit()
|
|
260
|
+
|
|
261
|
+
if on_progress:
|
|
262
|
+
try:
|
|
263
|
+
await on_progress(job_id, completed, failed, len(file_ids), result)
|
|
264
|
+
except Exception:
|
|
265
|
+
log.debug("on_progress callback failed", exc_info=True)
|
|
266
|
+
|
|
267
|
+
all_failed = failed == len(file_ids)
|
|
268
|
+
final_status = "failed" if all_failed else "completed"
|
|
269
|
+
async with db_factory() as session:
|
|
270
|
+
job = await session.get(AIBatchJob, job_id)
|
|
271
|
+
if job:
|
|
272
|
+
job.status = final_status
|
|
273
|
+
job.credits_consumed = credits
|
|
274
|
+
job.completed_at = datetime.now(timezone.utc)
|
|
275
|
+
if all_failed:
|
|
276
|
+
job.error = "None of the files could be read."
|
|
277
|
+
session.add(job)
|
|
278
|
+
await session.commit()
|
|
279
|
+
|
|
280
|
+
try:
|
|
281
|
+
from celerp.notifications.service import create as create_notification
|
|
282
|
+
async with db_factory() as session:
|
|
283
|
+
if all_failed:
|
|
284
|
+
title = f"Could not read {failed} file(s)"
|
|
285
|
+
body = "None of the attached files could be read. Open the conversation for details."
|
|
286
|
+
else:
|
|
287
|
+
title = f"{completed} of {len(file_ids)} file(s) read"
|
|
288
|
+
body = (
|
|
289
|
+
f"{completed} read, {failed} could not be read. "
|
|
290
|
+
"Open the conversation to review the proposed entries."
|
|
291
|
+
)
|
|
292
|
+
await create_notification(
|
|
293
|
+
session, company_id, "ai", title, body,
|
|
294
|
+
user_id=user_id,
|
|
295
|
+
action_url=(
|
|
296
|
+
f"/ai?conversation={conversation_id}" if conversation_id else "/ai"
|
|
297
|
+
),
|
|
298
|
+
priority="high",
|
|
299
|
+
)
|
|
300
|
+
await session.commit()
|
|
301
|
+
except Exception:
|
|
302
|
+
log.warning("Failed to create batch notification", exc_info=True)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
async def fail_interrupted_jobs(session: AsyncSession) -> int:
|
|
306
|
+
"""Mark every pending or running job as failed. Returns how many were marked.
|
|
307
|
+
|
|
308
|
+
Runs at process start: a job can only run inside the process that started
|
|
309
|
+
it, so anything still pending or running at boot was lost to the restart.
|
|
310
|
+
"""
|
|
311
|
+
rows = (await session.execute(
|
|
312
|
+
select(AIBatchJob).where(AIBatchJob.status.in_(("pending", "running")))
|
|
313
|
+
)).scalars().all()
|
|
314
|
+
now = datetime.now(timezone.utc)
|
|
315
|
+
for job in rows:
|
|
316
|
+
job.status = "failed"
|
|
317
|
+
job.error = INTERRUPTED_ERROR
|
|
318
|
+
job.completed_at = now
|
|
319
|
+
session.add(job)
|
|
320
|
+
return len(rows)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
async def get_batch_job(
|
|
324
|
+
session: AsyncSession,
|
|
325
|
+
job_id: uuid.UUID,
|
|
326
|
+
company_id: uuid.UUID,
|
|
327
|
+
user_id: uuid.UUID,
|
|
328
|
+
) -> AIBatchJob | None:
|
|
329
|
+
"""Get a batch job by ID, scoped to company and owning user."""
|
|
330
|
+
job = await session.get(AIBatchJob, job_id)
|
|
331
|
+
if job is None or job.company_id != company_id or job.user_id != user_id:
|
|
332
|
+
return None
|
|
333
|
+
return job
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
async def list_conversation_jobs(
|
|
337
|
+
session: AsyncSession,
|
|
338
|
+
conversation_id: uuid.UUID,
|
|
339
|
+
company_id: uuid.UUID,
|
|
340
|
+
user_id: uuid.UUID,
|
|
341
|
+
) -> list[AIBatchJob]:
|
|
342
|
+
"""Every job started from a conversation, oldest first."""
|
|
343
|
+
q = (
|
|
344
|
+
select(AIBatchJob)
|
|
345
|
+
.where(AIBatchJob.conversation_id == conversation_id, AIBatchJob.company_id == company_id, AIBatchJob.user_id == user_id)
|
|
346
|
+
.order_by(AIBatchJob.created_at.asc())
|
|
347
|
+
)
|
|
348
|
+
return list((await session.execute(q)).scalars().all())
|