Files
csbot-prototype/scripts/sap-bo.find-business-partner.js
T
JiriUhlirandClaude Opus 5 a771834e57 Realne sluzby, OpenAI, odesilani e-mailu a helpdesk
Katalog srovnany s tim, co opravdu bezi na services.csbot.cz/apps:
trinact sluzeb dostalo pristupove udaje a levne cteci overeni, opravena
appId, ktera nikam nevedla (ppl, microsoft365, transcription), a GA4,
Search Console, Google Ads i Sklik ted stoji na aplikaci analytics,
kazda s vlastnimi udaji. Nove sluzby SAP Business One, Google Workspace
a Meta Ads. K tomu 23 skriptu, ktere s nimi opravdu neco delaji.

OpenAI jako prvni sluzba, ktera nebezi u nas: Service.baseUrl s absolutni
adresou, prepis pres <SLUZBA>_BASE_URL nebo adresu u konektoru, predpona
hlavicky u pole udaju (uzivatel vlepi holy klic, Bearer dopise runtime).
Dotaz na model, nahrani souboru, otazka nad souborem, prepis zvuku.
Skript umi odeslat soubor pres ctx.http.postForm (multipart, obsah Base64).

Sluzba E-mail pres SMTP. Neni to skript, ale vnitrni krok - SMTP neni HTTP.
Konektor nese schranku firmy, krok ma HTML telo, ve kterem se dosazene
hodnoty escapuji (znacky autora sablony jsou zamer, ostre zavorky od
zakaznika ne). Overeni konektoru se prihlasi na server a nic neodesle.

Helpdesk: Ticket.helpdeskSourceId drzi firmu, ktera pozadavek poslala,
vlastnikem zustava ta, ktera ho resi - jinak by ho resitel nemel ve sve
fronte. Komu pozadavek pripadne, urcuje Tenant.helpdeskProviderId.
Zadavatel vidi jen svoje pozadavky a smi k nim pripsat komentar.

Opravy v portalu:
- hlasky o ulozisti a odchozi IP vidi jen spravce platformy
- typ ticketu se v automatizaci vybira ze seznamu firmy, nebo dosadi z dat
- stav ticketu je otevreny naseptavac, ne ciselnik
- ticket jde zalozit rucne, zakaznik u nej neni povinny
- kanal se prejmenoval a parametry u webhooku jsou oznacene jako nepovinne
- srovnane markdown tabulky v cele dokumentaci

Co z teto davky jeste neni: prepinac firmy je porad jen stav uvnitr stranky
Prehled, takze se prepnuti neprojevi v Lidech ani jinde.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 07:40:16 +02:00

113 lines
3.4 KiB
JavaScript

/**
* SAP Business One: dohledani obchodniho partnera.
*
* Sluzba: https://services.csbot.cz/apps/sap-bo
* Endpoint: GET /api/business-partners?$filter=...
*
* Vzor **predvalidace nad OData**. Service Layer filtruje jazykem OData, kde
* se retezce uvozuji apostrofem - a apostrof v nazvu firmy by dotaz rozbil,
* takze se zdvojuje. Nenalezeno neni chyba: podle toho se strom vetvi na
* zalozeni noveho partnera.
*/
export const manifest = {
id: 'sap-bo.find-business-partner',
name: 'Najít obchodního partnera',
description:
'Dohledá partnera v SAP Business One podle kódu, IČO nebo názvu. ' +
'Nic nezakládá, výsledek slouží k větvení stromu.',
inputs: [
{
id: 'cardCode',
label: 'Kód partnera',
type: 'string',
required: false,
hint: 'Například C00123. Nejpřesnější, hledá se podle něj první.',
},
{
id: 'taxId',
label: 'IČO',
type: 'string',
required: false,
hint: 'Porovnává se s polem FederalTaxID.',
},
{
id: 'name',
label: 'Název',
type: 'string',
required: false,
hint: 'Stačí část názvu, hledá se podřetězec.',
},
],
outputs: [
{ id: 'found', label: 'Partner nalezen', type: 'boolean', required: true },
{ id: 'cardCode', label: 'Kód partnera', type: 'string', required: false },
{ id: 'cardName', label: 'Název partnera', type: 'string', required: false },
{ id: 'taxId', label: 'IČO', type: 'string', required: false },
{ id: 'currency', label: 'Měna', type: 'string', required: false },
{ id: 'matchedBy', label: 'Podle čeho se našel', type: 'string', required: true },
],
timeoutMs: 30000,
};
/** Retezec do OData filtru. Apostrof se zdvojuje, jinak dotaz spadne. */
function quote(value) {
return `'${String(value).replace(/'/g, "''")}'`;
}
const notFound = {
found: false,
cardCode: null,
cardName: null,
taxId: null,
currency: null,
matchedBy: 'nenalezeno',
};
export async function run(inputs, ctx) {
const { pick, text } = ctx.util;
if (!inputs.cardCode && !inputs.taxId && !inputs.name) {
ctx.fail('Vyplňte kód partnera, IČO nebo název, jinak není podle čeho hledat.');
}
// Poradi je zamer: kod je klic, ICO je jednoznacne, nazev se pise pokazde jinak.
const attempts = [];
if (inputs.cardCode) attempts.push([`CardCode eq ${quote(inputs.cardCode)}`, 'kód']);
if (inputs.taxId) attempts.push([`FederalTaxID eq ${quote(inputs.taxId)}`, 'IČO']);
if (inputs.name) attempts.push([`contains(CardName,${quote(inputs.name)})`, 'název']);
for (const [filter, label] of attempts) {
const { body } = await ctx.http.get('/api/business-partners', {
query: {
$filter: filter,
$select: 'CardCode,CardName,FederalTaxID,Currency,CardType',
$top: 5,
},
});
const raw = pick(body, 'value', 'data', 'items');
const items = Array.isArray(raw) ? raw : Array.isArray(body) ? body : [];
if (items.length === 0) {
ctx.log(`Podle ${label} se nic nenašlo.`);
continue;
}
if (items.length > 1) ctx.log(`Podle ${label} vyšlo ${items.length} partnerů, bere se první.`);
const partner = items[0];
return {
found: true,
cardCode: text(pick(partner, 'CardCode')),
cardName: text(pick(partner, 'CardName')),
taxId: text(pick(partner, 'FederalTaxID')),
currency: text(pick(partner, 'Currency')),
matchedBy: label,
};
}
return notFound;
}