Fair PYTD comparison for current week/month
Weekly: cap pyToStr at elapsed days (not full Mon-Sun), and filter py_sales to past days only — both give WTD vs WTD. Labels show 'PY WTD' for current week, 'PY' for complete past weeks. Monthly: pyToStr already capped at same day-of-month; salesTo already capped at today. Labels now show 'PY MTD' for current month, 'PY' for complete past months. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
dc1a14a070
commit
44a7caa937
2 changed files with 20 additions and 11 deletions
|
|
@ -192,7 +192,7 @@ export default function Monthly() {
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
<div className="label">{isCurrentMonth ? 'Actual MTD' : 'Actual'}</div>
|
<div className="label">{isCurrentMonth ? 'Actual MTD' : 'Actual'}</div>
|
||||||
<div className="value">{fmtMoney(totalActual)}</div>
|
<div className="value">{fmtMoney(totalActual)}</div>
|
||||||
{pyWages != null && <div className="sub">PY {fmtMoney(pyWages)}{pyPct(totalActual, pyWages)}</div>}
|
{pyWages != null && <div className="sub">{isCurrentMonth ? 'PY MTD' : 'PY'} {fmtMoney(pyWages)}{pyPct(totalActual, pyWages)}</div>}
|
||||||
</div>
|
</div>
|
||||||
{isCurrentMonth && (
|
{isCurrentMonth && (
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
|
|
@ -221,7 +221,7 @@ export default function Monthly() {
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
<div className="label">{isCurrentMonth ? 'Net Sales MTD' : 'Net Sales'}</div>
|
<div className="label">{isCurrentMonth ? 'Net Sales MTD' : 'Net Sales'}</div>
|
||||||
<div className="value">{fmtMoney(netSales)}</div>
|
<div className="value">{fmtMoney(netSales)}</div>
|
||||||
{pySales > 0 && <div className="sub">PY {fmtMoney(pySales)}{pyPct(netSales, pySales)}</div>}
|
{pySales > 0 && <div className="sub">{isCurrentMonth ? 'PY MTD' : 'PY'} {fmtMoney(pySales)}{pyPct(netSales, pySales)}</div>}
|
||||||
</div>
|
</div>
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
<div className="label">% Net Sales</div>
|
<div className="label">% Net Sales</div>
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,15 @@ function pctClass(pct: number | null): string {
|
||||||
export default function Weekly() {
|
export default function Weekly() {
|
||||||
const [fromStr, setFromStr] = useState<string>(() => mondayOf(new Date()))
|
const [fromStr, setFromStr] = useState<string>(() => mondayOf(new Date()))
|
||||||
|
|
||||||
const toStr = addDaysStr(fromStr, 6)
|
const toStr = addDaysStr(fromStr, 6)
|
||||||
const todayStr = localStr(new Date())
|
const todayStr = localStr(new Date())
|
||||||
// Prior-year equivalent week (52 weeks back)
|
const isCurrentWeek = fromStr === mondayOf(new Date())
|
||||||
const pyFromStr = addDaysStr(fromStr, -364)
|
const pyFromStr = addDaysStr(fromStr, -364)
|
||||||
const pyToStr = addDaysStr(toStr, -364)
|
// For current (partial) week cap PY at equivalent elapsed day — fair WTD comparison
|
||||||
|
const daysElapsed = isCurrentWeek
|
||||||
|
? Math.round((new Date(todayStr + 'T00:00:00').getTime() - new Date(fromStr + 'T00:00:00').getTime()) / 86_400_000)
|
||||||
|
: 6
|
||||||
|
const pyToStr = addDaysStr(fromStr, -364 + daysElapsed)
|
||||||
|
|
||||||
const [depts, setDepts] = useState<DeptActuals[]>([])
|
const [depts, setDepts] = useState<DeptActuals[]>([])
|
||||||
const [netSales, setNetSales] = useState(0)
|
const [netSales, setNetSales] = useState(0)
|
||||||
|
|
@ -74,7 +78,13 @@ export default function Weekly() {
|
||||||
setShowOncosts(actRes.show_oncosts)
|
setShowOncosts(actRes.show_oncosts)
|
||||||
setDeptPcts(actRes.dept_pcts)
|
setDeptPcts(actRes.dept_pcts)
|
||||||
setNetSales(salesRes.days.reduce((s, d) => s + d.net_sales, 0))
|
setNetSales(salesRes.days.reduce((s, d) => s + d.net_sales, 0))
|
||||||
setPySales(salesRes.days.reduce((s, d) => s + d.py_sales, 0))
|
// For current week only sum PY sales for elapsed days (WTD = apples to apples)
|
||||||
|
const isCurrentWk = fromStr === mondayOf(new Date())
|
||||||
|
setPySales(
|
||||||
|
isCurrentWk
|
||||||
|
? salesRes.days.filter(d => d.date <= todayStr).reduce((s, d) => s + d.py_sales, 0)
|
||||||
|
: salesRes.days.reduce((s, d) => s + d.py_sales, 0)
|
||||||
|
)
|
||||||
|
|
||||||
const pyTotal = pyActRes.departments.reduce(
|
const pyTotal = pyActRes.departments.reduce(
|
||||||
(s, dep) => s + Object.values(dep.days).reduce((ds, d) => ds + d.cost, 0), 0
|
(s, dep) => s + Object.values(dep.days).reduce((ds, d) => ds + d.cost, 0), 0
|
||||||
|
|
@ -109,7 +119,6 @@ export default function Weekly() {
|
||||||
|
|
||||||
const prev = () => setFromStr(s => addDaysStr(s, -7))
|
const prev = () => setFromStr(s => addDaysStr(s, -7))
|
||||||
const next = () => setFromStr(s => addDaysStr(s, 7))
|
const next = () => setFromStr(s => addDaysStr(s, 7))
|
||||||
const isCurrentWeek = fromStr === mondayOf(new Date())
|
|
||||||
|
|
||||||
const deptWeekBudget = (deptId: string) =>
|
const deptWeekBudget = (deptId: string) =>
|
||||||
budget != null && monthlyBudg != null && (deptPcts[deptId] ?? 0) > 0
|
budget != null && monthlyBudg != null && (deptPcts[deptId] ?? 0) > 0
|
||||||
|
|
@ -154,7 +163,7 @@ export default function Weekly() {
|
||||||
<div className="label">Total Wages</div>
|
<div className="label">Total Wages</div>
|
||||||
<div className="value">{fmtMoney(totalWages)}</div>
|
<div className="value">{fmtMoney(totalWages)}</div>
|
||||||
{pyWages != null
|
{pyWages != null
|
||||||
? <div className="sub">PY {fmtMoney(pyWages)}{pyPct(totalWages, pyWages)}</div>
|
? <div className="sub">{isCurrentWeek ? 'PY WTD' : 'PY'} {fmtMoney(pyWages)}{pyPct(totalWages, pyWages)}</div>
|
||||||
: <div className="sub">{showOncosts ? 'incl. on-costs' : 'base cost'}</div>}
|
: <div className="sub">{showOncosts ? 'incl. on-costs' : 'base cost'}</div>}
|
||||||
</div>
|
</div>
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
|
|
@ -173,7 +182,7 @@ export default function Weekly() {
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
<div className="label">Net Sales</div>
|
<div className="label">Net Sales</div>
|
||||||
<div className="value">{fmtMoney(netSales)}</div>
|
<div className="value">{fmtMoney(netSales)}</div>
|
||||||
{pySales > 0 && <div className="sub">PY {fmtMoney(pySales)}{pyPct(netSales, pySales)}</div>}
|
{pySales > 0 && <div className="sub">{isCurrentWeek ? 'PY WTD' : 'PY'} {fmtMoney(pySales)}{pyPct(netSales, pySales)}</div>}
|
||||||
</div>
|
</div>
|
||||||
<div className="summary-card">
|
<div className="summary-card">
|
||||||
<div className="label">% of Net Sales</div>
|
<div className="label">% of Net Sales</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue