@blackcode_sa/metaestetics-api 1.12.6 → 1.12.8
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/admin/index.d.mts +51 -33
- package/dist/admin/index.d.ts +51 -33
- package/dist/index.d.mts +149 -34
- package/dist/index.d.ts +149 -34
- package/dist/index.js +1073 -924
- package/dist/index.mjs +833 -677
- package/package.json +1 -2
- package/src/services/clinic/billing-transactions.service.ts +217 -0
- package/src/services/clinic/clinic-group.service.ts +99 -102
- package/src/services/clinic/index.ts +5 -4
- package/src/types/clinic/preferences.types.ts +115 -97
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blackcode_sa/metaestetics-api",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.12.
|
|
4
|
+
"version": "1.12.8",
|
|
5
5
|
"description": "Firebase authentication service with anonymous upgrade support",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.mjs",
|
|
@@ -95,7 +95,6 @@
|
|
|
95
95
|
"typescript": "^5.7.3"
|
|
96
96
|
},
|
|
97
97
|
"dependencies": {
|
|
98
|
-
"@blackcode_sa/metaestetics-api": "^1.12.5",
|
|
99
98
|
"axios": "^1.8.3",
|
|
100
99
|
"expo-server-sdk": "^3.13.0",
|
|
101
100
|
"firebase-admin": "^13.0.2",
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collection,
|
|
3
|
+
getDocs,
|
|
4
|
+
query,
|
|
5
|
+
orderBy,
|
|
6
|
+
limit,
|
|
7
|
+
startAfter,
|
|
8
|
+
where,
|
|
9
|
+
DocumentSnapshot,
|
|
10
|
+
QueryConstraint,
|
|
11
|
+
} from 'firebase/firestore';
|
|
12
|
+
import { BaseService } from '../base.service';
|
|
13
|
+
import {
|
|
14
|
+
BillingTransaction,
|
|
15
|
+
BillingTransactionType,
|
|
16
|
+
CLINIC_GROUPS_COLLECTION,
|
|
17
|
+
} from '../../types/clinic';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Service for managing billing transactions
|
|
21
|
+
* Provides read-only access to billing transaction history
|
|
22
|
+
*/
|
|
23
|
+
export class BillingTransactionsService extends BaseService {
|
|
24
|
+
private readonly BILLING_TRANSACTIONS_COLLECTION = 'billingTransactions';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get billing transactions for a clinic group with pagination
|
|
28
|
+
* @param clinicGroupId - The clinic group ID
|
|
29
|
+
* @param options - Query options
|
|
30
|
+
* @returns Promise with transactions and pagination info
|
|
31
|
+
*/
|
|
32
|
+
async getBillingTransactions(
|
|
33
|
+
clinicGroupId: string,
|
|
34
|
+
options: {
|
|
35
|
+
limit?: number;
|
|
36
|
+
startAfter?: DocumentSnapshot;
|
|
37
|
+
transactionType?: BillingTransactionType;
|
|
38
|
+
} = {},
|
|
39
|
+
): Promise<{
|
|
40
|
+
transactions: BillingTransaction[];
|
|
41
|
+
lastDoc: DocumentSnapshot | null;
|
|
42
|
+
hasMore: boolean;
|
|
43
|
+
}> {
|
|
44
|
+
try {
|
|
45
|
+
const { limit: queryLimit = 50, startAfter: startAfterDoc, transactionType } = options;
|
|
46
|
+
|
|
47
|
+
// Build query constraints
|
|
48
|
+
const constraints: QueryConstraint[] = [];
|
|
49
|
+
|
|
50
|
+
// Add transaction type filter if specified
|
|
51
|
+
if (transactionType) {
|
|
52
|
+
constraints.push(where('type', '==', transactionType));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Add ordering
|
|
56
|
+
constraints.push(orderBy('timestamp', 'desc')); // Most recent first
|
|
57
|
+
|
|
58
|
+
// Add pagination
|
|
59
|
+
if (startAfterDoc) {
|
|
60
|
+
constraints.push(startAfter(startAfterDoc));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
constraints.push(limit(queryLimit + 1)); // Get one extra to check if there are more
|
|
64
|
+
|
|
65
|
+
// Execute query
|
|
66
|
+
const transactionsRef = collection(
|
|
67
|
+
this.db,
|
|
68
|
+
CLINIC_GROUPS_COLLECTION,
|
|
69
|
+
clinicGroupId,
|
|
70
|
+
this.BILLING_TRANSACTIONS_COLLECTION,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const q = query(transactionsRef, ...constraints);
|
|
74
|
+
const querySnapshot = await getDocs(q);
|
|
75
|
+
|
|
76
|
+
// Process results
|
|
77
|
+
const docs = querySnapshot.docs;
|
|
78
|
+
const hasMore = docs.length > queryLimit;
|
|
79
|
+
const transactions = docs.slice(0, queryLimit).map(doc => ({
|
|
80
|
+
id: doc.id,
|
|
81
|
+
...doc.data(),
|
|
82
|
+
})) as BillingTransaction[];
|
|
83
|
+
|
|
84
|
+
const lastDoc = transactions.length > 0 ? docs[transactions.length - 1] : null;
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
transactions,
|
|
88
|
+
lastDoc,
|
|
89
|
+
hasMore,
|
|
90
|
+
};
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error(
|
|
93
|
+
`Error fetching billing transactions for clinic group ${clinicGroupId}:`,
|
|
94
|
+
error,
|
|
95
|
+
);
|
|
96
|
+
throw new Error(
|
|
97
|
+
`Failed to fetch billing transactions: ${
|
|
98
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
99
|
+
}`,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get recent billing transactions (last 10)
|
|
106
|
+
* @param clinicGroupId - The clinic group ID
|
|
107
|
+
* @returns Promise with recent transactions
|
|
108
|
+
*/
|
|
109
|
+
async getRecentBillingTransactions(clinicGroupId: string): Promise<BillingTransaction[]> {
|
|
110
|
+
const result = await this.getBillingTransactions(clinicGroupId, { limit: 10 });
|
|
111
|
+
return result.transactions;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get billing transactions by type
|
|
116
|
+
* @param clinicGroupId - The clinic group ID
|
|
117
|
+
* @param transactionType - The transaction type to filter by
|
|
118
|
+
* @param options - Additional query options
|
|
119
|
+
* @returns Promise with filtered transactions
|
|
120
|
+
*/
|
|
121
|
+
async getBillingTransactionsByType(
|
|
122
|
+
clinicGroupId: string,
|
|
123
|
+
transactionType: BillingTransactionType,
|
|
124
|
+
options: {
|
|
125
|
+
limit?: number;
|
|
126
|
+
startAfter?: DocumentSnapshot;
|
|
127
|
+
} = {},
|
|
128
|
+
): Promise<{
|
|
129
|
+
transactions: BillingTransaction[];
|
|
130
|
+
lastDoc: DocumentSnapshot | null;
|
|
131
|
+
hasMore: boolean;
|
|
132
|
+
}> {
|
|
133
|
+
return this.getBillingTransactions(clinicGroupId, {
|
|
134
|
+
...options,
|
|
135
|
+
transactionType,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Get subscription-related transactions only
|
|
141
|
+
* @param clinicGroupId - The clinic group ID
|
|
142
|
+
* @param options - Query options
|
|
143
|
+
* @returns Promise with subscription transactions
|
|
144
|
+
*/
|
|
145
|
+
async getSubscriptionTransactions(
|
|
146
|
+
clinicGroupId: string,
|
|
147
|
+
options: {
|
|
148
|
+
limit?: number;
|
|
149
|
+
startAfter?: DocumentSnapshot;
|
|
150
|
+
} = {},
|
|
151
|
+
): Promise<{
|
|
152
|
+
transactions: BillingTransaction[];
|
|
153
|
+
lastDoc: DocumentSnapshot | null;
|
|
154
|
+
hasMore: boolean;
|
|
155
|
+
}> {
|
|
156
|
+
try {
|
|
157
|
+
const { limit: queryLimit = 50, startAfter: startAfterDoc } = options;
|
|
158
|
+
|
|
159
|
+
// Subscription-related transaction types
|
|
160
|
+
const subscriptionTypes = [
|
|
161
|
+
BillingTransactionType.SUBSCRIPTION_CREATED,
|
|
162
|
+
BillingTransactionType.SUBSCRIPTION_ACTIVATED,
|
|
163
|
+
BillingTransactionType.SUBSCRIPTION_RENEWED,
|
|
164
|
+
BillingTransactionType.SUBSCRIPTION_UPDATED,
|
|
165
|
+
BillingTransactionType.SUBSCRIPTION_CANCELED,
|
|
166
|
+
BillingTransactionType.SUBSCRIPTION_REACTIVATED,
|
|
167
|
+
BillingTransactionType.SUBSCRIPTION_DELETED,
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
const constraints: QueryConstraint[] = [
|
|
171
|
+
where('type', 'in', subscriptionTypes),
|
|
172
|
+
orderBy('timestamp', 'desc'),
|
|
173
|
+
];
|
|
174
|
+
|
|
175
|
+
if (startAfterDoc) {
|
|
176
|
+
constraints.push(startAfter(startAfterDoc));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
constraints.push(limit(queryLimit + 1));
|
|
180
|
+
|
|
181
|
+
const transactionsRef = collection(
|
|
182
|
+
this.db,
|
|
183
|
+
CLINIC_GROUPS_COLLECTION,
|
|
184
|
+
clinicGroupId,
|
|
185
|
+
this.BILLING_TRANSACTIONS_COLLECTION,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const q = query(transactionsRef, ...constraints);
|
|
189
|
+
const querySnapshot = await getDocs(q);
|
|
190
|
+
|
|
191
|
+
const docs = querySnapshot.docs;
|
|
192
|
+
const hasMore = docs.length > queryLimit;
|
|
193
|
+
const transactions = docs.slice(0, queryLimit).map(doc => ({
|
|
194
|
+
id: doc.id,
|
|
195
|
+
...doc.data(),
|
|
196
|
+
})) as BillingTransaction[];
|
|
197
|
+
|
|
198
|
+
const lastDoc = transactions.length > 0 ? docs[transactions.length - 1] : null;
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
transactions,
|
|
202
|
+
lastDoc,
|
|
203
|
+
hasMore,
|
|
204
|
+
};
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error(
|
|
207
|
+
`Error fetching subscription transactions for clinic group ${clinicGroupId}:`,
|
|
208
|
+
error,
|
|
209
|
+
);
|
|
210
|
+
throw new Error(
|
|
211
|
+
`Failed to fetch subscription transactions: ${
|
|
212
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
213
|
+
}`,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
Timestamp,
|
|
12
12
|
serverTimestamp,
|
|
13
13
|
FieldValue,
|
|
14
|
-
} from
|
|
15
|
-
import { BaseService } from
|
|
14
|
+
} from 'firebase/firestore';
|
|
15
|
+
import { BaseService } from '../base.service';
|
|
16
16
|
import {
|
|
17
17
|
ClinicGroup,
|
|
18
18
|
CreateClinicGroupData,
|
|
@@ -22,31 +22,28 @@ import {
|
|
|
22
22
|
CreateAdminTokenData,
|
|
23
23
|
ClinicGroupSetupData,
|
|
24
24
|
UpdateClinicGroupData,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
} from
|
|
32
|
-
import { z } from
|
|
33
|
-
import { Auth } from
|
|
34
|
-
import { Firestore } from
|
|
35
|
-
import { FirebaseApp } from
|
|
36
|
-
import * as ClinicGroupUtils from
|
|
37
|
-
import { uploadPhoto } from
|
|
25
|
+
BillingTransaction,
|
|
26
|
+
BillingTransactionType,
|
|
27
|
+
} from '../../types/clinic';
|
|
28
|
+
import { ClinicAdminService } from './clinic-admin.service';
|
|
29
|
+
import { BillingTransactionsService } from './billing-transactions.service';
|
|
30
|
+
import { geohashForLocation } from 'geofire-common';
|
|
31
|
+
import { clinicGroupSchema, createClinicGroupSchema } from '../../validations/clinic.schema';
|
|
32
|
+
import { z } from 'zod';
|
|
33
|
+
import { Auth } from 'firebase/auth';
|
|
34
|
+
import { Firestore } from 'firebase/firestore';
|
|
35
|
+
import { FirebaseApp } from 'firebase/app';
|
|
36
|
+
import * as ClinicGroupUtils from './utils/clinic-group.utils';
|
|
37
|
+
import { uploadPhoto } from './utils/photos.utils';
|
|
38
38
|
|
|
39
39
|
export class ClinicGroupService extends BaseService {
|
|
40
40
|
private clinicAdminService: ClinicAdminService;
|
|
41
|
+
private billingTransactionsService: BillingTransactionsService;
|
|
41
42
|
|
|
42
|
-
constructor(
|
|
43
|
-
db: Firestore,
|
|
44
|
-
auth: Auth,
|
|
45
|
-
app: FirebaseApp,
|
|
46
|
-
clinicAdminService: ClinicAdminService
|
|
47
|
-
) {
|
|
43
|
+
constructor(db: Firestore, auth: Auth, app: FirebaseApp, clinicAdminService: ClinicAdminService) {
|
|
48
44
|
super(db, auth, app);
|
|
49
45
|
this.clinicAdminService = clinicAdminService;
|
|
46
|
+
this.billingTransactionsService = new BillingTransactionsService(db, auth, app);
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
/**
|
|
@@ -55,7 +52,7 @@ export class ClinicGroupService extends BaseService {
|
|
|
55
52
|
async createClinicGroup(
|
|
56
53
|
data: CreateClinicGroupData,
|
|
57
54
|
ownerId: string,
|
|
58
|
-
isDefault: boolean = false
|
|
55
|
+
isDefault: boolean = false,
|
|
59
56
|
): Promise<ClinicGroup> {
|
|
60
57
|
return ClinicGroupUtils.createClinicGroup(
|
|
61
58
|
this.db,
|
|
@@ -63,7 +60,7 @@ export class ClinicGroupService extends BaseService {
|
|
|
63
60
|
ownerId,
|
|
64
61
|
isDefault,
|
|
65
62
|
this.clinicAdminService,
|
|
66
|
-
this.app
|
|
63
|
+
this.app,
|
|
67
64
|
);
|
|
68
65
|
}
|
|
69
66
|
|
|
@@ -84,10 +81,7 @@ export class ClinicGroupService extends BaseService {
|
|
|
84
81
|
/**
|
|
85
82
|
* Ažurira grupaciju klinika
|
|
86
83
|
*/
|
|
87
|
-
async updateClinicGroup(
|
|
88
|
-
groupId: string,
|
|
89
|
-
data: Partial<ClinicGroup>
|
|
90
|
-
): Promise<ClinicGroup> {
|
|
84
|
+
async updateClinicGroup(groupId: string, data: Partial<ClinicGroup>): Promise<ClinicGroup> {
|
|
91
85
|
return ClinicGroupUtils.updateClinicGroup(this.db, groupId, data, this.app);
|
|
92
86
|
}
|
|
93
87
|
|
|
@@ -95,24 +89,14 @@ export class ClinicGroupService extends BaseService {
|
|
|
95
89
|
* Dodaje admina u grupaciju
|
|
96
90
|
*/
|
|
97
91
|
async addAdminToGroup(groupId: string, adminId: string): Promise<void> {
|
|
98
|
-
return ClinicGroupUtils.addAdminToGroup(
|
|
99
|
-
this.db,
|
|
100
|
-
groupId,
|
|
101
|
-
adminId,
|
|
102
|
-
this.app
|
|
103
|
-
);
|
|
92
|
+
return ClinicGroupUtils.addAdminToGroup(this.db, groupId, adminId, this.app);
|
|
104
93
|
}
|
|
105
94
|
|
|
106
95
|
/**
|
|
107
96
|
* Uklanja admina iz grupacije
|
|
108
97
|
*/
|
|
109
98
|
async removeAdminFromGroup(groupId: string, adminId: string): Promise<void> {
|
|
110
|
-
return ClinicGroupUtils.removeAdminFromGroup(
|
|
111
|
-
this.db,
|
|
112
|
-
groupId,
|
|
113
|
-
adminId,
|
|
114
|
-
this.app
|
|
115
|
-
);
|
|
99
|
+
return ClinicGroupUtils.removeAdminFromGroup(this.db, groupId, adminId, this.app);
|
|
116
100
|
}
|
|
117
101
|
|
|
118
102
|
/**
|
|
@@ -129,32 +113,29 @@ export class ClinicGroupService extends BaseService {
|
|
|
129
113
|
* @param setupData - The setup data for the clinic group
|
|
130
114
|
* @returns The updated clinic group
|
|
131
115
|
*/
|
|
132
|
-
async setupClinicGroup(
|
|
133
|
-
groupId
|
|
134
|
-
setupData: ClinicGroupSetupData
|
|
135
|
-
): Promise<ClinicGroup> {
|
|
136
|
-
console.log("[CLINIC_GROUP] Setting up clinic group", { groupId });
|
|
116
|
+
async setupClinicGroup(groupId: string, setupData: ClinicGroupSetupData): Promise<ClinicGroup> {
|
|
117
|
+
console.log('[CLINIC_GROUP] Setting up clinic group', { groupId });
|
|
137
118
|
|
|
138
119
|
// Get the clinic group
|
|
139
120
|
const clinicGroup = await this.getClinicGroup(groupId);
|
|
140
121
|
if (!clinicGroup) {
|
|
141
|
-
console.error(
|
|
122
|
+
console.error('[CLINIC_GROUP] Clinic group not found', { groupId });
|
|
142
123
|
throw new Error(`Clinic group with ID ${groupId} not found`);
|
|
143
124
|
}
|
|
144
125
|
|
|
145
126
|
// Process logo if it's a data URL
|
|
146
127
|
let logoUrl = setupData.logo;
|
|
147
|
-
if (logoUrl && typeof logoUrl ===
|
|
148
|
-
console.log(
|
|
128
|
+
if (logoUrl && typeof logoUrl === 'string' && logoUrl.startsWith('data:')) {
|
|
129
|
+
console.log('[CLINIC_GROUP] Processing logo in setupClinicGroup');
|
|
149
130
|
try {
|
|
150
131
|
const uploadedLogoUrl = await uploadPhoto(
|
|
151
132
|
logoUrl,
|
|
152
|
-
|
|
133
|
+
'clinic-groups',
|
|
153
134
|
groupId,
|
|
154
|
-
|
|
155
|
-
this.app
|
|
135
|
+
'logo',
|
|
136
|
+
this.app,
|
|
156
137
|
);
|
|
157
|
-
console.log(
|
|
138
|
+
console.log('[CLINIC_GROUP] Logo processed in setupClinicGroup', {
|
|
158
139
|
uploadedLogoUrl,
|
|
159
140
|
});
|
|
160
141
|
|
|
@@ -163,10 +144,7 @@ export class ClinicGroupService extends BaseService {
|
|
|
163
144
|
logoUrl = uploadedLogoUrl;
|
|
164
145
|
}
|
|
165
146
|
} catch (error) {
|
|
166
|
-
console.error(
|
|
167
|
-
"[CLINIC_GROUP] Error processing logo in setupClinicGroup:",
|
|
168
|
-
error
|
|
169
|
-
);
|
|
147
|
+
console.error('[CLINIC_GROUP] Error processing logo in setupClinicGroup:', error);
|
|
170
148
|
// Continue with update even if logo upload fails
|
|
171
149
|
}
|
|
172
150
|
}
|
|
@@ -182,7 +160,7 @@ export class ClinicGroupService extends BaseService {
|
|
|
182
160
|
businessIdentificationNumber: setupData.businessIdentificationNumber,
|
|
183
161
|
};
|
|
184
162
|
|
|
185
|
-
console.log(
|
|
163
|
+
console.log('[CLINIC_GROUP] Updating clinic group with setup data');
|
|
186
164
|
|
|
187
165
|
// Update the clinic group
|
|
188
166
|
return this.updateClinicGroup(groupId, updateData);
|
|
@@ -194,64 +172,30 @@ export class ClinicGroupService extends BaseService {
|
|
|
194
172
|
async createAdminToken(
|
|
195
173
|
groupId: string,
|
|
196
174
|
creatorAdminId: string,
|
|
197
|
-
data?: CreateAdminTokenData
|
|
175
|
+
data?: CreateAdminTokenData,
|
|
198
176
|
): Promise<AdminToken> {
|
|
199
|
-
return ClinicGroupUtils.createAdminToken(
|
|
200
|
-
this.db,
|
|
201
|
-
groupId,
|
|
202
|
-
creatorAdminId,
|
|
203
|
-
this.app,
|
|
204
|
-
data
|
|
205
|
-
);
|
|
177
|
+
return ClinicGroupUtils.createAdminToken(this.db, groupId, creatorAdminId, this.app, data);
|
|
206
178
|
}
|
|
207
179
|
|
|
208
180
|
/**
|
|
209
181
|
* Verifikuje i koristi admin token
|
|
210
182
|
*/
|
|
211
|
-
async verifyAndUseAdminToken(
|
|
212
|
-
groupId
|
|
213
|
-
token: string,
|
|
214
|
-
userRef: string
|
|
215
|
-
): Promise<boolean> {
|
|
216
|
-
return ClinicGroupUtils.verifyAndUseAdminToken(
|
|
217
|
-
this.db,
|
|
218
|
-
groupId,
|
|
219
|
-
token,
|
|
220
|
-
userRef,
|
|
221
|
-
this.app
|
|
222
|
-
);
|
|
183
|
+
async verifyAndUseAdminToken(groupId: string, token: string, userRef: string): Promise<boolean> {
|
|
184
|
+
return ClinicGroupUtils.verifyAndUseAdminToken(this.db, groupId, token, userRef, this.app);
|
|
223
185
|
}
|
|
224
186
|
|
|
225
187
|
/**
|
|
226
188
|
* Briše admin token
|
|
227
189
|
*/
|
|
228
|
-
async deleteAdminToken(
|
|
229
|
-
groupId
|
|
230
|
-
tokenId: string,
|
|
231
|
-
adminId: string
|
|
232
|
-
): Promise<void> {
|
|
233
|
-
return ClinicGroupUtils.deleteAdminToken(
|
|
234
|
-
this.db,
|
|
235
|
-
groupId,
|
|
236
|
-
tokenId,
|
|
237
|
-
adminId,
|
|
238
|
-
this.app
|
|
239
|
-
);
|
|
190
|
+
async deleteAdminToken(groupId: string, tokenId: string, adminId: string): Promise<void> {
|
|
191
|
+
return ClinicGroupUtils.deleteAdminToken(this.db, groupId, tokenId, adminId, this.app);
|
|
240
192
|
}
|
|
241
193
|
|
|
242
194
|
/**
|
|
243
195
|
* Dohvata aktivne admin tokene
|
|
244
196
|
*/
|
|
245
|
-
async getActiveAdminTokens(
|
|
246
|
-
groupId
|
|
247
|
-
adminId: string
|
|
248
|
-
): Promise<AdminToken[]> {
|
|
249
|
-
return ClinicGroupUtils.getActiveAdminTokens(
|
|
250
|
-
this.db,
|
|
251
|
-
groupId,
|
|
252
|
-
adminId,
|
|
253
|
-
this.app
|
|
254
|
-
);
|
|
197
|
+
async getActiveAdminTokens(groupId: string, adminId: string): Promise<AdminToken[]> {
|
|
198
|
+
return ClinicGroupUtils.getActiveAdminTokens(this.db, groupId, adminId, this.app);
|
|
255
199
|
}
|
|
256
200
|
|
|
257
201
|
// TODO: Add a method to get all admin tokens for a clinic group (not just active ones)
|
|
@@ -274,9 +218,9 @@ export class ClinicGroupService extends BaseService {
|
|
|
274
218
|
onboardingData: {
|
|
275
219
|
completed?: boolean;
|
|
276
220
|
step?: number;
|
|
277
|
-
}
|
|
221
|
+
},
|
|
278
222
|
): Promise<ClinicGroup> {
|
|
279
|
-
console.log(
|
|
223
|
+
console.log('[CLINIC_GROUP] Updating onboarding status', {
|
|
280
224
|
groupId,
|
|
281
225
|
onboardingData,
|
|
282
226
|
});
|
|
@@ -294,7 +238,7 @@ export class ClinicGroupService extends BaseService {
|
|
|
294
238
|
* @returns The updated clinic group
|
|
295
239
|
*/
|
|
296
240
|
async setOnboardingStep(groupId: string, step: number): Promise<ClinicGroup> {
|
|
297
|
-
console.log(
|
|
241
|
+
console.log('[CLINIC_GROUP] Setting onboarding step', { groupId, step });
|
|
298
242
|
|
|
299
243
|
return this.setOnboarding(groupId, { step, completed: false });
|
|
300
244
|
}
|
|
@@ -306,8 +250,61 @@ export class ClinicGroupService extends BaseService {
|
|
|
306
250
|
* @returns The updated clinic group
|
|
307
251
|
*/
|
|
308
252
|
async completeOnboarding(groupId: string): Promise<ClinicGroup> {
|
|
309
|
-
console.log(
|
|
253
|
+
console.log('[CLINIC_GROUP] Completing onboarding', { groupId });
|
|
310
254
|
|
|
311
255
|
return this.setOnboarding(groupId, { completed: true });
|
|
312
256
|
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Get billing transactions for a clinic group
|
|
260
|
+
*
|
|
261
|
+
* @param groupId - The clinic group ID
|
|
262
|
+
* @param options - Query options for pagination and filtering
|
|
263
|
+
* @returns Promise with billing transactions and pagination info
|
|
264
|
+
*/
|
|
265
|
+
async getBillingTransactions(
|
|
266
|
+
groupId: string,
|
|
267
|
+
options: {
|
|
268
|
+
limit?: number;
|
|
269
|
+
startAfter?: any;
|
|
270
|
+
transactionType?: BillingTransactionType;
|
|
271
|
+
} = {},
|
|
272
|
+
): Promise<{
|
|
273
|
+
transactions: BillingTransaction[];
|
|
274
|
+
lastDoc: any;
|
|
275
|
+
hasMore: boolean;
|
|
276
|
+
}> {
|
|
277
|
+
return this.billingTransactionsService.getBillingTransactions(groupId, options);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Get recent billing transactions for a clinic group (last 10)
|
|
282
|
+
*
|
|
283
|
+
* @param groupId - The clinic group ID
|
|
284
|
+
* @returns Promise with recent billing transactions
|
|
285
|
+
*/
|
|
286
|
+
async getRecentBillingTransactions(groupId: string): Promise<BillingTransaction[]> {
|
|
287
|
+
return this.billingTransactionsService.getRecentBillingTransactions(groupId);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Get subscription-related billing transactions for a clinic group
|
|
292
|
+
*
|
|
293
|
+
* @param groupId - The clinic group ID
|
|
294
|
+
* @param options - Query options for pagination
|
|
295
|
+
* @returns Promise with subscription transactions and pagination info
|
|
296
|
+
*/
|
|
297
|
+
async getSubscriptionTransactions(
|
|
298
|
+
groupId: string,
|
|
299
|
+
options: {
|
|
300
|
+
limit?: number;
|
|
301
|
+
startAfter?: any;
|
|
302
|
+
} = {},
|
|
303
|
+
): Promise<{
|
|
304
|
+
transactions: BillingTransaction[];
|
|
305
|
+
lastDoc: any;
|
|
306
|
+
hasMore: boolean;
|
|
307
|
+
}> {
|
|
308
|
+
return this.billingTransactionsService.getSubscriptionTransactions(groupId, options);
|
|
309
|
+
}
|
|
313
310
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
1
|
+
export * from './clinic.service';
|
|
2
|
+
export * from './clinic-admin.service';
|
|
3
|
+
export * from './clinic-group.service';
|
|
4
|
+
export * from './practitioner-invite.service';
|
|
5
|
+
export * from './billing-transactions.service';
|