Tema 3 pradedama nuo to, kuo baigėme Temoje 2: mokiniai jau žino, kad pirkimo sąskaitų techninis duomenų šaltinis yra purchaseInvoices, o sąskaitos eilutės gaunamos per lines. Šioje temoje tą patį duomenų kelią pakartosime per Apollo Sandbox, tada perkelsime į ERP Report scriptą, išvesime JSON, „išflatinsime“ eilutes, papildysime duomenis antra užklausa ir paruošime failą parsisiuntimui.
Visi žingsniai remiasi tuo pačiu verslo klausimu: kaip iš pirkimo sąskaitų ištraukti antraštę, tiekėją, prekes, kiekius ir sumas, o tada šiuos duomenis paruošti ataskaitai ar failui.
| Etapas | Ką darome | Siekamas rezultatas |
|---|---|---|
| 1. Apollo Query | Schema Reference skiltyje susirandame purchaseInvoices Query ir jo grąžinamus laukus. |
Mokinys supranta, kokius laukus gali pasirinkti užklausoje ir mato JSON atsakymą. |
| 2. ERP Report scriptas | Sukuriame naują ERP Report scriptą ir padarome tokią pačią purchaseInvoices užklausą per rql. |
Ekrane matomas žalias JSON per output = { data: ... }. |
| 3. Flat JSON | Su JavaScript ciklais iš sąskaitos ir jos eilučių padarome vieno lygio masyvą. | Kiekviena prekės eilutė tampa viena JSON eilute su dokumento ir prekės laukais. |
| 4. Antra užklausa ir apjungimas | Iš pirmos užklausos paimame itemId reikšmes, užklausiame products ir apjungiame rezultatą. |
Flat eilutės papildomos tikru prekės kodu / pavadinimu iš prekės kortelės. |
| 5. Failas | Iš suformatuotų duomenų suformuojame CSV failą ir grąžiname parsisiuntimo nuorodą. | Mokinys turi failą, kurį gali parsisiųsti į savo kompiuterį. |
Apollo Sandbox pasiekiamas adresu https://erp.test.rivile.cloud/graphql-gen3. Naudokite tą pačią naršyklę, kurioje esate prisijungę prie Rivile ERP TEST aplinkos, kad sesija būtų atpažinta.
purchaseInvoices.size, filtrai, puslapiavimas ar kiti jūsų versijoje matomi parametrai.purchaseInvoices?content, totalElements, page ar analogas)?lines ar analogą)?clientId, clientName, įterptą client objektą ar kitus jūsų schemos laukus?purchaseInvoicesUžduotis: Apollo aplinkoje susirasti Query purchaseInvoices ir padaryti užklausą, kuri grąžintų: dokumento datą, dokumento numerį, dokumento būseną, tiekėjo informaciją, prekių informaciją, kiekius ir sumas.
query PurchaseInvoicesForTraining($companyId: UUID) {
purchaseInvoices(companyId: $companyId) {
content {
id
docDate
opDate
documentNo
statusId
status {
name
}
clientId
clientName
client {
id
code
name
}
lines {
id
itemId
itemName
qtyBase
price
amount
amountWithTax
}
}
totalElements
totalPages
}
}
Variables:
{
"companyId": "12e405fc-3487-4360-836d-855ab8500bfa"
}
Jei Apollo rodo, kad jūsų aplinkoje
purchaseInvoicesargumentai ar laukai vadinasi kitaip, koreguokite pavyzdį pagal schemą. Pvz. būsenos laukas gali būtistatus,statusIdar susijęs objektas; tiekėjas gali būticlientName/clientIdarba įterptasclient.
Siekamas rezultatas: mokinys turi veikiantį GraphQL Query ir JSON atsakymą, kuriame aiškiai matoma sąskaitos antraštė ir eilučių masyvas.
Toliau tą pačią užduotį perkeliame į ERP Report scriptą. Tikslas — susikurti naują reportą, jame padaryti PurchaseInvoice užklausą ir rezultatą išvesti į ekraną JSON formatu.
companyId ir rql užklausą.output = { data: ... }.log.info kaip duomenų išvedimo būdo reporto peržiūroje.const invoicePage = await rql(`
SELECT id, docDate, opDate, documentNo, statusId, status.name, clientId, clientName,
lines.item.code, lines.item.name,
lines.itemName, lines.qtyBase, lines.price, lines.amount, lines.amountWithTax
FROM purchaseInvoices
WITH companyId = ${companyId}
size = 10
`);
const purchaseInvoiceData = invoicePage?.content ?? [];
output = {
initial: initial,
companyId: `${companyId}`,
data: purchaseInvoiceData,
};
Siekamas rezultatas: reporto peržiūroje matomas žalias JSON masyvas su pirkimo sąskaitomis ir jų eilutėmis.
purchaseInvoices rezultato transformacija į flat JSONDabar iš hierarchinės struktūros (sąskaita → eilutės) padarome vieno lygio masyvą. Kiekviena sąskaitos eilutė tampa viena eilute, kurioje pakartojama dokumento informacija ir pridedami prekės laukai.
Flat rezultato laukai: Dokumento Data, Dokumento Numeris, Prekės kodas, Prekės pavadinimas, Kiekis, Kaina, Suma su PVM.
const flatRows = [];
for (const inv of purchaseInvoiceData) {
for (const line of inv.lines ?? []) {
flatRows.push({
dokumentoData: inv.docDate ?? inv.opDate,
dokumentoNumeris: inv.documentNo,
busena: inv.statusName ?? inv.statusId,
tiekejas: inv.clientName,
prekesId: line.itemId,
prekesKodas: line.itemCode ?? line.productCode ?? line.itemId,
prekesPavadinimas: line.itemName,
kiekis: line.qtyBase,
kaina: line.price,
sumaSuPvm: line.amountWithTax,
});
}
}
output = {
data: flatRows,
};
Siekamas rezultatas: mokinys pamato, kaip su JavaScript ciklu galima „flatinti“ duomenis: nebelieka įdėtinio lines masyvo, o kiekviena prekė tampa atskira ataskaitos eilute.
Dažna praktinė situacija: pirmoje užklausoje turime tik prekės ID arba nepilną prekės informaciją. Tada iš pirmos užklausos rezultato paimame itemId reikšmes, padarome antrą užklausą į products ir apjungiame duomenis į naują JSON.
const productIds = [
...new Set(
flatRows
.map((row) => row.prekesId)
.filter(Boolean)
),
];
let products = [];
if (productIds.length > 0) {
const productFilter = productIds.map((id) => toString(id)).join(", ");
const productsPage = await rql(`
SELECT id, code, name
FROM products
WITH companyId = ${companyId} size = ${productIds.length}
WHERE id IN (${productFilter})
`);
products = productsPage?.content ?? [];
}
const productsById = new Map(
products.map((product) => [product.id, product])
);
const enrichedRows = flatRows.map((row) => {
const product = productsById.get(row.prekesId);
return {
dokumentoData: row.dokumentoData,
dokumentoNumeris: row.dokumentoNumeris,
busena: row.busena,
tiekejas: row.tiekejas,
prekesKodas: product?.code ?? row.prekesKodas,
prekesPavadinimas: product?.name ?? row.prekesPavadinimas,
kiekis: row.kiekis,
kaina: row.kaina,
sumaSuPvm: row.sumaSuPvm,
};
});
output = {
data: enrichedRows,
};
Jei jūsų RQL versijoje
IN (...)sintaksė neveikia, tą patį mokymo tikslą galima pasiekti paprasčiau: pasirinkite vienąitemIdir padarykite antrą užklausą tik jam, arba naudokite dėstytojo parodytą filtravimo sintaksę pagal jūsų aplinkos RQL taisykles.
Siekamas rezultatas: mokinys supranta, kaip viena užklausa tampa įėjimu kitai užklausai, o kelių šaltinių rezultatai apjungiami į vieną JSON masyvą.
Paskutinis žingsnis — iš enrichedRows pasidaryti failą. Mokymams pradedame nuo CSV, nes jo struktūra aiški: pirmoje eilutėje antraštės, toliau — suformatuotos duomenų eilutės.
const headers = [
"Dokumento Data",
"Dokumento Numeris",
"Būsena",
"Tiekėjas",
"Prekės kodas",
"Prekės pavadinimas",
"Kiekis",
"Kaina",
"Suma su PVM",
];
const esc = (value) =>
'"' + String(value ?? "").replace(/"/g, '""') + '"';
const csvLines = [headers.join(";")];
for (const row of enrichedRows) {
csvLines.push([
row.dokumentoData,
row.dokumentoNumeris,
row.busena,
row.tiekejas,
row.prekesKodas,
row.prekesPavadinimas,
row.kiekis,
row.kaina,
row.sumaSuPvm,
].map(esc).join(";"));
}
const csvText = csvLines.join("\n");
const uploadedFile = await fileService.uploadFile(
csvText,
"purchase-invoices.csv",
{
fileType: "ATTACHMENT",
isTemporary: true,
generatePublicLink: true,
}
);
output = {
data: {
rows: enrichedRows,
file: {
id: uploadedFile.id,
fileName: "purchase-invoices.csv",
publicLink: uploadedFile.publicLink,
internalLink: uploadedFile.internalLink,
},
},
};
Jei konkrečiame Report kontekste fileService.uploadFile dar nėra leidžiamas, laikinai grąžinkite csvText per output.data. Tuomet mokymų tikslas lieka tas pats: pirma suformuojame turinį, vėliau jį prijungiame prie patvirtinto failų API.
Siekamas rezultatas: reporto rezultato JSON turi rows masyvą ir file.publicLink, per kurį failą galima atsisiųsti.
output.data.purchaseInvoices rezultatą per output.data.flatRows transformaciją su laukais: Dokumento Data, Dokumento Numeris, Prekės kodas, Prekės pavadinimas, Kiekis, Kaina, Suma su PVM.products ir papildykite rezultatą prekės kodu / pavadinimu iš prekės kortelės.fileService.uploadFile.