@loka-sms/core-integration-be 0.0.1 → 0.0.3
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/README.md +15 -7
- package/dist/core-integration.service.d.ts +30 -1
- package/dist/core-integration.service.js +221 -6
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# @loka-sms/core-integration-be
|
|
1
|
+
# @loka-sms/core-integration-be
|
|
2
2
|
|
|
3
|
-
NestJS helper package untuk backend modul
|
|
3
|
+
NestJS helper package untuk backend modul OMNISCHOOL yang perlu mengakses data Core via service-to-service auth (`X-App-ID` + `X-App-Secret`).
|
|
4
4
|
|
|
5
5
|
Package ini cocok untuk **worker/background job/service sync**, bukan untuk forwarding token user.
|
|
6
6
|
|
|
@@ -28,9 +28,9 @@ npm install @loka-sms/core-integration-be
|
|
|
28
28
|
|
|
29
29
|
| Variabel | Wajib | Fallback | Keterangan |
|
|
30
30
|
|---|---|---|---|
|
|
31
|
-
| `CORE_SERVICE_URL` |
|
|
32
|
-
| `CORE_APP_ID` |
|
|
33
|
-
| `CORE_APP_SECRET` |
|
|
31
|
+
| `CORE_SERVICE_URL` | ✅ | — | Base URL Gateway, contoh: `http://localhost:3000/api` |
|
|
32
|
+
| `CORE_APP_ID` | ✅ | `APP_ID` | Application ID yang terdaftar di Core |
|
|
33
|
+
| `CORE_APP_SECRET` | ✅ | `APP_SECRET` | Application secret (plain, bukan bcrypt) |
|
|
34
34
|
|
|
35
35
|
Contoh `.env`:
|
|
36
36
|
|
|
@@ -89,7 +89,7 @@ export class RaporSyncService {
|
|
|
89
89
|
|
|
90
90
|
async generate(schoolId: string) {
|
|
91
91
|
const students = await this.core.getStudents(schoolId, { status: 'active' });
|
|
92
|
-
const classes = await this.core.getClasses(schoolId);
|
|
92
|
+
const classes = await this.core.getClasses(schoolId, { grade: 7 });
|
|
93
93
|
return { students, classes };
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -107,10 +107,12 @@ Package selalu mengirim `X-App-ID`, `X-App-Secret`, dan `X-School-ID`. Tidak per
|
|
|
107
107
|
| `findStudentByEmail(email, schoolId)` | `GET /api/students?q=...&limit=1` |
|
|
108
108
|
| `getParentChildrenByUserId(parentUserId, schoolId)` | `GET /api/parents/by-user/:id/children` |
|
|
109
109
|
| `getParentChildIdsByUserId(parentUserId, schoolId)` | `GET /api/parents/by-user/:id/children` |
|
|
110
|
+
| `getParentChildUserIdsByUserId(parentUserId, schoolId)` | `GET /api/parents/by-user/:id/children` |
|
|
110
111
|
| `resolveParentStudentScope(parentUserId, schoolId, requestedStudentId?)` | `GET /api/parents/by-user/:id/children` |
|
|
112
|
+
| `resolveParentStudentUserScope(parentUserId, schoolId, requestedStudentUserId?)` | `GET /api/parents/by-user/:id/children` |
|
|
111
113
|
| `getTeachers(schoolId)` | `GET /api/teachers` |
|
|
112
114
|
| `getTeacher(teacherId, schoolId)` | `GET /api/teachers/:id` |
|
|
113
|
-
| `getClasses(schoolId)` | `GET /api/classes` |
|
|
115
|
+
| `getClasses(schoolId, params)` | `GET /api/classes` |
|
|
114
116
|
| `getSubjects(schoolId, params)` | `GET /api/subjects` |
|
|
115
117
|
| `getCurriculums(schoolId, params)` | `GET /api/curriculum` |
|
|
116
118
|
| `getAcademicCalendar(schoolId, params)` | `GET /api/academic-calendar` |
|
|
@@ -138,6 +140,12 @@ await this.core.post('notifications', schoolId, {
|
|
|
138
140
|
|
|
139
141
|
Path tidak perlu diawali `/api` atau `/api/v1`.
|
|
140
142
|
|
|
143
|
+
## Catatan Identity Siswa
|
|
144
|
+
|
|
145
|
+
- `getParentChildIdsByUserId()` dan `resolveParentStudentScope()` mengembalikan **Core student profile id** (`students.id`).
|
|
146
|
+
- `getParentChildUserIdsByUserId()` dan `resolveParentStudentUserScope()` mengembalikan **Core user id siswa** (`students.user_id` / `userId`). Gunakan ini untuk modul yang menyimpan relasi berdasarkan user id, misalnya LMS enrollment `studentUserId`.
|
|
147
|
+
- `getClasses(schoolId, params)` mendukung filter Core seperti `{ grade: 7, academic_year: '2025/2026' }`.
|
|
148
|
+
|
|
141
149
|
Benar:
|
|
142
150
|
```ts
|
|
143
151
|
this.core.get('students', schoolId)
|
|
@@ -14,6 +14,12 @@ export declare class CoreIntegrationService {
|
|
|
14
14
|
private getHeaders;
|
|
15
15
|
private makeUrl;
|
|
16
16
|
private extractStudentId;
|
|
17
|
+
private extractStudentUserId;
|
|
18
|
+
private unwrapRecord;
|
|
19
|
+
private extractUserId;
|
|
20
|
+
private extractEntityId;
|
|
21
|
+
private matchByUserId;
|
|
22
|
+
private assertTenantScope;
|
|
17
23
|
get<T = any>(path: string, schoolId?: string, options?: CoreRequestOptions): Promise<T>;
|
|
18
24
|
post<T = any>(path: string, schoolId: string | undefined, body?: unknown, options?: CoreRequestOptions): Promise<T>;
|
|
19
25
|
put<T = any>(path: string, schoolId: string | undefined, body?: unknown, options?: CoreRequestOptions): Promise<T>;
|
|
@@ -21,15 +27,38 @@ export declare class CoreIntegrationService {
|
|
|
21
27
|
delete<T = any>(path: string, schoolId?: string, options?: CoreRequestOptions): Promise<T>;
|
|
22
28
|
getParentChildrenByUserId(parentUserId: string, schoolId: string): Promise<any[]>;
|
|
23
29
|
getParentChildIdsByUserId(parentUserId: string, schoolId: string): Promise<string[]>;
|
|
30
|
+
getParentChildUserIdsByUserId(parentUserId: string, schoolId: string): Promise<string[]>;
|
|
31
|
+
resolveParentStudentUserScope(parentUserId: string, schoolId: string, requestedStudentUserId?: string): Promise<string[]>;
|
|
24
32
|
resolveParentStudentScope(parentUserId: string, schoolId: string, requestedStudentId?: string): Promise<string[]>;
|
|
25
33
|
getStudents(schoolId: string, params?: Record<string, unknown>): Promise<any[]>;
|
|
26
34
|
getStudentsByClass(classId: string, schoolId: string): Promise<any[]>;
|
|
35
|
+
getUser(userId: string, schoolId: string): Promise<any>;
|
|
27
36
|
getStudent(studentId: string, schoolId: string): Promise<any>;
|
|
37
|
+
getStudentByUserId(userId: string, schoolId: string): Promise<any>;
|
|
38
|
+
resolveStudentUserIdToStudentId(userId: string, schoolId: string): Promise<string | null>;
|
|
28
39
|
findStudentByEmail(email: string, schoolId: string): Promise<any>;
|
|
29
40
|
getTeacher(teacherId: string, schoolId: string): Promise<any>;
|
|
30
|
-
|
|
41
|
+
getTeacherByUserId(userId: string, schoolId: string): Promise<any>;
|
|
42
|
+
resolveTeacherUserIdToTeacherId(userId: string, schoolId: string): Promise<string | null>;
|
|
43
|
+
reconcileAcademicData(schoolId: string, academicYear?: string): Promise<{
|
|
44
|
+
teachers: any[];
|
|
45
|
+
classes: any[];
|
|
46
|
+
assignments: any[];
|
|
47
|
+
}>;
|
|
48
|
+
getTeacherAssignments(teacherId: string, schoolId: string, academicYear?: string): Promise<any[]>;
|
|
49
|
+
getClass(classId: string, schoolId: string): Promise<any>;
|
|
50
|
+
getClasses(schoolId: string, params?: Record<string, unknown>): Promise<any[]>;
|
|
31
51
|
getTeachers(schoolId: string): Promise<any[]>;
|
|
32
52
|
getSubjects(schoolId: string, params?: Record<string, unknown>): Promise<any[]>;
|
|
53
|
+
getSubject(subjectId: string, schoolId: string): Promise<any>;
|
|
54
|
+
getRoom(roomId: string, schoolId: string): Promise<any>;
|
|
55
|
+
getTimeSlots(schoolId: string): Promise<any[]>;
|
|
56
|
+
getActiveAcademicYear(schoolId: string): Promise<any | null>;
|
|
57
|
+
getActiveSemester(schoolId: string): Promise<any | null>;
|
|
58
|
+
getAcademicYear(yearId: string, schoolId: string): Promise<any | null>;
|
|
59
|
+
getSemester(semesterId: string, schoolId: string): Promise<any | null>;
|
|
60
|
+
getTeachingSchedule(scheduleId: string, schoolId: string): Promise<any | null>;
|
|
61
|
+
findTeachingSchedules(schoolId: string, params?: Record<string, unknown>): Promise<any[]>;
|
|
33
62
|
getCurriculums(schoolId: string, params?: Record<string, unknown>): Promise<any[]>;
|
|
34
63
|
getAcademicCalendar(schoolId: string, params?: Record<string, unknown>): Promise<any[]>;
|
|
35
64
|
getRooms(schoolId: string, params?: Record<string, unknown>): Promise<any[]>;
|
|
@@ -59,6 +59,34 @@ let CoreIntegrationService = CoreIntegrationService_1 = class CoreIntegrationSer
|
|
|
59
59
|
extractStudentId(child) {
|
|
60
60
|
return child?.student_id || child?.student?.id || child?.studentUserId || child?.id || null;
|
|
61
61
|
}
|
|
62
|
+
extractStudentUserId(child) {
|
|
63
|
+
return child?.student_user_id || child?.studentUserId || child?.student?.userId || child?.student?.user_id || child?.student?.user?.id || child?.userId || child?.user_id || null;
|
|
64
|
+
}
|
|
65
|
+
unwrapRecord(data) {
|
|
66
|
+
return data?.data || data;
|
|
67
|
+
}
|
|
68
|
+
extractUserId(entity) {
|
|
69
|
+
return entity?.userId || entity?.user_id || entity?.user?.id || null;
|
|
70
|
+
}
|
|
71
|
+
extractEntityId(entity) {
|
|
72
|
+
return entity?.id || null;
|
|
73
|
+
}
|
|
74
|
+
matchByUserId(items, userId) {
|
|
75
|
+
for (const item of items) {
|
|
76
|
+
if (item?.userId === userId)
|
|
77
|
+
return item;
|
|
78
|
+
if (item?.user_id === userId)
|
|
79
|
+
return item;
|
|
80
|
+
if (item?.user?.id === userId)
|
|
81
|
+
return item;
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
assertTenantScope(schoolId, contextLabel) {
|
|
86
|
+
if (!schoolId) {
|
|
87
|
+
throw new Error(`${contextLabel}: schoolId (X-School-ID) is required for non-super_admin operations`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
62
90
|
async get(path, schoolId, options = {}) {
|
|
63
91
|
const { headers, ...requestOptions } = options;
|
|
64
92
|
const res = await (0, rxjs_1.firstValueFrom)(this.httpService.get(this.makeUrl(path), {
|
|
@@ -118,6 +146,25 @@ let CoreIntegrationService = CoreIntegrationService_1 = class CoreIntegrationSer
|
|
|
118
146
|
.map((child) => this.extractStudentId(child))
|
|
119
147
|
.filter((studentId) => !!studentId);
|
|
120
148
|
}
|
|
149
|
+
async getParentChildUserIdsByUserId(parentUserId, schoolId) {
|
|
150
|
+
const children = await this.getParentChildrenByUserId(parentUserId, schoolId);
|
|
151
|
+
return children
|
|
152
|
+
.map((child) => this.extractStudentUserId(child))
|
|
153
|
+
.filter((studentUserId) => !!studentUserId);
|
|
154
|
+
}
|
|
155
|
+
async resolveParentStudentUserScope(parentUserId, schoolId, requestedStudentUserId) {
|
|
156
|
+
const childUserIds = await this.getParentChildUserIdsByUserId(parentUserId, schoolId);
|
|
157
|
+
if (childUserIds.length === 0) {
|
|
158
|
+
throw new common_1.ForbiddenException('Parent has no linked children with user accounts in this school');
|
|
159
|
+
}
|
|
160
|
+
if (!requestedStudentUserId) {
|
|
161
|
+
return childUserIds;
|
|
162
|
+
}
|
|
163
|
+
if (!childUserIds.includes(requestedStudentUserId)) {
|
|
164
|
+
throw new common_1.ForbiddenException('Child user is not linked to this parent');
|
|
165
|
+
}
|
|
166
|
+
return [requestedStudentUserId];
|
|
167
|
+
}
|
|
121
168
|
async resolveParentStudentScope(parentUserId, schoolId, requestedStudentId) {
|
|
122
169
|
const childIds = await this.getParentChildIdsByUserId(parentUserId, schoolId);
|
|
123
170
|
if (childIds.length === 0) {
|
|
@@ -134,7 +181,8 @@ let CoreIntegrationService = CoreIntegrationService_1 = class CoreIntegrationSer
|
|
|
134
181
|
async getStudents(schoolId, params = {}) {
|
|
135
182
|
try {
|
|
136
183
|
const data = await this.get('students', schoolId, { params });
|
|
137
|
-
|
|
184
|
+
const body = data?.data || data || {};
|
|
185
|
+
return body?.data || body?.students || body || [];
|
|
138
186
|
}
|
|
139
187
|
catch (error) {
|
|
140
188
|
if (error.response?.status === 404) {
|
|
@@ -147,15 +195,37 @@ let CoreIntegrationService = CoreIntegrationService_1 = class CoreIntegrationSer
|
|
|
147
195
|
async getStudentsByClass(classId, schoolId) {
|
|
148
196
|
return this.getStudents(schoolId, { class_id: classId, status: 'active' });
|
|
149
197
|
}
|
|
198
|
+
async getUser(userId, schoolId) {
|
|
199
|
+
try {
|
|
200
|
+
return this.unwrapRecord(await this.get(`users/${userId}`, schoolId));
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
this.logger.warn(`Failed to fetch user ${userId}: ${error.message}`);
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
150
207
|
async getStudent(studentId, schoolId) {
|
|
151
208
|
try {
|
|
152
|
-
return await this.get(`students/${studentId}`, schoolId);
|
|
209
|
+
return this.unwrapRecord(await this.get(`students/${studentId}`, schoolId));
|
|
153
210
|
}
|
|
154
211
|
catch (error) {
|
|
155
212
|
this.logger.warn(`Failed to fetch student ${studentId}: ${error.message}`);
|
|
156
213
|
return null;
|
|
157
214
|
}
|
|
158
215
|
}
|
|
216
|
+
async getStudentByUserId(userId, schoolId) {
|
|
217
|
+
try {
|
|
218
|
+
return this.unwrapRecord(await this.get(`students/by-user/${userId}`, schoolId));
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
this.logger.warn(`Failed to fetch student by user ${userId}: ${error.message}`);
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
async resolveStudentUserIdToStudentId(userId, schoolId) {
|
|
226
|
+
const student = await this.getStudentByUserId(userId, schoolId);
|
|
227
|
+
return student?.id || null;
|
|
228
|
+
}
|
|
159
229
|
async findStudentByEmail(email, schoolId) {
|
|
160
230
|
try {
|
|
161
231
|
const data = await this.get('students', schoolId, { params: { q: email, limit: 1 } });
|
|
@@ -177,10 +247,71 @@ let CoreIntegrationService = CoreIntegrationService_1 = class CoreIntegrationSer
|
|
|
177
247
|
return null;
|
|
178
248
|
}
|
|
179
249
|
}
|
|
180
|
-
async
|
|
250
|
+
async getTeacherByUserId(userId, schoolId) {
|
|
251
|
+
// Fast path: try direct lookup endpoint (if Core provides it)
|
|
181
252
|
try {
|
|
182
|
-
const data = await this.get(
|
|
183
|
-
return data
|
|
253
|
+
const data = await this.get(`teachers/by-user/${userId}`, schoolId);
|
|
254
|
+
return this.unwrapRecord(data);
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
// Fallback: fetch all active teachers and find match by userId
|
|
258
|
+
try {
|
|
259
|
+
const teachers = await this.getTeachers(schoolId);
|
|
260
|
+
return this.matchByUserId(teachers, userId);
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
async resolveTeacherUserIdToTeacherId(userId, schoolId) {
|
|
268
|
+
const teacher = await this.getTeacherByUserId(userId, schoolId);
|
|
269
|
+
return this.extractEntityId(teacher);
|
|
270
|
+
}
|
|
271
|
+
async reconcileAcademicData(schoolId, academicYear) {
|
|
272
|
+
try {
|
|
273
|
+
const data = await this.post('integrations/lms/reconcile', schoolId, {
|
|
274
|
+
schoolId,
|
|
275
|
+
academicYear,
|
|
276
|
+
});
|
|
277
|
+
const body = data?.data || data;
|
|
278
|
+
return {
|
|
279
|
+
teachers: body?.teachers || [],
|
|
280
|
+
classes: body?.classes || [],
|
|
281
|
+
assignments: body?.assignments || [],
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
this.logger.error(`Failed to reconcile academic data: ${error.message}`);
|
|
286
|
+
throw new Error('Core service unavailable: unable to reconcile academic data');
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
async getTeacherAssignments(teacherId, schoolId, academicYear) {
|
|
290
|
+
try {
|
|
291
|
+
const data = await this.get(`teachers/${teacherId}/assignments`, schoolId, {
|
|
292
|
+
params: academicYear ? { academicYear } : {},
|
|
293
|
+
});
|
|
294
|
+
const raw = data?.data || data;
|
|
295
|
+
return raw?.data || (Array.isArray(raw) ? raw : []);
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
return [];
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
async getClass(classId, schoolId) {
|
|
302
|
+
try {
|
|
303
|
+
return this.unwrapRecord(await this.get(`classes/${classId}`, schoolId));
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
this.logger.warn(`Failed to fetch class ${classId}: ${error.message}`);
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
async getClasses(schoolId, params = {}) {
|
|
311
|
+
try {
|
|
312
|
+
const data = await this.get('classes', schoolId, { params });
|
|
313
|
+
const body = data?.data || data || {};
|
|
314
|
+
return body?.data || body || [];
|
|
184
315
|
}
|
|
185
316
|
catch (error) {
|
|
186
317
|
this.logger.error(`Failed to fetch classes: ${error.message}`);
|
|
@@ -200,7 +331,91 @@ let CoreIntegrationService = CoreIntegrationService_1 = class CoreIntegrationSer
|
|
|
200
331
|
}
|
|
201
332
|
async getSubjects(schoolId, params = {}) {
|
|
202
333
|
const data = await this.get('subjects', schoolId, { params });
|
|
203
|
-
|
|
334
|
+
const body = data?.data || data || {};
|
|
335
|
+
return body?.data || body || [];
|
|
336
|
+
}
|
|
337
|
+
async getSubject(subjectId, schoolId) {
|
|
338
|
+
try {
|
|
339
|
+
return this.unwrapRecord(await this.get(`subjects/${subjectId}`, schoolId));
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
this.logger.warn(`Failed to fetch subject ${subjectId}: ${error.message}`);
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
async getRoom(roomId, schoolId) {
|
|
347
|
+
try {
|
|
348
|
+
return this.unwrapRecord(await this.get(`rooms/${roomId}`, schoolId));
|
|
349
|
+
}
|
|
350
|
+
catch (error) {
|
|
351
|
+
this.logger.warn(`Failed to fetch room ${roomId}: ${error.message}`);
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
async getTimeSlots(schoolId) {
|
|
356
|
+
try {
|
|
357
|
+
const data = await this.get('time-slots', schoolId);
|
|
358
|
+
return data?.data || data || [];
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
this.logger.warn(`Failed to fetch time slots: ${error.message}`);
|
|
362
|
+
return [];
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
async getActiveAcademicYear(schoolId) {
|
|
366
|
+
try {
|
|
367
|
+
return this.unwrapRecord(await this.get('academic-years/active', schoolId));
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
this.logger.warn(`Failed to fetch active academic year: ${error.message}`);
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
async getActiveSemester(schoolId) {
|
|
375
|
+
try {
|
|
376
|
+
return this.unwrapRecord(await this.get('academic-years/active-semester', schoolId));
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
this.logger.warn(`Failed to fetch active semester: ${error.message}`);
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
async getAcademicYear(yearId, schoolId) {
|
|
384
|
+
try {
|
|
385
|
+
return this.unwrapRecord(await this.get(`academic-years/${yearId}`, schoolId));
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
this.logger.warn(`Failed to fetch academic year ${yearId}: ${error.message}`);
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
async getSemester(semesterId, schoolId) {
|
|
393
|
+
try {
|
|
394
|
+
return this.unwrapRecord(await this.get(`academic-years/semesters/${semesterId}`, schoolId));
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
this.logger.warn(`Failed to fetch semester ${semesterId}: ${error.message}`);
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
async getTeachingSchedule(scheduleId, schoolId) {
|
|
402
|
+
try {
|
|
403
|
+
return this.unwrapRecord(await this.get(`teaching-schedules/${scheduleId}`, schoolId));
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
this.logger.warn(`Failed to fetch teaching schedule ${scheduleId}: ${error.message}`);
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
async findTeachingSchedules(schoolId, params = {}) {
|
|
411
|
+
try {
|
|
412
|
+
const data = await this.get('teaching-schedules', schoolId, { params });
|
|
413
|
+
return data?.data || data || [];
|
|
414
|
+
}
|
|
415
|
+
catch (error) {
|
|
416
|
+
this.logger.warn(`Failed to fetch teaching schedules: ${error.message}`);
|
|
417
|
+
return [];
|
|
418
|
+
}
|
|
204
419
|
}
|
|
205
420
|
async getCurriculums(schoolId, params = {}) {
|
|
206
421
|
const data = await this.get('curriculum', schoolId, { params });
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
2
|
"name": "@loka-sms/core-integration-be",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Internal NestJS client for service-to-service access to
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "Internal NestJS client for service-to-service access to OMNISCHOOL Core APIs",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"main": "dist/index.js",
|