Praktika · Finansai ir dokumentai (P01–P06)

P01 · Po pirkimo užsakymo patvirtinimo — gavimas ir pranešimas

GraphQL domenas: purchaseOrder, dokumentai / el. paštas (sendEmailTemplate mutacijų grupė schemoje).

Parametrai (formos schema)

/* Įvykio trigeris — dažnai be formos; jei reikia šablono ID: */
[ { "blockType": "SELECT", "meta": { "fieldName": "emailTemplateCode", "required": true,
    "meta": { "getItems": "rql:@MDPAGE SELECT code, name FROM emailTemplates WHERE active = true" } } } ]

Scenarijaus fragmentas

// Po įvykio: purchaseOrder jau kontekste; imame ID iš trigerio konteksto (pseudokodas)
const orderId = initial?.purchaseOrderId ?? initial?.id;
if (!orderId) throw new UserError("Nėra užsakymo konteksto");

const rows = await rql(`
  SELECT id, documentNo, supplier.id, supplier.name
  FROM purchaseOrders
  WITH companyId = ${companyId}
  WHERE id = ${toString(orderId)}
`);
const po = rows?.content?.[0];
await log.info("Apdorojamas PO: " + JSON.stringify(po));

try {
  // Kurti gavimą — tikslų mutate vardą ir payload tikrinkite pagal SDL
  await mutate("createGoodsReceiptFromPurchaseOrder", { purchaseOrderId: orderId }, { select: ["id", "documentNo"] });
} catch (error) {
  await log.error("createGoodsReceiptFromPurchaseOrder: " + (error?.message ?? error));
  throw error;
}

output = { message: "Gavimas sukurtas / pranešimas išsiųstas", documentsCount: 1 };

P02 · Rankinis „Siųsti į WMS“

GraphQL: sąrašas purchaseOrder(s); veiksmas per mutate į WMS API (tikslus vardas iš schemos).

Parametrai

[ { "blockType": "SELECT", "meta": { "fieldName": "wmsQueueCode", "required": true,
    "meta": { "getItems": "rql:SELECT code, name FROM classifierItems WHERE ..." } } } ]

Scenarijus

const ids = initial?.ids ?? [];
if (ids.length < 1) throw new UserError("Pažymėkite bent vieną užsakymą"));

const queue = initial.wmsQueueCode;
await log.info(`WMS eilė: ${queue}, užsakymų: ${ids.length}`);

for (const id of ids) {
  try {
    await mutate("postPurchaseOrderToWms", { purchaseOrderId: id, queueCode: queue });
    await log.info("PO " + id + " perduota į WMS");
  } catch (error) {
    await log.error(JSON.stringify({ id, error: error?.message }));
  }
}
output = { message: "WMS: apdorota " + ids.length + " užsakymų", executionStatus: "WARNING" };

P03 · CRON: laukiančių sąskaitų suvestinė

GraphQL: purchaseInvoice(s), puslapiavimas *Page.

Scenarijus (suvestinė į žurnalą)

const pending = await rql(`
  SELECT id, documentNo, totalAmount, dueDate
  FROM purchaseInvoices
  WITH companyId = ${companyId} size = 500
  WHERE status = 'PENDING_APPROVAL'
`);
const list = pending?.content ?? [];
await log.info("Laukiančių sąskaitų: " + list.length);
// Čia galima sendEmailTemplate / sukurti vidinę užduotį — pagal mutacijų sąrašą schemoje
output = { message: "Suvestinė žurnale", documentsCount: list.length, pendingIds: list.map(function (x) { return x.id; }) };
Pastaba

CRON paleidžia scheduler kontekstą — auditas „automation user“ (žr. Tema 8).

P04 · PVM dokumentas — tikrinimas prieš uždarymą

GraphQL: apskaitos dokumentai; sinchroninis lūkestis vartotojui — trumpas rql + sąlyga.

const docId = initial?.id;
if (!docId) throw new UserError("Nėra dokumento");

const chk = await rql(`
  SELECT id, taxTotal, linesCount FROM accountingDocuments
  WITH companyId = ${companyId} WHERE id = ${toString(docId)}
`);
const row = chk?.content?.[0];
if (!row || row.taxTotal == null) {
  throw new UserError("PVM suma nepatvirtinta — užbaigti negalima");
}
await log.info("PVM tikrinimas OK: " + docId);
output = { message: "Tikrinimas sėkmingas", documentsCount: 1 };

P05 · Dublikuotos taisyklės (įmonė ir globalus lygis)

Scenarijaus logika: aiškiai tikrinti companyId ir ar taisyklė turi vykti tik vienoje apimtyje.

const ruleScope = initial?.ruleScope ?? "COMPANY_ONLY";
await log.info("Vykdymo apimtis: " + ruleScope + ", companyId=" + companyId);

if (ruleScope === "COMPANY_ONLY" && initial?.targetCompanyId && initial.targetCompanyId !== companyId) {
  output = { message: "Praleista — ne ta įmonė", executionStatus: "SUCCESS", documentsCount: 0 };
} else {
  // ... bendra logika
  output = { message: "Atlikta" };
}

P06 · Banko importas — partijos ir klaidos

GraphQL: banko operacijos / batch mutacijos grupė; čia — partijų ciklas su try/catch.

const BATCH = 200;
const rows = initial?.importRows ?? []; // arba nuskaityta iš failo
let ok = 0, failed = [];

for (let i = 0; i < rows.length; i += BATCH) {
  const chunk = rows.slice(i, i + BATCH);
  await log.info(`Partija ${i}-${i + chunk.length}`);
  for (const row of chunk) {
    try {
      await mutate("createBankStatementLine", { line: row }); // vardas iliustratyvus
      ok++;
    } catch (error) {
      failed.push({ row, error: error?.message });
      await log.error("Eilutė: " + JSON.stringify(row) + " → " + error?.message);
    }
  }
}
output = {
  message: failed.length ? `Baigta su klaidomis: OK ${ok}, klaidų ${failed.length}` : `OK: ${ok}`,
  executionStatus: failed.length ? "WARNING" : "SUCCESS",
  documentsCount: ok,
  failedSample: failed.slice(0, 20)
};