@dssp/dkpi 1.0.0-alpha.53 → 1.0.0-alpha.55

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 (28) hide show
  1. package/KPI-STATISTICS-SERVICE.md +233 -0
  2. package/dist-client/components/kpi-single-boxplot-chart.js +109 -111
  3. package/dist-client/components/kpi-single-boxplot-chart.js.map +1 -1
  4. package/dist-client/pages/sv-project-completed-list.d.ts +3 -0
  5. package/dist-client/pages/sv-project-completed-list.js +70 -11
  6. package/dist-client/pages/sv-project-completed-list.js.map +1 -1
  7. package/dist-client/pages/sv-project-list.d.ts +3 -0
  8. package/dist-client/pages/sv-project-list.js +69 -11
  9. package/dist-client/pages/sv-project-list.js.map +1 -1
  10. package/dist-client/tsconfig.tsbuildinfo +1 -1
  11. package/dist-server/service/index.d.ts +1 -3
  12. package/dist-server/service/index.js +3 -4
  13. package/dist-server/service/index.js.map +1 -1
  14. package/dist-server/service/kpi-stat/index.d.ts +4 -0
  15. package/dist-server/service/kpi-stat/index.js +8 -0
  16. package/dist-server/service/kpi-stat/index.js.map +1 -0
  17. package/dist-server/service/kpi-stat/kpi-stat-query.d.ts +8 -0
  18. package/dist-server/service/kpi-stat/kpi-stat-query.js +225 -0
  19. package/dist-server/service/kpi-stat/kpi-stat-query.js.map +1 -0
  20. package/dist-server/service/kpi-stat/kpi-stat-types.d.ts +20 -0
  21. package/dist-server/service/kpi-stat/kpi-stat-types.js +78 -0
  22. package/dist-server/service/kpi-stat/kpi-stat-types.js.map +1 -0
  23. package/dist-server/tsconfig.tsbuildinfo +1 -1
  24. package/kpi-module-service-tests.md +1286 -0
  25. package/kpi-module-test-report.md +676 -0
  26. package/kpi-module-unit-test-detailed-report.md +925 -0
  27. package/kpi-module-unit-tests-detailed.md +1452 -0
  28. package/package.json +3 -3
@@ -1,6 +1,4 @@
1
- export * from './kpi-value/kpi-value-query.js';
2
- export * from './kpi-metric-value/kpi-metric-value-query.js';
3
1
  export declare const entities: any[];
4
2
  export declare const schema: {
5
- resolverClasses: (typeof import("./kpi-value/kpi-value-query.js").KpiValueQueryForProject | typeof import("./kpi-metric-value/kpi-metric-value-query.js").KpiMetricValueQuery | typeof import("./kpi-metric-value/kpi-metric-value-mutation.js").KpiMetricValueMutation)[];
3
+ resolverClasses: (typeof import("./kpi-stat/kpi-stat-query").KpiStatQuery | typeof import("./kpi-value/kpi-value-query").KpiValueQueryForProject | typeof import("./kpi-metric-value/kpi-metric-value-query").KpiMetricValueQuery | typeof import("./kpi-metric-value/kpi-metric-value-mutation").KpiMetricValueMutation)[];
6
4
  };
@@ -1,11 +1,9 @@
1
1
  "use strict";
2
+ /* EXPORT ENTITY TYPES */
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.schema = exports.entities = void 0;
4
- const tslib_1 = require("tslib");
5
- /* EXPORT ENTITY TYPES */
6
- tslib_1.__exportStar(require("./kpi-value/kpi-value-query.js"), exports);
7
- tslib_1.__exportStar(require("./kpi-metric-value/kpi-metric-value-query.js"), exports);
8
5
  /* IMPORT ENTITIES AND RESOLVERS */
6
+ const kpi_stat_1 = require("./kpi-stat");
9
7
  const kpi_value_1 = require("./kpi-value");
10
8
  const kpi_metric_value_1 = require("./kpi-metric-value");
11
9
  exports.entities = [
@@ -14,6 +12,7 @@ exports.entities = [
14
12
  exports.schema = {
15
13
  resolverClasses: [
16
14
  /* RESOLVER CLASSES */
15
+ ...kpi_stat_1.resolvers,
17
16
  ...kpi_value_1.resolvers,
18
17
  ...kpi_metric_value_1.resolvers
19
18
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yBAAyB;AACzB,yEAA8C;AAC9C,uFAA4D;AAE5D,mCAAmC;AACnC,2CAA4D;AAC5D,yDAAyE;AAE5D,QAAA,QAAQ,GAAG;AACtB,cAAc;CACf,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,sBAAsB;QACtB,GAAG,qBAAiB;QACpB,GAAG,4BAAuB;KAC3B;CACF,CAAA","sourcesContent":["/* EXPORT ENTITY TYPES */\nexport * from './kpi-value/kpi-value-query.js'\nexport * from './kpi-metric-value/kpi-metric-value-query.js'\n\n/* IMPORT ENTITIES AND RESOLVERS */\nimport { resolvers as KpiValueResolvers } from './kpi-value'\nimport { resolvers as KpiMetricValueResolvers } from './kpi-metric-value'\n\nexport const entities = [\n /* ENTITIES */\n]\n\nexport const schema = {\n resolverClasses: [\n /* RESOLVER CLASSES */\n ...KpiValueResolvers,\n ...KpiMetricValueResolvers\n ]\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";AAAA,yBAAyB;;;AAEzB,mCAAmC;AACnC,yCAA0D;AAC1D,2CAA4D;AAC5D,yDAAyE;AAE5D,QAAA,QAAQ,GAAG;AACtB,cAAc;CACf,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,sBAAsB;QACtB,GAAG,oBAAgB;QACnB,GAAG,qBAAiB;QACpB,GAAG,4BAAuB;KAC3B;CACF,CAAA","sourcesContent":["/* EXPORT ENTITY TYPES */\n\n/* IMPORT ENTITIES AND RESOLVERS */\nimport { resolvers as KpiStatResolvers } from './kpi-stat'\nimport { resolvers as KpiValueResolvers } from './kpi-value'\nimport { resolvers as KpiMetricValueResolvers } from './kpi-metric-value'\n\nexport const entities = [\n /* ENTITIES */\n]\n\nexport const schema = {\n resolverClasses: [\n /* RESOLVER CLASSES */\n ...KpiStatResolvers,\n ...KpiValueResolvers,\n ...KpiMetricValueResolvers\n ]\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { KpiStatQuery } from './kpi-stat-query';
2
+ export declare const entities: any[];
3
+ export declare const resolvers: (typeof KpiStatQuery)[];
4
+ export declare const subscribers: any[];
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.subscribers = exports.resolvers = exports.entities = void 0;
4
+ const kpi_stat_query_1 = require("./kpi-stat-query");
5
+ exports.entities = [];
6
+ exports.resolvers = [kpi_stat_query_1.KpiStatQuery];
7
+ exports.subscribers = [];
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/kpi-stat/index.ts"],"names":[],"mappings":";;;AAAA,qDAA+C;AAElC,QAAA,QAAQ,GAAG,EAAE,CAAA;AACb,QAAA,SAAS,GAAG,CAAC,6BAAY,CAAC,CAAA;AAC1B,QAAA,WAAW,GAAG,EAAE,CAAA","sourcesContent":["import { KpiStatQuery } from './kpi-stat-query'\n\nexport const entities = []\nexport const resolvers = [KpiStatQuery]\nexport const subscribers = []\n"]}
@@ -0,0 +1,8 @@
1
+ import { KpiBoxPlotStats, KpiRadarStats, KpiBoxPlotStatsByGeoGroup } from './kpi-stat-types';
2
+ export declare class KpiStatQuery {
3
+ totalKpiZValueBoxPlotStats(context?: ResolverContext): Promise<KpiBoxPlotStats[]>;
4
+ kpiZValueBoxPlotStats(geoGroup?: string, context?: ResolverContext): Promise<KpiBoxPlotStatsByGeoGroup[]>;
5
+ kpiYValueBoxPlotStats(geoGroup?: string, context?: ResolverContext): Promise<KpiBoxPlotStats[]>;
6
+ kpiRadarStats(kpiPattern: string, geoGroup?: string, context?: ResolverContext): Promise<KpiRadarStats[]>;
7
+ kpiComprehensiveStats(geoGroup?: string, includeOngoing?: boolean, context?: ResolverContext): Promise<KpiRadarStats[]>;
8
+ }
@@ -0,0 +1,225 @@
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 kpi_stat_types_1 = require("./kpi-stat-types");
9
+ let KpiStatQuery = class KpiStatQuery {
10
+ async totalKpiZValueBoxPlotStats(context) {
11
+ const { domain } = context.state;
12
+ const queryBuilder = (0, shell_1.getRepository)('kpi_values')
13
+ .createQueryBuilder('kv')
14
+ .select([
15
+ 'MIN(kv.score) as minVal',
16
+ 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
17
+ 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
18
+ 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
19
+ 'MAX(kv.score) as maxVal'
20
+ ])
21
+ .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
22
+ .innerJoin('projects', 'p', 'kv.kpi_org_scope_id = p.id')
23
+ .where('k.name LIKE :pattern', { pattern: 'Z%' })
24
+ .andWhere('p.end_date IS NOT NULL')
25
+ .andWhere('kv.domain_id = :domainId', { domainId: domain.id });
26
+ const results = await queryBuilder.getRawMany();
27
+ return results.map(result => {
28
+ const minVal = Number(result.minval);
29
+ const q1Val = Number(result.q1val);
30
+ const medVal = Number(result.medval);
31
+ const q3Val = Number(result.q3val);
32
+ const maxVal = Number(result.maxval);
33
+ return {
34
+ minVal: isNaN(minVal) ? 0 : minVal,
35
+ q1Val: isNaN(q1Val) ? 0 : q1Val,
36
+ medVal: isNaN(medVal) ? 0 : medVal,
37
+ q3Val: isNaN(q3Val) ? 0 : q3Val,
38
+ maxVal: isNaN(maxVal) ? 0 : maxVal
39
+ };
40
+ });
41
+ }
42
+ async kpiZValueBoxPlotStats(geoGroup, context) {
43
+ const { domain } = context.state;
44
+ const queryBuilder = (0, shell_1.getRepository)('kpi_values')
45
+ .createQueryBuilder('kv')
46
+ .select([
47
+ 'p.geo_group as geoGroup',
48
+ 'MIN(kv.score) as minVal',
49
+ 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
50
+ 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
51
+ 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
52
+ 'MAX(kv.score) as maxVal'
53
+ ])
54
+ .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
55
+ .innerJoin('projects', 'p', 'kv.kpi_org_scope_id = p.id')
56
+ .where('k.name LIKE :pattern', { pattern: 'Z%' })
57
+ .andWhere('p.end_date IS NOT NULL')
58
+ .andWhere('p.geo_group IS NOT NULL')
59
+ .andWhere('kv.domain_id = :domainId', { domainId: domain.id })
60
+ .groupBy('p.geo_group');
61
+ if (geoGroup && geoGroup.trim() !== '') {
62
+ queryBuilder.andWhere('p.geo_group LIKE :geoGroup', { geoGroup: `%${geoGroup}%` });
63
+ }
64
+ const results = await queryBuilder.getRawMany();
65
+ return results
66
+ .map(result => {
67
+ const minVal = Number(result.minVal);
68
+ const q1Val = Number(result.q1Val);
69
+ const medVal = Number(result.medVal);
70
+ const q3Val = Number(result.q3Val);
71
+ const maxVal = Number(result.maxVal);
72
+ return {
73
+ geoGroup: result.geoGroup || null,
74
+ minVal: isNaN(minVal) ? 0 : minVal,
75
+ q1Val: isNaN(q1Val) ? 0 : q1Val,
76
+ medVal: isNaN(medVal) ? 0 : medVal,
77
+ q3Val: isNaN(q3Val) ? 0 : q3Val,
78
+ maxVal: isNaN(maxVal) ? 0 : maxVal
79
+ };
80
+ })
81
+ .filter(result => result.geoGroup !== null);
82
+ }
83
+ async kpiYValueBoxPlotStats(geoGroup, context) {
84
+ const { domain } = context.state;
85
+ const queryBuilder = (0, shell_1.getRepository)('kpi_values')
86
+ .createQueryBuilder('kv')
87
+ .select([
88
+ 'p.geo_group as geoGroup',
89
+ 'k.name as kpiName',
90
+ 'MIN(kv.score) as minVal',
91
+ 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',
92
+ 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',
93
+ 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',
94
+ 'MAX(kv.score) as maxVal'
95
+ ])
96
+ .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
97
+ .innerJoin('projects', 'p', 'kv.kpi_org_scope_id = p.id')
98
+ .where('k.name LIKE :pattern', { pattern: 'Y%' })
99
+ .andWhere('p.end_date IS NOT NULL')
100
+ .andWhere('p.geo_group IS NOT NULL')
101
+ .andWhere('kv.domain_id = :domainId', { domainId: domain.id })
102
+ .groupBy('p.geo_group, k.name');
103
+ if (geoGroup && geoGroup.trim() !== '') {
104
+ queryBuilder.andWhere('p.geo_group LIKE :geoGroup', { geoGroup: `%${geoGroup}%` });
105
+ }
106
+ const results = await queryBuilder.getRawMany();
107
+ return results.map(result => ({
108
+ geoGroup: result.geoGroup,
109
+ kpiName: result.kpiName,
110
+ minVal: parseFloat(result.minVal),
111
+ q1Val: parseFloat(result.q1Val),
112
+ medVal: parseFloat(result.medVal),
113
+ q3Val: parseFloat(result.q3Val),
114
+ maxVal: parseFloat(result.maxVal)
115
+ }));
116
+ }
117
+ async kpiRadarStats(kpiPattern, geoGroup, context) {
118
+ const { domain } = context.state;
119
+ const queryBuilder = (0, shell_1.getRepository)('kpi_values')
120
+ .createQueryBuilder('kv')
121
+ .select([
122
+ 'p.geo_group as geoGroup',
123
+ 'k.name as kpiName',
124
+ 'AVG(kv.score) as avgScore',
125
+ 'COUNT(DISTINCT p.id) as projectCount'
126
+ ])
127
+ .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
128
+ .innerJoin('projects', 'p', 'kv.kpi_org_scope_id = p.id')
129
+ .where('k.name LIKE :pattern', { pattern: kpiPattern })
130
+ .andWhere('p.end_date IS NOT NULL')
131
+ .andWhere('p.geo_group IS NOT NULL')
132
+ .andWhere('kv.domain_id = :domainId', { domainId: domain.id })
133
+ .groupBy('p.geo_group, k.name');
134
+ if (geoGroup && geoGroup.trim() !== '') {
135
+ queryBuilder.andWhere('p.geo_group LIKE :geoGroup', { geoGroup: `%${geoGroup}%` });
136
+ }
137
+ const results = await queryBuilder.getRawMany();
138
+ return results.map(result => ({
139
+ geoGroup: result.geoGroup,
140
+ kpiName: result.kpiName,
141
+ avgScore: parseFloat(result.avgScore),
142
+ projectCount: parseInt(result.projectCount)
143
+ }));
144
+ }
145
+ async kpiComprehensiveStats(geoGroup, includeOngoing, context) {
146
+ const { domain } = context.state;
147
+ const queryBuilder = (0, shell_1.getRepository)('kpi_values')
148
+ .createQueryBuilder('kv')
149
+ .select([
150
+ 'p.geo_group as geoGroup',
151
+ 'k.name as kpiName',
152
+ 'AVG(kv.score) as avgScore',
153
+ 'COUNT(DISTINCT p.id) as projectCount'
154
+ ])
155
+ .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')
156
+ .innerJoin('projects', 'p', 'kv.kpi_org_scope_id = p.id')
157
+ .where('kv.domain_id = :domainId', { domainId: domain.id })
158
+ .andWhere('p.geo_group IS NOT NULL');
159
+ if (!includeOngoing) {
160
+ queryBuilder.andWhere('p.end_date IS NOT NULL');
161
+ }
162
+ if (geoGroup && geoGroup.trim() !== '') {
163
+ queryBuilder.andWhere('p.geo_group LIKE :geoGroup', { geoGroup: `%${geoGroup}%` });
164
+ }
165
+ queryBuilder.groupBy('p.geo_group, k.name').orderBy('p.geo_group, k.name');
166
+ const results = await queryBuilder.getRawMany();
167
+ return results.map(result => ({
168
+ geoGroup: result.geoGroup,
169
+ kpiName: result.kpiName,
170
+ avgScore: parseFloat(result.avgScore),
171
+ projectCount: parseInt(result.projectCount)
172
+ }));
173
+ }
174
+ };
175
+ exports.KpiStatQuery = KpiStatQuery;
176
+ tslib_1.__decorate([
177
+ (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)'),
178
+ (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiBoxPlotStats], { description: 'Get KPI box plot statistics for Z-category KPIs by geo group' }),
179
+ tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
180
+ tslib_1.__metadata("design:type", Function),
181
+ tslib_1.__metadata("design:paramtypes", [Object]),
182
+ tslib_1.__metadata("design:returntype", Promise)
183
+ ], KpiStatQuery.prototype, "totalKpiZValueBoxPlotStats", null);
184
+ tslib_1.__decorate([
185
+ (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)'),
186
+ (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiBoxPlotStatsByGeoGroup], { description: 'Get KPI box plot statistics for Z-category KPIs by geo group' }),
187
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('geoGroup', { nullable: true })),
188
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
189
+ tslib_1.__metadata("design:type", Function),
190
+ tslib_1.__metadata("design:paramtypes", [String, Object]),
191
+ tslib_1.__metadata("design:returntype", Promise)
192
+ ], KpiStatQuery.prototype, "kpiZValueBoxPlotStats", null);
193
+ tslib_1.__decorate([
194
+ (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)'),
195
+ (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiBoxPlotStats], { description: 'Get KPI box plot statistics for Y-category KPIs by geo group and KPI name' }),
196
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('geoGroup', { nullable: true })),
197
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
198
+ tslib_1.__metadata("design:type", Function),
199
+ tslib_1.__metadata("design:paramtypes", [String, Object]),
200
+ tslib_1.__metadata("design:returntype", Promise)
201
+ ], KpiStatQuery.prototype, "kpiYValueBoxPlotStats", null);
202
+ tslib_1.__decorate([
203
+ (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)'),
204
+ (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiRadarStats], { description: 'Get KPI radar chart statistics by geo group and KPI category' }),
205
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('kpiPattern', { defaultValue: '%' })),
206
+ tslib_1.__param(1, (0, type_graphql_1.Arg)('geoGroup', { nullable: true })),
207
+ tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
208
+ tslib_1.__metadata("design:type", Function),
209
+ tslib_1.__metadata("design:paramtypes", [String, String, Object]),
210
+ tslib_1.__metadata("design:returntype", Promise)
211
+ ], KpiStatQuery.prototype, "kpiRadarStats", null);
212
+ tslib_1.__decorate([
213
+ (0, type_graphql_1.Directive)('@privilege(category: "kpi", privilege: "query", domainOwnerGranted: true, superUserGranted: true)'),
214
+ (0, type_graphql_1.Query)(() => [kpi_stat_types_1.KpiRadarStats], { description: 'Get comprehensive KPI statistics for all completed projects' }),
215
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('geoGroup', { nullable: true })),
216
+ tslib_1.__param(1, (0, type_graphql_1.Arg)('includeOngoing', { defaultValue: false })),
217
+ tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
218
+ tslib_1.__metadata("design:type", Function),
219
+ tslib_1.__metadata("design:paramtypes", [String, Boolean, Object]),
220
+ tslib_1.__metadata("design:returntype", Promise)
221
+ ], KpiStatQuery.prototype, "kpiComprehensiveStats", null);
222
+ exports.KpiStatQuery = KpiStatQuery = tslib_1.__decorate([
223
+ (0, type_graphql_1.Resolver)(kpi_1.KpiStatistic)
224
+ ], KpiStatQuery);
225
+ //# sourceMappingURL=kpi-stat-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kpi-stat-query.js","sourceRoot":"","sources":["../../../server/service/kpi-stat/kpi-stat-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Query, Arg, Ctx, Directive } from 'type-graphql'\nimport { getRepository } from '@things-factory/shell'\nimport type ResolverContext from '@things-factory/auth-base'\nimport { KpiStatistic } from '@things-factory/kpi'\nimport { KpiBoxPlotStats, KpiRadarStats, KpiBoxPlotStatsByGeoGroup } from './kpi-stat-types'\n\n@Resolver(KpiStatistic)\nexport class KpiStatQuery {\n @Directive('@privilege(category: \"kpi\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(() => [KpiBoxPlotStats], { description: 'Get KPI box plot statistics for Z-category KPIs by geo group' })\n async totalKpiZValueBoxPlotStats(@Ctx() context?: ResolverContext): Promise<KpiBoxPlotStats[]> {\n const { domain } = context.state\n\n const queryBuilder = getRepository('kpi_values')\n .createQueryBuilder('kv')\n .select([\n 'MIN(kv.score) as minVal',\n 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',\n 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',\n 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',\n 'MAX(kv.score) as maxVal'\n ])\n .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')\n .innerJoin('projects', 'p', 'kv.kpi_org_scope_id = p.id')\n .where('k.name LIKE :pattern', { pattern: 'Z%' })\n .andWhere('p.end_date IS NOT NULL')\n .andWhere('kv.domain_id = :domainId', { domainId: domain.id })\n\n const results = await queryBuilder.getRawMany()\n\n return results.map(result => {\n const minVal = Number(result.minval)\n const q1Val = Number(result.q1val)\n const medVal = Number(result.medval)\n const q3Val = Number(result.q3val)\n const maxVal = Number(result.maxval)\n\n return {\n minVal: isNaN(minVal) ? 0 : minVal,\n q1Val: isNaN(q1Val) ? 0 : q1Val,\n medVal: isNaN(medVal) ? 0 : medVal,\n q3Val: isNaN(q3Val) ? 0 : q3Val,\n maxVal: isNaN(maxVal) ? 0 : maxVal\n }\n })\n }\n\n @Directive('@privilege(category: \"kpi\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(() => [KpiBoxPlotStatsByGeoGroup], { description: 'Get KPI box plot statistics for Z-category KPIs by geo group' })\n async kpiZValueBoxPlotStats(\n @Arg('geoGroup', { nullable: true }) geoGroup?: string,\n @Ctx() context?: ResolverContext\n ): Promise<KpiBoxPlotStatsByGeoGroup[]> {\n const { domain } = context.state\n\n const queryBuilder = getRepository('kpi_values')\n .createQueryBuilder('kv')\n .select([\n 'p.geo_group as geoGroup',\n 'MIN(kv.score) as minVal',\n 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',\n 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',\n 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',\n 'MAX(kv.score) as maxVal'\n ])\n .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')\n .innerJoin('projects', 'p', 'kv.kpi_org_scope_id = p.id')\n .where('k.name LIKE :pattern', { pattern: 'Z%' })\n .andWhere('p.end_date IS NOT NULL')\n .andWhere('p.geo_group IS NOT NULL')\n .andWhere('kv.domain_id = :domainId', { domainId: domain.id })\n .groupBy('p.geo_group')\n\n if (geoGroup && geoGroup.trim() !== '') {\n queryBuilder.andWhere('p.geo_group LIKE :geoGroup', { geoGroup: `%${geoGroup}%` })\n }\n\n const results = await queryBuilder.getRawMany()\n return results\n .map(result => {\n const minVal = Number(result.minVal)\n const q1Val = Number(result.q1Val)\n const medVal = Number(result.medVal)\n const q3Val = Number(result.q3Val)\n const maxVal = Number(result.maxVal)\n\n return {\n geoGroup: result.geoGroup || null,\n minVal: isNaN(minVal) ? 0 : minVal,\n q1Val: isNaN(q1Val) ? 0 : q1Val,\n medVal: isNaN(medVal) ? 0 : medVal,\n q3Val: isNaN(q3Val) ? 0 : q3Val,\n maxVal: isNaN(maxVal) ? 0 : maxVal\n }\n })\n .filter(result => result.geoGroup !== null)\n }\n\n @Directive('@privilege(category: \"kpi\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(() => [KpiBoxPlotStats], { description: 'Get KPI box plot statistics for Y-category KPIs by geo group and KPI name' })\n async kpiYValueBoxPlotStats(\n @Arg('geoGroup', { nullable: true }) geoGroup?: string,\n @Ctx() context?: ResolverContext\n ): Promise<KpiBoxPlotStats[]> {\n const { domain } = context.state\n\n const queryBuilder = getRepository('kpi_values')\n .createQueryBuilder('kv')\n .select([\n 'p.geo_group as geoGroup',\n 'k.name as kpiName',\n 'MIN(kv.score) as minVal',\n 'PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY kv.score) as q1Val',\n 'PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY kv.score) as medVal',\n 'PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY kv.score) as q3Val',\n 'MAX(kv.score) as maxVal'\n ])\n .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')\n .innerJoin('projects', 'p', 'kv.kpi_org_scope_id = p.id')\n .where('k.name LIKE :pattern', { pattern: 'Y%' })\n .andWhere('p.end_date IS NOT NULL')\n .andWhere('p.geo_group IS NOT NULL')\n .andWhere('kv.domain_id = :domainId', { domainId: domain.id })\n .groupBy('p.geo_group, k.name')\n\n if (geoGroup && geoGroup.trim() !== '') {\n queryBuilder.andWhere('p.geo_group LIKE :geoGroup', { geoGroup: `%${geoGroup}%` })\n }\n\n const results = await queryBuilder.getRawMany()\n return results.map(result => ({\n geoGroup: result.geoGroup,\n kpiName: result.kpiName,\n minVal: parseFloat(result.minVal),\n q1Val: parseFloat(result.q1Val),\n medVal: parseFloat(result.medVal),\n q3Val: parseFloat(result.q3Val),\n maxVal: parseFloat(result.maxVal)\n }))\n }\n\n @Directive('@privilege(category: \"kpi\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(() => [KpiRadarStats], { description: 'Get KPI radar chart statistics by geo group and KPI category' })\n async kpiRadarStats(\n @Arg('kpiPattern', { defaultValue: '%' }) kpiPattern: string,\n @Arg('geoGroup', { nullable: true }) geoGroup?: string,\n @Ctx() context?: ResolverContext\n ): Promise<KpiRadarStats[]> {\n const { domain } = context.state\n\n const queryBuilder = getRepository('kpi_values')\n .createQueryBuilder('kv')\n .select([\n 'p.geo_group as geoGroup',\n 'k.name as kpiName',\n 'AVG(kv.score) as avgScore',\n 'COUNT(DISTINCT p.id) as projectCount'\n ])\n .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')\n .innerJoin('projects', 'p', 'kv.kpi_org_scope_id = p.id')\n .where('k.name LIKE :pattern', { pattern: kpiPattern })\n .andWhere('p.end_date IS NOT NULL')\n .andWhere('p.geo_group IS NOT NULL')\n .andWhere('kv.domain_id = :domainId', { domainId: domain.id })\n .groupBy('p.geo_group, k.name')\n\n if (geoGroup && geoGroup.trim() !== '') {\n queryBuilder.andWhere('p.geo_group LIKE :geoGroup', { geoGroup: `%${geoGroup}%` })\n }\n\n const results = await queryBuilder.getRawMany()\n return results.map(result => ({\n geoGroup: result.geoGroup,\n kpiName: result.kpiName,\n avgScore: parseFloat(result.avgScore),\n projectCount: parseInt(result.projectCount)\n }))\n }\n\n @Directive('@privilege(category: \"kpi\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(() => [KpiRadarStats], { description: 'Get comprehensive KPI statistics for all completed projects' })\n async kpiComprehensiveStats(\n @Arg('geoGroup', { nullable: true }) geoGroup?: string,\n @Arg('includeOngoing', { defaultValue: false }) includeOngoing?: boolean,\n @Ctx() context?: ResolverContext\n ): Promise<KpiRadarStats[]> {\n const { domain } = context.state\n\n const queryBuilder = getRepository('kpi_values')\n .createQueryBuilder('kv')\n .select([\n 'p.geo_group as geoGroup',\n 'k.name as kpiName',\n 'AVG(kv.score) as avgScore',\n 'COUNT(DISTINCT p.id) as projectCount'\n ])\n .innerJoin('kpis', 'k', 'kv.kpi_id = k.id')\n .innerJoin('projects', 'p', 'kv.kpi_org_scope_id = p.id')\n .where('kv.domain_id = :domainId', { domainId: domain.id })\n .andWhere('p.geo_group IS NOT NULL')\n\n if (!includeOngoing) {\n queryBuilder.andWhere('p.end_date IS NOT NULL')\n }\n\n if (geoGroup && geoGroup.trim() !== '') {\n queryBuilder.andWhere('p.geo_group LIKE :geoGroup', { geoGroup: `%${geoGroup}%` })\n }\n\n queryBuilder.groupBy('p.geo_group, k.name').orderBy('p.geo_group, k.name')\n\n const results = await queryBuilder.getRawMany()\n return results.map(result => ({\n geoGroup: result.geoGroup,\n kpiName: result.kpiName,\n avgScore: parseFloat(result.avgScore),\n projectCount: parseInt(result.projectCount)\n }))\n }\n}\n"]}
@@ -0,0 +1,20 @@
1
+ export declare class KpiBoxPlotStats {
2
+ kpiName?: string;
3
+ minVal: number;
4
+ q1Val: number;
5
+ medVal: number;
6
+ q3Val: number;
7
+ maxVal: number;
8
+ }
9
+ export declare class KpiBoxPlotStatsByGeoGroup extends KpiBoxPlotStats {
10
+ geoGroup: string;
11
+ }
12
+ export declare class KpiRadarStats {
13
+ geoGroup: string;
14
+ kpiName: string;
15
+ avgScore: number;
16
+ projectCount: number;
17
+ }
18
+ export declare class KpiRadarStatsByGeoGroup extends KpiRadarStats {
19
+ geoGroup: string;
20
+ }
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KpiRadarStatsByGeoGroup = exports.KpiRadarStats = exports.KpiBoxPlotStatsByGeoGroup = exports.KpiBoxPlotStats = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const type_graphql_1 = require("type-graphql");
6
+ let KpiBoxPlotStats = class KpiBoxPlotStats {
7
+ };
8
+ exports.KpiBoxPlotStats = KpiBoxPlotStats;
9
+ tslib_1.__decorate([
10
+ (0, type_graphql_1.Field)({ nullable: true }),
11
+ tslib_1.__metadata("design:type", String)
12
+ ], KpiBoxPlotStats.prototype, "kpiName", void 0);
13
+ tslib_1.__decorate([
14
+ (0, type_graphql_1.Field)(() => type_graphql_1.Float),
15
+ tslib_1.__metadata("design:type", Number)
16
+ ], KpiBoxPlotStats.prototype, "minVal", void 0);
17
+ tslib_1.__decorate([
18
+ (0, type_graphql_1.Field)(() => type_graphql_1.Float),
19
+ tslib_1.__metadata("design:type", Number)
20
+ ], KpiBoxPlotStats.prototype, "q1Val", void 0);
21
+ tslib_1.__decorate([
22
+ (0, type_graphql_1.Field)(() => type_graphql_1.Float),
23
+ tslib_1.__metadata("design:type", Number)
24
+ ], KpiBoxPlotStats.prototype, "medVal", void 0);
25
+ tslib_1.__decorate([
26
+ (0, type_graphql_1.Field)(() => type_graphql_1.Float),
27
+ tslib_1.__metadata("design:type", Number)
28
+ ], KpiBoxPlotStats.prototype, "q3Val", void 0);
29
+ tslib_1.__decorate([
30
+ (0, type_graphql_1.Field)(() => type_graphql_1.Float),
31
+ tslib_1.__metadata("design:type", Number)
32
+ ], KpiBoxPlotStats.prototype, "maxVal", void 0);
33
+ exports.KpiBoxPlotStats = KpiBoxPlotStats = tslib_1.__decorate([
34
+ (0, type_graphql_1.ObjectType)()
35
+ ], KpiBoxPlotStats);
36
+ let KpiBoxPlotStatsByGeoGroup = class KpiBoxPlotStatsByGeoGroup extends KpiBoxPlotStats {
37
+ };
38
+ exports.KpiBoxPlotStatsByGeoGroup = KpiBoxPlotStatsByGeoGroup;
39
+ tslib_1.__decorate([
40
+ (0, type_graphql_1.Field)({ nullable: true }),
41
+ tslib_1.__metadata("design:type", String)
42
+ ], KpiBoxPlotStatsByGeoGroup.prototype, "geoGroup", void 0);
43
+ exports.KpiBoxPlotStatsByGeoGroup = KpiBoxPlotStatsByGeoGroup = tslib_1.__decorate([
44
+ (0, type_graphql_1.ObjectType)()
45
+ ], KpiBoxPlotStatsByGeoGroup);
46
+ let KpiRadarStats = class KpiRadarStats {
47
+ };
48
+ exports.KpiRadarStats = KpiRadarStats;
49
+ tslib_1.__decorate([
50
+ (0, type_graphql_1.Field)({ nullable: true }),
51
+ tslib_1.__metadata("design:type", String)
52
+ ], KpiRadarStats.prototype, "geoGroup", void 0);
53
+ tslib_1.__decorate([
54
+ (0, type_graphql_1.Field)(),
55
+ tslib_1.__metadata("design:type", String)
56
+ ], KpiRadarStats.prototype, "kpiName", void 0);
57
+ tslib_1.__decorate([
58
+ (0, type_graphql_1.Field)(() => type_graphql_1.Float),
59
+ tslib_1.__metadata("design:type", Number)
60
+ ], KpiRadarStats.prototype, "avgScore", void 0);
61
+ tslib_1.__decorate([
62
+ (0, type_graphql_1.Field)(() => type_graphql_1.Int),
63
+ tslib_1.__metadata("design:type", Number)
64
+ ], KpiRadarStats.prototype, "projectCount", void 0);
65
+ exports.KpiRadarStats = KpiRadarStats = tslib_1.__decorate([
66
+ (0, type_graphql_1.ObjectType)()
67
+ ], KpiRadarStats);
68
+ let KpiRadarStatsByGeoGroup = class KpiRadarStatsByGeoGroup extends KpiRadarStats {
69
+ };
70
+ exports.KpiRadarStatsByGeoGroup = KpiRadarStatsByGeoGroup;
71
+ tslib_1.__decorate([
72
+ (0, type_graphql_1.Field)({ nullable: true }),
73
+ tslib_1.__metadata("design:type", String)
74
+ ], KpiRadarStatsByGeoGroup.prototype, "geoGroup", void 0);
75
+ exports.KpiRadarStatsByGeoGroup = KpiRadarStatsByGeoGroup = tslib_1.__decorate([
76
+ (0, type_graphql_1.ObjectType)()
77
+ ], KpiRadarStatsByGeoGroup);
78
+ //# sourceMappingURL=kpi-stat-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kpi-stat-types.js","sourceRoot":"","sources":["../../../server/service/kpi-stat/kpi-stat-types.ts"],"names":[],"mappings":";;;;AAAA,+CAA4D;AAGrD,IAAM,eAAe,GAArB,MAAM,eAAe;CAkB3B,CAAA;AAlBY,0CAAe;AAE1B;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;gDACV;AAGhB;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,oBAAK,CAAC;;+CACL;AAGd;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,oBAAK,CAAC;;8CACN;AAGb;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,oBAAK,CAAC;;+CACL;AAGd;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,oBAAK,CAAC;;8CACN;AAGb;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,oBAAK,CAAC;;+CACL;0BAjBH,eAAe;IAD3B,IAAA,yBAAU,GAAE;GACA,eAAe,CAkB3B;AAGM,IAAM,yBAAyB,GAA/B,MAAM,yBAA0B,SAAQ,eAAe;CAqB7D,CAAA;AArBY,8DAAyB;AAEpC;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;2DACV;oCAFL,yBAAyB;IADrC,IAAA,yBAAU,GAAE;GACA,yBAAyB,CAqBrC;AAGM,IAAM,aAAa,GAAnB,MAAM,aAAa;CAYzB,CAAA;AAZY,sCAAa;AAExB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CACV;AAGhB;IADC,IAAA,oBAAK,GAAE;;8CACO;AAGf;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,oBAAK,CAAC;;+CACH;AAGhB;IADC,IAAA,oBAAK,EAAC,GAAG,EAAE,CAAC,kBAAG,CAAC;;mDACG;wBAXT,aAAa;IADzB,IAAA,yBAAU,GAAE;GACA,aAAa,CAYzB;AAGM,IAAM,uBAAuB,GAA7B,MAAM,uBAAwB,SAAQ,aAAa;CAYzD,CAAA;AAZY,0DAAuB;AAElC;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;yDACV;kCAFL,uBAAuB;IADnC,IAAA,yBAAU,GAAE;GACA,uBAAuB,CAYnC","sourcesContent":["import { ObjectType, Field, Float, Int } from 'type-graphql'\n\n@ObjectType()\nexport class KpiBoxPlotStats {\n @Field({ nullable: true })\n kpiName?: string\n\n @Field(() => Float)\n minVal: number\n\n @Field(() => Float)\n q1Val: number\n\n @Field(() => Float)\n medVal: number\n\n @Field(() => Float)\n q3Val: number\n\n @Field(() => Float)\n maxVal: number\n}\n\n@ObjectType()\nexport class KpiBoxPlotStatsByGeoGroup extends KpiBoxPlotStats {\n @Field({ nullable: true })\n geoGroup: string\n\n // @Field({ nullable: true })\n // kpiName?: string\n\n // @Field(() => Float)\n // minVal: number\n\n // @Field(() => Float)\n // q1Val: number\n\n // @Field(() => Float)\n // medVal: number\n\n // @Field(() => Float)\n // q3Val: number\n\n // @Field(() => Float)\n // maxVal: number\n}\n\n@ObjectType()\nexport class KpiRadarStats {\n @Field({ nullable: true })\n geoGroup: string\n\n @Field()\n kpiName: string\n\n @Field(() => Float)\n avgScore: number\n\n @Field(() => Int)\n projectCount: number\n}\n\n@ObjectType()\nexport class KpiRadarStatsByGeoGroup extends KpiRadarStats {\n @Field({ nullable: true })\n geoGroup: string\n\n // @Field()\n // kpiName: string\n\n // @Field(() => Float)\n // avgScore: number\n\n // @Field(() => Int)\n // projectCount: number\n}\n"]}