import { string } from 'alga-js' import refreshTokenHelper from "../../utils/refreshTokenHelper" import forceLogoutHelper from "../../utils/forceLogoutHelper" import errorHandlingHelper from "../../utils/errorHandlingHelper" import getTokenHelper from "../../utils/getTokenHelper" import fetchHelper from "../../utils/fetchHelper" const handleFunc = async (event: any, authToken: any = null) => { let data: any = {} const token = authToken ?? await getTokenHelper(event) const body = await readBody(event) const searchTerm = body?.search || '' const organizationId = body?.organizationId || null if (!searchTerm) { throw createError({ statusCode: 400, statusMessage: 'Search term is required' }) } // Convert search term to lowercase for case-insensitive search const searchTermLower = searchTerm.toLowerCase() // Build organization filter if provided const orgFilter = organizationId ? ` AND AD_Org_ID eq ${organizationId}` : '' const shipmentExpand = string.urlEncode('m_inoutline($expand=m_product_id,c_uom_id,m_locator_id),C_Order_ID,C_BPartner_ID,C_BPartner_Location_ID,AD_User_ID,M_Warehouse_ID,AD_Org_ID') const shipmentOrderby = string.urlEncode('MovementDate desc') // 1. First try: Search for Orders by ExternalOrderId const orderFilter = string.urlEncode( `contains(tolower(ExternalOrderId),'${searchTermLower}') AND isActive eq true AND DocStatus eq 'CO'${orgFilter}` ) const orderRes: any = await fetchHelper( event, `models/c_order?$filter=${orderFilter}&$expand=C_BPartner_ID&$top=30`, 'GET', token, null ) const orderIds: number[] = [] const bpartnersMap = new Map() if (orderRes?.records?.length > 0) { orderRes.records.forEach((order: any) => { orderIds.push(order.id) if (order.C_BPartner_ID?.id && !bpartnersMap.has(order.C_BPartner_ID.id)) { bpartnersMap.set(order.C_BPartner_ID.id, { id: order.C_BPartner_ID.id, name: order.C_BPartner_ID.Name || order.C_BPartner_ID.identifier, value: order.C_BPartner_ID.Value }) } }) // Fetch shipments for the matched orders const orderFilters = orderIds.map((id: number) => `C_Order_ID eq ${id}`).join(' OR ') const shipmentFilter = string.urlEncode( `MovementType eq 'C-' AND isActive eq true AND DocStatus eq 'CO' AND (${orderFilters})` ) const shipmentsRes: any = await fetchHelper( event, `models/m_inout?$filter=${shipmentFilter}&$expand=${shipmentExpand}&$orderby=${shipmentOrderby}&$top=50`, 'GET', token, null ) data = { bpartners: Array.from(bpartnersMap.values()), shipments: shipmentsRes?.records || [] } return data } // 2. Fallback: Search by BPartner name and location const bpartnerIdSet = new Set() const bpartnerFilter = string.urlEncode( `(contains(tolower(Name),'${searchTermLower}') OR contains(tolower(Name2),'${searchTermLower}')) AND isActive eq true${orgFilter}` ) const bpartnerRes: any = await fetchHelper( event, `models/c_bpartner?$filter=${bpartnerFilter}&$top=30`, 'GET', token, null ) if (bpartnerRes?.records) { bpartnerRes.records.forEach((bp: any) => bpartnerIdSet.add(bp.id)) } const locationFilter = string.urlEncode( `(contains(tolower(Name),'${searchTermLower}') OR contains(tolower(Name2),'${searchTermLower}')) AND isActive eq true${orgFilter}` ) const locationRes: any = await fetchHelper( event, `models/c_bpartner_location?$filter=${locationFilter}&$expand=C_BPartner_ID&$top=30`, 'GET', token, null ) if (locationRes?.records) { locationRes.records.forEach((loc: any) => { if (loc.C_BPartner_ID?.id) { bpartnerIdSet.add(loc.C_BPartner_ID.id) } }) } if (bpartnerIdSet.size === 0) { return { bpartners: [], shipments: [] } } const bpartnerIds = Array.from(bpartnerIdSet) const shipmentFilters = bpartnerIds.map((id: number) => `C_BPartner_ID eq ${id}`).join(' OR ') const shipmentFilter = string.urlEncode( `MovementType eq 'C-' AND isActive eq true AND DocStatus eq 'CO' AND (${shipmentFilters})` ) const shipmentsRes: any = await fetchHelper( event, `models/m_inout?$filter=${shipmentFilter}&$expand=${shipmentExpand}&$orderby=${shipmentOrderby}&$top=50`, 'GET', token, null ) // Build bpartners list if (bpartnerRes?.records) { bpartnerRes.records.forEach((bp: any) => { bpartnersMap.set(bp.id, { id: bp.id, name: bp.Name, value: bp.Value }) }) } if (locationRes?.records) { locationRes.records.forEach((loc: any) => { if (loc.C_BPartner_ID?.id && !bpartnersMap.has(loc.C_BPartner_ID.id)) { bpartnersMap.set(loc.C_BPartner_ID.id, { id: loc.C_BPartner_ID.id, name: loc.C_BPartner_ID.Name || loc.C_BPartner_ID.identifier, value: loc.C_BPartner_ID.Value }) } }) } data = { bpartners: Array.from(bpartnersMap.values()), shipments: shipmentsRes?.records || [] } return data } export default defineEventHandler(async (event) => { let data: any = {} try { data = await handleFunc(event) } catch(err: any) { try { let authToken: any = await refreshTokenHelper(event) data = await handleFunc(event, authToken) } catch(error: any) { data = errorHandlingHelper(err?.data ?? err, error?.data ?? error) forceLogoutHelper(event, data) throw createError({ statusCode: err?.statusCode || 500, statusMessage: err?.statusMessage || 'Error searching BPartner shipments', data: data }) } } return data })