/** * PPL CPL: zalozeni zasilky. * * Sluzba: https://services.csbot.cz/apps/pplcplapi * Endpoint: POST /shipments/create-and-wait * * CPL zpracovava zasilky **davkove**: zalozi se batch, pak se ceka na jeho * zpracovani a teprve pak je znamé cislo zasilky. Sluzba na to ma synchronni * obalku, ktera cely tok provede za nas - proto se vola ona a ne * `/shipments/batch`. Krok stromu, ktery by musel sam pollovat, by potreboval * runtime s cekanim, a ten zatim neni. * * Idempotence: hlavicku `Idempotency-Key` doplnuje runtime a je stabilni pres * vsechny pokusy tehoz kroku, takze druhy pokus po timeoutu neposle druhy balik. */ export const manifest = { id: 'ppl.create-shipment', name: 'Vytvořit zásilku', description: 'Založí zásilku v PPL a počká na její zpracování. Vrací číslo zásilky ' + 'a volitelně i etiketu k tisku.', inputs: [ { id: 'referenceId', label: 'Reference', type: 'string', required: true, hint: 'Vaše číslo, podle kterého zásilku poznáte. Typicky číslo objednávky.', }, { id: 'productType', label: 'Produkt', type: 'string', required: false, default: 'BUSS', hint: 'Kód produktu PPL, například BUSS (Business) nebo PRIV (Private). Číselník vrací /codelists/product.', }, { id: 'recipientName', label: 'Příjemce', type: 'string', required: true }, { id: 'recipientStreet', label: 'Ulice a číslo', type: 'string', required: true }, { id: 'recipientCity', label: 'Město', type: 'string', required: true }, { id: 'recipientZip', label: 'PSČ', type: 'string', required: true, hint: 'Bez mezer, například 60200.', }, { id: 'recipientCountry', label: 'Země', type: 'string', required: false, default: 'CZ', hint: 'Dvoupísmenný kód země.', }, { id: 'recipientPhone', label: 'Telefon příjemce', type: 'string', required: false }, { id: 'recipientEmail', label: 'E-mail příjemce', type: 'string', required: false }, { id: 'note', label: 'Poznámka', type: 'string', required: false, hint: 'Text pro kurýra. Diakritiku odstraní služba sama, CPL ji nepřijímá.', }, { id: 'withLabel', label: 'Vrátit i etiketu', type: 'boolean', required: false, default: false, hint: 'Etiketa je binární PDF, takže se vrací jen odkaz na ni, ne obsah.', }, ], outputs: [ { id: 'shipmentNumber', label: 'Číslo zásilky', type: 'string', required: false }, { id: 'batchId', label: 'ID dávky', type: 'string', required: false }, { id: 'completed', label: 'Zpracováno', type: 'boolean', required: true }, { id: 'result', label: 'Celá odpověď PPL', type: 'object', required: true }, ], // Sluzba uvnitr ceka na zpracovani davky. Kratsi limit by utnul i uspech. timeoutMs: 90000, }; /** * Cislo zasilky z odpovedi. * * CPL ho vraci na ruznych mistech podle toho, kolik zasilek davka mela. * Hledani do hloubky je levnejsi nez tri varianty `pick` za sebou, ktere by * stejne nepokryly dalsi tvar. */ function findShipmentNumber(value, depth = 0) { if (value === null || typeof value !== 'object' || depth > 5) return null; if (!Array.isArray(value)) { for (const [key, item] of Object.entries(value)) { if (/^shipmentnumber$/i.test(key) && typeof item === 'string' && item !== '') return item; } } for (const item of Array.isArray(value) ? value : Object.values(value)) { const found = findShipmentNumber(item, depth + 1); if (found !== null) return found; } return null; } export async function run(inputs, ctx) { const { pick, text, bool } = ctx.util; const recipient = { name: inputs.recipientName, street: inputs.recipientStreet, city: inputs.recipientCity, zipCode: inputs.recipientZip.replace(/\s+/g, ''), country: inputs.recipientCountry, }; if (inputs.recipientPhone) recipient.phone = inputs.recipientPhone; if (inputs.recipientEmail) recipient.email = inputs.recipientEmail; const shipment = { referenceId: inputs.referenceId, productType: inputs.productType, recipient, }; if (inputs.note) shipment.note = inputs.note; const { body } = await ctx.http.post( '/shipments/create-and-wait', { shipments: [shipment] }, { query: { include_labels: inputs.withLabel } }, ); const completed = bool(pick(body, 'completed')); const shipmentNumber = findShipmentNumber(body); if (!completed) { // Neni to chyba: davka bezi dal a stav se da dotahnout pres batchId. // Vyhodit chybu by znamenalo, ze uz zalozena zasilka vypadne ze stromu. ctx.log('PPL dávku ještě nedokončil, stav zjistíte podle ID dávky.'); } return { shipmentNumber, batchId: text(pick(body, 'batchId', 'batch_id')), completed, result: body, }; }