celerp 2.3.2__tar.gz → 2.3.3__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.2 → celerp-2.3.3}/PKG-INFO +1 -1
- celerp-2.3.3/celerp/db.py +136 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/events/schemas.py +11 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/main.py +11 -10
- celerp-2.3.3/celerp/migrations/versions/c9d8e7f6a5b4_seed_shrinkage_writeoff_account.py +65 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/migrations_runner.py +33 -29
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/doctor.py +8 -3
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/ledger.py +15 -5
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/auto_je.py +2 -2
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/cost_visibility.py +17 -1
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/field_schema.py +20 -1
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/system_health.py +19 -8
- {celerp-2.3.2 → celerp-2.3.3}/celerp.egg-info/PKG-INFO +1 -1
- {celerp-2.3.2 → celerp-2.3.3}/celerp.egg-info/SOURCES.txt +10 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp.egg-info/scm_file_list.json +23 -0
- celerp-2.3.3/celerp.egg-info/scm_version.json +8 -0
- {celerp-2.3.2 → celerp-2.3.3}/conftest.py +15 -1
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/celerp_accounting/routes.py +1 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/statement.html +1 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-admin/celerp_admin/routes.py +34 -29
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/doc_constants.py +3 -2
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/doc_projections.py +11 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/routes.py +789 -331
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/routes_payments.py +5 -5
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_audits.py +150 -3
- celerp-2.3.3/default_modules/celerp-docs/tests/test_bulk_payment_alloc_lock.py +502 -0
- celerp-2.3.3/default_modules/celerp-docs/tests/test_cross_lot_settlement.py +168 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_list_concurrency.py +115 -2
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_list_outcome_concurrency.py +268 -0
- celerp-2.3.3/default_modules/celerp-docs/tests/test_memo_close.py +176 -0
- celerp-2.3.3/default_modules/celerp-docs/tests/test_memo_close_projection.py +26 -0
- celerp-2.3.3/default_modules/celerp-docs/tests/test_memo_close_review_fixes.py +450 -0
- celerp-2.3.3/default_modules/celerp-docs/tests/test_memo_lifecycle_concurrency.py +992 -0
- celerp-2.3.3/default_modules/celerp-docs/tests/test_memo_line_labels.py +191 -0
- celerp-2.3.3/default_modules/celerp-docs/tests/test_memo_unfulfilled_filter.py +47 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_send_visibility.py +16 -0
- celerp-2.3.3/default_modules/celerp-docs/tests/test_sold_label_ordering.py +95 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_writeoffs.py +303 -1
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/celerp_inventory/routes.py +390 -49
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/routes.py +5 -2
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/first_party.lock.json +5 -5
- {celerp-2.3.2 → celerp-2.3.3}/ui/api_client.py +38 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/shell.py +6 -2
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/am.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/ar.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/de.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/en.json +18 -8
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/es.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/fr.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/id.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/it.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/ja.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/pt.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/th.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/locales/vi.json +17 -7
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/documents.py +153 -92
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_cloud.py +0 -12
- {celerp-2.3.2 → celerp-2.3.3}/ui/static/app.css +1 -1
- celerp-2.3.2/celerp/db.py +0 -61
- celerp-2.3.2/celerp.egg-info/scm_version.json +0 -8
- {celerp-2.3.2 → celerp-2.3.3}/CLA.md +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/CONTRIBUTING.md +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/LICENSING.md +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/MANIFEST.in +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/NOTICE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/README.md +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/alembic.ini +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/__main__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/batch.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/cleanup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/commands.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/conversations.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/files.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/intent.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/llm.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/memory.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/models.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/page_count.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/quota.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/service.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/ai/tools.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/alembic.ini +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/alembic_config.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/cli.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/compat.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/compute/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/compute/aggregations.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/compute/valuation.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/config.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/base.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/daily_scheduler.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/http.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/images.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/quickbooks.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/registry.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/relay_token.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/shopify.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/sync_runner.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/upsert.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/util.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/webhooks.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/woocommerce.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/connectors/xero.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/constants.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/embedded_pg.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/events/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/events/engine.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/events/types.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/gateway/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/gateway/client.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/gateway/state.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/importers/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/importers/importer.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/importers/schema.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/inventory_codes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/middleware.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/README.md +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/_auto_stamp.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/_data_reconcile.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/_json_compat.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/env.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/script.py.mako +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/a0b1c2d3e4f5_seed_landed_cost_clearing_accounts.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/a1b2c3d4e5f6_add_doc_share_tokens.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/b1c2d3e4f5a6_add_supporter_badges.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/b2c3d4e5f6a7_add_import_batches.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/b3c4d5e6f7a8_expand_role_permissions_to_role_grants.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/bc0d1e2f3a4b_barcode_unique_index.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/c1d2e3f4a5b6_add_marketplace.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/c2d3e4f5a6b7_add_is_sync_to_shopify.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/c4d5e6f7a8b9_account_cash_flow_category.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/d0e1f2a3b4c5_add_share_token_expiry.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/d2e3f4a5b6c7_add_password_reset_token.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/d5e6f7a8b9c0_rename_fx_rounding_to_fx_difference.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/e3f4a5b6c7d8_add_company_is_active.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/e4f5a6b7c8d9_backfill_connector_idempotency_key.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/e7c9a1b3d5f2_work_center_default_columns.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/f1a2b3c4d5e6_move_accounts_marketplace_to_modules.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/f6a7b8c9d0e1_seed_fx_rounding_account.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/f8a9b0c1d2e3_work_center_default_backfill.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/fd5de461e14e_initial_schema.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/g1h2i3j4k5l6_add_consignment_flag.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/h2i3j4k5l6m7_add_bank_accounts_and_reconciliation.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/j4k5l6m7n8o9_labels_db_persistence.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/k5l6m7n8o9p0_add_reconciliation_v2.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/l6m7n8o9p0q1_add_sync_runs_table.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/m7n8o9p0q1r2_add_connector_configs_and_outbound_queue.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/n8o9p0q1r2s3_backfill_payment_date.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/o9p0q1r2s3t4_backfill_item_price_fields.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/p1q2r3s4t5u6_add_session_registry_and_user_auth_state.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/q2r3s4t5u6v7_add_system_runtime_state.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/r3s4t5u6v7w8_add_projections_company_entity_type_index.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/s4t5u6v7w8x9_drop_user_company_id_role.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/t5u6v7w8x9y0_seed_inventory_sub_accounts.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/u6v7w8x9y0z1_backfill_item_prices_from_attributes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/v7w8x9y0z1a2_backfill_purchase_unit_defaults.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/w8x9y0z1a2b3_backfill_category_unit_defaults.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/x7y8z9a0b1c2_add_projection_created_at.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/y8z9a0b1c2d3_per_company_ledger_idempotency.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/migrations/versions/z9a0b1c2d3e4_work_centers.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/accounting.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/ai.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/auth.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/base.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/company.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/connector_config.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/import_batch.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/ledger.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/marketplace.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/notification.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/projections.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/share.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/supporter.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/models/sync_run.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/api.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/audit.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/demotion.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/importer.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/license.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/loader.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/meta.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/references.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/registry.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/modules/slots.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/notifications/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/notifications/service.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/notifications/sse.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/output/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/output/branding.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/output/doc_print.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/output/pdf.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/output/share_render.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/projections/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/projections/engine.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/projections/handlers/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/projections/handlers/marketplace.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/projections/handlers/scanning.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/projections/handlers/shopify.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/projections/handlers/system.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/auth.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/companies.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/debug.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/events.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/health.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/notifications.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/stars.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/routers/system.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/schemas/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/activity_redaction.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/attachments.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/auth.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/backup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/backup_export.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/backup_import.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/backup_repo.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/backup_scheduler.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/backup_state.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/cogs_backfill.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/demo.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/dev_release_guard.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/email.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/fulfill.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/holdings.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/je_keys.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/landed_cost.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/line_measures.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/list_behavior.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/money.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/payments.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/permissions.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/pick.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/pricing.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/relay_share.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/reorder.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/runtime_state.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/session_tracker.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/shipping.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/star_cta.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/status_doc_backfill.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/supporter_badge.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/services/units.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/session_gate.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp/tax_regimes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp.egg-info/dependency_links.txt +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp.egg-info/entry_points.txt +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp.egg-info/requires.txt +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/celerp.egg-info/top_level.txt +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/conftest_support.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/celerp_accounting/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/celerp_accounting/api_setup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/celerp_accounting/csv_parser.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/celerp_accounting/matcher.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/celerp_accounting/models.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/celerp_accounting/projections.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/celerp_accounting/ui_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/balance-sheet.html +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/cash-flow.html +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/extended-journal-csv.csv +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/extended-journal-print.html +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/extended-journal.html +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/general-ledger.html +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/journal-csv.csv +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/journal-print.html +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/journal.html +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/ledger.html +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/pnl.html +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/report_goldens/trial-balance.html +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_accounting_banking.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_accounting_banking_routers.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_accounting_gaps.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_accounting_import_idempotency.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_cash_flow.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_financial_reports_ui.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_journal_gl_soa.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_journal_gl_soa_ui.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_reconciliation_v2.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_reports_end_to_end.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-accounting/tests/test_route_permissions.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-admin/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-admin/celerp_admin/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-admin/celerp_admin/setup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/celerp_ai/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/celerp_ai/routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/celerp_ai/setup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/celerp_ai/ui_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/conftest.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_batch.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_cleanup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_conversations.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_coverage_gaps.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_intent.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_llm.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_memory.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_models.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_page_count.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_quota.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_router.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_routes_coverage.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_service.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-ai/tests/test_tools.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-backup/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-backup/celerp_backup/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-backup/celerp_backup/routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-backup/celerp_backup/setup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/celerp_connectors/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/celerp_connectors/models.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/celerp_connectors/routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/conftest.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_compliance.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_connector_correctness.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_connectors.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_credentials_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_images.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_outbound.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_quickbooks.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_rate_limiting.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_shopify.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_wiring.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_woocommerce.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_woocommerce_webhooks.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-connectors/tests/test_xero.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-contacts/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-contacts/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-contacts/celerp_contacts/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-contacts/celerp_contacts/migrations.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-contacts/celerp_contacts/projections.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-contacts/celerp_contacts/routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-contacts/celerp_contacts/services.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-contacts/celerp_contacts/ui_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-dashboard/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-dashboard/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-dashboard/celerp_dashboard/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-dashboard/celerp_dashboard/routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-dashboard/celerp_dashboard/setup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/api_setup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/doc_email.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/doc_service.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/models_share.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/routes_share.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/sequences.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/taxes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/celerp_docs/ui_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/conftest.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_consolidate_lots.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_freight_je.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_freight_lines.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_fulfill_no_split.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_fulfillment_activity.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_inbound_je_lifecycle.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_inventory_account_reconciliation.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_landed_receive.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_line_delete_persist.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_line_identifier.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_payment_void_activity.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_receive_sku_batch.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_service_lines.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-docs/tests/test_void_guards.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/celerp_inventory/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/celerp_inventory/models_import_batch.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/celerp_inventory/projections.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/celerp_inventory/routes_attachments.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/celerp_inventory/routes_scanning.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/celerp_inventory/services.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/celerp_inventory/ui_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/tests/test_item_recipe_projection.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/tests/test_item_workflow_projection.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-inventory/tests/test_landed_cost_projection.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/am.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/ar.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/de.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/en.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/es.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/fr.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/id.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/it.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/ja.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/pt.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/th.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/locales/vi.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/models.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/presets.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/service.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/celerp_labels/ui_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/requirements.txt +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/tests/test_labels.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-labels/tests/test_labels_module.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/celerp_manufacturing/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/celerp_manufacturing/costing.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/celerp_manufacturing/expansion.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/celerp_manufacturing/labor.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/celerp_manufacturing/migrations.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/celerp_manufacturing/projection_handler.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/celerp_manufacturing/routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/celerp_manufacturing/ui_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/requirements.txt +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_auto_complete_on_finalize.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_bom_removed.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_build_api.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_completion_lock_order.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_item_recipe_api.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_item_workflow_api.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_labor_providers.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_manufacture_from_doc.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_manufacturing.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_manufacturing_import_idempotency.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_manufacturing_module.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_mfg_events.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_phase2_manufacturing_validations.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_production_order.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_recipe_costing.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_recipe_expansion.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_recost_api.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_run_records.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_to_make_allocation.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_where_used.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_work_centers_and_settings.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-manufacturing/tests/test_workflow_time.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-reports/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-reports/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-reports/celerp_reports/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-reports/celerp_reports/api_setup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-reports/celerp_reports/routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-reports/celerp_reports/ui_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-reports/tests/test_reports_full.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-reports/tests/test_reports_unit.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-subscriptions/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-subscriptions/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-subscriptions/celerp_subscriptions/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-subscriptions/celerp_subscriptions/routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-subscriptions/celerp_subscriptions/ui_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-subscriptions/tests/test_subscriptions.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-subscriptions/tests/test_subscriptions_ui.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/LICENSE +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/accessory_fashion.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/activewear.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/art_photography.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/audio_equipment.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/bag_handbag.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/banknote.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/beauty_tool.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/bed_bedroom.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/beer.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/beverage_nonalc.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/body_part_auto.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/book.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/bottoms.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/brake_suspension.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/bullion_coin.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/camera.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/colored_stone.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/comic.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/commercial_space.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/component_part.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/confectionery.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/consulting_service.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/decorative_art.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/diamond.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/drawing.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/dress_jumpsuit.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_auto.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_component.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/emerald.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/engine_part.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/fastener.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/fertilizer_chemical.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/film_video.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/fine_writing_instrument.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/fluid_lubricant.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/footwear.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/fragrance.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_food.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_produce.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/frozen_food.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/gaming_console.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/gold_bullion.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/grain_cereal.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/haircare.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/hand_tool.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/ingredient_bulk.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/interior_part.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/jewelry.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/kitchen_dining.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/laptop.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/lighting.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/livestock_feed.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/makeup.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/measuring_instrument.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/medal_token.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/mineral_specimen.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/mobile_phone.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/music_cd.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/music_vinyl.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/nail.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/numismatic_coin.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/outdoor_furniture.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/outerwear.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/packaged_food.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/painting.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/parking_bay.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/pearl.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/personal_care.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/pipe_plumbing.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/platinum_bullion.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/power_tool.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/print_edition.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/residential_unit.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/rough_gemstone.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/ruby.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/saas_plan.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/safety_ppe.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/sapphire.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/sculpture.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/seating.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/seeds.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/silver_bullion.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/skincare.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/soft_furnishing.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/software_addon.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/software_license.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/spirit.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/storage_furniture.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/swimwear.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/table_desk.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/tablet.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/tire_wheel.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/tops.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/trading_card.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/tv_display.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/video_game.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/watch.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/watch_strap.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/categories/wine.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/agricultural.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/artwork.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/automotive.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/blank.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/books_media.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/coins_precious_metals.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/consulting.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/cosmetics.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/electronics.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/fashion.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/food_beverage.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/furniture.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/gemstones.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/hardware.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/property_rental.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/saas.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/watches.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/presets/wine_spirits.json +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/celerp_verticals/ui_routes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/tests/test_verticals.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/default_modules/celerp-verticals/tests/test_verticals_routers.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/legal/OFFICIAL-COMPONENTS.md +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/legal/TRADEMARK.md +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/packaging/winget/Celerp.Celerp.installer.yaml +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/packaging/winget/Celerp.Celerp.locale.en-US.yaml +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/packaging/winget/Celerp.Celerp.yaml +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/packaging/winget/README.md +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/pyproject.toml +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/setup.cfg +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/test_helpers.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/app.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/activity.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/attrs.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/backup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/cloud_gate.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/currency.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/files.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/journal.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/notes.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/phone.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/report_kit.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/components/table.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/config.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/i18n.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/marketplace_catalog.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/__init__.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/account.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/accounting.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/accounting_import.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/auth.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/contacts.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/csv_import.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/dashboard.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/docs_import.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/events.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/financial_reports.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/inventory.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/lists_import.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/manufacturing.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/modules_page.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/notifications.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/reconciliation.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/reports.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/search.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_accounting.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_connectors.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_contacts.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_general.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_import.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_inventory.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_manufacturing.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_payments.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_purchasing.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/settings_sales.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/setup.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/stars.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/subscriptions.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/routes/subscriptions_import.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/security.py +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/static/htmx.min.js +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/static/icon.png +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/static/logo.png +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/static/vendor/intl-tel-input/img/flags.webp +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/static/vendor/intl-tel-input/img/flags@2x.webp +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/static/vendor/intl-tel-input/intlTelInput.min.css +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/static/vendor/intl-tel-input/intlTelInput.min.js +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/static/vendor/intl-tel-input/intlTelInputWithUtils.min.js +0 -0
- {celerp-2.3.2 → celerp-2.3.3}/ui/static/vendor/intl-tel-input/utils.js +0 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Copyright (c) 2026 Noah Severs
|
|
2
|
+
# SPDX-License-Identifier: BUSL-1.1
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import re
|
|
6
|
+
from contextlib import asynccontextmanager
|
|
7
|
+
|
|
8
|
+
from sqlalchemy import text as _sql_text
|
|
9
|
+
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
|
|
10
|
+
from sqlalchemy.pool import NullPool
|
|
11
|
+
|
|
12
|
+
from celerp.config import settings
|
|
13
|
+
|
|
14
|
+
# Shared advisory-lock key that serialises schema migrations across every process
|
|
15
|
+
# that might run them (the CLI upgrade command and the API startup phase). One
|
|
16
|
+
# key, one source of truth, so two boots can never migrate the same database at
|
|
17
|
+
# once.
|
|
18
|
+
_MIGRATION_LOCK_KEY = 4207320001
|
|
19
|
+
|
|
20
|
+
# Redacts the password in any Postgres URL: "://user:secret@host" -> "://user:***@host".
|
|
21
|
+
# One authoritative masker for logs and surfaced errors so a connection string
|
|
22
|
+
# never leaks a password.
|
|
23
|
+
_DB_CREDENTIALS_RE = re.compile(r"(://[^:]+:)[^@]+(@)")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def mask_db_credentials(text: str) -> str:
|
|
27
|
+
"""Return text with any database URL password replaced by ``***``."""
|
|
28
|
+
return _DB_CREDENTIALS_RE.sub(r"\1***\2", text)
|
|
29
|
+
|
|
30
|
+
# Request-connection timeouts (ms). One source of truth: the engine sets them in
|
|
31
|
+
# server_settings, and lifecycle_timeouts_disabled restores exactly these values
|
|
32
|
+
# after clearing them for startup work.
|
|
33
|
+
_REQUEST_LOCK_TIMEOUT_MS = "3000"
|
|
34
|
+
_REQUEST_STATEMENT_TIMEOUT_MS = "30000"
|
|
35
|
+
|
|
36
|
+
# Pool budget: total_possible = (api_workers * (pool_size + max_overflow))
|
|
37
|
+
# + (gui_workers * (gui_pool_size + gui_max_overflow))
|
|
38
|
+
# Default workers 2 API + 1 GUI → 2*(10+5) + 1*(5+5) = 40 connections max.
|
|
39
|
+
# Postgres default max_connections=100 leaves 60 for migrations, admin tools, etc.
|
|
40
|
+
# If you increase worker counts, recalculate this budget before deploying.
|
|
41
|
+
if os.environ.get("CELERP_TEST_NULLPOOL"):
|
|
42
|
+
# Test mode: a fresh connection per use that closes on return, so a failed
|
|
43
|
+
# test can't leave a poisoned/locked connection lingering in a pooled
|
|
44
|
+
# connection and block the next test's TRUNCATE. Only ever set by the test
|
|
45
|
+
# harness; no effect in production.
|
|
46
|
+
engine = create_async_engine(settings.database_url, future=True, poolclass=NullPool)
|
|
47
|
+
else:
|
|
48
|
+
engine = create_async_engine(
|
|
49
|
+
settings.database_url,
|
|
50
|
+
future=True,
|
|
51
|
+
pool_pre_ping=True,
|
|
52
|
+
pool_size=10,
|
|
53
|
+
max_overflow=5,
|
|
54
|
+
# Bound how long any query may wait on a lock or run, so a stuck query is
|
|
55
|
+
# cancelled instead of pinning one of the few pooled connections for the
|
|
56
|
+
# full request lifetime (lock_timeout 3s, statement_timeout 30s, in ms).
|
|
57
|
+
# This is a per-connection default, so it applies to every request AND
|
|
58
|
+
# every pooled background job (connector syncs, the gateway, the daily
|
|
59
|
+
# scheduler) - all of which must stay bounded. Startup reconciliation and
|
|
60
|
+
# the projection rebuild are the only work that legitimately runs longer;
|
|
61
|
+
# they use lifecycle_engine below instead of this pool, and the migration
|
|
62
|
+
# advisory-lock wait self-exempts via lifecycle_timeouts_disabled.
|
|
63
|
+
connect_args={
|
|
64
|
+
"server_settings": {
|
|
65
|
+
"lock_timeout": _REQUEST_LOCK_TIMEOUT_MS,
|
|
66
|
+
"statement_timeout": _REQUEST_STATEMENT_TIMEOUT_MS,
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
)
|
|
70
|
+
SessionLocal = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
|
71
|
+
|
|
72
|
+
# Lifecycle/maintenance engine: a separate NullPool engine carrying NO statement
|
|
73
|
+
# or lock timeout. Startup reconciliation (create_all, module on_modules_ready
|
|
74
|
+
# seed hooks, the develop->release projection rebuild, the one-time status-doc and
|
|
75
|
+
# COGS backfills) and the on-demand projection rebuild routes run whole-table
|
|
76
|
+
# DELETEs and full-ledger replays that can legitimately exceed the request
|
|
77
|
+
# statement_timeout on a mature database. Running them on the bounded request pool
|
|
78
|
+
# would cancel them at 30s - permanently blocking boot's upgrade guard and the
|
|
79
|
+
# /ledger/rebuild recovery route. They run on this engine instead. NullPool: these
|
|
80
|
+
# operations are rare and brief, so no pooled slot is reserved and the request pool
|
|
81
|
+
# budget above is unaffected (at most one transient connection per concurrent
|
|
82
|
+
# lifecycle op).
|
|
83
|
+
lifecycle_engine = create_async_engine(settings.database_url, future=True, poolclass=NullPool)
|
|
84
|
+
LifecycleSessionLocal = async_sessionmaker(
|
|
85
|
+
lifecycle_engine, class_=AsyncSession, expire_on_commit=False
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@asynccontextmanager
|
|
90
|
+
async def lifecycle_timeouts_disabled(conn):
|
|
91
|
+
"""Clear the request statement/lock timeouts on the migration lock connection.
|
|
92
|
+
|
|
93
|
+
The migration advisory-lock wait runs on a connection drawn from the bounded
|
|
94
|
+
request engine (so a single engine serialises boots), but a second worker's
|
|
95
|
+
wait can legitimately exceed the 30s statement_timeout while the first worker
|
|
96
|
+
migrates, and a cancelled wait aborts the boot. This sets both timeouts to 0
|
|
97
|
+
(unbounded) for the block and restores the request defaults on exit, so the
|
|
98
|
+
connection returned to the pool still carries them. Other long-running startup
|
|
99
|
+
work uses lifecycle_engine (no timeout) rather than this in-place exemption.
|
|
100
|
+
Postgres only; a no-op on other dialects, which have no such settings.
|
|
101
|
+
"""
|
|
102
|
+
if conn.dialect.name != "postgresql":
|
|
103
|
+
yield
|
|
104
|
+
return
|
|
105
|
+
await conn.execute(_sql_text("SET statement_timeout = 0"))
|
|
106
|
+
await conn.execute(_sql_text("SET lock_timeout = 0"))
|
|
107
|
+
try:
|
|
108
|
+
yield
|
|
109
|
+
finally:
|
|
110
|
+
await conn.execute(_sql_text(f"SET statement_timeout = {_REQUEST_STATEMENT_TIMEOUT_MS}"))
|
|
111
|
+
await conn.execute(_sql_text(f"SET lock_timeout = {_REQUEST_LOCK_TIMEOUT_MS}"))
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
async def get_session() -> AsyncSession:
|
|
115
|
+
async with SessionLocal() as session:
|
|
116
|
+
yield session
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@asynccontextmanager
|
|
120
|
+
async def get_session_ctx():
|
|
121
|
+
"""Standalone async context manager for use outside FastAPI request handlers."""
|
|
122
|
+
async with SessionLocal() as session:
|
|
123
|
+
yield session
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@asynccontextmanager
|
|
127
|
+
async def get_lifecycle_session_ctx():
|
|
128
|
+
"""Session on the unbounded lifecycle_engine, for known long-running work.
|
|
129
|
+
|
|
130
|
+
Use for the projection rebuild and startup backfills: a full rebuild's
|
|
131
|
+
whole-table DELETE and full-ledger replay can exceed the request
|
|
132
|
+
statement_timeout on a mature database, and must not be cancelled. Ordinary
|
|
133
|
+
request and background work uses get_session/get_session_ctx (bounded).
|
|
134
|
+
"""
|
|
135
|
+
async with LifecycleSessionLocal() as session:
|
|
136
|
+
yield session
|
|
@@ -546,6 +546,15 @@ class DocUnvoided(BaseModel):
|
|
|
546
546
|
restored_status: str
|
|
547
547
|
|
|
548
548
|
|
|
549
|
+
class DocClosed(BaseModel):
|
|
550
|
+
reason: str | None = None
|
|
551
|
+
pre_close_status: str | None = None
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
class DocReopened(BaseModel):
|
|
555
|
+
restored_status: str
|
|
556
|
+
|
|
557
|
+
|
|
549
558
|
class DocSent(BaseModel):
|
|
550
559
|
sent_via: str | None = None
|
|
551
560
|
sent_to: str | None = None
|
|
@@ -1162,6 +1171,8 @@ EVENT_SCHEMA_MAP: dict[str, type[BaseModel]] = {
|
|
|
1162
1171
|
"doc.voided": DocVoided,
|
|
1163
1172
|
"doc.reverted_to_draft": DocRevertedToDraft,
|
|
1164
1173
|
"doc.unvoided": DocUnvoided,
|
|
1174
|
+
"doc.closed": DocClosed,
|
|
1175
|
+
"doc.reopened": DocReopened,
|
|
1165
1176
|
"doc.converted_to_bill": DocConvertedToBill,
|
|
1166
1177
|
"doc.sent": DocSent,
|
|
1167
1178
|
"doc.payment.received": DocPaymentReceived,
|
|
@@ -12,7 +12,7 @@ from slowapi import Limiter, _rate_limit_exceeded_handler
|
|
|
12
12
|
from slowapi.errors import RateLimitExceeded
|
|
13
13
|
from slowapi.util import get_remote_address
|
|
14
14
|
|
|
15
|
-
from celerp.db import engine, mask_db_credentials
|
|
15
|
+
from celerp.db import engine, lifecycle_engine, mask_db_credentials
|
|
16
16
|
from celerp.inventory_codes import BarcodeConflictError
|
|
17
17
|
from celerp.config import settings, assert_secure_jwt, ensure_instance_id, load_cloud_config, load_backup_config
|
|
18
18
|
load_cloud_config()
|
|
@@ -164,7 +164,7 @@ async def _try_auto_activate() -> None:
|
|
|
164
164
|
async def lifespan(_app: FastAPI):
|
|
165
165
|
(settings.data_dir / "static" / "attachments").mkdir(parents=True, exist_ok=True)
|
|
166
166
|
try:
|
|
167
|
-
async with
|
|
167
|
+
async with lifecycle_engine.begin() as conn:
|
|
168
168
|
await conn.run_sync(Base.metadata.create_all)
|
|
169
169
|
except Exception as exc:
|
|
170
170
|
masked_url = mask_db_credentials(settings.database_url)
|
|
@@ -205,19 +205,20 @@ async def lifespan(_app: FastAPI):
|
|
|
205
205
|
register_api_routes(_app, _loaded_modules)
|
|
206
206
|
# Module models register on Base.metadata at import time.
|
|
207
207
|
# Run create_all again so module tables are created (idempotent).
|
|
208
|
-
async with
|
|
208
|
+
async with lifecycle_engine.begin() as conn:
|
|
209
209
|
await conn.run_sync(Base.metadata.create_all)
|
|
210
210
|
# Allow modules to backfill data for existing companies (e.g. seed
|
|
211
211
|
# chart of accounts when accounting module is first enabled on an
|
|
212
212
|
# instance that already has companies).
|
|
213
213
|
from celerp.modules.slots import fire_lifecycle as _fire
|
|
214
|
-
from celerp.db import
|
|
214
|
+
from celerp.db import LifecycleSessionLocal as _LifecycleSession
|
|
215
215
|
# Best-effort, like the two sibling blocks below: a hook that fails
|
|
216
216
|
# during flush poisons the shared session, so the commit raises.
|
|
217
217
|
# Roll back and log at ERROR rather than let that crash boot - the
|
|
218
218
|
# manufacturing seed hook, for one, must never be able to take the
|
|
219
|
-
# app down.
|
|
220
|
-
|
|
219
|
+
# app down. Seed hooks can replay large ledgers, so they run on the
|
|
220
|
+
# unbounded lifecycle engine, not the timeout-bounded request pool.
|
|
221
|
+
async with _LifecycleSession() as _sess:
|
|
221
222
|
try:
|
|
222
223
|
await _fire("on_modules_ready", session=_sess)
|
|
223
224
|
await _sess.commit()
|
|
@@ -236,7 +237,7 @@ async def lifespan(_app: FastAPI):
|
|
|
236
237
|
_demoted = demoted_first_party(_enabled)
|
|
237
238
|
if _demoted:
|
|
238
239
|
from celerp.modules.demotion import notify_demoted_modules
|
|
239
|
-
async with
|
|
240
|
+
async with _LifecycleSession() as _dsess:
|
|
240
241
|
await notify_demoted_modules(_dsess, _demoted)
|
|
241
242
|
await _dsess.commit()
|
|
242
243
|
except Exception:
|
|
@@ -256,7 +257,7 @@ async def lifespan(_app: FastAPI):
|
|
|
256
257
|
# marker so it runs once per version. Non-fatal: a failure must not block
|
|
257
258
|
# boot — the marker stays unset and a later boot retries.
|
|
258
259
|
try:
|
|
259
|
-
from celerp.db import
|
|
260
|
+
from celerp.db import LifecycleSessionLocal as _GuardSession
|
|
260
261
|
from celerp.services.dev_release_guard import run_upgrade_guard
|
|
261
262
|
async with _GuardSession() as _guard_sess:
|
|
262
263
|
await run_upgrade_guard(_guard_sess)
|
|
@@ -271,7 +272,7 @@ async def lifespan(_app: FastAPI):
|
|
|
271
272
|
# or consigned in before that field shipped, so their inventory status links
|
|
272
273
|
# to its document. Marker-gated (runs once); non-fatal like the guard above.
|
|
273
274
|
try:
|
|
274
|
-
from celerp.db import
|
|
275
|
+
from celerp.db import LifecycleSessionLocal as _BackfillSession
|
|
275
276
|
from celerp.services.status_doc_backfill import run_status_doc_backfill
|
|
276
277
|
async with _BackfillSession() as _bf_sess:
|
|
277
278
|
await run_status_doc_backfill(_bf_sess)
|
|
@@ -287,7 +288,7 @@ async def lifespan(_app: FastAPI):
|
|
|
287
288
|
# (runs once; retries stragglers while any doc is locked or errored);
|
|
288
289
|
# non-fatal like the backfill above.
|
|
289
290
|
try:
|
|
290
|
-
from celerp.db import
|
|
291
|
+
from celerp.db import LifecycleSessionLocal as _CogsSession
|
|
291
292
|
from celerp.services.cogs_backfill import run_cogs_backfill
|
|
292
293
|
async with _CogsSession() as _cogs_sess:
|
|
293
294
|
await run_cogs_backfill(_cogs_sess)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Copyright (c) 2026 Noah Severs
|
|
2
|
+
# SPDX-License-Identifier: BUSL-1.1
|
|
3
|
+
|
|
4
|
+
"""seed the inventory shrinkage/write-off account 6970 for existing companies
|
|
5
|
+
|
|
6
|
+
Revision ID: c9d8e7f6a5b4
|
|
7
|
+
Revises: bc0d1e2f3a4b
|
|
8
|
+
Create Date: 2026-08-31
|
|
9
|
+
|
|
10
|
+
Inventory write-offs and audit shrinkage post to 6970. New companies get the
|
|
11
|
+
account from THAI_CHART_OF_ACCOUNTS on creation; this backfills existing ones,
|
|
12
|
+
which would otherwise be refused at posting time.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from alembic import op
|
|
18
|
+
import sqlalchemy as sa
|
|
19
|
+
|
|
20
|
+
revision = "c9d8e7f6a5b4"
|
|
21
|
+
down_revision = "bc0d1e2f3a4b"
|
|
22
|
+
branch_labels = None
|
|
23
|
+
depends_on = None
|
|
24
|
+
|
|
25
|
+
_CODE = "6970"
|
|
26
|
+
_NAME = "Inventory Shrinkage & Write-offs"
|
|
27
|
+
_TYPE = "expense"
|
|
28
|
+
_PARENT = "6000"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def upgrade() -> None:
|
|
32
|
+
conn = op.get_bind()
|
|
33
|
+
# to_regclass resolves against the connection's search_path rather than
|
|
34
|
+
# assuming public, so the guard is correct for any schema the migration is
|
|
35
|
+
# actually run in.
|
|
36
|
+
table_exists = conn.execute(sa.text("SELECT to_regclass('accounts')")).scalar()
|
|
37
|
+
if not table_exists:
|
|
38
|
+
return # Nothing to backfill on fresh install
|
|
39
|
+
|
|
40
|
+
companies = conn.execute(
|
|
41
|
+
sa.text("SELECT DISTINCT company_id FROM accounts WHERE code = :parent"),
|
|
42
|
+
{"parent": _PARENT},
|
|
43
|
+
).fetchall()
|
|
44
|
+
|
|
45
|
+
for (company_id,) in companies:
|
|
46
|
+
exists = conn.execute(
|
|
47
|
+
sa.text("SELECT 1 FROM accounts WHERE company_id = :cid AND code = :code"),
|
|
48
|
+
{"cid": company_id, "code": _CODE},
|
|
49
|
+
).fetchone()
|
|
50
|
+
if not exists:
|
|
51
|
+
conn.execute(
|
|
52
|
+
sa.text(
|
|
53
|
+
"INSERT INTO accounts (id, company_id, code, name, account_type, parent_code, is_active, created_at) "
|
|
54
|
+
"VALUES (gen_random_uuid(), :cid, :code, :name, :acc_type, :parent, TRUE, NOW())"
|
|
55
|
+
),
|
|
56
|
+
{"cid": company_id, "code": _CODE, "name": _NAME,
|
|
57
|
+
"acc_type": _TYPE, "parent": _PARENT},
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def downgrade() -> None:
|
|
62
|
+
# The upgrade only inserts 6970 when absent, so a seeded row is indistinguishable from a
|
|
63
|
+
# company's own pre-existing 6970. Deleting on downgrade would destroy user data and orphan any
|
|
64
|
+
# ledger row referencing it, so the reversal intentionally leaves the account in place.
|
|
65
|
+
pass
|
|
@@ -29,7 +29,7 @@ import sqlalchemy as sa
|
|
|
29
29
|
from alembic.operations import Operations
|
|
30
30
|
from alembic.runtime.migration import MigrationContext
|
|
31
31
|
|
|
32
|
-
from celerp.db import _MIGRATION_LOCK_KEY, mask_db_credentials
|
|
32
|
+
from celerp.db import _MIGRATION_LOCK_KEY, lifecycle_timeouts_disabled, mask_db_credentials
|
|
33
33
|
from celerp.modules import loader
|
|
34
34
|
|
|
35
35
|
# A prefix is well-formed when it is a non-empty string of at least this length
|
|
@@ -197,36 +197,40 @@ async def run_migration_phase(engine, enabled):
|
|
|
197
197
|
lock_conn = await engine.connect()
|
|
198
198
|
lock_conn = await lock_conn.execution_options(isolation_level="AUTOCOMMIT")
|
|
199
199
|
try:
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
for name in sorted(enabled):
|
|
205
|
-
module_path = loader.resolve_module_path(name)
|
|
206
|
-
if module_path is None:
|
|
207
|
-
continue
|
|
208
|
-
manifest = loader.read_manifest(module_path)
|
|
209
|
-
migrations_pkg = manifest.get("migrations")
|
|
210
|
-
if not migrations_pkg:
|
|
211
|
-
continue
|
|
212
|
-
table_prefix = manifest.get("table_prefix") or ""
|
|
213
|
-
try:
|
|
214
|
-
async with engine.begin() as conn:
|
|
215
|
-
await conn.run_sync(
|
|
216
|
-
run_module_migrations, name, module_path,
|
|
217
|
-
migrations_pkg, table_prefix,
|
|
218
|
-
)
|
|
219
|
-
except Exception as exc:
|
|
220
|
-
if loader.is_first_party(module_path):
|
|
221
|
-
raise
|
|
222
|
-
held_errors[name] = mask_db_credentials(
|
|
223
|
-
f"Migration failed: {type(exc).__name__}: {exc}"
|
|
224
|
-
)
|
|
225
|
-
surviving.discard(name)
|
|
226
|
-
finally:
|
|
200
|
+
# The advisory-lock wait blocks until any other worker's phase finishes;
|
|
201
|
+
# the request statement_timeout would cancel that wait and abort the boot,
|
|
202
|
+
# so clear it on this connection for the whole locked section.
|
|
203
|
+
async with lifecycle_timeouts_disabled(lock_conn):
|
|
227
204
|
await lock_conn.execute(
|
|
228
|
-
sa.text("SELECT
|
|
205
|
+
sa.text("SELECT pg_advisory_lock(:key)"), {"key": _MIGRATION_LOCK_KEY}
|
|
229
206
|
)
|
|
207
|
+
try:
|
|
208
|
+
for name in sorted(enabled):
|
|
209
|
+
module_path = loader.resolve_module_path(name)
|
|
210
|
+
if module_path is None:
|
|
211
|
+
continue
|
|
212
|
+
manifest = loader.read_manifest(module_path)
|
|
213
|
+
migrations_pkg = manifest.get("migrations")
|
|
214
|
+
if not migrations_pkg:
|
|
215
|
+
continue
|
|
216
|
+
table_prefix = manifest.get("table_prefix") or ""
|
|
217
|
+
try:
|
|
218
|
+
async with engine.begin() as conn:
|
|
219
|
+
await conn.run_sync(
|
|
220
|
+
run_module_migrations, name, module_path,
|
|
221
|
+
migrations_pkg, table_prefix,
|
|
222
|
+
)
|
|
223
|
+
except Exception as exc:
|
|
224
|
+
if loader.is_first_party(module_path):
|
|
225
|
+
raise
|
|
226
|
+
held_errors[name] = mask_db_credentials(
|
|
227
|
+
f"Migration failed: {type(exc).__name__}: {exc}"
|
|
228
|
+
)
|
|
229
|
+
surviving.discard(name)
|
|
230
|
+
finally:
|
|
231
|
+
await lock_conn.execute(
|
|
232
|
+
sa.text("SELECT pg_advisory_unlock(:key)"), {"key": _MIGRATION_LOCK_KEY}
|
|
233
|
+
)
|
|
230
234
|
finally:
|
|
231
235
|
await lock_conn.close()
|
|
232
236
|
return surviving, held_errors
|
|
@@ -29,7 +29,7 @@ from fastapi import APIRouter, Depends, HTTPException, Query
|
|
|
29
29
|
from sqlalchemy import func, select, text
|
|
30
30
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
31
31
|
|
|
32
|
-
from celerp.db import get_session
|
|
32
|
+
from celerp.db import get_lifecycle_session_ctx, get_session
|
|
33
33
|
from celerp.events.engine import emit_event
|
|
34
34
|
from celerp.models.ledger import LedgerEntry
|
|
35
35
|
from celerp.models.projections import Projection
|
|
@@ -848,8 +848,13 @@ async def run_doctor(
|
|
|
848
848
|
await session.commit()
|
|
849
849
|
|
|
850
850
|
if rebuild and fix:
|
|
851
|
-
|
|
852
|
-
|
|
851
|
+
# The fixes above are already committed, so a fresh lifecycle session
|
|
852
|
+
# sees them. Run the rebuild there: replaying the whole ledger can
|
|
853
|
+
# exceed the request statement_timeout on a mature database, and a
|
|
854
|
+
# cancelled rebuild would leave projections half-built.
|
|
855
|
+
async with get_lifecycle_session_ctx() as _rebuild_sess:
|
|
856
|
+
await ProjectionEngine.rebuild(_rebuild_sess, company_id=company_id)
|
|
857
|
+
await _rebuild_sess.commit()
|
|
853
858
|
|
|
854
859
|
total_found = sum(r["found"] for r in results)
|
|
855
860
|
total_fixed = sum(r["fixed"] for r in results)
|
|
@@ -7,12 +7,12 @@ from fastapi import APIRouter, Depends, HTTPException
|
|
|
7
7
|
from sqlalchemy import func, select
|
|
8
8
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
9
9
|
|
|
10
|
-
from celerp.db import get_session
|
|
10
|
+
from celerp.db import get_lifecycle_session_ctx, get_session
|
|
11
11
|
from celerp.models.ledger import LedgerEntry
|
|
12
12
|
from celerp.projections.engine import ProjectionEngine
|
|
13
13
|
from celerp.services.activity_redaction import redact_entries_for_role, redact_event_costs
|
|
14
14
|
from celerp.services.auth import get_current_company_id, get_current_role, get_current_user
|
|
15
|
-
from celerp.services.permissions import get_current_company_settings
|
|
15
|
+
from celerp.services.permissions import get_current_company_settings, require_permission
|
|
16
16
|
|
|
17
17
|
router = APIRouter(dependencies=[Depends(get_current_user)])
|
|
18
18
|
|
|
@@ -105,7 +105,17 @@ async def get_entry(entry_id: int, company_id: str = Depends(get_current_company
|
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
@router.post("/rebuild")
|
|
108
|
-
async def rebuild(
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
async def rebuild(
|
|
109
|
+
company_id: str = Depends(get_current_company_id),
|
|
110
|
+
_: None = require_permission("manage_company_lifecycle"),
|
|
111
|
+
) -> dict:
|
|
112
|
+
# A full rebuild deletes every projection for the company and replays the
|
|
113
|
+
# whole ledger, which can exceed the request statement_timeout on a mature
|
|
114
|
+
# database. Run it on the unbounded lifecycle session so recovery is never
|
|
115
|
+
# cancelled mid-replay, leaving projections half-rebuilt. That unbounded work
|
|
116
|
+
# is gated on the owner-only company-lifecycle permission so an ordinary
|
|
117
|
+
# subuser cannot open concurrent full replays outside the request pool budget.
|
|
118
|
+
async with get_lifecycle_session_ctx() as session:
|
|
119
|
+
await ProjectionEngine.rebuild(session, company_id=company_id)
|
|
120
|
+
await session.commit()
|
|
111
121
|
return {"ok": True}
|
|
@@ -1127,9 +1127,9 @@ async def create_for_mfg_completed(session, *, company_id, user_id, order_id: st
|
|
|
1127
1127
|
|
|
1128
1128
|
|
|
1129
1129
|
# Inventory-audit stock adjustment accounts:
|
|
1130
|
-
# shrinkage (count < system): Dr
|
|
1130
|
+
# shrinkage (count < system): Dr 6970 Inventory Shrinkage & Write-offs / Cr 1130-P Inventory
|
|
1131
1131
|
# overage (count > system): Dr 1130-P Inventory / Cr 4300 Other Income
|
|
1132
|
-
_AUDIT_SHRINKAGE_ACCT = "
|
|
1132
|
+
_AUDIT_SHRINKAGE_ACCT = "6970"
|
|
1133
1133
|
_AUDIT_OVERAGE_ACCT = "4300"
|
|
1134
1134
|
_AUDIT_INVENTORY_ACCT = _INVENTORY_ACCT
|
|
1135
1135
|
|
|
@@ -15,11 +15,17 @@ from celerp.services.auth import ROLE_LEVELS
|
|
|
15
15
|
|
|
16
16
|
# Item-dict keys stripped when the caller lacks view_inventory_costs.
|
|
17
17
|
COST_ITEM_KEYS: frozenset[str] = frozenset({"cost_price", "cost_total"})
|
|
18
|
+
# Read-side cost companions: derived cost data that a cost-hidden caller must not see
|
|
19
|
+
# either, or the goods cost leaks through a value computed off it. Kept separate from
|
|
20
|
+
# COST_ITEM_KEYS because that set also drives write-path price classification; these are
|
|
21
|
+
# stripped only, never written or validated against.
|
|
22
|
+
COST_DERIVED_ITEM_KEYS: frozenset[str] = frozenset({"cost_base", "cost_landed", "landed_contributions"})
|
|
18
23
|
|
|
19
24
|
|
|
20
25
|
def apply_field_visibility(
|
|
21
26
|
items: list[dict], role: str, field_schema: list[dict], can_see_costs: bool,
|
|
22
27
|
can_author_drafts: bool = False,
|
|
28
|
+
derived_field_deps: dict[str, tuple[str, ...]] | None = None,
|
|
23
29
|
) -> list[dict]:
|
|
24
30
|
"""Strip fields from item dicts that the caller is not allowed to see.
|
|
25
31
|
|
|
@@ -36,6 +42,12 @@ def apply_field_visibility(
|
|
|
36
42
|
available, not at creation. When ``can_author_drafts`` (the caller holds
|
|
37
43
|
edit_inventory), a DRAFT item keeps its cost keys so its creator can finish
|
|
38
44
|
authoring it; every non-draft item is stripped as before.
|
|
45
|
+
|
|
46
|
+
Derived fields: ``derived_field_deps`` maps a computed key to the source keys
|
|
47
|
+
it is derived from (e.g. qty_each from quantity and pieces). A derived key is
|
|
48
|
+
stripped whenever ANY of its sources is stripped, so a caller cannot recover a
|
|
49
|
+
hidden source from a value computed off it. The rule is stated once by the
|
|
50
|
+
caller; this service stays generic and holds no field names of its own.
|
|
39
51
|
"""
|
|
40
52
|
caller_level = ROLE_LEVELS.get(role, 0)
|
|
41
53
|
restricted = {
|
|
@@ -55,6 +67,10 @@ def apply_field_visibility(
|
|
|
55
67
|
if cost_hidden and not (
|
|
56
68
|
can_author_drafts and str(item.get("status") or "").lower() == "draft"
|
|
57
69
|
):
|
|
58
|
-
drop |= COST_ITEM_KEYS
|
|
70
|
+
drop |= COST_ITEM_KEYS | COST_DERIVED_ITEM_KEYS
|
|
71
|
+
if derived_field_deps:
|
|
72
|
+
for derived, sources in derived_field_deps.items():
|
|
73
|
+
if any(s in drop for s in sources):
|
|
74
|
+
drop.add(derived)
|
|
59
75
|
out.append({k: v for k, v in item.items() if k not in drop} if drop else item)
|
|
60
76
|
return out
|
|
@@ -166,6 +166,18 @@ def cost_columns(price_lists: list[dict]) -> list[dict]:
|
|
|
166
166
|
return [f for f in _inject_price_columns([], price_lists) if f.get("key") in COST_SCHEMA_KEYS]
|
|
167
167
|
|
|
168
168
|
|
|
169
|
+
# The schema field types whose stored values are numeric, so a field of one of these
|
|
170
|
+
# types is range/exact scope-searchable and classified numeric on merge. Single source
|
|
171
|
+
# for that classification, consumed by the inventory search and merge paths.
|
|
172
|
+
NUMERIC_SCHEMA_TYPES: frozenset[str] = frozenset({"number", "money", "rate", "weight"})
|
|
173
|
+
|
|
174
|
+
# Field keys a company can never hide through a visible_to_roles override. status drives
|
|
175
|
+
# lifecycle membership filtering (sold/archived/draft) that runs BEFORE field visibility
|
|
176
|
+
# in list_items, so a role-restricted status would be a membership oracle: probing
|
|
177
|
+
# ?status=sold against the default view discloses the hidden value. Forcing an empty
|
|
178
|
+
# visible_to_roles keeps that pre-visibility filter safe.
|
|
179
|
+
NON_HIDEABLE_FIELD_KEYS: frozenset[str] = frozenset({"status"})
|
|
180
|
+
|
|
169
181
|
# Backward-compatible constant: base fields + default price columns
|
|
170
182
|
DEFAULT_ITEM_SCHEMA: list[dict] = _inject_price_columns(_BASE_FIELDS, _DEFAULT_PRICE_LISTS)
|
|
171
183
|
|
|
@@ -222,5 +234,12 @@ async def get_effective_field_schema(
|
|
|
222
234
|
keys_in_cat = {f["key"] for f in cat_fields}
|
|
223
235
|
merged = [f for f in base_schema if f["key"] not in keys_in_cat]
|
|
224
236
|
merged.extend(cat_fields)
|
|
225
|
-
|
|
237
|
+
base_schema = merged
|
|
238
|
+
|
|
239
|
+
# Non-hideable fields carry an empty visible_to_roles no matter what a stored base or
|
|
240
|
+
# category override set. Applied at the single exit so both paths are covered.
|
|
241
|
+
base_schema = [
|
|
242
|
+
{**f, "visible_to_roles": []} if f["key"] in NON_HIDEABLE_FIELD_KEYS else f
|
|
243
|
+
for f in base_schema
|
|
244
|
+
]
|
|
226
245
|
return _rehydrate_builtin_metadata(base_schema)
|
|
@@ -25,14 +25,23 @@ _MESSAGES = {
|
|
|
25
25
|
" unresponsive. Upgrade your RAM or close other applications."
|
|
26
26
|
),
|
|
27
27
|
"cpu_warning": "Your computer's processor is under heavy load. Response times may be slow.",
|
|
28
|
-
"disk_warning": "Your disk is getting full. Free up space to keep Celerp running smoothly.",
|
|
29
|
-
"disk_critical": (
|
|
30
|
-
"Your disk is almost full. Celerp may stop working if disk space runs out."
|
|
31
|
-
" Free up space immediately."
|
|
32
|
-
),
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
|
|
31
|
+
def _disk_message(suffix: str, used_percent: float, free_gb: float, total_gb: float) -> str:
|
|
32
|
+
"""A disk warning that names the numbers the user needs to act: how much is free
|
|
33
|
+
now, the total, and how much to free to clear the warning. The clear target is the
|
|
34
|
+
warning threshold (used <= _DISK_WARN), so the same actionable figure is shown for
|
|
35
|
+
both warning and critical - it is what makes the message disappear."""
|
|
36
|
+
to_free = round(max(0.0, (used_percent - _DISK_WARN) / 100.0 * total_gb), 1)
|
|
37
|
+
where = f"{free_gb:.1f} GB free of {total_gb:.1f} GB"
|
|
38
|
+
if suffix == "critical":
|
|
39
|
+
return (f"Your disk is almost full: {where}. Free up about {to_free:.1f} GB to"
|
|
40
|
+
" clear this warning, or Celerp may stop working if space runs out.")
|
|
41
|
+
return (f"Your disk is getting full: {where}. Free up about {to_free:.1f} GB more"
|
|
42
|
+
" to clear this warning.")
|
|
43
|
+
|
|
44
|
+
|
|
36
45
|
def _threshold(value: float, warn: float, crit: float | None) -> tuple[str, str | None]:
|
|
37
46
|
"""Return (status, message_key_suffix | None) for a metric."""
|
|
38
47
|
if crit is not None and value > crit:
|
|
@@ -54,6 +63,8 @@ def get_system_health() -> dict:
|
|
|
54
63
|
ram_status, ram_suffix = _threshold(mem.percent, _RAM_WARN, _RAM_CRIT)
|
|
55
64
|
cpu_status, cpu_suffix = _threshold(cpu_pct, _CPU_WARN, None)
|
|
56
65
|
disk_status, disk_suffix = _threshold(disk.percent, _DISK_WARN, _DISK_CRIT)
|
|
66
|
+
disk_free_gb = round(disk.free / _GB, 2)
|
|
67
|
+
disk_total_gb = round(disk.total / _GB, 2)
|
|
57
68
|
|
|
58
69
|
return {
|
|
59
70
|
"ram": {
|
|
@@ -70,10 +81,10 @@ def get_system_health() -> dict:
|
|
|
70
81
|
},
|
|
71
82
|
"disk": {
|
|
72
83
|
"used_percent": disk.percent,
|
|
73
|
-
"free_gb":
|
|
74
|
-
"total_gb":
|
|
84
|
+
"free_gb": disk_free_gb,
|
|
85
|
+
"total_gb": disk_total_gb,
|
|
75
86
|
"status": disk_status,
|
|
76
|
-
"message":
|
|
87
|
+
"message": _disk_message(disk_suffix, disk.percent, disk_free_gb, disk_total_gb) if disk_suffix else None,
|
|
77
88
|
},
|
|
78
89
|
"overall": _worst(ram_status, cpu_status, disk_status),
|
|
79
90
|
}
|
|
@@ -90,6 +90,7 @@ celerp/migrations/versions/bc0d1e2f3a4b_barcode_unique_index.py
|
|
|
90
90
|
celerp/migrations/versions/c1d2e3f4a5b6_add_marketplace.py
|
|
91
91
|
celerp/migrations/versions/c2d3e4f5a6b7_add_is_sync_to_shopify.py
|
|
92
92
|
celerp/migrations/versions/c4d5e6f7a8b9_account_cash_flow_category.py
|
|
93
|
+
celerp/migrations/versions/c9d8e7f6a5b4_seed_shrinkage_writeoff_account.py
|
|
93
94
|
celerp/migrations/versions/d0e1f2a3b4c5_add_share_token_expiry.py
|
|
94
95
|
celerp/migrations/versions/d2e3f4a5b6c7_add_password_reset_token.py
|
|
95
96
|
celerp/migrations/versions/d5e6f7a8b9c0_rename_fx_rounding_to_fx_difference.py
|
|
@@ -324,7 +325,9 @@ default_modules/celerp-docs/celerp_docs/taxes.py
|
|
|
324
325
|
default_modules/celerp-docs/celerp_docs/ui_routes.py
|
|
325
326
|
default_modules/celerp-docs/tests/conftest.py
|
|
326
327
|
default_modules/celerp-docs/tests/test_audits.py
|
|
328
|
+
default_modules/celerp-docs/tests/test_bulk_payment_alloc_lock.py
|
|
327
329
|
default_modules/celerp-docs/tests/test_consolidate_lots.py
|
|
330
|
+
default_modules/celerp-docs/tests/test_cross_lot_settlement.py
|
|
328
331
|
default_modules/celerp-docs/tests/test_freight_je.py
|
|
329
332
|
default_modules/celerp-docs/tests/test_freight_lines.py
|
|
330
333
|
default_modules/celerp-docs/tests/test_fulfill_no_split.py
|
|
@@ -336,10 +339,17 @@ default_modules/celerp-docs/tests/test_line_delete_persist.py
|
|
|
336
339
|
default_modules/celerp-docs/tests/test_line_identifier.py
|
|
337
340
|
default_modules/celerp-docs/tests/test_list_concurrency.py
|
|
338
341
|
default_modules/celerp-docs/tests/test_list_outcome_concurrency.py
|
|
342
|
+
default_modules/celerp-docs/tests/test_memo_close.py
|
|
343
|
+
default_modules/celerp-docs/tests/test_memo_close_projection.py
|
|
344
|
+
default_modules/celerp-docs/tests/test_memo_close_review_fixes.py
|
|
345
|
+
default_modules/celerp-docs/tests/test_memo_lifecycle_concurrency.py
|
|
346
|
+
default_modules/celerp-docs/tests/test_memo_line_labels.py
|
|
347
|
+
default_modules/celerp-docs/tests/test_memo_unfulfilled_filter.py
|
|
339
348
|
default_modules/celerp-docs/tests/test_payment_void_activity.py
|
|
340
349
|
default_modules/celerp-docs/tests/test_receive_sku_batch.py
|
|
341
350
|
default_modules/celerp-docs/tests/test_send_visibility.py
|
|
342
351
|
default_modules/celerp-docs/tests/test_service_lines.py
|
|
352
|
+
default_modules/celerp-docs/tests/test_sold_label_ordering.py
|
|
343
353
|
default_modules/celerp-docs/tests/test_void_guards.py
|
|
344
354
|
default_modules/celerp-docs/tests/test_writeoffs.py
|
|
345
355
|
default_modules/celerp-inventory/LICENSE
|