Net sales: use forecast (otb + pickup) instead of otb-only for future dates
The forecasting API's total.otb is booked-to-date only; total.forecast adds expected pickup and equals otb for past dates anyway. Using otb-only for future days understated expected net sales in the current-week/month forecast sections. Relabelled "(OTB)" cards to "(Forecast)" to match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
320a0ce1ec
commit
69b4c50e14
3 changed files with 10 additions and 9 deletions
|
|
@ -40,13 +40,14 @@ export async function netSalesRoutes(fastify) {
|
||||||
const startStr = batchStart.toISOString().slice(0, 10)
|
const startStr = batchStart.toISOString().slice(0, 10)
|
||||||
const data = await fcFetch(`/forecast/revenue?start_date=${startStr}&days=${batchDays}&type=all&dow_align=true`)
|
const data = await fcFetch(`/forecast/revenue?start_date=${startStr}&days=${batchDays}&type=all&dow_align=true`)
|
||||||
for (const d of (data?.data ?? [])) {
|
for (const d of (data?.data ?? [])) {
|
||||||
|
// forecast = otb + expected pickup for future dates; equals otb for past dates
|
||||||
allDays.push({
|
allDays.push({
|
||||||
date: d.date,
|
date: d.date,
|
||||||
net_sales: parseFloat(d.total?.otb ?? 0),
|
net_sales: parseFloat(d.total?.forecast ?? d.total?.otb ?? 0),
|
||||||
py_sales: parseFloat(d.total?.prior_final ?? 0),
|
py_sales: parseFloat(d.total?.prior_final ?? 0),
|
||||||
accom: parseFloat(d.accom?.otb ?? 0),
|
accom: parseFloat(d.accom?.forecast ?? d.accom?.otb ?? 0),
|
||||||
dry: parseFloat(d.dry?.otb ?? 0),
|
dry: parseFloat(d.dry?.forecast ?? d.dry?.otb ?? 0),
|
||||||
wet: parseFloat(d.wet?.otb ?? 0),
|
wet: parseFloat(d.wet?.forecast ?? d.wet?.otb ?? 0),
|
||||||
is_past: d.is_past ?? true,
|
is_past: d.is_past ?? true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -303,14 +303,14 @@ export default function Monthly() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
<div className="label">% Net Sales (OTB)</div>
|
<div className="label">% Net Sales (Forecast)</div>
|
||||||
<div className="value">{pctSalesFull != null ? `${pctSalesFull.toFixed(1)}%` : '—'}</div>
|
<div className="value">{pctSalesFull != null ? `${pctSalesFull.toFixed(1)}%` : '—'}</div>
|
||||||
{pyWagesFull != null && pySalesFull > 0 && (
|
{pyWagesFull != null && pySalesFull > 0 && (
|
||||||
<div className="sub">PY {((pyWagesFull / pySalesFull) * 100).toFixed(1)}%</div>
|
<div className="sub">PY {((pyWagesFull / pySalesFull) * 100).toFixed(1)}%</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
<div className="label">Net Sales (OTB)</div>
|
<div className="label">Net Sales (Forecast)</div>
|
||||||
<div className="value">{fmtMoney(netSalesFull)}</div>
|
<div className="value">{fmtMoney(netSalesFull)}</div>
|
||||||
{pySalesFull > 0 && <div className="sub">PY {fmtMoney(pySalesFull)}{pyPct(netSalesFull, pySalesFull)}</div>}
|
{pySalesFull > 0 && <div className="sub">PY {fmtMoney(pySalesFull)}{pyPct(netSalesFull, pySalesFull)}</div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -272,11 +272,11 @@ export default function Weekly() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
<div className="label">% Net Sales (OTB)</div>
|
<div className="label">% Net Sales (Forecast)</div>
|
||||||
<div className="value">{pctSalesFull != null ? `${pctSalesFull.toFixed(1)}%` : '—'}</div>
|
<div className="value">{pctSalesFull != null ? `${pctSalesFull.toFixed(1)}%` : '—'}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
<div className="label">Net Sales (OTB)</div>
|
<div className="label">Net Sales (Forecast)</div>
|
||||||
<div className="value">{fmtMoney(netSalesFull)}</div>
|
<div className="value">{fmtMoney(netSalesFull)}</div>
|
||||||
{pySalesFull > 0 && <div className="sub">PY {fmtMoney(pySalesFull)}{pyPct(netSalesFull, pySalesFull)}</div>}
|
{pySalesFull > 0 && <div className="sub">PY {fmtMoney(pySalesFull)}{pyPct(netSalesFull, pySalesFull)}</div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue