wealth dashboard: replace returns table with per-window stat panels [ci skip]
Swap the single "Returns over time windows" table (panel 9201) for 5 stat panels (1d/7d/30d/90d/12mo), each showing Return % (Modified-Dietz) as the headline value + Δ market (£, net of contributions) as a second value, colored red/green by sign. Same per-window Modified-Dietz math as the old table, just scoped to one interval per panel — verified against live wealthfolio_sync PG and reproduced through Grafana's datasource API (e.g. 30d = 8.15% / £86,875, 12mo = 38.68% / £297,846, matching the prior table exactly). Kept the same 24×8 grid footprint so nothing else on the dashboard reflows. Already applied via targeted `tg apply` of the wealth.json configmap; [ci skip] because a full monitoring-stack CI apply would pull in unrelated pre-existing drift. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6cec27f8dc
commit
fc1486c3dd
1 changed files with 421 additions and 72 deletions
|
|
@ -295,79 +295,44 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"id": 9201,
|
||||
"title": "Returns over time windows",
|
||||
"description": "Replaces the 12mo + \u0394 stat cards. \u0394 all = total change; \u0394 market = change net of contributions; Return % = Modified-Dietz.",
|
||||
"type": "table",
|
||||
"id": 9211,
|
||||
"title": "1d",
|
||||
"description": "Return % (Modified-Dietz) and \u0394 market = \u00a3 change net of contributions, over the trailing 1d.",
|
||||
"type": "stat",
|
||||
"datasource": {
|
||||
"type": "grafana-postgresql-datasource",
|
||||
"uid": "wealth-pg"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 24,
|
||||
"w": 5,
|
||||
"x": 0,
|
||||
"y": 5
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"align": "right"
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "red",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "\u0394 all (\u00a3)"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "currencyGBP"
|
||||
},
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"mode": "continuous-RdYlGr"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "\u0394 market (\u00a3)"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "currencyGBP"
|
||||
},
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"mode": "continuous-RdYlGr"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Return %"
|
||||
"options": "Return"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
|
|
@ -375,26 +340,38 @@
|
|||
"value": "percent"
|
||||
},
|
||||
{
|
||||
"id": "custom.cellOptions",
|
||||
"value": {
|
||||
"type": "color-text"
|
||||
}
|
||||
},
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "\u0394 market"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "color",
|
||||
"value": {
|
||||
"mode": "continuous-RdYlGr"
|
||||
}
|
||||
"id": "unit",
|
||||
"value": "currencyGBP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"cellHeight": "sm",
|
||||
"footer": {
|
||||
"show": false
|
||||
}
|
||||
"colorMode": "value",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "vertical",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "value_and_name"
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
|
|
@ -403,10 +380,382 @@
|
|||
"type": "grafana-postgresql-datasource",
|
||||
"uid": "wealth-pg"
|
||||
},
|
||||
"format": "table",
|
||||
"editorMode": "code",
|
||||
"rawQuery": true,
|
||||
"rawSql": "WITH active_count AS (SELECT COUNT(*) n FROM accounts), mc AS (SELECT MAX(valuation_date) d FROM (SELECT valuation_date, COUNT(*) c FROM dav_corrected GROUP BY valuation_date) x WHERE c>=(SELECT n FROM active_count)), latest AS (SELECT DISTINCT ON (account_id) account_id, total_value nw_now, net_contribution c_now FROM dav_corrected WHERE valuation_date<=(SELECT d FROM mc) ORDER BY account_id, valuation_date DESC), an AS (SELECT SUM(nw_now) nw_now, SUM(c_now) c_now FROM latest), w(label,ord,iv) AS (VALUES ('1d',1,interval '1 day'),('7d',2,interval '7 days'),('30d',3,interval '30 days'),('90d',4,interval '90 days'),('12mo',5,interval '12 months')), ago AS (SELECT wl.label, wl.ord, SUM(x.nw) nw_ago, SUM(x.c) c_ago FROM w wl CROSS JOIN latest l LEFT JOIN LATERAL (SELECT total_value nw, net_contribution c FROM dav_corrected dd WHERE dd.account_id=l.account_id AND dd.valuation_date<=(SELECT d FROM mc)-wl.iv ORDER BY dd.valuation_date DESC LIMIT 1) x ON true GROUP BY wl.label, wl.ord) SELECT a.label AS \"Window\", round((an.nw_now-a.nw_ago)::numeric,0) AS \"\u0394 all (\u00a3)\", round(((an.nw_now-a.nw_ago)-(an.c_now-a.c_ago))::numeric,0) AS \"\u0394 market (\u00a3)\", round((((an.nw_now-a.nw_ago)-(an.c_now-a.c_ago))/NULLIF(a.nw_ago+0.5*(an.c_now-a.c_ago),0)*100)::numeric,2) AS \"Return %\" FROM ago a CROSS JOIN an ORDER BY a.ord"
|
||||
"editorMode": "code",
|
||||
"format": "table",
|
||||
"rawSql": "WITH active_count AS (SELECT COUNT(*) n FROM accounts), mc AS (SELECT MAX(valuation_date) d FROM (SELECT valuation_date, COUNT(*) c FROM dav_corrected GROUP BY valuation_date) x WHERE c>=(SELECT n FROM active_count)), latest AS (SELECT DISTINCT ON (account_id) account_id, total_value nw_now, net_contribution c_now FROM dav_corrected WHERE valuation_date<=(SELECT d FROM mc) ORDER BY account_id, valuation_date DESC), an AS (SELECT SUM(nw_now) nw_now, SUM(c_now) c_now FROM latest), ago AS (SELECT SUM(x.nw) nw_ago, SUM(x.c) c_ago FROM latest l LEFT JOIN LATERAL (SELECT total_value nw, net_contribution c FROM dav_corrected dd WHERE dd.account_id=l.account_id AND dd.valuation_date<=(SELECT d FROM mc)-interval '1 day' ORDER BY dd.valuation_date DESC LIMIT 1) x ON true) SELECT round((((an.nw_now-ago.nw_ago)-(an.c_now-ago.c_ago))/NULLIF(ago.nw_ago+0.5*(an.c_now-ago.c_ago),0)*100)::numeric,2) AS \"Return\", round(((an.nw_now-ago.nw_ago)-(an.c_now-ago.c_ago))::numeric,0) AS \"\u0394 market\" FROM an CROSS JOIN ago"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9212,
|
||||
"title": "7d",
|
||||
"description": "Return % (Modified-Dietz) and \u0394 market = \u00a3 change net of contributions, over the trailing 7d.",
|
||||
"type": "stat",
|
||||
"datasource": {
|
||||
"type": "grafana-postgresql-datasource",
|
||||
"uid": "wealth-pg"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 5,
|
||||
"x": 5,
|
||||
"y": 5
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "red",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Return"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "percent"
|
||||
},
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "\u0394 market"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "currencyGBP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "vertical",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "value_and_name"
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "grafana-postgresql-datasource",
|
||||
"uid": "wealth-pg"
|
||||
},
|
||||
"rawQuery": true,
|
||||
"editorMode": "code",
|
||||
"format": "table",
|
||||
"rawSql": "WITH active_count AS (SELECT COUNT(*) n FROM accounts), mc AS (SELECT MAX(valuation_date) d FROM (SELECT valuation_date, COUNT(*) c FROM dav_corrected GROUP BY valuation_date) x WHERE c>=(SELECT n FROM active_count)), latest AS (SELECT DISTINCT ON (account_id) account_id, total_value nw_now, net_contribution c_now FROM dav_corrected WHERE valuation_date<=(SELECT d FROM mc) ORDER BY account_id, valuation_date DESC), an AS (SELECT SUM(nw_now) nw_now, SUM(c_now) c_now FROM latest), ago AS (SELECT SUM(x.nw) nw_ago, SUM(x.c) c_ago FROM latest l LEFT JOIN LATERAL (SELECT total_value nw, net_contribution c FROM dav_corrected dd WHERE dd.account_id=l.account_id AND dd.valuation_date<=(SELECT d FROM mc)-interval '7 days' ORDER BY dd.valuation_date DESC LIMIT 1) x ON true) SELECT round((((an.nw_now-ago.nw_ago)-(an.c_now-ago.c_ago))/NULLIF(ago.nw_ago+0.5*(an.c_now-ago.c_ago),0)*100)::numeric,2) AS \"Return\", round(((an.nw_now-ago.nw_ago)-(an.c_now-ago.c_ago))::numeric,0) AS \"\u0394 market\" FROM an CROSS JOIN ago"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9213,
|
||||
"title": "30d",
|
||||
"description": "Return % (Modified-Dietz) and \u0394 market = \u00a3 change net of contributions, over the trailing 30d.",
|
||||
"type": "stat",
|
||||
"datasource": {
|
||||
"type": "grafana-postgresql-datasource",
|
||||
"uid": "wealth-pg"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 5,
|
||||
"x": 10,
|
||||
"y": 5
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "red",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Return"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "percent"
|
||||
},
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "\u0394 market"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "currencyGBP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "vertical",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "value_and_name"
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "grafana-postgresql-datasource",
|
||||
"uid": "wealth-pg"
|
||||
},
|
||||
"rawQuery": true,
|
||||
"editorMode": "code",
|
||||
"format": "table",
|
||||
"rawSql": "WITH active_count AS (SELECT COUNT(*) n FROM accounts), mc AS (SELECT MAX(valuation_date) d FROM (SELECT valuation_date, COUNT(*) c FROM dav_corrected GROUP BY valuation_date) x WHERE c>=(SELECT n FROM active_count)), latest AS (SELECT DISTINCT ON (account_id) account_id, total_value nw_now, net_contribution c_now FROM dav_corrected WHERE valuation_date<=(SELECT d FROM mc) ORDER BY account_id, valuation_date DESC), an AS (SELECT SUM(nw_now) nw_now, SUM(c_now) c_now FROM latest), ago AS (SELECT SUM(x.nw) nw_ago, SUM(x.c) c_ago FROM latest l LEFT JOIN LATERAL (SELECT total_value nw, net_contribution c FROM dav_corrected dd WHERE dd.account_id=l.account_id AND dd.valuation_date<=(SELECT d FROM mc)-interval '30 days' ORDER BY dd.valuation_date DESC LIMIT 1) x ON true) SELECT round((((an.nw_now-ago.nw_ago)-(an.c_now-ago.c_ago))/NULLIF(ago.nw_ago+0.5*(an.c_now-ago.c_ago),0)*100)::numeric,2) AS \"Return\", round(((an.nw_now-ago.nw_ago)-(an.c_now-ago.c_ago))::numeric,0) AS \"\u0394 market\" FROM an CROSS JOIN ago"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9214,
|
||||
"title": "90d",
|
||||
"description": "Return % (Modified-Dietz) and \u0394 market = \u00a3 change net of contributions, over the trailing 90d.",
|
||||
"type": "stat",
|
||||
"datasource": {
|
||||
"type": "grafana-postgresql-datasource",
|
||||
"uid": "wealth-pg"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 5,
|
||||
"x": 15,
|
||||
"y": 5
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "red",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Return"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "percent"
|
||||
},
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "\u0394 market"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "currencyGBP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "vertical",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "value_and_name"
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "grafana-postgresql-datasource",
|
||||
"uid": "wealth-pg"
|
||||
},
|
||||
"rawQuery": true,
|
||||
"editorMode": "code",
|
||||
"format": "table",
|
||||
"rawSql": "WITH active_count AS (SELECT COUNT(*) n FROM accounts), mc AS (SELECT MAX(valuation_date) d FROM (SELECT valuation_date, COUNT(*) c FROM dav_corrected GROUP BY valuation_date) x WHERE c>=(SELECT n FROM active_count)), latest AS (SELECT DISTINCT ON (account_id) account_id, total_value nw_now, net_contribution c_now FROM dav_corrected WHERE valuation_date<=(SELECT d FROM mc) ORDER BY account_id, valuation_date DESC), an AS (SELECT SUM(nw_now) nw_now, SUM(c_now) c_now FROM latest), ago AS (SELECT SUM(x.nw) nw_ago, SUM(x.c) c_ago FROM latest l LEFT JOIN LATERAL (SELECT total_value nw, net_contribution c FROM dav_corrected dd WHERE dd.account_id=l.account_id AND dd.valuation_date<=(SELECT d FROM mc)-interval '90 days' ORDER BY dd.valuation_date DESC LIMIT 1) x ON true) SELECT round((((an.nw_now-ago.nw_ago)-(an.c_now-ago.c_ago))/NULLIF(ago.nw_ago+0.5*(an.c_now-ago.c_ago),0)*100)::numeric,2) AS \"Return\", round(((an.nw_now-ago.nw_ago)-(an.c_now-ago.c_ago))::numeric,0) AS \"\u0394 market\" FROM an CROSS JOIN ago"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9215,
|
||||
"title": "12mo",
|
||||
"description": "Return % (Modified-Dietz) and \u0394 market = \u00a3 change net of contributions, over the trailing 12mo.",
|
||||
"type": "stat",
|
||||
"datasource": {
|
||||
"type": "grafana-postgresql-datasource",
|
||||
"uid": "wealth-pg"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 4,
|
||||
"x": 20,
|
||||
"y": 5
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "red",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Return"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "percent"
|
||||
},
|
||||
{
|
||||
"id": "decimals",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "\u0394 market"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "unit",
|
||||
"value": "currencyGBP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "center",
|
||||
"orientation": "vertical",
|
||||
"reduceOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "value_and_name"
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"datasource": {
|
||||
"type": "grafana-postgresql-datasource",
|
||||
"uid": "wealth-pg"
|
||||
},
|
||||
"rawQuery": true,
|
||||
"editorMode": "code",
|
||||
"format": "table",
|
||||
"rawSql": "WITH active_count AS (SELECT COUNT(*) n FROM accounts), mc AS (SELECT MAX(valuation_date) d FROM (SELECT valuation_date, COUNT(*) c FROM dav_corrected GROUP BY valuation_date) x WHERE c>=(SELECT n FROM active_count)), latest AS (SELECT DISTINCT ON (account_id) account_id, total_value nw_now, net_contribution c_now FROM dav_corrected WHERE valuation_date<=(SELECT d FROM mc) ORDER BY account_id, valuation_date DESC), an AS (SELECT SUM(nw_now) nw_now, SUM(c_now) c_now FROM latest), ago AS (SELECT SUM(x.nw) nw_ago, SUM(x.c) c_ago FROM latest l LEFT JOIN LATERAL (SELECT total_value nw, net_contribution c FROM dav_corrected dd WHERE dd.account_id=l.account_id AND dd.valuation_date<=(SELECT d FROM mc)-interval '12 months' ORDER BY dd.valuation_date DESC LIMIT 1) x ON true) SELECT round((((an.nw_now-ago.nw_ago)-(an.c_now-ago.c_ago))/NULLIF(ago.nw_ago+0.5*(an.c_now-ago.c_ago),0)*100)::numeric,2) AS \"Return\", round(((an.nw_now-ago.nw_ago)-(an.c_now-ago.c_ago))::numeric,0) AS \"\u0394 market\" FROM an CROSS JOIN ago"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue