Yesterday cutoff for actuals; two-row monthly summary cards
Both Weekly and Monthly now cut off actuals at yesterday (not today) to avoid partial clockins and open timesheets skewing the WTD/MTD figures and % net sales. PY comparison periods also cap at the equivalent yesterday for fair comparison. Monthly rota forecast removed — all future days use prior-week same-day actuals from yesterday back, which is more reliable than partially-published future rotas. Monthly summary cards split into two rows for current month: Row 1 (MTD to yesterday): Actual MTD · Budget pro-rata · % Budget MTD · % Net Sales MTD Row 2 (Full month): Forecast EOM · Monthly Budget · % Budget (Forecast) · % Net Sales (OTB) Net sales fetched for full month so row 2 % net sales uses OTB forecast revenue. Past months show one row (full month actuals only). Weekly: budget pro-rata now counts days Monday to yesterday for current week; dept totals filtered to yesterday for current week. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d04cd1e82c
commit
5b243b3ef8
3 changed files with 204 additions and 136 deletions
|
|
@ -51,11 +51,13 @@ export default function Weekly() {
|
|||
|
||||
const toStr = addDaysStr(fromStr, 6)
|
||||
const todayStr = localStr(new Date())
|
||||
const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1)
|
||||
const yesterdayStr = localStr(yesterday)
|
||||
const isCurrentWeek = fromStr === mondayOf(new Date())
|
||||
const pyFromStr = addDaysStr(fromStr, -364)
|
||||
// For current (partial) week cap PY at equivalent elapsed day — fair WTD comparison
|
||||
// Cut-off at yesterday: avoids partial clockins/open timesheets skewing today's figures
|
||||
const daysElapsed = isCurrentWeek
|
||||
? Math.round((new Date(todayStr + 'T00:00:00').getTime() - new Date(fromStr + 'T00:00:00').getTime()) / 86_400_000)
|
||||
? Math.round((new Date(yesterdayStr + 'T00:00:00').getTime() - new Date(fromStr + 'T00:00:00').getTime()) / 86_400_000)
|
||||
: 6
|
||||
const pyToStr = addDaysStr(fromStr, -364 + daysElapsed)
|
||||
|
||||
|
|
@ -87,12 +89,16 @@ export default function Weekly() {
|
|||
setDepts(actRes.departments)
|
||||
setShowOncosts(actRes.show_oncosts)
|
||||
setDeptPcts(actRes.dept_pcts)
|
||||
setNetSales(salesRes.days.reduce((s, d) => s + d.net_sales, 0))
|
||||
// For current week only sum PY sales for elapsed days (WTD = apples to apples)
|
||||
// Current week cut-off at yesterday to avoid partial clockins
|
||||
const isCurrentWk = fromStr === mondayOf(new Date())
|
||||
setNetSales(
|
||||
isCurrentWk
|
||||
? salesRes.days.filter(d => d.date <= yesterdayStr).reduce((s, d) => s + d.net_sales, 0)
|
||||
: salesRes.days.reduce((s, d) => s + d.net_sales, 0)
|
||||
)
|
||||
setPySales(
|
||||
isCurrentWk
|
||||
? salesRes.days.filter(d => d.date <= todayStr).reduce((s, d) => s + d.py_sales, 0)
|
||||
? salesRes.days.filter(d => d.date <= yesterdayStr).reduce((s, d) => s + d.py_sales, 0)
|
||||
: salesRes.days.reduce((s, d) => s + d.py_sales, 0)
|
||||
)
|
||||
|
||||
|
|
@ -110,10 +116,10 @@ export default function Weekly() {
|
|||
const bRow = (budgetRes.budgets as WageBudget[]).find(b => b.month === monthKey)
|
||||
if (bRow) {
|
||||
const dim = daysInMonthFor(fromStr)
|
||||
const effectiveTo = todayStr < toStr ? todayStr : toStr
|
||||
const effectiveFrom = fromStr > todayStr ? todayStr : fromStr
|
||||
const weekDays = effectiveTo >= effectiveFrom
|
||||
? Math.round((new Date(effectiveTo + 'T00:00:00').getTime() - new Date(effectiveFrom + 'T00:00:00').getTime()) / 86_400_000) + 1
|
||||
const cutoff = isCurrentWk ? yesterdayStr : toStr
|
||||
const effectiveTo = cutoff < toStr ? cutoff : toStr
|
||||
const weekDays = effectiveTo >= fromStr
|
||||
? Math.round((new Date(effectiveTo + 'T00:00:00').getTime() - new Date(fromStr + 'T00:00:00').getTime()) / 86_400_000) + 1
|
||||
: 7
|
||||
const ratio = weekDays / dim
|
||||
setMonthlyBudg(bRow.budget_amount)
|
||||
|
|
@ -151,7 +157,9 @@ export default function Weekly() {
|
|||
const deptTotals = depts.map(dep => ({
|
||||
department_id: dep.department_id,
|
||||
department_name: dep.department_name,
|
||||
cost: Object.values(dep.days).reduce((s, d) => s + d.cost, 0),
|
||||
cost: Object.entries(dep.days)
|
||||
.filter(([d]) => !isCurrentWeek || d <= yesterdayStr)
|
||||
.reduce((s, [, v]) => s + v.cost, 0),
|
||||
})).sort((a, b) => b.cost - a.cost)
|
||||
|
||||
const totalWages = deptTotals.reduce((s, d) => s + d.cost, 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue