// Pick-code resolution shared by every picklist surface (the digital lists on // /generate-shipments, /mobile/generate-shipments, /mobile/picklist, // /integrations/picklist-desktop and the PDF in ~/utils/picklistPdf.ts): which // product code the picker should match. // // Priority: // 1. the merchant's C_BPartner.PickProductIdentifier (value|upc|sku|mpn|asin) — // arrives on each line as `pickIdentifier` from /api/processes/inouts/[id] // 2. the product's own M_Product.PickListCode (val|sku|upc|mpn) // 3. first filled of mpn -> sku -> upc -> val // A configured code that is EMPTY on the product falls through to the next step, // so the picker is never pointed at a blank field. export const PICK_CODE_KEYS = ['val', 'sku', 'upc', 'mpn', 'asin'] export const PICK_CODE_FALLBACK = ['mpn', 'sku', 'upc', 'val'] export const PICK_CODE_LABELS: Record = { val: 'Value', sku: 'SKU', upc: 'UPC', mpn: 'MPN', asin: 'ASIN' } // Options of the partner-level setting (keys = the iDempiere list values). export const PICK_IDENTIFIER_OPTIONS = [ { id: 'value', Name: 'Value' }, { id: 'upc', Name: 'UPC / EAN' }, { id: 'sku', Name: 'SKU' }, { id: 'mpn', Name: 'MPN' }, { id: 'asin', Name: 'ASIN' }, ] // iDempiere list value ({ id, identifier } or bare string) -> 'value'|'upc'|'sku'|'mpn'|'asin'|''. export const pickIdentifierListValue = (raw: any): string => { const code = (raw && typeof raw === 'object') ? (raw.id ?? raw.identifier ?? '') : (raw ?? '') const key = code.toString().trim().toLowerCase() return PICK_IDENTIFIER_OPTIONS.some(o => o.id === key) ? key : '' } export type PickCodeSource = 'partner' | 'product' | 'fallback' export const getProductCodeValue = (product: any, key: string | null): string => { if (!product) return '' switch (key) { case 'val': return product.Value || '' case 'sku': return product.SKU || '' case 'upc': return product.UPC || '' case 'mpn': return product.mpn || product.MPN || '' case 'asin': return product.asin || product.ASIN || '' } return '' } // Partner list value ('value', as an iDempiere list object or a bare string) -> pick-code key ('val'). const partnerKeyToPickCode = (raw: any): string | null => { const code = (raw && typeof raw === 'object') ? (raw.id ?? raw.identifier ?? '') : (raw ?? '') const key = code.toString().trim().toLowerCase() if (key === 'value') return 'val' return PICK_CODE_KEYS.includes(key) ? key : null } export const resolvePickCode = (product: any, partnerKey: any = null): { key: string, source: PickCodeSource } | null => { if (!product) return null const fromPartner = partnerKeyToPickCode(partnerKey) if (fromPartner && getProductCodeValue(product, fromPartner)) return { key: fromPartner, source: 'partner' } const fromProduct = partnerKeyToPickCode(product.PickListCode ?? product.pickListCode ?? product.picklistcode) // Without a partner setting an explicit PickListCode wins even when empty (legacy behaviour). if (fromProduct && (!fromPartner || getProductCodeValue(product, fromProduct))) return { key: fromProduct, source: 'product' } for (const k of PICK_CODE_FALLBACK) { if (getProductCodeValue(product, k)) return { key: k, source: 'fallback' } } return { key: PICK_CODE_FALLBACK[0], source: 'fallback' } } export const resolvePrimaryPickCode = (product: any, partnerKey: any = null) => resolvePickCode(product, partnerKey)?.key ?? null // All code rows for a digital picklist card, primary first. `isConfigured` = the primary // comes from the partner setting (drawn larger). ASIN only shows when filled or primary. export const getPickCodeRows = (product: any, partnerKey: any = null) => { const resolved = resolvePickCode(product, partnerKey) const primary = resolved?.key ?? null const order = primary ? [primary, ...PICK_CODE_KEYS.filter(k => k !== primary)] : PICK_CODE_KEYS.slice() return order .map(key => ({ key, label: PICK_CODE_LABELS[key], value: getProductCodeValue(product, key), isPrimary: key === primary, isConfigured: key === primary && resolved?.source === 'partner', })) .filter(row => row.key !== 'asin' || row.isPrimary || row.value) } // Compact "primary code" label for preview lists / tables. export const primaryCode = (product: any, partnerKey: any = null) => { const key = resolvePrimaryPickCode(product, partnerKey) return { label: (key && PICK_CODE_LABELS[key]) || 'Code', value: getProductCodeValue(product, key) || '-' } }