monitoring/wealth: dash the in-progress year on the hourly-rate panel
All checks were successful
ci/woodpecker/push/default Pipeline was successful
All checks were successful
ci/woodpecker/push/default Pipeline was successful
The current, still-accruing calendar year read misleadingly high (e.g. 2026 at 5 months showed £149/h gross, above all of 2025) because the full-year bonus - paid every March - plus front-loaded quarterly RSU vests get divided by only the months worked so far. It settles lower as the year completes. Split each line into a solid series (complete years) and a dashed series (the latest, still-accruing year), so the provisional point is visually flagged. The split auto-detects the in-progress year (latest year with < 12 months of payslips), so it needs no per-year maintenance. Panel description now explains the caveat. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
28984dda9a
commit
5a312563c6
1 changed files with 60 additions and 2 deletions
|
|
@ -1509,7 +1509,7 @@
|
|||
{
|
||||
"id": 9230,
|
||||
"title": "Effective hourly rate \u2014 gross vs net (\u00a3/h, per year)",
|
||||
"description": "Annual pay \u00f7 hours worked. Hours = 40h/week contractual (2,080h per full year, per offer letter: Mon\u2013Fri 9\u201318 less 1h lunch), prorated by months actually worked. Gross = gross_pay incl. notional RSU vest; Net = take-home (RSU offset out). Calendar year; last 10y.",
|
||||
"description": "Annual pay \u00f7 hours worked. Hours = 40h/week contractual (2,080h per full year, per offer letter: Mon\u2013Fri 09:00\u201318:00 less 1h lunch), prorated by months actually worked. Gross = gross_pay incl. notional RSU vest; Net = take-home. The latest still-accruing year is shown DASHED: it reads high because the full-year bonus (paid each March) and front-loaded quarterly RSU vests are divided by only the months worked so far, and settles lower as the year completes. Calendar year; last 10y.",
|
||||
"type": "timeseries",
|
||||
"datasource": {
|
||||
"type": "grafana-postgresql-datasource",
|
||||
|
|
@ -1575,6 +1575,64 @@
|
|||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Gross (current yr, partial)"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"mode": "fixed",
|
||||
"fixedColor": "#FF9830"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "custom.lineStyle",
|
||||
"value": {
|
||||
"fill": "dash",
|
||||
"dash": [
|
||||
10,
|
||||
10
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "custom.fillOpacity",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Net (current yr, partial)"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"mode": "fixed",
|
||||
"fixedColor": "blue"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "custom.lineStyle",
|
||||
"value": {
|
||||
"fill": "dash",
|
||||
"dash": [
|
||||
10,
|
||||
10
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "custom.fillOpacity",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -1603,7 +1661,7 @@
|
|||
"format": "time_series",
|
||||
"editorMode": "code",
|
||||
"rawQuery": true,
|
||||
"rawSql": "WITH y AS (\n SELECT date_trunc('year', pay_date) AS yr,\n COUNT(DISTINCT date_trunc('month', pay_date)) AS months,\n SUM(gross_pay) AS gross,\n SUM(net_pay) AS net\n FROM payslip_ingest.payslip\n GROUP BY 1\n)\nSELECT yr::timestamp AS \"time\",\n gross / (months * (40.0 * 52 / 12)) AS \"Gross (incl. RSU)\",\n net / (months * (40.0 * 52 / 12)) AS \"Net (take-home)\"\nFROM y\nORDER BY yr"
|
||||
"rawSql": "WITH y AS (\n SELECT date_trunc('year', pay_date) AS yr,\n COUNT(DISTINCT date_trunc('month', pay_date)) AS months,\n SUM(gross_pay) AS gross, SUM(net_pay) AS net\n FROM payslip_ingest.payslip GROUP BY 1\n),\ncalc AS (\n SELECT yr, months,\n gross / (months * (40.0 * 52 / 12)) AS gross_h,\n net / (months * (40.0 * 52 / 12)) AS net_h\n FROM y\n),\nflagged AS (\n SELECT yr, gross_h, net_h, (yr = MAX(yr) OVER () AND months < 12) AS partial FROM calc\n),\nwithlead AS (\n SELECT yr, gross_h, net_h, partial,\n COALESCE(LEAD(partial) OVER (ORDER BY yr), false) AS next_partial FROM flagged\n)\nSELECT yr::timestamp AS \"time\",\n CASE WHEN partial THEN NULL ELSE gross_h END AS \"Gross (incl. RSU)\",\n CASE WHEN partial THEN NULL ELSE net_h END AS \"Net (take-home)\",\n CASE WHEN partial OR next_partial THEN gross_h ELSE NULL END AS \"Gross (current yr, partial)\",\n CASE WHEN partial OR next_partial THEN net_h ELSE NULL END AS \"Net (current yr, partial)\"\nFROM withlead ORDER BY yr"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue