celerp 1.2.8__tar.gz → 1.3.1__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-1.2.8 → celerp-1.3.1}/CONTRIBUTING.md +39 -1
- {celerp-1.2.8 → celerp-1.3.1}/NOTICE +10 -0
- {celerp-1.2.8 → celerp-1.3.1}/PKG-INFO +11 -2
- {celerp-1.2.8 → celerp-1.3.1}/README.md +9 -1
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/tools.py +5 -4
- {celerp-1.2.8 → celerp-1.3.1}/celerp/cli.py +332 -61
- {celerp-1.2.8 → celerp-1.3.1}/celerp/config.py +7 -1
- celerp-1.3.1/celerp/embedded_pg.py +302 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/gateway/client.py +29 -1
- {celerp-1.2.8 → celerp-1.3.1}/celerp/main.py +7 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/notification.py +1 -1
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/field_schema.py +4 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/fulfill.py +2 -2
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/pick.py +51 -30
- celerp-1.3.1/celerp/services/reorder.py +279 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp.egg-info/PKG-INFO +11 -2
- {celerp-1.2.8 → celerp-1.3.1}/celerp.egg-info/SOURCES.txt +4 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp.egg-info/requires.txt +3 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp.egg-info/scm_file_list.json +15 -0
- celerp-1.3.1/celerp.egg-info/scm_version.json +8 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-dashboard/celerp_dashboard/routes.py +2 -1
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/__init__.py +1 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/routes.py +123 -10
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_audits.py +46 -0
- celerp-1.3.1/default_modules/celerp-docs/tests/test_receive_sku_batch.py +73 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/celerp_inventory/projections.py +87 -15
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/celerp_inventory/routes.py +153 -93
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/celerp_inventory/routes_scanning.py +45 -8
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/celerp_labels/ui_routes.py +36 -18
- {celerp-1.2.8 → celerp-1.3.1}/pyproject.toml +10 -1
- {celerp-1.2.8 → celerp-1.3.1}/ui/api_client.py +11 -2
- {celerp-1.2.8 → celerp-1.3.1}/ui/app.py +2 -1
- celerp-1.3.1/ui/components/attrs.py +28 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/components/files.py +4 -3
- {celerp-1.2.8 → celerp-1.3.1}/ui/components/shell.py +5 -3
- {celerp-1.2.8 → celerp-1.3.1}/ui/components/table.py +37 -5
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/en.json +4 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/auth.py +23 -45
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/contacts.py +6 -4
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/csv_import.py +1 -1
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/dashboard.py +10 -10
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/documents.py +243 -27
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/inventory.py +119 -59
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/reconciliation.py +2 -1
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings.py +2 -1
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings_connectors.py +18 -1
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings_inventory.py +82 -1
- celerp-1.2.8/celerp.egg-info/scm_version.json +0 -8
- {celerp-1.2.8 → celerp-1.3.1}/CLA.md +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/LICENSING.md +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/MANIFEST.in +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/alembic.ini +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/__main__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/batch.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/cleanup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/commands.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/conversations.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/files.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/intent.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/llm.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/memory.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/models.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/page_count.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/quota.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/ai/service.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/alembic.ini +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/alembic_config.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/compute/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/compute/aggregations.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/compute/valuation.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/base.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/daily_scheduler.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/http.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/images.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/quickbooks.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/registry.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/relay_token.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/shopify.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/sync_runner.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/upsert.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/util.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/webhooks.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/woocommerce.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/connectors/xero.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/constants.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/db.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/events/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/events/engine.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/events/schemas.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/events/types.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/gateway/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/gateway/state.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/importers/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/importers/importer.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/importers/schema.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/middleware.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/README.md +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/_auto_stamp.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/_data_reconcile.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/_json_compat.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/env.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/script.py.mako +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/a0b1c2d3e4f5_seed_landed_cost_clearing_accounts.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/a1b2c3d4e5f6_add_doc_share_tokens.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/b1c2d3e4f5a6_add_supporter_badges.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/b2c3d4e5f6a7_add_import_batches.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/c1d2e3f4a5b6_add_marketplace.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/c2d3e4f5a6b7_add_is_sync_to_shopify.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/d2e3f4a5b6c7_add_password_reset_token.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/e3f4a5b6c7d8_add_company_is_active.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/e4f5a6b7c8d9_backfill_connector_idempotency_key.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/f1a2b3c4d5e6_move_accounts_marketplace_to_modules.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/fd5de461e14e_initial_schema.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/g1h2i3j4k5l6_add_consignment_flag.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/h2i3j4k5l6m7_add_bank_accounts_and_reconciliation.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/j4k5l6m7n8o9_labels_db_persistence.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/k5l6m7n8o9p0_add_reconciliation_v2.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/l6m7n8o9p0q1_add_sync_runs_table.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/m7n8o9p0q1r2_add_connector_configs_and_outbound_queue.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/n8o9p0q1r2s3_backfill_payment_date.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/o9p0q1r2s3t4_backfill_item_price_fields.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/p1q2r3s4t5u6_add_session_registry_and_user_auth_state.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/q2r3s4t5u6v7_add_system_runtime_state.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/r3s4t5u6v7w8_add_projections_company_entity_type_index.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/s4t5u6v7w8x9_drop_user_company_id_role.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/t5u6v7w8x9y0_seed_inventory_sub_accounts.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/u6v7w8x9y0z1_backfill_item_prices_from_attributes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/v7w8x9y0z1a2_backfill_purchase_unit_defaults.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/w8x9y0z1a2b3_backfill_category_unit_defaults.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/x7y8z9a0b1c2_add_projection_created_at.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/y8z9a0b1c2d3_per_company_ledger_idempotency.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/migrations/versions/z9a0b1c2d3e4_work_centers.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/accounting.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/ai.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/auth.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/base.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/company.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/connector_config.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/import_batch.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/ledger.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/marketplace.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/projections.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/share.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/supporter.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/models/sync_run.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/modules/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/modules/api.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/modules/audit.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/modules/license.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/modules/loader.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/modules/references.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/modules/registry.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/modules/slots.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/notifications/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/notifications/service.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/notifications/sse.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/output/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/output/pdf.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/output/share_render.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/projections/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/projections/engine.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/projections/handlers/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/projections/handlers/marketplace.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/projections/handlers/scanning.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/projections/handlers/shopify.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/projections/handlers/system.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/auth.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/companies.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/debug.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/doctor.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/events.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/health.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/ledger.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/notifications.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/stars.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/routers/system.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/schemas/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/activity_redaction.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/attachments.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/auth.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/auto_je.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/backup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/backup_export.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/backup_import.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/backup_repo.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/backup_scheduler.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/backup_state.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/demo.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/dev_release_guard.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/email.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/je_keys.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/landed_cost.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/line_measures.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/list_behavior.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/money.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/runtime_state.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/session_tracker.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/star_cta.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/supporter_badge.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/system_health.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/services/units.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/session_gate.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp/tax_regimes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp.egg-info/dependency_links.txt +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp.egg-info/entry_points.txt +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/celerp.egg-info/top_level.txt +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/conftest.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/celerp_accounting/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/celerp_accounting/api_setup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/celerp_accounting/csv_parser.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/celerp_accounting/matcher.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/celerp_accounting/models.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/celerp_accounting/projections.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/celerp_accounting/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/celerp_accounting/ui_routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/tests/test_accounting_banking.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/tests/test_accounting_banking_routers.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/tests/test_accounting_gaps.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/tests/test_accounting_import_idempotency.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-accounting/tests/test_reconciliation_v2.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-admin/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-admin/celerp_admin/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-admin/celerp_admin/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-admin/celerp_admin/setup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/celerp_ai/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/celerp_ai/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/celerp_ai/setup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/celerp_ai/ui_routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/conftest.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_batch.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_cleanup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_conversations.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_coverage_gaps.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_intent.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_llm.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_memory.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_models.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_page_count.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_quota.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_router.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_routes_coverage.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_service.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-ai/tests/test_tools.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-backup/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-backup/celerp_backup/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-backup/celerp_backup/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-backup/celerp_backup/setup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/celerp_connectors/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/celerp_connectors/models.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/celerp_connectors/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/conftest.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_compliance.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_connector_correctness.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_connectors.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_images.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_outbound.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_quickbooks.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_rate_limiting.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_shopify.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_wiring.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_woocommerce.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_woocommerce_webhooks.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-connectors/tests/test_xero.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-contacts/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-contacts/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-contacts/celerp_contacts/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-contacts/celerp_contacts/migrations.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-contacts/celerp_contacts/projections.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-contacts/celerp_contacts/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-contacts/celerp_contacts/services.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-contacts/celerp_contacts/ui_routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-dashboard/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-dashboard/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-dashboard/celerp_dashboard/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-dashboard/celerp_dashboard/setup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/api_setup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/doc_constants.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/doc_projections.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/doc_service.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/models_share.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/routes_share.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/sequences.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/taxes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/celerp_docs/ui_routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/conftest.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_freight_je.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_freight_lines.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_fulfill_no_split.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_fulfillment_activity.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_inbound_je_lifecycle.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_inventory_account_reconciliation.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_landed_receive.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_line_delete_persist.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_payment_void_activity.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_send_visibility.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-docs/tests/test_service_lines.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/celerp_inventory/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/celerp_inventory/models_import_batch.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/celerp_inventory/routes_attachments.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/celerp_inventory/services.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/celerp_inventory/ui_routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/tests/test_item_recipe_projection.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/tests/test_item_workflow_projection.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-inventory/tests/test_landed_cost_projection.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/celerp_labels/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/celerp_labels/migrations/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/celerp_labels/migrations/labels_001_create_label_templates.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/celerp_labels/models.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/celerp_labels/presets.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/celerp_labels/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/celerp_labels/service.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/requirements.txt +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/tests/test_labels.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-labels/tests/test_labels_module.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/celerp_manufacturing/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/celerp_manufacturing/costing.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/celerp_manufacturing/expansion.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/celerp_manufacturing/labor.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/celerp_manufacturing/migrations.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/celerp_manufacturing/projection_handler.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/celerp_manufacturing/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/celerp_manufacturing/ui_routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/requirements.txt +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_bom_removed.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_build_api.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_item_recipe_api.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_item_workflow_api.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_labor_providers.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_manufacture_from_doc.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_manufacturing.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_manufacturing_import_idempotency.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_manufacturing_module.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_mfg_events.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_phase2_manufacturing_validations.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_production_order.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_recipe_costing.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_recipe_expansion.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_recost_api.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_to_make_allocation.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_where_used.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_work_centers_and_settings.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-manufacturing/tests/test_workflow_time.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-reports/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-reports/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-reports/celerp_reports/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-reports/celerp_reports/api_setup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-reports/celerp_reports/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-reports/celerp_reports/ui_routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-reports/tests/test_reports_full.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-reports/tests/test_reports_unit.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-subscriptions/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-subscriptions/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-subscriptions/celerp_subscriptions/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-subscriptions/celerp_subscriptions/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-subscriptions/celerp_subscriptions/ui_routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-subscriptions/tests/test_subscriptions.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-subscriptions/tests/test_subscriptions_ui.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/LICENSE +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/accessory_fashion.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/activewear.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/art_photography.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/audio_equipment.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/bag_handbag.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/banknote.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/beauty_tool.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/bed_bedroom.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/beer.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/beverage_nonalc.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/body_part_auto.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/book.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/bottoms.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/brake_suspension.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/bullion_coin.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/camera.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/colored_stone.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/comic.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/commercial_space.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/component_part.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/confectionery.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/consulting_service.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/decorative_art.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/diamond.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/drawing.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/dress_jumpsuit.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_auto.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_component.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/emerald.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/engine_part.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/fastener.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/fertilizer_chemical.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/film_video.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/fine_writing_instrument.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/fluid_lubricant.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/footwear.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/fragrance.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_food.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_produce.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/frozen_food.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/gaming_console.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/gold_bullion.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/grain_cereal.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/haircare.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/hand_tool.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/ingredient_bulk.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/interior_part.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/jewelry.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/kitchen_dining.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/laptop.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/lighting.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/livestock_feed.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/makeup.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/measuring_instrument.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/medal_token.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/mineral_specimen.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/mobile_phone.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/music_cd.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/music_vinyl.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/nail.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/numismatic_coin.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/outdoor_furniture.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/outerwear.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/packaged_food.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/painting.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/parking_bay.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/pearl.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/personal_care.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/pipe_plumbing.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/platinum_bullion.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/power_tool.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/print_edition.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/residential_unit.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/rough_gemstone.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/ruby.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/saas_plan.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/safety_ppe.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/sapphire.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/sculpture.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/seating.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/seeds.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/silver_bullion.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/skincare.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/soft_furnishing.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/software_addon.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/software_license.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/spirit.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/storage_furniture.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/swimwear.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/table_desk.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/tablet.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/tire_wheel.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/tops.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/trading_card.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/tv_display.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/video_game.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/watch.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/watch_strap.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/categories/wine.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/agricultural.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/artwork.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/automotive.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/blank.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/books_media.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/coins_precious_metals.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/consulting.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/cosmetics.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/electronics.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/fashion.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/food_beverage.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/furniture.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/gemstones.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/hardware.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/property_rental.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/saas.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/watches.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/presets/wine_spirits.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/celerp_verticals/ui_routes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/tests/test_verticals.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/default_modules/celerp-verticals/tests/test_verticals_routers.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/legal/OFFICIAL-COMPONENTS.md +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/legal/TRADEMARK.md +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/setup.cfg +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/test_helpers.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/components/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/components/activity.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/components/backup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/components/cloud_gate.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/components/currency.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/components/notes.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/components/phone.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/config.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/i18n.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/ar.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/de.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/es.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/fr.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/id.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/it.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/ja.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/pt.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/th.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/locales/vi.json +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/__init__.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/accounting.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/accounting_import.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/docs_import.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/events.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/lists_import.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/manufacturing.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/notifications.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/reports.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/search.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings_accounting.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings_cloud.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings_contacts.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings_general.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings_import.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings_manufacturing.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings_purchasing.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/settings_sales.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/setup.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/stars.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/subscriptions.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/routes/subscriptions_import.py +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/static/app.css +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/static/htmx.min.js +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/static/icon.png +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/static/logo.png +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/static/vendor/intl-tel-input/img/flags.webp +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/static/vendor/intl-tel-input/img/flags@2x.webp +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/static/vendor/intl-tel-input/intlTelInput.min.css +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/static/vendor/intl-tel-input/intlTelInput.min.js +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/static/vendor/intl-tel-input/intlTelInputWithUtils.min.js +0 -0
- {celerp-1.2.8 → celerp-1.3.1}/ui/static/vendor/intl-tel-input/utils.js +0 -0
|
@@ -58,9 +58,40 @@ celerp upgrade # pip install --upgrade celerp + migrate
|
|
|
58
58
|
| `--force` | off | Overwrite existing config |
|
|
59
59
|
| `--yes` / `-y` | off | Skip the `--force` wipe confirmation (non-interactive) |
|
|
60
60
|
| `--no-start` | off | Set up, then exit WITHOUT launching servers (service-managed/headless) |
|
|
61
|
+
| `--embedded` | off | Force the bundled PostgreSQL even if a server is reachable (cannot combine with `--db-url`) |
|
|
62
|
+
| `--no-embedded` | off | Never fall back to the bundled PostgreSQL; require an external server |
|
|
61
63
|
|
|
62
64
|
To change ports after init, edit `~/.config/celerp/config.toml` directly.
|
|
63
65
|
|
|
66
|
+
### External vs embedded PostgreSQL
|
|
67
|
+
|
|
68
|
+
`celerp init` picks the database automatically, and **an existing server always wins**:
|
|
69
|
+
|
|
70
|
+
1. `--db-url` given → that external server (no detection).
|
|
71
|
+
2. else a PostgreSQL server reachable on `localhost:5432` → use it (as root, init
|
|
72
|
+
provisions the role/database via `sudo -u postgres psql`; otherwise it prints the
|
|
73
|
+
`CREATE USER`/`CREATE DATABASE` to run).
|
|
74
|
+
3. else the **bundled** PostgreSQL 17 — a self-contained cluster under
|
|
75
|
+
`~/.config/celerp/pgdata`, started from binaries shipped in the
|
|
76
|
+
[`celerp-postgres`](https://github.com/celerp/celerp-postgres) wheel. No `sudo`, no
|
|
77
|
+
system service. Available on Linux x86_64/arm64 (glibc and musl/Alpine) and Windows
|
|
78
|
+
x64, any CPython; on macOS 26+ opt in with `pip install celerp-postgres`. Elsewhere
|
|
79
|
+
init asks you to install PostgreSQL.
|
|
80
|
+
|
|
81
|
+
Override the detection with `--embedded` / `--no-embedded`. The chosen mode is written to
|
|
82
|
+
`config.toml` as `[database] embedded = true|<absent>` and preserved across `--force`
|
|
83
|
+
re-inits, so an external install never silently switches to the bundled cluster.
|
|
84
|
+
|
|
85
|
+
**Moving bundled data to an external server** (e.g. outgrowing single-machine): dump from
|
|
86
|
+
the bundled cluster and restore into the target, using the bundled tools so versions match.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
BIN=$(celerp status >/dev/null; python -c "from celerp import embedded_pg; print(embedded_pg.bin_dir())")
|
|
90
|
+
"$BIN/pg_dump" "$(python -c "from celerp import embedded_pg,pathlib; from celerp.config import config_path; print(embedded_pg.ensure_cluster(config_path().parent).replace('+asyncpg',''))")" \
|
|
91
|
+
| psql "postgresql://celerp:celerp@newhost:5432/celerp"
|
|
92
|
+
celerp init --force --db-url "postgresql+asyncpg://celerp:celerp@newhost:5432/celerp"
|
|
93
|
+
```
|
|
94
|
+
|
|
64
95
|
### Run as a service (systemd)
|
|
65
96
|
|
|
66
97
|
`celerp init` launches the servers and blocks (good for the one-command desktop
|
|
@@ -68,16 +99,23 @@ flow). For a headless box where a process manager owns the lifecycle, set up wit
|
|
|
68
99
|
`--no-start` and let systemd run `celerp start`:
|
|
69
100
|
|
|
70
101
|
```bash
|
|
71
|
-
# First boot: provision DB + migrations + config, then
|
|
102
|
+
# First boot against a system PostgreSQL: provision DB + migrations + config, then
|
|
103
|
+
# exit (do not block). Run as root so init can create the role/database.
|
|
72
104
|
sudo celerp init --no-start \
|
|
73
105
|
--db-url "postgresql+asyncpg://celerp:<password>@localhost:5432/celerp" \
|
|
74
106
|
--api-port 8000 --ui-port 8080
|
|
75
107
|
```
|
|
76
108
|
|
|
109
|
+
Prefer the bundled database? Drop `--db-url` (and the `sudo` — the bundled cluster needs
|
|
110
|
+
neither) and run `celerp init --no-start` as the service user. The cluster then lives under
|
|
111
|
+
that user's `~/.config/celerp/pgdata`, and the systemd unit needs no `postgresql.service`
|
|
112
|
+
dependency.
|
|
113
|
+
|
|
77
114
|
```ini
|
|
78
115
|
# /etc/systemd/system/celerp.service
|
|
79
116
|
[Unit]
|
|
80
117
|
Description=Celerp
|
|
118
|
+
# Drop the postgresql.service dependency line when using the bundled database.
|
|
81
119
|
After=network.target postgresql.service
|
|
82
120
|
|
|
83
121
|
[Service]
|
|
@@ -24,4 +24,14 @@ see legal/TRADEMARK.md.
|
|
|
24
24
|
Third-party components included in packaged desktop builds are governed by their
|
|
25
25
|
own license files; see licenses/.
|
|
26
26
|
|
|
27
|
+
Bundled PostgreSQL (pip distribution): on supported platforms the pip package
|
|
28
|
+
declares a dependency on `celerp-postgres` (MIT), whose wheels embed PostgreSQL
|
|
29
|
+
server binaries and client tools so `celerp init` can run a self-contained
|
|
30
|
+
database with no separate install. PostgreSQL is distributed under the PostgreSQL
|
|
31
|
+
License (a permissive OSI-approved license); its full text and copyright notice
|
|
32
|
+
ship inside the celerp-postgres wheels, which repackage binaries built by the
|
|
33
|
+
theseus-rs/postgresql-binaries project. These binaries are used unmodified and
|
|
34
|
+
only when no external PostgreSQL server is configured. See
|
|
35
|
+
https://github.com/celerp/celerp-postgres.
|
|
36
|
+
|
|
27
37
|
For commercial, OEM, or white-label inquiries: https://celerp.com
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: celerp
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: Free, self-hosted ERP for small businesses
|
|
5
5
|
License: Business Source License 1.1
|
|
6
6
|
|
|
@@ -154,6 +154,7 @@ Requires-Dist: Pillow>=10.0
|
|
|
154
154
|
Requires-Dist: pypdf>=4.0
|
|
155
155
|
Requires-Dist: psycopg2-binary>=2.9
|
|
156
156
|
Requires-Dist: tzdata>=2024.1
|
|
157
|
+
Requires-Dist: celerp-postgres<18,>=17.10; (sys_platform == "linux" and (platform_machine == "x86_64" or platform_machine == "aarch64")) or (sys_platform == "win32" and platform_machine == "AMD64")
|
|
157
158
|
Provides-Extra: dev
|
|
158
159
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
159
160
|
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
@@ -220,6 +221,10 @@ celerp init # sets up the database and launches Celerp
|
|
|
220
221
|
Open **http://localhost:8080**. Done.
|
|
221
222
|
Your office can securely access the system at your IP address :8080.
|
|
222
223
|
|
|
224
|
+
No PostgreSQL to install: `celerp init` uses your existing PostgreSQL server if one is
|
|
225
|
+
running, and otherwise starts a self-contained bundled database — no `sudo`, no system
|
|
226
|
+
service. Point it at a specific server with `celerp init --db-url postgresql+asyncpg://…`.
|
|
227
|
+
|
|
223
228
|
Running headless or under a process manager? Use `celerp init --no-start` to set up
|
|
224
229
|
without launching, then have your service run `celerp start` — see
|
|
225
230
|
[Run as a service (systemd)](CONTRIBUTING.md#run-as-a-service-systemd).
|
|
@@ -288,9 +293,13 @@ git clone git@github.com:celerp/celerp.git
|
|
|
288
293
|
cd celerp
|
|
289
294
|
python3 -m venv .venv && source .venv/bin/activate
|
|
290
295
|
pip install -e ".[dev]"
|
|
291
|
-
|
|
296
|
+
celerp init # creates DB, runs migrations, starts servers
|
|
292
297
|
```
|
|
293
298
|
|
|
299
|
+
`celerp init` boots a bundled PostgreSQL when no server is running, so no `sudo` and no
|
|
300
|
+
system Postgres are required. To develop against your own server instead, pass
|
|
301
|
+
`--db-url postgresql+asyncpg://…`.
|
|
302
|
+
|
|
294
303
|
Open **http://localhost:8080**. Run tests with `pytest tests/`.
|
|
295
304
|
|
|
296
305
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for environment variables, troubleshooting, and coding guidelines.
|
|
@@ -49,6 +49,10 @@ celerp init # sets up the database and launches Celerp
|
|
|
49
49
|
Open **http://localhost:8080**. Done.
|
|
50
50
|
Your office can securely access the system at your IP address :8080.
|
|
51
51
|
|
|
52
|
+
No PostgreSQL to install: `celerp init` uses your existing PostgreSQL server if one is
|
|
53
|
+
running, and otherwise starts a self-contained bundled database — no `sudo`, no system
|
|
54
|
+
service. Point it at a specific server with `celerp init --db-url postgresql+asyncpg://…`.
|
|
55
|
+
|
|
52
56
|
Running headless or under a process manager? Use `celerp init --no-start` to set up
|
|
53
57
|
without launching, then have your service run `celerp start` — see
|
|
54
58
|
[Run as a service (systemd)](CONTRIBUTING.md#run-as-a-service-systemd).
|
|
@@ -117,9 +121,13 @@ git clone git@github.com:celerp/celerp.git
|
|
|
117
121
|
cd celerp
|
|
118
122
|
python3 -m venv .venv && source .venv/bin/activate
|
|
119
123
|
pip install -e ".[dev]"
|
|
120
|
-
|
|
124
|
+
celerp init # creates DB, runs migrations, starts servers
|
|
121
125
|
```
|
|
122
126
|
|
|
127
|
+
`celerp init` boots a bundled PostgreSQL when no server is running, so no `sudo` and no
|
|
128
|
+
system Postgres are required. To develop against your own server instead, pass
|
|
129
|
+
`--db-url postgresql+asyncpg://…`.
|
|
130
|
+
|
|
123
131
|
Open **http://localhost:8080**. Run tests with `pytest tests/`.
|
|
124
132
|
|
|
125
133
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for environment variables, troubleshooting, and coding guidelines.
|
|
@@ -22,6 +22,7 @@ from sqlalchemy import select
|
|
|
22
22
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
23
23
|
|
|
24
24
|
from celerp.models.projections import Projection
|
|
25
|
+
from celerp.services.reorder import is_below_reorder
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
@dataclass
|
|
@@ -61,7 +62,7 @@ async def _dashboard_kpis(session: AsyncSession, company_id: uuid.UUID, **_) ->
|
|
|
61
62
|
return {
|
|
62
63
|
"total_items": len(items),
|
|
63
64
|
"inventory_value": round(sum(float(i.state.get("total_cost", 0) or 0) for i in items), 2),
|
|
64
|
-
"low_stock_items": sum(1 for i in items if
|
|
65
|
+
"low_stock_items": sum(1 for i in items if is_below_reorder(i.state)),
|
|
65
66
|
"ar_outstanding": round(
|
|
66
67
|
sum(
|
|
67
68
|
float(d.state.get("amount_outstanding", 0) or 0)
|
|
@@ -75,12 +76,12 @@ async def _dashboard_kpis(session: AsyncSession, company_id: uuid.UUID, **_) ->
|
|
|
75
76
|
async def _low_stock_items(
|
|
76
77
|
session: AsyncSession, company_id: uuid.UUID, limit: int = 20, **_,
|
|
77
78
|
) -> dict:
|
|
78
|
-
"""List items
|
|
79
|
+
"""List items at or below their reorder point."""
|
|
79
80
|
items = await _projections(session, company_id, "item")
|
|
80
81
|
low = sorted(
|
|
81
82
|
[
|
|
82
83
|
{"sku": r.state.get("sku"), "name": r.state.get("name"), "quantity": r.state.get("quantity", 0)}
|
|
83
|
-
for r in items if
|
|
84
|
+
for r in items if is_below_reorder(r.state)
|
|
84
85
|
],
|
|
85
86
|
key=lambda x: float(x["quantity"] or 0),
|
|
86
87
|
)
|
|
@@ -263,7 +264,7 @@ TOOLS: dict[str, ToolDef] = {
|
|
|
263
264
|
t.name: t
|
|
264
265
|
for t in [
|
|
265
266
|
ToolDef("dashboard_kpis", "Return high-level KPIs: inventory value, AR outstanding, low stock count, active deals.", [], _dashboard_kpis),
|
|
266
|
-
ToolDef("low_stock_items", "List items
|
|
267
|
+
ToolDef("low_stock_items", "List items at or below their reorder point (defaults to zero/negative quantity for items without a reorder point set). Param: limit (default 20).", ["limit"], _low_stock_items),
|
|
267
268
|
ToolDef("outstanding_invoices", "List unpaid invoices. Param: limit (default 20).", ["limit"], _outstanding_invoices),
|
|
268
269
|
ToolDef("top_items_by_value", "List items ranked by total inventory value. Param: limit (default 10).", ["limit"], _top_items_by_value),
|
|
269
270
|
ToolDef("active_deals_summary", "Summarise the CRM pipeline - open deals by stage with count and total value.", [], _active_deals_summary),
|
|
@@ -273,6 +273,176 @@ def _test_db(db_url: str) -> str | None:
|
|
|
273
273
|
return str(e)
|
|
274
274
|
|
|
275
275
|
|
|
276
|
+
# ── Database mode resolution (external vs embedded) ────────────────────────────
|
|
277
|
+
#
|
|
278
|
+
# `celerp init` supports two ways to reach Postgres:
|
|
279
|
+
# external — a PostgreSQL server the user (or the droplet/apt) already runs.
|
|
280
|
+
# embedded — a self-contained cluster we boot from bundled binaries when the
|
|
281
|
+
# user has no server. See celerp.embedded_pg.
|
|
282
|
+
# The rule is "an existing server always wins": embedded is only a fallback so
|
|
283
|
+
# a machine with a real Postgres never ends up with two postmasters.
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def _is_root() -> bool:
|
|
287
|
+
"""True only where we can `sudo -u postgres` to provision (POSIX, uid 0).
|
|
288
|
+
|
|
289
|
+
Guarded with hasattr because os.getuid() does not exist on Windows — the old
|
|
290
|
+
unguarded call raised AttributeError instead of showing guidance there.
|
|
291
|
+
"""
|
|
292
|
+
return hasattr(os, "getuid") and os.getuid() == 0
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def _classify_probe(err: str | None) -> str:
|
|
296
|
+
"""Map a connection attempt's outcome to server reachability.
|
|
297
|
+
|
|
298
|
+
Returns:
|
|
299
|
+
"ok" — connected; server up and the target DB exists.
|
|
300
|
+
"needs_provision" — server is up but the role/database is missing or auth
|
|
301
|
+
failed; external provisioning (root) can fix it.
|
|
302
|
+
"unreachable" — nothing is listening (connection refused / timeout).
|
|
303
|
+
|
|
304
|
+
"needs_provision" still means a server EXISTS, so init stays in external
|
|
305
|
+
mode rather than booting an embedded cluster beside it.
|
|
306
|
+
"""
|
|
307
|
+
if err is None:
|
|
308
|
+
return "ok"
|
|
309
|
+
low = err.lower()
|
|
310
|
+
# Server answered, but the role/db isn't set up yet, or auth was rejected.
|
|
311
|
+
if (
|
|
312
|
+
"does not exist" in low
|
|
313
|
+
or "authentication failed" in low
|
|
314
|
+
or "no password supplied" in low
|
|
315
|
+
or "role" in low and "does not exist" in low
|
|
316
|
+
):
|
|
317
|
+
return "needs_provision"
|
|
318
|
+
# Nothing accepted the connection.
|
|
319
|
+
return "unreachable"
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _resolve_db_mode(
|
|
323
|
+
*,
|
|
324
|
+
db_url: str | None,
|
|
325
|
+
server_reachable: bool | None,
|
|
326
|
+
provider_available: bool,
|
|
327
|
+
want_embedded: bool,
|
|
328
|
+
no_embedded: bool,
|
|
329
|
+
existing_embedded: bool | None = None,
|
|
330
|
+
) -> tuple[str, str | None]:
|
|
331
|
+
"""Pure decision function for `celerp init`'s database mode.
|
|
332
|
+
|
|
333
|
+
Returns (mode, error_kind) where mode is "external" | "embedded" | "error".
|
|
334
|
+
Kept side-effect-free so the whole branch table can be unit-tested without a
|
|
335
|
+
database.
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
db_url: explicit --db-url; taken at face value (external), never probed.
|
|
339
|
+
server_reachable: result of probing the default host; None when not probed.
|
|
340
|
+
provider_available: whether the embedded backend can run here.
|
|
341
|
+
want_embedded/no_embedded: the --embedded / --no-embedded overrides.
|
|
342
|
+
existing_embedded: the mode of an already-initialized instance (True/False),
|
|
343
|
+
or None for a fresh install. On `--force` this PRESERVES the instance's
|
|
344
|
+
mode so re-initializing an external install (e.g. a droplet) never flips
|
|
345
|
+
to embedded just because its server was momentarily unreachable.
|
|
346
|
+
|
|
347
|
+
Precedence: conflicting-flags → db_url → --embedded → --no-embedded →
|
|
348
|
+
existing config's mode → probe.
|
|
349
|
+
"""
|
|
350
|
+
if want_embedded and no_embedded:
|
|
351
|
+
return ("error", "conflicting_flags")
|
|
352
|
+
if db_url and want_embedded:
|
|
353
|
+
# An explicit external URL and "force embedded" are contradictory.
|
|
354
|
+
return ("error", "db_url_with_embedded")
|
|
355
|
+
if db_url:
|
|
356
|
+
return ("external", None)
|
|
357
|
+
if want_embedded:
|
|
358
|
+
return ("embedded", None) if provider_available else ("error", "no_provider")
|
|
359
|
+
if no_embedded:
|
|
360
|
+
# User requires external. Reachable → use it; otherwise fail with external
|
|
361
|
+
# guidance rather than silently starting a cluster.
|
|
362
|
+
return ("external", None) if server_reachable else ("error", "no_server_external_only")
|
|
363
|
+
if existing_embedded is True:
|
|
364
|
+
return ("embedded", None) if provider_available else ("error", "no_provider")
|
|
365
|
+
if existing_embedded is False:
|
|
366
|
+
return ("external", None)
|
|
367
|
+
# Fresh install, no overrides: an existing server always wins.
|
|
368
|
+
if server_reachable:
|
|
369
|
+
return ("external", None)
|
|
370
|
+
if provider_available:
|
|
371
|
+
return ("embedded", None)
|
|
372
|
+
return ("error", "no_server_no_provider")
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _emit_db_error(kind: str, db_url: str) -> None:
|
|
376
|
+
"""Print actionable guidance for a resolve/connect failure (stderr)."""
|
|
377
|
+
if kind == "conflicting_flags":
|
|
378
|
+
click.echo(" ✗ --embedded and --no-embedded are mutually exclusive.", err=True)
|
|
379
|
+
return
|
|
380
|
+
if kind == "db_url_with_embedded":
|
|
381
|
+
click.echo(
|
|
382
|
+
" ✗ --embedded cannot be combined with --db-url (which selects an "
|
|
383
|
+
"external server).",
|
|
384
|
+
err=True,
|
|
385
|
+
)
|
|
386
|
+
return
|
|
387
|
+
if kind == "no_provider":
|
|
388
|
+
click.echo(
|
|
389
|
+
f" ✗ Embedded PostgreSQL is not available on this platform ({sys.platform}).",
|
|
390
|
+
err=True,
|
|
391
|
+
)
|
|
392
|
+
click.echo(
|
|
393
|
+
"\nInstall PostgreSQL and re-run, or use a supported platform "
|
|
394
|
+
"(Linux x86_64/arm64 — glibc or musl — or Windows x64).",
|
|
395
|
+
err=True,
|
|
396
|
+
)
|
|
397
|
+
if sys.platform == "darwin":
|
|
398
|
+
click.echo(
|
|
399
|
+
"On macOS 26 or newer: pip install celerp-postgres — then re-run "
|
|
400
|
+
"`celerp init` for the bundled database.",
|
|
401
|
+
err=True,
|
|
402
|
+
)
|
|
403
|
+
return
|
|
404
|
+
# no_server_external_only / no_server_no_provider: nothing was listening.
|
|
405
|
+
click.echo(f" ✗ No PostgreSQL server found at {db_url}.", err=True)
|
|
406
|
+
if kind == "no_server_external_only":
|
|
407
|
+
click.echo(
|
|
408
|
+
"\n--no-embedded was set, so no cluster was started. Install and start "
|
|
409
|
+
"PostgreSQL, then re-run `celerp init`.",
|
|
410
|
+
err=True,
|
|
411
|
+
)
|
|
412
|
+
return
|
|
413
|
+
# no_server_no_provider — embedded unavailable AND no server.
|
|
414
|
+
click.echo(
|
|
415
|
+
"\nInstall PostgreSQL and start it, then re-run `celerp init` — or use a "
|
|
416
|
+
"supported platform (Linux x86_64/arm64 — glibc or musl — or Windows x64) "
|
|
417
|
+
"to get the bundled database automatically.",
|
|
418
|
+
err=True,
|
|
419
|
+
)
|
|
420
|
+
if sys.platform.startswith("linux"):
|
|
421
|
+
click.echo(" e.g. sudo apt install postgresql && sudo service postgresql start", err=True)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def ensure_database(cfg: dict) -> None:
|
|
425
|
+
"""Boot the embedded cluster for a DB-touching command, if this install uses
|
|
426
|
+
one, and refresh the connection URI in `cfg` in place.
|
|
427
|
+
|
|
428
|
+
No-op for external mode (never imports the embedded provider, so external
|
|
429
|
+
installs — including every droplet — are unaffected). Idempotent: safe to
|
|
430
|
+
call from every command that reads cfg["database"]["url"].
|
|
431
|
+
"""
|
|
432
|
+
db = cfg.get("database", {})
|
|
433
|
+
if not db.get("embedded"):
|
|
434
|
+
return
|
|
435
|
+
from celerp import embedded_pg
|
|
436
|
+
|
|
437
|
+
config_dir = _config_path().parent
|
|
438
|
+
# Re-derive the URI on every boot rather than trusting the stored one: the
|
|
439
|
+
# unix-socket path lives under a runtime dir that a reboot can relocate.
|
|
440
|
+
db["url"] = embedded_pg.ensure_cluster(config_dir)
|
|
441
|
+
bd = embedded_pg.bin_dir()
|
|
442
|
+
if bd:
|
|
443
|
+
cfg.setdefault("backup", {}).setdefault("pg_bin_dir", bd)
|
|
444
|
+
|
|
445
|
+
|
|
276
446
|
def _run_upgrade_with_auto_stamp(alembic_cfg, engine_url: str) -> None:
|
|
277
447
|
"""Run alembic upgrade head, auto-stamping past any already-applied revisions.
|
|
278
448
|
|
|
@@ -464,6 +634,103 @@ def _reconcile_after_migrate(db_url: str) -> None:
|
|
|
464
634
|
engine.dispose()
|
|
465
635
|
|
|
466
636
|
|
|
637
|
+
def _wipe_attachment_dirs(purge_dirs: list) -> None:
|
|
638
|
+
"""Remove attached-file directories on --force so a re-init is truly fresh."""
|
|
639
|
+
import shutil
|
|
640
|
+
for _d in purge_dirs:
|
|
641
|
+
if _d.exists():
|
|
642
|
+
shutil.rmtree(_d, ignore_errors=True)
|
|
643
|
+
click.echo(f" ✓ Removed {_d.resolve()}")
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
def _init_embedded(cfg: dict, config_dir: "Path", *, force: bool, purge_dirs: list) -> None:
|
|
647
|
+
"""Provision the bundled PostgreSQL cluster and point cfg at it.
|
|
648
|
+
|
|
649
|
+
No sudo, no ownership/grant dance: the app connects as the cluster superuser
|
|
650
|
+
over a unix socket, so it owns every object it creates.
|
|
651
|
+
"""
|
|
652
|
+
from celerp import embedded_pg
|
|
653
|
+
|
|
654
|
+
if force:
|
|
655
|
+
click.echo("Wiping embedded database for fresh init...")
|
|
656
|
+
embedded_pg.wipe(config_dir)
|
|
657
|
+
_wipe_attachment_dirs(purge_dirs)
|
|
658
|
+
click.echo(" ✓ Database ready (fresh)")
|
|
659
|
+
|
|
660
|
+
click.echo("Starting embedded PostgreSQL...")
|
|
661
|
+
uri = embedded_pg.ensure_cluster(config_dir)
|
|
662
|
+
cfg["database"]["url"] = uri
|
|
663
|
+
cfg["database"]["embedded"] = True
|
|
664
|
+
bd = embedded_pg.bin_dir()
|
|
665
|
+
if bd:
|
|
666
|
+
cfg.setdefault("backup", {})["pg_bin_dir"] = bd
|
|
667
|
+
click.echo(f" ✓ Using embedded PostgreSQL at {embedded_pg.pgdata_dir(config_dir)}")
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
def _init_external(cfg: dict, *, force: bool, db_url: str | None, purge_dirs: list) -> None:
|
|
671
|
+
"""Connect to (and, as root, provision) an external PostgreSQL server.
|
|
672
|
+
|
|
673
|
+
This is the pre-existing path, preserved verbatim for the droplet/self-hosted
|
|
674
|
+
contract: explicit --db-url, root auto-provisioning via `sudo -u postgres`,
|
|
675
|
+
and the same connect-or-guidance flow for non-root.
|
|
676
|
+
"""
|
|
677
|
+
if force:
|
|
678
|
+
click.echo("Wiping database for fresh init...")
|
|
679
|
+
db_url_for_wipe = db_url or _DEFAULT_DB_URL
|
|
680
|
+
try:
|
|
681
|
+
_provision_db(db_url_for_wipe, drop_existing=True)
|
|
682
|
+
except RuntimeError as e:
|
|
683
|
+
click.echo(f" ✗ DB wipe failed: {e}", err=True)
|
|
684
|
+
click.echo("\nEnsure PostgreSQL is running and you have sudo access.", err=True)
|
|
685
|
+
sys.exit(1)
|
|
686
|
+
click.echo(" ✓ Database ready (fresh)")
|
|
687
|
+
_wipe_attachment_dirs(purge_dirs)
|
|
688
|
+
return
|
|
689
|
+
|
|
690
|
+
click.echo("Connecting to database...")
|
|
691
|
+
err = _test_db(cfg["database"]["url"])
|
|
692
|
+
if not err:
|
|
693
|
+
click.echo(" ✓ Database connection OK")
|
|
694
|
+
return
|
|
695
|
+
if _is_root():
|
|
696
|
+
click.echo(" · Could not connect — attempting to provision database...")
|
|
697
|
+
try:
|
|
698
|
+
_provision_db(cfg["database"]["url"])
|
|
699
|
+
except RuntimeError as e:
|
|
700
|
+
click.echo(f" ✗ Provisioning failed: {e}", err=True)
|
|
701
|
+
click.echo("\nEnsure PostgreSQL is installed and running, then retry with sudo.", err=True)
|
|
702
|
+
sys.exit(1)
|
|
703
|
+
err = _test_db(cfg["database"]["url"])
|
|
704
|
+
if err:
|
|
705
|
+
click.echo(f" ✗ Still could not connect after provisioning: {err}", err=True)
|
|
706
|
+
sys.exit(1)
|
|
707
|
+
click.echo(" ✓ Database connection OK")
|
|
708
|
+
return
|
|
709
|
+
# Non-root and the server rejected us. On POSIX, sudo can provision; on
|
|
710
|
+
# Windows there is no `sudo -u postgres`, so only suggest it where it works.
|
|
711
|
+
click.echo(f" ✗ Could not connect: {err}", err=True)
|
|
712
|
+
import shutil
|
|
713
|
+
real_bin = shutil.which("celerp") or "celerp"
|
|
714
|
+
if hasattr(os, "getuid"):
|
|
715
|
+
click.echo(
|
|
716
|
+
f"\nRe-run with sudo to have Celerp create the database automatically:\n"
|
|
717
|
+
f" sudo {real_bin} init\n"
|
|
718
|
+
"\nOr create it manually:\n"
|
|
719
|
+
" sudo -u postgres psql -c \"CREATE USER celerp WITH PASSWORD 'celerp';\"\n"
|
|
720
|
+
" sudo -u postgres psql -c \"CREATE DATABASE celerp OWNER celerp;\"",
|
|
721
|
+
err=True,
|
|
722
|
+
)
|
|
723
|
+
else:
|
|
724
|
+
click.echo(
|
|
725
|
+
"\nCreate the database and role on your PostgreSQL server, then re-run "
|
|
726
|
+
"`celerp init --db-url ...`:\n"
|
|
727
|
+
" CREATE USER celerp WITH PASSWORD 'celerp';\n"
|
|
728
|
+
" CREATE DATABASE celerp OWNER celerp;",
|
|
729
|
+
err=True,
|
|
730
|
+
)
|
|
731
|
+
sys.exit(1)
|
|
732
|
+
|
|
733
|
+
|
|
467
734
|
# ── Commands ──────────────────────────────────────────────────────────────────
|
|
468
735
|
|
|
469
736
|
@click.group()
|
|
@@ -484,8 +751,23 @@ def main() -> None:
|
|
|
484
751
|
"WITHOUT launching the servers. For service-managed/headless installs "
|
|
485
752
|
"where a process manager (e.g. systemd) runs `celerp start`.",
|
|
486
753
|
)
|
|
487
|
-
|
|
488
|
-
""
|
|
754
|
+
@click.option(
|
|
755
|
+
"--embedded", "want_embedded", is_flag=True,
|
|
756
|
+
help="Force the bundled PostgreSQL even if a server is reachable. "
|
|
757
|
+
"Cannot be combined with --db-url.",
|
|
758
|
+
)
|
|
759
|
+
@click.option(
|
|
760
|
+
"--no-embedded", "no_embedded", is_flag=True,
|
|
761
|
+
help="Never fall back to the bundled PostgreSQL; require an external server.",
|
|
762
|
+
)
|
|
763
|
+
def init(db_url, api_port, ui_port, cloud_token, force, assume_yes, no_start, want_embedded, no_embedded):
|
|
764
|
+
"""Initialize Celerp: write config and run database migrations.
|
|
765
|
+
|
|
766
|
+
With no --db-url, init uses an existing PostgreSQL server if one is running,
|
|
767
|
+
and otherwise boots a self-contained bundled cluster (no sudo, no system
|
|
768
|
+
service). An existing server always wins; pass --embedded / --no-embedded to
|
|
769
|
+
override the auto-detection.
|
|
770
|
+
"""
|
|
489
771
|
config_path = _config_path()
|
|
490
772
|
|
|
491
773
|
if config_path.exists() and not force:
|
|
@@ -493,16 +775,49 @@ def init(db_url, api_port, ui_port, cloud_token, force, assume_yes, no_start):
|
|
|
493
775
|
click.echo("Run `celerp migrate` to apply updates, or `celerp init --force` to reconfigure.")
|
|
494
776
|
return
|
|
495
777
|
|
|
778
|
+
from celerp import embedded_pg
|
|
779
|
+
|
|
780
|
+
# ── Resolve external vs embedded ──────────────────────────────────────────
|
|
781
|
+
# On --force, config_path exists: preserve the initialized instance's mode so
|
|
782
|
+
# re-init never flips an external install (e.g. a droplet) to embedded.
|
|
783
|
+
existing_cfg = _read_config() if config_path.exists() else {}
|
|
784
|
+
existing_embedded = (
|
|
785
|
+
bool(existing_cfg.get("database", {}).get("embedded")) if existing_cfg else None
|
|
786
|
+
)
|
|
787
|
+
provider_available = embedded_pg.is_available()
|
|
788
|
+
# Probe the default host only when nothing else determines the mode — an
|
|
789
|
+
# explicit --db-url/--embedded, or a known existing mode, needs no probe.
|
|
790
|
+
server_reachable: bool | None = None
|
|
791
|
+
need_probe = not db_url and not want_embedded and (no_embedded or existing_embedded is None)
|
|
792
|
+
if need_probe:
|
|
793
|
+
server_reachable = _classify_probe(_test_db(_DEFAULT_DB_URL)) in ("ok", "needs_provision")
|
|
794
|
+
mode, error_kind = _resolve_db_mode(
|
|
795
|
+
db_url=db_url,
|
|
796
|
+
server_reachable=server_reachable,
|
|
797
|
+
provider_available=provider_available,
|
|
798
|
+
want_embedded=want_embedded,
|
|
799
|
+
no_embedded=no_embedded,
|
|
800
|
+
existing_embedded=existing_embedded,
|
|
801
|
+
)
|
|
802
|
+
if mode == "error":
|
|
803
|
+
_emit_db_error(error_kind, db_url or _DEFAULT_DB_URL)
|
|
804
|
+
sys.exit(1)
|
|
805
|
+
|
|
806
|
+
config_dir = config_path.parent
|
|
807
|
+
|
|
496
808
|
if force:
|
|
497
|
-
# --force is destructive: it
|
|
498
|
-
# init can run under sudo, so warn (with full paths) and confirm
|
|
809
|
+
# --force is destructive: it wipes the database AND attached files.
|
|
810
|
+
# init can run under sudo, so warn (with full paths) and confirm first.
|
|
499
811
|
from celerp.config import settings
|
|
500
812
|
_purge_dirs = [
|
|
501
813
|
settings.data_dir / "static" / "attachments",
|
|
502
814
|
settings.data_dir / "ai_uploads",
|
|
503
815
|
]
|
|
504
816
|
click.echo("⚠ `init --force` permanently WIPES this instance:")
|
|
505
|
-
|
|
817
|
+
if mode == "embedded":
|
|
818
|
+
click.echo(f" - database: embedded cluster at {embedded_pg.pgdata_dir(config_dir)}")
|
|
819
|
+
else:
|
|
820
|
+
click.echo(f" - database: {db_url or _DEFAULT_DB_URL}")
|
|
506
821
|
for _d in _purge_dirs:
|
|
507
822
|
click.echo(f" - files: {_d.resolve()}")
|
|
508
823
|
click.echo(" Make sure you have a backup.")
|
|
@@ -523,62 +838,10 @@ def init(db_url, api_port, ui_port, cloud_token, force, assume_yes, no_start):
|
|
|
523
838
|
"modules": {"enabled": enabled_modules},
|
|
524
839
|
}
|
|
525
840
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
click.echo("Wiping database for fresh init...")
|
|
529
|
-
db_url_for_wipe = db_url or _DEFAULT_DB_URL
|
|
530
|
-
try:
|
|
531
|
-
_provision_db(db_url_for_wipe, drop_existing=True)
|
|
532
|
-
except RuntimeError as e:
|
|
533
|
-
click.echo(f" ✗ DB wipe failed: {e}", err=True)
|
|
534
|
-
click.echo(
|
|
535
|
-
"\nEnsure PostgreSQL is running and you have sudo access.",
|
|
536
|
-
err=True,
|
|
537
|
-
)
|
|
538
|
-
sys.exit(1)
|
|
539
|
-
click.echo(" ✓ Database ready (fresh)")
|
|
540
|
-
# Wipe attached files too, so a forced re-init is a truly fresh instance and no
|
|
541
|
-
# orphaned files remain. Recreated automatically on next boot.
|
|
542
|
-
import shutil
|
|
543
|
-
for _d in _purge_dirs:
|
|
544
|
-
if _d.exists():
|
|
545
|
-
shutil.rmtree(_d, ignore_errors=True)
|
|
546
|
-
click.echo(f" ✓ Removed {_d.resolve()}")
|
|
841
|
+
if mode == "embedded":
|
|
842
|
+
_init_embedded(cfg, config_dir, force=force, purge_dirs=_purge_dirs if force else [])
|
|
547
843
|
else:
|
|
548
|
-
|
|
549
|
-
click.echo("Connecting to database...")
|
|
550
|
-
err = _test_db(cfg["database"]["url"])
|
|
551
|
-
if err:
|
|
552
|
-
if os.getuid() == 0:
|
|
553
|
-
click.echo(" · Could not connect — attempting to provision database...")
|
|
554
|
-
try:
|
|
555
|
-
_provision_db(cfg["database"]["url"])
|
|
556
|
-
except RuntimeError as e:
|
|
557
|
-
click.echo(f" ✗ Provisioning failed: {e}", err=True)
|
|
558
|
-
click.echo(
|
|
559
|
-
"\nEnsure PostgreSQL is installed and running, then retry with sudo.",
|
|
560
|
-
err=True,
|
|
561
|
-
)
|
|
562
|
-
sys.exit(1)
|
|
563
|
-
# Verify connection now works
|
|
564
|
-
err = _test_db(cfg["database"]["url"])
|
|
565
|
-
if err:
|
|
566
|
-
click.echo(f" ✗ Still could not connect after provisioning: {err}", err=True)
|
|
567
|
-
sys.exit(1)
|
|
568
|
-
else:
|
|
569
|
-
click.echo(f" ✗ Could not connect: {err}", err=True)
|
|
570
|
-
import shutil
|
|
571
|
-
real_bin = shutil.which("celerp") or "celerp"
|
|
572
|
-
click.echo(
|
|
573
|
-
f"\nRe-run with sudo to have Celerp create the database automatically:\n"
|
|
574
|
-
f" sudo {real_bin} init\n"
|
|
575
|
-
"\nOr create it manually:\n"
|
|
576
|
-
" sudo -u postgres psql -c \"CREATE USER celerp WITH PASSWORD 'celerp';\"\n"
|
|
577
|
-
" sudo -u postgres psql -c \"CREATE DATABASE celerp OWNER celerp;\"",
|
|
578
|
-
err=True,
|
|
579
|
-
)
|
|
580
|
-
sys.exit(1)
|
|
581
|
-
click.echo(" ✓ Database connection OK")
|
|
844
|
+
_init_external(cfg, force=force, db_url=db_url, purge_dirs=_purge_dirs if force else [])
|
|
582
845
|
|
|
583
846
|
# Fix table ownership before migrations (covers tables created by postgres superuser)
|
|
584
847
|
db_url_val = cfg["database"]["url"]
|
|
@@ -720,6 +983,7 @@ def reset_password(email: str, password: str) -> None:
|
|
|
720
983
|
if not cfg:
|
|
721
984
|
click.echo("Not initialized. Run `celerp init` first.", err=True)
|
|
722
985
|
sys.exit(1)
|
|
986
|
+
ensure_database(cfg)
|
|
723
987
|
db_url = cfg["database"]["url"]
|
|
724
988
|
sync_url = db_url.replace("postgresql+asyncpg://", "postgresql://")
|
|
725
989
|
try:
|
|
@@ -748,6 +1012,7 @@ def start():
|
|
|
748
1012
|
if not cfg:
|
|
749
1013
|
click.echo("Not initialized. Run `celerp init` first.", err=True)
|
|
750
1014
|
sys.exit(1)
|
|
1015
|
+
ensure_database(cfg)
|
|
751
1016
|
_start(cfg)
|
|
752
1017
|
|
|
753
1018
|
|
|
@@ -761,6 +1026,7 @@ def migrate(db_url):
|
|
|
761
1026
|
if not cfg:
|
|
762
1027
|
click.echo("Not initialized. Run `celerp init` first.", err=True)
|
|
763
1028
|
sys.exit(1)
|
|
1029
|
+
ensure_database(cfg)
|
|
764
1030
|
url = cfg["database"]["url"]
|
|
765
1031
|
click.echo("Running migrations...")
|
|
766
1032
|
_run_migrations(url)
|
|
@@ -780,11 +1046,14 @@ def status():
|
|
|
780
1046
|
click.echo("Run `celerp init` to initialize.")
|
|
781
1047
|
return
|
|
782
1048
|
|
|
1049
|
+
is_embedded = cfg.get("database", {}).get("embedded")
|
|
1050
|
+
ensure_database(cfg)
|
|
783
1051
|
db_url = cfg["database"]["url"]
|
|
784
1052
|
# Mask password in display
|
|
785
1053
|
import re
|
|
786
1054
|
display_url = re.sub(r"://([^:]+):([^@]+)@", r"://\1:***@", db_url)
|
|
787
|
-
|
|
1055
|
+
prefix = "embedded (bundled PostgreSQL) — " if is_embedded else ""
|
|
1056
|
+
click.echo(f"Database: {prefix}{display_url}")
|
|
788
1057
|
|
|
789
1058
|
err = _test_db(db_url)
|
|
790
1059
|
click.echo(f" DB connection: {'✓ OK' if not err else f'✗ {err}'}")
|
|
@@ -831,6 +1100,7 @@ def demo():
|
|
|
831
1100
|
if not cfg:
|
|
832
1101
|
click.echo("Not initialized. Run `celerp init` first.", err=True)
|
|
833
1102
|
sys.exit(1)
|
|
1103
|
+
ensure_database(cfg)
|
|
834
1104
|
env = _config_to_env(cfg)
|
|
835
1105
|
pkg_root = Path(__file__).parent.parent
|
|
836
1106
|
script = pkg_root / "scripts" / "seed_demo.py"
|
|
@@ -853,6 +1123,7 @@ def upgrade():
|
|
|
853
1123
|
if not cfg:
|
|
854
1124
|
click.echo("Not initialized. Run `celerp init` first.", err=True)
|
|
855
1125
|
sys.exit(1)
|
|
1126
|
+
ensure_database(cfg)
|
|
856
1127
|
_run_migrations(cfg["database"]["url"])
|
|
857
1128
|
click.echo("✓ Upgrade complete")
|
|
858
1129
|
|