@startuml CrowdReport Class Relationships !define ENTITY class !define INTERFACE interface package "API Concept Layer" { INTERFACE CrowdReportInterface { +id: str +owner_id: str +type: str +name: str +status: str +created_at: timestamp +updated_at: timestamp +progress: int +options: dict +create(user, type, options, name) } ENTITY APIObject { +api_method() +error_codes() } package "Errors" { ENTITY errors.BadRequest ENTITY errors.FeatureNotSupported ENTITY errors.BadParameter ENTITY errors.MalformedSchedule } } package "Crowd Frontend Implementation" { ENTITY CrowdReport { +ID_REGEX: str +COLLECTION: Collection +MAX_REPORT_INTERVAL: int = 90 +MAX_WORK_TIME_REPORT_INTERVAL: int = 31 +MAX_REPORT_NAME_LEN: int = 60 +create(user, type, options, name) +delete() } ENTITY InitializerMixin { +_initialize(data) +COLLECTION +underscored_name() } ENTITY ReportCustomizer { +RESTRICTION_COLLECTION +_type: str +_required_fields: set +_allowed_fields: set +_registry: dict +for_type(report_type) +validate(options) +setup(query, options) +__init_subclass__() } ENTITY CrowdOverallStatsReportCustomizer { +_type = 'crowd_overall_stats_report' +_required_fields +_allowed_fields +setup(query, options) } ENTITY CrowdQueuesStatsReportCustomizer { +_type = 'crowd_queue_stats_report' +_required_fields +_allowed_fields +setup(query, options) } ENTITY CrowdWorkTimeReportCustomizer { +_type = 'crowd_work_time_report' +_required_fields +_allowed_fields +setup(query, options) } ENTITY QueryEnricher { +query: dict +start_time: int +end_time: int +options: dict +enrich() -_populate_time_condition() -_populate_sources() -_populate_step() -_populate_max_queue_size() -_populate_duration_from() } } package "Utilities & Helpers" { ENTITY api_helpers { +InitializerMixin +get_user_timezone(user) +schedule_parser(schedule) +get_default_schedule() +zone_settings_changed() } ENTITY validators { +validate_list_of_strings() +validate_schedule() +validate_time_range() +validate_limit() +validate_schedule_values() } ENTITY helpers { +get_user_zones(user_id, zone_ids) +_get_user_zones() } } package "Database & External" { ENTITY db { +reports() +user_reports +insert_with_random_id() } ENTITY time_tools { +DAY +to_seconds() } ENTITY pendulum { +from_timestamp() } } ' Inheritance relationships CrowdReportInterface <|-- CrowdReport APIObject <|-- CrowdReportInterface InitializerMixin <|-- CrowdReport ReportCustomizer <|-- CrowdOverallStatsReportCustomizer ReportCustomizer <|-- CrowdQueuesStatsReportCustomizer ReportCustomizer <|-- CrowdWorkTimeReportCustomizer ' Composition/Usage relationships CrowdReport ..> QueryEnricher : creates CrowdReport ..> ReportCustomizer : uses CrowdReport ..> db : persists to CrowdReport ..> time_tools : uses CrowdReport ..> pendulum : uses CrowdReport ..> api_helpers : uses get_user_timezone CrowdReport ..> helpers : uses get_user_zones QueryEnricher ..> validators : uses validate_list_of_strings QueryEnricher ..> helpers : uses get_user_zones ReportCustomizer ..> validators : uses validate_schedule CrowdReport --> errors.BadRequest : throws CrowdReport --> errors.FeatureNotSupported : throws ReportCustomizer --> errors.BadRequest : throws ReportCustomizer --> errors.FeatureNotSupported : throws ReportCustomizer --> errors.BadParameter : throws validators --> errors.BadRequest : throws validators --> errors.MalformedSchedule : throws ' Registry pattern ReportCustomizer : <> CrowdOverallStatsReportCustomizer ..> ReportCustomizer : auto-registers CrowdQueuesStatsReportCustomizer ..> ReportCustomizer : auto-registers CrowdWorkTimeReportCustomizer ..> ReportCustomizer : auto-registers note right of ReportCustomizer Uses __init_subclass__ for automatic subclass registration in _registry dictionary end note note right of CrowdReport Main report factory class. Validates inputs, creates queries, and persists report tasks to MongoDB. Maximum intervals: 90 days (regular), 31 days (work time reports) end note note right of QueryEnricher Builds MongoDB queries from user parameters, handles time ranges, zones, and filtering end note @enduml