@deenruv/dashboard-widgets-plugin 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 (108) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +58 -0
  3. package/dist/plugin-server/constants.d.ts +4 -0
  4. package/dist/plugin-server/constants.js +12 -0
  5. package/dist/plugin-server/controllers/admin-ui-controller.d.ts +4 -0
  6. package/dist/plugin-server/controllers/admin-ui-controller.js +46 -0
  7. package/dist/plugin-server/controllers/refresh-view-controller.d.ts +8 -0
  8. package/dist/plugin-server/controllers/refresh-view-controller.js +41 -0
  9. package/dist/plugin-server/index.d.ts +1 -0
  10. package/dist/plugin-server/index.js +17 -0
  11. package/dist/plugin-server/materialisedViewEntities/order_summary.d.ts +9 -0
  12. package/dist/plugin-server/materialisedViewEntities/order_summary.js +79 -0
  13. package/dist/plugin-server/materialisedViewEntities/orders_summary_with_state.d.ts +10 -0
  14. package/dist/plugin-server/materialisedViewEntities/orders_summary_with_state.js +79 -0
  15. package/dist/plugin-server/materialisedViewEntities/total_products.d.ts +7 -0
  16. package/dist/plugin-server/materialisedViewEntities/total_products.js +62 -0
  17. package/dist/plugin-server/materialisedViewEntities/total_products_with_state.d.ts +9 -0
  18. package/dist/plugin-server/materialisedViewEntities/total_products_with_state.js +62 -0
  19. package/dist/plugin-server/plugin.d.ts +6 -0
  20. package/dist/plugin-server/plugin.js +149 -0
  21. package/dist/plugin-server/raw-sql.d.ts +8 -0
  22. package/dist/plugin-server/raw-sql.js +48 -0
  23. package/dist/plugin-server/resolvers/admin.resolver.d.ts +47 -0
  24. package/dist/plugin-server/resolvers/admin.resolver.js +63 -0
  25. package/dist/plugin-server/services/metrics.service.d.ts +30 -0
  26. package/dist/plugin-server/services/metrics.service.js +272 -0
  27. package/dist/plugin-server/types.d.ts +20 -0
  28. package/dist/plugin-server/types.js +2 -0
  29. package/dist/plugin-server/utils.d.ts +1 -0
  30. package/dist/plugin-server/utils.js +12 -0
  31. package/dist/plugin-server/zeus/const.d.ts +6 -0
  32. package/dist/plugin-server/zeus/const.js +3675 -0
  33. package/dist/plugin-server/zeus/index.d.ts +18709 -0
  34. package/dist/plugin-server/zeus/index.js +1122 -0
  35. package/dist/plugin-server/zeus/typedDocumentNode.d.ts +3 -0
  36. package/dist/plugin-server/zeus/typedDocumentNode.js +16 -0
  37. package/dist/plugin-ui/components/CategoriesChartWidget/dashCaseToSpaces.d.ts +1 -0
  38. package/dist/plugin-ui/components/CategoriesChartWidget/dashCaseToSpaces.js +6 -0
  39. package/dist/plugin-ui/components/CategoriesChartWidget/index.d.ts +2 -0
  40. package/dist/plugin-ui/components/CategoriesChartWidget/index.js +100 -0
  41. package/dist/plugin-ui/components/LatestOrdersWidget/index.d.ts +4 -0
  42. package/dist/plugin-ui/components/LatestOrdersWidget/index.js +96 -0
  43. package/dist/plugin-ui/components/LatestOrdersWidget/paymentMethod.d.ts +6 -0
  44. package/dist/plugin-ui/components/LatestOrdersWidget/paymentMethod.js +7 -0
  45. package/dist/plugin-ui/components/OrdersWidget/CustomTooltip.d.ts +18 -0
  46. package/dist/plugin-ui/components/OrdersWidget/CustomTooltip.js +92 -0
  47. package/dist/plugin-ui/components/OrdersWidget/GroupBySelect.d.ts +8 -0
  48. package/dist/plugin-ui/components/OrdersWidget/GroupBySelect.js +17 -0
  49. package/dist/plugin-ui/components/OrdersWidget/MetricCustomDates.d.ts +9 -0
  50. package/dist/plugin-ui/components/OrdersWidget/MetricCustomDates.js +27 -0
  51. package/dist/plugin-ui/components/OrdersWidget/MetricTypeSelect.d.ts +9 -0
  52. package/dist/plugin-ui/components/OrdersWidget/MetricTypeSelect.js +17 -0
  53. package/dist/plugin-ui/components/OrdersWidget/OrdersChart.d.ts +24 -0
  54. package/dist/plugin-ui/components/OrdersWidget/OrdersChart.js +46 -0
  55. package/dist/plugin-ui/components/OrdersWidget/OrdersSummaryTile.d.ts +13 -0
  56. package/dist/plugin-ui/components/OrdersWidget/OrdersSummaryTile.js +115 -0
  57. package/dist/plugin-ui/components/OrdersWidget/ProductSelector.d.ts +17 -0
  58. package/dist/plugin-ui/components/OrdersWidget/ProductSelector.js +37 -0
  59. package/dist/plugin-ui/components/OrdersWidget/RatioBadge.d.ts +6 -0
  60. package/dist/plugin-ui/components/OrdersWidget/RatioBadge.js +12 -0
  61. package/dist/plugin-ui/components/OrdersWidget/index.d.ts +2 -0
  62. package/dist/plugin-ui/components/OrdersWidget/index.js +229 -0
  63. package/dist/plugin-ui/components/ProductsChartWidget/CustomBarChartTooltip.d.ts +9 -0
  64. package/dist/plugin-ui/components/ProductsChartWidget/CustomBarChartTooltip.js +14 -0
  65. package/dist/plugin-ui/components/ProductsChartWidget/index.d.ts +2 -0
  66. package/dist/plugin-ui/components/ProductsChartWidget/index.js +116 -0
  67. package/dist/plugin-ui/components/index.d.ts +4 -0
  68. package/dist/plugin-ui/components/index.js +4 -0
  69. package/dist/plugin-ui/components/shared/EmptyData.d.ts +6 -0
  70. package/dist/plugin-ui/components/shared/EmptyData.js +8 -0
  71. package/dist/plugin-ui/components/shared/MetricsRangeSelect.d.ts +10 -0
  72. package/dist/plugin-ui/components/shared/MetricsRangeSelect.js +26 -0
  73. package/dist/plugin-ui/components/shared/OrderStatesSelect.d.ts +8 -0
  74. package/dist/plugin-ui/components/shared/OrderStatesSelect.js +28 -0
  75. package/dist/plugin-ui/components/shared/PeriodSelect.d.ts +20 -0
  76. package/dist/plugin-ui/components/shared/PeriodSelect.js +56 -0
  77. package/dist/plugin-ui/components/shared/colors.d.ts +1 -0
  78. package/dist/plugin-ui/components/shared/colors.js +1 -0
  79. package/dist/plugin-ui/components/shared/index.d.ts +3 -0
  80. package/dist/plugin-ui/components/shared/index.js +3 -0
  81. package/dist/plugin-ui/graphql/index.d.ts +2 -0
  82. package/dist/plugin-ui/graphql/index.js +2 -0
  83. package/dist/plugin-ui/graphql/queries.d.ts +425 -0
  84. package/dist/plugin-ui/graphql/queries.js +182 -0
  85. package/dist/plugin-ui/graphql/selectors.d.ts +19 -0
  86. package/dist/plugin-ui/graphql/selectors.js +21 -0
  87. package/dist/plugin-ui/index.d.ts +9 -0
  88. package/dist/plugin-ui/index.js +21 -0
  89. package/dist/plugin-ui/locales/en/index.d.ts +72 -0
  90. package/dist/plugin-ui/locales/en/index.js +2 -0
  91. package/dist/plugin-ui/locales/en/test.json +71 -0
  92. package/dist/plugin-ui/locales/pl/index.d.ts +71 -0
  93. package/dist/plugin-ui/locales/pl/index.js +2 -0
  94. package/dist/plugin-ui/locales/pl/test.json +70 -0
  95. package/dist/plugin-ui/tsconfig.json +18 -0
  96. package/dist/plugin-ui/types.d.ts +64 -0
  97. package/dist/plugin-ui/types.js +14 -0
  98. package/dist/plugin-ui/utils.d.ts +70 -0
  99. package/dist/plugin-ui/utils.js +366 -0
  100. package/dist/plugin-ui/widgets.d.ts +15 -0
  101. package/dist/plugin-ui/widgets.js +36 -0
  102. package/dist/plugin-ui/zeus/const.d.ts +6 -0
  103. package/dist/plugin-ui/zeus/const.js +3672 -0
  104. package/dist/plugin-ui/zeus/index.d.ts +18709 -0
  105. package/dist/plugin-ui/zeus/index.js +1114 -0
  106. package/dist/plugin-ui/zeus/typedDocumentNode.d.ts +3 -0
  107. package/dist/plugin-ui/zeus/typedDocumentNode.js +9 -0
  108. package/package.json +52 -0
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ var DashboardWidgetsPlugin_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.DashboardWidgetsPlugin = void 0;
14
+ const core_1 = require("@deenruv/core");
15
+ const admin_resolver_1 = require("./resolvers/admin.resolver");
16
+ const metrics_service_1 = require("./services/metrics.service");
17
+ const graphql_tag_1 = __importDefault(require("graphql-tag"));
18
+ const admin_ui_controller_1 = require("./controllers/admin-ui-controller");
19
+ const constants_1 = require("./constants");
20
+ const order_summary_1 = require("./materialisedViewEntities/order_summary");
21
+ const total_products_1 = require("./materialisedViewEntities/total_products");
22
+ const orders_summary_with_state_1 = require("./materialisedViewEntities/orders_summary_with_state");
23
+ const total_products_with_state_1 = require("./materialisedViewEntities/total_products_with_state");
24
+ const refresh_view_controller_1 = require("./controllers/refresh-view-controller");
25
+ let DashboardWidgetsPlugin = DashboardWidgetsPlugin_1 = class DashboardWidgetsPlugin {
26
+ static init(options) {
27
+ DashboardWidgetsPlugin_1.options = options;
28
+ return this;
29
+ }
30
+ };
31
+ exports.DashboardWidgetsPlugin = DashboardWidgetsPlugin;
32
+ exports.DashboardWidgetsPlugin = DashboardWidgetsPlugin = DashboardWidgetsPlugin_1 = __decorate([
33
+ (0, core_1.DeenruvPlugin)({
34
+ compatibility: "^0.0.0",
35
+ imports: [core_1.PluginCommonModule],
36
+ controllers: [admin_ui_controller_1.AdminUIController, refresh_view_controller_1.RefreshViewController],
37
+ entities: [
38
+ order_summary_1.OrderSummaryViewEntity,
39
+ orders_summary_with_state_1.OrderSummaryWithStateViewEntity,
40
+ total_products_1.TotalProductsViewEntity,
41
+ total_products_with_state_1.TotalProductsWithStateViewEntity,
42
+ ],
43
+ providers: [
44
+ metrics_service_1.BetterMetricsService,
45
+ {
46
+ provide: constants_1.PLUGIN_INIT_OPTIONS,
47
+ useFactory: () => DashboardWidgetsPlugin.options,
48
+ },
49
+ ],
50
+ configuration: (config) => {
51
+ return config;
52
+ },
53
+ adminApiExtensions: {
54
+ schema: (0, graphql_tag_1.default) `
55
+ type AdditionalOrderState {
56
+ state: String!
57
+ selectedByDefault: Boolean!
58
+ }
59
+
60
+ type ChartDataType {
61
+ type: ChartMetricType!
62
+ title: String!
63
+ entries: [ChartEntry!]!
64
+ }
65
+
66
+ type ChartMetrics {
67
+ data: [ChartDataType!]!
68
+ }
69
+ type OrderSummaryMetrics {
70
+ data: OrderSummaryDataMetric!
71
+ }
72
+ type OrderSummaryDataMetric {
73
+ currencyCode: CurrencyCode!
74
+ total: Float!
75
+ totalWithTax: Float!
76
+ orderCount: Float!
77
+ averageOrderValue: Float!
78
+ averageOrderValueWithTax: Float!
79
+ productCount: Float!
80
+ }
81
+ enum MetricRangeType {
82
+ Today
83
+ Yesterday
84
+ ThisWeek
85
+ LastWeek
86
+ ThisMonth
87
+ LastMonth
88
+ ThisYear
89
+ LastYear
90
+ FirstQuarter
91
+ SecondQuarter
92
+ ThirdQuarter
93
+ FourthQuarter
94
+ Custom
95
+ }
96
+
97
+ enum MetricIntervalType {
98
+ Day
99
+ Hour
100
+ }
101
+
102
+ enum ChartMetricType {
103
+ OrderCount
104
+ OrderTotal
105
+ AverageOrderValue
106
+ OrderTotalProductsCount
107
+ }
108
+ type ChartEntryAdditionalData {
109
+ id: String!
110
+ name: String!
111
+ quantity: Float!
112
+ }
113
+
114
+ type ChartEntry {
115
+ intervalTick: Int!
116
+ value: Float!
117
+ additionalData: [ChartEntryAdditionalData!]
118
+ }
119
+ input BetterMetricRangeInput {
120
+ start: DateTime!
121
+ end: DateTime
122
+ }
123
+
124
+ input OrderSummaryMetricInput {
125
+ range: BetterMetricRangeInput!
126
+ orderStates: [String!]!
127
+ }
128
+
129
+ input ChartMetricInput {
130
+ range: BetterMetricRangeInput!
131
+ interval: MetricIntervalType!
132
+ types: [ChartMetricType!]!
133
+ orderStates: [String!]!
134
+ productIDs: [String!]
135
+ net: Boolean
136
+ }
137
+
138
+ extend type Query {
139
+ additionalOrderStates: [AdditionalOrderState!]!
140
+ chartMetric(input: ChartMetricInput!): ChartMetrics!
141
+ orderSummaryMetric(
142
+ input: OrderSummaryMetricInput!
143
+ ): OrderSummaryMetrics!
144
+ }
145
+ `,
146
+ resolvers: [admin_resolver_1.AdminResolver],
147
+ },
148
+ })
149
+ ], DashboardWidgetsPlugin);
@@ -0,0 +1,8 @@
1
+ export declare const RANKED_TRANSLATIONS_SELECT: string[];
2
+ export declare const TOTAL_PRODUCT_VIEW_SELECT: string[];
3
+ export declare const ORDER_TOTAL_DAILY_SELECT: string[];
4
+ export declare const ORDER_TOTAL_HOURLY_SELECT: string[];
5
+ export declare const ORDER_COUNT_DAILY_SELECT: string[];
6
+ export declare const ORDER_COUNT_HOURLY_SELECT: string[];
7
+ export declare const ORDER_AVERAGE_DAILY_SELECT: string[];
8
+ export declare const ORDER_AVERAGE_HOURLY_SELECT: string[];
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ORDER_AVERAGE_HOURLY_SELECT = exports.ORDER_AVERAGE_DAILY_SELECT = exports.ORDER_COUNT_HOURLY_SELECT = exports.ORDER_COUNT_DAILY_SELECT = exports.ORDER_TOTAL_HOURLY_SELECT = exports.ORDER_TOTAL_DAILY_SELECT = exports.TOTAL_PRODUCT_VIEW_SELECT = exports.RANKED_TRANSLATIONS_SELECT = void 0;
4
+ exports.RANKED_TRANSLATIONS_SELECT = [
5
+ 'pvt.baseId AS "baseId"',
6
+ "pvt.name AS name",
7
+ 'pvt.languageCode AS "languageCode"',
8
+ `ROW_NUMBER() OVER (
9
+ PARTITION BY pvt."baseId"
10
+ ORDER BY CASE WHEN pvt."languageCode" = :languageCode THEN 1 ELSE 2 END
11
+ ) AS rank`,
12
+ ];
13
+ exports.TOTAL_PRODUCT_VIEW_SELECT = [
14
+ 'tpv."productVariantId" AS "productVariantId"',
15
+ 'SUM(tpv."orderPlacedQuantitySum") AS "orderPlacedQuantitySum"',
16
+ 'tpv."channelId" AS "channelId"',
17
+ "rt.name AS name",
18
+ ];
19
+ exports.ORDER_TOTAL_DAILY_SELECT = [
20
+ 'extract(epoch from osv.hour - :startDate)::integer/86400 + 1 as "intervalTick"',
21
+ 'SUM(osv."total") as value',
22
+ 'SUM(osv."totalWithTax") as "valueWithTax"',
23
+ ];
24
+ exports.ORDER_TOTAL_HOURLY_SELECT = [
25
+ 'extract(epoch from osv.hour - :startDate)::integer/3600 as "intervalTick"',
26
+ 'SUM(osv."total") as value',
27
+ 'SUM(osv."totalWithTax") as "valueWithTax"',
28
+ ];
29
+ exports.ORDER_COUNT_DAILY_SELECT = [
30
+ 'extract(epoch from osv.hour - :startDate)::integer/86400 + 1 as "intervalTick"',
31
+ 'SUM(osv."orderCount") as value',
32
+ ];
33
+ exports.ORDER_COUNT_HOURLY_SELECT = [
34
+ 'extract(epoch from osv.hour - :startDate)::integer/3600 as "intervalTick"',
35
+ 'SUM(osv."orderCount") as value',
36
+ ];
37
+ exports.ORDER_AVERAGE_DAILY_SELECT = [
38
+ 'extract(epoch from osv.hour - :startDate)::integer/86400 + 1 as "intervalTick"',
39
+ 'SUM(osv."orderCount") as orderCount',
40
+ 'SUM(osv."total") as value',
41
+ 'SUM(osv."totalWithTax") as "valueWithTax"',
42
+ ];
43
+ exports.ORDER_AVERAGE_HOURLY_SELECT = [
44
+ 'extract(epoch from osv.hour - :startDate)::integer/3600 as "intervalTick"',
45
+ 'SUM(osv."orderCount") as orderCount',
46
+ 'SUM(osv."total") as value',
47
+ 'SUM(osv."totalWithTax") as "valueWithTax"',
48
+ ];
@@ -0,0 +1,47 @@
1
+ import { RequestContext } from "@deenruv/core";
2
+ import { ResolverInputTypes } from "../zeus";
3
+ import { BetterMetricsService } from "../services/metrics.service";
4
+ export declare class AdminResolver {
5
+ private betterMetricsService;
6
+ constructor(betterMetricsService: BetterMetricsService);
7
+ chartMetric(ctx: RequestContext, args: {
8
+ input: ResolverInputTypes["ChartMetricInput"];
9
+ }): Promise<{
10
+ __typename: "ChartMetrics";
11
+ data: {
12
+ __typename: "ChartDataType";
13
+ type: import("../zeus").ChartMetricType;
14
+ title: string;
15
+ entries: {
16
+ __typename: "ChartEntry";
17
+ intervalTick: number;
18
+ value: number;
19
+ additionalData?: {
20
+ __typename: "ChartEntryAdditionalData";
21
+ id: string;
22
+ name: string;
23
+ quantity: number;
24
+ }[] | null | undefined;
25
+ }[];
26
+ }[];
27
+ }>;
28
+ orderSummaryMetric(ctx: RequestContext, args: {
29
+ input: ResolverInputTypes["OrderSummaryMetricInput"];
30
+ }): Promise<{
31
+ __typename: "OrderSummaryMetrics";
32
+ data: {
33
+ __typename: "OrderSummaryDataMetric";
34
+ currencyCode: import("../zeus").CurrencyCode;
35
+ total: number;
36
+ totalWithTax: number;
37
+ orderCount: number;
38
+ averageOrderValue: number;
39
+ averageOrderValueWithTax: number;
40
+ productCount: number;
41
+ };
42
+ }>;
43
+ additionalOrderStates(ctx: RequestContext): Promise<{
44
+ state: string;
45
+ selectedByDefault: boolean;
46
+ }[]>;
47
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.AdminResolver = void 0;
16
+ const graphql_1 = require("@nestjs/graphql");
17
+ const core_1 = require("@deenruv/core");
18
+ const metrics_service_1 = require("../services/metrics.service");
19
+ let AdminResolver = class AdminResolver {
20
+ constructor(betterMetricsService) {
21
+ this.betterMetricsService = betterMetricsService;
22
+ }
23
+ async chartMetric(ctx, args) {
24
+ return this.betterMetricsService.getChartMetrics(ctx, args.input);
25
+ }
26
+ async orderSummaryMetric(ctx, args) {
27
+ return this.betterMetricsService.getOrderSummaryMetric(ctx, args.input);
28
+ }
29
+ async additionalOrderStates(ctx) {
30
+ return this.betterMetricsService.additionalOrderStates(ctx);
31
+ }
32
+ };
33
+ exports.AdminResolver = AdminResolver;
34
+ __decorate([
35
+ (0, core_1.Allow)(core_1.Permission.Authenticated),
36
+ (0, graphql_1.Query)(),
37
+ __param(0, (0, core_1.Ctx)()),
38
+ __param(1, (0, graphql_1.Args)()),
39
+ __metadata("design:type", Function),
40
+ __metadata("design:paramtypes", [core_1.RequestContext, Object]),
41
+ __metadata("design:returntype", Promise)
42
+ ], AdminResolver.prototype, "chartMetric", null);
43
+ __decorate([
44
+ (0, core_1.Allow)(core_1.Permission.Authenticated),
45
+ (0, graphql_1.Query)(),
46
+ __param(0, (0, core_1.Ctx)()),
47
+ __param(1, (0, graphql_1.Args)()),
48
+ __metadata("design:type", Function),
49
+ __metadata("design:paramtypes", [core_1.RequestContext, Object]),
50
+ __metadata("design:returntype", Promise)
51
+ ], AdminResolver.prototype, "orderSummaryMetric", null);
52
+ __decorate([
53
+ (0, core_1.Allow)(core_1.Permission.Authenticated),
54
+ (0, graphql_1.Query)(),
55
+ __param(0, (0, core_1.Ctx)()),
56
+ __metadata("design:type", Function),
57
+ __metadata("design:paramtypes", [core_1.RequestContext]),
58
+ __metadata("design:returntype", Promise)
59
+ ], AdminResolver.prototype, "additionalOrderStates", null);
60
+ exports.AdminResolver = AdminResolver = __decorate([
61
+ (0, graphql_1.Resolver)(),
62
+ __metadata("design:paramtypes", [metrics_service_1.BetterMetricsService])
63
+ ], AdminResolver);
@@ -0,0 +1,30 @@
1
+ import { RequestContext, TransactionalConnection } from "@deenruv/core";
2
+ import { ChartMetricType, GraphQLTypes, MetricIntervalType, ResolverInputTypes } from "../zeus";
3
+ import { DashboardWidgetsPluginOptions, MetricResponse } from "../types";
4
+ export type MetricData = {
5
+ date: Date;
6
+ orders: MetricResponse[];
7
+ };
8
+ export declare class BetterMetricsService {
9
+ private connection;
10
+ private options?;
11
+ constructor(connection: TransactionalConnection, options?: DashboardWidgetsPluginOptions | undefined);
12
+ additionalOrderStates(ctx: RequestContext): Promise<{
13
+ state: string;
14
+ selectedByDefault: boolean;
15
+ }[]>;
16
+ refreshViews(ctx: RequestContext): Promise<void>;
17
+ getOrderSummaryMetric(ctx: RequestContext, { range, orderStates }: ResolverInputTypes["OrderSummaryMetricInput"]): Promise<GraphQLTypes["OrderSummaryMetrics"]>;
18
+ getChartMetrics(ctx: RequestContext, { range, types, interval, orderStates, net, }: ResolverInputTypes["ChartMetricInput"]): Promise<GraphQLTypes["ChartMetrics"]>;
19
+ loadChartData(ctx: RequestContext, { start, end, metricType, interval, orderStates, net, }: ResolverInputTypes["BetterMetricRangeInput"] & {
20
+ metricType: ChartMetricType;
21
+ interval: MetricIntervalType;
22
+ orderStates: string[];
23
+ net?: boolean | null;
24
+ }): Promise<{
25
+ response: any;
26
+ }>;
27
+ loadSummaryOrdersData(ctx: RequestContext, { start, end, orderStates, }: ResolverInputTypes["BetterMetricRangeInput"] & {
28
+ orderStates: string[];
29
+ }): Promise<GraphQLTypes["OrderSummaryDataMetric"]>;
30
+ }
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.BetterMetricsService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const core_1 = require("@deenruv/core");
18
+ const zeus_1 = require("../zeus");
19
+ const raw_sql_1 = require("../raw-sql");
20
+ const constants_1 = require("../constants");
21
+ const total_products_1 = require("../materialisedViewEntities/total_products");
22
+ const order_summary_1 = require("../materialisedViewEntities/order_summary");
23
+ const utils_1 = require("../utils");
24
+ const total_products_with_state_1 = require("../materialisedViewEntities/total_products_with_state");
25
+ const orders_summary_with_state_1 = require("../materialisedViewEntities/orders_summary_with_state");
26
+ const typeorm_1 = require("typeorm");
27
+ const DEFAULT_ORDER_STATES_ARRAY = [
28
+ "PaymentSettled",
29
+ "PartiallyShipped",
30
+ "Shipped",
31
+ "PartiallyDelivered",
32
+ "Delivered",
33
+ ];
34
+ const MAPPINGS = {
35
+ [zeus_1.ChartMetricType.OrderCount]: {
36
+ title: "order-count",
37
+ dailyQuery: raw_sql_1.ORDER_COUNT_DAILY_SELECT,
38
+ hourlyQuery: raw_sql_1.ORDER_COUNT_HOURLY_SELECT,
39
+ },
40
+ [zeus_1.ChartMetricType.OrderTotal]: {
41
+ title: "order-total",
42
+ dailyQuery: raw_sql_1.ORDER_TOTAL_DAILY_SELECT,
43
+ hourlyQuery: raw_sql_1.ORDER_TOTAL_HOURLY_SELECT,
44
+ },
45
+ [zeus_1.ChartMetricType.AverageOrderValue]: {
46
+ title: "average-order-value",
47
+ dailyQuery: raw_sql_1.ORDER_AVERAGE_DAILY_SELECT,
48
+ hourlyQuery: raw_sql_1.ORDER_AVERAGE_HOURLY_SELECT,
49
+ },
50
+ [zeus_1.ChartMetricType.OrderTotalProductsCount]: {
51
+ title: "order-products-count",
52
+ },
53
+ };
54
+ let BetterMetricsService = class BetterMetricsService {
55
+ constructor(connection, options) {
56
+ this.connection = connection;
57
+ this.options = options;
58
+ this.options = options;
59
+ }
60
+ async additionalOrderStates(ctx) {
61
+ var _a, _b;
62
+ return (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.additionalOrderStates) !== null && _b !== void 0 ? _b : [];
63
+ }
64
+ async refreshViews(ctx) {
65
+ await this.connection
66
+ .getRepository(ctx, order_summary_1.OrderSummaryViewEntity)
67
+ .query(`REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary_view_entity`);
68
+ await this.connection
69
+ .getRepository(ctx, orders_summary_with_state_1.OrderSummaryWithStateViewEntity)
70
+ .query(`REFRESH MATERIALIZED VIEW CONCURRENTLY order_summary_with_state_view_entity`);
71
+ await this.connection
72
+ .getRepository(ctx, total_products_1.TotalProductsViewEntity)
73
+ .query(`REFRESH MATERIALIZED VIEW CONCURRENTLY total_products_view_entity`);
74
+ await this.connection
75
+ .getRepository(ctx, total_products_with_state_1.TotalProductsWithStateViewEntity)
76
+ .query(`REFRESH MATERIALIZED VIEW CONCURRENTLY total_products_with_state_view_entity`);
77
+ }
78
+ async getOrderSummaryMetric(ctx, { range, orderStates }) {
79
+ const data = await this.loadSummaryOrdersData(ctx, Object.assign(Object.assign({}, range), { orderStates }));
80
+ return {
81
+ __typename: "OrderSummaryMetrics",
82
+ data,
83
+ };
84
+ }
85
+ async getChartMetrics(ctx, { range, types, interval, orderStates, net, }) {
86
+ var _a;
87
+ const data = await this.loadChartData(ctx, Object.assign(Object.assign({}, range), {
88
+ // for now bcs we are using only one type
89
+ metricType: types[0], interval,
90
+ orderStates,
91
+ net }));
92
+ const metrics = {
93
+ __typename: "ChartMetrics",
94
+ data: [],
95
+ };
96
+ for (const type of types) {
97
+ const entry = MAPPINGS[type];
98
+ const entries = [];
99
+ (_a = data.response) === null || _a === void 0 ? void 0 : _a.forEach((dataPerDay) => {
100
+ entries.push(Object.assign({ __typename: "ChartEntry" }, dataPerDay));
101
+ });
102
+ metrics.data.push({
103
+ __typename: "ChartDataType",
104
+ title: entry.title,
105
+ type,
106
+ entries: entries,
107
+ });
108
+ }
109
+ return metrics;
110
+ }
111
+ async loadChartData(ctx, { start, end, metricType, interval, orderStates, net, }) {
112
+ var _a;
113
+ let response;
114
+ const startDate = start.toISOString();
115
+ const endDate = end;
116
+ const shoulBeFromDefaultView = (0, utils_1.areArraysIdentical)(DEFAULT_ORDER_STATES_ARRAY, orderStates);
117
+ if (metricType === zeus_1.ChartMetricType.OrderTotalProductsCount) {
118
+ // sub query for product variant name translations with rank
119
+ // (if we have translation for choosen language we will take it first, if not, we will take one of rest languages)
120
+ const rankedTranslations = this.connection
121
+ .getRepository(ctx, core_1.ProductVariantTranslation)
122
+ .createQueryBuilder("pvt")
123
+ .select(raw_sql_1.RANKED_TRANSLATIONS_SELECT)
124
+ .setParameter("languageCode", ctx.languageCode);
125
+ // view query for total products count
126
+ const viewQb = this.connection
127
+ .getRepository(ctx, shoulBeFromDefaultView
128
+ ? total_products_1.TotalProductsViewEntity
129
+ : total_products_with_state_1.TotalProductsWithStateViewEntity)
130
+ .createQueryBuilder("tpv");
131
+ // here we are checking if we should return tick as modulo of hour or day
132
+ if (interval === zeus_1.MetricIntervalType.Hour) {
133
+ viewQb.select('extract(epoch from tpv.hour - :startDate)::integer / 3600 AS "intervalTick"');
134
+ }
135
+ else {
136
+ viewQb.select('extract(epoch from tpv.hour - :startDate)::integer / 86400 + 1 AS "intervalTick"');
137
+ }
138
+ viewQb
139
+ .setParameter("startDate", startDate)
140
+ .addSelect(raw_sql_1.TOTAL_PRODUCT_VIEW_SELECT)
141
+ // join with ranked translations
142
+ .innerJoin(`(${rankedTranslations.getQuery()})`, "rt", 'rt."baseId" = tpv.productVariantId AND rt.rank = 1')
143
+ .setParameters(rankedTranslations.getParameters())
144
+ .where("tpv.hour::timestamptz >= :startDate::timestamptz", {
145
+ startDate,
146
+ })
147
+ .andWhere('tpv."channelId" = :channelId', {
148
+ channelId: ctx.channel.id,
149
+ });
150
+ if (endDate) {
151
+ viewQb.andWhere("tpv.hour::timestamptz <= :endDate::timestamptz", {
152
+ endDate: endDate.toISOString(),
153
+ });
154
+ }
155
+ if (!shoulBeFromDefaultView && orderStates.length) {
156
+ viewQb.andWhere({ state: (0, typeorm_1.In)(orderStates) });
157
+ }
158
+ viewQb
159
+ .groupBy('"intervalTick", tpv."productVariantId", tpv."channelId", rt.name, rt."languageCode" ')
160
+ .orderBy('"intervalTick"', "ASC");
161
+ const dbResponse = await viewQb.getRawMany();
162
+ const reducedRes = dbResponse.reduce((acc, curr) => {
163
+ if (acc[curr.intervalTick]) {
164
+ acc[curr.intervalTick].value += +curr.orderPlacedQuantitySum;
165
+ acc[curr.intervalTick].additionaldata.push({
166
+ name: curr.name,
167
+ id: curr.productVariantId,
168
+ quantity: +curr.orderPlacedQuantitySum,
169
+ });
170
+ }
171
+ else {
172
+ acc[curr.intervalTick] = {
173
+ value: +curr.orderPlacedQuantitySum,
174
+ additionaldata: [
175
+ {
176
+ name: curr.name,
177
+ id: curr.productVariantId,
178
+ quantity: +curr.orderPlacedQuantitySum,
179
+ },
180
+ ],
181
+ };
182
+ }
183
+ return acc;
184
+ }, {});
185
+ const mappedResponse = (_a = Object.entries(reducedRes)) === null || _a === void 0 ? void 0 : _a.map(([key, r]) => ({
186
+ intervalTick: key,
187
+ value: +(+r.value.toFixed(2)),
188
+ additionalData: r.additionaldata,
189
+ }));
190
+ response = mappedResponse;
191
+ }
192
+ else {
193
+ const isDaily = interval === zeus_1.MetricIntervalType.Day;
194
+ const viewQb = this.connection
195
+ .getRepository(ctx, shoulBeFromDefaultView
196
+ ? order_summary_1.OrderSummaryViewEntity
197
+ : orders_summary_with_state_1.OrderSummaryWithStateViewEntity)
198
+ .createQueryBuilder("osv")
199
+ .select(MAPPINGS[metricType][isDaily ? "dailyQuery" : "hourlyQuery"])
200
+ .where("osv.hour::timestamptz >= :startDate::timestamptz", {
201
+ startDate,
202
+ })
203
+ .andWhere('osv."channelId" = :channelId', {
204
+ channelId: ctx.channel.id,
205
+ });
206
+ if (endDate) {
207
+ viewQb.andWhere("osv.hour::timestamptz <= :endDate::timestamptz", {
208
+ endDate: endDate.toISOString(),
209
+ });
210
+ }
211
+ if (!shoulBeFromDefaultView && orderStates.length) {
212
+ viewQb.andWhere({ state: (0, typeorm_1.In)(orderStates) });
213
+ }
214
+ viewQb.groupBy('"intervalTick"').orderBy('"intervalTick"', "ASC");
215
+ const viewResponse = await viewQb.getRawMany();
216
+ const mappedResponse = viewResponse.map((r) => {
217
+ const value = !net && "valueWithTax" in r ? +r.valueWithTax : +r.value;
218
+ return {
219
+ intervalTick: r.intervalTick,
220
+ value: +("ordercount" in r ? value / +r.ordercount : value).toFixed(2),
221
+ };
222
+ });
223
+ response = mappedResponse;
224
+ }
225
+ return { response };
226
+ }
227
+ async loadSummaryOrdersData(ctx, { start, end, orderStates, }) {
228
+ const shoulBeFromDefaultView = (0, utils_1.areArraysIdentical)(DEFAULT_ORDER_STATES_ARRAY, orderStates);
229
+ const ordersSummaryViewRepo = this.connection.getRepository(ctx, shoulBeFromDefaultView
230
+ ? order_summary_1.OrderSummaryViewEntity
231
+ : orders_summary_with_state_1.OrderSummaryWithStateViewEntity);
232
+ const startDate = start.toISOString();
233
+ const endDate = end;
234
+ const viewQb = ordersSummaryViewRepo
235
+ .createQueryBuilder("osv")
236
+ .select('SUM(osv."orderCount")', "orderCount")
237
+ .addSelect('SUM(osv."totalWithTax")', "totalWithTax")
238
+ .addSelect("SUM(osv.total)", "total")
239
+ .addSelect('SUM(osv."productPlacedCount")', "productCount")
240
+ .where("osv.hour::timestamptz >= :startDate::timestamptz", {
241
+ startDate,
242
+ })
243
+ .andWhere('osv."channelId" = :channelId', {
244
+ channelId: ctx.channel.id,
245
+ });
246
+ if (endDate) {
247
+ viewQb.andWhere("osv.hour::timestamptz <= :endDate::timestamptz", {
248
+ endDate: endDate.toISOString(),
249
+ });
250
+ }
251
+ if (!shoulBeFromDefaultView && orderStates.length) {
252
+ viewQb.andWhere({ state: (0, typeorm_1.In)(orderStates) });
253
+ }
254
+ const viewResponse = await viewQb.getRawOne();
255
+ return {
256
+ currencyCode: ctx.currencyCode,
257
+ __typename: "OrderSummaryDataMetric",
258
+ averageOrderValue: +(+(+(viewResponse === null || viewResponse === void 0 ? void 0 : viewResponse.total) / +(viewResponse === null || viewResponse === void 0 ? void 0 : viewResponse.orderCount)) || 0).toFixed(2),
259
+ averageOrderValueWithTax: +(+(+(viewResponse === null || viewResponse === void 0 ? void 0 : viewResponse.totalWithTax) / +(viewResponse === null || viewResponse === void 0 ? void 0 : viewResponse.orderCount)) || 0).toFixed(2),
260
+ orderCount: +(viewResponse === null || viewResponse === void 0 ? void 0 : viewResponse.orderCount) || 0,
261
+ total: +(+(viewResponse === null || viewResponse === void 0 ? void 0 : viewResponse.total) || 0).toFixed(2),
262
+ totalWithTax: +(+(viewResponse === null || viewResponse === void 0 ? void 0 : viewResponse.totalWithTax) || 0).toFixed(2),
263
+ productCount: +(viewResponse === null || viewResponse === void 0 ? void 0 : viewResponse.productCount) || 0,
264
+ };
265
+ }
266
+ };
267
+ exports.BetterMetricsService = BetterMetricsService;
268
+ exports.BetterMetricsService = BetterMetricsService = __decorate([
269
+ (0, common_1.Injectable)(),
270
+ __param(1, (0, common_1.Inject)(constants_1.PLUGIN_INIT_OPTIONS)),
271
+ __metadata("design:paramtypes", [core_1.TransactionalConnection, Object])
272
+ ], BetterMetricsService);
@@ -0,0 +1,20 @@
1
+ export type MetricResponse = {
2
+ orderId: string;
3
+ orderPlacedAt: string;
4
+ totalWithTax: number;
5
+ orderProducts: {
6
+ id: number;
7
+ name: string;
8
+ quantity: number;
9
+ }[];
10
+ overallQuantity: number;
11
+ };
12
+ export interface DashboardWidgetsPluginOptions {
13
+ cacheTime?: number;
14
+ /** This field is populated right now at Samarite and Minko storefronts */
15
+ discountByCustomField?: boolean;
16
+ additionalOrderStates?: Array<{
17
+ state: string;
18
+ selectedByDefault: boolean;
19
+ }>;
20
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export declare const areArraysIdentical: (arr1: string[], arr2: string[]) => boolean;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.areArraysIdentical = void 0;
4
+ const areArraysIdentical = (arr1, arr2) => {
5
+ if (arr1.length !== arr2.length) {
6
+ return false;
7
+ }
8
+ const sortedArr1 = [...arr1].sort();
9
+ const sortedArr2 = [...arr2].sort();
10
+ return sortedArr1.every((value, index) => value === sortedArr2[index]);
11
+ };
12
+ exports.areArraysIdentical = areArraysIdentical;
@@ -0,0 +1,6 @@
1
+ export declare const AllTypesProps: Record<string, any>;
2
+ export declare const ReturnTypes: Record<string, any>;
3
+ export declare const Ops: {
4
+ query: "Query";
5
+ mutation: "Mutation";
6
+ };