From e028f7c03829e07a4f8d82a58e4a5c04cc7e5a30 Mon Sep 17 00:00:00 2001 From: Ruslan Bakiev Date: Sun, 31 May 2026 12:05:54 +0500 Subject: [PATCH] Remove Odoo order fallback --- src/schemas/team.ts | 245 +++----------------------------------------- 1 file changed, 12 insertions(+), 233 deletions(-) diff --git a/src/schemas/team.ts b/src/schemas/team.ts index 88fefb5..22128f7 100644 --- a/src/schemas/team.ts +++ b/src/schemas/team.ts @@ -9,8 +9,6 @@ import { import { requireScopes, type AuthContext } from '../auth.js' import { prisma } from '../db.js' -const ODOO_INTERNAL_URL = process.env.ODOO_INTERNAL_URL || 'odoo:8069' - const quotationInclude = { selectedTariff: true, changes: { @@ -27,82 +25,6 @@ const orderInclude = { type QuotationWithRelations = Prisma.QuotationGetPayload<{ include: typeof quotationInclude }> type OrderWithRelations = Prisma.OrderGetPayload<{ include: typeof orderInclude }> -interface OdooCompany { - uuid?: string - name?: string - tax_id?: string - country?: string - country_code?: string - active?: boolean -} - -interface OdooTrip { - uuid?: string - name?: string - sequence?: number - company?: OdooCompany - planned_loading_date?: string - actual_loading_date?: string - real_loading_date?: string - planned_unloading_date?: string - actual_unloading_date?: string - planned_weight?: number - weight_at_loading?: number - weight_at_unloading?: number -} - -interface OdooStage { - uuid?: string - name?: string - sequence?: number - stage_type?: string - transport_type?: string - source_location_name?: string - source_latitude?: number - source_longitude?: number - destination_location_name?: string - destination_latitude?: number - destination_longitude?: number - location_name?: string - location_latitude?: number - location_longitude?: number - selected_company?: OdooCompany - trips?: OdooTrip[] -} - -interface OdooOrderLine { - uuid?: string - product_uuid?: string - product_name?: string - quantity?: number - unit?: string - price_unit?: number - subtotal?: number - currency?: string - notes?: string -} - -interface OdooOrder { - uuid?: string - name?: string - team_uuid?: string - user_id?: string - status?: string - total_amount?: number - currency?: string - source_location_uuid?: string - source_location_name?: string - source_latitude?: number - source_longitude?: number - destination_location_uuid?: string - destination_location_name?: string - created_at?: string - updated_at?: string - notes?: string - order_lines?: OdooOrderLine[] - stages?: OdooStage[] -} - interface TariffMatchResult { tariff: PrismaTariffReference score: number @@ -491,95 +413,6 @@ function assertTeamAccess(ctx: AuthContext): { teamUuid: string; userId: string } } -function mapCompany(c?: OdooCompany | null) { - if (!c) return null - return { - uuid: c.uuid ?? '', - name: c.name ?? '', - taxId: c.tax_id ?? '', - country: c.country ?? '', - countryCode: c.country_code ?? '', - active: c.active ?? true, - } -} - -function mapTrip(t: OdooTrip) { - return { - uuid: t.uuid, - name: t.name, - sequence: t.sequence, - company: mapCompany(t.company), - plannedLoadingDate: t.planned_loading_date, - actualLoadingDate: t.actual_loading_date, - realLoadingDate: t.real_loading_date, - plannedUnloadingDate: t.planned_unloading_date, - actualUnloadingDate: t.actual_unloading_date, - plannedWeight: t.planned_weight, - weightAtLoading: t.weight_at_loading, - weightAtUnloading: t.weight_at_unloading, - } -} - -function mapStage(s: OdooStage) { - return { - uuid: s.uuid, - name: s.name, - sequence: s.sequence, - stageType: s.stage_type, - transportType: s.transport_type, - sourceLocationName: s.source_location_name, - sourceLatitude: s.source_latitude, - sourceLongitude: s.source_longitude, - destinationLocationName: s.destination_location_name, - destinationLatitude: s.destination_latitude, - destinationLongitude: s.destination_longitude, - locationName: s.location_name, - locationLatitude: s.location_latitude, - locationLongitude: s.location_longitude, - selectedCompany: mapCompany(s.selected_company), - trips: (s.trips ?? []).map(mapTrip), - } -} - -function mapOdooOrder(o: OdooOrder) { - const stages = o.stages ?? [] - const firstStage = stages[0] - return { - uuid: o.uuid, - quotationUuid: null, - name: o.name, - teamUuid: o.team_uuid, - userId: o.user_id, - status: o.status ?? 'active', - totalAmount: o.total_amount, - currency: o.currency, - sourceCountryCode: null, - sourceLocationUuid: o.source_location_uuid, - sourceLocationName: o.source_location_name, - sourceLatitude: o.source_latitude || firstStage?.source_latitude, - sourceLongitude: o.source_longitude || firstStage?.source_longitude, - destinationCountryCode: null, - destinationLocationUuid: o.destination_location_uuid, - destinationLocationName: o.destination_location_name, - etaDays: null, - createdAt: o.created_at, - updatedAt: o.updated_at, - notes: o.notes ?? '', - orderLines: (o.order_lines ?? []).map(l => ({ - uuid: l.uuid, - productUuid: l.product_uuid, - productName: l.product_name, - quantity: l.quantity, - unit: l.unit, - priceUnit: l.price_unit, - subtotal: l.subtotal, - currency: l.currency, - notes: l.notes ?? '', - })), - stages: stages.map(mapStage), - } -} - function mapTariffReference(item: PrismaTariffReference) { return { uuid: item.uuid, @@ -693,53 +526,6 @@ function mapLocalOrder(item: OrderWithRelations) { } } -async function fetchOdoo(path: string): Promise { - const controller = new AbortController() - const timeout = setTimeout(() => controller.abort(), 10000) - try { - return await fetch(`http://${ODOO_INTERNAL_URL}${path}`, { signal: controller.signal }) - } finally { - clearTimeout(timeout) - } -} - -async function fetchTeamOdooOrders(teamUuid: string) { - try { - const res = await fetchOdoo(`/fastapi/orders/orders/team/${teamUuid}`) - if (!res.ok) return [] - const data = (await res.json()) as OdooOrder[] - return data.map(mapOdooOrder) - } catch (error) { - console.error('Error calling Odoo:', error) - return [] - } -} - -async function fetchSingleOdooOrder(orderUuid: string, teamUuid: string) { - try { - const res = await fetchOdoo(`/fastapi/orders/orders/${orderUuid}`) - if (!res.ok) return null - const data = (await res.json()) as OdooOrder - if (data.team_uuid !== teamUuid) { - throw new GraphQLError('Access denied: order belongs to different team') - } - return mapOdooOrder(data) - } catch (error) { - if (error instanceof GraphQLError) throw error - console.error('Error calling Odoo:', error) - return null - } -} - -function compareByCreatedAtDesc( - left: { createdAt: string | null | undefined }, - right: { createdAt: string | null | undefined }, -) { - const leftTime = left.createdAt ? new Date(left.createdAt).getTime() : 0 - const rightTime = right.createdAt ? new Date(right.createdAt).getTime() : 0 - return rightTime - leftTime -} - function requiredString(value: unknown, label: string): string { const next = normalizeString(value) if (!next) { @@ -1098,26 +884,23 @@ export const teamResolvers = { getTeamOrders: async (_: unknown, __: unknown, ctx: AuthContext) => { const { teamUuid } = assertTeamAccess(ctx) - const [localOrders, odooOrders] = await Promise.all([ - prisma.order.findMany({ - where: { - teamUuid, - }, - include: orderInclude, - orderBy: { - createdAt: 'desc', - }, - }), - fetchTeamOdooOrders(teamUuid), - ]) + const localOrders = await prisma.order.findMany({ + where: { + teamUuid, + }, + include: orderInclude, + orderBy: { + createdAt: 'desc', + }, + }) - return [...localOrders.map(mapLocalOrder), ...odooOrders].sort(compareByCreatedAtDesc) + return localOrders.map(mapLocalOrder) }, getOrder: async (_: unknown, args: { orderUuid: string }, ctx: AuthContext) => { const { teamUuid } = assertTeamAccess(ctx) - const localOrder = await prisma.order.findFirst({ + const order = await prisma.order.findFirst({ where: { uuid: args.orderUuid, teamUuid, @@ -1125,11 +908,7 @@ export const teamResolvers = { include: orderInclude, }) - if (localOrder) { - return mapLocalOrder(localOrder) - } - - return await fetchSingleOdooOrder(args.orderUuid, teamUuid) + return order ? mapLocalOrder(order) : null }, quotations: async (_: unknown, args: { status?: string | null }, ctx: AuthContext) => {