export type WorkType = "support" | "consulting"; export type BillingStatus = "billed" | "non_billable" | null; export type PeriodType = "month" | "day"; export type TicketDetailPeriodType = PeriodType | "all"; export type UserRole = "admin" | "user"; export type AuthUser = { id: string; username: string; display_name: string; role: UserRole; active: boolean; }; export type AdminUser = AuthUser & { created_at: string; updated_at: string; }; export type Organization = { id: string; zammad_id: string; name: string; synced_at: string; }; export type RecurringBillingSlot = { id?: string; weekday: number | null; start_time: string | null; duration_minutes: number; }; export type RecurringBilling = { id: string; user_id: string; owner_username: string; owner_display_name: string; ticket_number: string; configured_ticket_number: string | null; organization_id: string; organization_name: string; activity: string; work_type: WorkType; recurrence_type: "weekly" | "every_n_weeks"; interval_value: number; valid_from: string; valid_until: string | null; start_time: string; active: boolean; created_at: string; updated_at: string; slots: RecurringBillingSlot[]; }; export type TicketMeta = { id: string; ticket_number: string; organization_id: string | null; organization_name: string | null; customer_name: string | null; work_type: WorkType | null; }; export type TicketSearchResult = { ticket_id: string; ticket_number: string; organization_id: string | null; organization_name: string | null; customer_name: string | null; work_type: WorkType | null; latest_started_at: string; latest_period: string; session_count: number; total_minutes: number; }; export type TicketSummary = { id: string; ticket_number: string; organization_id: string | null; organization_name: string | null; customer_name: string | null; work_type: WorkType | null; session_count: number; total_minutes: number; non_billable_minutes: number; open_minutes: number; open_count: number; ticket_open_count: number; billed_count: number; non_billable_count: number; recurring_session_count: number; manual_session_count: number; requires_closure: boolean; closed: boolean; closed_at: string | null; }; export type OpenSession = { id: string; ticket_id: string; ticket_number: string; organization_id: string | null; organization_name: string | null; customer_name: string; activity: string; work_type: WorkType; started_at: string; rounded_minutes: number; }; export type ActivityBucket = { bucket_key: string; session_count: number; total_minutes: number; }; export type PeriodOverview = { periodType: PeriodType; period: string; closed: boolean; closedAt: string | null; canClose: boolean; totals: { tickets: number; sessions: number; minutes: number; crmBilledMinutes: number; nonBillableMinutes: number; openMinutes: number; openSessions: number; }; tickets: TicketSummary[]; openSessions: OpenSession[]; activitySeries: ActivityBucket[]; }; export type TicketDayBilling = { day: string; billed_minutes: number; }; export type TicketAvailableMonth = { month: string; session_count: number; }; export type SessionEntry = { id: string; organization_id: string | null; organization_name: string | null; customer_name: string; activity: string; work_type: WorkType; started_at: string; ended_at: string; duration_seconds: number; rounded_minutes: number; billing_status: BillingStatus; billing_updated_at: string | null; created_at: string; recurring_billing_id: string | null; recurring_billing_slot_id: string | null; recurring_occurrence_date: string | null; }; export type TicketPeriod = { periodType: TicketDetailPeriodType; period: string; closed: boolean; closedAt: string | null; filters?: { month: string; status: "all" | "open" | "billed" | "non_billable"; source: "all" | "manual" | "recurring"; }; availableMonths?: TicketAvailableMonth[]; ticket: { id: string; ticket_number: string; organization_id: string | null; organization_name: string | null; customer_name: string | null; work_type: WorkType | null; closed_at: string | null; requires_closure: boolean; recurring_session_count: number; manual_session_count: number; }; sessions: SessionEntry[]; dayBillings: TicketDayBilling[]; canClose: boolean; openCount: number; ticketOpenCount: number; }; export type MonthOverview = PeriodOverview; export type TicketMonth = TicketPeriod; export type StatisticsDailyBucket = { day: string; sessions: number; total_minutes: number; billed_minutes: number; non_billable_minutes: number; open_minutes: number; billed_sessions: number; non_billable_sessions: number; open_sessions: number; crm_billed_minutes: number; }; export type StatisticsGroup = { organization_id?: string | null; organization_name?: string; work_type?: WorkType; tickets: number; sessions: number; total_minutes: number; billed_minutes: number; non_billable_minutes: number; open_minutes: number; billed_sessions: number; non_billable_sessions: number; open_sessions: number; crm_billed_minutes: number; crm_delta_minutes: number; }; export type StatisticsTicket = { ticket_id: string; ticket_number: string; organization_id: string | null; organization_name: string; active_days: number; sessions: number; total_minutes: number; billed_minutes: number; non_billable_minutes: number; open_minutes: number; billed_sessions: number; non_billable_sessions: number; open_sessions: number; crm_billed_minutes: number; crm_delta_minutes: number; }; export type StatisticsOpenSession = { id: string; ticket_id: string; ticket_number: string; organization_name: string; activity: string; started_at: string; rounded_minutes: number; }; export type StatisticsCrmDay = { ticket_id: string; ticket_number: string; organization_name: string; day: string; tracked_minutes: number; crm_billed_minutes: number; delta_minutes?: number; acknowledged?: boolean; acknowledged_at?: string | null; }; export type StatisticsOverview = { periodType: "month"; period: string; closed: boolean; closedAt: string | null; totals: { tickets: number; sessions: number; minutes: number; billedMinutes: number; nonBillableMinutes: number; openMinutes: number; billedSessions: number; nonBillableSessions: number; openSessions: number; recurringMinutes: number; manualMinutes: number; recurringSessions: number; manualSessions: number; averageSessionMinutes: number; activeDays: number; crmBilledMinutes: number; crmDeltaMinutes: number; }; dailySeries: StatisticsDailyBucket[]; organizations: StatisticsGroup[]; workTypes: StatisticsGroup[]; tickets: StatisticsTicket[]; attention: { openSessions: StatisticsOpenSession[]; missingCrmDays: StatisticsCrmDay[]; acknowledgedMissingCrmDays: StatisticsCrmDay[]; crmMismatches: StatisticsCrmDay[]; }; };