From c881dd7ddea72c79781ded94b44dc53e49eca26f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Faleiros?= Date: Tue, 7 Jul 2026 14:29:21 -0300 Subject: [PATCH] Separate replenishment coverage target --- src/pages/Replenishment.tsx | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/pages/Replenishment.tsx b/src/pages/Replenishment.tsx index f9db27c..45251d5 100644 --- a/src/pages/Replenishment.tsx +++ b/src/pages/Replenishment.tsx @@ -59,6 +59,8 @@ const filterOptions: Array<{ value: ReplenishmentFilter; label: string }> = [ { value: 'no_sales', label: 'Sem venda' } ]; +const coverageTargetOptions = [7, 15, 30, 60]; + const formatNumber = (value: number, maximumFractionDigits = 0) => ( new Intl.NumberFormat('pt-BR', { maximumFractionDigits }).format(value) ); @@ -121,9 +123,9 @@ const Replenishment = () => { }); const [sortBy, setSortBy] = useState('need_desc'); const [viewMode, setViewMode] = useState(() => searchParams.get('view') === 'group' ? 'group' : 'sku'); + const [targetCoverageDays, setTargetCoverageDays] = useState(30); const [currentPage, setCurrentPage] = useState(1); const [itemsPerPage, setItemsPerPage] = useState(10); - const horizonDays = useMemo(() => getRangeDays(dateRange), [dateRange]); useEffect(() => { let isMounted = true; @@ -150,7 +152,7 @@ const Replenishment = () => { return products.map(product => { const dailySales = product.quantitySold / rangeDays; - const projectedDemand = dailySales * horizonDays; + const projectedDemand = dailySales * targetCoverageDays; const rawNeed = projectedDemand - product.stock; const suggestedQuantity = Math.max(0, Math.ceil(rawNeed)); const daysOfCover = dailySales > 0 ? product.stock / dailySales : null; @@ -180,7 +182,7 @@ const Replenishment = () => { sizes: metadata.size ? [metadata.size] : [] }; }); - }, [dateRange, horizonDays, products]); + }, [dateRange, products, targetCoverageDays]); const groupedRows = useMemo(() => { const groups = new Map(); @@ -287,7 +289,7 @@ const Replenishment = () => {

Necessidade de Reposição

- O período selecionado define a base de vendas e a duração da projeção de reposição. + O período selecionado define a base de vendas; a cobertura define quantos dias de estoque sugerir.

@@ -310,7 +312,7 @@ const Replenishment = () => { 'Tamanhos': row.sizes.join(' | '), 'SKUs': row.productCount, 'Status': row.statusLabel, - 'Horizonte (dias)': horizonDays, + 'Cobertura alvo (dias)': targetCoverageDays, 'Vendido no Periodo': row.quantitySold, 'Media Diaria': row.dailySales.toFixed(2).replace('.', ','), 'Demanda Projetada': row.projectedDemand.toFixed(2).replace('.', ','), @@ -352,7 +354,7 @@ const Replenishment = () => {

Sugestão total

{formatNumber(totalSuggestedQuantity)}

-

Unidades para cobrir {horizonDays} dias

+

Unidades para cobrir {targetCoverageDays} dias

@@ -387,7 +389,7 @@ const Replenishment = () => {
-
+
{[ { key: 'sku' as const, label: 'SKU' }, @@ -425,6 +427,20 @@ const Replenishment = () => { />
+ +