@luquimbo/bi-superpowers 1.0.0
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/.claude-plugin/plugin.json +8 -0
- package/.mcp.json +25 -0
- package/AGENTS.md +244 -0
- package/CHANGELOG.md +265 -0
- package/LICENSE +21 -0
- package/README.md +211 -0
- package/bin/build-plugin.js +30 -0
- package/bin/cli.js +1064 -0
- package/bin/commands/add.js +533 -0
- package/bin/commands/add.test.js +77 -0
- package/bin/commands/build-desktop.js +166 -0
- package/bin/commands/changelog.js +443 -0
- package/bin/commands/diff.js +325 -0
- package/bin/commands/lint.js +419 -0
- package/bin/commands/lint.test.js +103 -0
- package/bin/commands/mcp-setup.js +246 -0
- package/bin/commands/pull.js +287 -0
- package/bin/commands/pull.test.js +36 -0
- package/bin/commands/push.js +231 -0
- package/bin/commands/push.test.js +14 -0
- package/bin/commands/search.js +344 -0
- package/bin/commands/search.test.js +115 -0
- package/bin/commands/setup.js +545 -0
- package/bin/commands/setup.test.js +46 -0
- package/bin/commands/sync-profile.js +405 -0
- package/bin/commands/sync-profile.test.js +14 -0
- package/bin/commands/sync-source.js +418 -0
- package/bin/commands/sync-source.test.js +14 -0
- package/bin/commands/watch.js +206 -0
- package/bin/lib/generators/claude-plugin.js +266 -0
- package/bin/lib/generators/claude-plugin.test.js +110 -0
- package/bin/lib/generators/index.js +116 -0
- package/bin/lib/generators/shared.js +282 -0
- package/bin/lib/licensing/index.js +35 -0
- package/bin/lib/licensing/storage.js +364 -0
- package/bin/lib/licensing/storage.test.js +55 -0
- package/bin/lib/licensing/validator.js +213 -0
- package/bin/lib/licensing/validator.test.js +137 -0
- package/bin/lib/microsoft-mcp.js +176 -0
- package/bin/lib/microsoft-mcp.test.js +106 -0
- package/bin/lib/skills.js +84 -0
- package/bin/mcp/powerbi-modeling-launcher.js +38 -0
- package/bin/postinstall.js +44 -0
- package/bin/utils/errors.js +159 -0
- package/bin/utils/git.js +298 -0
- package/bin/utils/logger.js +142 -0
- package/bin/utils/mcp-detect.js +274 -0
- package/bin/utils/mcp-detect.test.js +105 -0
- package/bin/utils/pbix.js +305 -0
- package/bin/utils/pbix.test.js +37 -0
- package/bin/utils/profiles.js +312 -0
- package/bin/utils/projects.js +168 -0
- package/bin/utils/readline.js +206 -0
- package/bin/utils/readline.test.js +47 -0
- package/bin/utils/tui.js +314 -0
- package/bin/utils/tui.test.js +127 -0
- package/commands/contributions.md +265 -0
- package/commands/data-model-design.md +468 -0
- package/commands/dax-doctor.md +248 -0
- package/commands/fabric-scripts.md +452 -0
- package/commands/migration-assistant.md +290 -0
- package/commands/model-documenter.md +242 -0
- package/commands/pbi-connect.md +239 -0
- package/commands/project-kickoff.md +905 -0
- package/commands/report-layout.md +296 -0
- package/commands/rls-design.md +533 -0
- package/commands/theme-tweaker.md +624 -0
- package/config.example.json +23 -0
- package/config.json +23 -0
- package/desktop-extension/manifest.json +37 -0
- package/desktop-extension/package.json +10 -0
- package/desktop-extension/server.js +95 -0
- package/docs/openrouter-free-models.md +92 -0
- package/library/examples/README.md +151 -0
- package/library/examples/finance-reporting/README.md +351 -0
- package/library/examples/finance-reporting/data-model.md +267 -0
- package/library/examples/finance-reporting/measures.dax +557 -0
- package/library/examples/hr-analytics/README.md +371 -0
- package/library/examples/hr-analytics/data-model.md +315 -0
- package/library/examples/hr-analytics/measures.dax +460 -0
- package/library/examples/marketing-analytics/README.md +37 -0
- package/library/examples/marketing-analytics/data-model.md +62 -0
- package/library/examples/marketing-analytics/measures.dax +110 -0
- package/library/examples/retail-analytics/README.md +439 -0
- package/library/examples/retail-analytics/data-model.md +288 -0
- package/library/examples/retail-analytics/measures.dax +481 -0
- package/library/examples/supply-chain/README.md +37 -0
- package/library/examples/supply-chain/data-model.md +69 -0
- package/library/examples/supply-chain/measures.dax +77 -0
- package/library/examples/udf-library/README.md +228 -0
- package/library/examples/udf-library/functions.dax +571 -0
- package/library/snippets/dax/README.md +292 -0
- package/library/snippets/dax/business-domains.md +576 -0
- package/library/snippets/dax/calculate-patterns.md +276 -0
- package/library/snippets/dax/calculation-groups.md +489 -0
- package/library/snippets/dax/error-handling.md +495 -0
- package/library/snippets/dax/iterators-and-aggregations.md +474 -0
- package/library/snippets/dax/kpis-and-metrics.md +293 -0
- package/library/snippets/dax/rankings-and-topn.md +235 -0
- package/library/snippets/dax/security-patterns.md +413 -0
- package/library/snippets/dax/text-and-formatting.md +316 -0
- package/library/snippets/dax/time-intelligence.md +196 -0
- package/library/snippets/dax/user-defined-functions.md +477 -0
- package/library/snippets/dax/virtual-tables.md +546 -0
- package/library/snippets/excel-formulas/README.md +84 -0
- package/library/snippets/excel-formulas/aggregations.md +330 -0
- package/library/snippets/excel-formulas/dates-and-times.md +361 -0
- package/library/snippets/excel-formulas/dynamic-arrays.md +314 -0
- package/library/snippets/excel-formulas/lookups.md +169 -0
- package/library/snippets/excel-formulas/text-functions.md +363 -0
- package/library/snippets/governance/naming-conventions.md +97 -0
- package/library/snippets/governance/review-checklists.md +107 -0
- package/library/snippets/power-query/README.md +389 -0
- package/library/snippets/power-query/api-integration.md +707 -0
- package/library/snippets/power-query/connections.md +434 -0
- package/library/snippets/power-query/data-cleaning.md +298 -0
- package/library/snippets/power-query/error-handling.md +526 -0
- package/library/snippets/power-query/parameters.md +350 -0
- package/library/snippets/power-query/performance.md +506 -0
- package/library/snippets/power-query/transformations.md +330 -0
- package/library/snippets/report-design/accessibility.md +78 -0
- package/library/snippets/report-design/chart-selection.md +54 -0
- package/library/snippets/report-design/layout-patterns.md +87 -0
- package/library/templates/data-models/README.md +93 -0
- package/library/templates/data-models/finance-model.md +627 -0
- package/library/templates/data-models/retail-star-schema.md +473 -0
- package/library/templates/excel/README.md +83 -0
- package/library/templates/excel/budget-tracker.md +432 -0
- package/library/templates/excel/data-entry-form.md +533 -0
- package/library/templates/power-bi/README.md +72 -0
- package/library/templates/power-bi/finance-report.md +449 -0
- package/library/templates/power-bi/kpi-scorecard.md +461 -0
- package/library/templates/power-bi/sales-dashboard.md +281 -0
- package/library/themes/excel/README.md +436 -0
- package/library/themes/power-bi/README.md +271 -0
- package/library/themes/power-bi/accessible.json +307 -0
- package/library/themes/power-bi/bi-superpowers-default.json +858 -0
- package/library/themes/power-bi/corporate-blue.json +291 -0
- package/library/themes/power-bi/dark-mode.json +291 -0
- package/library/themes/power-bi/minimal.json +292 -0
- package/library/themes/power-bi/print-friendly.json +309 -0
- package/package.json +93 -0
- package/skills/contributions/SKILL.md +267 -0
- package/skills/data-model-design/SKILL.md +470 -0
- package/skills/data-modeling/SKILL.md +254 -0
- package/skills/data-quality/SKILL.md +664 -0
- package/skills/dax/SKILL.md +708 -0
- package/skills/dax-doctor/SKILL.md +250 -0
- package/skills/dax-udf/SKILL.md +489 -0
- package/skills/deployment/SKILL.md +320 -0
- package/skills/excel-formulas/SKILL.md +463 -0
- package/skills/fabric-scripts/SKILL.md +454 -0
- package/skills/fast-standard/SKILL.md +509 -0
- package/skills/governance/SKILL.md +205 -0
- package/skills/migration-assistant/SKILL.md +292 -0
- package/skills/model-documenter/SKILL.md +244 -0
- package/skills/pbi-connect/SKILL.md +241 -0
- package/skills/power-query/SKILL.md +406 -0
- package/skills/project-kickoff/SKILL.md +907 -0
- package/skills/query-performance/SKILL.md +480 -0
- package/skills/report-design/SKILL.md +207 -0
- package/skills/report-layout/SKILL.md +298 -0
- package/skills/rls-design/SKILL.md +535 -0
- package/skills/semantic-model/SKILL.md +237 -0
- package/skills/testing-validation/SKILL.md +643 -0
- package/skills/theme-tweaker/SKILL.md +626 -0
- package/src/content/base.md +237 -0
- package/src/content/mcp-requirements.json +69 -0
- package/src/content/routing.md +203 -0
- package/src/content/skills/contributions.md +259 -0
- package/src/content/skills/data-model-design.md +462 -0
- package/src/content/skills/data-modeling.md +246 -0
- package/src/content/skills/data-quality.md +656 -0
- package/src/content/skills/dax-doctor.md +242 -0
- package/src/content/skills/dax-udf.md +481 -0
- package/src/content/skills/dax.md +700 -0
- package/src/content/skills/deployment.md +312 -0
- package/src/content/skills/excel-formulas.md +455 -0
- package/src/content/skills/fabric-scripts.md +446 -0
- package/src/content/skills/fast-standard.md +501 -0
- package/src/content/skills/governance.md +197 -0
- package/src/content/skills/migration-assistant.md +284 -0
- package/src/content/skills/model-documenter.md +236 -0
- package/src/content/skills/pbi-connect.md +233 -0
- package/src/content/skills/power-query.md +398 -0
- package/src/content/skills/project-kickoff.md +899 -0
- package/src/content/skills/query-performance.md +472 -0
- package/src/content/skills/report-design.md +199 -0
- package/src/content/skills/report-layout.md +290 -0
- package/src/content/skills/rls-design.md +527 -0
- package/src/content/skills/semantic-model.md +229 -0
- package/src/content/skills/testing-validation.md +635 -0
- package/src/content/skills/theme-tweaker.md +618 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// HR ANALYTICS - DAX MEASURE LIBRARY
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Comprehensive measures for headcount, turnover, tenure, and diversity
|
|
5
|
+
// All measures follow BI Agent Superpowers naming conventions
|
|
6
|
+
// ============================================================================
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
// ----------------------------------------------------------------------------
|
|
10
|
+
// HEADCOUNT MEASURES
|
|
11
|
+
// ----------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
// Current active headcount
|
|
14
|
+
Headcount =
|
|
15
|
+
CALCULATE(
|
|
16
|
+
DISTINCTCOUNT(FactEmployeeSnap[EmployeeKey]),
|
|
17
|
+
DimEmployee[IsActive] = TRUE()
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
// Headcount at end of selected period
|
|
21
|
+
Headcount EOP =
|
|
22
|
+
CALCULATE(
|
|
23
|
+
[Headcount],
|
|
24
|
+
LASTDATE(DimDate[Date])
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
// Headcount at beginning of period
|
|
28
|
+
Headcount BOP =
|
|
29
|
+
CALCULATE(
|
|
30
|
+
[Headcount],
|
|
31
|
+
FIRSTDATE(DimDate[Date])
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
// Average headcount across period
|
|
35
|
+
Headcount Avg =
|
|
36
|
+
AVERAGEX(
|
|
37
|
+
VALUES(DimDate[YearMonth]),
|
|
38
|
+
CALCULATE([Headcount EOP], LASTDATE(DimDate[Date]))
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// Full-Time Equivalents
|
|
42
|
+
FTE =
|
|
43
|
+
CALCULATE(
|
|
44
|
+
SUM(FactEmployeeSnap[FTEFactor]),
|
|
45
|
+
DimEmployee[IsActive] = TRUE(),
|
|
46
|
+
LASTDATE(DimDate[Date])
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
// Part-time headcount
|
|
50
|
+
Part Time Count =
|
|
51
|
+
CALCULATE(
|
|
52
|
+
DISTINCTCOUNT(FactEmployeeSnap[EmployeeKey]),
|
|
53
|
+
FactEmployeeSnap[FTEFactor] < 1,
|
|
54
|
+
DimEmployee[IsActive] = TRUE()
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
// Contractor count (if tracked)
|
|
58
|
+
Contractor Count =
|
|
59
|
+
CALCULATE(
|
|
60
|
+
[Headcount],
|
|
61
|
+
DimEmployee[EmployeeType] = "Contractor"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
// ----------------------------------------------------------------------------
|
|
66
|
+
// TURNOVER MEASURES
|
|
67
|
+
// ----------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
// Total terminations in period
|
|
70
|
+
Terminations =
|
|
71
|
+
VAR _MinDate = MIN(DimDate[Date])
|
|
72
|
+
VAR _MaxDate = MAX(DimDate[Date])
|
|
73
|
+
RETURN
|
|
74
|
+
CALCULATE(
|
|
75
|
+
COUNTROWS(DimEmployee),
|
|
76
|
+
DimEmployee[TermDate] >= _MinDate,
|
|
77
|
+
DimEmployee[TermDate] <= _MaxDate
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
// Voluntary terminations
|
|
81
|
+
Voluntary Terms =
|
|
82
|
+
VAR _MinDate = MIN(DimDate[Date])
|
|
83
|
+
VAR _MaxDate = MAX(DimDate[Date])
|
|
84
|
+
RETURN
|
|
85
|
+
CALCULATE(
|
|
86
|
+
COUNTROWS(DimEmployee),
|
|
87
|
+
DimEmployee[TermDate] >= _MinDate,
|
|
88
|
+
DimEmployee[TermDate] <= _MaxDate,
|
|
89
|
+
DimEmployee[TermType] = "Voluntary"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
// Involuntary terminations
|
|
93
|
+
Involuntary Terms =
|
|
94
|
+
VAR _MinDate = MIN(DimDate[Date])
|
|
95
|
+
VAR _MaxDate = MAX(DimDate[Date])
|
|
96
|
+
RETURN
|
|
97
|
+
CALCULATE(
|
|
98
|
+
COUNTROWS(DimEmployee),
|
|
99
|
+
DimEmployee[TermDate] >= _MinDate,
|
|
100
|
+
DimEmployee[TermDate] <= _MaxDate,
|
|
101
|
+
DimEmployee[TermType] = "Involuntary"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
// Regrettable turnover (high performers who left voluntarily)
|
|
105
|
+
Regrettable Terms =
|
|
106
|
+
VAR _MinDate = MIN(DimDate[Date])
|
|
107
|
+
VAR _MaxDate = MAX(DimDate[Date])
|
|
108
|
+
RETURN
|
|
109
|
+
CALCULATE(
|
|
110
|
+
COUNTROWS(DimEmployee),
|
|
111
|
+
DimEmployee[TermDate] >= _MinDate,
|
|
112
|
+
DimEmployee[TermDate] <= _MaxDate,
|
|
113
|
+
DimEmployee[TermType] = "Voluntary",
|
|
114
|
+
DimEmployee[LastPerformanceRating] >= 4
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
// Turnover Rate (annualized)
|
|
118
|
+
Turnover Rate =
|
|
119
|
+
VAR _Terms = [Terminations]
|
|
120
|
+
VAR _AvgHC = [Headcount Avg]
|
|
121
|
+
VAR _Months = DISTINCTCOUNT(DimDate[YearMonth])
|
|
122
|
+
VAR _AnnualizationFactor = DIVIDE(12, _Months)
|
|
123
|
+
RETURN
|
|
124
|
+
DIVIDE(_Terms, _AvgHC) * _AnnualizationFactor
|
|
125
|
+
|
|
126
|
+
// Voluntary Turnover Rate
|
|
127
|
+
Voluntary Turnover Rate =
|
|
128
|
+
VAR _VolTerms = [Voluntary Terms]
|
|
129
|
+
VAR _AvgHC = [Headcount Avg]
|
|
130
|
+
VAR _Months = DISTINCTCOUNT(DimDate[YearMonth])
|
|
131
|
+
VAR _AnnualizationFactor = DIVIDE(12, _Months)
|
|
132
|
+
RETURN
|
|
133
|
+
DIVIDE(_VolTerms, _AvgHC) * _AnnualizationFactor
|
|
134
|
+
|
|
135
|
+
// Regrettable Turnover Rate
|
|
136
|
+
Regrettable Turnover Rate =
|
|
137
|
+
VAR _RegTerms = [Regrettable Terms]
|
|
138
|
+
VAR _AvgHC = [Headcount Avg]
|
|
139
|
+
VAR _Months = DISTINCTCOUNT(DimDate[YearMonth])
|
|
140
|
+
VAR _AnnualizationFactor = DIVIDE(12, _Months)
|
|
141
|
+
RETURN
|
|
142
|
+
DIVIDE(_RegTerms, _AvgHC) * _AnnualizationFactor
|
|
143
|
+
|
|
144
|
+
// Retention Rate
|
|
145
|
+
Retention Rate =
|
|
146
|
+
1 - [Turnover Rate]
|
|
147
|
+
|
|
148
|
+
// 90-Day Turnover (early attrition)
|
|
149
|
+
Early Attrition =
|
|
150
|
+
VAR _MinDate = MIN(DimDate[Date])
|
|
151
|
+
VAR _MaxDate = MAX(DimDate[Date])
|
|
152
|
+
RETURN
|
|
153
|
+
CALCULATE(
|
|
154
|
+
COUNTROWS(DimEmployee),
|
|
155
|
+
DimEmployee[TermDate] >= _MinDate,
|
|
156
|
+
DimEmployee[TermDate] <= _MaxDate,
|
|
157
|
+
DimEmployee[TenureYears] * 365 <= 90
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
// First Year Turnover
|
|
161
|
+
First Year Turnover Rate =
|
|
162
|
+
VAR _FirstYearTerms =
|
|
163
|
+
CALCULATE(
|
|
164
|
+
[Terminations],
|
|
165
|
+
DimEmployee[TenureYears] < 1
|
|
166
|
+
)
|
|
167
|
+
VAR _NewHires = [New Hires]
|
|
168
|
+
RETURN
|
|
169
|
+
DIVIDE(_FirstYearTerms, _NewHires)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
// ----------------------------------------------------------------------------
|
|
173
|
+
// HIRING MEASURES
|
|
174
|
+
// ----------------------------------------------------------------------------
|
|
175
|
+
|
|
176
|
+
// New hires in period
|
|
177
|
+
New Hires =
|
|
178
|
+
VAR _MinDate = MIN(DimDate[Date])
|
|
179
|
+
VAR _MaxDate = MAX(DimDate[Date])
|
|
180
|
+
RETURN
|
|
181
|
+
CALCULATE(
|
|
182
|
+
COUNTROWS(DimEmployee),
|
|
183
|
+
DimEmployee[HireDate] >= _MinDate,
|
|
184
|
+
DimEmployee[HireDate] <= _MaxDate
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
// Net headcount change
|
|
188
|
+
Net Change =
|
|
189
|
+
[New Hires] - [Terminations]
|
|
190
|
+
|
|
191
|
+
// Hiring Rate
|
|
192
|
+
Hiring Rate =
|
|
193
|
+
VAR _Hires = [New Hires]
|
|
194
|
+
VAR _AvgHC = [Headcount Avg]
|
|
195
|
+
VAR _Months = DISTINCTCOUNT(DimDate[YearMonth])
|
|
196
|
+
VAR _AnnualizationFactor = DIVIDE(12, _Months)
|
|
197
|
+
RETURN
|
|
198
|
+
DIVIDE(_Hires, _AvgHC) * _AnnualizationFactor
|
|
199
|
+
|
|
200
|
+
// Growth Rate
|
|
201
|
+
Growth Rate =
|
|
202
|
+
DIVIDE([Net Change], [Headcount BOP])
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
// ----------------------------------------------------------------------------
|
|
206
|
+
// TENURE MEASURES
|
|
207
|
+
// ----------------------------------------------------------------------------
|
|
208
|
+
|
|
209
|
+
// Average tenure (active employees)
|
|
210
|
+
Avg Tenure =
|
|
211
|
+
AVERAGEX(
|
|
212
|
+
FILTER(DimEmployee, DimEmployee[IsActive] = TRUE()),
|
|
213
|
+
DimEmployee[TenureYears]
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
// Median tenure
|
|
217
|
+
Median Tenure =
|
|
218
|
+
MEDIANX(
|
|
219
|
+
FILTER(DimEmployee, DimEmployee[IsActive] = TRUE()),
|
|
220
|
+
DimEmployee[TenureYears]
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
// Tenure by bucket (for visualization)
|
|
224
|
+
Tenure < 1 Year =
|
|
225
|
+
CALCULATE(
|
|
226
|
+
[Headcount],
|
|
227
|
+
DimEmployee[TenureBucket] = "< 1 Year"
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
Tenure 1-2 Years =
|
|
231
|
+
CALCULATE(
|
|
232
|
+
[Headcount],
|
|
233
|
+
DimEmployee[TenureBucket] = "1-2 Years"
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
Tenure 2-5 Years =
|
|
237
|
+
CALCULATE(
|
|
238
|
+
[Headcount],
|
|
239
|
+
DimEmployee[TenureBucket] = "2-5 Years"
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
Tenure 5-10 Years =
|
|
243
|
+
CALCULATE(
|
|
244
|
+
[Headcount],
|
|
245
|
+
DimEmployee[TenureBucket] = "5-10 Years"
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
Tenure 10+ Years =
|
|
249
|
+
CALCULATE(
|
|
250
|
+
[Headcount],
|
|
251
|
+
DimEmployee[TenureBucket] = ">= 10 Years"
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
// ----------------------------------------------------------------------------
|
|
256
|
+
// DIVERSITY MEASURES
|
|
257
|
+
// ----------------------------------------------------------------------------
|
|
258
|
+
|
|
259
|
+
// Gender breakdown
|
|
260
|
+
Female Count =
|
|
261
|
+
CALCULATE([Headcount], DimEmployee[Gender] = "Female")
|
|
262
|
+
|
|
263
|
+
Male Count =
|
|
264
|
+
CALCULATE([Headcount], DimEmployee[Gender] = "Male")
|
|
265
|
+
|
|
266
|
+
Non Binary Count =
|
|
267
|
+
CALCULATE([Headcount], DimEmployee[Gender] = "Non-Binary")
|
|
268
|
+
|
|
269
|
+
// Gender percentages
|
|
270
|
+
Female % =
|
|
271
|
+
DIVIDE([Female Count], [Headcount])
|
|
272
|
+
|
|
273
|
+
Male % =
|
|
274
|
+
DIVIDE([Male Count], [Headcount])
|
|
275
|
+
|
|
276
|
+
// Female in management
|
|
277
|
+
Female Managers % =
|
|
278
|
+
DIVIDE(
|
|
279
|
+
CALCULATE([Headcount], DimEmployee[Gender] = "Female", DimJob[IsManagement] = TRUE()),
|
|
280
|
+
CALCULATE([Headcount], DimJob[IsManagement] = TRUE())
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
// Female in leadership (Director+)
|
|
284
|
+
Female Leaders % =
|
|
285
|
+
DIVIDE(
|
|
286
|
+
CALCULATE([Headcount], DimEmployee[Gender] = "Female", DimJob[JobLevel] >= 8),
|
|
287
|
+
CALCULATE([Headcount], DimJob[JobLevel] >= 8)
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
// Diversity Index (Blau Index: 1 - sum of squared proportions)
|
|
291
|
+
Diversity Index =
|
|
292
|
+
VAR _Total = [Headcount]
|
|
293
|
+
VAR _ByEthnicity =
|
|
294
|
+
ADDCOLUMNS(
|
|
295
|
+
VALUES(DimEmployee[Ethnicity]),
|
|
296
|
+
"@Count", [Headcount]
|
|
297
|
+
)
|
|
298
|
+
VAR _SumSquares =
|
|
299
|
+
SUMX(_ByEthnicity, POWER(DIVIDE([@Count], _Total), 2))
|
|
300
|
+
RETURN
|
|
301
|
+
IF(_Total > 0, 1 - _SumSquares)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
// ----------------------------------------------------------------------------
|
|
305
|
+
// COMPENSATION MEASURES
|
|
306
|
+
// ----------------------------------------------------------------------------
|
|
307
|
+
|
|
308
|
+
// Average salary
|
|
309
|
+
Avg Salary =
|
|
310
|
+
AVERAGE(FactEmployeeSnap[Salary])
|
|
311
|
+
|
|
312
|
+
// Median salary
|
|
313
|
+
Median Salary =
|
|
314
|
+
MEDIAN(FactEmployeeSnap[Salary])
|
|
315
|
+
|
|
316
|
+
// Salary per headcount (for budget tracking)
|
|
317
|
+
Total Salary Expense =
|
|
318
|
+
SUM(FactEmployeeSnap[Salary])
|
|
319
|
+
|
|
320
|
+
// Compa-ratio average
|
|
321
|
+
Avg Compa Ratio =
|
|
322
|
+
AVERAGE(FactEmployeeSnap[CompaRatio])
|
|
323
|
+
|
|
324
|
+
// Pay equity ratio (female / male median salary)
|
|
325
|
+
Pay Equity Ratio =
|
|
326
|
+
VAR _FemaleSalary =
|
|
327
|
+
CALCULATE(MEDIAN(FactEmployeeSnap[Salary]), DimEmployee[Gender] = "Female")
|
|
328
|
+
VAR _MaleSalary =
|
|
329
|
+
CALCULATE(MEDIAN(FactEmployeeSnap[Salary]), DimEmployee[Gender] = "Male")
|
|
330
|
+
RETURN
|
|
331
|
+
DIVIDE(_FemaleSalary, _MaleSalary)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
// ----------------------------------------------------------------------------
|
|
335
|
+
// ENGAGEMENT & PERFORMANCE
|
|
336
|
+
// ----------------------------------------------------------------------------
|
|
337
|
+
|
|
338
|
+
// Average engagement score
|
|
339
|
+
Avg Engagement =
|
|
340
|
+
AVERAGE(FactEmployeeSnap[EngagementScore])
|
|
341
|
+
|
|
342
|
+
// Average performance rating
|
|
343
|
+
Avg Performance =
|
|
344
|
+
AVERAGE(FactEmployeeSnap[PerformanceRating])
|
|
345
|
+
|
|
346
|
+
// High performers (rating 4-5)
|
|
347
|
+
High Performers =
|
|
348
|
+
CALCULATE(
|
|
349
|
+
[Headcount],
|
|
350
|
+
FactEmployeeSnap[PerformanceRating] >= 4
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
High Performers % =
|
|
354
|
+
DIVIDE([High Performers], [Headcount])
|
|
355
|
+
|
|
356
|
+
// Low performers
|
|
357
|
+
Low Performers =
|
|
358
|
+
CALCULATE(
|
|
359
|
+
[Headcount],
|
|
360
|
+
FactEmployeeSnap[PerformanceRating] <= 2
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
// Flight risk (high performers with low engagement + long tenure)
|
|
364
|
+
Flight Risk =
|
|
365
|
+
CALCULATE(
|
|
366
|
+
[Headcount],
|
|
367
|
+
FactEmployeeSnap[PerformanceRating] >= 4,
|
|
368
|
+
FactEmployeeSnap[EngagementScore] < 3.5,
|
|
369
|
+
DimEmployee[TenureYears] >= 3
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
// ----------------------------------------------------------------------------
|
|
374
|
+
// TIME COMPARISONS
|
|
375
|
+
// ----------------------------------------------------------------------------
|
|
376
|
+
|
|
377
|
+
// Prior year headcount
|
|
378
|
+
Headcount PY =
|
|
379
|
+
CALCULATE(
|
|
380
|
+
[Headcount EOP],
|
|
381
|
+
SAMEPERIODLASTYEAR(DimDate[Date])
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
// YoY headcount change
|
|
385
|
+
Headcount YoY Change =
|
|
386
|
+
[Headcount EOP] - [Headcount PY]
|
|
387
|
+
|
|
388
|
+
Headcount YoY % =
|
|
389
|
+
DIVIDE([Headcount YoY Change], [Headcount PY])
|
|
390
|
+
|
|
391
|
+
// Prior year turnover
|
|
392
|
+
Turnover Rate PY =
|
|
393
|
+
CALCULATE(
|
|
394
|
+
[Turnover Rate],
|
|
395
|
+
SAMEPERIODLASTYEAR(DimDate[Date])
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
// ----------------------------------------------------------------------------
|
|
400
|
+
// DISPLAY / FORMATTING
|
|
401
|
+
// ----------------------------------------------------------------------------
|
|
402
|
+
|
|
403
|
+
Headcount Display =
|
|
404
|
+
FORMAT([Headcount], "#,##0")
|
|
405
|
+
|
|
406
|
+
Turnover Display =
|
|
407
|
+
FORMAT([Turnover Rate], "0.0%")
|
|
408
|
+
|
|
409
|
+
Tenure Display =
|
|
410
|
+
FORMAT([Avg Tenure], "0.0") & " years"
|
|
411
|
+
|
|
412
|
+
Salary Display =
|
|
413
|
+
FORMAT([Avg Salary], "$#,##0")
|
|
414
|
+
|
|
415
|
+
// Trend indicator
|
|
416
|
+
Turnover Trend =
|
|
417
|
+
VAR _Current = [Turnover Rate]
|
|
418
|
+
VAR _PY = [Turnover Rate PY]
|
|
419
|
+
RETURN
|
|
420
|
+
SWITCH(
|
|
421
|
+
TRUE(),
|
|
422
|
+
ISBLANK(_PY), "•",
|
|
423
|
+
_Current < _PY * 0.95, "▼ Improving",
|
|
424
|
+
_Current > _PY * 1.05, "▲ Worsening",
|
|
425
|
+
"• Stable"
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
// ============================================================================
|
|
430
|
+
// MEASURE ORGANIZATION (Display Folders)
|
|
431
|
+
// ============================================================================
|
|
432
|
+
//
|
|
433
|
+
// 👥 Headcount
|
|
434
|
+
// - Headcount, Headcount EOP, Headcount Avg, FTE
|
|
435
|
+
//
|
|
436
|
+
// 🚪 Turnover
|
|
437
|
+
// - Terminations, Voluntary Terms, Involuntary Terms
|
|
438
|
+
// - Turnover Rate, Voluntary Turnover Rate, Retention Rate
|
|
439
|
+
//
|
|
440
|
+
// 🆕 Hiring
|
|
441
|
+
// - New Hires, Net Change, Hiring Rate, Growth Rate
|
|
442
|
+
//
|
|
443
|
+
// ⏱️ Tenure
|
|
444
|
+
// - Avg Tenure, Median Tenure, Tenure buckets
|
|
445
|
+
//
|
|
446
|
+
// 🌍 Diversity
|
|
447
|
+
// - Female %, Female Managers %, Diversity Index
|
|
448
|
+
//
|
|
449
|
+
// 💰 Compensation
|
|
450
|
+
// - Avg Salary, Median Salary, Compa Ratio, Pay Equity
|
|
451
|
+
//
|
|
452
|
+
// ⭐ Performance
|
|
453
|
+
// - Avg Engagement, High Performers %, Flight Risk
|
|
454
|
+
//
|
|
455
|
+
// 📅 Time Comparison
|
|
456
|
+
// - Headcount PY, Headcount YoY %, Turnover Rate PY
|
|
457
|
+
//
|
|
458
|
+
// 🎨 Display
|
|
459
|
+
// - Headcount Display, Turnover Display, Tenure Display
|
|
460
|
+
// ============================================================================
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Marketing Analytics Example
|
|
2
|
+
|
|
3
|
+
Reference implementation for a marketing analytics Power BI model.
|
|
4
|
+
|
|
5
|
+
## Business Context
|
|
6
|
+
|
|
7
|
+
Analyze campaign performance, channel effectiveness, lead generation, and marketing ROI across digital and traditional channels.
|
|
8
|
+
|
|
9
|
+
## Key Metrics
|
|
10
|
+
|
|
11
|
+
| Metric | Description |
|
|
12
|
+
|--------|-------------|
|
|
13
|
+
| Cost Per Lead (CPL) | Total spend / leads generated |
|
|
14
|
+
| Cost Per Acquisition (CPA) | Total spend / customers acquired |
|
|
15
|
+
| Return on Ad Spend (ROAS) | Revenue attributed / ad spend |
|
|
16
|
+
| Conversion Rate | Conversions / total interactions |
|
|
17
|
+
| Click-Through Rate (CTR) | Clicks / impressions |
|
|
18
|
+
| Customer Acquisition Cost (CAC) | Total marketing cost / new customers |
|
|
19
|
+
| Marketing Qualified Leads (MQL) | Leads meeting qualification criteria |
|
|
20
|
+
|
|
21
|
+
## Data Model
|
|
22
|
+
|
|
23
|
+
See [data-model.md](data-model.md) for the complete star schema design.
|
|
24
|
+
|
|
25
|
+
## Files
|
|
26
|
+
|
|
27
|
+
| File | Purpose |
|
|
28
|
+
|------|---------|
|
|
29
|
+
| `data-model.md` | Star schema with tables and relationships |
|
|
30
|
+
| `measures.dax` | Core DAX measures for marketing KPIs |
|
|
31
|
+
|
|
32
|
+
## Report Pages
|
|
33
|
+
|
|
34
|
+
1. **Campaign Overview** — Spend, leads, conversions by campaign
|
|
35
|
+
2. **Channel Performance** — ROI comparison across channels
|
|
36
|
+
3. **Funnel Analysis** — Lead → MQL → SQL → Opportunity → Customer
|
|
37
|
+
4. **Attribution** — Multi-touch attribution analysis
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Marketing Analytics Data Model
|
|
2
|
+
|
|
3
|
+
## Star Schema
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
┌──────────────┐
|
|
7
|
+
│ DimDate │
|
|
8
|
+
│──────────────│
|
|
9
|
+
│ DateKey (PK) │
|
|
10
|
+
│ Date │
|
|
11
|
+
│ Month │
|
|
12
|
+
│ Quarter │
|
|
13
|
+
│ Year │
|
|
14
|
+
│ WeekOfYear │
|
|
15
|
+
└──────┬───────┘
|
|
16
|
+
│
|
|
17
|
+
┌──────────────┐ ┌───────┴────────┐ ┌──────────────┐
|
|
18
|
+
│ DimCampaign │ │ FactCampaign │ │ DimChannel │
|
|
19
|
+
│──────────────│ │ Performance │ │──────────────│
|
|
20
|
+
│ CampaignKey │◄──│ CampaignKey │──►│ ChannelKey │
|
|
21
|
+
│ CampaignName │ │ ChannelKey │ │ ChannelName │
|
|
22
|
+
│ CampaignType │ │ DateKey │ │ ChannelType │
|
|
23
|
+
│ StartDate │ │ Impressions │ │ IsDigital │
|
|
24
|
+
│ EndDate │ │ Clicks │ └──────────────┘
|
|
25
|
+
│ Budget │ │ Spend │
|
|
26
|
+
│ Objective │ │ Leads │
|
|
27
|
+
└──────────────┘ │ Conversions │
|
|
28
|
+
│ Revenue │
|
|
29
|
+
└───────────────┘
|
|
30
|
+
|
|
31
|
+
┌──────────────┐ ┌───────────────┐ ┌──────────────┐
|
|
32
|
+
│ DimLeadSource│ │ FactLeads │ │ DimLeadStage │
|
|
33
|
+
│──────────────│ │───────────────│ │──────────────│
|
|
34
|
+
│ SourceKey │◄──│ SourceKey │──►│ StageKey │
|
|
35
|
+
│ SourceName │ │ StageKey │ │ StageName │
|
|
36
|
+
│ SourceType │ │ CampaignKey │ │ StageOrder │
|
|
37
|
+
│ Medium │ │ DateKey │ │ IsQualified │
|
|
38
|
+
└──────────────┘ │ LeadKey │ └──────────────┘
|
|
39
|
+
│ IsConverted │
|
|
40
|
+
│ DaysInStage │
|
|
41
|
+
│ LeadScore │
|
|
42
|
+
└───────────────┘
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Relationships
|
|
46
|
+
|
|
47
|
+
| From | To | Cardinality | Direction |
|
|
48
|
+
|------|----|-------------|-----------|
|
|
49
|
+
| FactCampaignPerformance[DateKey] | DimDate[DateKey] | Many-to-One | Single |
|
|
50
|
+
| FactCampaignPerformance[CampaignKey] | DimCampaign[CampaignKey] | Many-to-One | Single |
|
|
51
|
+
| FactCampaignPerformance[ChannelKey] | DimChannel[ChannelKey] | Many-to-One | Single |
|
|
52
|
+
| FactLeads[DateKey] | DimDate[DateKey] | Many-to-One | Single |
|
|
53
|
+
| FactLeads[SourceKey] | DimLeadSource[SourceKey] | Many-to-One | Single |
|
|
54
|
+
| FactLeads[StageKey] | DimLeadStage[StageKey] | Many-to-One | Single |
|
|
55
|
+
| FactLeads[CampaignKey] | DimCampaign[CampaignKey] | Many-to-One | Single |
|
|
56
|
+
|
|
57
|
+
## Notes
|
|
58
|
+
|
|
59
|
+
- `FactCampaignPerformance` is a daily snapshot of campaign metrics per channel
|
|
60
|
+
- `FactLeads` tracks individual leads through the funnel (one row per lead per stage transition)
|
|
61
|
+
- `DimLeadStage` defines the marketing/sales funnel stages
|
|
62
|
+
- Connect to CRM data via `LeadKey` for full customer journey analysis
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Marketing Analytics KPI Measures
|
|
2
|
+
// ================================
|
|
3
|
+
// Core measures for marketing analytics model.
|
|
4
|
+
|
|
5
|
+
// --- Spend & Volume Metrics ---
|
|
6
|
+
|
|
7
|
+
// Total marketing spend across all campaigns
|
|
8
|
+
TotalSpend =
|
|
9
|
+
SUM(FactCampaignPerformance[Spend])
|
|
10
|
+
|
|
11
|
+
// Total impressions served
|
|
12
|
+
TotalImpressions =
|
|
13
|
+
SUM(FactCampaignPerformance[Impressions])
|
|
14
|
+
|
|
15
|
+
// Total clicks received
|
|
16
|
+
TotalClicks =
|
|
17
|
+
SUM(FactCampaignPerformance[Clicks])
|
|
18
|
+
|
|
19
|
+
// Total leads generated from campaigns
|
|
20
|
+
TotalLeads =
|
|
21
|
+
SUM(FactCampaignPerformance[Leads])
|
|
22
|
+
|
|
23
|
+
// Total conversions (leads that became customers)
|
|
24
|
+
TotalConversions =
|
|
25
|
+
SUM(FactCampaignPerformance[Conversions])
|
|
26
|
+
|
|
27
|
+
// Revenue attributed to marketing campaigns
|
|
28
|
+
TotalRevenue =
|
|
29
|
+
SUM(FactCampaignPerformance[Revenue])
|
|
30
|
+
|
|
31
|
+
// --- Efficiency Metrics ---
|
|
32
|
+
|
|
33
|
+
// Click-through rate: clicks as percentage of impressions
|
|
34
|
+
CTR =
|
|
35
|
+
DIVIDE([TotalClicks], [TotalImpressions])
|
|
36
|
+
|
|
37
|
+
// Conversion rate: conversions as percentage of clicks
|
|
38
|
+
ConversionRate =
|
|
39
|
+
DIVIDE([TotalConversions], [TotalClicks])
|
|
40
|
+
|
|
41
|
+
// Cost per click
|
|
42
|
+
CPC =
|
|
43
|
+
DIVIDE([TotalSpend], [TotalClicks])
|
|
44
|
+
|
|
45
|
+
// Cost per lead
|
|
46
|
+
CPL =
|
|
47
|
+
DIVIDE([TotalSpend], [TotalLeads])
|
|
48
|
+
|
|
49
|
+
// Cost per acquisition (customer)
|
|
50
|
+
CPA =
|
|
51
|
+
DIVIDE([TotalSpend], [TotalConversions])
|
|
52
|
+
|
|
53
|
+
// --- ROI Metrics ---
|
|
54
|
+
|
|
55
|
+
// Return on ad spend: revenue generated per dollar spent
|
|
56
|
+
ROAS =
|
|
57
|
+
DIVIDE([TotalRevenue], [TotalSpend])
|
|
58
|
+
|
|
59
|
+
// Marketing ROI: net profit from marketing as percentage of spend
|
|
60
|
+
MarketingROI =
|
|
61
|
+
DIVIDE([TotalRevenue] - [TotalSpend], [TotalSpend])
|
|
62
|
+
|
|
63
|
+
// --- Funnel Metrics ---
|
|
64
|
+
|
|
65
|
+
// Count of Marketing Qualified Leads
|
|
66
|
+
MQLCount =
|
|
67
|
+
CALCULATE(
|
|
68
|
+
DISTINCTCOUNT(FactLeads[LeadKey]),
|
|
69
|
+
RELATEDTABLE(DimLeadStage),
|
|
70
|
+
DimLeadStage[IsQualified] = TRUE()
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
// Lead-to-MQL conversion rate
|
|
74
|
+
LeadToMQLRate =
|
|
75
|
+
VAR _TotalLeads = DISTINCTCOUNT(FactLeads[LeadKey])
|
|
76
|
+
RETURN DIVIDE([MQLCount], _TotalLeads)
|
|
77
|
+
|
|
78
|
+
// Average days in current funnel stage
|
|
79
|
+
AvgDaysInStage =
|
|
80
|
+
AVERAGE(FactLeads[DaysInStage])
|
|
81
|
+
|
|
82
|
+
// Average lead score
|
|
83
|
+
AvgLeadScore =
|
|
84
|
+
AVERAGE(FactLeads[LeadScore])
|
|
85
|
+
|
|
86
|
+
// --- Budget Metrics ---
|
|
87
|
+
|
|
88
|
+
// Budget utilization: actual spend vs allocated budget
|
|
89
|
+
BudgetUtilization =
|
|
90
|
+
VAR _ActualSpend = [TotalSpend]
|
|
91
|
+
VAR _Budget = SUM(DimCampaign[Budget])
|
|
92
|
+
RETURN DIVIDE(_ActualSpend, _Budget)
|
|
93
|
+
|
|
94
|
+
// Budget remaining
|
|
95
|
+
BudgetRemaining =
|
|
96
|
+
SUM(DimCampaign[Budget]) - [TotalSpend]
|
|
97
|
+
|
|
98
|
+
// --- Time Comparisons ---
|
|
99
|
+
|
|
100
|
+
// Spend vs prior period (for any time selection)
|
|
101
|
+
SpendVsPrior =
|
|
102
|
+
VAR _Current = [TotalSpend]
|
|
103
|
+
VAR _Prior = CALCULATE([TotalSpend], DATEADD('Date'[Date], -1, MONTH))
|
|
104
|
+
RETURN _Current - _Prior
|
|
105
|
+
|
|
106
|
+
// Spend growth rate
|
|
107
|
+
SpendGrowthRate =
|
|
108
|
+
VAR _Current = [TotalSpend]
|
|
109
|
+
VAR _Prior = CALCULATE([TotalSpend], DATEADD('Date'[Date], -1, MONTH))
|
|
110
|
+
RETURN DIVIDE(_Current - _Prior, _Prior)
|