# app/modules/loyalty/definition.py """ Loyalty module definition. Defines the loyalty module including its features, menu items, route configurations, and scheduled tasks. """ from app.modules.base import ( MenuItemDefinition, MenuSectionDefinition, ModuleDefinition, PermissionDefinition, ScheduledTask, ) from app.modules.enums import FrontendType def _get_admin_router(): """Lazy import of admin router to avoid circular imports.""" from app.modules.loyalty.routes.api.admin import admin_router return admin_router def _get_merchant_router(): """Lazy import of merchant router to avoid circular imports.""" from app.modules.loyalty.routes.api.merchant import router as merchant_router return merchant_router def _get_store_router(): """Lazy import of store router to avoid circular imports.""" from app.modules.loyalty.routes.api.store import store_router return store_router def _get_platform_router(): """Lazy import of platform router to avoid circular imports.""" from app.modules.loyalty.routes.api.platform import platform_router return platform_router def _get_storefront_router(): """Lazy import of storefront router to avoid circular imports.""" from app.modules.loyalty.routes.api.storefront import storefront_router return storefront_router def _get_feature_provider(): """Lazy import of feature provider to avoid circular imports.""" from app.modules.loyalty.services.loyalty_features import loyalty_feature_provider return loyalty_feature_provider # Loyalty module definition loyalty_module = ModuleDefinition( code="loyalty", name="Loyalty Programs", description=( "Stamp-based and points-based loyalty programs with Google Wallet " "and Apple Wallet integration. Includes anti-fraud features like " "staff PINs, cooldown periods, and daily limits." ), version="1.0.0", requires=["customers"], # Depends on customers module for customer data features=[ # Core features "loyalty_stamps", # Stamp-based loyalty "loyalty_points", # Points-based loyalty "loyalty_hybrid", # Both stamps and points # Card management "loyalty_cards", # Customer card management "loyalty_enrollment", # Customer enrollment # Staff/fraud prevention "loyalty_staff_pins", # Staff PIN management "loyalty_anti_fraud", # Cooldown, daily limits # Wallet integration "loyalty_google_wallet", # Google Wallet passes "loyalty_apple_wallet", # Apple Wallet passes # Analytics "loyalty_stats", # Dashboard statistics "loyalty_reports", # Transaction reports ], # Module-driven permissions permissions=[ PermissionDefinition( id="loyalty.view_programs", label_key="loyalty.permissions.view_programs", description_key="loyalty.permissions.view_programs_desc", category="loyalty", ), PermissionDefinition( id="loyalty.manage_programs", label_key="loyalty.permissions.manage_programs", description_key="loyalty.permissions.manage_programs_desc", category="loyalty", ), PermissionDefinition( id="loyalty.view_rewards", label_key="loyalty.permissions.view_rewards", description_key="loyalty.permissions.view_rewards_desc", category="loyalty", ), PermissionDefinition( id="loyalty.manage_rewards", label_key="loyalty.permissions.manage_rewards", description_key="loyalty.permissions.manage_rewards_desc", category="loyalty", ), ], menu_items={ FrontendType.ADMIN: [ "loyalty-programs", # View all programs "loyalty-analytics", # Platform-wide stats ], FrontendType.STORE: [ "loyalty", # Loyalty dashboard "loyalty-cards", # Customer cards "loyalty-stats", # Store stats ], FrontendType.MERCHANT: [ "loyalty-overview", # Merchant loyalty overview "loyalty-settings", # Merchant loyalty settings ], }, # New module-driven menu definitions menus={ FrontendType.ADMIN: [ MenuSectionDefinition( id="loyalty", label_key="loyalty.menu.loyalty", icon="gift", order=55, items=[ MenuItemDefinition( id="loyalty-programs", label_key="loyalty.menu.programs", icon="gift", route="/admin/loyalty/programs", order=10, ), MenuItemDefinition( id="loyalty-analytics", label_key="loyalty.menu.analytics", icon="chart-bar", route="/admin/loyalty/analytics", order=20, ), ], ), ], FrontendType.STORE: [ MenuSectionDefinition( id="loyalty", label_key="loyalty.menu.loyalty_programs", icon="gift", order=35, items=[ MenuItemDefinition( id="terminal", label_key="loyalty.menu.terminal", icon="gift", route="/store/{store_code}/loyalty/terminal", order=10, ), MenuItemDefinition( id="cards", label_key="loyalty.menu.customer_cards", icon="identification", route="/store/{store_code}/loyalty/cards", order=20, ), MenuItemDefinition( id="stats", label_key="loyalty.menu.statistics", icon="chart-bar", route="/store/{store_code}/loyalty/stats", order=30, ), ], ), ], FrontendType.MERCHANT: [ MenuSectionDefinition( id="loyalty", label_key="loyalty.menu.loyalty", icon="gift", order=60, items=[ MenuItemDefinition( id="loyalty-overview", label_key="loyalty.menu.overview", icon="gift", route="/merchants/loyalty/overview", order=10, ), MenuItemDefinition( id="loyalty-settings", label_key="loyalty.menu.settings", icon="cog", route="/merchants/loyalty/settings", order=20, ), ], ), ], FrontendType.STOREFRONT: [ MenuSectionDefinition( id="account", label_key=None, order=10, items=[ MenuItemDefinition( id="loyalty", label_key="storefront.account.loyalty", icon="gift", route="account/loyalty", order=60, ), ], ), ], }, is_core=False, # Loyalty can be disabled # ========================================================================= # Self-Contained Module Configuration # ========================================================================= is_self_contained=True, services_path="app.modules.loyalty.services", models_path="app.modules.loyalty.models", schemas_path="app.modules.loyalty.schemas", exceptions_path="app.modules.loyalty.exceptions", tasks_path="app.modules.loyalty.tasks", migrations_path="migrations", # ========================================================================= # Scheduled Tasks # ========================================================================= scheduled_tasks=[ ScheduledTask( name="loyalty.sync_wallet_passes", task="app.modules.loyalty.tasks.wallet_sync.sync_wallet_passes", schedule="0 * * * *", # Hourly options={"queue": "scheduled"}, ), ScheduledTask( name="loyalty.expire_points", task="app.modules.loyalty.tasks.point_expiration.expire_points", schedule="0 2 * * *", # Daily at 02:00 options={"queue": "scheduled"}, ), ], # Feature provider for billing feature gating feature_provider=_get_feature_provider, ) def get_loyalty_module_with_routers() -> ModuleDefinition: """ Get loyalty module with routers attached. This function attaches the routers lazily to avoid circular imports during module initialization. """ loyalty_module.admin_router = _get_admin_router() loyalty_module.merchant_router = _get_merchant_router() loyalty_module.store_router = _get_store_router() loyalty_module.platform_router = _get_platform_router() loyalty_module.storefront_router = _get_storefront_router() return loyalty_module __all__ = ["loyalty_module", "get_loyalty_module_with_routers"]