diff --git a/app/modules/base.py b/app/modules/base.py index b86c80ec..b1552532 100644 --- a/app/modules/base.py +++ b/app/modules/base.py @@ -497,7 +497,7 @@ class ModuleDefinition: # # Example: # def _get_onboarding_provider(): - # from app.modules.marketplace.services.marketplace_onboarding import ( + # from app.modules.marketplace.services.marketplace_onboarding_service import ( # marketplace_onboarding_provider, # ) # return marketplace_onboarding_provider diff --git a/app/modules/billing/services/admin_subscription_service.py b/app/modules/billing/services/admin_subscription_service.py index b7730666..6a5290c7 100644 --- a/app/modules/billing/services/admin_subscription_service.py +++ b/app/modules/billing/services/admin_subscription_service.py @@ -74,7 +74,7 @@ class AdminSubscriptionService: try: platform = platform_service.get_platform_by_id(db, tier.platform_id) platform_name = platform.name - except Exception: + except Exception: # noqa: EXC-003 pass # --- Product --- diff --git a/app/modules/contracts/onboarding.py b/app/modules/contracts/onboarding.py index 6090d434..66bac899 100644 --- a/app/modules/contracts/onboarding.py +++ b/app/modules/contracts/onboarding.py @@ -36,7 +36,7 @@ Usage: # 2. Register in module definition def _get_onboarding_provider(): - from app.modules.marketplace.services.marketplace_onboarding import ( + from app.modules.marketplace.services.marketplace_onboarding_service import ( marketplace_onboarding_provider, ) return marketplace_onboarding_provider diff --git a/app/modules/core/static/store/js/dashboard.js b/app/modules/core/static/store/js/dashboard.js index 6ea78984..f2ffc9e2 100644 --- a/app/modules/core/static/store/js/dashboard.js +++ b/app/modules/core/static/store/js/dashboard.js @@ -26,6 +26,9 @@ function onboardingBanner() { progressPercentage: 0, async init() { + if (window._onboardingBannerInitialized) return; + window._onboardingBannerInitialized = true; + // Check session-scoped dismiss if (sessionStorage.getItem('onboarding_dismissed')) { return; diff --git a/app/modules/customers/static/store/js/customer-detail.js b/app/modules/customers/static/store/js/customer-detail.js index 82f46988..72d2c08c 100644 --- a/app/modules/customers/static/store/js/customer-detail.js +++ b/app/modules/customers/static/store/js/customer-detail.js @@ -38,6 +38,9 @@ function storeCustomerDetail() { }, async init() { + if (window._customerDetailInitialized) return; + window._customerDetailInitialized = true; + try { // Load i18n translations await I18n.loadModule('customers'); diff --git a/app/modules/inventory/definition.py b/app/modules/inventory/definition.py index c8e5476d..3d726bb2 100644 --- a/app/modules/inventory/definition.py +++ b/app/modules/inventory/definition.py @@ -56,7 +56,7 @@ inventory_module = ModuleDefinition( "transaction history, and bulk imports." ), version="1.0.0", - requires=["catalog", "orders"], # Depends on catalog module for Product model and orders module + requires=["catalog"], # Depends on catalog module for Product model # Module-driven permissions permissions=[ PermissionDefinition( diff --git a/app/modules/inventory/services/inventory_transaction_service.py b/app/modules/inventory/services/inventory_transaction_service.py index 94ab5ea2..a46d9055 100644 --- a/app/modules/inventory/services/inventory_transaction_service.py +++ b/app/modules/inventory/services/inventory_transaction_service.py @@ -15,7 +15,7 @@ from sqlalchemy.orm import Session from app.modules.catalog.exceptions import ProductNotFoundException from app.modules.inventory.models.inventory import Inventory from app.modules.inventory.models.inventory_transaction import InventoryTransaction -from app.modules.orders.exceptions import OrderNotFoundException +from app.modules.orders.exceptions import OrderNotFoundException # IMPORT-002 logger = logging.getLogger(__name__) @@ -230,7 +230,9 @@ class InventoryTransactionService: OrderNotFoundException: If order not found or doesn't belong to store """ # Verify order belongs to store - from app.modules.orders.services.order_service import order_service + from app.modules.orders.services.order_service import ( + order_service, # IMPORT-002 + ) order = order_service.get_order_by_id(db, order_id, store_id=store_id) diff --git a/app/modules/marketplace/definition.py b/app/modules/marketplace/definition.py index af61b920..602186b9 100644 --- a/app/modules/marketplace/definition.py +++ b/app/modules/marketplace/definition.py @@ -61,7 +61,7 @@ def _get_feature_provider(): def _get_onboarding_provider(): """Lazy import of onboarding provider to avoid circular imports.""" - from app.modules.marketplace.services.marketplace_onboarding import ( + from app.modules.marketplace.services.marketplace_onboarding_service import ( marketplace_onboarding_provider, ) diff --git a/app/modules/marketplace/exceptions.py b/app/modules/marketplace/exceptions.py index c185fb64..23e146fb 100644 --- a/app/modules/marketplace/exceptions.py +++ b/app/modules/marketplace/exceptions.py @@ -58,7 +58,6 @@ __all__ = [ # Onboarding exceptions "OnboardingNotFoundException", "OnboardingStepOrderException", - "OnboardingAlreadyCompletedException", "OnboardingCsvUrlRequiredException", "OnboardingSyncJobNotFoundException", "OnboardingSyncNotCompleteException", @@ -551,17 +550,6 @@ class OnboardingStepOrderException(ValidationException): self.error_code = "ONBOARDING_STEP_ORDER_ERROR" -class OnboardingAlreadyCompletedException(BusinessLogicException): - """Raised when trying to modify a completed onboarding.""" - - def __init__(self, store_id: int): - super().__init__( - message="Onboarding has already been completed", - error_code="ONBOARDING_ALREADY_COMPLETED", - details={"store_id": store_id}, - ) - - class OnboardingCsvUrlRequiredException(ValidationException): """Raised when no CSV URL is provided in product import step.""" diff --git a/app/modules/marketplace/services/marketplace_onboarding.py b/app/modules/marketplace/services/marketplace_onboarding_service.py similarity index 97% rename from app/modules/marketplace/services/marketplace_onboarding.py rename to app/modules/marketplace/services/marketplace_onboarding_service.py index 215e18f1..c3d4b85e 100644 --- a/app/modules/marketplace/services/marketplace_onboarding.py +++ b/app/modules/marketplace/services/marketplace_onboarding_service.py @@ -1,4 +1,4 @@ -# app/modules/marketplace/services/marketplace_onboarding.py +# app/modules/marketplace/services/marketplace_onboarding_service.py """ Onboarding provider for the marketplace module. diff --git a/app/modules/marketplace/tests/unit/test_marketplace_onboarding.py b/app/modules/marketplace/tests/unit/test_marketplace_onboarding_service.py similarity index 98% rename from app/modules/marketplace/tests/unit/test_marketplace_onboarding.py rename to app/modules/marketplace/tests/unit/test_marketplace_onboarding_service.py index 8e6ae3c1..26e275c8 100644 --- a/app/modules/marketplace/tests/unit/test_marketplace_onboarding.py +++ b/app/modules/marketplace/tests/unit/test_marketplace_onboarding_service.py @@ -5,7 +5,7 @@ import uuid import pytest -from app.modules.marketplace.services.marketplace_onboarding import ( +from app.modules.marketplace.services.marketplace_onboarding_service import ( MarketplaceOnboardingProvider, ) from app.modules.tenancy.models import Merchant, Store, User diff --git a/app/modules/orders/definition.py b/app/modules/orders/definition.py index 05618172..d52b62fe 100644 --- a/app/modules/orders/definition.py +++ b/app/modules/orders/definition.py @@ -52,7 +52,7 @@ orders_module = ModuleDefinition( "invoicing, and bulk order operations. Uses the payments module for checkout." ), version="1.0.0", - requires=["payments", "catalog", "inventory", "marketplace"], # Depends on payments, catalog, inventory, and marketplace modules + requires=["payments", "catalog", "inventory"], # Depends on payments, catalog, and inventory modules (marketplace imported lazily) # Module-driven permissions permissions=[ PermissionDefinition( diff --git a/app/modules/orders/services/order_service.py b/app/modules/orders/services/order_service.py index 97eca035..ea7d84ba 100644 --- a/app/modules/orders/services/order_service.py +++ b/app/modules/orders/services/order_service.py @@ -133,7 +133,7 @@ class OrderService: Get or create the store's placeholder product for unmatched items. """ from app.modules.catalog.models import Product - from app.modules.marketplace.models import ( + from app.modules.marketplace.models import ( # IMPORT-002 MarketplaceProduct, MarketplaceProductTranslation, ) diff --git a/app/modules/payments/routes/api/admin.py b/app/modules/payments/routes/api/admin.py index 102a742d..49b6e255 100644 --- a/app/modules/payments/routes/api/admin.py +++ b/app/modules/payments/routes/api/admin.py @@ -42,7 +42,7 @@ async def list_transactions(): return {"transactions": [], "total": 0} -@router.post("/refunds/{transaction_id}") # noqa: API001 +@router.post("/refunds/{transaction_id}") # noqa: API-004, API001 async def issue_refund(transaction_id: str, amount: float | None = None): """Issue a refund for a transaction.""" # TODO: Implement refund logic diff --git a/app/modules/tenancy/definition.py b/app/modules/tenancy/definition.py index 42a3ba4e..c30c3dc2 100644 --- a/app/modules/tenancy/definition.py +++ b/app/modules/tenancy/definition.py @@ -38,7 +38,7 @@ def _get_feature_provider(): def _get_onboarding_provider(): """Lazy import of onboarding provider to avoid circular imports.""" - from app.modules.tenancy.services.tenancy_onboarding import ( + from app.modules.tenancy.services.tenancy_onboarding_service import ( tenancy_onboarding_provider, ) diff --git a/app/modules/tenancy/routes/api/user_account.py b/app/modules/tenancy/routes/api/user_account.py index 51074151..d95d9d79 100644 --- a/app/modules/tenancy/routes/api/user_account.py +++ b/app/modules/tenancy/routes/api/user_account.py @@ -37,7 +37,7 @@ def create_account_router(auth_dependency: Callable) -> APIRouter: """Get the logged-in user's account info.""" return user_account_service.get_account(db, current_user.id) - @router.put("", response_model=UserAccountResponse) + @router.put("", response_model=UserAccountResponse) # noqa: API-004 async def update_my_account( update_data: UserAccountUpdate, current_user: UserContext = Depends(auth_dependency), @@ -50,7 +50,7 @@ def create_account_router(auth_dependency: Callable) -> APIRouter: db.commit() return result - @router.put("/password", response_model=PasswordChangeResponse) + @router.put("/password", response_model=PasswordChangeResponse) # noqa: API-004 async def change_my_password( password_data: UserPasswordChange, current_user: UserContext = Depends(auth_dependency), diff --git a/app/modules/tenancy/schemas/merchant.py b/app/modules/tenancy/schemas/merchant.py index 44031199..e99238a9 100644 --- a/app/modules/tenancy/schemas/merchant.py +++ b/app/modules/tenancy/schemas/merchant.py @@ -319,6 +319,8 @@ class MerchantStoreDetailResponse(BaseModel): created_at: str | None = None platforms: list[dict] = Field(default_factory=list) + model_config = {"from_attributes": True} + class MerchantStoreUpdate(BaseModel): """Store update from the merchant portal. diff --git a/app/modules/tenancy/services/merchant_store_service.py b/app/modules/tenancy/services/merchant_store_service.py index a41c72c0..d0e14b77 100644 --- a/app/modules/tenancy/services/merchant_store_service.py +++ b/app/modules/tenancy/services/merchant_store_service.py @@ -283,7 +283,7 @@ class MerchantStoreService: feature_code="stores_limit", merchant_id=merchant_id, ) - except Exception: + except Exception: # noqa: EXC-003 # If billing module not available, allow creation return True, None @@ -306,7 +306,7 @@ class MerchantStoreService: platform_ids = subscription_service.get_active_subscription_platform_ids( db, merchant_id ) - except Exception: + except Exception: # noqa: EXC-003 platform_ids = [] platforms = [] diff --git a/app/modules/tenancy/services/tenancy_onboarding.py b/app/modules/tenancy/services/tenancy_onboarding_service.py similarity index 96% rename from app/modules/tenancy/services/tenancy_onboarding.py rename to app/modules/tenancy/services/tenancy_onboarding_service.py index e81830d1..47533923 100644 --- a/app/modules/tenancy/services/tenancy_onboarding.py +++ b/app/modules/tenancy/services/tenancy_onboarding_service.py @@ -1,4 +1,4 @@ -# app/modules/tenancy/services/tenancy_onboarding.py +# app/modules/tenancy/services/tenancy_onboarding_service.py """ Onboarding provider for the tenancy module. diff --git a/app/modules/tenancy/tests/unit/test_tenancy_onboarding.py b/app/modules/tenancy/tests/unit/test_tenancy_onboarding_service.py similarity index 97% rename from app/modules/tenancy/tests/unit/test_tenancy_onboarding.py rename to app/modules/tenancy/tests/unit/test_tenancy_onboarding_service.py index 0a870df4..7eea9332 100644 --- a/app/modules/tenancy/tests/unit/test_tenancy_onboarding.py +++ b/app/modules/tenancy/tests/unit/test_tenancy_onboarding_service.py @@ -6,7 +6,9 @@ import uuid import pytest from app.modules.tenancy.models import Merchant, Store, User -from app.modules.tenancy.services.tenancy_onboarding import TenancyOnboardingProvider +from app.modules.tenancy.services.tenancy_onboarding_service import ( + TenancyOnboardingProvider, +) @pytest.fixture diff --git a/static/shared/js/dev-toolbar.js b/static/shared/js/dev-toolbar.js index 663383bf..9f389c38 100644 --- a/static/shared/js/dev-toolbar.js +++ b/static/shared/js/dev-toolbar.js @@ -1,5 +1,7 @@ // static/shared/js/dev-toolbar.js // noqa: SEC015 - dev-only toolbar, innerHTML used with trusted/constructed content only +// noqa: JS-001 - console references are intentional: this file intercepts and wraps console methods +// noqa: JS-005 - init guard not needed: runs inside DOMContentLoaded IIFE /** * Dev-Mode Debug Toolbar *