@dssp/dkpi 1.0.0-alpha.99 → 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.
Files changed (236) hide show
  1. package/package.json +55 -55
  2. package/dist-client/bootstrap.d.ts +0 -9
  3. package/dist-client/bootstrap.js +0 -272
  4. package/dist-client/bootstrap.js.map +0 -1
  5. package/dist-client/components/kpi-2d-lookup-chart.d.ts +0 -50
  6. package/dist-client/components/kpi-2d-lookup-chart.js +0 -263
  7. package/dist-client/components/kpi-2d-lookup-chart.js.map +0 -1
  8. package/dist-client/components/kpi-boxplot-chart.d.ts +0 -31
  9. package/dist-client/components/kpi-boxplot-chart.js +0 -306
  10. package/dist-client/components/kpi-boxplot-chart.js.map +0 -1
  11. package/dist-client/components/kpi-lookup-chart.d.ts +0 -58
  12. package/dist-client/components/kpi-lookup-chart.js +0 -464
  13. package/dist-client/components/kpi-lookup-chart.js.map +0 -1
  14. package/dist-client/components/kpi-mini-trend-chart.d.ts +0 -14
  15. package/dist-client/components/kpi-mini-trend-chart.js +0 -180
  16. package/dist-client/components/kpi-mini-trend-chart.js.map +0 -1
  17. package/dist-client/components/kpi-radar-chart.d.ts +0 -17
  18. package/dist-client/components/kpi-radar-chart.js +0 -259
  19. package/dist-client/components/kpi-radar-chart.js.map +0 -1
  20. package/dist-client/components/kpi-single-boxplot-chart.d.ts +0 -36
  21. package/dist-client/components/kpi-single-boxplot-chart.js +0 -417
  22. package/dist-client/components/kpi-single-boxplot-chart.js.map +0 -1
  23. package/dist-client/components/kpi-step-lookup-chart.d.ts +0 -33
  24. package/dist-client/components/kpi-step-lookup-chart.js +0 -181
  25. package/dist-client/components/kpi-step-lookup-chart.js.map +0 -1
  26. package/dist-client/components/kpi-trend-chart.d.ts +0 -25
  27. package/dist-client/components/kpi-trend-chart.js +0 -241
  28. package/dist-client/components/kpi-trend-chart.js.map +0 -1
  29. package/dist-client/components/sv-pagenation-control.d.ts +0 -18
  30. package/dist-client/components/sv-pagenation-control.js +0 -142
  31. package/dist-client/components/sv-pagenation-control.js.map +0 -1
  32. package/dist-client/entries/auth/checkin.d.ts +0 -38
  33. package/dist-client/entries/auth/checkin.js +0 -551
  34. package/dist-client/entries/auth/checkin.js.map +0 -1
  35. package/dist-client/entries/public/home.d.ts +0 -8
  36. package/dist-client/entries/public/home.js +0 -97
  37. package/dist-client/entries/public/home.js.map +0 -1
  38. package/dist-client/google-map/common-google-map.d.ts +0 -35
  39. package/dist-client/google-map/common-google-map.js +0 -349
  40. package/dist-client/google-map/common-google-map.js.map +0 -1
  41. package/dist-client/google-map/google-map-loader.d.ts +0 -6
  42. package/dist-client/google-map/google-map-loader.js +0 -23
  43. package/dist-client/google-map/google-map-loader.js.map +0 -1
  44. package/dist-client/icons/menu-icons.d.ts +0 -11
  45. package/dist-client/icons/menu-icons.js +0 -126
  46. package/dist-client/icons/menu-icons.js.map +0 -1
  47. package/dist-client/index.d.ts +0 -0
  48. package/dist-client/index.js +0 -2
  49. package/dist-client/index.js.map +0 -1
  50. package/dist-client/menu.d.ts +0 -23
  51. package/dist-client/menu.js +0 -59
  52. package/dist-client/menu.js.map +0 -1
  53. package/dist-client/pages/component/project-update-header.d.ts +0 -1
  54. package/dist-client/pages/component/project-update-header.js +0 -127
  55. package/dist-client/pages/component/project-update-header.js.map +0 -1
  56. package/dist-client/pages/kpi-admin/dssp-kpi-list-page.d.ts +0 -22
  57. package/dist-client/pages/kpi-admin/dssp-kpi-list-page.js +0 -57
  58. package/dist-client/pages/kpi-admin/dssp-kpi-list-page.js.map +0 -1
  59. package/dist-client/pages/kpi-admin/dssp-kpi-overview.d.ts +0 -47
  60. package/dist-client/pages/kpi-admin/dssp-kpi-overview.js +0 -393
  61. package/dist-client/pages/kpi-admin/dssp-kpi-overview.js.map +0 -1
  62. package/dist-client/pages/kpi-admin/kpi-grade-2d-editor.d.ts +0 -20
  63. package/dist-client/pages/kpi-admin/kpi-grade-2d-editor.js +0 -445
  64. package/dist-client/pages/kpi-admin/kpi-grade-2d-editor.js.map +0 -1
  65. package/dist-client/pages/kpi-admin/kpi-system-guide.d.ts +0 -18
  66. package/dist-client/pages/kpi-admin/kpi-system-guide.js +0 -696
  67. package/dist-client/pages/kpi-admin/kpi-system-guide.js.map +0 -1
  68. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.d.ts +0 -18
  69. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js +0 -259
  70. package/dist-client/pages/kpi-dashboard/cards/kpi-level1-card.js.map +0 -1
  71. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.d.ts +0 -22
  72. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js +0 -346
  73. package/dist-client/pages/kpi-dashboard/cards/kpi-level2-comparison.js.map +0 -1
  74. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.d.ts +0 -26
  75. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js +0 -433
  76. package/dist-client/pages/kpi-dashboard/cards/kpi-level3-comparison.js.map +0 -1
  77. package/dist-client/pages/kpi-dashboard/components/kpi-chart-toggle.d.ts +0 -8
  78. package/dist-client/pages/kpi-dashboard/components/kpi-chart-toggle.js +0 -78
  79. package/dist-client/pages/kpi-dashboard/components/kpi-chart-toggle.js.map +0 -1
  80. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.d.ts +0 -46
  81. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js +0 -945
  82. package/dist-client/pages/kpi-dashboard/components/kpi-left-panel.js.map +0 -1
  83. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.d.ts +0 -34
  84. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js +0 -238
  85. package/dist-client/pages/kpi-dashboard/components/kpi-map-panel.js.map +0 -1
  86. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.d.ts +0 -37
  87. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js +0 -689
  88. package/dist-client/pages/kpi-dashboard/components/kpi-region-popup.js.map +0 -1
  89. package/dist-client/pages/kpi-dashboard/kpi-alert-panel.d.ts +0 -18
  90. package/dist-client/pages/kpi-dashboard/kpi-alert-panel.js +0 -131
  91. package/dist-client/pages/kpi-dashboard/kpi-alert-panel.js.map +0 -1
  92. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.d.ts +0 -57
  93. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +0 -866
  94. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +0 -1
  95. package/dist-client/pages/kpi-dashboard/kpi-dashboard.d.ts +0 -63
  96. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js +0 -1097
  97. package/dist-client/pages/kpi-dashboard/kpi-dashboard.js.map +0 -1
  98. package/dist-client/pages/kpi-dashboard/kpi-grade-visualization.d.ts +0 -12
  99. package/dist-client/pages/kpi-dashboard/kpi-grade-visualization.js +0 -82
  100. package/dist-client/pages/kpi-dashboard/kpi-grade-visualization.js.map +0 -1
  101. package/dist-client/pages/kpi-dashboard/kpi-history-viewer.d.ts +0 -11
  102. package/dist-client/pages/kpi-dashboard/kpi-history-viewer.js +0 -65
  103. package/dist-client/pages/kpi-dashboard/kpi-history-viewer.js.map +0 -1
  104. package/dist-client/pages/kpi-dashboard/kpi-list-summary.d.ts +0 -13
  105. package/dist-client/pages/kpi-dashboard/kpi-list-summary.js +0 -115
  106. package/dist-client/pages/kpi-dashboard/kpi-list-summary.js.map +0 -1
  107. package/dist-client/pages/kpi-dashboard/kpi-performance-summary.d.ts +0 -15
  108. package/dist-client/pages/kpi-dashboard/kpi-performance-summary.js +0 -147
  109. package/dist-client/pages/kpi-dashboard/kpi-performance-summary.js.map +0 -1
  110. package/dist-client/pages/kpi-dashboard/kpi-value-entry.d.ts +0 -7
  111. package/dist-client/pages/kpi-dashboard/kpi-value-entry.js +0 -86
  112. package/dist-client/pages/kpi-dashboard/kpi-value-entry.js.map +0 -1
  113. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.d.ts +0 -57
  114. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js +0 -719
  115. package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js.map +0 -1
  116. package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.d.ts +0 -23
  117. package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js +0 -76
  118. package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js.map +0 -1
  119. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +0 -68
  120. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +0 -394
  121. package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +0 -1
  122. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.d.ts +0 -12
  123. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js +0 -174
  124. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js.map +0 -1
  125. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.d.ts +0 -40
  126. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js +0 -190
  127. package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js.map +0 -1
  128. package/dist-client/pages/kpi-value/kpi-value-importer.d.ts +0 -23
  129. package/dist-client/pages/kpi-value/kpi-value-importer.js +0 -93
  130. package/dist-client/pages/kpi-value/kpi-value-importer.js.map +0 -1
  131. package/dist-client/pages/kpi-value/kpi-value-list-page.d.ts +0 -71
  132. package/dist-client/pages/kpi-value/kpi-value-list-page.js +0 -454
  133. package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +0 -1
  134. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.d.ts +0 -69
  135. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js +0 -790
  136. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js.map +0 -1
  137. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.d.ts +0 -22
  138. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js +0 -344
  139. package/dist-client/pages/project-complete-tabs/pc-tab2-rating.js.map +0 -1
  140. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.d.ts +0 -21
  141. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.js +0 -335
  142. package/dist-client/pages/project-complete-tabs/pc-tab3-upload.js.map +0 -1
  143. package/dist-client/pages/project-complete-tabs/pc-tab4-monthly.d.ts +0 -51
  144. package/dist-client/pages/project-complete-tabs/pc-tab4-monthly.js +0 -674
  145. package/dist-client/pages/project-complete-tabs/pc-tab4-monthly.js.map +0 -1
  146. package/dist-client/pages/sv-project-complete.d.ts +0 -31
  147. package/dist-client/pages/sv-project-complete.js +0 -359
  148. package/dist-client/pages/sv-project-complete.js.map +0 -1
  149. package/dist-client/pages/sv-project-completed-list.d.ts +0 -27
  150. package/dist-client/pages/sv-project-completed-list.js +0 -416
  151. package/dist-client/pages/sv-project-completed-list.js.map +0 -1
  152. package/dist-client/pages/sv-project-detail.d.ts +0 -73
  153. package/dist-client/pages/sv-project-detail.js +0 -1501
  154. package/dist-client/pages/sv-project-detail.js.map +0 -1
  155. package/dist-client/pages/sv-project-list.d.ts +0 -175
  156. package/dist-client/pages/sv-project-list.js +0 -581
  157. package/dist-client/pages/sv-project-list.js.map +0 -1
  158. package/dist-client/pages/sv-project-update.d.ts +0 -91
  159. package/dist-client/pages/sv-project-update.js +0 -1150
  160. package/dist-client/pages/sv-project-update.js.map +0 -1
  161. package/dist-client/pages/sv-user-management.d.ts +0 -6
  162. package/dist-client/pages/sv-user-management.js +0 -224
  163. package/dist-client/pages/sv-user-management.js.map +0 -1
  164. package/dist-client/route.d.ts +0 -1
  165. package/dist-client/route.js +0 -58
  166. package/dist-client/route.js.map +0 -1
  167. package/dist-client/shared/complete-api.d.ts +0 -45
  168. package/dist-client/shared/complete-api.js +0 -272
  169. package/dist-client/shared/complete-api.js.map +0 -1
  170. package/dist-client/shared/func.d.ts +0 -2
  171. package/dist-client/shared/func.js +0 -22
  172. package/dist-client/shared/func.js.map +0 -1
  173. package/dist-client/shared/geo-group-mapping.d.ts +0 -25
  174. package/dist-client/shared/geo-group-mapping.js +0 -189
  175. package/dist-client/shared/geo-group-mapping.js.map +0 -1
  176. package/dist-client/shared/integration-fetch.d.ts +0 -35
  177. package/dist-client/shared/integration-fetch.js +0 -53
  178. package/dist-client/shared/integration-fetch.js.map +0 -1
  179. package/dist-client/shared/kpi-project-sync.d.ts +0 -16
  180. package/dist-client/shared/kpi-project-sync.js +0 -129
  181. package/dist-client/shared/kpi-project-sync.js.map +0 -1
  182. package/dist-client/themes/dark.css +0 -51
  183. package/dist-client/themes/light.css +0 -51
  184. package/dist-client/tsconfig.tsbuildinfo +0 -1
  185. package/dist-client/viewparts/menu-tools.d.ts +0 -62
  186. package/dist-client/viewparts/menu-tools.js +0 -554
  187. package/dist-client/viewparts/menu-tools.js.map +0 -1
  188. package/dist-client/viewparts/user-circle.d.ts +0 -5
  189. package/dist-client/viewparts/user-circle.js +0 -26
  190. package/dist-client/viewparts/user-circle.js.map +0 -1
  191. package/dist-server/index.d.ts +0 -2
  192. package/dist-server/index.js +0 -6
  193. package/dist-server/index.js.map +0 -1
  194. package/dist-server/migrations/index.d.ts +0 -1
  195. package/dist-server/migrations/index.js +0 -12
  196. package/dist-server/migrations/index.js.map +0 -1
  197. package/dist-server/scripts/calculate-kpi-scores.d.ts +0 -10
  198. package/dist-server/scripts/calculate-kpi-scores.js +0 -333
  199. package/dist-server/scripts/calculate-kpi-scores.js.map +0 -1
  200. package/dist-server/scripts/load-grade-data-migration.d.ts +0 -14
  201. package/dist-server/scripts/load-grade-data-migration.js +0 -279
  202. package/dist-server/scripts/load-grade-data-migration.js.map +0 -1
  203. package/dist-server/scripts/propagate-parent-kpi-values.d.ts +0 -14
  204. package/dist-server/scripts/propagate-parent-kpi-values.js +0 -786
  205. package/dist-server/scripts/propagate-parent-kpi-values.js.map +0 -1
  206. package/dist-server/scripts/recalculate-by-project-name.d.ts +0 -2
  207. package/dist-server/scripts/recalculate-by-project-name.js +0 -72
  208. package/dist-server/scripts/recalculate-by-project-name.js.map +0 -1
  209. package/dist-server/service/index.d.ts +0 -4
  210. package/dist-server/service/index.js +0 -20
  211. package/dist-server/service/index.js.map +0 -1
  212. package/dist-server/service/kpi-metric-value/index.d.ts +0 -4
  213. package/dist-server/service/kpi-metric-value/index.js +0 -8
  214. package/dist-server/service/kpi-metric-value/index.js.map +0 -1
  215. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +0 -171
  216. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +0 -993
  217. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +0 -1
  218. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.d.ts +0 -12
  219. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js +0 -56
  220. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js.map +0 -1
  221. package/dist-server/service/kpi-stat/index.d.ts +0 -4
  222. package/dist-server/service/kpi-stat/index.js +0 -8
  223. package/dist-server/service/kpi-stat/index.js.map +0 -1
  224. package/dist-server/service/kpi-stat/kpi-stat-query.d.ts +0 -13
  225. package/dist-server/service/kpi-stat/kpi-stat-query.js +0 -751
  226. package/dist-server/service/kpi-stat/kpi-stat-query.js.map +0 -1
  227. package/dist-server/service/kpi-stat/kpi-stat-types.d.ts +0 -32
  228. package/dist-server/service/kpi-stat/kpi-stat-types.js +0 -180
  229. package/dist-server/service/kpi-stat/kpi-stat-types.js.map +0 -1
  230. package/dist-server/service/kpi-value/index.d.ts +0 -3
  231. package/dist-server/service/kpi-value/index.js +0 -7
  232. package/dist-server/service/kpi-value/index.js.map +0 -1
  233. package/dist-server/service/kpi-value/kpi-value-query.d.ts +0 -8
  234. package/dist-server/service/kpi-value/kpi-value-query.js +0 -90
  235. package/dist-server/service/kpi-value/kpi-value-query.js.map +0 -1
  236. package/dist-server/tsconfig.tsbuildinfo +0 -1
@@ -1,751 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.KpiStatQuery = void 0;
4
- const tslib_1 = require("tslib");
5
- const type_graphql_1 = require("type-graphql");
6
- const shell_1 = require("@things-factory/shell");
7
- const kpi_1 = require("@things-factory/kpi");
8
- const domain_inheritance_js_1 = require("@things-factory/kpi/dist-server/service/utils/domain-inheritance.js");
9
- const kpi_stat_types_1 = require("./kpi-stat-types");
10
- let KpiStatQuery = class KpiStatQuery {
11
- async totalKpiZValueComprehensiveStats(startYearMonth, endYearMonth, sectorType, buildingUsage, context) {
12
- const { domain } = context.state;
13
- const queryBuilder = (0, shell_1.getRepository)('kpi_values')
14
- .createQueryBuilder('kv')
15
- .select([
16
- 'k.name as kpiName',
17
- 'MIN(kv.score) as minVal',
18
- 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
19
- 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
20
- 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
21
- 'AVG(kv.score) as avgVal',
22
- 'MAX(kv.score) as maxVal',
23
- 'COUNT(DISTINCT p.id) as projectCount'
24
- ])
25
- .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
26
- .innerJoin('projects', 'p', 'kv."group" = p.id::text')
27
- .where('k.name LIKE :pattern', { pattern: 'Z%' })
28
- .andWhere('p.end_date IS NOT NULL')
29
- .andWhere('kv.domain_id IN (:...domainIds)', { domainIds: await (0, domain_inheritance_js_1.getDomainIdsWithAncestors)(domain) });
30
- // 기간 필터
31
- if (startYearMonth && startYearMonth.trim() !== '') {
32
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) >= :startYearMonth`, { startYearMonth });
33
- }
34
- if (endYearMonth && endYearMonth.trim() !== '') {
35
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) <= :endYearMonth`, { endYearMonth });
36
- }
37
- if (sectorType === null || sectorType === void 0 ? void 0 : sectorType.trim()) {
38
- queryBuilder.andWhere('p.sector_type = :sectorType', { sectorType });
39
- }
40
- if (buildingUsage === null || buildingUsage === void 0 ? void 0 : buildingUsage.trim()) {
41
- queryBuilder.andWhere('p.building_usage = :buildingUsage', { buildingUsage });
42
- }
43
- queryBuilder.groupBy('k.name');
44
- const results = await queryBuilder.getRawMany();
45
- return results.map(result => {
46
- const kpiName = result.kpiname;
47
- const minVal = Math.min(Math.max(Number(result.minval), 0), 1);
48
- const q1Val = Math.min(Math.max(Number(result.q1val), 0), 1);
49
- const medVal = Math.min(Math.max(Number(result.medval), 0), 1);
50
- const q3Val = Math.min(Math.max(Number(result.q3val), 0), 1);
51
- const avgVal = Math.min(Math.max(Number(result.avgval), 0), 1);
52
- const maxVal = Math.min(Math.max(Number(result.maxval), 0), 1);
53
- const projectCount = Number(result.projectcount);
54
- return {
55
- kpiName: kpiName,
56
- minVal: isNaN(minVal) ? 0 : minVal,
57
- q1Val: isNaN(q1Val) ? 0 : q1Val,
58
- medVal: isNaN(medVal) ? 0 : medVal,
59
- q3Val: isNaN(q3Val) ? 0 : q3Val,
60
- maxVal: isNaN(maxVal) ? 0 : maxVal,
61
- avgVal: isNaN(avgVal) ? 0 : avgVal,
62
- projectCount: isNaN(projectCount) ? 0 : projectCount
63
- };
64
- });
65
- }
66
- async totalKpiYValueComprehensiveStats(startYearMonth, endYearMonth, sectorType, buildingUsage, context) {
67
- const { domain } = context.state;
68
- const queryBuilder = (0, shell_1.getRepository)('kpi_values')
69
- .createQueryBuilder('kv')
70
- .select([
71
- 'k.name as kpiName',
72
- 'MIN(kv.score) as minVal',
73
- 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
74
- 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
75
- 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
76
- 'AVG(kv.score) as avgVal',
77
- 'MAX(kv.score) as maxVal',
78
- 'COUNT(DISTINCT p.id) as projectCount'
79
- ])
80
- .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
81
- .innerJoin('projects', 'p', 'kv."group" = p.id::text')
82
- .where('k.name LIKE :pattern', { pattern: 'Y%' })
83
- .andWhere('p.end_date IS NOT NULL')
84
- .andWhere('kv.domain_id IN (:...domainIds)', { domainIds: await (0, domain_inheritance_js_1.getDomainIdsWithAncestors)(domain) });
85
- // 기간 필터
86
- if (startYearMonth && startYearMonth.trim() !== '') {
87
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) >= :startYearMonth`, { startYearMonth });
88
- }
89
- if (endYearMonth && endYearMonth.trim() !== '') {
90
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) <= :endYearMonth`, { endYearMonth });
91
- }
92
- if (sectorType === null || sectorType === void 0 ? void 0 : sectorType.trim()) {
93
- queryBuilder.andWhere('p.sector_type = :sectorType', { sectorType });
94
- }
95
- if (buildingUsage === null || buildingUsage === void 0 ? void 0 : buildingUsage.trim()) {
96
- queryBuilder.andWhere('p.building_usage = :buildingUsage', { buildingUsage });
97
- }
98
- queryBuilder.groupBy('k.name').orderBy('k.name', 'ASC');
99
- const results = await queryBuilder.getRawMany();
100
- return results.map(result => {
101
- const kpiName = result.kpiname;
102
- const minVal = Math.min(Math.max(Number(result.minval), 0), 1);
103
- const q1Val = Math.min(Math.max(Number(result.q1val), 0), 1);
104
- const medVal = Math.min(Math.max(Number(result.medval), 0), 1);
105
- const q3Val = Math.min(Math.max(Number(result.q3val), 0), 1);
106
- const avgVal = Math.min(Math.max(Number(result.avgval), 0), 1);
107
- const maxVal = Math.min(Math.max(Number(result.maxval), 0), 1);
108
- const projectCount = Number(result.projectcount);
109
- return {
110
- kpiName: kpiName,
111
- minVal: isNaN(minVal) ? 0 : minVal,
112
- q1Val: isNaN(q1Val) ? 0 : q1Val,
113
- medVal: isNaN(medVal) ? 0 : medVal,
114
- q3Val: isNaN(q3Val) ? 0 : q3Val,
115
- maxVal: isNaN(maxVal) ? 0 : maxVal,
116
- avgVal: isNaN(avgVal) ? 0 : avgVal,
117
- projectCount: isNaN(projectCount) ? 0 : projectCount
118
- };
119
- });
120
- }
121
- async kpiZValueComprehensiveStatsByGeoGroup(geoGroup, kpiName, startYearMonth, endYearMonth, sectorType, buildingUsage, context) {
122
- var _a, _b;
123
- const { domain } = context.state;
124
- const queryBuilder = (0, shell_1.getRepository)('kpi_values')
125
- .createQueryBuilder('kv')
126
- .select([
127
- `CASE
128
- WHEN p.geo_group IN ('01','02','03','04','05','06','07','08') THEN '서울특별시'
129
- WHEN p.geo_group IN ('46','47','48','49') THEN '부산광역시'
130
- WHEN p.geo_group IN ('41','42','43') THEN '대구광역시'
131
- WHEN p.geo_group IN ('21','22','23') THEN '인천광역시'
132
- WHEN p.geo_group IN ('61','62') THEN '광주광역시'
133
- WHEN p.geo_group IN ('34','35') THEN '대전광역시'
134
- WHEN p.geo_group IN ('44','45') THEN '울산광역시'
135
- WHEN p.geo_group = '30' THEN '세종특별자치시'
136
- WHEN p.geo_group IN ('10','11','12','13','14','15','16','17','18') THEN '경기도'
137
- WHEN p.geo_group IN ('24','25','26','33') THEN '강원도'
138
- WHEN p.geo_group IN ('27','28','29') THEN '충청북도'
139
- WHEN p.geo_group IN ('31','32') THEN '충청남도'
140
- WHEN p.geo_group IN ('54','55','56') THEN '전라북도'
141
- WHEN p.geo_group IN ('57','58','59') THEN '전라남도'
142
- WHEN p.geo_group IN ('36','37','38','39','40') THEN '경상북도'
143
- WHEN p.geo_group IN ('50','51','52','53') THEN '경상남도'
144
- WHEN p.geo_group = '63' THEN '제주특별자치도'
145
- END as geoGroup`,
146
- 'MIN(kv.score) as minVal',
147
- 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
148
- 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
149
- 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
150
- 'MAX(kv.score) as maxVal',
151
- 'AVG(kv.score) as avgVal',
152
- 'COUNT(DISTINCT p.id) as projectCount'
153
- ])
154
- .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
155
- .innerJoin('projects', 'p', 'kv."group" = p.id::text')
156
- .where('p.end_date IS NOT NULL')
157
- .andWhere('p.geo_group IS NOT NULL')
158
- .andWhere('kv.domain_id IN (:...domainIds)', { domainIds: await (0, domain_inheritance_js_1.getDomainIdsWithAncestors)(domain) });
159
- // 기간 필터
160
- if (startYearMonth && startYearMonth.trim() !== '') {
161
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) >= :startYearMonth`, { startYearMonth });
162
- }
163
- if (endYearMonth && endYearMonth.trim() !== '') {
164
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) <= :endYearMonth`, { endYearMonth });
165
- }
166
- if (sectorType === null || sectorType === void 0 ? void 0 : sectorType.trim()) {
167
- queryBuilder.andWhere('p.sector_type = :sectorType', { sectorType });
168
- }
169
- if (buildingUsage === null || buildingUsage === void 0 ? void 0 : buildingUsage.trim()) {
170
- queryBuilder.andWhere('p.building_usage = :buildingUsage', { buildingUsage });
171
- }
172
- // KPI 필터: kpiName이 지정되면 해당 Y-level KPI만, 없으면 Z-level KPI 전체
173
- if (kpiName && kpiName.trim() !== '') {
174
- // kpiName 표기 불일치('일정성과(Y1)' vs 'Y1. 일정...') 방지 — Y1~Y6 코드로 LIKE 매칭
175
- queryBuilder.andWhere('k.name LIKE :kpiNameLike', { kpiNameLike: `%${(_b = (_a = kpiName.match(/Y[1-6]/)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : kpiName}%` });
176
- }
177
- else {
178
- queryBuilder.andWhere('k.name LIKE :pattern', { pattern: 'Z%' });
179
- }
180
- queryBuilder.groupBy('geoGroup');
181
- if (geoGroup && geoGroup.trim() !== '') {
182
- queryBuilder.having('geoGroup = :geoGroup', { geoGroup });
183
- }
184
- const results = await queryBuilder.getRawMany();
185
- return results
186
- .map(result => {
187
- const kpiName = result.kpiname;
188
- const minVal = Math.min(Math.max(Number(result.minval), 0), 1);
189
- const q1Val = Math.min(Math.max(Number(result.q1val), 0), 1);
190
- const medVal = Math.min(Math.max(Number(result.medval), 0), 1);
191
- const q3Val = Math.min(Math.max(Number(result.q3val), 0), 1);
192
- const maxVal = Math.min(Math.max(Number(result.maxval), 0), 1);
193
- const avgVal = Math.min(Math.max(Number(result.avgval), 0), 1);
194
- const projectCount = Number(result.projectcount);
195
- return {
196
- kpiName: kpiName,
197
- geoGroup: result.geogroup || null,
198
- minVal: isNaN(minVal) ? 0 : minVal,
199
- q1Val: isNaN(q1Val) ? 0 : q1Val,
200
- medVal: isNaN(medVal) ? 0 : medVal,
201
- q3Val: isNaN(q3Val) ? 0 : q3Val,
202
- maxVal: isNaN(maxVal) ? 0 : maxVal,
203
- avgVal: isNaN(avgVal) ? 0 : avgVal,
204
- projectCount: isNaN(projectCount) ? 0 : projectCount
205
- };
206
- })
207
- .filter(result => result.geoGroup !== null);
208
- }
209
- async kpiYValueComprehensiveStatsByGeoGroup(geoGroup, context) {
210
- const { domain } = context.state;
211
- const queryBuilder = (0, shell_1.getRepository)('kpi_values')
212
- .createQueryBuilder('kv')
213
- .select([
214
- 'p.geo_group as geoGroup',
215
- 'k.name as kpiName',
216
- 'MIN(kv.score) as minVal',
217
- 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
218
- 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
219
- 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
220
- 'MAX(kv.score) as maxVal',
221
- 'AVG(kv.score) as avgVal',
222
- 'COUNT(DISTINCT p.id) as projectCount'
223
- ])
224
- .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
225
- .innerJoin('projects', 'p', 'kv."group" = p.id::text')
226
- .where('k.name LIKE :pattern', { pattern: 'Y%' })
227
- .andWhere('p.end_date IS NOT NULL')
228
- .andWhere('p.geo_group IS NOT NULL')
229
- .andWhere('kv.domain_id IN (:...domainIds)', { domainIds: await (0, domain_inheritance_js_1.getDomainIdsWithAncestors)(domain) })
230
- .groupBy('p.geo_group, k.name');
231
- if (geoGroup && geoGroup.trim() !== '') {
232
- queryBuilder.andWhere('p.geo_group LIKE :geoGroup', { geoGroup: `%${geoGroup}%` });
233
- }
234
- const results = await queryBuilder.getRawMany();
235
- return results
236
- .map(result => {
237
- const kpiName = result.kpiname;
238
- const minVal = Math.min(Math.max(Number(result.minval), 0), 1);
239
- const q1Val = Math.min(Math.max(Number(result.q1val), 0), 1);
240
- const medVal = Math.min(Math.max(Number(result.medval), 0), 1);
241
- const q3Val = Math.min(Math.max(Number(result.q3val), 0), 1);
242
- const maxVal = Math.min(Math.max(Number(result.maxval), 0), 1);
243
- const avgVal = Math.min(Math.max(Number(result.avgval), 0), 1);
244
- const projectCount = Number(result.projectcount);
245
- return {
246
- kpiName: kpiName,
247
- geoGroup: result.geogroup || null,
248
- minVal: isNaN(minVal) ? 0 : minVal,
249
- q1Val: isNaN(q1Val) ? 0 : q1Val,
250
- medVal: isNaN(medVal) ? 0 : medVal,
251
- q3Val: isNaN(q3Val) ? 0 : q3Val,
252
- maxVal: isNaN(maxVal) ? 0 : maxVal,
253
- avgVal: isNaN(avgVal) ? 0 : avgVal,
254
- projectCount: isNaN(projectCount) ? 0 : projectCount
255
- };
256
- })
257
- .filter(result => result.geoGroup !== null);
258
- }
259
- async kpiZValueMonthlyTrendByGeoGroup(kpiName, startYearMonth, endYearMonth, sectorType, buildingUsage, context) {
260
- var _a, _b;
261
- const { domain } = context.state;
262
- const queryBuilder = (0, shell_1.getRepository)('kpi_values')
263
- .createQueryBuilder('kv')
264
- .select([
265
- `CASE
266
- WHEN p.geo_group IN ('01','02','03','04','05','06','07','08') THEN '서울특별시'
267
- WHEN p.geo_group IN ('46','47','48','49') THEN '부산광역시'
268
- WHEN p.geo_group IN ('41','42','43') THEN '대구광역시'
269
- WHEN p.geo_group IN ('21','22','23') THEN '인천광역시'
270
- WHEN p.geo_group IN ('61','62') THEN '광주광역시'
271
- WHEN p.geo_group IN ('34','35') THEN '대전광역시'
272
- WHEN p.geo_group IN ('44','45') THEN '울산광역시'
273
- WHEN p.geo_group = '30' THEN '세종특별자치시'
274
- WHEN p.geo_group IN ('10','11','12','13','14','15','16','17','18') THEN '경기도'
275
- WHEN p.geo_group IN ('24','25','26','33') THEN '강원도'
276
- WHEN p.geo_group IN ('27','28','29') THEN '충청북도'
277
- WHEN p.geo_group IN ('31','32') THEN '충청남도'
278
- WHEN p.geo_group IN ('54','55','56') THEN '전라북도'
279
- WHEN p.geo_group IN ('57','58','59') THEN '전라남도'
280
- WHEN p.geo_group IN ('36','37','38','39','40') THEN '경상북도'
281
- WHEN p.geo_group IN ('50','51','52','53') THEN '경상남도'
282
- WHEN p.geo_group = '63' THEN '제주특별자치도'
283
- END as geoGroup`,
284
- // 월 기준 = KPI 측정월(kv.value_date, 'YYYY-MM-DD' 문자열) — 프로젝트 준공월(p.end_date) 아님.
285
- `LEFT(kv.value_date, 7) as yearMonth`,
286
- 'AVG(kv.score) as avgVal',
287
- 'COUNT(DISTINCT p.id) as projectCount'
288
- ])
289
- .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
290
- .innerJoin('projects', 'p', 'kv."group" = p.id::text')
291
- .where('kv.value_date IS NOT NULL')
292
- .andWhere('p.geo_group IS NOT NULL')
293
- .andWhere('kv.domain_id IN (:...domainIds)', { domainIds: await (0, domain_inheritance_js_1.getDomainIdsWithAncestors)(domain) });
294
- // 기간 필터 — KPI 측정월(kv.value_date) 기준
295
- if (startYearMonth && startYearMonth.trim() !== '') {
296
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) >= :startYearMonth`, { startYearMonth });
297
- }
298
- if (endYearMonth && endYearMonth.trim() !== '') {
299
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) <= :endYearMonth`, { endYearMonth });
300
- }
301
- if (sectorType === null || sectorType === void 0 ? void 0 : sectorType.trim()) {
302
- queryBuilder.andWhere('p.sector_type = :sectorType', { sectorType });
303
- }
304
- if (buildingUsage === null || buildingUsage === void 0 ? void 0 : buildingUsage.trim()) {
305
- queryBuilder.andWhere('p.building_usage = :buildingUsage', { buildingUsage });
306
- }
307
- // KPI 필터: kpiName이 지정되면 해당 Y-level KPI만, 없으면 Z-level KPI 전체
308
- if (kpiName && kpiName.trim() !== '') {
309
- // kpiName 표기 불일치('일정성과(Y1)' vs 'Y1. 일정...') 방지 — Y1~Y6 코드로 LIKE 매칭
310
- queryBuilder.andWhere('k.name LIKE :kpiNameLike', { kpiNameLike: `%${(_b = (_a = kpiName.match(/Y[1-6]/)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : kpiName}%` });
311
- }
312
- else {
313
- queryBuilder.andWhere('k.name LIKE :pattern', { pattern: 'Z%' });
314
- }
315
- queryBuilder.groupBy('geoGroup, yearMonth').orderBy('yearMonth', 'ASC');
316
- const results = await queryBuilder.getRawMany();
317
- return results
318
- .map(result => {
319
- const avgVal = Math.min(Math.max(Number(result.avgval), 0), 1);
320
- const projectCount = Number(result.projectcount);
321
- return {
322
- geoGroup: result.geogroup || null,
323
- yearMonth: result.yearmonth,
324
- avgVal: isNaN(avgVal) ? 0 : avgVal,
325
- projectCount: isNaN(projectCount) ? 0 : projectCount
326
- };
327
- })
328
- .filter(result => result.geoGroup !== null);
329
- }
330
- async kpiZValueMonthlyTrendBySigungu(geoGroup, kpiName, startYearMonth, endYearMonth, sectorType, buildingUsage, context) {
331
- var _a, _b;
332
- const { domain } = context.state;
333
- const queryBuilder = (0, shell_1.getRepository)('kpi_values')
334
- .createQueryBuilder('kv')
335
- .select([
336
- 'p.geo_group as geoGroup',
337
- // 월 기준 = KPI 측정월(kv.value_date)
338
- `LEFT(kv.value_date, 7) as yearMonth`,
339
- 'AVG(kv.score) as avgVal',
340
- 'COUNT(DISTINCT p.id) as projectCount'
341
- ])
342
- .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
343
- .innerJoin('projects', 'p', 'kv."group" = p.id::text')
344
- .where('kv.value_date IS NOT NULL')
345
- .andWhere('p.geo_group = :geoGroup', { geoGroup }) // 특정 시군구 코드만
346
- .andWhere('kv.domain_id IN (:...domainIds)', { domainIds: await (0, domain_inheritance_js_1.getDomainIdsWithAncestors)(domain) });
347
- if (startYearMonth && startYearMonth.trim() !== '') {
348
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) >= :startYearMonth`, { startYearMonth });
349
- }
350
- if (endYearMonth && endYearMonth.trim() !== '') {
351
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) <= :endYearMonth`, { endYearMonth });
352
- }
353
- if (sectorType === null || sectorType === void 0 ? void 0 : sectorType.trim()) {
354
- queryBuilder.andWhere('p.sector_type = :sectorType', { sectorType });
355
- }
356
- if (buildingUsage === null || buildingUsage === void 0 ? void 0 : buildingUsage.trim()) {
357
- queryBuilder.andWhere('p.building_usage = :buildingUsage', { buildingUsage });
358
- }
359
- if (kpiName && kpiName.trim() !== '') {
360
- // kpiName 표기 불일치('일정성과(Y1)' vs 'Y1. 일정...') 방지 — Y1~Y6 코드로 LIKE 매칭
361
- queryBuilder.andWhere('k.name LIKE :kpiNameLike', { kpiNameLike: `%${(_b = (_a = kpiName.match(/Y[1-6]/)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : kpiName}%` });
362
- }
363
- else {
364
- queryBuilder.andWhere('k.name LIKE :pattern', { pattern: 'Z%' });
365
- }
366
- queryBuilder.groupBy('geoGroup, yearMonth').orderBy('yearMonth', 'ASC');
367
- const results = await queryBuilder.getRawMany();
368
- return results.map(result => {
369
- const avgVal = Math.min(Math.max(Number(result.avgval), 0), 1);
370
- const projectCount = Number(result.projectcount);
371
- return {
372
- geoGroup: result.geogroup || null,
373
- yearMonth: result.yearmonth,
374
- avgVal: isNaN(avgVal) ? 0 : avgVal,
375
- projectCount: isNaN(projectCount) ? 0 : projectCount
376
- };
377
- });
378
- }
379
- async kpiProjectStats(sectorType, buildingUsage, kpiNamePattern, startYearMonth, endYearMonth, context) {
380
- const { domain } = context.state;
381
- const qb = (0, shell_1.getRepository)('kpi_values')
382
- .createQueryBuilder('kv')
383
- .select([
384
- 'k.name as kpiName',
385
- 'pk.name as categoryName',
386
- 'MIN(kv.score) as minVal',
387
- 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
388
- 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
389
- 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
390
- 'MAX(kv.score) as maxVal',
391
- 'AVG(kv.score) as avgVal',
392
- 'STDDEV_POP(kv.score) as stddevVal',
393
- 'COUNT(DISTINCT p.id) as projectCount'
394
- ])
395
- .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
396
- .leftJoin('kpis', 'pk', 'k.parent_id = pk.id')
397
- .innerJoin('projects', 'p', 'kv."group" = p.id::text')
398
- .where('p.end_date IS NOT NULL')
399
- .andWhere('kv.domain_id IN (:...domainIds)', { domainIds: await (0, domain_inheritance_js_1.getDomainIdsWithAncestors)(domain) });
400
- if (sectorType === null || sectorType === void 0 ? void 0 : sectorType.trim()) {
401
- qb.andWhere('p.sector_type = :sectorType', { sectorType });
402
- }
403
- if (buildingUsage === null || buildingUsage === void 0 ? void 0 : buildingUsage.trim()) {
404
- qb.andWhere('p.building_usage = :buildingUsage', { buildingUsage });
405
- }
406
- if (kpiNamePattern === null || kpiNamePattern === void 0 ? void 0 : kpiNamePattern.trim()) {
407
- qb.andWhere('k.name LIKE :kpiNamePattern', { kpiNamePattern: `${kpiNamePattern}%` });
408
- }
409
- if (startYearMonth === null || startYearMonth === void 0 ? void 0 : startYearMonth.trim()) {
410
- qb.andWhere(`LEFT(kv.value_date, 7) >= :startYearMonth`, { startYearMonth });
411
- }
412
- if (endYearMonth === null || endYearMonth === void 0 ? void 0 : endYearMonth.trim()) {
413
- qb.andWhere(`LEFT(kv.value_date, 7) <= :endYearMonth`, { endYearMonth });
414
- }
415
- qb.groupBy('k.name, pk.name').orderBy('k.name', 'ASC');
416
- const results = await qb.getRawMany();
417
- const clamp = (v) => Math.min(Math.max(isNaN(v) ? 0 : v, 0), 1);
418
- return results.map(r => ({
419
- kpiName: r.kpiname,
420
- categoryName: r.categoryname || undefined,
421
- minVal: clamp(Number(r.minval)),
422
- q1Val: clamp(Number(r.q1val)),
423
- medVal: clamp(Number(r.medval)),
424
- q3Val: clamp(Number(r.q3val)),
425
- maxVal: clamp(Number(r.maxval)),
426
- avgVal: clamp(Number(r.avgval)),
427
- stddevVal: isNaN(Number(r.stddevval)) ? 0 : Math.max(0, Number(r.stddevval)),
428
- projectCount: isNaN(Number(r.projectcount)) ? 0 : Number(r.projectcount)
429
- }));
430
- }
431
- async kpiZValueStatsBySigungu(kpiName, startYearMonth, endYearMonth, sectorType, buildingUsage, context) {
432
- var _a, _b;
433
- const { domain } = context.state;
434
- const queryBuilder = (0, shell_1.getRepository)('kpi_values')
435
- .createQueryBuilder('kv')
436
- .select([
437
- 'p.geo_group as geoGroup',
438
- 'MIN(kv.score) as minVal',
439
- 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
440
- 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
441
- 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
442
- 'MAX(kv.score) as maxVal',
443
- 'AVG(kv.score) as avgVal',
444
- 'COUNT(DISTINCT p.id) as projectCount'
445
- ])
446
- .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
447
- .innerJoin('projects', 'p', 'kv."group" = p.id::text')
448
- .where('p.end_date IS NOT NULL')
449
- .andWhere('p.geo_group IS NOT NULL')
450
- .andWhere('kv.domain_id IN (:...domainIds)', { domainIds: await (0, domain_inheritance_js_1.getDomainIdsWithAncestors)(domain) });
451
- if (startYearMonth === null || startYearMonth === void 0 ? void 0 : startYearMonth.trim()) {
452
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) >= :startYearMonth`, { startYearMonth });
453
- }
454
- if (endYearMonth === null || endYearMonth === void 0 ? void 0 : endYearMonth.trim()) {
455
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) <= :endYearMonth`, { endYearMonth });
456
- }
457
- if (sectorType === null || sectorType === void 0 ? void 0 : sectorType.trim()) {
458
- queryBuilder.andWhere('p.sector_type = :sectorType', { sectorType });
459
- }
460
- if (buildingUsage === null || buildingUsage === void 0 ? void 0 : buildingUsage.trim()) {
461
- queryBuilder.andWhere('p.building_usage = :buildingUsage', { buildingUsage });
462
- }
463
- if (kpiName === null || kpiName === void 0 ? void 0 : kpiName.trim()) {
464
- // kpiName 표기 불일치('일정성과(Y1)' vs 'Y1. 일정...') 방지 — Y1~Y6 코드로 LIKE 매칭
465
- queryBuilder.andWhere('k.name LIKE :kpiNameLike', { kpiNameLike: `%${(_b = (_a = kpiName.match(/Y[1-6]/)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : kpiName}%` });
466
- }
467
- else {
468
- queryBuilder.andWhere('k.name LIKE :pattern', { pattern: 'Z%' });
469
- }
470
- queryBuilder.groupBy('p.geo_group');
471
- const results = await queryBuilder.getRawMany();
472
- const clamp = (v) => Math.min(Math.max(isNaN(v) ? 0 : v, 0), 1);
473
- return results
474
- .map(r => ({
475
- kpiName: r.kpiname || undefined,
476
- geoGroup: r.geogroup || null,
477
- minVal: clamp(Number(r.minval)),
478
- q1Val: clamp(Number(r.q1val)),
479
- medVal: clamp(Number(r.medval)),
480
- q3Val: clamp(Number(r.q3val)),
481
- maxVal: clamp(Number(r.maxval)),
482
- avgVal: clamp(Number(r.avgval)),
483
- projectCount: isNaN(Number(r.projectcount)) ? 0 : Number(r.projectcount)
484
- }))
485
- .filter(r => r.geoGroup !== null);
486
- }
487
- async kpiYValueStatsByGeoGroup(geoGroup, startYearMonth, endYearMonth, sectorType, buildingUsage, context) {
488
- const { domain } = context.state;
489
- const queryBuilder = (0, shell_1.getRepository)('kpi_values')
490
- .createQueryBuilder('kv')
491
- .select([
492
- 'k.name as kpiName',
493
- 'MIN(kv.score) as minVal',
494
- 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
495
- 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
496
- 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
497
- 'MAX(kv.score) as maxVal',
498
- 'AVG(kv.score) as avgVal',
499
- 'COUNT(DISTINCT p.id) as projectCount'
500
- ])
501
- .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
502
- .innerJoin('projects', 'p', 'kv."group" = p.id::text')
503
- .where('k.name LIKE :pattern', { pattern: 'Y%' })
504
- .andWhere('p.end_date IS NOT NULL')
505
- .andWhere('p.geo_group = :geoGroup', { geoGroup })
506
- .andWhere('kv.domain_id IN (:...domainIds)', { domainIds: await (0, domain_inheritance_js_1.getDomainIdsWithAncestors)(domain) });
507
- if (startYearMonth === null || startYearMonth === void 0 ? void 0 : startYearMonth.trim()) {
508
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) >= :startYearMonth`, { startYearMonth });
509
- }
510
- if (endYearMonth === null || endYearMonth === void 0 ? void 0 : endYearMonth.trim()) {
511
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) <= :endYearMonth`, { endYearMonth });
512
- }
513
- if (sectorType === null || sectorType === void 0 ? void 0 : sectorType.trim()) {
514
- queryBuilder.andWhere('p.sector_type = :sectorType', { sectorType });
515
- }
516
- if (buildingUsage === null || buildingUsage === void 0 ? void 0 : buildingUsage.trim()) {
517
- queryBuilder.andWhere('p.building_usage = :buildingUsage', { buildingUsage });
518
- }
519
- queryBuilder.groupBy('k.name').orderBy('k.name', 'ASC');
520
- const results = await queryBuilder.getRawMany();
521
- const clamp = (v) => Math.min(Math.max(isNaN(v) ? 0 : v, 0), 1);
522
- return results.map(r => ({
523
- kpiName: r.kpiname,
524
- minVal: clamp(Number(r.minval)),
525
- q1Val: clamp(Number(r.q1val)),
526
- medVal: clamp(Number(r.medval)),
527
- q3Val: clamp(Number(r.q3val)),
528
- maxVal: clamp(Number(r.maxval)),
529
- avgVal: clamp(Number(r.avgval)),
530
- projectCount: isNaN(Number(r.projectcount)) ? 0 : Number(r.projectcount)
531
- }));
532
- }
533
- async kpiYValueStatsByMetroArea(metroArea, startYearMonth, endYearMonth, sectorType, buildingUsage, context) {
534
- if (!context || !context.state) {
535
- console.error('Context is undefined or missing state');
536
- return [];
537
- }
538
- const { domain } = context.state;
539
- const queryBuilder = (0, shell_1.getRepository)('kpi_values')
540
- .createQueryBuilder('kv')
541
- .select([
542
- 'k.name as kpiName',
543
- 'MIN(kv.score) as minVal',
544
- 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
545
- 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
546
- 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
547
- 'MAX(kv.score) as maxVal',
548
- 'AVG(kv.score) as avgVal',
549
- 'COUNT(DISTINCT p.id) as projectCount'
550
- ])
551
- .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
552
- .innerJoin('projects', 'p', 'kv."group" = p.id::text')
553
- .where('k.name LIKE :pattern', { pattern: 'Y%' })
554
- .andWhere('p.end_date IS NOT NULL')
555
- .andWhere('p.geo_group IS NOT NULL')
556
- .andWhere('kv.domain_id IN (:...domainIds)', { domainIds: await (0, domain_inheritance_js_1.getDomainIdsWithAncestors)(domain) });
557
- // 기간 필터
558
- if (startYearMonth && startYearMonth.trim() !== '') {
559
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) >= :startYearMonth`, { startYearMonth });
560
- }
561
- if (endYearMonth && endYearMonth.trim() !== '') {
562
- queryBuilder.andWhere(`LEFT(kv.value_date, 7) <= :endYearMonth`, { endYearMonth });
563
- }
564
- if (sectorType === null || sectorType === void 0 ? void 0 : sectorType.trim()) {
565
- queryBuilder.andWhere('p.sector_type = :sectorType', { sectorType });
566
- }
567
- if (buildingUsage === null || buildingUsage === void 0 ? void 0 : buildingUsage.trim()) {
568
- queryBuilder.andWhere('p.building_usage = :buildingUsage', { buildingUsage });
569
- }
570
- queryBuilder
571
- .andWhere(`CASE
572
- WHEN p.geo_group IN ('01','02','03','04','05','06','07','08') THEN '서울특별시'
573
- WHEN p.geo_group IN ('46','47','48','49') THEN '부산광역시'
574
- WHEN p.geo_group IN ('41','42','43') THEN '대구광역시'
575
- WHEN p.geo_group IN ('21','22','23') THEN '인천광역시'
576
- WHEN p.geo_group IN ('61','62') THEN '광주광역시'
577
- WHEN p.geo_group IN ('34','35') THEN '대전광역시'
578
- WHEN p.geo_group IN ('44','45') THEN '울산광역시'
579
- WHEN p.geo_group = '30' THEN '세종특별자치시'
580
- WHEN p.geo_group IN ('10','11','12','13','14','15','16','17','18') THEN '경기도'
581
- WHEN p.geo_group IN ('24','25','26','33') THEN '강원도'
582
- WHEN p.geo_group IN ('27','28','29') THEN '충청북도'
583
- WHEN p.geo_group IN ('31','32') THEN '충청남도'
584
- WHEN p.geo_group IN ('54','55','56') THEN '전라북도'
585
- WHEN p.geo_group IN ('57','58','59') THEN '전라남도'
586
- WHEN p.geo_group IN ('36','37','38','39','40') THEN '경상북도'
587
- WHEN p.geo_group IN ('50','51','52','53') THEN '경상남도'
588
- WHEN p.geo_group = '63' THEN '제주특별자치도'
589
- END = :metroArea`, { metroArea })
590
- .groupBy('k.name')
591
- .orderBy('k.name', 'ASC');
592
- const results = await queryBuilder.getRawMany();
593
- return results.map(result => {
594
- const kpiName = result.kpiname;
595
- const minVal = Math.min(Math.max(Number(result.minval), 0), 1);
596
- const q1Val = Math.min(Math.max(Number(result.q1val), 0), 1);
597
- const medVal = Math.min(Math.max(Number(result.medval), 0), 1);
598
- const q3Val = Math.min(Math.max(Number(result.q3val), 0), 1);
599
- const avgVal = Math.min(Math.max(Number(result.avgval), 0), 1);
600
- const maxVal = Math.min(Math.max(Number(result.maxval), 0), 1);
601
- const projectCount = Number(result.projectcount);
602
- return {
603
- kpiName: kpiName,
604
- minVal: isNaN(minVal) ? 0 : minVal,
605
- q1Val: isNaN(q1Val) ? 0 : q1Val,
606
- medVal: isNaN(medVal) ? 0 : medVal,
607
- q3Val: isNaN(q3Val) ? 0 : q3Val,
608
- maxVal: isNaN(maxVal) ? 0 : maxVal,
609
- avgVal: isNaN(avgVal) ? 0 : avgVal,
610
- projectCount: isNaN(projectCount) ? 0 : projectCount
611
- };
612
- });
613
- }
614
- };
615
- exports.KpiStatQuery = KpiStatQuery;
616
- tslib_1.__decorate([
617
- (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "read", domainOwnerGranted: true, superUserGranted: true)'),
618
- (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiComprehensiveStats], { description: 'Get KPI box plot statistics for Z-category KPIs for all projects' }),
619
- tslib_1.__param(0, (0, type_graphql_1.Arg)('startYearMonth', { nullable: true })),
620
- tslib_1.__param(1, (0, type_graphql_1.Arg)('endYearMonth', { nullable: true })),
621
- tslib_1.__param(2, (0, type_graphql_1.Arg)('sectorType', { nullable: true })),
622
- tslib_1.__param(3, (0, type_graphql_1.Arg)('buildingUsage', { nullable: true })),
623
- tslib_1.__param(4, (0, type_graphql_1.Ctx)()),
624
- tslib_1.__metadata("design:type", Function),
625
- tslib_1.__metadata("design:paramtypes", [String, String, String, String, Object]),
626
- tslib_1.__metadata("design:returntype", Promise)
627
- ], KpiStatQuery.prototype, "totalKpiZValueComprehensiveStats", null);
628
- tslib_1.__decorate([
629
- (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "read", domainOwnerGranted: true, superUserGranted: true)'),
630
- (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiComprehensiveStats], { description: 'Get KPI box plot statistics for Y-category KPIs for all projects' }),
631
- tslib_1.__param(0, (0, type_graphql_1.Arg)('startYearMonth', { nullable: true })),
632
- tslib_1.__param(1, (0, type_graphql_1.Arg)('endYearMonth', { nullable: true })),
633
- tslib_1.__param(2, (0, type_graphql_1.Arg)('sectorType', { nullable: true })),
634
- tslib_1.__param(3, (0, type_graphql_1.Arg)('buildingUsage', { nullable: true })),
635
- tslib_1.__param(4, (0, type_graphql_1.Ctx)()),
636
- tslib_1.__metadata("design:type", Function),
637
- tslib_1.__metadata("design:paramtypes", [String, String, String, String, Object]),
638
- tslib_1.__metadata("design:returntype", Promise)
639
- ], KpiStatQuery.prototype, "totalKpiYValueComprehensiveStats", null);
640
- tslib_1.__decorate([
641
- (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "read", domainOwnerGranted: true, superUserGranted: true)'),
642
- (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiComprehensiveStatsByGeoGroup], {
643
- description: 'Get KPI box plot statistics for Z-category KPIs by metro area'
644
- }),
645
- tslib_1.__param(0, (0, type_graphql_1.Arg)('geoGroup', { nullable: true })),
646
- tslib_1.__param(1, (0, type_graphql_1.Arg)('kpiName', { nullable: true })),
647
- tslib_1.__param(2, (0, type_graphql_1.Arg)('startYearMonth', { nullable: true })),
648
- tslib_1.__param(3, (0, type_graphql_1.Arg)('endYearMonth', { nullable: true })),
649
- tslib_1.__param(4, (0, type_graphql_1.Arg)('sectorType', { nullable: true })),
650
- tslib_1.__param(5, (0, type_graphql_1.Arg)('buildingUsage', { nullable: true })),
651
- tslib_1.__param(6, (0, type_graphql_1.Ctx)()),
652
- tslib_1.__metadata("design:type", Function),
653
- tslib_1.__metadata("design:paramtypes", [String, String, String, String, String, String, Object]),
654
- tslib_1.__metadata("design:returntype", Promise)
655
- ], KpiStatQuery.prototype, "kpiZValueComprehensiveStatsByGeoGroup", null);
656
- tslib_1.__decorate([
657
- (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "read", domainOwnerGranted: true, superUserGranted: true)'),
658
- (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiComprehensiveStatsByGeoGroup], { description: 'Get KPI box plot statistics for Y-category KPIs by geo group' }),
659
- tslib_1.__param(0, (0, type_graphql_1.Arg)('geoGroup', { nullable: true })),
660
- tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
661
- tslib_1.__metadata("design:type", Function),
662
- tslib_1.__metadata("design:paramtypes", [String, Object]),
663
- tslib_1.__metadata("design:returntype", Promise)
664
- ], KpiStatQuery.prototype, "kpiYValueComprehensiveStatsByGeoGroup", null);
665
- tslib_1.__decorate([
666
- (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "read", domainOwnerGranted: true, superUserGranted: true)'),
667
- (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiMonthlyTrend], { description: 'Get monthly KPI trend for Z-category KPIs by metro area' }),
668
- tslib_1.__param(0, (0, type_graphql_1.Arg)('kpiName', { nullable: true })),
669
- tslib_1.__param(1, (0, type_graphql_1.Arg)('startYearMonth', { nullable: true })),
670
- tslib_1.__param(2, (0, type_graphql_1.Arg)('endYearMonth', { nullable: true })),
671
- tslib_1.__param(3, (0, type_graphql_1.Arg)('sectorType', { nullable: true })),
672
- tslib_1.__param(4, (0, type_graphql_1.Arg)('buildingUsage', { nullable: true })),
673
- tslib_1.__param(5, (0, type_graphql_1.Ctx)()),
674
- tslib_1.__metadata("design:type", Function),
675
- tslib_1.__metadata("design:paramtypes", [String, String, String, String, String, Object]),
676
- tslib_1.__metadata("design:returntype", Promise)
677
- ], KpiStatQuery.prototype, "kpiZValueMonthlyTrendByGeoGroup", null);
678
- tslib_1.__decorate([
679
- (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "read", domainOwnerGranted: true, superUserGranted: true)'),
680
- (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiMonthlyTrend], {
681
- description: 'Get monthly KPI trend for Z-category KPIs for a specific sigungu (geo_group code)'
682
- }),
683
- tslib_1.__param(0, (0, type_graphql_1.Arg)('geoGroup')),
684
- tslib_1.__param(1, (0, type_graphql_1.Arg)('kpiName', { nullable: true })),
685
- tslib_1.__param(2, (0, type_graphql_1.Arg)('startYearMonth', { nullable: true })),
686
- tslib_1.__param(3, (0, type_graphql_1.Arg)('endYearMonth', { nullable: true })),
687
- tslib_1.__param(4, (0, type_graphql_1.Arg)('sectorType', { nullable: true })),
688
- tslib_1.__param(5, (0, type_graphql_1.Arg)('buildingUsage', { nullable: true })),
689
- tslib_1.__param(6, (0, type_graphql_1.Ctx)()),
690
- tslib_1.__metadata("design:type", Function),
691
- tslib_1.__metadata("design:paramtypes", [String, String, String, String, String, String, Object]),
692
- tslib_1.__metadata("design:returntype", Promise)
693
- ], KpiStatQuery.prototype, "kpiZValueMonthlyTrendBySigungu", null);
694
- tslib_1.__decorate([
695
- (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "read", domainOwnerGranted: true, superUserGranted: true)'),
696
- (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiProjectStat], { description: 'Get KPI stats aggregated from project data with optional sectorType/buildingUsage filters' }),
697
- tslib_1.__param(0, (0, type_graphql_1.Arg)('sectorType', { nullable: true })),
698
- tslib_1.__param(1, (0, type_graphql_1.Arg)('buildingUsage', { nullable: true })),
699
- tslib_1.__param(2, (0, type_graphql_1.Arg)('kpiNamePattern', { nullable: true })),
700
- tslib_1.__param(3, (0, type_graphql_1.Arg)('startYearMonth', { nullable: true })),
701
- tslib_1.__param(4, (0, type_graphql_1.Arg)('endYearMonth', { nullable: true })),
702
- tslib_1.__param(5, (0, type_graphql_1.Ctx)()),
703
- tslib_1.__metadata("design:type", Function),
704
- tslib_1.__metadata("design:paramtypes", [String, String, String, String, String, Object]),
705
- tslib_1.__metadata("design:returntype", Promise)
706
- ], KpiStatQuery.prototype, "kpiProjectStats", null);
707
- tslib_1.__decorate([
708
- (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "read", domainOwnerGranted: true, superUserGranted: true)'),
709
- (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiComprehensiveStatsByGeoGroup], {
710
- description: 'Get KPI statistics by sigungu (geo_group code) level'
711
- }),
712
- tslib_1.__param(0, (0, type_graphql_1.Arg)('kpiName', { nullable: true })),
713
- tslib_1.__param(1, (0, type_graphql_1.Arg)('startYearMonth', { nullable: true })),
714
- tslib_1.__param(2, (0, type_graphql_1.Arg)('endYearMonth', { nullable: true })),
715
- tslib_1.__param(3, (0, type_graphql_1.Arg)('sectorType', { nullable: true })),
716
- tslib_1.__param(4, (0, type_graphql_1.Arg)('buildingUsage', { nullable: true })),
717
- tslib_1.__param(5, (0, type_graphql_1.Ctx)()),
718
- tslib_1.__metadata("design:type", Function),
719
- tslib_1.__metadata("design:paramtypes", [String, String, String, String, String, Object]),
720
- tslib_1.__metadata("design:returntype", Promise)
721
- ], KpiStatQuery.prototype, "kpiZValueStatsBySigungu", null);
722
- tslib_1.__decorate([
723
- (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "read", domainOwnerGranted: true, superUserGranted: true)'),
724
- (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiComprehensiveStats], { description: 'Get Y-level KPI statistics by geo_group code (sigungu)' }),
725
- tslib_1.__param(0, (0, type_graphql_1.Arg)('geoGroup')),
726
- tslib_1.__param(1, (0, type_graphql_1.Arg)('startYearMonth', { nullable: true })),
727
- tslib_1.__param(2, (0, type_graphql_1.Arg)('endYearMonth', { nullable: true })),
728
- tslib_1.__param(3, (0, type_graphql_1.Arg)('sectorType', { nullable: true })),
729
- tslib_1.__param(4, (0, type_graphql_1.Arg)('buildingUsage', { nullable: true })),
730
- tslib_1.__param(5, (0, type_graphql_1.Ctx)()),
731
- tslib_1.__metadata("design:type", Function),
732
- tslib_1.__metadata("design:paramtypes", [String, String, String, String, String, Object]),
733
- tslib_1.__metadata("design:returntype", Promise)
734
- ], KpiStatQuery.prototype, "kpiYValueStatsByGeoGroup", null);
735
- tslib_1.__decorate([
736
- (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "read", domainOwnerGranted: true, superUserGranted: true)'),
737
- (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiComprehensiveStats], { description: 'Get KPI statistics for Y-category KPIs by specific metro area' }),
738
- tslib_1.__param(0, (0, type_graphql_1.Arg)('metroArea')),
739
- tslib_1.__param(1, (0, type_graphql_1.Arg)('startYearMonth', { nullable: true })),
740
- tslib_1.__param(2, (0, type_graphql_1.Arg)('endYearMonth', { nullable: true })),
741
- tslib_1.__param(3, (0, type_graphql_1.Arg)('sectorType', { nullable: true })),
742
- tslib_1.__param(4, (0, type_graphql_1.Arg)('buildingUsage', { nullable: true })),
743
- tslib_1.__param(5, (0, type_graphql_1.Ctx)()),
744
- tslib_1.__metadata("design:type", Function),
745
- tslib_1.__metadata("design:paramtypes", [String, String, String, String, String, Object]),
746
- tslib_1.__metadata("design:returntype", Promise)
747
- ], KpiStatQuery.prototype, "kpiYValueStatsByMetroArea", null);
748
- exports.KpiStatQuery = KpiStatQuery = tslib_1.__decorate([
749
- (0, type_graphql_1.Resolver)(kpi_1.KpiStatistic)
750
- ], KpiStatQuery);
751
- //# sourceMappingURL=kpi-stat-query.js.map