1.1.0-rc1

This commit is contained in:
michael committed 2026-10-13 10:43:53 +02:00
1 parent 649dd6f028
commit 45ff46b7eb
26 files changed
+4752 -1108

No files matched your search

+83 -10
View File
@@ -134,11 +134,35 @@ export type TeamspaceProjectIdSyncItem = {
previousApiProjectId: string | null;
apiProjectId: string | null;
apiProjectUrl: string | null;
status: "updated" | "current" | "missing" | "ambiguous";
ttMonthBillableMinutes: number;
teamspaceMonthMinutes: number;
teamspaceMonthBillableMinutes: number;
teamspaceMonthEntryCount: number;
teamspaceMonthDeltaMinutes: number;
teamspaceMonthPositions: TeamspaceProjectIdSyncPosition[];
status: "updated" | "current" | "missing" | "ambiguous" | "excluded";
message: string | null;
};
export type TeamspaceProjectIdSyncPosition = {
apiProjectId: string;
projectId: string | null;
label: string;
isSubentry: boolean;
billingType?: string | null;
minutes: number;
billableMinutes: number;
entryCount: number;
days?: Array<{
day: string;
minutes: number;
billableMinutes: number;
entryCount: number;
}>;
};
export type TeamspaceProjectIdSyncResult = {
month: string;
checkedEntries: number;
matched: number;
updated: number;
@@ -151,6 +175,10 @@ export type TeamspaceProjectIdSyncResult = {
remoteSubprojectsScanned: number;
subentriesSynced: number;
subentriesRemoved: number;
teamspaceTimeEntriesScanned: number;
teamspaceTimeEntriesMapped: number;
teamspaceTimeBillableMinutes: number;
teamspaceTimeDeltaMinutes: number;
duplicateRemoteProjectIds: string[];
items: TeamspaceProjectIdSyncItem[];
};
@@ -161,6 +189,10 @@ export type TeamspaceProjectSubentrySyncResult = {
remoteProjectsScanned: number;
subentriesSynced: number;
subentriesRemoved: number;
monthsSynced: string[];
teamspaceTimeEntriesScanned: number;
teamspaceTimeEntriesMapped: number;
teamspaceTimeBillableMinutes: number;
};
export type TeamspaceAllSubentrySyncResult = {
@@ -482,16 +514,34 @@ export function saveZammadSettings(payload: { baseUrl: string; apiKey?: string }
}
export function getTeamspaceSettings() {
return request<{ settings: { baseUrl: string } }>("/api/admin/teamspace/settings");
return request<{ settings: { baseUrl: string; credentialsUserId: string | null } }>("/api/admin/teamspace/settings");
}
export function saveTeamspaceSettings(payload: { baseUrl: string }) {
return request<{ settings: { baseUrl: string } }>("/api/admin/teamspace/settings", {
export function saveTeamspaceSettings(payload: { baseUrl: string; credentialsUserId?: string | null }) {
return request<{ settings: { baseUrl: string; credentialsUserId: string | null } }>("/api/admin/teamspace/settings", {
method: "PUT",
body: JSON.stringify(payload)
});
}
export type TeamspaceProjectExclusion = {
teamspace_project: string;
teamspace_name: string | null;
customer_name: string | null;
note: string;
};
export function getTeamspaceProjectExclusions() {
return request<{ exclusions: TeamspaceProjectExclusion[] }>("/api/admin/teamspace/project-exclusions");
}
export function saveTeamspaceProjectExclusions(projects: string[]) {
return request<{ exclusions: TeamspaceProjectExclusion[] }>("/api/admin/teamspace/project-exclusions", {
method: "PUT",
body: JSON.stringify({ projects })
});
}
export function syncZammadOrganizations(payload: { baseUrl?: string; apiKey?: string }) {
return request<{ synced: number; skipped: number; removed: number; unlinkedTickets: number; unlinkedSessions: number }>("/api/admin/zammad/organizations/sync", {
method: "POST",
@@ -538,25 +588,46 @@ async function runZammadSyncJob(url: string, body: Record<string, unknown>, onJo
return { jobId: job.id, result };
}
export async function syncExistingZammadTickets(fields: ZammadSyncExistingFields, options: { dryRun?: boolean; ticketNumbers?: string[] } = {}) {
export async function syncExistingZammadTickets(fields: ZammadSyncExistingFields, options: { dryRun?: boolean; ticketNumbers?: string[] } = {}, onJobStarted?: (job: ZammadSyncJob) => void) {
const { result } = await runZammadSyncJob("/api/zammad-sync/jobs/existing", {
fields,
dryRun: options.dryRun ?? true,
ticketNumbers: options.ticketNumbers
});
}, onJobStarted);
return result;
}
export async function importOwnZammadConsultingTickets(options: { dryRun?: boolean; ticketNumbers?: string[] } = {}) {
export async function importOwnZammadConsultingTickets(options: { dryRun?: boolean; ticketNumbers?: string[] } = {}, onJobStarted?: (job: ZammadSyncJob) => void) {
const { result } = await runZammadSyncJob("/api/zammad-sync/jobs/consulting-import", {
dryRun: options.dryRun ?? true,
ticketNumbers: options.ticketNumbers
});
}, onJobStarted);
return result;
}
export function syncExistingZammadTicketsDirect(fields: ZammadSyncExistingFields, onJobStarted?: (job: ZammadSyncJob) => void) {
return runZammadSyncJob("/api/zammad-sync/jobs/existing", {
fields,
dryRun: false
}, onJobStarted);
}
export function importOwnZammadConsultingTicketsDirect(onJobStarted?: (job: ZammadSyncJob) => void) {
return runZammadSyncJob("/api/zammad-sync/jobs/consulting-import", {
dryRun: false
}, onJobStarted);
}
export function syncZammadMailSessionsDirect(daysBack: number, perPage: number, onJobStarted?: (job: ZammadSyncJob) => void) {
return runZammadSyncJob("/api/zammad-sync/jobs/mail-sessions", {
dryRun: false,
daysBack,
perPage
}, onJobStarted);
}
export function previewExistingZammadTickets(fields: ZammadSyncExistingFields, onJobStarted?: (job: ZammadSyncJob) => void) {
return runZammadSyncJob("/api/zammad-sync/jobs/existing", {
fields,
@@ -597,16 +668,18 @@ export function applyZammadMailSessionsFromPreview(previewJobId: string, article
}, onJobStarted);
}
export function syncTeamspaceProjectIds() {
export function syncTeamspaceProjectIds(month?: string) {
return request<{ result: TeamspaceProjectIdSyncResult }>("/api/teamspace/project-ids/sync", {
method: "POST",
body: JSON.stringify(month ? { month } : {}),
timeoutMs: 5 * 60 * 1000
});
}
export function syncProjectTeamspaceSubentries(projectId: string) {
export function syncProjectTeamspaceSubentries(projectId: string, months?: string[]) {
return request<{ result: TeamspaceProjectSubentrySyncResult }>(`/api/projects/${projectId}/teamspace-subentries/sync`, {
method: "POST",
body: JSON.stringify(months?.length ? { months } : {}),
timeoutMs: 5 * 60 * 1000
});
}