celerp 2.1.0__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {celerp-2.1.0 → celerp-2.2.0}/PKG-INFO +12 -9
- {celerp-2.1.0 → celerp-2.2.0}/README.md +11 -8
- {celerp-2.1.0 → celerp-2.2.0}/celerp/config.py +5 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/events/schemas.py +2 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/main.py +41 -1
- celerp-2.2.0/celerp/migrations/versions/b3c4d5e6f7a8_expand_role_permissions_to_role_grants.py +175 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/companies.py +31 -24
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/events.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/health.py +0 -10
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/stars.py +2 -2
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/auto_je.py +3 -2
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/cost_visibility.py +18 -5
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/field_schema.py +30 -1
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/permissions.py +25 -14
- {celerp-2.1.0 → celerp-2.2.0}/celerp.egg-info/PKG-INFO +12 -9
- {celerp-2.1.0 → celerp-2.2.0}/celerp.egg-info/SOURCES.txt +1 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp.egg-info/scm_file_list.json +22 -0
- celerp-2.2.0/celerp.egg-info/scm_version.json +8 -0
- {celerp-2.1.0 → celerp-2.2.0}/conftest.py +31 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_accounting_gaps.py +2 -2
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-dashboard/celerp_dashboard/routes.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/doc_constants.py +7 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/routes.py +396 -85
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_audits.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_freight_je.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_freight_lines.py +2 -2
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_fulfill_no_split.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_fulfillment_activity.py +4 -4
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_inbound_je_lifecycle.py +3 -3
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_inventory_account_reconciliation.py +2 -2
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_landed_receive.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_line_delete_persist.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_line_identifier.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_payment_void_activity.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_receive_sku_batch.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_service_lines.py +3 -3
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_void_guards.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/celerp_inventory/routes.py +476 -49
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/tests/test_labels.py +2 -2
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/celerp_manufacturing/routes.py +19 -5
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_auto_complete_on_finalize.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_bom_removed.py +2 -2
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_build_api.py +45 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_item_workflow_api.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_manufacture_from_doc.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_manufacturing.py +2 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_manufacturing_module.py +8 -8
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_phase2_manufacturing_validations.py +2 -2
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_production_order.py +2 -2
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_to_make_allocation.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_work_centers_and_settings.py +4 -4
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-subscriptions/celerp_subscriptions/routes.py +13 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-subscriptions/tests/test_subscriptions.py +20 -0
- celerp-2.2.0/default_modules/first_party.lock.json +16 -0
- {celerp-2.1.0 → celerp-2.2.0}/test_helpers.py +25 -8
- {celerp-2.1.0 → celerp-2.2.0}/ui/api_client.py +42 -3
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/activity.py +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/shell.py +83 -10
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/table.py +64 -17
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/ar.json +0 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/de.json +0 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/en.json +1 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/es.json +0 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/fr.json +0 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/id.json +0 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/it.json +0 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/ja.json +0 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/pt.json +0 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/th.json +0 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/locales/vi.json +0 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/contacts.py +2 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/documents.py +482 -134
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/inventory.py +224 -31
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/manufacturing.py +4 -2
- celerp-2.2.0/ui/routes/search.py +152 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings.py +5 -28
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_general.py +0 -7
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/subscriptions.py +2 -1
- {celerp-2.1.0 → celerp-2.2.0}/ui/static/app.css +64 -7
- celerp-2.1.0/celerp.egg-info/scm_version.json +0 -8
- celerp-2.1.0/default_modules/first_party.lock.json +0 -16
- celerp-2.1.0/ui/routes/search.py +0 -72
- {celerp-2.1.0 → celerp-2.2.0}/CLA.md +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/CONTRIBUTING.md +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/LICENSING.md +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/MANIFEST.in +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/NOTICE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/alembic.ini +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/__main__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/batch.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/cleanup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/commands.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/conversations.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/files.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/intent.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/llm.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/memory.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/models.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/page_count.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/quota.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/service.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/ai/tools.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/alembic.ini +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/alembic_config.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/cli.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/compat.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/compute/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/compute/aggregations.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/compute/valuation.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/base.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/daily_scheduler.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/http.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/images.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/quickbooks.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/registry.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/relay_token.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/shopify.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/sync_runner.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/upsert.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/util.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/webhooks.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/woocommerce.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/connectors/xero.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/constants.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/db.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/embedded_pg.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/events/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/events/engine.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/events/types.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/gateway/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/gateway/client.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/gateway/state.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/importers/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/importers/importer.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/importers/schema.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/middleware.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/README.md +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/_auto_stamp.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/_data_reconcile.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/_json_compat.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/env.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/script.py.mako +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/a0b1c2d3e4f5_seed_landed_cost_clearing_accounts.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/a1b2c3d4e5f6_add_doc_share_tokens.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/b1c2d3e4f5a6_add_supporter_badges.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/b2c3d4e5f6a7_add_import_batches.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/c1d2e3f4a5b6_add_marketplace.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/c2d3e4f5a6b7_add_is_sync_to_shopify.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/c4d5e6f7a8b9_account_cash_flow_category.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/d0e1f2a3b4c5_add_share_token_expiry.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/d2e3f4a5b6c7_add_password_reset_token.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/d5e6f7a8b9c0_rename_fx_rounding_to_fx_difference.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/e3f4a5b6c7d8_add_company_is_active.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/e4f5a6b7c8d9_backfill_connector_idempotency_key.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/e7c9a1b3d5f2_work_center_default_columns.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/f1a2b3c4d5e6_move_accounts_marketplace_to_modules.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/f6a7b8c9d0e1_seed_fx_rounding_account.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/f8a9b0c1d2e3_work_center_default_backfill.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/fd5de461e14e_initial_schema.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/g1h2i3j4k5l6_add_consignment_flag.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/h2i3j4k5l6m7_add_bank_accounts_and_reconciliation.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/j4k5l6m7n8o9_labels_db_persistence.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/k5l6m7n8o9p0_add_reconciliation_v2.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/l6m7n8o9p0q1_add_sync_runs_table.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/m7n8o9p0q1r2_add_connector_configs_and_outbound_queue.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/n8o9p0q1r2s3_backfill_payment_date.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/o9p0q1r2s3t4_backfill_item_price_fields.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/p1q2r3s4t5u6_add_session_registry_and_user_auth_state.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/q2r3s4t5u6v7_add_system_runtime_state.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/r3s4t5u6v7w8_add_projections_company_entity_type_index.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/s4t5u6v7w8x9_drop_user_company_id_role.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/t5u6v7w8x9y0_seed_inventory_sub_accounts.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/u6v7w8x9y0z1_backfill_item_prices_from_attributes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/v7w8x9y0z1a2_backfill_purchase_unit_defaults.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/w8x9y0z1a2b3_backfill_category_unit_defaults.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/x7y8z9a0b1c2_add_projection_created_at.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/y8z9a0b1c2d3_per_company_ledger_idempotency.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/migrations/versions/z9a0b1c2d3e4_work_centers.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/accounting.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/ai.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/auth.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/base.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/company.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/connector_config.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/import_batch.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/ledger.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/marketplace.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/notification.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/projections.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/share.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/supporter.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/models/sync_run.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/api.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/audit.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/demotion.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/importer.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/license.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/loader.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/meta.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/migrations_runner.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/references.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/registry.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/modules/slots.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/notifications/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/notifications/service.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/notifications/sse.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/output/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/output/branding.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/output/doc_print.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/output/pdf.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/output/share_render.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/projections/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/projections/engine.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/projections/handlers/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/projections/handlers/marketplace.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/projections/handlers/scanning.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/projections/handlers/shopify.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/projections/handlers/system.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/auth.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/debug.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/doctor.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/ledger.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/notifications.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/routers/system.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/schemas/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/activity_redaction.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/attachments.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/auth.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/backup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/backup_export.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/backup_import.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/backup_repo.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/backup_scheduler.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/backup_state.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/demo.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/dev_release_guard.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/email.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/fulfill.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/holdings.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/je_keys.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/landed_cost.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/line_measures.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/list_behavior.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/money.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/payments.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/pick.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/pricing.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/relay_share.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/reorder.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/runtime_state.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/session_tracker.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/shipping.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/star_cta.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/status_doc_backfill.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/supporter_badge.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/system_health.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/services/units.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/session_gate.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp/tax_regimes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp.egg-info/dependency_links.txt +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp.egg-info/entry_points.txt +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp.egg-info/requires.txt +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/celerp.egg-info/top_level.txt +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/celerp_accounting/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/celerp_accounting/api_setup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/celerp_accounting/csv_parser.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/celerp_accounting/matcher.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/celerp_accounting/models.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/celerp_accounting/projections.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/celerp_accounting/routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/celerp_accounting/ui_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/balance-sheet.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/cash-flow.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/extended-journal-csv.csv +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/extended-journal-print.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/extended-journal.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/general-ledger.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/journal-csv.csv +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/journal-print.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/journal.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/ledger.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/pnl.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/statement.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/report_goldens/trial-balance.html +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_accounting_banking.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_accounting_banking_routers.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_accounting_import_idempotency.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_cash_flow.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_financial_reports_ui.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_journal_gl_soa.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_journal_gl_soa_ui.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_reconciliation_v2.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_reports_end_to_end.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-accounting/tests/test_route_permissions.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-admin/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-admin/celerp_admin/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-admin/celerp_admin/routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-admin/celerp_admin/setup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/celerp_ai/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/celerp_ai/routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/celerp_ai/setup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/celerp_ai/ui_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/conftest.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_batch.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_cleanup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_conversations.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_coverage_gaps.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_intent.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_llm.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_memory.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_models.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_page_count.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_quota.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_router.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_routes_coverage.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_service.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-ai/tests/test_tools.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-backup/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-backup/celerp_backup/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-backup/celerp_backup/routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-backup/celerp_backup/setup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/celerp_connectors/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/celerp_connectors/models.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/celerp_connectors/routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/conftest.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_compliance.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_connector_correctness.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_connectors.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_credentials_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_images.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_outbound.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_quickbooks.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_rate_limiting.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_shopify.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_wiring.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_woocommerce.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_woocommerce_webhooks.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-connectors/tests/test_xero.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-contacts/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-contacts/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-contacts/celerp_contacts/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-contacts/celerp_contacts/migrations.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-contacts/celerp_contacts/projections.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-contacts/celerp_contacts/routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-contacts/celerp_contacts/services.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-contacts/celerp_contacts/ui_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-dashboard/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-dashboard/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-dashboard/celerp_dashboard/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-dashboard/celerp_dashboard/setup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/api_setup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/doc_email.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/doc_projections.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/doc_service.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/models_share.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/routes_payments.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/routes_share.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/sequences.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/taxes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/celerp_docs/ui_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/conftest.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-docs/tests/test_send_visibility.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/celerp_inventory/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/celerp_inventory/models_import_batch.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/celerp_inventory/projections.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/celerp_inventory/routes_attachments.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/celerp_inventory/routes_scanning.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/celerp_inventory/services.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/celerp_inventory/ui_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/tests/test_item_recipe_projection.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/tests/test_item_workflow_projection.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-inventory/tests/test_landed_cost_projection.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/celerp_labels/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/celerp_labels/models.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/celerp_labels/presets.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/celerp_labels/routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/celerp_labels/service.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/celerp_labels/ui_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/requirements.txt +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-labels/tests/test_labels_module.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/celerp_manufacturing/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/celerp_manufacturing/costing.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/celerp_manufacturing/expansion.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/celerp_manufacturing/labor.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/celerp_manufacturing/migrations.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/celerp_manufacturing/projection_handler.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/celerp_manufacturing/ui_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/requirements.txt +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_item_recipe_api.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_labor_providers.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_manufacturing_import_idempotency.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_mfg_events.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_recipe_costing.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_recipe_expansion.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_recost_api.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_where_used.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-manufacturing/tests/test_workflow_time.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-reports/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-reports/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-reports/celerp_reports/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-reports/celerp_reports/api_setup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-reports/celerp_reports/routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-reports/celerp_reports/ui_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-reports/tests/test_reports_full.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-reports/tests/test_reports_unit.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-subscriptions/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-subscriptions/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-subscriptions/celerp_subscriptions/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-subscriptions/celerp_subscriptions/ui_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-subscriptions/tests/test_subscriptions_ui.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/LICENSE +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/accessory_fashion.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/activewear.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/art_photography.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/audio_equipment.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/bag_handbag.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/banknote.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/beauty_tool.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/bed_bedroom.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/beer.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/beverage_nonalc.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/body_part_auto.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/book.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/bottoms.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/brake_suspension.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/bullion_coin.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/camera.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/colored_stone.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/comic.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/commercial_space.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/component_part.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/confectionery.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/consulting_service.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/decorative_art.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/diamond.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/drawing.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/dress_jumpsuit.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_auto.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/electrical_component.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/emerald.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/engine_part.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/fastener.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/fertilizer_chemical.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/film_video.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/fine_writing_instrument.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/fluid_lubricant.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/footwear.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/fragrance.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_food.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/fresh_produce.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/frozen_food.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/gaming_console.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/gold_bullion.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/grain_cereal.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/haircare.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/hand_tool.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/ingredient_bulk.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/interior_part.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/jewelry.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/kitchen_dining.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/laptop.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/lighting.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/livestock_feed.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/makeup.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/measuring_instrument.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/medal_token.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/mineral_specimen.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/mobile_phone.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/music_cd.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/music_vinyl.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/nail.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/numismatic_coin.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/outdoor_furniture.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/outerwear.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/packaged_food.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/painting.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/parking_bay.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/pearl.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/personal_care.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/pipe_plumbing.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/platinum_bullion.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/power_tool.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/print_edition.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/residential_unit.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/rough_gemstone.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/ruby.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/saas_plan.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/safety_ppe.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/sapphire.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/sculpture.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/seating.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/seeds.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/silver_bullion.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/skincare.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/soft_furnishing.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/software_addon.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/software_license.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/spirit.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/storage_furniture.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/swimwear.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/table_desk.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/tablet.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/tire_wheel.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/tops.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/trading_card.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/tv_display.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/video_game.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/watch.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/watch_strap.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/categories/wine.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/agricultural.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/artwork.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/automotive.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/blank.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/books_media.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/coins_precious_metals.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/consulting.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/cosmetics.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/electronics.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/fashion.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/food_beverage.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/furniture.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/gemstones.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/hardware.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/property_rental.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/saas.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/watches.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/presets/wine_spirits.json +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/celerp_verticals/ui_routes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/tests/test_verticals.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/default_modules/celerp-verticals/tests/test_verticals_routers.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/legal/OFFICIAL-COMPONENTS.md +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/legal/TRADEMARK.md +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/packaging/winget/Celerp.Celerp.installer.yaml +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/packaging/winget/Celerp.Celerp.locale.en-US.yaml +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/packaging/winget/Celerp.Celerp.yaml +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/packaging/winget/README.md +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/pyproject.toml +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/setup.cfg +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/app.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/attrs.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/backup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/cloud_gate.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/currency.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/files.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/journal.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/notes.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/phone.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/components/report_kit.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/config.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/i18n.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/marketplace_catalog.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/__init__.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/account.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/accounting.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/accounting_import.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/auth.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/csv_import.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/dashboard.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/docs_import.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/events.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/financial_reports.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/lists_import.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/modules_page.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/notifications.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/reconciliation.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/reports.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_accounting.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_cloud.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_connectors.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_contacts.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_import.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_inventory.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_manufacturing.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_payments.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_purchasing.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/settings_sales.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/setup.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/stars.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/routes/subscriptions_import.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/security.py +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/static/htmx.min.js +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/static/icon.png +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/static/logo.png +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/static/vendor/intl-tel-input/img/flags.webp +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/static/vendor/intl-tel-input/img/flags@2x.webp +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/static/vendor/intl-tel-input/intlTelInput.min.css +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/static/vendor/intl-tel-input/intlTelInput.min.js +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/static/vendor/intl-tel-input/intlTelInputWithUtils.min.js +0 -0
- {celerp-2.1.0 → celerp-2.2.0}/ui/static/vendor/intl-tel-input/utils.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: celerp
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Free, self-hosted ERP for small businesses
|
|
5
5
|
License: Business Source License 1.1
|
|
6
6
|
|
|
@@ -185,18 +185,22 @@ Celerp is simple to use, flexible, customizable, and designed to transition your
|
|
|
185
185
|
[](https://github.com/celerp/celerp/actions)
|
|
186
186
|
[](LICENSE)
|
|
187
187
|
|
|
188
|
+
<!-- PRESS_KIT:root-hero start -->
|
|
188
189
|

|
|
190
|
+
<!-- PRESS_KIT:root-hero end -->
|
|
189
191
|
|
|
190
192
|
## Screenshots
|
|
191
193
|
|
|
192
194
|
Real double-entry accounting, multi-location inventory, manufacturing, and a built-in REST API - one self-hosted app.
|
|
193
195
|
|
|
196
|
+
<!-- PRESS_KIT:root-grid start -->
|
|
194
197
|
| | |
|
|
195
198
|
|---|---|
|
|
199
|
+
| <br>**Dashboard** - revenue trend, AR aging, inventory mix | <br>**Inventory** - multi-location, barcode, valuation |
|
|
196
200
|
| <br>**Trial balance** - ties out to zero | <br>**Balance sheet** - live from the ledger |
|
|
197
|
-
| <br>**Production planning** - work orders, priorities, due dates | <br>**Shipping documents** - commercial invoice and customs |
|
|
202
|
+
| <br>**REST API** - integrate anything | <br>**Statement of account** - customer AR at a glance |
|
|
203
|
+
<!-- PRESS_KIT:root-grid end -->
|
|
200
204
|
|
|
201
205
|
More in the [press kit](docs/press-kit/).
|
|
202
206
|
|
|
@@ -206,9 +210,9 @@ More in the [press kit](docs/press-kit/).
|
|
|
206
210
|
|
|
207
211
|
| Platform | Link |
|
|
208
212
|
|----------|------|
|
|
209
|
-
| Windows (.exe) | [
|
|
210
|
-
| Linux (.
|
|
211
|
-
| macOS (.dmg) | [
|
|
213
|
+
| Windows (.exe) | [Download](https://celerp.com/download-thanks.html?dl=win) |
|
|
214
|
+
| Linux (.deb) | [Download](https://celerp.com/download-thanks.html?dl=linux) |
|
|
215
|
+
| macOS (.dmg) | [Download](https://celerp.com/download-thanks.html?dl=mac) |
|
|
212
216
|
|
|
213
217
|
**Double-click. No account. No credit card. Your computer securely becomes the server for your office**
|
|
214
218
|
|
|
@@ -335,8 +339,7 @@ Celerp is open-core:
|
|
|
335
339
|
self-hosting permitted, contributions welcome.
|
|
336
340
|
- **An MIT-licensed module ecosystem** - the default business modules are MIT, so you can
|
|
337
341
|
fork them, build your own modules, and ship them however you like. See [LICENSING.md](LICENSING.md).
|
|
338
|
-
- **A
|
|
339
|
-
services) that powers the hosted experience.
|
|
342
|
+
- **A source available application** (official UI, document/PDF output and AI & Connect services).
|
|
340
343
|
|
|
341
344
|
See [LICENSING.md](LICENSING.md) for the full map and [TRADEMARK.md](legal/TRADEMARK.md) for use of the Celerp
|
|
342
345
|
name. One restriction: don't resell Celerp itself as a competing product.
|
|
@@ -12,18 +12,22 @@ Celerp is simple to use, flexible, customizable, and designed to transition your
|
|
|
12
12
|
[](https://github.com/celerp/celerp/actions)
|
|
13
13
|
[](LICENSE)
|
|
14
14
|
|
|
15
|
+
<!-- PRESS_KIT:root-hero start -->
|
|
15
16
|

|
|
17
|
+
<!-- PRESS_KIT:root-hero end -->
|
|
16
18
|
|
|
17
19
|
## Screenshots
|
|
18
20
|
|
|
19
21
|
Real double-entry accounting, multi-location inventory, manufacturing, and a built-in REST API - one self-hosted app.
|
|
20
22
|
|
|
23
|
+
<!-- PRESS_KIT:root-grid start -->
|
|
21
24
|
| | |
|
|
22
25
|
|---|---|
|
|
26
|
+
| <br>**Dashboard** - revenue trend, AR aging, inventory mix | <br>**Inventory** - multi-location, barcode, valuation |
|
|
23
27
|
| <br>**Trial balance** - ties out to zero | <br>**Balance sheet** - live from the ledger |
|
|
24
|
-
| <br>**Production planning** - work orders, priorities, due dates | <br>**Shipping documents** - commercial invoice and customs |
|
|
29
|
+
| <br>**REST API** - integrate anything | <br>**Statement of account** - customer AR at a glance |
|
|
30
|
+
<!-- PRESS_KIT:root-grid end -->
|
|
27
31
|
|
|
28
32
|
More in the [press kit](docs/press-kit/).
|
|
29
33
|
|
|
@@ -33,9 +37,9 @@ More in the [press kit](docs/press-kit/).
|
|
|
33
37
|
|
|
34
38
|
| Platform | Link |
|
|
35
39
|
|----------|------|
|
|
36
|
-
| Windows (.exe) | [
|
|
37
|
-
| Linux (.
|
|
38
|
-
| macOS (.dmg) | [
|
|
40
|
+
| Windows (.exe) | [Download](https://celerp.com/download-thanks.html?dl=win) |
|
|
41
|
+
| Linux (.deb) | [Download](https://celerp.com/download-thanks.html?dl=linux) |
|
|
42
|
+
| macOS (.dmg) | [Download](https://celerp.com/download-thanks.html?dl=mac) |
|
|
39
43
|
|
|
40
44
|
**Double-click. No account. No credit card. Your computer securely becomes the server for your office**
|
|
41
45
|
|
|
@@ -162,8 +166,7 @@ Celerp is open-core:
|
|
|
162
166
|
self-hosting permitted, contributions welcome.
|
|
163
167
|
- **An MIT-licensed module ecosystem** - the default business modules are MIT, so you can
|
|
164
168
|
fork them, build your own modules, and ship them however you like. See [LICENSING.md](LICENSING.md).
|
|
165
|
-
- **A
|
|
166
|
-
services) that powers the hosted experience.
|
|
169
|
+
- **A source available application** (official UI, document/PDF output and AI & Connect services).
|
|
167
170
|
|
|
168
171
|
See [LICENSING.md](LICENSING.md) for the full map and [TRADEMARK.md](legal/TRADEMARK.md) for use of the Celerp
|
|
169
172
|
name. One restriction: don't resell Celerp itself as a competing product.
|
|
@@ -25,6 +25,11 @@ class Settings(BaseSettings):
|
|
|
25
25
|
idle_logout_minutes: int = 15
|
|
26
26
|
# Set to "true" to allow the default JWT secret (CI only).
|
|
27
27
|
allow_insecure_jwt: str = "false"
|
|
28
|
+
# Serve the OpenAPI schema (/openapi.json) and the grouped API reference.
|
|
29
|
+
# Default off: production does not publish the API shape. Enabled only by the
|
|
30
|
+
# press-kit capture harness (and CI) to render the reference. Never set true
|
|
31
|
+
# in production.
|
|
32
|
+
expose_openapi_schema: bool = False
|
|
28
33
|
# Logging level for both API and UI processes. Override with LOG_LEVEL env var.
|
|
29
34
|
# Accepted values: debug, info, warning, error, critical (case-insensitive).
|
|
30
35
|
log_level: str = "INFO"
|
|
@@ -356,7 +356,47 @@ log = logging.getLogger(__name__)
|
|
|
356
356
|
_storage_uri = settings.redis_url or "memory://"
|
|
357
357
|
limiter = Limiter(key_func=get_remote_address, default_limits=["60/minute"], storage_uri=_storage_uri)
|
|
358
358
|
|
|
359
|
-
|
|
359
|
+
_OPENAPI_TAGS = [
|
|
360
|
+
{"name": "auth", "description": "Sign in, sessions, and access tokens."},
|
|
361
|
+
{"name": "companies", "description": "Companies, members, and roles."},
|
|
362
|
+
{"name": "items", "description": "Inventory items, stock, and valuation."},
|
|
363
|
+
{"name": "docs", "description": "Invoices, purchase orders, quotations, and credit notes."},
|
|
364
|
+
{"name": "lists", "description": "Shipping documents and packing lists."},
|
|
365
|
+
{"name": "accounting", "description": "Chart of accounts and journal entries."},
|
|
366
|
+
{"name": "ledger", "description": "Event-sourced ledger and projections."},
|
|
367
|
+
{"name": "reports", "description": "Financial statements and aging reports."},
|
|
368
|
+
{"name": "manufacturing", "description": "Bills of materials and production orders."},
|
|
369
|
+
{"name": "labels", "description": "Label templates and barcode printing."},
|
|
370
|
+
{"name": "crm", "description": "Contacts, pipeline, and activity."},
|
|
371
|
+
{"name": "subscriptions", "description": "Recurring billing and auto-invoicing."},
|
|
372
|
+
{"name": "connectors", "description": "External integrations."},
|
|
373
|
+
{"name": "payments", "description": "Payment collection."},
|
|
374
|
+
{"name": "backup", "description": "Data export and import."},
|
|
375
|
+
{"name": "notifications", "description": "In-app notifications."},
|
|
376
|
+
{"name": "events", "description": "Server-sent event stream for live updates."},
|
|
377
|
+
{"name": "system", "description": "Health, status, and instance metadata."},
|
|
378
|
+
]
|
|
379
|
+
|
|
380
|
+
_OPENAPI_DESCRIPTION = "REST API for Celerp, the self-hosted business management platform."
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def _openapi_settings() -> dict:
|
|
384
|
+
"""FastAPI OpenAPI kwargs for the current settings. Production keeps the schema
|
|
385
|
+
unserved (openapi_url=None); the press-kit capture harness turns
|
|
386
|
+
expose_openapi_schema on to publish it for the API reference shot, and that
|
|
387
|
+
non-default state is logged so it is never silent. Isolated so the exposure
|
|
388
|
+
boundary is unit-testable without reconstructing the whole app."""
|
|
389
|
+
expose = settings.expose_openapi_schema
|
|
390
|
+
if expose:
|
|
391
|
+
log.warning("expose_openapi_schema is on: serving the public OpenAPI schema at /openapi.json")
|
|
392
|
+
return {
|
|
393
|
+
"description": _OPENAPI_DESCRIPTION,
|
|
394
|
+
"openapi_tags": _OPENAPI_TAGS,
|
|
395
|
+
"openapi_url": "/openapi.json" if expose else None,
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
app = FastAPI(title="Celerp", docs_url=None, redoc_url=None, lifespan=lifespan, **_openapi_settings())
|
|
360
400
|
app.state.limiter = limiter
|
|
361
401
|
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
|
|
362
402
|
app.add_middleware(DrainMiddleware)
|
celerp-2.2.0/celerp/migrations/versions/b3c4d5e6f7a8_expand_role_permissions_to_role_grants.py
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Copyright (c) 2026 Noah Severs
|
|
2
|
+
# SPDX-License-Identifier: BUSL-1.1
|
|
3
|
+
|
|
4
|
+
"""expand the role_permissions threshold overrides into explicit role_grants sets
|
|
5
|
+
|
|
6
|
+
Revision ID: b3c4d5e6f7a8
|
|
7
|
+
Revises: f8a9b0c1d2e3
|
|
8
|
+
Create Date: 2026-08-09
|
|
9
|
+
|
|
10
|
+
The data half of the per-role permissions change. Role overrides used to be a
|
|
11
|
+
single minimum-role threshold per permission (Company.settings["role_permissions"]
|
|
12
|
+
= {permission_key: minimum_role_key}); every role at or above that threshold was
|
|
13
|
+
granted, so the roles moved as a block. They are now an explicit set of granted
|
|
14
|
+
roles per permission (Company.settings["role_grants"] = {permission_key:
|
|
15
|
+
[role_key, ...]}), each role granted independently. This migration rewrites every
|
|
16
|
+
stored threshold into the exact set of roles it used to grant, so no company's
|
|
17
|
+
effective permissions change, then drops the retired key.
|
|
18
|
+
|
|
19
|
+
Deltas only: it materializes a grant set for the keys a company actually
|
|
20
|
+
overrode, never the whole catalogue; unoverridden keys keep resolving to their
|
|
21
|
+
registry default. Each threshold expands to every role at or above it, clamped up
|
|
22
|
+
to the permission's floor (so a grandfathered sub-floor override lands on the
|
|
23
|
+
floor exactly as the resolver reads it). A threshold on a permission that is no
|
|
24
|
+
longer overridable, unknown to the catalogue, or naming a role that no longer
|
|
25
|
+
exists never resolved to anything but the default, so it becomes no delta and is
|
|
26
|
+
left absent.
|
|
27
|
+
|
|
28
|
+
Signature-less (data only), so the develop-to-release reconcile replays it on
|
|
29
|
+
every create_all/restore database. Idempotent: guarded on the presence of the
|
|
30
|
+
retired key, so a second application is a no-op. The downgrade is the best-effort
|
|
31
|
+
inverse: it collapses each grant set back to a single threshold at its lowest
|
|
32
|
+
granted role and restores the retired key, so a rollback to the threshold-reading
|
|
33
|
+
code keeps a company's effective permissions. This round-trips exactly for the
|
|
34
|
+
contiguous sets the upgrade produces; a hand-authored non-contiguous set is
|
|
35
|
+
documented lossy (it collapses to its lowest role, which the older resolver then
|
|
36
|
+
re-expands as a block).
|
|
37
|
+
|
|
38
|
+
The catalogue (floor role and overridability per permission) and the role levels
|
|
39
|
+
are snapshotted here as literals, because a migration is immutable history: it
|
|
40
|
+
must expand exactly as the rules stood when it was written, even after the
|
|
41
|
+
registry in celerp.services.permissions later changes.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
from __future__ import annotations
|
|
45
|
+
|
|
46
|
+
import json
|
|
47
|
+
|
|
48
|
+
import sqlalchemy as sa
|
|
49
|
+
from alembic import op
|
|
50
|
+
|
|
51
|
+
revision = "b3c4d5e6f7a8"
|
|
52
|
+
down_revision = "f8a9b0c1d2e3"
|
|
53
|
+
branch_labels = None
|
|
54
|
+
depends_on = None
|
|
55
|
+
|
|
56
|
+
# Snapshot of auth.ROLE_LEVELS at this revision.
|
|
57
|
+
_ROLE_LEVELS = {"viewer": 1, "operator": 2, "manager": 3, "admin": 4, "owner": 5}
|
|
58
|
+
|
|
59
|
+
# Snapshot of the permission catalogue at this revision: key -> (floor_role,
|
|
60
|
+
# grantable). default_role is irrelevant here because every key processed carries
|
|
61
|
+
# an explicit override; only the floor (which clamps the expansion) and whether
|
|
62
|
+
# the key is overridable at all matter.
|
|
63
|
+
_CATALOGUE = {
|
|
64
|
+
"view_dashboards": ("viewer", True),
|
|
65
|
+
"view_documents": ("viewer", True),
|
|
66
|
+
"view_contacts": ("viewer", True),
|
|
67
|
+
"view_inventory": ("viewer", True),
|
|
68
|
+
"edit_documents": ("viewer", True),
|
|
69
|
+
"edit_contacts": ("viewer", True),
|
|
70
|
+
"edit_inventory": ("viewer", True),
|
|
71
|
+
"edit_inventory_amounts": ("viewer", True),
|
|
72
|
+
"finalize_documents": ("viewer", True),
|
|
73
|
+
"fulfill_documents": ("viewer", True),
|
|
74
|
+
"record_payments": ("viewer", True),
|
|
75
|
+
"manage_labels": ("viewer", True),
|
|
76
|
+
"manage_manufacturing": ("viewer", True),
|
|
77
|
+
"use_ai_assistant": ("viewer", True),
|
|
78
|
+
"run_backups": ("viewer", True),
|
|
79
|
+
"view_subscriptions": ("viewer", True),
|
|
80
|
+
"view_inventory_costs": ("viewer", True),
|
|
81
|
+
"set_inventory_prices": ("viewer", True),
|
|
82
|
+
"set_sales_doc_prices": ("viewer", True),
|
|
83
|
+
"delete_documents": ("viewer", True),
|
|
84
|
+
"adjust_inventory": ("viewer", True),
|
|
85
|
+
"import_export_data": ("viewer", True),
|
|
86
|
+
"view_payments": ("viewer", True),
|
|
87
|
+
"view_financial_reports": ("viewer", True),
|
|
88
|
+
"manage_accounting": ("viewer", True),
|
|
89
|
+
"manage_module_settings": ("viewer", True),
|
|
90
|
+
"manage_users": ("viewer", True),
|
|
91
|
+
"manage_company_settings": ("admin", True),
|
|
92
|
+
"manage_integrations": ("viewer", True),
|
|
93
|
+
"manage_permissions": ("owner", False),
|
|
94
|
+
"manage_company_lifecycle": ("owner", False),
|
|
95
|
+
"manage_billing": ("owner", False),
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _expand(stored_role: str, floor_role: str) -> list[str]:
|
|
100
|
+
"""The role keys a threshold used to grant: every role at or above the
|
|
101
|
+
threshold, clamped up to the floor, ordered low to high."""
|
|
102
|
+
threshold = max(_ROLE_LEVELS[stored_role], _ROLE_LEVELS[floor_role])
|
|
103
|
+
return sorted(
|
|
104
|
+
(r for r, lvl in _ROLE_LEVELS.items() if lvl >= threshold),
|
|
105
|
+
key=lambda r: _ROLE_LEVELS[r],
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _collapse(granted_roles: list[str]) -> str | None:
|
|
110
|
+
"""Best-effort inverse of _expand: the threshold role at the lowest granted
|
|
111
|
+
level. Exact for a contiguous set (the shape upgrade produces); lossy for a
|
|
112
|
+
non-contiguous set, which no longer round-trips to the same set. None when no
|
|
113
|
+
granted role is known, leaving the permission absent (resolves to default)."""
|
|
114
|
+
levels = [_ROLE_LEVELS[r] for r in granted_roles if r in _ROLE_LEVELS]
|
|
115
|
+
if not levels:
|
|
116
|
+
return None
|
|
117
|
+
low = min(levels)
|
|
118
|
+
return next(r for r, lvl in _ROLE_LEVELS.items() if lvl == low)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def upgrade() -> None:
|
|
122
|
+
conn = op.get_bind()
|
|
123
|
+
# Only companies that still carry the retired key; this is also the
|
|
124
|
+
# idempotency guard, so a replay after the key is stripped touches nothing.
|
|
125
|
+
rows = conn.execute(sa.text(
|
|
126
|
+
"SELECT id, settings FROM companies WHERE settings::jsonb ? 'role_permissions'"
|
|
127
|
+
)).fetchall()
|
|
128
|
+
|
|
129
|
+
for cid, settings in rows:
|
|
130
|
+
data = settings if isinstance(settings, dict) else json.loads(settings)
|
|
131
|
+
role_perms = data.get("role_permissions")
|
|
132
|
+
grants = dict(data.get("role_grants") or {})
|
|
133
|
+
if isinstance(role_perms, dict):
|
|
134
|
+
for key, stored_role in role_perms.items():
|
|
135
|
+
meta = _CATALOGUE.get(key)
|
|
136
|
+
if meta is None:
|
|
137
|
+
continue # unknown key: never resolved to an override
|
|
138
|
+
floor_role, grantable = meta
|
|
139
|
+
if not grantable:
|
|
140
|
+
continue # fixed permission: overrides were never honored
|
|
141
|
+
if stored_role not in _ROLE_LEVELS:
|
|
142
|
+
continue # stale role: resolved to the default, no delta
|
|
143
|
+
grants[key] = _expand(stored_role, floor_role)
|
|
144
|
+
if grants:
|
|
145
|
+
data["role_grants"] = grants
|
|
146
|
+
data.pop("role_permissions", None)
|
|
147
|
+
conn.execute(
|
|
148
|
+
sa.text("UPDATE companies SET settings = CAST(:s AS json) WHERE id = :id"),
|
|
149
|
+
{"s": json.dumps(data), "id": str(cid)},
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def downgrade() -> None:
|
|
154
|
+
conn = op.get_bind()
|
|
155
|
+
# Only companies that carry the new key; this is also the idempotency guard.
|
|
156
|
+
rows = conn.execute(sa.text(
|
|
157
|
+
"SELECT id, settings FROM companies WHERE settings::jsonb ? 'role_grants'"
|
|
158
|
+
)).fetchall()
|
|
159
|
+
|
|
160
|
+
for cid, settings in rows:
|
|
161
|
+
data = settings if isinstance(settings, dict) else json.loads(settings)
|
|
162
|
+
grants = data.get("role_grants")
|
|
163
|
+
role_perms = dict(data.get("role_permissions") or {})
|
|
164
|
+
if isinstance(grants, dict):
|
|
165
|
+
for key, roles in grants.items():
|
|
166
|
+
threshold = _collapse(roles if isinstance(roles, list) else [])
|
|
167
|
+
if threshold is not None:
|
|
168
|
+
role_perms[key] = threshold
|
|
169
|
+
if role_perms:
|
|
170
|
+
data["role_permissions"] = role_perms
|
|
171
|
+
data.pop("role_grants", None)
|
|
172
|
+
conn.execute(
|
|
173
|
+
sa.text("UPDATE companies SET settings = CAST(:s AS json) WHERE id = :id"),
|
|
174
|
+
{"s": json.dumps(data), "id": str(cid)},
|
|
175
|
+
)
|
|
@@ -22,6 +22,7 @@ from celerp.services.permissions import (
|
|
|
22
22
|
ROLES,
|
|
23
23
|
get_current_company_settings,
|
|
24
24
|
require_permission,
|
|
25
|
+
resolved_grant_roles,
|
|
25
26
|
role_has_permission,
|
|
26
27
|
)
|
|
27
28
|
from celerp.tax_regimes import get_regime, TAX_REGIMES
|
|
@@ -286,6 +287,16 @@ async def patch_me(payload: CompanyPatch, company_id=Depends(get_current_company
|
|
|
286
287
|
# and category_schemas whenever a caller sent only one field (the UI happens
|
|
287
288
|
# to pre-merge, but partial callers — and a name-only patch — must be safe).
|
|
288
289
|
if payload.settings:
|
|
290
|
+
# Role grants are owner-only and may be written only through the dedicated
|
|
291
|
+
# PATCH /me/role-permissions endpoint (manage_permissions). This door is
|
|
292
|
+
# admin-gated (manage_company_settings), so accepting role_grants here would
|
|
293
|
+
# let an admin self-escalate around the owner gate. role_permissions is the
|
|
294
|
+
# retired storage key; reject it too so it can never be re-introduced.
|
|
295
|
+
if "role_grants" in payload.settings or "role_permissions" in payload.settings:
|
|
296
|
+
raise HTTPException(
|
|
297
|
+
status_code=422,
|
|
298
|
+
detail="Role permissions are set through the permissions matrix, not company settings",
|
|
299
|
+
)
|
|
289
300
|
merged = {**(company.settings or {}), **payload.settings}
|
|
290
301
|
# Price config must pass the same gate as the dedicated endpoints: the read
|
|
291
302
|
# path trusts stored config, so no door may store what the validator rejects.
|
|
@@ -309,12 +320,12 @@ async def patch_role_permissions(
|
|
|
309
320
|
_: None = require_permission("manage_permissions"),
|
|
310
321
|
session: AsyncSession = Depends(get_session),
|
|
311
322
|
) -> dict:
|
|
312
|
-
"""
|
|
323
|
+
"""Toggle one (permission, role) cell from the matrix.
|
|
313
324
|
|
|
314
325
|
Owner-only (manage_permissions is a fixed owner row, so no owner can revoke
|
|
315
326
|
their own ability to edit permissions). A toggle names a (permission, role)
|
|
316
|
-
cell and whether that role should now hold the permission;
|
|
317
|
-
|
|
327
|
+
cell and whether that role should now hold the permission; only that role's
|
|
328
|
+
membership changes - every other role keeps the grant it already had.
|
|
318
329
|
"""
|
|
319
330
|
perm = next((p for p in PERMISSIONS if p.key == payload.perm_key), None)
|
|
320
331
|
if perm is None:
|
|
@@ -324,31 +335,29 @@ async def patch_role_permissions(
|
|
|
324
335
|
if not perm.grantable:
|
|
325
336
|
raise HTTPException(status_code=403, detail=f"The {perm.key} permission is fixed and cannot be reassigned")
|
|
326
337
|
|
|
327
|
-
|
|
328
|
-
|
|
338
|
+
company = await session.get(Company, company_id)
|
|
339
|
+
if company is None:
|
|
340
|
+
raise HTTPException(status_code=404, detail="Not found")
|
|
341
|
+
settings = dict(company.settings or {})
|
|
342
|
+
grants = dict(settings.get("role_grants") or {})
|
|
343
|
+
# Seed from the currently RESOLVED set on first touch, so toggling one role
|
|
344
|
+
# leaves every other role's grant exactly as it is today.
|
|
345
|
+
roles = set(resolved_grant_roles(settings, perm.key))
|
|
329
346
|
if payload.granted:
|
|
330
|
-
|
|
347
|
+
roles.add(payload.role_key)
|
|
331
348
|
else:
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
new_threshold = higher[0].key
|
|
336
|
-
if ROLE_LEVELS[new_threshold] < ROLE_LEVELS[perm.floor_role]:
|
|
349
|
+
roles.discard(payload.role_key)
|
|
350
|
+
# Floor guard: no override may drop the permission below its floor role.
|
|
351
|
+
if payload.granted and ROLE_LEVELS[payload.role_key] < ROLE_LEVELS[perm.floor_role]:
|
|
337
352
|
raise HTTPException(
|
|
338
353
|
status_code=422,
|
|
339
354
|
detail=f"The {perm.key} permission cannot go below the {perm.floor_role} role",
|
|
340
355
|
)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
if company is None:
|
|
344
|
-
raise HTTPException(status_code=404, detail="Not found")
|
|
345
|
-
settings = dict(company.settings or {})
|
|
346
|
-
overrides = dict(settings.get("role_permissions") or {})
|
|
347
|
-
overrides[perm.key] = new_threshold
|
|
348
|
-
settings["role_permissions"] = overrides
|
|
356
|
+
grants[perm.key] = sorted(roles, key=lambda r: ROLE_LEVELS[r])
|
|
357
|
+
settings["role_grants"] = grants
|
|
349
358
|
company.settings = settings
|
|
350
359
|
await session.commit()
|
|
351
|
-
return {"ok": True, "perm_key": perm.key, "
|
|
360
|
+
return {"ok": True, "perm_key": perm.key, "roles": grants[perm.key]}
|
|
352
361
|
|
|
353
362
|
|
|
354
363
|
# ---------------------------------------------------------------------------
|
|
@@ -676,18 +685,16 @@ async def patch_user(
|
|
|
676
685
|
# Item schema configuration
|
|
677
686
|
# ---------------------------------------------------------------------------
|
|
678
687
|
|
|
688
|
+
from celerp.services.field_schema import COST_SCHEMA_KEYS # noqa: F401 re-export
|
|
679
689
|
from celerp.services.field_schema import DEFAULT_ITEM_SCHEMA # noqa: F401 re-export
|
|
680
690
|
from celerp.services.field_schema import get_effective_field_schema # noqa: F401 re-export
|
|
681
691
|
|
|
682
692
|
|
|
683
|
-
_COST_SCHEMA_KEYS: frozenset[str] = frozenset({"cost_price", "cost_price_total"})
|
|
684
|
-
|
|
685
|
-
|
|
686
693
|
@router.get("/me/item-schema")
|
|
687
694
|
async def get_item_schema(company_id=Depends(get_current_company_id), role: str = Depends(get_current_role), settings: dict = Depends(get_current_company_settings), session: AsyncSession = Depends(get_session)) -> list[dict]:
|
|
688
695
|
schema = await get_effective_field_schema(session, company_id)
|
|
689
696
|
if not role_has_permission(settings, role, "view_inventory_costs"):
|
|
690
|
-
schema = [f for f in schema if f.get("key") not in
|
|
697
|
+
schema = [f for f in schema if f.get("key") not in COST_SCHEMA_KEYS]
|
|
691
698
|
return schema
|
|
692
699
|
|
|
693
700
|
|
|
@@ -171,16 +171,6 @@ async def backup_status() -> dict:
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
|
|
174
|
-
@router.get("/settings/email-status")
|
|
175
|
-
async def email_status() -> dict:
|
|
176
|
-
"""Return whether SMTP and/or gateway are configured for email sending."""
|
|
177
|
-
from celerp.config import settings
|
|
178
|
-
return {
|
|
179
|
-
"smtp_configured": bool(settings.smtp_host),
|
|
180
|
-
"gateway_connected": bool(settings.gateway_token),
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
184
174
|
@router.post("/settings/cloud-disconnect", dependencies=[Depends(get_current_user)])
|
|
185
175
|
async def cloud_disconnect() -> dict:
|
|
186
176
|
"""Stop the gateway WebSocket client and record a sticky Cloud disconnect.
|
|
@@ -31,9 +31,9 @@ async def star_cta(
|
|
|
31
31
|
session: AsyncSession = Depends(get_session),
|
|
32
32
|
) -> dict:
|
|
33
33
|
"""Return the relay-resolved CTA for ``medium`` (or the neutral link if the relay
|
|
34
|
-
is unreachable), plus the install-level dismissed flag.
|
|
34
|
+
is unreachable), plus the install-level dismissed flag. Neutral mode when disabled."""
|
|
35
35
|
if not settings.star_cta_enabled:
|
|
36
|
-
return {}
|
|
36
|
+
return {"mode": "neutral"}
|
|
37
37
|
cta = await get_star_cta(medium) or neutral_cta(medium)
|
|
38
38
|
return {**cta, "dismissed": await star_prompt_dismissed(session)}
|
|
39
39
|
|
|
@@ -837,8 +837,9 @@ async def upsert_opening_inventory_je(
|
|
|
837
837
|
)
|
|
838
838
|
).scalars().all()
|
|
839
839
|
|
|
840
|
-
# Inactive statuses: items no longer owned
|
|
841
|
-
|
|
840
|
+
# Inactive statuses: items whose stock is not counted - no longer owned, or
|
|
841
|
+
# (draft) not yet committed. Must match get_valuation()'s filter.
|
|
842
|
+
_INACTIVE = frozenset({"archived", "deleted", "void", "sold", "fulfilled", "merged", "expired", "draft"})
|
|
842
843
|
|
|
843
844
|
catalog_total = _Dec("0")
|
|
844
845
|
for row in item_rows:
|
|
@@ -18,7 +18,8 @@ COST_ITEM_KEYS: frozenset[str] = frozenset({"cost_price", "cost_total"})
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def apply_field_visibility(
|
|
21
|
-
items: list[dict], role: str, field_schema: list[dict], can_see_costs: bool
|
|
21
|
+
items: list[dict], role: str, field_schema: list[dict], can_see_costs: bool,
|
|
22
|
+
can_author_drafts: bool = False,
|
|
22
23
|
) -> list[dict]:
|
|
23
24
|
"""Strip fields from item dicts that the caller is not allowed to see.
|
|
24
25
|
|
|
@@ -30,6 +31,11 @@ def apply_field_visibility(
|
|
|
30
31
|
Cost keys are governed only by the permission, so the cost column's own
|
|
31
32
|
visible_to_roles floor never double-gates them: a granted operator sees cost,
|
|
32
33
|
an ungranted manager does not.
|
|
34
|
+
|
|
35
|
+
Draft carve-out: cost stripping attaches when an item is committed to
|
|
36
|
+
available, not at creation. When ``can_author_drafts`` (the caller holds
|
|
37
|
+
edit_inventory), a DRAFT item keeps its cost keys so its creator can finish
|
|
38
|
+
authoring it; every non-draft item is stripped as before.
|
|
33
39
|
"""
|
|
34
40
|
caller_level = ROLE_LEVELS.get(role, 0)
|
|
35
41
|
restricted = {
|
|
@@ -40,8 +46,15 @@ def apply_field_visibility(
|
|
|
40
46
|
)
|
|
41
47
|
}
|
|
42
48
|
restricted -= COST_ITEM_KEYS
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if not restricted:
|
|
49
|
+
cost_hidden = not can_see_costs
|
|
50
|
+
if not restricted and not cost_hidden:
|
|
46
51
|
return items
|
|
47
|
-
|
|
52
|
+
out = []
|
|
53
|
+
for item in items:
|
|
54
|
+
drop = set(restricted)
|
|
55
|
+
if cost_hidden and not (
|
|
56
|
+
can_author_drafts and str(item.get("status") or "").lower() == "draft"
|
|
57
|
+
):
|
|
58
|
+
drop |= COST_ITEM_KEYS
|
|
59
|
+
out.append({k: v for k, v in item.items() if k not in drop} if drop else item)
|
|
60
|
+
return out
|
|
@@ -24,6 +24,18 @@ MIXED_VALUE = "Mixed"
|
|
|
24
24
|
# COST_ITEM_KEYS precedent in celerp.services.cost_visibility.
|
|
25
25
|
AMOUNT_ITEM_KEYS: frozenset[str] = frozenset({"quantity", "weight", "pieces", "gross_weight"})
|
|
26
26
|
|
|
27
|
+
# Fields whose edit is gated by edit_inventory_amounts. Superset of the numeric
|
|
28
|
+
# amount keys with sell_by added: changing the sell unit rewrites quantity, so it
|
|
29
|
+
# carries the same authority as editing an amount directly. Kept distinct from
|
|
30
|
+
# AMOUNT_ITEM_KEYS, which also drives the non-negative numeric validator on create
|
|
31
|
+
# and import - sell_by is a unit string and must never reach that float() path.
|
|
32
|
+
AMOUNT_EDIT_GATED_KEYS: frozenset[str] = AMOUNT_ITEM_KEYS | {"sell_by"}
|
|
33
|
+
|
|
34
|
+
# Schema-field keys for the canonical cost price list, stripped from /me/item-schema
|
|
35
|
+
# for callers without view_inventory_costs. Distinct from cost_visibility.COST_ITEM_KEYS,
|
|
36
|
+
# which names the item-DATA keys (cost_total, not the virtual schema key cost_price_total).
|
|
37
|
+
COST_SCHEMA_KEYS: frozenset[str] = frozenset({"cost_price", "cost_price_total"})
|
|
38
|
+
|
|
27
39
|
# Default price lists (used when company has none configured)
|
|
28
40
|
_DEFAULT_PRICE_LISTS: list[dict] = [
|
|
29
41
|
{"name": "Wholesale"},
|
|
@@ -49,7 +61,9 @@ _BASE_FIELDS: list[dict] = [
|
|
|
49
61
|
{"key": "pick_method", "label": "Stock Cutting", "type": "select", "editable": True, "required": False, "options": ["default", "fifo", "fefo", "lifo"], "visible_to_roles": [], "position": 4.6, "show_in_table": False, "tooltip_key": "field.tooltip.pick_method"},
|
|
50
62
|
{"key": "location_name", "label": "Location", "type": "text", "editable": False, "required": False, "options": [], "visible_to_roles": [], "position": 5, "show_in_table": True, "tooltip_key": "field.tooltip.location_name"},
|
|
51
63
|
# Price columns are injected dynamically at position 6+ by _inject_price_columns()
|
|
52
|
-
|
|
64
|
+
# Read-only: status changes only through dedicated actions (Make Available, Revert
|
|
65
|
+
# to Draft), never a free-form dropdown edit - same convention as document status.
|
|
66
|
+
{"key": "status", "label": "Status", "type": "status", "editable": False, "required": False, "options": [], "visible_to_roles": [], "position": 100, "show_in_table": True},
|
|
53
67
|
{"key": "short_description", "label": "Short Description", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 101, "show_in_table": False},
|
|
54
68
|
{"key": "description", "label": "Description", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 102, "show_in_table": False},
|
|
55
69
|
{"key": "notes", "label": "Notes", "type": "text", "editable": True, "required": False, "options": [], "visible_to_roles": [], "position": 103, "show_in_table": False},
|
|
@@ -112,6 +126,14 @@ def _inject_price_columns(base: list[dict], price_lists: list[dict]) -> list[dic
|
|
|
112
126
|
return sorted(base + price_cols, key=lambda f: f.get("position", 999))
|
|
113
127
|
|
|
114
128
|
|
|
129
|
+
def cost_columns(price_lists: list[dict]) -> list[dict]:
|
|
130
|
+
"""The cost schema columns (cost_price and its virtual total) generated for the given
|
|
131
|
+
price lists, empty if none is a cost list. Used to re-inject the cost fields that the
|
|
132
|
+
company-scoped /me/item-schema strips, for a draft whose cost is item-visible - the
|
|
133
|
+
single source the schema endpoint would have produced, never a hand-built copy."""
|
|
134
|
+
return [f for f in _inject_price_columns([], price_lists) if f.get("key") in COST_SCHEMA_KEYS]
|
|
135
|
+
|
|
136
|
+
|
|
115
137
|
# Backward-compatible constant: base fields + default price columns
|
|
116
138
|
DEFAULT_ITEM_SCHEMA: list[dict] = _inject_price_columns(_BASE_FIELDS, _DEFAULT_PRICE_LISTS)
|
|
117
139
|
|
|
@@ -154,6 +176,13 @@ async def get_effective_field_schema(
|
|
|
154
176
|
for f in base_schema
|
|
155
177
|
]
|
|
156
178
|
|
|
179
|
+
# Status is never a free-form dropdown, regardless of a stored schema round-trip
|
|
180
|
+
# captured before this became a hard rule.
|
|
181
|
+
base_schema = [
|
|
182
|
+
{**f, "editable": False, "options": []} if f["key"] == "status" else f
|
|
183
|
+
for f in base_schema
|
|
184
|
+
]
|
|
185
|
+
|
|
157
186
|
if category:
|
|
158
187
|
cat_schemas: dict[str, list[dict]] = settings.get("category_schemas") or {}
|
|
159
188
|
cat_fields: list[dict] = cat_schemas.get(category) or []
|