@gymspace/sdk 1.7.4 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.mts +350 -13
- package/dist/index.d.ts +350 -13
- package/dist/index.js +289 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +285 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
- package/src/client.ts +5 -6
- package/src/errors.ts +3 -5
- package/src/models/activities.ts +12 -3
- package/src/models/bulk-messaging.ts +26 -7
- package/src/models/contracts.ts +18 -0
- package/src/models/credits.ts +79 -0
- package/src/models/index.ts +3 -0
- package/src/models/membership-plans.ts +4 -0
- package/src/models/pricing-packages.ts +65 -0
- package/src/models/promo-codes.ts +97 -0
- package/src/resources/credits.ts +203 -0
- package/src/resources/index.ts +3 -0
- package/src/resources/pricing-packages.ts +72 -0
- package/src/resources/promo-codes.ts +76 -0
- package/src/sdk.ts +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gymspace/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "GymSpace TypeScript SDK for API integration",
|
|
5
5
|
"author": "GymSpace Team",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,9 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@gymspace/shared": "^1.0.0",
|
|
43
|
-
"
|
|
43
|
+
"@types/jsonwebtoken": "^9.0.10",
|
|
44
|
+
"axios": ">=1.0.0",
|
|
45
|
+
"jsonwebtoken": "^9.0.2",
|
|
44
46
|
"zod": "^3.25.76"
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
package/src/client.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import axios, {
|
|
2
|
+
AxiosError,
|
|
2
3
|
AxiosInstance,
|
|
3
4
|
AxiosRequestConfig,
|
|
4
|
-
AxiosError,
|
|
5
5
|
InternalAxiosRequestConfig,
|
|
6
|
-
AxiosRequestHeaders,
|
|
7
6
|
} from 'axios';
|
|
8
|
-
import { GymSpaceConfig, RequestOptions } from './types';
|
|
9
7
|
import {
|
|
10
|
-
GymSpaceError,
|
|
11
8
|
AuthenticationError,
|
|
12
9
|
AuthorizationError,
|
|
10
|
+
GymSpaceError,
|
|
11
|
+
NetworkError,
|
|
13
12
|
NotFoundError,
|
|
14
13
|
ValidationError,
|
|
15
|
-
NetworkError,
|
|
16
14
|
} from './errors';
|
|
15
|
+
import { GymSpaceConfig, RequestOptions } from './types';
|
|
17
16
|
|
|
18
17
|
export class ApiClient {
|
|
19
18
|
private axiosInstance: AxiosInstance;
|
|
@@ -74,7 +73,7 @@ export class ApiClient {
|
|
|
74
73
|
config.headers['Authorization'] = `Bearer ${this.config.apiKey}`;
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
// Add refresh token header
|
|
76
|
+
// Add refresh token header if available (not skipped)
|
|
78
77
|
if (this.refreshToken && this.config.apiKey && config.headers && !skipAuth) {
|
|
79
78
|
config.headers['X-Refresh-Token'] = this.refreshToken;
|
|
80
79
|
}
|
package/src/errors.ts
CHANGED
|
@@ -3,7 +3,7 @@ export class GymSpaceError extends Error {
|
|
|
3
3
|
message: string,
|
|
4
4
|
public statusCode?: number,
|
|
5
5
|
public code?: string,
|
|
6
|
-
public details?: any
|
|
6
|
+
public details?: any,
|
|
7
7
|
) {
|
|
8
8
|
super(message);
|
|
9
9
|
this.name = 'GymSpaceError';
|
|
@@ -26,9 +26,7 @@ export class AuthorizationError extends GymSpaceError {
|
|
|
26
26
|
|
|
27
27
|
export class NotFoundError extends GymSpaceError {
|
|
28
28
|
constructor(resource: string, id?: string) {
|
|
29
|
-
const message = id
|
|
30
|
-
? `${resource} with id ${id} not found`
|
|
31
|
-
: `${resource} not found`;
|
|
29
|
+
const message = id ? `${resource} with id ${id} not found` : `${resource} not found`;
|
|
32
30
|
super(message, 404, 'NOT_FOUND');
|
|
33
31
|
this.name = 'NotFoundError';
|
|
34
32
|
}
|
|
@@ -46,4 +44,4 @@ export class NetworkError extends GymSpaceError {
|
|
|
46
44
|
super(message, 0, 'NETWORK_ERROR');
|
|
47
45
|
this.name = 'NetworkError';
|
|
48
46
|
}
|
|
49
|
-
}
|
|
47
|
+
}
|
package/src/models/activities.ts
CHANGED
|
@@ -64,14 +64,22 @@ export interface SearchActivitiesParams {
|
|
|
64
64
|
isActive?: boolean;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
export interface BulkMessageDto {
|
|
68
|
+
type: 'text' | 'image';
|
|
69
|
+
content: string;
|
|
70
|
+
mediaRef?: 'file' | 'asset';
|
|
71
|
+
caption?: string;
|
|
72
|
+
order: number;
|
|
73
|
+
}
|
|
74
|
+
|
|
67
75
|
export interface CreateActivityNotificationDto {
|
|
68
|
-
|
|
76
|
+
messages: BulkMessageDto[];
|
|
69
77
|
advanceTimeMinutes: number;
|
|
70
78
|
isActive?: boolean;
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
export interface UpdateActivityNotificationDto {
|
|
74
|
-
|
|
82
|
+
messages?: BulkMessageDto[];
|
|
75
83
|
advanceTimeMinutes?: number;
|
|
76
84
|
isActive?: boolean;
|
|
77
85
|
}
|
|
@@ -82,7 +90,8 @@ export interface ActivityNotificationDto {
|
|
|
82
90
|
templateId: string;
|
|
83
91
|
advanceTimeMinutes: number;
|
|
84
92
|
isActive: boolean;
|
|
85
|
-
|
|
93
|
+
messages: BulkMessageDto[];
|
|
94
|
+
template?: {
|
|
86
95
|
id: string;
|
|
87
96
|
name: string;
|
|
88
97
|
message: string;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type { BulkMessage } from '@gymspace/shared';
|
|
2
|
+
export type { BulkMessage };
|
|
3
|
+
|
|
1
4
|
export interface BulkTemplate {
|
|
2
5
|
id: string;
|
|
3
6
|
gymId: string;
|
|
4
7
|
name: string;
|
|
5
|
-
|
|
8
|
+
messages: BulkMessage[];
|
|
6
9
|
description?: string;
|
|
7
10
|
tags: string[];
|
|
8
11
|
isActive: boolean;
|
|
@@ -16,7 +19,7 @@ export interface BulkTemplate {
|
|
|
16
19
|
|
|
17
20
|
export interface CreateBulkTemplateDto {
|
|
18
21
|
name: string;
|
|
19
|
-
|
|
22
|
+
messages: BulkMessage[];
|
|
20
23
|
description?: string;
|
|
21
24
|
tags?: string[];
|
|
22
25
|
isActive?: boolean;
|
|
@@ -24,7 +27,7 @@ export interface CreateBulkTemplateDto {
|
|
|
24
27
|
|
|
25
28
|
export interface UpdateBulkTemplateDto {
|
|
26
29
|
name?: string;
|
|
27
|
-
|
|
30
|
+
messages?: BulkMessage[];
|
|
28
31
|
description?: string;
|
|
29
32
|
tags?: string[];
|
|
30
33
|
isActive?: boolean;
|
|
@@ -37,8 +40,10 @@ export type { BulkMessageVariable } from '@gymspace/shared';
|
|
|
37
40
|
|
|
38
41
|
export interface SendBulkMessagesDto {
|
|
39
42
|
templateId?: string;
|
|
40
|
-
|
|
43
|
+
messages?: BulkMessage[];
|
|
41
44
|
clientIds: string[];
|
|
45
|
+
variableContext?: string;
|
|
46
|
+
scheduledAt?: string; // ISO 8601 datetime string for scheduled messages
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
export interface RejectedClientDto {
|
|
@@ -64,14 +69,27 @@ export interface BulkMessageLogDto {
|
|
|
64
69
|
clientId: string;
|
|
65
70
|
clientName: string;
|
|
66
71
|
phoneNumber: string;
|
|
67
|
-
message
|
|
68
|
-
|
|
72
|
+
message?: string;
|
|
73
|
+
messages?: Array<{
|
|
74
|
+
type: 'text' | 'image';
|
|
75
|
+
order: number;
|
|
76
|
+
status: 'pending' | 'sent' | 'failed';
|
|
77
|
+
preview: string;
|
|
78
|
+
caption?: string;
|
|
79
|
+
externalMessageId?: string;
|
|
80
|
+
error?: string;
|
|
81
|
+
sentAt?: string;
|
|
82
|
+
}>;
|
|
83
|
+
status?: 'pending' | 'queued' | 'sent' | 'delivered' | 'failed';
|
|
84
|
+
overallStatus?: 'pending' | 'sending' | 'sent' | 'partial' | 'failed';
|
|
69
85
|
sentAt?: string;
|
|
70
86
|
deliveredAt?: string;
|
|
71
87
|
failedAt?: string;
|
|
72
88
|
failureReason?: string;
|
|
73
89
|
retryCount: number;
|
|
74
|
-
timestamp
|
|
90
|
+
timestamp?: string;
|
|
91
|
+
createdAt?: string;
|
|
92
|
+
updatedAt?: string;
|
|
75
93
|
}
|
|
76
94
|
|
|
77
95
|
export interface GetBulkLogsQueryDto {
|
|
@@ -85,6 +103,7 @@ export interface BulkLogsResponseDto {
|
|
|
85
103
|
delivered: number;
|
|
86
104
|
failed: number;
|
|
87
105
|
pending: number;
|
|
106
|
+
partial?: number;
|
|
88
107
|
logs: BulkMessageLogDto[];
|
|
89
108
|
isComplete: boolean;
|
|
90
109
|
}
|
package/src/models/contracts.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { PaginationQueryDto } from '../types';
|
|
|
4
4
|
export interface CreateContractDto {
|
|
5
5
|
gymClientId: string;
|
|
6
6
|
gymMembershipPlanId: string;
|
|
7
|
+
pricingPackageId?: string;
|
|
8
|
+
promoCode?: string;
|
|
7
9
|
paymentMethodId: string;
|
|
8
10
|
startDate: string;
|
|
9
11
|
discountPercentage?: number;
|
|
@@ -16,6 +18,8 @@ export interface RenewContractDto {
|
|
|
16
18
|
startDate?: string;
|
|
17
19
|
discountPercentage?: number;
|
|
18
20
|
customPrice?: number;
|
|
21
|
+
pricingPackageId?: string;
|
|
22
|
+
promoCode?: string;
|
|
19
23
|
// Payment method ID (UUID) - uses the existing payment method if not provided
|
|
20
24
|
paymentMethodId?: string;
|
|
21
25
|
applyAtEndOfContract?: boolean;
|
|
@@ -66,6 +70,7 @@ export interface Contract {
|
|
|
66
70
|
contractNumber: string;
|
|
67
71
|
gymClientId: string;
|
|
68
72
|
gymMembershipPlanId: string;
|
|
73
|
+
pricingPackageId?: string | null;
|
|
69
74
|
paymentMethodId?: string;
|
|
70
75
|
parentId?: string; // Reference to parent contract for renewals
|
|
71
76
|
startDate: string;
|
|
@@ -77,6 +82,9 @@ export interface Contract {
|
|
|
77
82
|
currency: string;
|
|
78
83
|
discountPercentage?: number | null;
|
|
79
84
|
discountAmount?: string | null;
|
|
85
|
+
promoCode?: string | null;
|
|
86
|
+
promoCodeSnapshot?: Record<string, any> | null;
|
|
87
|
+
promoDiscount?: string | null;
|
|
80
88
|
paymentFrequency: string;
|
|
81
89
|
notes?: string | null;
|
|
82
90
|
termsAndConditions?: string | null;
|
|
@@ -122,6 +130,16 @@ export interface Contract {
|
|
|
122
130
|
assetsIds?: string[];
|
|
123
131
|
status?: string;
|
|
124
132
|
};
|
|
133
|
+
pricingPackage?: {
|
|
134
|
+
id: string;
|
|
135
|
+
planId: string;
|
|
136
|
+
name: string;
|
|
137
|
+
price: number;
|
|
138
|
+
durationMonths?: number | null;
|
|
139
|
+
durationDays?: number | null;
|
|
140
|
+
isDefault: boolean;
|
|
141
|
+
isActive: boolean;
|
|
142
|
+
};
|
|
125
143
|
paymentMethod?: {
|
|
126
144
|
id: string;
|
|
127
145
|
organizationId: string;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Feature Types
|
|
2
|
+
export enum FeatureType {
|
|
3
|
+
AI_GENERATION = 'ai_generation',
|
|
4
|
+
BULK_WHATSAPP = 'bulk_whatsapp',
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// Credit Account Models
|
|
8
|
+
export interface CreditAccount {
|
|
9
|
+
id: string;
|
|
10
|
+
organizationId: string;
|
|
11
|
+
balance: number;
|
|
12
|
+
monthlyAllowance: number;
|
|
13
|
+
lastResetAt: string;
|
|
14
|
+
createdAt: string;
|
|
15
|
+
updatedAt: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface CreditAccountWithOrgName {
|
|
19
|
+
id: string;
|
|
20
|
+
organizationId: string;
|
|
21
|
+
organizationName: string;
|
|
22
|
+
balance: number;
|
|
23
|
+
monthlyAllowance: number;
|
|
24
|
+
lastResetAt: string;
|
|
25
|
+
createdAt: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Credit Transaction Models
|
|
29
|
+
export interface CreditTransaction {
|
|
30
|
+
id: string;
|
|
31
|
+
accountId: string;
|
|
32
|
+
featureType: FeatureType;
|
|
33
|
+
quantity: number;
|
|
34
|
+
description?: string;
|
|
35
|
+
metadata?: Record<string, any>;
|
|
36
|
+
createdAt: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Credit Adjustment Models
|
|
40
|
+
export interface CreditAdjustment {
|
|
41
|
+
adjustment: number;
|
|
42
|
+
reason: string;
|
|
43
|
+
notes?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface CreditAdjustmentResponse {
|
|
47
|
+
previousBalance: number;
|
|
48
|
+
newBalance: number;
|
|
49
|
+
adjusted: number;
|
|
50
|
+
transactionId: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Credit Usage Report Models
|
|
54
|
+
export interface CreditUsageReport {
|
|
55
|
+
balance: number;
|
|
56
|
+
monthlyAllowance: number;
|
|
57
|
+
usedThisMonth: number;
|
|
58
|
+
remaining: number;
|
|
59
|
+
lastReset: string;
|
|
60
|
+
usagePercentage: number;
|
|
61
|
+
transactionCount: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface CreditUsageReportQuery {
|
|
65
|
+
startDate?: string;
|
|
66
|
+
endDate?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Credit Stats (for existing endpoint)
|
|
70
|
+
export interface CreditStats {
|
|
71
|
+
balance: number;
|
|
72
|
+
monthlyAllowance: number;
|
|
73
|
+
usedThisMonth: number;
|
|
74
|
+
lastReset: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// DTOs for existing endpoints (already exported in bulk-messaging)
|
|
78
|
+
// export interface GenerateAIMessageDto { ... }
|
|
79
|
+
// export interface SendBulkMessagesDto { ... }
|
package/src/models/index.ts
CHANGED
|
@@ -33,6 +33,9 @@ export * from './tags';
|
|
|
33
33
|
export * from './commissions';
|
|
34
34
|
export * from './catalog';
|
|
35
35
|
export * from './messages';
|
|
36
|
+
export * from './credits';
|
|
37
|
+
export * from './pricing-packages';
|
|
38
|
+
export * from './promo-codes';
|
|
36
39
|
|
|
37
40
|
export interface ApiResponse<T> {
|
|
38
41
|
data: T;
|
|
@@ -57,6 +57,9 @@ export interface MembershipPlan {
|
|
|
57
57
|
assetsIds?: string[];
|
|
58
58
|
createdAt: string;
|
|
59
59
|
updatedAt: string;
|
|
60
|
+
_count?: {
|
|
61
|
+
pricingPackages: number;
|
|
62
|
+
};
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
export interface MembershipPlanStats {
|
|
@@ -126,4 +129,5 @@ export interface MembershipPlanStats {
|
|
|
126
129
|
|
|
127
130
|
export interface GetMembershipPlansParams {
|
|
128
131
|
activeOnly?: boolean;
|
|
132
|
+
includeCounts?: boolean;
|
|
129
133
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Request DTOs
|
|
2
|
+
export interface CreatePricingPackageDto {
|
|
3
|
+
name: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
durationMonths?: number;
|
|
6
|
+
durationDays?: number;
|
|
7
|
+
price: number;
|
|
8
|
+
currency?: string;
|
|
9
|
+
displayOrder?: number;
|
|
10
|
+
isActive?: boolean;
|
|
11
|
+
isDefault?: boolean;
|
|
12
|
+
metadata?: Record<string, any>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface UpdatePricingPackageDto {
|
|
16
|
+
name?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
durationMonths?: number;
|
|
19
|
+
durationDays?: number;
|
|
20
|
+
price?: number;
|
|
21
|
+
currency?: string;
|
|
22
|
+
displayOrder?: number;
|
|
23
|
+
isActive?: boolean;
|
|
24
|
+
isDefault?: boolean;
|
|
25
|
+
metadata?: Record<string, any>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SearchPricingPackagesParams {
|
|
29
|
+
membershipPlanId?: string;
|
|
30
|
+
isActive?: boolean;
|
|
31
|
+
isDefault?: boolean;
|
|
32
|
+
page?: number;
|
|
33
|
+
limit?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Response types
|
|
37
|
+
export interface PricingPackage {
|
|
38
|
+
id: string;
|
|
39
|
+
gymId: string;
|
|
40
|
+
membershipPlanId: string;
|
|
41
|
+
name: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
durationMonths?: number;
|
|
44
|
+
durationDays?: number;
|
|
45
|
+
price: number;
|
|
46
|
+
currency: string;
|
|
47
|
+
displayOrder: number;
|
|
48
|
+
isActive: boolean;
|
|
49
|
+
isDefault: boolean;
|
|
50
|
+
metadata?: Record<string, any>;
|
|
51
|
+
createdAt: string;
|
|
52
|
+
updatedAt: string;
|
|
53
|
+
deletedAt?: string;
|
|
54
|
+
|
|
55
|
+
// Relations
|
|
56
|
+
membershipPlan?: {
|
|
57
|
+
id: string;
|
|
58
|
+
name: string;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Counters
|
|
62
|
+
_count?: {
|
|
63
|
+
contracts: number;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export enum DiscountType {
|
|
2
|
+
PERCENTAGE = 'PERCENTAGE',
|
|
3
|
+
FIXED_AMOUNT = 'FIXED_AMOUNT',
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// Request DTOs
|
|
7
|
+
export interface CreatePromoCodeDto {
|
|
8
|
+
code: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
discountType: DiscountType;
|
|
11
|
+
discountValue: number;
|
|
12
|
+
validFrom: string;
|
|
13
|
+
validUntil: string;
|
|
14
|
+
maxUses?: number;
|
|
15
|
+
minPurchaseAmount?: number;
|
|
16
|
+
applicableTo?: {
|
|
17
|
+
planIds?: string[];
|
|
18
|
+
packageIds?: string[];
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface UpdatePromoCodeDto {
|
|
23
|
+
description?: string;
|
|
24
|
+
discountType?: DiscountType;
|
|
25
|
+
discountValue?: number;
|
|
26
|
+
validFrom?: string;
|
|
27
|
+
validUntil?: string;
|
|
28
|
+
maxUses?: number;
|
|
29
|
+
minPurchaseAmount?: number;
|
|
30
|
+
applicableTo?: {
|
|
31
|
+
planIds?: string[];
|
|
32
|
+
packageIds?: string[];
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface SearchPromoCodesParams {
|
|
37
|
+
isActive?: boolean;
|
|
38
|
+
code?: string;
|
|
39
|
+
status?: 'active' | 'expired' | 'exhausted';
|
|
40
|
+
page?: number;
|
|
41
|
+
limit?: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ValidatePromoCodeDto {
|
|
45
|
+
code: string;
|
|
46
|
+
pricingPackageId: string;
|
|
47
|
+
packagePrice: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ValidatePromoCodeResponseDto {
|
|
51
|
+
valid: boolean;
|
|
52
|
+
id?: string;
|
|
53
|
+
code?: string;
|
|
54
|
+
discountType?: string;
|
|
55
|
+
discountValue?: number;
|
|
56
|
+
discountAmount?: number;
|
|
57
|
+
finalAmount?: number;
|
|
58
|
+
error?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Response types
|
|
62
|
+
export interface PromoCode {
|
|
63
|
+
id: string;
|
|
64
|
+
gymId: string;
|
|
65
|
+
code: string;
|
|
66
|
+
description?: string;
|
|
67
|
+
discountType: DiscountType;
|
|
68
|
+
discountValue: number;
|
|
69
|
+
validFrom: string;
|
|
70
|
+
validUntil: string;
|
|
71
|
+
maxUses?: number;
|
|
72
|
+
currentUses: number;
|
|
73
|
+
minPurchaseAmount?: number;
|
|
74
|
+
applicableTo?: {
|
|
75
|
+
planIds?: string[];
|
|
76
|
+
packageIds?: string[];
|
|
77
|
+
};
|
|
78
|
+
isActive: boolean;
|
|
79
|
+
createdAt: string;
|
|
80
|
+
updatedAt: string;
|
|
81
|
+
deletedAt?: string;
|
|
82
|
+
|
|
83
|
+
// Counters
|
|
84
|
+
_count?: {
|
|
85
|
+
contracts: number;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface PromoCodeAnalytics {
|
|
90
|
+
totalUses: number;
|
|
91
|
+
remainingUses?: number;
|
|
92
|
+
totalDiscount: number;
|
|
93
|
+
averageDiscount: number;
|
|
94
|
+
contractCount: number;
|
|
95
|
+
isActive: boolean;
|
|
96
|
+
daysUntilExpiration?: number;
|
|
97
|
+
}
|