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), }; }, }; }