npm_microservice 1.0.24 → 1.0.25

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/service.js CHANGED
@@ -867,6 +867,22 @@ var require_DeviceService = __commonJS({
867
867
  }
868
868
  });
869
869
 
870
+ // src/services/crm/OpportunitiesService.js
871
+ var require_OpportunitiesService = __commonJS({
872
+ "src/services/crm/OpportunitiesService.js"(exports2, module2) {
873
+ var BaseService = require_BaseService();
874
+ var { CONFIG_ROUTER_SERVICE } = require_config();
875
+ var OpportunitiesService = class extends BaseService {
876
+ constructor() {
877
+ super(CONFIG_ROUTER_SERVICE.Crm.OpportunitiesService);
878
+ this.module = "opportunitiesService";
879
+ this.service = "crm";
880
+ }
881
+ };
882
+ module2.exports = OpportunitiesService;
883
+ }
884
+ });
885
+
870
886
  // src/services/finance/InvoicesCancelService.js
871
887
  var require_InvoicesCancelService = __commonJS({
872
888
  "src/services/finance/InvoicesCancelService.js"(exports2, module2) {
@@ -2583,6 +2599,7 @@ module.exports = {
2583
2599
  // crm
2584
2600
  contactsService: new (require_ContactsService())(),
2585
2601
  deviceService: new (require_DeviceService())(),
2602
+ opportunitiesService: new (require_OpportunitiesService())(),
2586
2603
  // finance
2587
2604
  invoicesCancelService: new (require_InvoicesCancelService())(),
2588
2605
  invoicesDetailService: new (require_InvoicesDetailService())(),
@@ -0,0 +1,437 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __commonJS = (cb, mod) => function __require() {
3
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
4
+ };
5
+
6
+ // src/config.js
7
+ var require_config = __commonJS({
8
+ "src/config.js"(exports2, module2) {
9
+ require("dotenv").config({ quiet: true, override: true });
10
+ var Redis = require("ioredis");
11
+ var redis = new Redis({
12
+ host: process.env.REDIS_HOST || "128.199.195.180",
13
+ port: process.env.REDIS_PORT || 6379,
14
+ password: process.env.REDIS_PASSWORD || "WZyB5Z7BRRgvrzuGzRwB"
15
+ });
16
+ var baseUrl = process.env.API_MICROSERVICE_URL;
17
+ var configRouteService = {
18
+ BASE_URL: baseUrl,
19
+ Finance: {
20
+ InvoicesService: `${baseUrl}/finance/invoices`,
21
+ InvoicesCancelService: `${baseUrl}/finance/invoice_detail_cancel`,
22
+ InvoicesDetailService: `${baseUrl}/finance/invoices-detail`,
23
+ InvoicesLogsAssignService: `${baseUrl}/finance/invoices-logs-assign`,
24
+ PaymentService: `${baseUrl}/finance/payments`,
25
+ PaymentRequestService: `${baseUrl}/finance/payments-request`,
26
+ VouchersService: `${baseUrl}/finance/vouchers`,
27
+ VouchersCategoryService: `${baseUrl}/finance/vouchers-category`,
28
+ WalletsService: `${baseUrl}/finance/wallets`,
29
+ WalletTransactionService: `${baseUrl}/finance/wallet-transaction`
30
+ },
31
+ CallCenter: {
32
+ CategoryService: `${baseUrl}/call-center/ticket-categories`,
33
+ TicketService: `${baseUrl}/call-center/ticket`,
34
+ TicketActivityService: `${baseUrl}/call-center/ticket-activities`,
35
+ TicketTemplateService: `${baseUrl}/call-center/ticket-template`,
36
+ TicketTopicService: `${baseUrl}/call-center/ticket-topics`,
37
+ CallService: `${baseUrl}/call-center/calls`
38
+ },
39
+ Inventory: {
40
+ InventoryService: `${baseUrl}/inventory/inventory-products`,
41
+ LogService: `${baseUrl}/inventory/logs`,
42
+ ProductService: `${baseUrl}/inventory/products`,
43
+ ProductShipmentService: `${baseUrl}/inventory/products_shipment`,
44
+ StoreService: `${baseUrl}/inventory/stores`,
45
+ SupplierService: `${baseUrl}/inventory/supplier`,
46
+ TransactionService: `${baseUrl}/inventory/transaction`,
47
+ TransactionDetailService: `${baseUrl}/inventory/transaction_detail`
48
+ },
49
+ App: {
50
+ CategoryService: `${baseUrl}/app/category`,
51
+ NewService: `${baseUrl}/app/news`,
52
+ BannerService: `${baseUrl}/app/banner`,
53
+ AppTestService: `${baseUrl}/app/test`,
54
+ RecommendedCourseService: `${baseUrl}/app/recommended_level`,
55
+ SettingAppService: `${baseUrl}/app/setting`,
56
+ TargetAppService: `${baseUrl}/app/target`
57
+ },
58
+ Course: {
59
+ CategoryService: `${baseUrl}/course/category`,
60
+ CourseService: `${baseUrl}/course/course`,
61
+ CourseLessonService: `${baseUrl}/course/course_schedule`,
62
+ StudentService: `${baseUrl}/course/students`
63
+ },
64
+ Asset: {
65
+ AllocationDetailService: `${baseUrl}/asset/asset-allocation-detail`,
66
+ BroadcastService: `${baseUrl}/asset/broadcast`,
67
+ EntityAssetService: `${baseUrl}/asset/entity-asset`,
68
+ SubAssetService: `${baseUrl}/asset/sub-asset`
69
+ },
70
+ Test: {
71
+ TestService: `${baseUrl}/tests/tests`
72
+ },
73
+ Pm: {
74
+ NoteService: `${baseUrl}/pm/notes`,
75
+ TaskService: `${baseUrl}/pm/tasks`
76
+ },
77
+ Crm: {
78
+ ContactService: `${baseUrl}/crm/contacts`,
79
+ AccountsService: `${baseUrl}/crm/accounts`,
80
+ CalendarContactService: `${baseUrl}/crm/calendar-contact`,
81
+ CalendarsService: `${baseUrl}/crm/calendars`,
82
+ CampaignService: `${baseUrl}/crm/campaigns`,
83
+ CompanyService: `${baseUrl}/crm/company`,
84
+ ContactDocumentService: `${baseUrl}/crm/contact-document`,
85
+ ContactToCampaignService: `${baseUrl}/crm/contacts-campaign`,
86
+ DeviceService: `${baseUrl}/crm/devices`,
87
+ LeadsService: `${baseUrl}/crm/leads`,
88
+ NotificationService: `${baseUrl}/crm/notifications`,
89
+ NotificationContactService: `${baseUrl}/crm/notification-to-contact`,
90
+ OpportunitiesService: `${baseUrl}/crm/opportunities`,
91
+ SegmentsService: `${baseUrl}/crm/segments`
92
+ },
93
+ Notification: {
94
+ AppService: `${baseUrl}/notification/type/app`,
95
+ MailService: `${baseUrl}/notification/type/mail`,
96
+ SmsService: `${baseUrl}/notification/type/sms`,
97
+ ZnsService: `${baseUrl}/notification/type/zns`,
98
+ NotificationContactService: `${baseUrl}/notification/notification_contact`,
99
+ NotificationEmployeeService: `${baseUrl}/notification/notification_employee`,
100
+ NotificationService: `${baseUrl}/notification`,
101
+ TemplateService: `${baseUrl}/notification/template`
102
+ },
103
+ Org: {
104
+ BranchService: `${baseUrl}/org/branch`,
105
+ BranchRequestService: `${baseUrl}/org/branch_request`,
106
+ BranchToMacsService: `${baseUrl}/org/branch_to_mac`,
107
+ BrandService: `${baseUrl}/org/brand`,
108
+ CitiesService: `${baseUrl}/org/city`,
109
+ LegalEntityService: `${baseUrl}/org/legal_entities`
110
+ },
111
+ Lms: {
112
+ AlbumService: `${baseUrl}/lms/album`,
113
+ AlbumCategoryService: `${baseUrl}/lms/cate_album`,
114
+ AlbumFileService: `${baseUrl}/lms/album_file`,
115
+ ClassesService: `${baseUrl}/lms/classes`,
116
+ ClassScheduleService: `${baseUrl}/lms/class-schedules`,
117
+ CourseLessonService: `${baseUrl}/lms/course-lessons`,
118
+ CoursePriceService: `${baseUrl}/lms/course-prices`,
119
+ CourseProductService: `${baseUrl}/lms/course-product`,
120
+ CourseService: `${baseUrl}/lms/courses`,
121
+ DocumentService: `${baseUrl}/lms/documents`,
122
+ DocumentCategoryService: `${baseUrl}/lms/document-categories`,
123
+ LicenseService: `${baseUrl}/lms/license`,
124
+ PracticeResultService: `${baseUrl}/lms/practices-result`,
125
+ PracticeService: `${baseUrl}/lms/practices`,
126
+ StudentAgainService: `${baseUrl}/lms/students-agains`,
127
+ StudentDocumentService: `${baseUrl}/lms/students-documents`,
128
+ StudentExamTimeService: `${baseUrl}/lms/student-exam-time`,
129
+ StudentReviewService: `${baseUrl}/lms/students-reviews`,
130
+ StudentService: `${baseUrl}/lms/students`,
131
+ StudentScoreService: `${baseUrl}/lms/students-scores`,
132
+ StudentSettingReviewService: `${baseUrl}/lms/setting-reviews`,
133
+ StudentTrackingService: `${baseUrl}/lms/students-tracking`,
134
+ StudentTrialService: `${baseUrl}/lms/students-trial`
135
+ },
136
+ Hr: {
137
+ AllowanceService: `${baseUrl}/hr/allowance`,
138
+ CategoryService: `${baseUrl}/hr/setting/category`,
139
+ AnnualLeaveService: `${baseUrl}/hr/annual_leave`,
140
+ EmployeeService: `${baseUrl}/hr/employees`,
141
+ JobTitleService: `${baseUrl}/hr/setting/job_title`,
142
+ DepartmentService: `${baseUrl}/hr/departments`,
143
+ DeviceService: `${baseUrl}/hr/device`,
144
+ DocumentService: `${baseUrl}/hr/documents`,
145
+ EmployeeExtendService: `${baseUrl}/hr/employees/extend`,
146
+ EmployeeExtendTempService: `${baseUrl}/hr/employees/extend/temp`,
147
+ EmployeeLeaveService: `${baseUrl}/hr/employee_leave`,
148
+ EmployeeNotificationService: `${baseUrl}/hr/notification-employee`,
149
+ EmployeeQuitService: `${baseUrl}/hr/employee_quit`,
150
+ EmployeeShiftService: `${baseUrl}/hr/employee_shift`,
151
+ HolidayService: `${baseUrl}/hr/holidays`,
152
+ PositionService: `${baseUrl}/hr/positions`,
153
+ ReasonTypeService: `${baseUrl}/hr/setting/reason_type`,
154
+ ResignationService: `${baseUrl}/hr/resignations`,
155
+ SalaryService: `${baseUrl}/hr/employee_salary`,
156
+ ScheduleService: `${baseUrl}/hr/schedule`,
157
+ ScheduleOnlineService: `${baseUrl}/hr/schedule_online`,
158
+ ShiftService: `${baseUrl}/hr/setting/shifts`,
159
+ ShiftsCustomerCareService: `${baseUrl}/hr/setting/shifts-customer-care`,
160
+ TicketService: `${baseUrl}/hr/ticket`,
161
+ TicketExtendService: `${baseUrl}/hr/ticket/extend`,
162
+ TicketTypeService: `${baseUrl}/hr/ticket-type`,
163
+ TrackingConfirmService: `${baseUrl}/hr/tracking_confirm`,
164
+ TrackingErrorService: `${baseUrl}/hr/tracking-error`,
165
+ SettingDocumentService: `${baseUrl}/hr/setting/profile`
166
+ },
167
+ Support: {
168
+ CommentService: `${baseUrl}/support/comment`
169
+ }
170
+ };
171
+ module2.exports = {
172
+ AUTHENTICATOR_PUBLIC_KEY: process.env.AUTHENTICATOR_PUBLIC_KEY || "",
173
+ API_MICROSERVICE_URL: process.env.API_MICROSERVICE_URL || "",
174
+ API_MICROSERVICE_TOKEN: process.env.API_MICROSERVICE_TOKEN || "",
175
+ CONFIG_ROUTER_SERVICE: configRouteService,
176
+ CONFIG_REDIS: redis
177
+ };
178
+ }
179
+ });
180
+
181
+ // src/services/CacheService.js
182
+ var require_CacheService = __commonJS({
183
+ "src/services/CacheService.js"(exports2, module2) {
184
+ var qs = require("qs");
185
+ var CacheService = class {
186
+ isCache = false;
187
+ // bật/tắt cache mặc định
188
+ service = null;
189
+ // nhớ gán ở subclass
190
+ module = null;
191
+ // module
192
+ configService = "microservice";
193
+ // module
194
+ timeCache = 3600;
195
+ // cache 60p
196
+ redis = null;
197
+ buildCacheKeyUrl(path, params = {}) {
198
+ const q = qs.stringify(params, { arrayFormat: "brackets", encode: true });
199
+ const full = `${path}${q ? "?" + q : ""}`;
200
+ return `${this.configService}.${this.service || "unknown"}.${this.module || "unknown"}.urls:${full}`;
201
+ }
202
+ // Lấy cache theo id
203
+ async getCacheByKey(key) {
204
+ const data = await this.redis.get(key);
205
+ return data ? JSON.parse(data) : null;
206
+ }
207
+ // Lấy cache theo id
208
+ async getCacheById(id) {
209
+ if (!this.isCache || !this.redis) return null;
210
+ const key = `${this.configService}.${this.service || "unknown"}.${this.module || "unknown"}.id:${id}`;
211
+ const data = await this.redis.get(key);
212
+ return data ? JSON.parse(data) : null;
213
+ }
214
+ // Lấy cache theo nhiều ids
215
+ async getCacheByIds(ids = []) {
216
+ if (!this.isCache || !this.redis) return [];
217
+ const keys = ids.map(
218
+ (id) => `${this.configService}.${this.service || "unknown"}.${this.module || "unknown"}.id:${id}`
219
+ );
220
+ const results = await this.redis.mget(keys);
221
+ return results.map((r) => r ? JSON.parse(r) : null).filter(Boolean);
222
+ }
223
+ // Set cache
224
+ async setCache(key, value, ttl = this.timeCache) {
225
+ if (!this.isCache || !this.redis) return;
226
+ await this.redis.set(key, JSON.stringify(value), "EX", ttl);
227
+ }
228
+ // Ví dụ set cache theo id
229
+ async setCacheById(id, value, ttl) {
230
+ const key = `${this.configService}.${this.service || "unknown"}.${this.module || "unknown"}.id:${id}`;
231
+ await this.setCache(key, value, ttl);
232
+ }
233
+ async deleteById(id) {
234
+ const key = `${this.configService}.${this.service || "unknown"}.${this.module || "unknown"}.id:${id}`;
235
+ await this.deleteCache(key);
236
+ }
237
+ async deleteByIds(ids = []) {
238
+ if (!this.isCache || !this.redis) return;
239
+ const keys = ids.map(
240
+ (id) => `${this.configService}.${this.service || "unknown"}.${this.module || "unknown"}.id:${id}`
241
+ );
242
+ if (keys.length) {
243
+ await this.redis.del(...keys);
244
+ }
245
+ }
246
+ // Xóa cache theo key
247
+ async deleteCache(key) {
248
+ if (!this.isCache || !this.redis) return;
249
+ await this.redis.del(key);
250
+ }
251
+ };
252
+ module2.exports = CacheService;
253
+ }
254
+ });
255
+
256
+ // src/services/BaseService.js
257
+ var require_BaseService = __commonJS({
258
+ "src/services/BaseService.js"(exports2, module2) {
259
+ var axios = require("axios");
260
+ var qs = require("qs");
261
+ var { API_MICROSERVICE_TOKEN, CONFIG_REDIS } = require_config();
262
+ var CacheService = require_CacheService();
263
+ var BaseService2 = class extends CacheService {
264
+ baseUrl = "";
265
+ headers = {};
266
+ constructor(baseUrl = "", defaultHeaders = {}) {
267
+ super(baseUrl, defaultHeaders);
268
+ this.baseUrl = baseUrl;
269
+ this.setHeader(defaultHeaders);
270
+ this.redis = CONFIG_REDIS;
271
+ this.http = axios.create({
272
+ baseURL: this.baseUrl,
273
+ headers: this.headers,
274
+ paramsSerializer: (params) => qs.stringify(params, { arrayFormat: "brackets", encode: true })
275
+ });
276
+ }
277
+ /**
278
+ * Set header cho request
279
+ * - headers: object { Authorization: "Bearer x" }
280
+ * - string: "Bearer x"
281
+ * - không truyền: dùng token từ ENV
282
+ */
283
+ setHeader(headers = {}) {
284
+ let Authorization = `Bearer ${API_MICROSERVICE_TOKEN}`;
285
+ if (typeof headers === "string") {
286
+ Authorization = headers;
287
+ } else if (headers && headers.Authorization) {
288
+ Authorization = headers.Authorization;
289
+ }
290
+ this.headers = {
291
+ ...this.headers || {},
292
+ Authorization
293
+ };
294
+ return this;
295
+ }
296
+ async request(method, url, options = {}, cacheOption = {}) {
297
+ var _a, _b;
298
+ const isGet = method.toLowerCase() === "get";
299
+ const enableCache = cacheOption.isCache ?? false;
300
+ if (isGet && enableCache) {
301
+ let cacheKey = (cacheOption == null ? void 0 : cacheOption.cacheKey) ?? this.buildCacheKeyUrl(url, options.params);
302
+ const cached = await this.getCacheByKey(cacheKey);
303
+ if (cached) return cached;
304
+ }
305
+ try {
306
+ if (isGet) {
307
+ console.log(`[HTTP GET] ${this.buildGET(url, options.params || {})}`);
308
+ }
309
+ const startTime = Date.now();
310
+ const res = await this.http.request({
311
+ method,
312
+ url,
313
+ headers: this.headers,
314
+ ...options
315
+ });
316
+ const data = res.data;
317
+ if (isGet && enableCache) {
318
+ let cacheKey = cacheOption.cacheKey ?? this.buildCacheKeyUrl(url, options.params);
319
+ const ttl = cacheOption.timeCache || this.timeCache;
320
+ await this.setCache(cacheKey, data, ttl);
321
+ console.log(`[CACHE SET] ${cacheKey} - TTL ${ttl}s`);
322
+ }
323
+ const duration = (Date.now() - startTime) / 1e3;
324
+ if (duration > 5) {
325
+ console.log(
326
+ `[SLOW ${method.toUpperCase()}] ${url} - ${duration.toFixed(2)}s`
327
+ );
328
+ if (options.params) console.log("Query:", options.params);
329
+ if (options.data) console.log("Body:", options.data);
330
+ }
331
+ return data;
332
+ } catch (error) {
333
+ const safeError = {
334
+ statusCode: ((_a = error.response) == null ? void 0 : _a.status) || 500,
335
+ ...(_b = error.response) == null ? void 0 : _b.data
336
+ };
337
+ if (safeError.statusCode === 404) {
338
+ const q = qs.stringify(options.params || {}, {
339
+ arrayFormat: "brackets",
340
+ encode: true
341
+ });
342
+ return {
343
+ statusCode: 404,
344
+ status: "error",
345
+ message: `[HTTP ${method.toUpperCase()}] ${url}${q ? "?" + q : ""} not found`
346
+ };
347
+ }
348
+ console.error(`[${method.toUpperCase()}] ${url} failed:`, safeError);
349
+ return { error: true, ...safeError };
350
+ }
351
+ }
352
+ buildGET(url, params = {}) {
353
+ const queryString = qs.stringify(params, {
354
+ arrayFormat: "brackets",
355
+ encode: true
356
+ });
357
+ return `${url}${queryString ? "?" + queryString : ""}`;
358
+ }
359
+ async all(query = {}, cacheOption = {}) {
360
+ let { filter = {} } = query;
361
+ const useCache = this.isCache && filter && filter._id && Object.keys(filter).length === 1;
362
+ if (useCache) {
363
+ let ids = Array.isArray(filter._id) ? filter._id : [filter._id];
364
+ return this.details(ids);
365
+ }
366
+ if (query.order_by && Array.isArray(query.order_by)) {
367
+ query.order_by = query.order_by.slice(0, 2);
368
+ if (query.order_by[1] && !["asc", "desc"].includes(query.order_by[1])) {
369
+ query.order_by[1] = "asc";
370
+ }
371
+ }
372
+ return this.request("get", this.baseUrl, { params: query }, cacheOption);
373
+ }
374
+ async details(ids = [], options = {}, cacheOption = {}) {
375
+ const enableCache = cacheOption.isCache ?? this.isCache;
376
+ let dataCache = [];
377
+ if (enableCache) {
378
+ dataCache = await this.getCacheByIds(ids);
379
+ const cachedIds = dataCache.filter((item) => item && Object.keys(item).length > 0).map((item) => item._id);
380
+ ids = ids.filter((id) => !cachedIds.includes(id));
381
+ }
382
+ if (ids.length === 0) return dataCache;
383
+ let params = { params: { filter: { _id: ids }, limit: ids.length } };
384
+ const datas = await this.request("get", this.baseUrl, params, cacheOption);
385
+ const rows = [...dataCache];
386
+ if (enableCache && Array.isArray(datas) && datas.length) {
387
+ for (const item of datas) {
388
+ if (item && item._id) {
389
+ await this.setCacheById(item._id, item, this.timeCache);
390
+ rows.push(item);
391
+ }
392
+ }
393
+ }
394
+ return rows;
395
+ }
396
+ async detail(id, cacheOption = {}) {
397
+ const enableCache = cacheOption.isCache ?? this.isCache;
398
+ if (enableCache) {
399
+ let data = await this.getCacheById(id);
400
+ if (data) return data;
401
+ }
402
+ let url = `${this.baseUrl}/${id}`;
403
+ return this.request("get", url, {}, cacheOption);
404
+ }
405
+ async create(data) {
406
+ return this.request("post", this.baseUrl, { data });
407
+ }
408
+ async update(id, data) {
409
+ let response = this.request("put", `${this.baseUrl}/${id}`, { data });
410
+ if (response && (response == null ? void 0 : response.status) == "success" && this.isCache) {
411
+ this.deleteById(id);
412
+ }
413
+ return response;
414
+ }
415
+ async delete(id) {
416
+ let response = this.request("delete", `${this.baseUrl}/${id}`);
417
+ if (response && (response == null ? void 0 : response.status) == "success" && this.isCache) {
418
+ this.deleteById(id);
419
+ }
420
+ return response;
421
+ }
422
+ };
423
+ module2.exports = BaseService2;
424
+ }
425
+ });
426
+
427
+ // src/services/crm/OpportunitiesService.js
428
+ var BaseService = require_BaseService();
429
+ var { CONFIG_ROUTER_SERVICE } = require_config();
430
+ var OpportunitiesService = class extends BaseService {
431
+ constructor() {
432
+ super(CONFIG_ROUTER_SERVICE.Crm.OpportunitiesService);
433
+ this.module = "opportunitiesService";
434
+ this.service = "crm";
435
+ }
436
+ };
437
+ module.exports = OpportunitiesService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "npm_microservice",
3
- "version": "1.0.24",
3
+ "version": "1.0.25",
4
4
  "type": "commonjs",
5
5
  "main": "dist/index.js",
6
6
  "exports": {