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 || '' // Opt-in BOM exclusion (checkbox on the mobile print-labels page). IsBOM is the // standard flag (filtered server-side); the custom isJtlBom column is filtered in JS. const excludeBom = body?.excludeBom === true || body?.excludeBom === 'true' || body?.excludeBom === '1' const isJtlBom = (p: any) => (p.isJtlBom ?? p.IsJtlBom) === true || (p.isJtlBom ?? p.IsJtlBom) === 'Y' const isBom = (p: any) => (p.IsBOM ?? p.isBOM) === true || (p.IsBOM ?? p.isBOM) === 'Y' if (!searchTerm) { throw createError({ statusCode: 400, statusMessage: 'Search term is required' }) } // Build filter to search by Value, SKU, UPC, Name, or MPN — all partial, case-insensitive const escapedTerm = searchTerm.replace(/'/g, "''") const lowerTerm = escapedTerm.toLowerCase() const strippedTerm = lowerTerm.replace(/[\s-]+/g, '') const bomClause = excludeBom ? ' AND (IsBOM eq false)' : '' const buildFilter = (term: string) => string.urlEncode( `(contains(tolower(Value),'${term}') OR contains(tolower(SKU),'${term}') OR contains(tolower(UPC),'${term}') OR contains(tolower(MPN),'${term}') OR contains(tolower(fnsku),'${term}') OR contains(tolower(Name),'${term}')) AND (isActive eq true)${bomClause}` ) let res: any = await fetchHelper( event, `models/m_product?$filter=${buildFilter(lowerTerm)}&$top=50`, 'GET', token, null ) // No match on the raw term → retry with separators stripped so a scanned // barcode "PZN-15821889" / "PZN - 15821889" finds stored "PZN15821889". if ((!res?.records || res.records.length === 0) && strippedTerm && strippedTerm !== lowerTerm) { res = await fetchHelper( event, `models/m_product?$filter=${buildFilter(strippedTerm)}&$top=50`, 'GET', token, null ) } if (res?.records && excludeBom) { res.records = res.records.filter((p: any) => !isJtlBom(p)) } if (res?.records && res.records.length > 0) { // Map products with necessary fields for label printing data.records = res.records.map((product: any) => ({ id: product.id, Name: product.Name, isBOM: isBom(product), isJtlBom: isJtlBom(product), imageUrl: product.ImageURL || null, Value: product.Value, SKU: product.SKU, UPC: product.UPC, MPN: product.MPN, ASIN: product.ASIN, FNSKU: product.fnsku || null, labelPrinterId: product.labelprinter?.id || null, labelPrinter: product.labelprinter?.identifier || null, Strapi_Product_documentId: product.Strapi_Product_documentId || null, organizationId: product.AD_Org_ID?.id || product.AD_Org_ID, organization: product.AD_Org_ID?.identifier || product.AD_Org_ID?.Name })) } else { data.records = [] } return data } export default defineEventHandler(async (event) => { // Auth-only retry: a business 404 no longer triggers a token refresh. return await withAuthRetry(event, handleFunc) })