@luquimbo/bi-superpowers 5.0.0 → 5.0.2

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.
Files changed (196) hide show
  1. package/.claude-plugin/marketplace.json +5 -3
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.claude-plugin/skill-manifest.json +23 -7
  4. package/.plugin/plugin.json +1 -1
  5. package/AGENTS.md +124 -26
  6. package/CHANGELOG.md +494 -16
  7. package/README.md +33 -117
  8. package/bin/cli.js +1 -1
  9. package/bin/commands/diff.js +2 -2
  10. package/bin/commands/install.js +58 -45
  11. package/bin/commands/lint.js +2 -2
  12. package/bin/commands/validate-projects.js +1 -1
  13. package/bin/lib/generators/claude-plugin.js +14 -5
  14. package/bin/lib/generators/shared.js +9 -5
  15. package/bin/lib/mcp-config.js +22 -2
  16. package/bin/lib/skills.js +8 -8
  17. package/bin/mcp/powerbi-modeling-launcher.js +8 -4
  18. package/bin/postinstall.js +14 -12
  19. package/bin/utils/mcp-detect.js +11 -11
  20. package/commands/bi-connect.md +34 -17
  21. package/commands/bi-dax.md +385 -0
  22. package/commands/bi-kickoff.md +75 -44
  23. package/commands/bi-modeling.md +395 -0
  24. package/commands/bi-performance.md +455 -0
  25. package/commands/bi-start.md +30 -18
  26. package/desktop-extension/manifest.json +2 -2
  27. package/package.json +6 -3
  28. package/skills/bi-connect/SKILL.md +34 -17
  29. package/skills/bi-connect/scripts/update-check.js +1 -1
  30. package/skills/bi-dax/SKILL.md +387 -0
  31. package/skills/{bi-report → bi-dax}/scripts/update-check.js +1 -1
  32. package/skills/bi-kickoff/SKILL.md +75 -44
  33. package/skills/bi-kickoff/scripts/update-check.js +1 -1
  34. package/skills/bi-modeling/SKILL.md +397 -0
  35. package/skills/bi-modeling/scripts/update-check.js +403 -0
  36. package/skills/bi-performance/SKILL.md +457 -0
  37. package/skills/bi-performance/scripts/install-tabular-editor.ps1 +90 -0
  38. package/skills/bi-performance/scripts/run-bpa.ps1 +161 -0
  39. package/skills/bi-performance/scripts/update-check.js +403 -0
  40. package/skills/bi-start/SKILL.md +31 -19
  41. package/skills/bi-start/scripts/update-check.js +1 -1
  42. package/src/content/base.md +13 -8
  43. package/src/content/routing.md +1 -5
  44. package/src/content/skills/bi-connect.md +32 -15
  45. package/src/content/skills/bi-dax.md +358 -0
  46. package/src/content/skills/bi-kickoff.md +73 -42
  47. package/src/content/skills/bi-modeling.md +368 -0
  48. package/src/content/skills/bi-performance/SKILL.md +428 -0
  49. package/src/content/skills/bi-performance/scripts/install-tabular-editor.ps1 +90 -0
  50. package/src/content/skills/bi-performance/scripts/run-bpa.ps1 +161 -0
  51. package/src/content/skills/bi-start.md +30 -18
  52. package/templates/sales/AGENTS.md +33 -0
  53. package/templates/sales/sales-template.Report/.platform +11 -0
  54. package/templates/sales/sales-template.Report/StaticResources/RegisteredResources/BISuperpowers.json +3888 -0
  55. package/templates/sales/sales-template.Report/StaticResources/SharedResources/BaseThemes/Fluent2-CY26SU03.json +4104 -0
  56. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/page.json +123 -0
  57. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/10420560e5b8c5235857/visual.json +16 -0
  58. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/2181c54a94f0c67abb2d/visual.json +283 -0
  59. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/24eba6a7af0b59974ef5/visual.json +703 -0
  60. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/26db24c91e5b615a5c29/mobile.json +11 -0
  61. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/26db24c91e5b615a5c29/visual.json +528 -0
  62. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/2ec652d0956901dd2afd/mobile.json +11 -0
  63. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/2ec652d0956901dd2afd/visual.json +324 -0
  64. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/45dda4e0b159becf2dcd/mobile.json +11 -0
  65. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/45dda4e0b159becf2dcd/visual.json +359 -0
  66. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/4ca8800cf1539ad423f2/visual.json +468 -0
  67. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/4f5704218eb88f7cdff6/mobile.json +29 -0
  68. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/4f5704218eb88f7cdff6/visual.json +241 -0
  69. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/54d3fdbedbbb863a9d7a/visual.json +575 -0
  70. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/68043403e96ca8ed23e8/visual.json +575 -0
  71. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/80b54a678ef36a250994/visual.json +351 -0
  72. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/814f624b6056dc4c8de5/mobile.json +11 -0
  73. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/814f624b6056dc4c8de5/visual.json +421 -0
  74. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/85e1cc13559f4e107ede/visual.json +681 -0
  75. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/8686961b837e855963fe/mobile.json +11 -0
  76. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/8686961b837e855963fe/visual.json +720 -0
  77. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/8d302c5b7e87e8cb57bb/visual.json +590 -0
  78. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/a02c5b30f2e757637d78/mobile.json +11 -0
  79. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/a02c5b30f2e757637d78/visual.json +102 -0
  80. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/a405d29e7744c770d445/visual.json +575 -0
  81. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/b0dc2036d3cf2baafb35/mobile.json +11 -0
  82. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/b0dc2036d3cf2baafb35/visual.json +333 -0
  83. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/cdd696baaf3b80b326f8/mobile.json +11 -0
  84. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/cdd696baaf3b80b326f8/visual.json +468 -0
  85. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/ff77ca1bafff5bfe5044/mobile.json +11 -0
  86. package/templates/sales/sales-template.Report/definition/pages/017e2c84c7dc89f26e57/visuals/ff77ca1bafff5bfe5044/visual.json +523 -0
  87. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/page.json +130 -0
  88. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/visual.json +681 -0
  89. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/visual.json +351 -0
  90. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/mobile.json +11 -0
  91. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/visual.json +333 -0
  92. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/mobile.json +11 -0
  93. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/visual.json +102 -0
  94. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/mobile.json +11 -0
  95. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/visual.json +468 -0
  96. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/mobile.json +11 -0
  97. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/visual.json +359 -0
  98. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/visual.json +685 -0
  99. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/85090dcdf75ac2487d1e/visual.json +283 -0
  100. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/visual.json +468 -0
  101. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/visual.json +590 -0
  102. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/mobile.json +11 -0
  103. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/visual.json +528 -0
  104. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a90aaa3e3117494f18f8/mobile.json +11 -0
  105. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a90aaa3e3117494f18f8/visual.json +523 -0
  106. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/mobile.json +11 -0
  107. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/visual.json +720 -0
  108. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/mobile.json +37 -0
  109. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/visual.json +1230 -0
  110. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/b06ef80aa78cabcef8a6/mobile.json +11 -0
  111. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/b06ef80aa78cabcef8a6/visual.json +324 -0
  112. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/d97979633a91e041107e/mobile.json +11 -0
  113. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/d97979633a91e041107e/visual.json +421 -0
  114. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/mobile.json +29 -0
  115. package/templates/sales/sales-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/visual.json +241 -0
  116. package/templates/sales/sales-template.Report/definition/pages/pages.json +8 -0
  117. package/templates/sales/sales-template.Report/definition/report.json +89 -0
  118. package/templates/sales/sales-template.Report/definition/version.json +4 -0
  119. package/templates/sales/sales-template.Report/definition.pbir +9 -0
  120. package/templates/sales/sales-template.SemanticModel/.pbi/editorSettings.json +8 -0
  121. package/templates/sales/sales-template.SemanticModel/.platform +11 -0
  122. package/templates/sales/sales-template.SemanticModel/DAXQueries/.pbi/daxQueries.json +9 -0
  123. package/templates/sales/sales-template.SemanticModel/DAXQueries/Calendar445MonthNr.dax +0 -0
  124. package/templates/sales/sales-template.SemanticModel/DAXQueries/Consulta 1.dax +6 -0
  125. package/templates/sales/sales-template.SemanticModel/DAXQueries/Consulta 2.dax +32 -0
  126. package/templates/sales/sales-template.SemanticModel/definition/cultures/es-AR.tmdl +7324 -0
  127. package/templates/sales/sales-template.SemanticModel/definition/database.tmdl +3 -0
  128. package/templates/sales/sales-template.SemanticModel/definition/expressions.tmdl +233 -0
  129. package/templates/sales/sales-template.SemanticModel/definition/functions.tmdl +247 -0
  130. package/templates/sales/sales-template.SemanticModel/definition/model.tmdl +46 -0
  131. package/templates/sales/sales-template.SemanticModel/definition/relationships.tmdl +16 -0
  132. package/templates/sales/sales-template.SemanticModel/definition/tables/Aux Comparaciones.tmdl +194 -0
  133. package/templates/sales/sales-template.SemanticModel/definition/tables/Aux Dimensiones ventas.tmdl +71 -0
  134. package/templates/sales/sales-template.SemanticModel/definition/tables/Aux Ejes temporales.tmdl +67 -0
  135. package/templates/sales/sales-template.SemanticModel/definition/tables/Aux Per/303/255odos.tmdl" +318 -0
  136. package/templates/sales/sales-template.SemanticModel/definition/tables/Aux Vista de calendario.tmdl +36 -0
  137. package/templates/sales/sales-template.SemanticModel/definition/tables/Aux Vista del valor.tmdl +87 -0
  138. package/templates/sales/sales-template.SemanticModel/definition/tables/Aux Vista temporal.tmdl +62 -0
  139. package/templates/sales/sales-template.SemanticModel/definition/tables/Calendario.tmdl +198 -0
  140. package/templates/sales/sales-template.SemanticModel/definition/tables/Canales.tmdl +59 -0
  141. package/templates/sales/sales-template.SemanticModel/definition/tables/Clientes.tmdl +120 -0
  142. package/templates/sales/sales-template.SemanticModel/definition/tables/Modelo Configuraci/303/263n.tmdl" +48 -0
  143. package/templates/sales/sales-template.SemanticModel/definition/tables/Monedas.tmdl +43 -0
  144. package/templates/sales/sales-template.SemanticModel/definition/tables/M/303/251tricas.tmdl +553 -0
  145. package/templates/sales/sales-template.SemanticModel/definition/tables/Productos.tmdl +73 -0
  146. package/templates/sales/sales-template.SemanticModel/definition/tables/Tipo de cambio.tmdl +66 -0
  147. package/templates/sales/sales-template.SemanticModel/definition/tables/Ventas.tmdl +133 -0
  148. package/templates/sales/sales-template.SemanticModel/definition.pbism +5 -0
  149. package/templates/sales/sales-template.SemanticModel/diagramLayout.json +239 -0
  150. package/templates/sales/sales-template.pbip +14 -0
  151. package/theme/BISuperpowers.json +3888 -0
  152. package/commands/bi-report.md +0 -403
  153. package/skills/bi-report/SKILL.md +0 -405
  154. package/skills/bi-report/references/cli-commands.md +0 -184
  155. package/skills/bi-report/references/cli-setup.md +0 -101
  156. package/skills/bi-report/references/close-write-open-pattern.md +0 -80
  157. package/skills/bi-report/references/layouts/finance.md +0 -65
  158. package/skills/bi-report/references/layouts/generic.md +0 -46
  159. package/skills/bi-report/references/layouts/hr.md +0 -48
  160. package/skills/bi-report/references/layouts/marketing.md +0 -45
  161. package/skills/bi-report/references/layouts/operations.md +0 -44
  162. package/skills/bi-report/references/layouts/sales.md +0 -50
  163. package/skills/bi-report/references/native-visuals.md +0 -341
  164. package/skills/bi-report/references/pbi-desktop-installation.md +0 -87
  165. package/skills/bi-report/references/pbir-preview-activation.md +0 -40
  166. package/skills/bi-report/references/slicer.md +0 -89
  167. package/skills/bi-report/references/textbox.md +0 -101
  168. package/skills/bi-report/references/themes/BISuperpowers.json +0 -915
  169. package/skills/bi-report/references/troubleshooting.md +0 -135
  170. package/skills/bi-report/references/visual-types.md +0 -78
  171. package/skills/bi-report/scripts/apply-theme.js +0 -243
  172. package/skills/bi-report/scripts/create-visual.js +0 -942
  173. package/skills/bi-report/scripts/ensure-pbi-cli.sh +0 -41
  174. package/skills/bi-report/scripts/validate-pbir.js +0 -351
  175. package/src/content/skills/bi-report/SKILL.md +0 -376
  176. package/src/content/skills/bi-report/references/cli-commands.md +0 -184
  177. package/src/content/skills/bi-report/references/cli-setup.md +0 -101
  178. package/src/content/skills/bi-report/references/close-write-open-pattern.md +0 -80
  179. package/src/content/skills/bi-report/references/layouts/finance.md +0 -65
  180. package/src/content/skills/bi-report/references/layouts/generic.md +0 -46
  181. package/src/content/skills/bi-report/references/layouts/hr.md +0 -48
  182. package/src/content/skills/bi-report/references/layouts/marketing.md +0 -45
  183. package/src/content/skills/bi-report/references/layouts/operations.md +0 -44
  184. package/src/content/skills/bi-report/references/layouts/sales.md +0 -50
  185. package/src/content/skills/bi-report/references/native-visuals.md +0 -341
  186. package/src/content/skills/bi-report/references/pbi-desktop-installation.md +0 -87
  187. package/src/content/skills/bi-report/references/pbir-preview-activation.md +0 -40
  188. package/src/content/skills/bi-report/references/slicer.md +0 -89
  189. package/src/content/skills/bi-report/references/textbox.md +0 -101
  190. package/src/content/skills/bi-report/references/themes/BISuperpowers.json +0 -915
  191. package/src/content/skills/bi-report/references/troubleshooting.md +0 -135
  192. package/src/content/skills/bi-report/references/visual-types.md +0 -78
  193. package/src/content/skills/bi-report/scripts/apply-theme.js +0 -243
  194. package/src/content/skills/bi-report/scripts/create-visual.js +0 -942
  195. package/src/content/skills/bi-report/scripts/ensure-pbi-cli.sh +0 -41
  196. package/src/content/skills/bi-report/scripts/validate-pbir.js +0 -351
@@ -0,0 +1,553 @@
1
+ /// Tabla desconectada del template para enrutar medidas seleccionables de ventas.
2
+ table Métricas
3
+ lineageTag: f1c7296b-4b19-4310-8f46-a654a261f537
4
+
5
+ /// Moneda destino seleccionada para mostrar importes convertidos. Si no hay selección, usa la moneda base definida por el parámetro MonedaBase.
6
+ measure 'Moneda seleccionada' =
7
+ // Lee la moneda elegida en el slicer de Monedas.
8
+ // Si el usuario no elige una moneda, usa la misma moneda base definida para el modelo.
9
+ SELECTEDVALUE ( Monedas[Moneda], [Moneda base] )
10
+ displayFolder: Auxiliar
11
+ lineageTag: 5bf2e0fa-5bf2-43bc-be26-590f8e1b0aff
12
+
13
+ /// Ventas convertidas a la moneda seleccionada usando la UDF ConvertCurrency.
14
+ measure Ventas =
15
+ // Lee la moneda destino seleccionada por el usuario en el slicer Monedas.
16
+ VAR __MonedaDestino = [Moneda seleccionada]
17
+ // Recorre cada fila de ventas para convertirla desde su moneda origen a la moneda destino.
18
+ RETURN
19
+ SUMX (
20
+ Ventas,
21
+ // ConvertCurrency usa la moneda de la fila, la moneda seleccionada y la fecha de venta.
22
+ ConvertCurrency ( Ventas[Venta Bruta], Ventas[Moneda], __MonedaDestino, Ventas[Fecha] )
23
+ )
24
+ formatString: #,0
25
+ displayFolder: Ventas
26
+ lineageTag: 3ec2726a-08d9-438c-98fe-5cf700866b37
27
+
28
+ /// Costo convertido a la moneda seleccionada usando la UDF ConvertCurrency.
29
+ measure Costo =
30
+ // Lee la moneda destino seleccionada por el usuario en el slicer Monedas.
31
+ VAR __MonedaDestino = [Moneda seleccionada]
32
+ // Recorre cada fila de ventas para convertir el costo desde su moneda origen a la moneda destino.
33
+ RETURN
34
+ SUMX (
35
+ Ventas,
36
+ // ConvertCurrency usa la moneda de la fila, la moneda seleccionada y la fecha de venta.
37
+ ConvertCurrency ( Ventas[Costo Total], Ventas[Moneda], __MonedaDestino, Ventas[Fecha] )
38
+ )
39
+ formatString: #,0
40
+ displayFolder: Ventas
41
+ lineageTag: bdf3cf39-b975-490d-a90a-4a07f07f8921
42
+
43
+ /// Ventas menos costo en la moneda seleccionada.
44
+ measure 'Margen bruto' =
45
+ // Calcula cuánto queda después de restar el costo a las ventas.
46
+ // Ventas y Costo ya están convertidos a la moneda seleccionada.
47
+ [Ventas] - [Costo]
48
+ formatString: #,0
49
+ displayFolder: Ventas
50
+ lineageTag: fb554d55-eae7-4308-8744-fa8d60fef44d
51
+
52
+ /// Margen bruto dividido por ventas.
53
+ measure 'Margen %' =
54
+ // Divide el margen bruto por las ventas para obtener rentabilidad porcentual.
55
+ // DIVIDE evita errores cuando las ventas son cero o están en blanco.
56
+ DIVIDE ( [Margen bruto], [Ventas] )
57
+ formatString: 0.0%
58
+ displayFolder: Ratios
59
+ lineageTag: 286165a6-4e9e-4264-9418-e794ef369916
60
+
61
+ /// Cantidad total de unidades vendidas.
62
+ measure 'Unidades vendidas' =
63
+ // Suma la cantidad de unidades de todas las ventas visibles en el contexto actual.
64
+ SUM ( Ventas[Cantidad] )
65
+ formatString: #,0
66
+ displayFolder: Ventas
67
+ lineageTag: e7f830b2-df93-4991-83ff-03ce6358ec1e
68
+
69
+ /// Cantidad de líneas/pedidos sintéticos visibles.
70
+ measure Pedidos =
71
+ // Cuenta ventas distintas usando VentaId como identificador de pedido/línea.
72
+ DISTINCTCOUNT ( Ventas[VentaId] )
73
+ formatString: #,0
74
+ displayFolder: Ventas
75
+ lineageTag: a804b7f2-306f-46db-a712-d1f1459c9bf6
76
+
77
+ /// Ventas divididas por pedidos en la moneda seleccionada.
78
+ measure 'Ticket promedio' =
79
+ // Divide las ventas convertidas por la cantidad de pedidos.
80
+ // DIVIDE evita errores si no hay pedidos en el contexto actual.
81
+ DIVIDE ( [Ventas], [Pedidos] )
82
+ formatString: #,0
83
+ displayFolder: Ratios
84
+ lineageTag: 61c8a07a-62ca-49e1-a2d6-3db9587ca795
85
+
86
+ /// Valor de la métrica seleccionada para el período actual. Requiere una única métrica en contexto.
87
+ measure 'Periodo Actual' =
88
+ // Lee qué métrica eligió el usuario. Sin selección única, el cálculo queda en blanco.
89
+ VAR __MetricName = SELECTEDVALUE ( 'Métricas'[Métrica] )
90
+ // Pide a la UDF CalendarContext la definición del período actual y previo.
91
+ VAR __CalendarContext = CalendarContext ()
92
+ // Extrae la primera fecha del período actual.
93
+ VAR __Start = MAXX ( __CalendarContext, [Current Start] )
94
+ // Extrae la última fecha del período actual.
95
+ VAR __End = MAXX ( __CalendarContext, [Current End] )
96
+ // Detecta si el visual tiene un eje temporal (UDF central, un solo punto de cambio).
97
+ VAR __HasCalendarAxis = EjeCalendarioEnContexto ()
98
+ RETURN
99
+ IF (
100
+ NOT ISBLANK ( __MetricName )
101
+ && NOT ISBLANK ( __Start )
102
+ && NOT ISBLANK ( __End ),
103
+ IF (
104
+ __HasCalendarAxis,
105
+ // En gráficos con eje temporal respetamos el eje y solo limitamos el rango.
106
+ CALCULATE (
107
+ [Selector métrica],
108
+ TREATAS ( { __MetricName }, 'Métricas'[Métrica] ),
109
+ KEEPFILTERS ( DATESBETWEEN ( 'Calendario'[Fecha], __Start, __End ) )
110
+ ),
111
+ // En tarjetas quitamos el filtro de fecha previo y aplicamos el rango completo.
112
+ CALCULATE (
113
+ [Selector métrica],
114
+ TREATAS ( { __MetricName }, 'Métricas'[Métrica] ),
115
+ REMOVEFILTERS ( 'Calendario' ),
116
+ DATESBETWEEN ( 'Calendario'[Fecha], __Start, __End )
117
+ )
118
+ )
119
+ )
120
+ displayFolder: Auxiliar
121
+ lineageTag: 7d83954c-90a1-4b67-b326-826100ef6038
122
+
123
+ formatStringDefinition = FormatoMetricaSeleccionada ()
124
+
125
+ /// Valor de la métrica seleccionada para el período anterior comparable. Requiere una única métrica en contexto.
126
+ measure 'Periodo Previo' =
127
+ // Lee qué métrica eligió el usuario. Sin selección única, el cálculo queda en blanco.
128
+ VAR __MetricName = SELECTEDVALUE ( 'Métricas'[Métrica] )
129
+ // Pide a la UDF CalendarContext la definición del período actual y previo.
130
+ VAR __CalendarContext = CalendarContext ()
131
+ // Extrae la primera fecha del período actual.
132
+ VAR __CurrentStart = MAXX ( __CalendarContext, [Current Start] )
133
+ // Extrae la última fecha del período actual.
134
+ VAR __CurrentEnd = MAXX ( __CalendarContext, [Current End] )
135
+ // Extrae la primera fecha del período previo comparable.
136
+ VAR __PreviousStart = MAXX ( __CalendarContext, [Previous Start] )
137
+ // Extrae la última fecha del período previo comparable.
138
+ VAR __PreviousEnd = MAXX ( __CalendarContext, [Previous End] )
139
+ // Calcula cuántos días separan el inicio actual del inicio previo.
140
+ VAR __DateOffset = __CurrentStart - __PreviousStart
141
+ // Detecta si el visual tiene un eje temporal (UDF central, un solo punto de cambio).
142
+ VAR __HasCalendarAxis = EjeCalendarioEnContexto ()
143
+ RETURN
144
+ IF (
145
+ NOT ISBLANK ( __MetricName )
146
+ && NOT ISBLANK ( __PreviousStart )
147
+ && NOT ISBLANK ( __PreviousEnd ),
148
+ IF (
149
+ __HasCalendarAxis,
150
+ // Captura las fechas visibles del período actual para desplazar punto a punto.
151
+ VAR __VisibleCurrentDates =
152
+ CALCULATETABLE (
153
+ VALUES ( 'Calendario'[Fecha] ),
154
+ KEEPFILTERS ( DATESBETWEEN ( 'Calendario'[Fecha], __CurrentStart, __CurrentEnd ) )
155
+ )
156
+ // Desplaza esas fechas hacia el período previo manteniendo el mismo patrón temporal.
157
+ VAR __ShiftedPreviousDates =
158
+ SELECTCOLUMNS (
159
+ FILTER (
160
+ ADDCOLUMNS ( __VisibleCurrentDates, "__PreviousDate", 'Calendario'[Fecha] - __DateOffset ),
161
+ [__PreviousDate] >= __PreviousStart
162
+ && [__PreviousDate] <= __PreviousEnd
163
+ ),
164
+ "Fecha", [__PreviousDate]
165
+ )
166
+ RETURN
167
+ IF (
168
+ NOT ISEMPTY ( __ShiftedPreviousDates ),
169
+ CALCULATE (
170
+ [Selector métrica],
171
+ TREATAS ( { __MetricName }, 'Métricas'[Métrica] ),
172
+ REMOVEFILTERS ( 'Calendario' ),
173
+ TREATAS ( __ShiftedPreviousDates, 'Calendario'[Fecha] )
174
+ )
175
+ ),
176
+ // En tarjetas usamos directamente todo el rango previo comparable.
177
+ CALCULATE (
178
+ [Selector métrica],
179
+ TREATAS ( { __MetricName }, 'Métricas'[Métrica] ),
180
+ REMOVEFILTERS ( 'Calendario' ),
181
+ DATESBETWEEN ( 'Calendario'[Fecha], __PreviousStart, __PreviousEnd )
182
+ )
183
+ )
184
+ )
185
+ displayFolder: Auxiliar
186
+ lineageTag: 11e4fee6-6079-4522-91c4-f4f653ccc2b2
187
+
188
+ formatStringDefinition = FormatoMetricaSeleccionada ()
189
+
190
+ /// Diferencia entre el período actual y el período anterior para la métrica seleccionada.
191
+ measure Variación =
192
+ // Guarda el valor del período actual.
193
+ VAR __Actual = [Periodo Actual]
194
+ // Guarda el valor del período anterior comparable.
195
+ VAR __Anterior = [Periodo Previo]
196
+ // Resta anterior a actual solo cuando ambos valores existen.
197
+ RETURN
198
+ IF ( NOT ISBLANK ( __Actual ) && NOT ISBLANK ( __Anterior ), __Actual - __Anterior )
199
+ displayFolder: Auxiliar
200
+ lineageTag: 5c881ac9-8f88-4fcb-914b-cdf064840418
201
+
202
+ formatStringDefinition = FormatoMetricaSeleccionada ()
203
+
204
+ /// Variación porcentual del período actual contra el período anterior.
205
+ measure 'Variación %' =
206
+ // Divide la variación absoluta por el valor anterior para obtener variación porcentual.
207
+ // DIVIDE evita errores si el valor anterior es cero o está en blanco.
208
+ DIVIDE ( [Variación], [Periodo Previo] )
209
+ formatString: 0.0%;-0.0%;0.0%
210
+ displayFolder: Ratios
211
+ lineageTag: 66146073-d9e7-41ee-8a34-563faeab1afb
212
+
213
+ /// Router interno que devuelve la medida real cuando hay exactamente una métrica seleccionada.
214
+ measure 'Selector métrica' =
215
+ // Lee el nombre de la métrica elegida. En producción no usamos default:
216
+ // si no hay exactamente una métrica en contexto, devolvemos BLANK().
217
+ VAR __MetricName = SELECTEDVALUE ( 'Métricas'[Métrica] )
218
+ RETURN
219
+ SWITCH (
220
+ TRUE (),
221
+ ISBLANK ( __MetricName ), BLANK (),
222
+ __MetricName = "Ventas", [Ventas],
223
+ __MetricName = "Margen bruto", [Margen bruto],
224
+ __MetricName = "Margen %", [Margen %],
225
+ __MetricName = "Unidades vendidas", [Unidades vendidas],
226
+ __MetricName = "Pedidos", [Pedidos],
227
+ __MetricName = "Ticket promedio", [Ticket promedio],
228
+ __MetricName = "Ventas nuevos clientes", [Ventas nuevos clientes],
229
+ __MetricName = "Ventas nuevos clientes %", [Ventas nuevos clientes %],
230
+ BLANK ()
231
+ )
232
+ formatString: #,0
233
+ isHidden
234
+ displayFolder: Auxiliar
235
+ lineageTag: f8cb8072-fffe-4f9d-ab14-15b87910158f
236
+
237
+ /// Primera fecha del período actual seleccionado.
238
+ measure 'Fecha inicial actual' =
239
+ // Pide a CalendarContext la fila con los rangos de comparación.
240
+ // Devuelve la primera fecha del rango actual.
241
+ MAXX ( CalendarContext (), [Current Start] )
242
+ formatString: dd/mm/yyyy
243
+ isHidden
244
+ displayFolder: Auxiliar
245
+ lineageTag: 9512b74d-b5f8-4c16-a523-9d859f85bf41
246
+
247
+ /// Última fecha del período actual seleccionado.
248
+ measure 'Fecha final actual' =
249
+ // Pide a CalendarContext la fila con los rangos de comparación.
250
+ // Devuelve la última fecha del rango actual.
251
+ MAXX ( CalendarContext (), [Current End] )
252
+ formatString: dd/mm/yyyy
253
+ isHidden
254
+ displayFolder: Auxiliar
255
+ lineageTag: 9491d15a-a1a7-4ded-8161-21474fdaffb6
256
+
257
+ /// Primera fecha del período previo seleccionado.
258
+ measure 'Fecha inicial anterior' =
259
+ // Pide a CalendarContext la fila con los rangos de comparación.
260
+ // Devuelve la primera fecha del rango previo.
261
+ MAXX ( CalendarContext (), [Previous Start] )
262
+ formatString: dd/mm/yyyy
263
+ isHidden
264
+ displayFolder: Auxiliar
265
+ lineageTag: ef4de0c9-0fd3-4de8-a970-89642c59064e
266
+
267
+ /// Última fecha del período previo seleccionado.
268
+ measure 'Fecha final anterior' =
269
+ // Pide a CalendarContext la fila con los rangos de comparación.
270
+ // Devuelve la última fecha del rango previo.
271
+ MAXX ( CalendarContext (), [Previous End] )
272
+ formatString: dd/mm/yyyy
273
+ isHidden
274
+ displayFolder: Auxiliar
275
+ lineageTag: be892c13-b21d-442e-b210-1a53e47debc2
276
+
277
+ /// Título de comparación que muestra el rango actual y el rango previo en una sola línea.
278
+ measure 'Título comparación' =
279
+ // Devuelve en una sola medida el rango actual y su rango comparable.
280
+ VAR __CurrentStart = [Fecha inicial actual]
281
+ VAR __CurrentEnd = [Fecha final actual]
282
+ VAR __PreviousStart = [Fecha inicial anterior]
283
+ VAR __PreviousEnd = [Fecha final anterior]
284
+ VAR __CurrentStartText = SUBSTITUTE ( LOWER ( FORMAT ( __CurrentStart, "ddd d/m/yy", "es-AR" ) ), ".", "" )
285
+ VAR __CurrentEndText = SUBSTITUTE ( LOWER ( FORMAT ( __CurrentEnd, "ddd d/m/yy", "es-AR" ) ), ".", "" )
286
+ VAR __PreviousStartText = SUBSTITUTE ( LOWER ( FORMAT ( __PreviousStart, "ddd d/m/yy", "es-AR" ) ), ".", "" )
287
+ VAR __PreviousEndText = SUBSTITUTE ( LOWER ( FORMAT ( __PreviousEnd, "ddd d/m/yy", "es-AR" ) ), ".", "" )
288
+ RETURN
289
+ IF (
290
+ NOT ISBLANK ( __CurrentStart )
291
+ && NOT ISBLANK ( __CurrentEnd )
292
+ && NOT ISBLANK ( __PreviousStart )
293
+ && NOT ISBLANK ( __PreviousEnd ),
294
+ "Del " & __CurrentStartText & " al " & __CurrentEndText
295
+ & " (vs. " & __PreviousStartText & " al " & __PreviousEndText & ")"
296
+ )
297
+ isHidden
298
+ displayFolder: Auxiliar
299
+ lineageTag: 62eb5630-a405-4a36-adf1-48f07b3345fd
300
+
301
+ /// Etiqueta textual de variación porcentual con icono Unicode de dirección e incluye el valor del periodo anterior en formato compacto como `Prev.`.
302
+ measure 'Etiqueta variación %' =
303
+ // Muestra la direccion de la variacion porcentual con un icono Unicode.
304
+ // Tambien muestra el valor del periodo anterior en formato compacto de etiqueta.
305
+ VAR __ChangePct = [Variación %]
306
+ VAR __Previous = [Periodo Previo]
307
+ VAR __Icon =
308
+ SWITCH (
309
+ TRUE (),
310
+ ISBLANK ( __ChangePct ), BLANK (),
311
+ __ChangePct > 0, UNICHAR ( 9650 ),
312
+ __ChangePct < 0, UNICHAR ( 9660 ),
313
+ BLANK ()
314
+ )
315
+ VAR __ChangeText = FORMAT ( ABS ( __ChangePct ), "0.0%" )
316
+ VAR __PreviousText = FormatoValorEtiqueta ( __Previous )
317
+ VAR __Label =
318
+ IF (
319
+ ISBLANK ( __Icon ),
320
+ __ChangeText,
321
+ __Icon & " " & __ChangeText
322
+ )
323
+ RETURN
324
+ IF (
325
+ ISBLANK ( __ChangePct ),
326
+ "-",
327
+ __Label & " (Prev. " & __PreviousText & ")"
328
+ )
329
+ displayFolder: Auxiliar
330
+ lineageTag: 3065df96-b375-4d44-9b89-730a0f864b92
331
+
332
+ /// Ventas de clientes cuya primera venta histórica cae dentro del contexto de fechas visible. Devuelve 0 cuando no hay clientes nuevos para que los visuals no queden en blanco.
333
+ measure 'Ventas nuevos clientes' =
334
+ // Identifica los clientes cuya primera venta historica cae dentro del contexto de fechas visible.
335
+ // REMOVEFILTERS ( Calendario ) evita que la primera venta quede recortada por el periodo actual.
336
+ VAR __FechasVisibles = VALUES ( 'Calendario'[Fecha] )
337
+ VAR __ClientesNuevos =
338
+ FILTER (
339
+ VALUES ( Clientes[ClienteId] ),
340
+ VAR __PrimeraVentaCliente =
341
+ CALCULATE (
342
+ MIN ( Ventas[Fecha] ),
343
+ REMOVEFILTERS ( 'Calendario' )
344
+ )
345
+ RETURN
346
+ CONTAINSROW ( __FechasVisibles, __PrimeraVentaCliente )
347
+ )
348
+ VAR __VentasNuevos = CALCULATE ( [Ventas], __ClientesNuevos )
349
+ RETURN
350
+ COALESCE ( __VentasNuevos, 0 )
351
+ formatString: #,0
352
+ displayFolder: Ventas
353
+ lineageTag: eca6420b-769a-4a38-8cf3-67d9056f74f4
354
+
355
+ /// Porcentaje de ventas visibles explicado por clientes nuevos. Devuelve 0 cuando no hay ventas o no hay clientes nuevos.
356
+ measure 'Ventas nuevos clientes %' =
357
+ // Participacion de las ventas generadas por clientes nuevos sobre las ventas totales visibles.
358
+ // El tercer argumento devuelve 0 cuando no hay ventas en el contexto.
359
+ DIVIDE ( [Ventas nuevos clientes], [Ventas], 0 )
360
+ formatString: 0.0%
361
+ displayFolder: Ratios
362
+ lineageTag: 44abd84b-93fd-4691-9595-5dd70d5c1ec0
363
+
364
+ /// Color para formato condicional de bullet charts: Tremor Green #22C55E cuando la variación es favorable, Tremor Red #EF4444 cuando es desfavorable y Tremor Gray #6B7280 cuando es neutra o no evaluable.
365
+ measure 'Color bullet variación' =
366
+ // Color para aplicar con fx sobre bullet charts.
367
+ // Interpreta el signo de [Variación %] contra la Tendencia configurada en Métricas.
368
+ VAR __ChangePct = [Variación %]
369
+ VAR __Trend = SELECTEDVALUE ( 'Métricas'[Tendencia] )
370
+ VAR __Direction =
371
+ SWITCH (
372
+ TRUE (),
373
+ ISBLANK ( __ChangePct ), 0,
374
+ __ChangePct > 0, 1,
375
+ __ChangePct < 0, -1,
376
+ 0
377
+ )
378
+ VAR __Score =
379
+ SWITCH (
380
+ TRUE (),
381
+ __Direction = 0 || ISBLANK ( __Trend ), 0,
382
+ __Trend IN { "Baja es positivo", "Negativo", "Negativa" } && __Direction < 0, 1,
383
+ __Trend IN { "Baja es positivo", "Negativo", "Negativa" } && __Direction > 0, -1,
384
+ __Trend IN { "Sube es positivo", "Positivo", "Positiva" } && __Direction > 0, 1,
385
+ __Trend IN { "Sube es positivo", "Positivo", "Positiva" } && __Direction < 0, -1,
386
+ 0
387
+ )
388
+ RETURN
389
+ SWITCH (
390
+ TRUE (),
391
+ __Score > 0, "#22C55E",
392
+ __Score < 0, "#EF4444",
393
+ "#6B7280"
394
+ )
395
+ displayFolder: Auxiliar
396
+ lineageTag: 96ee8802-7a64-4454-991f-08c8a08daef1
397
+
398
+ /// Color para formato condicional de etiquetas de variación: Tremor Green #22C55E cuando la variación es favorable, Tremor Red #EF4444 cuando es desfavorable y Tremor Gray #6B7280 cuando es neutra o no evaluable.
399
+ measure 'Color etiqueta variación' =
400
+ // Color para aplicar con fx sobre etiquetas de variacion.
401
+ // Interpreta el signo de [Variación %] contra la Tendencia configurada en Métricas.
402
+ VAR __ChangePct = [Variación %]
403
+ VAR __Trend = SELECTEDVALUE ( 'Métricas'[Tendencia] )
404
+ VAR __Direction =
405
+ SWITCH (
406
+ TRUE (),
407
+ ISBLANK ( __ChangePct ), 0,
408
+ __ChangePct > 0, 1,
409
+ __ChangePct < 0, -1,
410
+ 0
411
+ )
412
+ VAR __Score =
413
+ SWITCH (
414
+ TRUE (),
415
+ __Direction = 0 || ISBLANK ( __Trend ), 0,
416
+ __Trend IN { "Baja es positivo", "Negativo", "Negativa" } && __Direction < 0, 1,
417
+ __Trend IN { "Baja es positivo", "Negativo", "Negativa" } && __Direction > 0, -1,
418
+ __Trend IN { "Sube es positivo", "Positivo", "Positiva" } && __Direction > 0, 1,
419
+ __Trend IN { "Sube es positivo", "Positivo", "Positiva" } && __Direction < 0, -1,
420
+ 0
421
+ )
422
+ RETURN
423
+ SWITCH (
424
+ TRUE (),
425
+ __Score > 0, "#22C55E",
426
+ __Score < 0, "#EF4444",
427
+ "#6B7280"
428
+ )
429
+ displayFolder: Auxiliar
430
+ lineageTag: 0d772674-7987-48b4-812a-1eea6d3b63da
431
+
432
+ /// Etiqueta para bullet charts: icono Unicode de subida/bajada y variación porcentual. El color se aplica con la medida de color del bullet.
433
+ measure 'Etiqueta bullet chart' =
434
+ // Etiqueta compacta para bullet charts: icono de variacion y porcentaje.
435
+ VAR __ChangePct = [Variación %]
436
+ VAR __Icon =
437
+ SWITCH (
438
+ TRUE (),
439
+ ISBLANK ( __ChangePct ), BLANK (),
440
+ __ChangePct > 0, UNICHAR ( 9650 ),
441
+ __ChangePct < 0, UNICHAR ( 9660 ),
442
+ BLANK ()
443
+ )
444
+ VAR __ChangeText = FORMAT ( ABS ( __ChangePct ), "0.0%" )
445
+ RETURN
446
+ IF (
447
+ ISBLANK ( __ChangePct ),
448
+ BLANK (),
449
+ IF ( ISBLANK ( __Icon ), __ChangeText, __Icon & " " & __ChangeText )
450
+ )
451
+ displayFolder: Auxiliar
452
+ lineageTag: 4ca5174b-6818-4632-a87c-825364b498a3
453
+
454
+ /// Título textual para visuals: devuelve el nombre de la métrica seleccionada desde Métricas[Métrica].
455
+ measure 'Título métrica' =
456
+ // Titulo de visual basado en la metrica seleccionada.
457
+ SELECTEDVALUE ( 'Métricas'[Métrica] )
458
+ displayFolder: Auxiliar
459
+ lineageTag: ab43c6f2-0fee-4d37-96fe-ca978cf66ea2
460
+
461
+ /// Subtítulo textual para visuals: devuelve la definición de la métrica seleccionada desde Métricas[Descripción].
462
+ measure 'Subtítulo métrica' =
463
+ // Subtitulo de visual basado en la definicion de la metrica seleccionada.
464
+ SELECTEDVALUE ( 'Métricas'[Descripción] )
465
+ displayFolder: Auxiliar
466
+ lineageTag: eab62d0c-d40b-4b8a-b79c-cec58830ea57
467
+
468
+ /// Moneda base definida por el parámetro Power Query MonedaBase. También es el default de visualización cuando no hay una selección única en Monedas.
469
+ measure 'Moneda base' =
470
+ VAR __ConfiguredCurrency =
471
+ MAXX (
472
+ FILTER (
473
+ ALL ( 'Modelo Configuración' ),
474
+ 'Modelo Configuración'[Configuración] = "Moneda Base"
475
+ ),
476
+ 'Modelo Configuración'[ValorTexto]
477
+ )
478
+ RETURN
479
+ COALESCE ( __ConfiguredCurrency, "USD" )
480
+ isHidden
481
+ displayFolder: Auxiliar
482
+ lineageTag: b65ba356-1fcd-4f55-b408-68e69b6bc77b
483
+
484
+ column Métrica
485
+ lineageTag: 748cb7e2-0803-4f55-a9e0-eb44ea479875
486
+ summarizeBy: none
487
+ isNameInferred
488
+ sourceColumn: [Métrica]
489
+ sortByColumn: Índice
490
+
491
+ column Índice
492
+ isHidden
493
+ formatString: 0
494
+ lineageTag: cda91f1e-e9df-4a43-a7e0-93b753a3aa2f
495
+ summarizeBy: none
496
+ isNameInferred
497
+ sourceColumn: [Índice]
498
+
499
+ column Formato
500
+ isHidden
501
+ lineageTag: 42b9b96a-0e2a-4101-8948-c109fb8060e2
502
+ summarizeBy: none
503
+ isNameInferred
504
+ sourceColumn: [Formato]
505
+
506
+ column Tendencia
507
+ isHidden
508
+ lineageTag: 2c23d1b2-5d16-4816-9950-7b808c986195
509
+ summarizeBy: none
510
+ isNameInferred
511
+ sourceColumn: [Tendencia]
512
+
513
+ column Acumulado
514
+ isHidden
515
+ lineageTag: 02dbb720-4ccb-4bf5-8dcb-d968fb47cef0
516
+ summarizeBy: none
517
+ isNameInferred
518
+ sourceColumn: [Acumulado]
519
+
520
+ column Descripción
521
+ lineageTag: 44a61e89-9050-4664-b8f0-cb86c9afb703
522
+ summarizeBy: none
523
+ isNameInferred
524
+ sourceColumn: [Descripción]
525
+
526
+ column Monetaria
527
+ lineageTag: 01fbb1bb-8876-49bb-aaa1-6a956dac8ff0
528
+ isNameInferred
529
+ sourceColumn: [Monetaria]
530
+
531
+ partition Métricas = calculated
532
+ mode: import
533
+ source =
534
+ DATATABLE (
535
+ "Métrica", STRING,
536
+ "Índice", INTEGER,
537
+ "Formato", STRING,
538
+ "Tendencia", STRING,
539
+ "Monetaria", BOOLEAN,
540
+ "Acumulado", BOOLEAN,
541
+ "Descripción", STRING,
542
+ {
543
+ { "Ventas", 1, "#,0", "Sube es positivo", TRUE, TRUE, "Ventas convertidas a la moneda seleccionada." },
544
+ { "Margen bruto", 2, "#,0", "Sube es positivo", TRUE, TRUE, "Ventas menos costo en la moneda seleccionada." },
545
+ { "Margen %", 3, "0.0%", "Sube es positivo", FALSE, FALSE, "Margen bruto dividido por ventas." },
546
+ { "Unidades vendidas", 4, "#,0", "Sube es positivo", FALSE, TRUE, "Cantidad de unidades vendidas." },
547
+ { "Pedidos", 5, "#,0", "Sube es positivo", FALSE, TRUE, "Cantidad de pedidos o líneas de venta." },
548
+ { "Ticket promedio", 6, "#,0", "Sube es positivo", TRUE, FALSE, "Ventas divididas por pedidos en la moneda seleccionada." },
549
+ { "Ventas nuevos clientes", 7, "#,0", "Sube es positivo", TRUE, TRUE, "Ventas de clientes cuya primera venta histórica cae dentro del contexto de fechas visible." },
550
+ { "Ventas nuevos clientes %", 8, "0.0%", "Sube es positivo", FALSE, FALSE, "Porcentaje de ventas visibles explicado por clientes nuevos." }
551
+ }
552
+ )
553
+
@@ -0,0 +1,73 @@
1
+ /// Dimension de productos sintética para ventas, cargada desde Power Query para que el sample dataset no dependa de DAX calculated tables.
2
+ table Productos
3
+ lineageTag: 129abf05-1906-4a84-b7ce-0f26b4b60083
4
+
5
+ column ProductoId
6
+ dataType: string
7
+ isHidden
8
+ lineageTag: ca5f9070-95c1-4d7f-bb7f-dcd5caf63e86
9
+ summarizeBy: none
10
+ sourceColumn: ProductoId
11
+
12
+ annotation SummarizationSetBy = Automatic
13
+
14
+ column Producto
15
+ dataType: string
16
+ lineageTag: 7251821c-c2b3-4e71-a4f7-a492793acf44
17
+ summarizeBy: none
18
+ sourceColumn: Producto
19
+
20
+ column Categoría
21
+ dataType: string
22
+ lineageTag: f0b5325a-2564-4f0e-9a33-f59b72a49a41
23
+ summarizeBy: none
24
+ sourceColumn: Categoria
25
+
26
+ column Subcategoría
27
+ dataType: string
28
+ lineageTag: 79b4bb01-8955-4f4d-8021-485d2c0b0869
29
+ summarizeBy: none
30
+ sourceColumn: Subcategoria
31
+
32
+ /// Drill-down estándar de Productos: Categoría -> Subcategoría -> Producto.
33
+ hierarchy 'Jerarquía de productos'
34
+ lineageTag: 4c61c740-5ac8-4a33-ae38-cc46369099dd
35
+
36
+ level Categoría
37
+ lineageTag: 4f5c233f-66ae-46d0-bc3a-cc19daca8161
38
+ column: Categoría
39
+
40
+ level Subcategoría
41
+ lineageTag: d82a4e44-77c3-4792-a764-a4610c6794f4
42
+ column: Subcategoría
43
+
44
+ level Producto
45
+ lineageTag: f439e85f-0346-4b49-8467-2e639f07364b
46
+ column: Producto
47
+
48
+ partition Productos = m
49
+ mode: import
50
+ queryGroup: 'Sample Dataset'
51
+ source =
52
+ let
53
+ Source = #table(
54
+ type table [ProductoId = Int64.Type, Producto = text, Categoria = text, Subcategoria = text],
55
+ {
56
+ { 1, "Notebook Pro", "Hardware", "Computadoras" },
57
+ { 2, "Monitor 27", "Hardware", "Perifericos" },
58
+ { 3, "Dock USB-C", "Hardware", "Accesorios" },
59
+ { 4, "Licencia BI", "Software", "Analytics" },
60
+ { 5, "Soporte Premium", "Servicios", "Soporte" },
61
+ { 6, "Implementacion", "Servicios", "Consultoria" },
62
+ { 7, "Capacitacion", "Servicios", "Training" },
63
+ { 8, "Integracion API", "Software", "Integraciones" }
64
+ }
65
+ ),
66
+ #"Tipo cambiado" = Table.TransformColumnTypes(Source,{{"ProductoId", type text}, {"Producto", type text}, {"Categoria", type text}, {"Subcategoria", type text}})
67
+ in
68
+ #"Tipo cambiado"
69
+
70
+ annotation PBI_NavigationStepName = Navegación
71
+
72
+ annotation PBI_ResultType = Table
73
+
@@ -0,0 +1,66 @@
1
+ /// Tabla helper sintética de tipos de cambio por fecha y moneda, cargada desde Power Query para validar patrones de conversión de moneda.
2
+ table 'Tipo de cambio'
3
+ isHidden
4
+ lineageTag: 876182f9-6e8d-495e-bf52-13fc9db4ffef
5
+
6
+ column Fecha
7
+ dataType: dateTime
8
+ isHidden
9
+ formatString: Long Date
10
+ lineageTag: a3b5f7ba-ec6d-40f8-a78e-49f5b2f89ec6
11
+ summarizeBy: none
12
+ sourceColumn: Fecha
13
+
14
+ annotation UnderlyingDateTimeDataType = Date
15
+
16
+ column Moneda
17
+ dataType: string
18
+ isHidden
19
+ lineageTag: 6c8a29b7-41d3-4f41-97b8-db3f5f3b1cdc
20
+ summarizeBy: none
21
+ sourceColumn: Moneda
22
+
23
+ column TipoCambioBase
24
+ dataType: double
25
+ formatString: #,0.00
26
+ lineageTag: f7a93c19-5278-4d38-ae49-fef3b8a53173
27
+ summarizeBy: none
28
+ sourceColumn: TipoCambioBase
29
+
30
+ partition TipoCambio = m
31
+ mode: import
32
+ queryGroup: 'Sample Dataset'
33
+ source =
34
+ let
35
+ BaseCurrency = Text.From(MonedaBase),
36
+ RatesUsd = #table(
37
+ type table [Moneda = text, TipoCambioUSD = number, VariacionDiaria = number],
38
+ {
39
+ { "USD", 1.00, 0.00 },
40
+ { "ARS", 1200.00, 0.15 },
41
+ { "EUR", 0.92, 0.00005 }
42
+ }
43
+ ),
44
+ Dates = Table.SelectColumns(Calendario, {"Fecha"}),
45
+ AddRates = Table.AddColumn(Dates, "Rates", each RatesUsd),
46
+ ExpandRates = Table.ExpandTableColumn(AddRates, "Rates", {"Moneda", "TipoCambioUSD", "VariacionDiaria"}, {"Moneda", "TipoCambioUSD", "VariacionDiaria"}),
47
+ AddRateUsd = Table.AddColumn(
48
+ ExpandRates,
49
+ "RateUsd",
50
+ each if [Moneda] = "USD" then 1.0 else [TipoCambioUSD] + (Duration.Days(Date.From([Fecha]) - #date(2025, 1, 1)) * [VariacionDiaria]),
51
+ type number
52
+ ),
53
+ BaseRows = Table.SelectRows(AddRateUsd, each [Moneda] = BaseCurrency),
54
+ BaseRates = Table.RenameColumns(Table.SelectColumns(BaseRows, {"Fecha", "RateUsd"}), {{"RateUsd", "BaseRateUsd"}}),
55
+ JoinBase = Table.NestedJoin(AddRateUsd, {"Fecha"}, BaseRates, {"Fecha"}, "Base", JoinKind.LeftOuter),
56
+ ExpandBase = Table.ExpandTableColumn(JoinBase, "Base", {"BaseRateUsd"}, {"BaseRateUsd"}),
57
+ AddTipoCambioBase = Table.AddColumn(ExpandBase, "TipoCambioBase", each if [BaseRateUsd] = null or [BaseRateUsd] = 0 then [RateUsd] else [RateUsd] / [BaseRateUsd], type number),
58
+ Result = Table.SelectColumns(AddTipoCambioBase, {"Fecha", "Moneda", "TipoCambioBase"}),
59
+ #"Tipo cambiado" = Table.TransformColumnTypes(Result,{{"Moneda", type text}})
60
+ in
61
+ #"Tipo cambiado"
62
+
63
+ annotation PBI_NavigationStepName = Navegación
64
+
65
+ annotation PBI_ResultType = Table
66
+