chore(n8n): keep the stored PO-ingest callback in step with the published workflow
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
c55676bff0
commit
1fb65a9d9c
1 changed files with 1 additions and 1 deletions
|
|
@ -6,7 +6,7 @@
|
|||
"nodeName": "Build Callback Payload",
|
||||
"parameters": {
|
||||
"mode": "runOnceForEachItem",
|
||||
"jsCode": "const sourceItem = $input.item;\nif (!sourceItem) {\n throw new Error('Build Callback Payload: no input item');\n}\nconst parsed = (sourceItem.json && typeof sourceItem.json.output === 'object' && sourceItem.json.output !== null)\n ? sourceItem.json.output\n : sourceItem.json;\n\n// This item's id is the purchase_orders row Atomic Claim just claimed --\n// the placeholder created at upload time (src/lib/po-placeholder.ts).\n// There is no separate batch row anymore.\nconst purchase_order_id = $('Atomic Claim').item.json.id;\nconst po_number_extracted = String(parsed.po_number || '').trim();\nconst supplier = String(parsed.supplier || '').trim();\nconst project_code = String(parsed.project_code || '').trim();\nif (!po_number_extracted) {\n throw new Error('AI extraction returned an empty PO number');\n}\n\nconst po_number_normalized = po_number_extracted\n .replace(/^p\\.?o\\.?([-#.]|\\s+)?/i, '')\n .replace(/\\s+/g, ' ')\n .trim()\n .toUpperCase();\nif (!po_number_normalized) {\n throw new Error('AI Agent po_number normalises to empty string: \"' + po_number_extracted + '\"');\n}\n\nconst required_by_date = parsed.required_by_date || undefined;\nconst ordered_by = parsed.ordered_by || undefined;\nconst rawItems = Array.isArray(parsed.items) ? parsed.items : [];\nconst items = rawItems.map(it => {\n if (!it) return null;\n return {\n ...it,\n qty: Number(it.qty),\n rate: Number(it.rate),\n material_code: (it.material_code && String(it.material_code).trim() !== '' && String(it.material_code).toLowerCase() !== 'null') ? String(it.material_code).trim() : '',\n cost_code: (it.cost_code && String(it.cost_code).trim() !== '' && String(it.cost_code).toLowerCase() !== 'null') ? String(it.cost_code).trim() : '',\n disc_percent: (it.disc_percent !== null && it.disc_percent !== undefined && !isNaN(it.disc_percent)) ? Number(it.disc_percent) : 0,\n vat_percent: (it.vat_percent !== null && it.vat_percent !== undefined && !isNaN(it.vat_percent)) ? Number(it.vat_percent) : 15\n };\n}).filter(it =>\n it &&\n typeof it.description === 'string' && it.description.trim().length > 0 &&\n !isNaN(it.qty) && it.qty >= 0 &&\n !isNaN(it.rate) && it.rate >= 0\n);\nif (items.length === 0) {\n throw new Error('AI Agent returned no valid line items (all missing description/qty/rate)');\n}\n\n// Duplicate detection now lives server-side in\n// /api/purchase-orders/process-batch (merge onto the existing PO, delete\n// this placeholder) -- it already owns the purchase_orders schema and is\n// covered by tests. n8n no longer queries or writes purchase_orders\n// directly to pre-empt it.\n//\n// purchase_order_number is the exact field name the route validates --\n// the old contract used po_number here, which would fail every upload.\nreturn {\n json: {\n purchase_order_id,\n extracted: {\n purchase_order_number: po_number_normalized,\n po_number_extracted,\n supplier,\n project_code,\n required_by_date,\n ordered_by,\n items,\n raw_ocr: { source: 'ai-agent', model: 'MiniMax-M3' },\n },\n },\n};\n"
|
||||
"jsCode": "const sourceItem = $input.item;\nif (!sourceItem) {\n throw new Error('Build Callback Payload: no input item');\n}\nconst parsed = (sourceItem.json && typeof sourceItem.json.output === 'object' && sourceItem.json.output !== null)\n ? sourceItem.json.output\n : sourceItem.json;\n\n// This item's id is the purchase_orders row Atomic Claim just claimed --\n// the placeholder created at upload time (src/lib/po-placeholder.ts).\n// There is no separate batch row anymore.\nconst purchase_order_id = $('Atomic Claim').item.json.id;\nconst po_number_extracted = String(parsed.po_number || '').trim();\nconst supplier = String(parsed.supplier || '').trim();\nconst project_code = String(parsed.project_code || '').trim();\nif (!po_number_extracted) {\n throw new Error('AI extraction returned an empty PO number');\n}\n\nconst po_number_normalized = po_number_extracted\n .replace(/^p\\.?o\\.?([-#.]|\\s+)?/i, '')\n .replace(/\\s+/g, ' ')\n .trim()\n .toUpperCase();\nif (!po_number_normalized) {\n throw new Error('AI Agent po_number normalises to empty string: \"' + po_number_extracted + '\"');\n}\n\nconst required_by_date = parsed.required_by_date || undefined;\n// \"PO Creation Date\" printed on the PO: when it was ordered. Money is dated by it.\nconst order_date = /^\\d{4}-\\d{2}-\\d{2}$/.test(String(parsed.order_date || '')) ? String(parsed.order_date) : undefined;\nconst ordered_by = parsed.ordered_by || undefined;\nconst rawItems = Array.isArray(parsed.items) ? parsed.items : [];\nconst items = rawItems.map(it => {\n if (!it) return null;\n return {\n ...it,\n qty: Number(it.qty),\n rate: Number(it.rate),\n material_code: (it.material_code && String(it.material_code).trim() !== '' && String(it.material_code).toLowerCase() !== 'null') ? String(it.material_code).trim() : '',\n cost_code: (it.cost_code && String(it.cost_code).trim() !== '' && String(it.cost_code).toLowerCase() !== 'null') ? String(it.cost_code).trim() : '',\n disc_percent: (it.disc_percent !== null && it.disc_percent !== undefined && !isNaN(it.disc_percent)) ? Number(it.disc_percent) : 0,\n vat_percent: (it.vat_percent !== null && it.vat_percent !== undefined && !isNaN(it.vat_percent)) ? Number(it.vat_percent) : 15\n };\n}).filter(it =>\n it &&\n typeof it.description === 'string' && it.description.trim().length > 0 &&\n !isNaN(it.qty) && it.qty >= 0 &&\n !isNaN(it.rate) && it.rate >= 0\n);\nif (items.length === 0) {\n throw new Error('AI Agent returned no valid line items (all missing description/qty/rate)');\n}\n\n// Duplicate detection now lives server-side in\n// /api/purchase-orders/process-batch (merge onto the existing PO, delete\n// this placeholder) -- it already owns the purchase_orders schema and is\n// covered by tests. n8n no longer queries or writes purchase_orders\n// directly to pre-empt it.\n//\n// purchase_order_number is the exact field name the route validates --\n// the old contract used po_number here, which would fail every upload.\nreturn {\n json: {\n purchase_order_id,\n extracted: {\n purchase_order_number: po_number_normalized,\n po_number_extracted,\n supplier,\n project_code,\n required_by_date,\n order_date,\n ordered_by,\n items,\n raw_ocr: { source: 'ai-agent', model: 'MiniMax-M3' },\n },\n },\n};\n"
|
||||
},
|
||||
"replace": true
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue