import { safeSupabaseCall } from "../safeSupabaseCall"; import { hasSupabaseConfig, supabase } from "../../supabaseClient"; const CHANNEL_CODES = { "смс": "sms", "эл. почта": "email", "эл почта": "email", "электронная почта": "email", sms: "sms", email: "email", }; const requireSupabase = () => { if (!hasSupabaseConfig || !supabase) { throw new Error("Supabase не сконфигурирован"); } return supabase; }; const mapHistoryRow = (row) => ({ id: row.id, action: row.action, oldStatus: row.old_status, newStatus: row.new_status, userId: row.user_id, userName: row.user_name || null, metadata: row.metadata || {}, at: row.created_at, }); const mapDeliverySlotRow = (row) => ({ id: row.id, date: row.delivery_date, time: row.delivery_time, logisticianId: row.logistician_id || null, logisticianName: row.logistician_name || null, status: row.status, createdAt: row.created_at, selectedByClientAt: row.selected_by_client_at || null, }); const mapChatMessageRow = (row) => ({ id: row.id, sender: row.sender_type, senderName: row.sender_name || null, channel: row.channel, text: row.text, externalMessageId: row.external_message_id || null, payload: row.payload || {}, sentAt: row.created_at, }); const getCustomerBlob = (row) => row.customer || {}; export const mapOrderRowToOrder = (row) => { if (!row) { return null; } const customer = getCustomerBlob(row); const history = Array.isArray(row.order_history) ? row.order_history.map(mapHistoryRow) : []; const deliverySlots = Array.isArray(row.delivery_slots) ? row.delivery_slots.map(mapDeliverySlotRow) : []; const chatMessages = Array.isArray(row.chat_messages) ? row.chat_messages.map(mapChatMessageRow) : []; const logisticianIdsFromAssignments = Array.isArray(row.order_logisticians) ? row.order_logisticians.map((item) => item.logistician_id).filter(Boolean) : []; const logisticianIds = Array.from( new Set([row.logistician_id, ...logisticianIdsFromAssignments].filter(Boolean)), ); return { id: row.id, orderNumber: row.order_number, customer: { name: customer.name || "Без имени", phone: customer.phone || "", messenger: customer.messenger || "СМС", address: customer.address || "", city: customer.city || "", items: Array.isArray(customer.items) ? customer.items : [], comments: Array.isArray(customer.comments) ? customer.comments : [], tags: Array.isArray(customer.tags) ? customer.tags : [], orderNotes: Array.isArray(customer.orderNotes) ? customer.orderNotes : [], internalMessages: Array.isArray(customer.internalMessages) ? customer.internalMessages : [], scheduledDelivery: customer.scheduledDelivery || null, deliveryDate: customer.deliveryDate || null, deliveryTime: customer.deliveryTime || null, exception: customer.exception || null, }, status: row.status, deliveryAgreementStatus: row.delivery_agreement_status || "Не начато", managerId: row.manager_id || null, logisticianIds, assignedDriverId: row.assigned_driver_id || null, driverRouteOrder: customer.driverRouteOrder ?? null, readyForDeliveryAt: row.ready_for_delivery_at || null, deliveryFlowStartedAt: row.delivery_flow_started_at || null, deliveryFlowSource: row.delivery_flow_source || null, sourceOrderNumber: row.source_order_number || null, sourceOrderDate: row.source_order_date || null, sourceCustomerName: row.source_customer_name || null, sourceCustomerPhone: row.source_customer_phone || null, sourceCustomerEmail: row.source_customer_email || null, sourceCustomerCity: row.source_customer_city || null, sourceTotalSum: row.source_total_sum ?? null, sourcePaidAt: row.source_paid_at || null, sourceGateway: row.source_gateway || null, sourceAssociatedBillsText: row.source_associated_bills_text || null, sourceProductionAt: row.source_production_at || null, sourceSawAt: row.source_saw_at || null, sourceGlueAt: row.source_glue_at || null, sourceHGlueAt: row.source_h_glue_at || null, sourceCurveAt: row.source_curve_at || null, sourceAcceptAt: row.source_accept_at || null, sourceShipAt: row.source_ship_at || null, sourceSmsLegacyAt: row.source_sms_legacy_at || null, sourcePayload: row.source_payload || null, deliverySetKey: row.delivery_set_key || null, deliverySetName: row.delivery_set_name || null, deliverySetStatus: row.delivery_set_status || null, deliverySetReadyAt: row.delivery_set_ready_at || null, deliveryReadyReason: row.delivery_ready_reason || null, createdAt: row.created_at, updatedAt: row.updated_at, scheduledDelivery: customer.scheduledDelivery || customer.deliveryDate || row.ready_for_delivery_at || null, items: Array.isArray(customer.items) ? customer.items : [], comments: Array.isArray(customer.comments) ? customer.comments : [], tags: Array.isArray(customer.tags) ? customer.tags : [], orderNotes: Array.isArray(customer.orderNotes) ? customer.orderNotes : [], internalMessages: Array.isArray(customer.internalMessages) ? customer.internalMessages : [], history, chatMessages, deliverySlots, exception: customer.exception || null, }; }; export const enrichOrdersWithUsers = (orders, users = []) => { const usersById = new Map(users.map((user) => [user.id, user])); return orders.map((order) => ({ ...order, history: order.history.map((entry) => ({ ...entry, userName: entry.userName || usersById.get(entry.userId)?.name || entry.userName || "Система", })), deliverySlots: order.deliverySlots.map((slot) => ({ ...slot, logisticianName: slot.logisticianName || usersById.get(slot.logisticianId)?.name || slot.logisticianName || null, })), })); }; export const buildOrderPayload = (order) => { const customer = order.customer || {}; return { id: order.id, order_number: order.orderNumber, customer: { name: customer.name || "", phone: customer.phone || "", messenger: customer.messenger || "СМС", address: customer.address || "", city: customer.city || "", items: Array.isArray(order.items) ? order.items : Array.isArray(customer.items) ? customer.items : [], comments: Array.isArray(order.comments) ? order.comments : Array.isArray(customer.comments) ? customer.comments : [], tags: Array.isArray(order.tags) ? order.tags : Array.isArray(customer.tags) ? customer.tags : [], orderNotes: Array.isArray(order.orderNotes) ? order.orderNotes : Array.isArray(customer.orderNotes) ? customer.orderNotes : [], internalMessages: Array.isArray(order.internalMessages) ? order.internalMessages : Array.isArray(customer.internalMessages) ? customer.internalMessages : [], scheduledDelivery: order.scheduledDelivery || customer.scheduledDelivery || null, deliveryDate: customer.deliveryDate || null, deliveryTime: customer.deliveryTime || null, exception: order.exception || customer.exception || null, driverRouteOrder: order.driverRouteOrder ?? customer.driverRouteOrder ?? null, }, status: order.status, delivery_agreement_status: order.deliveryAgreementStatus || "Не начато", manager_id: order.managerId || null, logistician_id: order.logisticianIds?.[0] || null, assigned_driver_id: order.assignedDriverId || null, ready_for_delivery_at: order.readyForDeliveryAt || null, delivery_flow_started_at: order.deliveryFlowStartedAt || null, delivery_flow_source: order.deliveryFlowSource || null, }; }; export const fetchOrders = async () => { return safeSupabaseCall(async () => { const client = requireSupabase(); const { data, error } = await client .from("orders") .select("id, order_number, customer, status, delivery_agreement_status, manager_id, logistician_id, assigned_driver_id, ready_for_delivery_at, delivery_flow_started_at, delivery_flow_source, source_order_number, source_order_date, source_customer_name, source_customer_phone, source_customer_email, source_customer_city, source_total_sum, source_paid_at, source_gateway, source_associated_bills_text, source_production_at, source_saw_at, source_glue_at, source_h_glue_at, source_curve_at, source_accept_at, source_ship_at, source_sms_legacy_at, source_payload, delivery_set_key, delivery_set_name, delivery_set_status, delivery_set_ready_at, delivery_ready_reason, created_at, updated_at, order_history(id, action, old_status, new_status, user_id, user_name, metadata, created_at), delivery_slots(id, delivery_date, delivery_time, logistician_id, logistician_name, status, created_at, selected_by_client_at), chat_messages(id, sender_type, sender_name, channel, text, external_message_id, payload, created_at), order_logisticians(order_id, logistician_id)") .order("updated_at", { ascending: false }); if (error) { throw error; } return (data || []).map(mapOrderRowToOrder).filter(Boolean); }, "Ошибка загрузки заказов"); }; export const saveOrder = async (order) => { return safeSupabaseCall(async () => { const client = requireSupabase(); const payload = buildOrderPayload(order); const { data, error } = await client.from("orders").upsert(payload).select().single(); if (error) { throw error; } return data; }, "Ошибка сохранения заказа"); }; export const saveChatMessage = async ({ orderId, message }) => { return safeSupabaseCall(async () => { const client = requireSupabase(); const normalizedChannel = CHANNEL_CODES[message.channel.toLowerCase()] || message.channel.toLowerCase().replace(/\s+/g, "_"); const { data, error } = await client .from("chat_messages") .insert({ order_id: orderId, sender_type: message.sender, sender_name: message.senderName || null, channel: normalizedChannel, text: message.text, payload: message.payload || {}, }) .select() .single(); if (error) { throw error; } return data; }, "Ошибка сохранения сообщения"); };