306 lines
7.1 KiB
TypeScript
306 lines
7.1 KiB
TypeScript
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[];
|
|
};
|
|
};
|