create-dql-app 1.4.1 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -7
- package/bin/create-dql-app.mjs +6 -5
- package/package.json +1 -1
- package/templates/acme-bank/.dql/skills/mei.chen@acme-bank.com/cards-fraud.skill.md +15 -0
- package/templates/acme-bank/.dql/skills/sara.fitch@acme-bank.com/cfo-weekly.skill.md +15 -0
- package/templates/acme-bank/README.md +75 -0
- package/templates/acme-bank/apps/cards-ops/README.md +9 -0
- package/templates/acme-bank/apps/cards-ops/dashboards/daily-ops.dqld +61 -0
- package/templates/acme-bank/apps/cards-ops/dashboards/fraud-watch.dqld +37 -0
- package/templates/acme-bank/apps/cards-ops/dql.app.json +76 -0
- package/templates/acme-bank/apps/cards-ops/drafts/.gitkeep +1 -0
- package/templates/acme-bank/apps/cards-ops/notebooks/.gitkeep +1 -0
- package/templates/acme-bank/apps/executive-cockpit/README.md +9 -0
- package/templates/acme-bank/apps/executive-cockpit/dashboards/bank-overview.dqld +57 -0
- package/templates/acme-bank/apps/executive-cockpit/dql.app.json +82 -0
- package/templates/acme-bank/apps/executive-cockpit/drafts/.gitkeep +1 -0
- package/templates/acme-bank/apps/executive-cockpit/notebooks/.gitkeep +1 -0
- package/templates/acme-bank/apps/retail-deposits/README.md +9 -0
- package/templates/acme-bank/apps/retail-deposits/dashboards/deposit-growth.dqld +48 -0
- package/templates/acme-bank/apps/retail-deposits/dql.app.json +59 -0
- package/templates/acme-bank/apps/retail-deposits/drafts/.gitkeep +1 -0
- package/templates/acme-bank/apps/retail-deposits/notebooks/.gitkeep +1 -0
- package/templates/acme-bank/apps/risk-office/README.md +8 -0
- package/templates/acme-bank/apps/risk-office/dashboards/credit-risk.dqld +48 -0
- package/templates/acme-bank/apps/risk-office/dql.app.json +57 -0
- package/templates/acme-bank/apps/risk-office/drafts/.gitkeep +1 -0
- package/templates/acme-bank/apps/risk-office/notebooks/.gitkeep +1 -0
- package/templates/acme-bank/blocks/cards/card_approval_rate.dql +24 -0
- package/templates/acme-bank/blocks/cards/daily_transaction_volume.dql +34 -0
- package/templates/acme-bank/blocks/cards/fraud_alerts_by_region.dql +33 -0
- package/templates/acme-bank/blocks/cards/fraud_by_merchant_recent.dql +33 -0
- package/templates/acme-bank/blocks/deposits/branch_deposit_leaders.dql +30 -0
- package/templates/acme-bank/blocks/deposits/deposit_trend.dql +30 -0
- package/templates/acme-bank/blocks/deposits/deposits_by_segment.dql +33 -0
- package/templates/acme-bank/blocks/executive/bank_health_scorecard.dql +34 -0
- package/templates/acme-bank/blocks/lending/high_risk_loan_exposure.dql +31 -0
- package/templates/acme-bank/blocks/lending/loan_delinquency_by_region.dql +32 -0
- package/templates/acme-bank/data/customers.csv +12 -0
- package/templates/acme-bank/data/deposits.csv +22 -0
- package/templates/acme-bank/data/fraud_alerts.csv +9 -0
- package/templates/acme-bank/data/loans.csv +11 -0
- package/templates/acme-bank/data/merchants.csv +10 -0
- package/templates/acme-bank/data/transactions.csv +20 -0
- package/templates/acme-bank/dql.config.json +21 -0
- package/templates/acme-bank/notebooks/cards_fraud_ops.dqlnb +47 -0
- package/templates/acme-bank/notebooks/credit_risk_review.dqlnb +42 -0
- package/templates/acme-bank/notebooks/executive_weekly_review.dqlnb +47 -0
- package/templates/acme-bank/notebooks/retail_deposits_review.dqlnb +42 -0
- package/templates/acme-bank/notebooks/welcome.dqlnb +44 -0
- package/templates/acme-bank/package.json +18 -0
- package/templates/acme-bank/semantic-layer/dimensions/banking.yaml +36 -0
- package/templates/acme-bank/semantic-layer/metrics/banking.yaml +37 -0
- package/templates/empty/README.md +4 -3
- package/templates/empty/package.json +1 -1
- package/templates/jaffle-shop/README.md +1 -1
- package/templates/jaffle-shop/package.json +1 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"id": "credit-risk",
|
|
4
|
+
"metadata": {
|
|
5
|
+
"title": "Credit Risk",
|
|
6
|
+
"description": "Certified lending risk dashboard for delinquency and high-risk exposure.",
|
|
7
|
+
"domain": "lending",
|
|
8
|
+
"tags": ["risk", "lending", "credit-risk"]
|
|
9
|
+
},
|
|
10
|
+
"layout": {
|
|
11
|
+
"kind": "grid",
|
|
12
|
+
"cols": 12,
|
|
13
|
+
"rowHeight": 80,
|
|
14
|
+
"items": [
|
|
15
|
+
{
|
|
16
|
+
"i": "delinquency-region",
|
|
17
|
+
"x": 0,
|
|
18
|
+
"y": 0,
|
|
19
|
+
"w": 6,
|
|
20
|
+
"h": 3,
|
|
21
|
+
"block": { "blockId": "loan_delinquency_by_region" },
|
|
22
|
+
"viz": { "type": "bar" },
|
|
23
|
+
"title": "Delinquency by Region"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"i": "high-risk-exposure",
|
|
27
|
+
"x": 6,
|
|
28
|
+
"y": 0,
|
|
29
|
+
"w": 6,
|
|
30
|
+
"h": 4,
|
|
31
|
+
"block": { "blockId": "high_risk_loan_exposure" },
|
|
32
|
+
"viz": { "type": "table" },
|
|
33
|
+
"title": "High-Risk Loan Exposure"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"i": "merchant-fraud",
|
|
37
|
+
"x": 0,
|
|
38
|
+
"y": 4,
|
|
39
|
+
"w": 6,
|
|
40
|
+
"h": 3,
|
|
41
|
+
"block": { "blockId": "fraud_by_merchant_recent" },
|
|
42
|
+
"viz": { "type": "bar" },
|
|
43
|
+
"title": "Merchant Fraud Watch"
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"id": "risk-office",
|
|
4
|
+
"name": "Risk Office",
|
|
5
|
+
"description": "Credit and fraud exposure App for risk management leaders.",
|
|
6
|
+
"domain": "lending",
|
|
7
|
+
"owners": ["anika.shah@acme-bank.com"],
|
|
8
|
+
"tags": ["risk", "lending", "fraud", "audience:risk-committee"],
|
|
9
|
+
"members": [
|
|
10
|
+
{
|
|
11
|
+
"userId": "anika.shah@acme-bank.com",
|
|
12
|
+
"displayName": "Anika Shah - Chief Risk Officer",
|
|
13
|
+
"roles": ["owner"],
|
|
14
|
+
"attributes": { "department": "risk" }
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"userId": "omar.ali@acme-bank.com",
|
|
18
|
+
"displayName": "Omar Ali - Risk Analyst",
|
|
19
|
+
"roles": ["analyst"],
|
|
20
|
+
"attributes": { "department": "risk" }
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"roles": [
|
|
24
|
+
{ "id": "owner", "displayName": "Owner", "description": "Full App configuration and execution." },
|
|
25
|
+
{ "id": "analyst", "displayName": "Analyst", "description": "Can execute dashboards and review proposed blocks." },
|
|
26
|
+
{ "id": "viewer", "displayName": "Viewer", "description": "Can view and run certified dashboard tiles." }
|
|
27
|
+
],
|
|
28
|
+
"policies": [
|
|
29
|
+
{
|
|
30
|
+
"id": "risk-dashboard-execute",
|
|
31
|
+
"domain": "lending",
|
|
32
|
+
"minClassification": "internal",
|
|
33
|
+
"allowedRoles": ["viewer", "analyst", "owner"],
|
|
34
|
+
"accessLevel": "execute",
|
|
35
|
+
"enabled": true
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"id": "risk-fraud-readthrough",
|
|
39
|
+
"domain": "cards",
|
|
40
|
+
"minClassification": "internal",
|
|
41
|
+
"allowedRoles": ["viewer", "analyst", "owner"],
|
|
42
|
+
"accessLevel": "execute",
|
|
43
|
+
"enabled": true
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "risk-admin",
|
|
47
|
+
"domain": "lending",
|
|
48
|
+
"minClassification": "restricted",
|
|
49
|
+
"allowedRoles": ["owner"],
|
|
50
|
+
"accessLevel": "admin",
|
|
51
|
+
"enabled": true
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"rlsBindings": [],
|
|
55
|
+
"schedules": [],
|
|
56
|
+
"homepage": { "type": "dashboard", "id": "credit-risk" }
|
|
57
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// dql-format: 1
|
|
2
|
+
|
|
3
|
+
block "card_approval_rate" {
|
|
4
|
+
domain = "cards"
|
|
5
|
+
type = "custom"
|
|
6
|
+
status = "certified"
|
|
7
|
+
description = "Card approval rate across the seeded card transaction stream."
|
|
8
|
+
tags = ["cards", "kpi", "approval-rate", "ops"]
|
|
9
|
+
owner = "mei.chen@acme-bank.com"
|
|
10
|
+
llmContext = "Use this single-value KPI when stakeholders ask about card approval rate or transaction decline pressure."
|
|
11
|
+
examples = [{ question = "What is our card approval rate?" }]
|
|
12
|
+
invariants = ["approval_rate_pct >= 0", "approval_rate_pct <= 100"]
|
|
13
|
+
query = """
|
|
14
|
+
SELECT
|
|
15
|
+
ROUND(100.0 * SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END) / COUNT(*), 2) AS approval_rate_pct
|
|
16
|
+
FROM read_csv_auto('./data/transactions.csv')
|
|
17
|
+
"""
|
|
18
|
+
visualization {
|
|
19
|
+
chart = "single_value"
|
|
20
|
+
}
|
|
21
|
+
tests {
|
|
22
|
+
assert row_count == 1
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// dql-format: 1
|
|
2
|
+
|
|
3
|
+
@rls("region", "{user.region}")
|
|
4
|
+
@rls("branch_id", "{user.branch}")
|
|
5
|
+
block "daily_transaction_volume" {
|
|
6
|
+
domain = "cards"
|
|
7
|
+
type = "custom"
|
|
8
|
+
status = "certified"
|
|
9
|
+
description = "Daily approved and declined card transaction volume."
|
|
10
|
+
tags = ["cards", "volume", "daily", "ops"]
|
|
11
|
+
owner = "mei.chen@acme-bank.com"
|
|
12
|
+
llmContext = "Use for daily card transaction count, card spend volume, and approval or decline trend questions."
|
|
13
|
+
examples = [{ question = "What was card volume this week?" }, { question = "Show transaction volume by day." }]
|
|
14
|
+
invariants = ["volume_usd >= 0", "txn_count >= 0"]
|
|
15
|
+
query = """
|
|
16
|
+
SELECT
|
|
17
|
+
CAST(txn_ts AS DATE) AS day,
|
|
18
|
+
region,
|
|
19
|
+
branch_id,
|
|
20
|
+
COUNT(*) AS txn_count,
|
|
21
|
+
ROUND(SUM(amount_usd), 2) AS volume_usd
|
|
22
|
+
FROM read_csv_auto('./data/transactions.csv')
|
|
23
|
+
GROUP BY 1, 2, 3
|
|
24
|
+
ORDER BY 1, 2, 3
|
|
25
|
+
"""
|
|
26
|
+
visualization {
|
|
27
|
+
chart = "line"
|
|
28
|
+
x = "day"
|
|
29
|
+
y = "volume_usd"
|
|
30
|
+
}
|
|
31
|
+
tests {
|
|
32
|
+
assert row_count > 0
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// dql-format: 1
|
|
2
|
+
|
|
3
|
+
@rls("region", "{user.region}")
|
|
4
|
+
@rls("branch_id", "{user.branch}")
|
|
5
|
+
block "fraud_alerts_by_region" {
|
|
6
|
+
domain = "cards"
|
|
7
|
+
type = "custom"
|
|
8
|
+
status = "certified"
|
|
9
|
+
description = "Confirmed and review fraud exposure by region and branch."
|
|
10
|
+
tags = ["fraud", "cards", "ops", "risk"]
|
|
11
|
+
owner = "mei.chen@acme-bank.com"
|
|
12
|
+
llmContext = "Use this block for card fraud exposure, fraud alert counts, and branch-level fraud monitoring. It supports persona RLS on region and branch_id."
|
|
13
|
+
examples = [{ question = "Which regions have the most card fraud exposure?" }, { question = "Show fraud alerts for my branch." }]
|
|
14
|
+
invariants = ["exposure_usd >= 0", "alert_count >= 0"]
|
|
15
|
+
query = """
|
|
16
|
+
SELECT
|
|
17
|
+
region,
|
|
18
|
+
branch_id,
|
|
19
|
+
COUNT(*) AS alert_count,
|
|
20
|
+
ROUND(SUM(amount_usd), 2) AS exposure_usd
|
|
21
|
+
FROM read_csv_auto('./data/fraud_alerts.csv')
|
|
22
|
+
GROUP BY 1, 2
|
|
23
|
+
ORDER BY exposure_usd DESC
|
|
24
|
+
"""
|
|
25
|
+
visualization {
|
|
26
|
+
chart = "bar"
|
|
27
|
+
x = "region"
|
|
28
|
+
y = "exposure_usd"
|
|
29
|
+
}
|
|
30
|
+
tests {
|
|
31
|
+
assert row_count >= 0
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// dql-format: 1
|
|
2
|
+
|
|
3
|
+
block "fraud_by_merchant_recent" {
|
|
4
|
+
domain = "cards"
|
|
5
|
+
type = "custom"
|
|
6
|
+
status = "certified"
|
|
7
|
+
description = "Fraud exposure grouped by merchant and merchant risk band."
|
|
8
|
+
tags = ["fraud", "merchant", "cards", "risk"]
|
|
9
|
+
owner = "mei.chen@acme-bank.com"
|
|
10
|
+
llmContext = "Use this block when users ask which merchants are driving fraud, merchant risk, blocklist exposure, or card fraud concentration."
|
|
11
|
+
examples = [{ question = "Which merchants are driving card fraud?" }, { question = "Show fraud exposure by merchant risk band." }]
|
|
12
|
+
invariants = ["exposure_usd >= 0", "alerts >= 0"]
|
|
13
|
+
query = """
|
|
14
|
+
SELECT
|
|
15
|
+
m.merchant_name,
|
|
16
|
+
m.merchant_category,
|
|
17
|
+
m.risk_band,
|
|
18
|
+
COUNT(*) AS alerts,
|
|
19
|
+
ROUND(SUM(f.amount_usd), 2) AS exposure_usd
|
|
20
|
+
FROM read_csv_auto('./data/fraud_alerts.csv') f
|
|
21
|
+
JOIN read_csv_auto('./data/merchants.csv') m USING (merchant_id)
|
|
22
|
+
GROUP BY 1, 2, 3
|
|
23
|
+
ORDER BY exposure_usd DESC
|
|
24
|
+
"""
|
|
25
|
+
visualization {
|
|
26
|
+
chart = "bar"
|
|
27
|
+
x = "merchant_name"
|
|
28
|
+
y = "exposure_usd"
|
|
29
|
+
}
|
|
30
|
+
tests {
|
|
31
|
+
assert row_count > 0
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// dql-format: 1
|
|
2
|
+
|
|
3
|
+
block "branch_deposit_leaders" {
|
|
4
|
+
domain = "deposits"
|
|
5
|
+
type = "custom"
|
|
6
|
+
status = "certified"
|
|
7
|
+
description = "Branches ranked by current deposit balance and weekly net-new deposits."
|
|
8
|
+
tags = ["deposits", "branch", "leaderboard", "retail"]
|
|
9
|
+
owner = "diego.ramos@acme-bank.com"
|
|
10
|
+
llmContext = "Use this block for branch deposit leaderboards, branch ranking, and regional retail growth conversations."
|
|
11
|
+
examples = [{ question = "Which branches lead deposits?" }]
|
|
12
|
+
invariants = ["balance_usd >= 0"]
|
|
13
|
+
query = """
|
|
14
|
+
SELECT
|
|
15
|
+
region,
|
|
16
|
+
branch_id,
|
|
17
|
+
ROUND(SUM(balance_usd), 2) AS balance_usd,
|
|
18
|
+
ROUND(SUM(net_new_usd), 2) AS net_new_usd
|
|
19
|
+
FROM read_csv_auto('./data/deposits.csv')
|
|
20
|
+
WHERE as_of_date = (SELECT MAX(as_of_date) FROM read_csv_auto('./data/deposits.csv'))
|
|
21
|
+
GROUP BY 1, 2
|
|
22
|
+
ORDER BY balance_usd DESC
|
|
23
|
+
"""
|
|
24
|
+
visualization {
|
|
25
|
+
chart = "table"
|
|
26
|
+
}
|
|
27
|
+
tests {
|
|
28
|
+
assert row_count > 0
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// dql-format: 1
|
|
2
|
+
|
|
3
|
+
block "deposit_trend" {
|
|
4
|
+
domain = "deposits"
|
|
5
|
+
type = "custom"
|
|
6
|
+
status = "certified"
|
|
7
|
+
description = "Total deposit balance trend by snapshot date."
|
|
8
|
+
tags = ["deposits", "trend", "growth", "retail"]
|
|
9
|
+
owner = "diego.ramos@acme-bank.com"
|
|
10
|
+
llmContext = "Use for total deposit trend, retail deposit growth, and balance movement over time."
|
|
11
|
+
examples = [{ question = "Are deposits growing?" }, { question = "Show deposit balance trend." }]
|
|
12
|
+
invariants = ["balance_usd >= 0"]
|
|
13
|
+
query = """
|
|
14
|
+
SELECT
|
|
15
|
+
as_of_date,
|
|
16
|
+
ROUND(SUM(balance_usd), 2) AS balance_usd,
|
|
17
|
+
ROUND(SUM(net_new_usd), 2) AS net_new_usd
|
|
18
|
+
FROM read_csv_auto('./data/deposits.csv')
|
|
19
|
+
GROUP BY 1
|
|
20
|
+
ORDER BY 1
|
|
21
|
+
"""
|
|
22
|
+
visualization {
|
|
23
|
+
chart = "line"
|
|
24
|
+
x = "as_of_date"
|
|
25
|
+
y = "balance_usd"
|
|
26
|
+
}
|
|
27
|
+
tests {
|
|
28
|
+
assert row_count > 0
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// dql-format: 1
|
|
2
|
+
|
|
3
|
+
@rls("region", "{user.region}")
|
|
4
|
+
block "deposits_by_segment" {
|
|
5
|
+
domain = "deposits"
|
|
6
|
+
type = "custom"
|
|
7
|
+
status = "certified"
|
|
8
|
+
description = "Current deposit balance and net-new deposits by customer segment."
|
|
9
|
+
tags = ["deposits", "retail", "segment", "balance"]
|
|
10
|
+
owner = "diego.ramos@acme-bank.com"
|
|
11
|
+
llmContext = "Use for deposit balances, net-new deposits, and segment mix questions in the retail deposits domain."
|
|
12
|
+
examples = [{ question = "Which customer segments hold the most deposits?" }, { question = "How much net-new deposit growth did we see?" }]
|
|
13
|
+
invariants = ["balance_usd >= 0"]
|
|
14
|
+
query = """
|
|
15
|
+
SELECT
|
|
16
|
+
segment,
|
|
17
|
+
region,
|
|
18
|
+
ROUND(SUM(balance_usd), 2) AS balance_usd,
|
|
19
|
+
ROUND(SUM(net_new_usd), 2) AS net_new_usd
|
|
20
|
+
FROM read_csv_auto('./data/deposits.csv')
|
|
21
|
+
WHERE as_of_date = (SELECT MAX(as_of_date) FROM read_csv_auto('./data/deposits.csv'))
|
|
22
|
+
GROUP BY 1, 2
|
|
23
|
+
ORDER BY balance_usd DESC
|
|
24
|
+
"""
|
|
25
|
+
visualization {
|
|
26
|
+
chart = "bar"
|
|
27
|
+
x = "segment"
|
|
28
|
+
y = "balance_usd"
|
|
29
|
+
}
|
|
30
|
+
tests {
|
|
31
|
+
assert row_count > 0
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// dql-format: 1
|
|
2
|
+
|
|
3
|
+
block "bank_health_scorecard" {
|
|
4
|
+
domain = "executive"
|
|
5
|
+
type = "custom"
|
|
6
|
+
status = "certified"
|
|
7
|
+
description = "Executive scorecard with cards volume, fraud exposure, deposits, and high-risk lending exposure."
|
|
8
|
+
tags = ["executive", "cxo", "scorecard", "bank-health"]
|
|
9
|
+
owner = "sara.fitch@acme-bank.com"
|
|
10
|
+
llmContext = "Use for CXO questions about overall Acme Bank health across cards, fraud, deposits, and lending risk."
|
|
11
|
+
examples = [{ question = "Give me the bank health scorecard." }, { question = "What should the CFO review this week?" }]
|
|
12
|
+
invariants = ["metric_value >= 0"]
|
|
13
|
+
query = """
|
|
14
|
+
SELECT 'card_volume_usd' AS metric, ROUND(SUM(amount_usd), 2) AS metric_value
|
|
15
|
+
FROM read_csv_auto('./data/transactions.csv')
|
|
16
|
+
UNION ALL
|
|
17
|
+
SELECT 'fraud_exposure_usd' AS metric, ROUND(SUM(amount_usd), 2) AS metric_value
|
|
18
|
+
FROM read_csv_auto('./data/fraud_alerts.csv')
|
|
19
|
+
UNION ALL
|
|
20
|
+
SELECT 'current_deposits_usd' AS metric, ROUND(SUM(balance_usd), 2) AS metric_value
|
|
21
|
+
FROM read_csv_auto('./data/deposits.csv')
|
|
22
|
+
WHERE as_of_date = (SELECT MAX(as_of_date) FROM read_csv_auto('./data/deposits.csv'))
|
|
23
|
+
UNION ALL
|
|
24
|
+
SELECT 'high_risk_loans_usd' AS metric, ROUND(SUM(outstanding_usd), 2) AS metric_value
|
|
25
|
+
FROM read_csv_auto('./data/loans.csv')
|
|
26
|
+
WHERE risk_grade IN ('C', 'D')
|
|
27
|
+
"""
|
|
28
|
+
visualization {
|
|
29
|
+
chart = "table"
|
|
30
|
+
}
|
|
31
|
+
tests {
|
|
32
|
+
assert row_count == 4
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// dql-format: 1
|
|
2
|
+
|
|
3
|
+
block "high_risk_loan_exposure" {
|
|
4
|
+
domain = "lending"
|
|
5
|
+
type = "custom"
|
|
6
|
+
status = "certified"
|
|
7
|
+
description = "High-risk loan exposure for risk grades C and D."
|
|
8
|
+
tags = ["lending", "credit-risk", "exposure", "risk"]
|
|
9
|
+
owner = "anika.shah@acme-bank.com"
|
|
10
|
+
llmContext = "Use for high-risk loan exposure, watchlist balances, risk grades C and D, and credit-risk committee reviews."
|
|
11
|
+
examples = [{ question = "How much exposure is in high-risk loans?" }, { question = "Show the credit watchlist." }]
|
|
12
|
+
invariants = ["outstanding_usd >= 0"]
|
|
13
|
+
query = """
|
|
14
|
+
SELECT
|
|
15
|
+
risk_grade,
|
|
16
|
+
product,
|
|
17
|
+
COUNT(*) AS loans,
|
|
18
|
+
ROUND(SUM(outstanding_usd), 2) AS outstanding_usd,
|
|
19
|
+
ROUND(AVG(probability_default), 4) AS avg_probability_default
|
|
20
|
+
FROM read_csv_auto('./data/loans.csv')
|
|
21
|
+
WHERE risk_grade IN ('C', 'D')
|
|
22
|
+
GROUP BY 1, 2
|
|
23
|
+
ORDER BY outstanding_usd DESC
|
|
24
|
+
"""
|
|
25
|
+
visualization {
|
|
26
|
+
chart = "table"
|
|
27
|
+
}
|
|
28
|
+
tests {
|
|
29
|
+
assert row_count > 0
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// dql-format: 1
|
|
2
|
+
|
|
3
|
+
@rls("region", "{user.region}")
|
|
4
|
+
block "loan_delinquency_by_region" {
|
|
5
|
+
domain = "lending"
|
|
6
|
+
type = "custom"
|
|
7
|
+
status = "certified"
|
|
8
|
+
description = "Loan delinquency exposure by region."
|
|
9
|
+
tags = ["lending", "credit-risk", "delinquency", "risk"]
|
|
10
|
+
owner = "anika.shah@acme-bank.com"
|
|
11
|
+
llmContext = "Use for delinquent loan exposure, days-past-due summaries, and regional lending risk questions."
|
|
12
|
+
examples = [{ question = "Which regions have the most delinquent loan exposure?" }, { question = "Show credit risk by region." }]
|
|
13
|
+
invariants = ["delinquent_balance_usd >= 0"]
|
|
14
|
+
query = """
|
|
15
|
+
SELECT
|
|
16
|
+
region,
|
|
17
|
+
COUNT(*) AS loan_count,
|
|
18
|
+
ROUND(SUM(CASE WHEN days_past_due >= 30 THEN outstanding_usd ELSE 0 END), 2) AS delinquent_balance_usd,
|
|
19
|
+
ROUND(AVG(probability_default), 4) AS avg_probability_default
|
|
20
|
+
FROM read_csv_auto('./data/loans.csv')
|
|
21
|
+
GROUP BY 1
|
|
22
|
+
ORDER BY delinquent_balance_usd DESC
|
|
23
|
+
"""
|
|
24
|
+
visualization {
|
|
25
|
+
chart = "bar"
|
|
26
|
+
x = "region"
|
|
27
|
+
y = "delinquent_balance_usd"
|
|
28
|
+
}
|
|
29
|
+
tests {
|
|
30
|
+
assert row_count > 0
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
customer_id,customer_name,segment,region,branch_id,risk_tier,opened_date
|
|
2
|
+
C001,Northwind Manufacturing,commercial,NA-NE,NYC-042,medium,2021-03-14
|
|
3
|
+
C002,Summit Retail Group,small_business,NA-W,SFO-007,low,2020-07-09
|
|
4
|
+
C003,Arbor Family Trust,wealth,NA-NE,BOS-015,low,2019-01-22
|
|
5
|
+
C004,Blue Harbor Importers,commercial,EMEA,LON-018,high,2022-09-30
|
|
6
|
+
C005,Beacon Foods,small_business,NA-SE,ATL-011,medium,2023-05-17
|
|
7
|
+
C006,Juniper Digital,commercial,NA-W,SEA-004,medium,2021-11-06
|
|
8
|
+
C007,River City Co-op,consumer,NA-SE,ATL-011,low,2024-02-02
|
|
9
|
+
C008,Atlas Travel,small_business,EMEA,LON-018,high,2022-04-12
|
|
10
|
+
C009,Maple Medical,commercial,NA-NE,NYC-042,low,2018-12-19
|
|
11
|
+
C010,Sunset Builders,small_business,NA-W,SFO-007,medium,2023-10-23
|
|
12
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
deposit_id,customer_id,region,branch_id,segment,balance_usd,net_new_usd,as_of_date
|
|
2
|
+
D001,C001,NA-NE,NYC-042,commercial,1250000,42000,2026-04-20
|
|
3
|
+
D002,C002,NA-W,SFO-007,small_business,380000,18500,2026-04-20
|
|
4
|
+
D003,C003,NA-NE,BOS-015,wealth,2100000,76000,2026-04-20
|
|
5
|
+
D004,C004,EMEA,LON-018,commercial,940000,-12000,2026-04-20
|
|
6
|
+
D005,C005,NA-SE,ATL-011,small_business,265000,8000,2026-04-20
|
|
7
|
+
D006,C006,NA-W,SEA-004,commercial,1175000,51500,2026-04-20
|
|
8
|
+
D007,C007,NA-SE,ATL-011,consumer,42000,1200,2026-04-20
|
|
9
|
+
D008,C008,EMEA,LON-018,small_business,198000,-9000,2026-04-20
|
|
10
|
+
D009,C009,NA-NE,NYC-042,commercial,1580000,63000,2026-04-20
|
|
11
|
+
D010,C010,NA-W,SFO-007,small_business,225000,11000,2026-04-20
|
|
12
|
+
D011,C001,NA-NE,NYC-042,commercial,1294000,44000,2026-04-26
|
|
13
|
+
D012,C002,NA-W,SFO-007,small_business,397500,17500,2026-04-26
|
|
14
|
+
D013,C003,NA-NE,BOS-015,wealth,2190000,90000,2026-04-26
|
|
15
|
+
D014,C004,EMEA,LON-018,commercial,932000,-8000,2026-04-26
|
|
16
|
+
D015,C005,NA-SE,ATL-011,small_business,276000,11000,2026-04-26
|
|
17
|
+
D016,C006,NA-W,SEA-004,commercial,1221000,46000,2026-04-26
|
|
18
|
+
D017,C007,NA-SE,ATL-011,consumer,43800,1800,2026-04-26
|
|
19
|
+
D018,C008,EMEA,LON-018,small_business,191000,-7000,2026-04-26
|
|
20
|
+
D019,C009,NA-NE,NYC-042,commercial,1648000,68000,2026-04-26
|
|
21
|
+
D020,C010,NA-W,SFO-007,small_business,239000,14000,2026-04-26
|
|
22
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
alert_id,txn_id,merchant_id,customer_id,amount_usd,region,branch_id,alert_ts,reason,status
|
|
2
|
+
F001,T003,M-amzn,C001,4900.00,NA-NE,NYC-042,2026-04-20T22:12:00Z,velocity,review
|
|
3
|
+
F002,T004,M-darknet1,C004,2700.00,EMEA,LON-018,2026-04-20T22:15:00Z,merchant_blocklist,confirmed
|
|
4
|
+
F003,T005,M-darknet1,C008,3200.00,EMEA,LON-018,2026-04-20T22:19:00Z,merchant_blocklist,confirmed
|
|
5
|
+
F004,T010,M-travel,C004,5200.00,EMEA,LON-018,2026-04-22T14:20:00Z,geo_anomaly,review
|
|
6
|
+
F005,T012,M-darknet1,C008,4100.00,EMEA,LON-018,2026-04-23T23:10:00Z,merchant_blocklist,confirmed
|
|
7
|
+
F006,T013,M-travel,C001,2200.00,NA-NE,NYC-042,2026-04-24T18:23:00Z,amount_outlier,review
|
|
8
|
+
F007,T016,M-darknet1,C005,1800.00,NA-SE,ATL-011,2026-04-25T23:24:00Z,merchant_blocklist,confirmed
|
|
9
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
loan_id,customer_id,region,branch_id,product,outstanding_usd,days_past_due,probability_default,risk_grade,as_of_date
|
|
2
|
+
L001,C001,NA-NE,NYC-042,commercial_line,850000,0,0.018,A,2026-04-26
|
|
3
|
+
L002,C002,NA-W,SFO-007,sba_term,220000,4,0.033,B,2026-04-26
|
|
4
|
+
L003,C003,NA-NE,BOS-015,mortgage,1100000,0,0.011,A,2026-04-26
|
|
5
|
+
L004,C004,EMEA,LON-018,trade_finance,760000,45,0.115,D,2026-04-26
|
|
6
|
+
L005,C005,NA-SE,ATL-011,sba_term,310000,18,0.071,C,2026-04-26
|
|
7
|
+
L006,C006,NA-W,SEA-004,commercial_line,640000,0,0.026,B,2026-04-26
|
|
8
|
+
L007,C007,NA-SE,ATL-011,consumer_auto,18000,0,0.019,A,2026-04-26
|
|
9
|
+
L008,C008,EMEA,LON-018,business_card,92000,62,0.142,D,2026-04-26
|
|
10
|
+
L009,C009,NA-NE,NYC-042,commercial_real_estate,1480000,0,0.021,B,2026-04-26
|
|
11
|
+
L010,C010,NA-W,SFO-007,equipment_finance,175000,9,0.052,C,2026-04-26
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
merchant_id,merchant_name,merchant_category,mcc_code,risk_band
|
|
2
|
+
M-amzn,Amazon Marketplace,ecommerce,5942,low
|
|
3
|
+
M-walmart,Walmart Stores,grocery,5411,low
|
|
4
|
+
M-target,Target Stores,grocery,5310,low
|
|
5
|
+
M-apple,Apple Store,electronics,5732,low
|
|
6
|
+
M-home,Home Depot,home_improvement,5200,medium
|
|
7
|
+
M-travel,Global Travel Desk,travel,4722,medium
|
|
8
|
+
M-grocery,Neighborhood Grocery,grocery,5411,low
|
|
9
|
+
M-darknet1,Darknet Vendor 1,restricted,7995,critical
|
|
10
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
txn_id,customer_id,merchant_id,amount_usd,status,region,branch_id,txn_ts
|
|
2
|
+
T001,C001,M-amzn,84.20,approved,NA-NE,NYC-042,2026-04-20T08:14:00Z
|
|
3
|
+
T002,C002,M-walmart,162.00,approved,NA-W,SFO-007,2026-04-20T08:32:00Z
|
|
4
|
+
T003,C001,M-amzn,4900.00,approved,NA-NE,NYC-042,2026-04-20T22:11:00Z
|
|
5
|
+
T004,C004,M-darknet1,2700.00,declined,EMEA,LON-018,2026-04-20T22:14:00Z
|
|
6
|
+
T005,C008,M-darknet1,3200.00,declined,EMEA,LON-018,2026-04-20T22:18:00Z
|
|
7
|
+
T006,C005,M-target,242.50,approved,NA-SE,ATL-011,2026-04-21T09:04:00Z
|
|
8
|
+
T007,C006,M-apple,1180.00,approved,NA-W,SEA-004,2026-04-21T10:41:00Z
|
|
9
|
+
T008,C010,M-home,1580.25,approved,NA-W,SFO-007,2026-04-21T15:30:00Z
|
|
10
|
+
T009,C003,M-amzn,440.00,approved,NA-NE,BOS-015,2026-04-22T11:01:00Z
|
|
11
|
+
T010,C004,M-travel,5200.00,approved,EMEA,LON-018,2026-04-22T14:18:00Z
|
|
12
|
+
T011,C007,M-grocery,76.11,approved,NA-SE,ATL-011,2026-04-23T07:40:00Z
|
|
13
|
+
T012,C008,M-darknet1,4100.00,declined,EMEA,LON-018,2026-04-23T23:09:00Z
|
|
14
|
+
T013,C001,M-travel,2200.00,approved,NA-NE,NYC-042,2026-04-24T18:21:00Z
|
|
15
|
+
T014,C002,M-amzn,93.42,approved,NA-W,SFO-007,2026-04-24T19:44:00Z
|
|
16
|
+
T015,C009,M-apple,890.00,approved,NA-NE,NYC-042,2026-04-25T13:17:00Z
|
|
17
|
+
T016,C005,M-darknet1,1800.00,declined,NA-SE,ATL-011,2026-04-25T23:22:00Z
|
|
18
|
+
T017,C006,M-walmart,338.20,approved,NA-W,SEA-004,2026-04-26T09:30:00Z
|
|
19
|
+
T018,C003,M-home,2800.00,approved,NA-NE,BOS-015,2026-04-26T12:08:00Z
|
|
20
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"project": "{{PROJECT_NAME}}",
|
|
3
|
+
"connections": {
|
|
4
|
+
"default": {
|
|
5
|
+
"driver": "duckdb",
|
|
6
|
+
"filepath": ":memory:"
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
"semanticLayer": {
|
|
10
|
+
"provider": "dql",
|
|
11
|
+
"path": "semantic-layer"
|
|
12
|
+
},
|
|
13
|
+
"dbt": {
|
|
14
|
+
"projectDir": "{{DBT_PROJECT_DIR}}",
|
|
15
|
+
"manifestPath": "target/manifest.json"
|
|
16
|
+
},
|
|
17
|
+
"governance": {
|
|
18
|
+
"required_fields": ["domain", "owner", "description"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dqlnbVersion": 1,
|
|
3
|
+
"version": 1,
|
|
4
|
+
"metadata": {
|
|
5
|
+
"title": "Cards Fraud Operations",
|
|
6
|
+
"description": "Daily card volume, approval rate, and fraud exposure review for Cards Operations.",
|
|
7
|
+
"status": "certified",
|
|
8
|
+
"categories": ["cards", "fraud", "operations"],
|
|
9
|
+
"owner": "mei.chen@acme-bank.com"
|
|
10
|
+
},
|
|
11
|
+
"cells": [
|
|
12
|
+
{
|
|
13
|
+
"id": "intro",
|
|
14
|
+
"type": "markdown",
|
|
15
|
+
"source": "# Cards Fraud Operations\n\nUse this notebook when fraud analysts need to inspect the same certified logic that powers the Cards Operations App.\n\nRun the SQL cells for raw context, then run the certified block cells to compare with the packaged App dashboard."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": "daily_status_volume",
|
|
19
|
+
"title": "Daily card volume by status",
|
|
20
|
+
"type": "sql",
|
|
21
|
+
"source": "SELECT\n CAST(txn_ts AS DATE) AS day,\n status,\n COUNT(*) AS txn_count,\n ROUND(SUM(amount_usd), 2) AS volume_usd\nFROM read_csv_auto('./data/transactions.csv')\nGROUP BY 1, 2\nORDER BY 1, 2"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "approval_rate",
|
|
25
|
+
"title": "Approval rate (certified block)",
|
|
26
|
+
"type": "dql",
|
|
27
|
+
"source": "@block(\"card_approval_rate\")"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "fraud_region",
|
|
31
|
+
"title": "Fraud exposure by region and branch (certified block)",
|
|
32
|
+
"type": "dql",
|
|
33
|
+
"source": "@block(\"fraud_alerts_by_region\")"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "merchant_watchlist",
|
|
37
|
+
"title": "Merchant watchlist",
|
|
38
|
+
"type": "sql",
|
|
39
|
+
"source": "SELECT\n m.merchant_name,\n m.merchant_category,\n m.risk_band,\n COUNT(*) AS alerts,\n ROUND(SUM(f.amount_usd), 2) AS exposure_usd\nFROM read_csv_auto('./data/fraud_alerts.csv') f\nJOIN read_csv_auto('./data/merchants.csv') m ON f.merchant_id = m.merchant_id\nGROUP BY 1, 2, 3\nORDER BY exposure_usd DESC"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "next_step",
|
|
43
|
+
"type": "markdown",
|
|
44
|
+
"source": "## App handoff\n\nOpen Apps -> Cards Operations -> Fraud Watch to see these same certified blocks packaged for stakeholders with persona preview."
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dqlnbVersion": 1,
|
|
3
|
+
"version": 1,
|
|
4
|
+
"metadata": {
|
|
5
|
+
"title": "Credit Risk Review",
|
|
6
|
+
"description": "Regional delinquency, probability of default, and high-risk exposure for risk office review.",
|
|
7
|
+
"status": "certified",
|
|
8
|
+
"categories": ["lending", "risk", "delinquency"],
|
|
9
|
+
"owner": "anika.shah@acme-bank.com"
|
|
10
|
+
},
|
|
11
|
+
"cells": [
|
|
12
|
+
{
|
|
13
|
+
"id": "intro",
|
|
14
|
+
"type": "markdown",
|
|
15
|
+
"source": "# Credit Risk Review\n\nRisk analysts can use this notebook to inspect lending exposure before sending a dashboard to the Risk Office App."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": "risk_grade_exposure",
|
|
19
|
+
"title": "Exposure by risk grade",
|
|
20
|
+
"type": "sql",
|
|
21
|
+
"source": "SELECT\n risk_grade,\n COUNT(*) AS loan_count,\n ROUND(SUM(outstanding_usd), 2) AS outstanding_usd,\n ROUND(AVG(probability_default), 4) AS avg_probability_default\nFROM read_csv_auto('./data/loans.csv')\nGROUP BY 1\nORDER BY risk_grade"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "delinquency_region",
|
|
25
|
+
"title": "Delinquency by region (certified block)",
|
|
26
|
+
"type": "dql",
|
|
27
|
+
"source": "@block(\"loan_delinquency_by_region\")"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "high_risk_exposure",
|
|
31
|
+
"title": "High risk exposure (certified block)",
|
|
32
|
+
"type": "dql",
|
|
33
|
+
"source": "@block(\"high_risk_loan_exposure\")"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "past_due_detail",
|
|
37
|
+
"title": "Loans past due by product",
|
|
38
|
+
"type": "sql",
|
|
39
|
+
"source": "SELECT\n product,\n COUNT(*) AS loans,\n ROUND(SUM(outstanding_usd), 2) AS outstanding_usd,\n ROUND(SUM(CASE WHEN days_past_due >= 30 THEN outstanding_usd ELSE 0 END), 2) AS delinquent_balance_usd\nFROM read_csv_auto('./data/loans.csv')\nGROUP BY 1\nORDER BY delinquent_balance_usd DESC"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|