u
This commit is contained in:
50
src/defaultApplets/order-revenue-by-month.applet.js
Normal file
50
src/defaultApplets/order-revenue-by-month.applet.js
Normal file
@@ -0,0 +1,50 @@
|
||||
// @applet-input-schema {"type":"object","properties":{"month":{"type":"string","title":"Month (YYYY-MM)","default":"","description":"Only include orders placed in this month. Leave empty for all months."},"limit":{"type":"integer","title":"Max rows","default":50,"minimum":1,"maximum":500}}}
|
||||
// @applet-output-schema month:string;orders:integer;positions:integer;net:number
|
||||
//
|
||||
// Order revenue by month — orders grouped per calendar month.
|
||||
//
|
||||
// Demonstrates: paging, then aggregating into a Map keyed by `YYYY-MM` and rendering a small
|
||||
// report. `GET /order` list rows already carry their line items, so no detail call is needed.
|
||||
// Endpoints: GET /order (paged).
|
||||
|
||||
module.exports = async function (applet_input) {
|
||||
const only = String(applet_input.month || '').trim();
|
||||
const maxRows = Math.max(1, Number(applet_input.limit) || 50);
|
||||
|
||||
// 1. Page through orders.
|
||||
const orders = [];
|
||||
let offset = 0;
|
||||
for (;;) {
|
||||
const res = await fetch(`/order?offset=${offset}&limit=100`);
|
||||
if (!res.ok) throw new Error(`GET /order failed: ${res.status}`);
|
||||
const data = await res.json();
|
||||
const page = data.orders || [];
|
||||
orders.push(...page);
|
||||
offset += page.length;
|
||||
if (page.length === 0 || offset >= (data.total ?? orders.length)) break;
|
||||
}
|
||||
|
||||
// 2. Aggregate per calendar month.
|
||||
const buckets = new Map();
|
||||
for (const order of orders) {
|
||||
const month = String(order.date || '').slice(0, 7);
|
||||
if (!month) continue;
|
||||
if (only && month !== only) continue;
|
||||
const bucket = buckets.get(month) || { month, orders: 0, positions: 0, net: 0 };
|
||||
bucket.orders += 1;
|
||||
for (const line of order.lines || []) {
|
||||
bucket.positions += 1;
|
||||
bucket.net += (line.amount || 0) * (line.net || 0);
|
||||
}
|
||||
buckets.set(month, bucket);
|
||||
}
|
||||
|
||||
const rows = [...buckets.values()]
|
||||
.map((b) => ({ ...b, net: Math.round(b.net * 100) / 100 }))
|
||||
.sort((a, b) => a.month.localeCompare(b.month))
|
||||
.slice(-maxRows);
|
||||
|
||||
const totalNet = rows.reduce((sum, r) => sum + r.net, 0);
|
||||
console.log(`${rows.length} month(s), ${rows.reduce((n, r) => n + r.orders, 0)} order(s), net ${totalNet.toFixed(2)}.`);
|
||||
return rows;
|
||||
};
|
||||
Reference in New Issue
Block a user