Files
graphs/src/analytics/products.ts
Cauê Faleiros 72ded82ec7
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m12s
extract frontend analytics helpers
2026-05-27 15:58:12 -03:00

118 lines
3.3 KiB
TypeScript

import type { DateRange, OrderData, StockData } from '../types';
import { getBaseProductName, getOrderItemRevenue, isOrderInDateRange } from './orders';
export interface ProductSummary {
id: string;
name: string;
totalSold: number;
revenue: number;
lastPrice: number;
stock: number;
}
export interface ProductDetailsMetrics {
productInfo: {
id: string;
name: string;
price: number;
} | null;
chartData: Array<{
date: string;
value: number;
}>;
totalSold: number;
totalRevenue: number;
}
export const buildProductsSummary = (
ordersData: OrderData[],
stockData: StockData[],
dateRange: DateRange,
searchTerm: string
): ProductSummary[] => {
const productMap: Record<string, ProductSummary> = {};
stockData.forEach(item => {
productMap[item.produto_id] = {
id: item.produto_id,
name: item.nome,
totalSold: 0,
revenue: 0,
lastPrice: 0,
stock: item.saldo || 0
};
});
ordersData.forEach(order => {
if (!isOrderInDateRange(order, dateRange)) return;
if (!productMap[order.ID_Produto]) {
productMap[order.ID_Produto] = {
id: order.ID_Produto,
name: getBaseProductName(order.Descricao_Produto),
totalSold: 0,
revenue: 0,
lastPrice: order.Valor_Unitario,
stock: 0
};
}
if (productMap[order.ID_Produto].name === 'Unknown' || !productMap[order.ID_Produto].name) {
productMap[order.ID_Produto].name = getBaseProductName(order.Descricao_Produto);
}
productMap[order.ID_Produto].totalSold += order.Quantidade;
productMap[order.ID_Produto].revenue += getOrderItemRevenue(order);
productMap[order.ID_Produto].lastPrice = order.Valor_Unitario;
});
const normalizedSearch = searchTerm.trim().toLowerCase();
const products = Object.values(productMap);
const filteredProducts = normalizedSearch
? products.filter(product => product.name.toLowerCase().includes(normalizedSearch) || product.id.includes(searchTerm))
: products;
return filteredProducts.sort((a, b) => b.totalSold - a.totalSold);
};
export const buildProductDetailsMetrics = (
ordersData: OrderData[],
productId: string | undefined,
dateRange: DateRange
): ProductDetailsMetrics => {
const productOrders = ordersData.filter(order => order.ID_Produto === productId);
if (productOrders.length === 0) {
return { productInfo: null, chartData: [], totalSold: 0, totalRevenue: 0 };
}
const productInfo = {
id: productOrders[0].ID_Produto,
name: getBaseProductName(productOrders[0].Descricao_Produto),
price: productOrders[0].Valor_Unitario
};
const salesByDate: Record<string, number> = {};
let totalSold = 0;
let totalRevenue = 0;
productOrders.forEach(order => {
if (!isOrderInDateRange(order, dateRange)) return;
salesByDate[order.Data_Pedido] = (salesByDate[order.Data_Pedido] || 0) + order.Quantidade;
totalSold += order.Quantidade;
totalRevenue += getOrderItemRevenue(order);
});
const chartData = Object.keys(salesByDate).map(date => ({
date,
value: salesByDate[date]
})).sort((a, b) => {
const [da, ma, ya] = a.date.split('-').map(Number);
const [db, mb, yb] = b.date.split('-').map(Number);
return new Date(ya, ma - 1, da).getTime() - new Date(yb, mb - 1, db).getTime();
});
return { productInfo, chartData, totalSold, totalRevenue };
};