44 lines
2.3 KiB
JavaScript
44 lines
2.3 KiB
JavaScript
export function createDashboardService({ productService, inventoryItemService, listingService, saleService, acquisitionService, pricingRepository }) {
|
|
return {
|
|
async get({ sellerId }) {
|
|
const [products, inventory, listings, sales, acquisitions, valuations] = await Promise.all([
|
|
productService.listBySellerId(sellerId),
|
|
inventoryItemService.listBySellerId(sellerId),
|
|
listingService.list({ sellerId }),
|
|
saleService.list({ sellerId }),
|
|
acquisitionService.list({ sellerId }),
|
|
pricingRepository?.listLatestValuationsForSeller(sellerId) ?? [],
|
|
]);
|
|
|
|
const activeListings = listings.filter(({ status }) => ['AVAILABLE', 'PENDING'].includes(status));
|
|
const completedSales = sales.filter(({ status }) => status !== 'VOIDED');
|
|
const valuationByItem = new Map(valuations.map((valuation) => [valuation.inventoryItemId, valuation]));
|
|
const staleThreshold = 7 * 24 * 60 * 60 * 1000;
|
|
const total = (values, field) => values.reduce((sum, value) => sum + (value[field] ?? 0), 0);
|
|
|
|
return {
|
|
counts: {
|
|
products: products.length,
|
|
inventory: inventory.length,
|
|
activeInventory: inventory.filter(({ status }) => status === 'ACTIVE').length,
|
|
soldInventory: inventory.filter(({ status }) => status === 'SOLD').length,
|
|
availableListings: activeListings.length,
|
|
sales: completedSales.length,
|
|
acquisitions: acquisitions.length,
|
|
missingImages: listings.filter(({ imageCount }) => imageCount < 1).length,
|
|
missingPricing: inventory.filter(({ id }) => !valuationByItem.has(id)).length,
|
|
stalePricing: valuations.filter(({ calculatedAt }) => Date.now() - new Date(calculatedAt).getTime() > staleThreshold).length,
|
|
},
|
|
financials: {
|
|
totalAcquisitionCostMinor: total(acquisitions, 'costBasisMinor'),
|
|
totalAskingValueMinor: total(activeListings, 'askingPriceMinor'),
|
|
totalNetSaleProceedsMinor: total(completedSales, 'netProceedsMinor'),
|
|
totalProfitMinor: total(completedSales, 'profitMinor'),
|
|
totalMarketValueMinor: total([...valuationByItem.values()], 'valueMinor'),
|
|
},
|
|
recentSales: completedSales.slice(0, 5),
|
|
recentAcquisitions: acquisitions.slice(0, 5),
|
|
};
|
|
},
|
|
};
|
|
} |