import api from './client' import type { Product } from './products' import type { OutputType } from './outputTypes' export interface RenderLog { renderer?: string type?: string format?: string engine?: string engine_used?: string samples?: number smooth_angle?: number total_duration_s?: number stl_duration_s?: number render_duration_s?: number ffmpeg_duration_s?: number stl_size_bytes?: number output_size_bytes?: number parts_count?: number device_used?: string compute_type?: string gpu_fallback?: boolean frame_count?: number fps?: number template?: string lighting_only?: boolean shadow_catcher?: boolean material_replace?: boolean fallback?: boolean error?: string started_at?: string completed_at?: string log_lines?: string[] } export interface OrderLine { id: string order_id: string product_id: string product: Product output_type_id: string | null output_type: OutputType | null gewuenschte_bildnummer: string | null item_status: 'pending' | 'approved' | 'rejected' render_status: 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled' result_path: string | null thumbnail_url: string | null ai_validation_status: string ai_validation_result: Record | null render_backend_used: string | null flamenco_job_id: string | null unit_price: number | null render_position_id: string | null render_position_name: string | null render_log: RenderLog | null render_started_at: string | null render_completed_at: string | null material_override: string | null render_overrides: Record | null notes: string | null created_at: string updated_at: string } export interface OrderLineCreate { product_id: string output_type_id?: string | null render_position_id?: string | null global_render_position_id?: string | null gewuenschte_bildnummer?: string | null material_override?: string | null render_overrides?: Record | null notes?: string | null } export interface Order { id: string order_number: string template_id: string | null status: 'draft' | 'submitted' | 'processing' | 'completed' | 'rejected' created_by: string source_excel: string | null notes: string | null created_at: string updated_at: string submitted_at: string | null completed_at: string | null rejected_at: string | null rejection_reason: string | null estimated_price: number | null item_count: number line_count: number render_progress: { total: number completed: number processing: number failed: number pending: number cancelled: number } | null } export interface OrderItem { id: string order_id: string row_index: number ebene1: string | null ebene2: string | null baureihe: string | null pim_id: string | null produkt_baureihe: string | null gewaehltes_produkt: string | null name_cad_modell: string | null gewuenschte_bildnummer: string | null lagertyp: string | null medias_rendering: boolean | null components: Array<{ part_name: string | null; material: string | null; component_type: string | null; column_index: number }> cad_file_id: string | null thumbnail_path: string | null ai_validation_status: string ai_validation_result: Record | null cad_parsed_objects: string[] | null cad_part_materials: Array<{ part_name: string; material: string }> item_status: 'pending' | 'approved' | 'rejected' notes: string | null created_at: string } export interface OrderDetail extends Order { items: OrderItem[] lines: OrderLine[] } export async function listOrders(params?: { status?: string; skip?: number; limit?: number }) { const res = await api.get('/orders', { params }) return res.data } export async function searchOrders(params: { q?: string statuses?: string[] date_from?: string date_to?: string limit?: number }): Promise { const res = await api.get('/orders/search', { params: { q: params.q || '', statuses: params.statuses?.join(',') || '', date_from: params.date_from || '', date_to: params.date_to || '', limit: params.limit || 50, }, }) return res.data } export async function getOrder(id: string) { const res = await api.get(`/orders/${id}`) return res.data } export async function patchOrderItem( orderId: string, itemId: string, patch: Partial<{ ebene1: string | null ebene2: string | null baureihe: string | null pim_id: string | null produkt_baureihe: string | null gewaehltes_produkt: string | null name_cad_modell: string | null gewuenschte_bildnummer: string | null lagertyp: string | null medias_rendering: boolean | null notes: string | null }>, ) { const res = await api.patch(`/orders/${orderId}/items/${itemId}`, patch) return res.data } export async function createOrder(data: { template_id?: string source_excel?: string notes?: string items?: Array<{ row_index: number ebene1?: string | null ebene2?: string | null baureihe?: string | null pim_id?: string | null produkt_baureihe?: string | null gewaehltes_produkt?: string | null name_cad_modell?: string | null gewuenschte_bildnummer?: string | null lagertyp?: string | null medias_rendering?: boolean | null components: Array<{ part_name?: string | null; material?: string | null; component_type?: string | null; column_index: number }> }> lines?: OrderLineCreate[] }) { const res = await api.post('/orders', data) return res.data } export async function addOrderLine(orderId: string, data: OrderLineCreate): Promise { const res = await api.post(`/orders/${orderId}/lines`, data) return res.data } export async function removeOrderLine(orderId: string, lineId: string): Promise { await api.delete(`/orders/${orderId}/lines/${lineId}`) } export async function submitOrder(id: string) { const res = await api.post(`/orders/${id}/submit`) return res.data } export async function deleteOrder(id: string) { await api.delete(`/orders/${id}`) } export async function unlinkCadFile(orderId: string, itemId: string) { await api.delete(`/orders/${orderId}/items/${itemId}/cad-file`) } export async function dispatchRenders(orderId: string) { const res = await api.post<{ dispatched: number }>(`/orders/${orderId}/dispatch-renders`) return res.data } export async function cancelLineRender(orderId: string, lineId: string) { const res = await api.post<{ cancelled: boolean; line_id: string; backend: string; errors: string[] | null }>( `/orders/${orderId}/lines/${lineId}/cancel-render` ) return res.data } export async function dispatchLineRender(orderId: string, lineId: string) { const res = await api.post<{ dispatched: boolean; line_id: string }>( `/orders/${orderId}/lines/${lineId}/dispatch-render` ) return res.data } export async function batchMaterialOverride(orderId: string, materialOverride: string | null) { const res = await api.post<{ updated: number; material_override: string | null }>( `/orders/${orderId}/batch-material-override`, { material_override: materialOverride } ) return res.data } export async function patchOrderLine(orderId: string, lineId: string, data: { material_override?: string | null; render_overrides?: Record | null }) { const res = await api.patch<{ updated: boolean; line_id: string }>( `/orders/${orderId}/lines/${lineId}`, data ) return res.data } export async function batchRenderOverrides(orderId: string, renderOverrides: Record | null) { const res = await api.post<{ updated: number; render_overrides: Record | null }>( `/orders/${orderId}/batch-render-overrides`, { render_overrides: renderOverrides } ) return res.data } export async function cancelOrderRenders(orderId: string) { const res = await api.post<{ cancelled: number; order_status: string; errors: string[] | null }>( `/orders/${orderId}/cancel-renders` ) return res.data } export async function regenerateItemThumbnail(orderId: string, itemId: string) { const res = await api.post<{ status: string; task_id: string; cad_file_id: string }>( `/orders/${orderId}/items/${itemId}/regenerate-thumbnail` ) return res.data } export interface SplitMissingStepResult { new_order_id: string new_order_number: string moved_item_count: number moved_line_count: number } export async function splitMissingStep(orderId: string): Promise { const res = await api.post(`/orders/${orderId}/split-missing-step`) return res.data } export interface GenerateLinesResult { created: number skipped: number no_product_count: number no_step_count: number } export async function generateLinesFromItems( orderId: string, outputTypeIds: string[], ): Promise { const res = await api.post(`/orders/${orderId}/generate-lines`, { output_type_ids: outputTypeIds, }) return res.data } export async function rejectOrderLine( orderId: string, lineId: string, reason: string, ): Promise<{ rejected: boolean; line_id: string; reason: string }> { const res = await api.post<{ rejected: boolean; line_id: string; reason: string }>( `/orders/${orderId}/lines/${lineId}/reject`, { reason }, ) return res.data } export async function rejectOrder(orderId: string, reason: string, notifyClient: boolean = true): Promise { const res = await api.post(`/orders/${orderId}/reject`, { reason, notify_client: notifyClient, }) return res.data } export async function resubmitOrder(orderId: string): Promise { const res = await api.post(`/orders/${orderId}/resubmit`) return res.data } export async function downloadOrderRenders(orderId: string, orderNumber: string): Promise { const res = await api.get(`/orders/${orderId}/download-renders`, { responseType: 'blob' }) const url = URL.createObjectURL(res.data) const a = document.createElement('a') a.href = url a.download = `${orderNumber}_renders.zip` a.click() URL.revokeObjectURL(url) }