import { enhance } from "@zenstackhq/runtime"; import { random_rgba } from "~/utils/color"; import { volume } from "~/utils/conversions"; import timeAgo from "~/utils/datetime"; import { db } from "~/utils/db.server"; import { randomRange } from "~/utils/random"; export async function generateDrinksChartData(id: number){ const dbe = enhance(db); // Get the previous month in dates var dates = []; const now = Date.now(); const subtracter = (1000 * 60 * 60 * 24); for(let i = 0; i <= 30; i++){ let date = now - (subtracter * i); dates.push(new Date(date)); } dates.reverse(); // Generate labels const labels = dates.map((date)=> timeAgo(date)); // History of specific drink const containersWithHistory = await dbe.container.findMany({ where: {drink_id: id}, include: {checkouts: {orderBy: {checkoutAt: "asc"}, where: {checkoutAt: {gte: dates[0]}}}} }) var datasets : any = []; for(let container of containersWithHistory){ if(container.inventory == 0 && container.checkouts.length == 0) continue; var history = container.checkouts; var totalInventory = container.inventory; // Generate arrays of data var checkouts = []; var inventoryAfter = []; var lastInventoryAfter = history.length > 0 ? history[0].inventoryAfter + 1 : 0; var previousCheckoutInventoryAfter = history.length > 0 ? history[0].inventoryAfter : 0; var lastChange = 0; var previousLastChange = 0; for(let i = 0; i <= dates.length - 1; i++){ let startDate = dates[i]; let endDate = dates[i+1]; let totalCheckouts = 0; for(let entry of history){ if(entry.checkoutAt > startDate && entry.checkoutAt < endDate){ totalCheckouts++; lastInventoryAfter = entry.inventoryAfter; lastChange = i; } } // There was inventory added if((lastInventoryAfter + totalCheckouts) > previousCheckoutInventoryAfter){ if(i > 0 && checkouts[i-1] > 0){ // Special case, there were also checkouts the previous day, do nothing } else if(i > 0) { let index = randomRange(previousLastChange + 1, i - 1); for(let j = index; j <= i - 1; j++){ inventoryAfter[j] = lastInventoryAfter + totalCheckouts; } } } previousCheckoutInventoryAfter = lastInventoryAfter; previousLastChange = lastChange; checkouts[i] = totalCheckouts; inventoryAfter[i] = lastInventoryAfter; } // Force the remaining inventory left values after the last checkout to be equal to // the actual remaining inventory let index = randomRange(lastChange + 1, dates.length - 1); for(let i = index; i <= dates.length - 1; i++){ inventoryAfter[i] = totalInventory; } let [color1, color2] = random_rgba(2); datasets.push({ type: "line", label: 'Inventory ' + volume(container.volume), data: inventoryAfter, borderColor: color1, backgroundColor: color1, tension: 0.1 }); datasets.push({ type: 'bar', label: 'Checkouts ' + volume(container.volume), data: checkouts, borderColor: color2, backgroundColor: color2, }); } const data = { labels, datasets: datasets }; return data; }