Konektory dostaly vykonnou cast. Jeden skript je jeden soubor, ktery nese manifest (vstupni a vystupni parametry) i kod. Diky manifestu s nim umi pracovat strom automatizace, aniz by o kodu cokoliv vedel. Soubory jsou zamerne obycejny JavaScript, ne TypeScript. TypeScript by se musel prelozit a to je presne to otaceni, ktere tady nema byt. Registr sleduje cas zmeny souboru, takze uprava v portalu, rucni uprava souboru i novy soubor ve slozce funguji stejne a bez restartu. Pridano: - scripts/ se skripty konektoru, nazev souboru je zaroven ID operace - kontrola vstupu i vystupu proti manifestu, jedna funkce pro obe strany. Chybejici povinny vystup je chyba skriptu, ne uzivatele - jinak by strom veril parametru, ktery nikdy nedosel - ctx predavany skriptu: http nad adresou napojeni, util, log, config, idempotencyKey, fail a retry. Skript nedostane pristupove udaje - rozliseni opakovatelne a koncove chyby. Runner nikdy nevyhodi vyjimku, vzdy vraci vysledek vcetne retryable - redakce tajnych hodnot pred zapisem do logu. Cizi API rado vraci prijaty token v chybove zprave a log ticketu vidi klient - napojeni z environment variables vcetne iDokladu - sest ukazkovych skriptu pro iDoklad proti skutecnemu API sluzby services.csbot.cz/apps/idoklad, kazdy na jiny vzor - stranka /dashboard/skripty: seznam, manifest, editor, zkusebni spusteni. Formular testu se sklada z manifestu, nepise se pro kazdy skript - endpointy /api/dashboard/scripts vcetne Swaggeru Zmeneno: - katalog konektoru uz neni jen staticky seznam. Akce ze skriptu se domeruji prekryvem v src/data/connectors.ts, takze se naraz objevi ve validaci stromu, ve vypoctu scope i v sablonach. Pri stejnem ID vyhrava skript - ConnectorOperation ma implementation a scriptId - ApiError na klientovi nese cele telo odpovedi a umi z nej vytahnout issues - Dockerfile kopiruje scripts/ do vysledneho image Ukladani nemuze rozbit fungujici skript: kod se nejdriv zapise do docasneho souboru, ten se nacte a overi, a az pak prepise puvodni. K tomu tri dokumenty navrhu dalsich kroku: 09 datove modely a prava, 10 runtime a rozpocet na 150 klientu, 11 popis skriptu konektoru. Overeno: npm run typecheck prochazi na serveru i webu. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
81 lines
2.6 KiB
JavaScript
81 lines
2.6 KiB
JavaScript
/**
|
|
* iDoklad: odeslani vydane faktury e-mailem.
|
|
*
|
|
* Sluzba: https://services.csbot.cz/apps/idoklad
|
|
* Endpoint: POST /mail/issued-invoices/send
|
|
*
|
|
* Vzor akce, u ktere **odpoved sluzby nic nevraci**. Vystup se proto sklada
|
|
* z toho, co skript posilal, ne z toho, co prislo zpatky. Bez toho by strom
|
|
* za timhle krokem nemel na cem stavet podminku.
|
|
*
|
|
* Zaroven je to vzor toho, jak nahradit jeden vstup dvema chovanimi: kdyz je
|
|
* vyplneny e-mail, posle se na nej. Kdyz neni, posle se na adresu odberatele
|
|
* vedenou v iDokladu.
|
|
*/
|
|
|
|
export const manifest = {
|
|
id: 'idoklad.send-invoice-email',
|
|
name: 'Odeslat fakturu e-mailem',
|
|
description:
|
|
'Odešle vydanou fakturu e-mailem. Bez zadané adresy jde na e-mail ' +
|
|
'odběratele vedený v iDokladu.',
|
|
timeoutMs: 30000,
|
|
|
|
inputs: [
|
|
{ id: 'invoiceId', label: 'ID faktury v iDokladu', type: 'number', required: true },
|
|
{
|
|
id: 'email',
|
|
label: 'E-mail příjemce',
|
|
type: 'string',
|
|
required: false,
|
|
pattern: '^[^@\\s]+@[^@\\s]+\\.[A-Za-z]{2,}$',
|
|
hint: 'Nevyplněno = adresa odběratele z iDokladu.',
|
|
},
|
|
{ id: 'subject', label: 'Předmět', type: 'string', required: false },
|
|
{ id: 'body', label: 'Text e-mailu', type: 'string', required: false, multiline: true },
|
|
{
|
|
id: 'sendAttachment',
|
|
label: 'Přiložit PDF faktury',
|
|
type: 'boolean',
|
|
required: false,
|
|
default: true,
|
|
},
|
|
{
|
|
id: 'sendToSelf',
|
|
label: 'Poslat kopii sobě',
|
|
type: 'boolean',
|
|
required: false,
|
|
default: false,
|
|
},
|
|
],
|
|
|
|
outputs: [
|
|
{ id: 'sent', label: 'Odesláno', type: 'boolean', required: true },
|
|
{ id: 'recipient', label: 'Komu se odeslalo', type: 'string', required: true },
|
|
],
|
|
};
|
|
|
|
export async function run(inputs, ctx) {
|
|
const toGivenAddress = Boolean(inputs.email);
|
|
|
|
const payload = {
|
|
documentId: inputs.invoiceId,
|
|
// Vsechna tri pole jsou u iDokladu povinna, i kdyz jsou nepravdiva.
|
|
sendToPartner: !toGivenAddress,
|
|
sendToAccountant: false,
|
|
sendToSelf: inputs.sendToSelf ?? false,
|
|
sendAttachment: inputs.sendAttachment ?? true,
|
|
...(toGivenAddress ? { otherRecipients: [inputs.email] } : {}),
|
|
...(inputs.subject ? { emailSubject: inputs.subject } : {}),
|
|
...(inputs.body ? { emailBody: inputs.body } : {}),
|
|
};
|
|
|
|
// Nektere instance vraci 204 bez tela, jine 200 s potvrzenim. Obojí je uspech.
|
|
const { status } = await ctx.http.post('/mail/issued-invoices/send', payload);
|
|
|
|
const recipient = toGivenAddress ? String(inputs.email) : 'odběratel z iDokladu';
|
|
ctx.log(`Faktura ${inputs.invoiceId} odeslána (${recipient}), HTTP ${status}.`);
|
|
|
|
return { sent: true, recipient };
|
|
}
|