av6-core 1.4.8 → 1.4.10

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 (3) hide show
  1. package/dist/index.js +252 -85
  2. package/dist/index.mjs +252 -85
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2196,6 +2196,15 @@ var uinConfigService = (uinDeps) => {
2196
2196
  };
2197
2197
  };
2198
2198
 
2199
+ // src/types/notification.ts
2200
+ var TemplateType = /* @__PURE__ */ ((TemplateType2) => {
2201
+ TemplateType2["EMAIL"] = "EMAIL";
2202
+ TemplateType2["SMS"] = "SMS";
2203
+ TemplateType2["WHATSAPP"] = "WHATSAPP";
2204
+ TemplateType2["APP_NOTIFICATION"] = "APP_NOTIFICATION";
2205
+ return TemplateType2;
2206
+ })(TemplateType || {});
2207
+
2199
2208
  // src/providers/app.provider.ts
2200
2209
  var AppNotificationProvider = class {
2201
2210
  async send(args) {
@@ -2226,7 +2235,7 @@ var AppNotificationProvider = class {
2226
2235
  // src/providers/email.providers.ts
2227
2236
  var import_nodemailer = __toESM(require("nodemailer"));
2228
2237
  var EmailProvider = class {
2229
- constructor(prisma, logger = console, serviceDomain = "FIXUJI", EMAIL_USERNAME = "info@aerialview6.com") {
2238
+ constructor(prisma, logger = console, serviceDomain = "LEVEL2", EMAIL_USERNAME = "info@aerialview6.com") {
2230
2239
  this.prisma = prisma;
2231
2240
  this.logger = logger;
2232
2241
  this.serviceDomain = serviceDomain;
@@ -2483,101 +2492,256 @@ function normalizeEmail(v) {
2483
2492
  function normalizePhone(v) {
2484
2493
  return v.replace(/[^\d]/g, "");
2485
2494
  }
2486
- function normalize(t, v) {
2495
+ function initRes() {
2496
+ return {
2497
+ ["EMAIL" /* EMAIL */]: [],
2498
+ ["SMS" /* SMS */]: [],
2499
+ ["WHATSAPP" /* WHATSAPP */]: [],
2500
+ ["APP_NOTIFICATION" /* APP_NOTIFICATION */]: []
2501
+ };
2502
+ }
2503
+ function normalizeByType(type, v) {
2487
2504
  if (!v) return "";
2488
- if (t === "EMAIL") return normalizeEmail(v);
2489
- if (t === "APP_NOTIFICATION") return v.trim();
2505
+ if (type === "EMAIL" /* EMAIL */) return normalizeEmail(v);
2506
+ if (type === "APP_NOTIFICATION" /* APP_NOTIFICATION */) return v.trim();
2490
2507
  return normalizePhone(v);
2491
2508
  }
2492
- async function pickStaffValues(prisma, staffIds, field) {
2493
- const staff = await prisma.staff.findMany({
2494
- where: { id: { in: staffIds } },
2495
- select: { email: true, contactNo: true, userId: true, isActive: true }
2496
- });
2497
- const out = [];
2498
- for (const s of staff) {
2499
- if (field === "EMAIL") out.push(s.email ?? "");
2500
- if (field === "CONTACT_NO") out.push(s.contactNo ?? "");
2501
- if (field === "USER_ID") out.push(s.userId ? String(s.userId) : "");
2502
- }
2503
- return out;
2509
+ function pickFromStaffRow(type, valueField, row) {
2510
+ if (valueField === "EMAIL") return row.email ?? "";
2511
+ if (valueField === "CONTACT_NO") return row.contactNo ?? "";
2512
+ if (valueField === "USER_ID") return row.userId != null ? String(row.userId) : "";
2513
+ return type === "EMAIL" /* EMAIL */ ? row.email ?? "" : row.contactNo ?? "";
2504
2514
  }
2505
- async function resolveRecipients(args) {
2515
+ var getUsersFromRoleAndLevel1Level2 = async (args) => {
2516
+ switch (args.serviceDomain) {
2517
+ case "FIXUJI":
2518
+ const users = await args.prisma.userAreaMapping.findMany({
2519
+ where: {
2520
+ areaId: args.level1Ids.length ? {
2521
+ in: args.level1Ids
2522
+ } : void 0,
2523
+ isActive: true,
2524
+ userAreaDeptMappings: {
2525
+ some: {
2526
+ deptId: args.level2Ids.length ? {
2527
+ in: args.level2Ids
2528
+ } : void 0,
2529
+ isActive: true,
2530
+ userRoleMappings: {
2531
+ some: {
2532
+ roleId: {
2533
+ in: args.roles
2534
+ },
2535
+ isActive: true
2536
+ }
2537
+ }
2538
+ }
2539
+ }
2540
+ },
2541
+ select: {
2542
+ userId: true
2543
+ },
2544
+ distinct: ["userId"]
2545
+ });
2546
+ const userIds = users.map((r) => r.userId);
2547
+ return userIds;
2548
+ case "AV6": {
2549
+ const { roles, level1Ids } = args;
2550
+ const result = await args.prisma.$queryRawUnsafe(
2551
+ `
2552
+ SELECT
2553
+ distinct scc.staff_id AS staff_id
2554
+ FROM
2555
+ staff_roles sr
2556
+ LEFT JOIN staff_collection_center scc
2557
+ ON
2558
+ scc.staff_id = sr.staff_id
2559
+ AND scc.staff_id = sr.staff_id
2560
+ WHERE
2561
+ sr.is_active = 1
2562
+ and scc.is_active = 1
2563
+ ${roles.length ? `AND sr.role_id IN (${roles.map(() => "?").join(",")})` : ""}
2564
+ ${level1Ids.length ? `AND scc.collection_center_id IN (${level1Ids.map(() => "?").join(",")})` : ""}
2565
+ `,
2566
+ ...roles,
2567
+ ...level1Ids
2568
+ );
2569
+ const staffIds = result.map((r) => r.staff_id);
2570
+ return staffIds;
2571
+ }
2572
+ default: {
2573
+ const users2 = await args.prisma.userLevel1Mapping.findMany({
2574
+ where: {
2575
+ level1Id: {
2576
+ in: args.level1Ids.length ? {
2577
+ in: args.level1Ids
2578
+ } : void 0
2579
+ },
2580
+ isActive: true,
2581
+ userLevel1Level2Mappings: {
2582
+ some: {
2583
+ level2Id: {
2584
+ in: args.level2Ids.length ? {
2585
+ in: args.level2Ids
2586
+ } : void 0
2587
+ },
2588
+ isActive: true,
2589
+ userRoleMappings: {
2590
+ some: {
2591
+ roleId: {
2592
+ in: args.roles
2593
+ },
2594
+ isActive: true
2595
+ }
2596
+ }
2597
+ }
2598
+ }
2599
+ },
2600
+ select: {
2601
+ userId: true
2602
+ },
2603
+ distinct: ["userId"]
2604
+ });
2605
+ const userIds2 = users2.map((r) => r.userId);
2606
+ return userIds2;
2607
+ }
2608
+ }
2609
+ };
2610
+ var getStaffInfoFromStaffIds = async (args) => {
2611
+ let staffById = /* @__PURE__ */ new Map();
2612
+ if (args.staffIds.length) {
2613
+ switch (args.serviceDomain) {
2614
+ case "AV6":
2615
+ const staffRows = await args.prisma.staff.findMany({
2616
+ where: { id: { in: args.staffIds } },
2617
+ select: { id: true, email: true, contactNo: true }
2618
+ });
2619
+ staffById = new Map(
2620
+ staffRows.map((s) => [s.id, { email: s.email ?? null, contactNo: s.contactNo ?? null, userId: null }])
2621
+ );
2622
+ break;
2623
+ case "LEVEL2": {
2624
+ const result2 = await args.prisma.user.findMany({
2625
+ where: {
2626
+ id: {
2627
+ in: args.staffIds
2628
+ },
2629
+ isActive: true
2630
+ },
2631
+ select: {
2632
+ phoneNumber: true,
2633
+ email: true
2634
+ }
2635
+ });
2636
+ staffById = new Map(
2637
+ result2.map((s) => [s.id, { email: s.email ?? null, contactNo: s.phoneNumber ?? null, userId: null }])
2638
+ );
2639
+ break;
2640
+ }
2641
+ default:
2642
+ const result = await args.prisma.user.findMany({
2643
+ where: {
2644
+ id: {
2645
+ in: args.staffIds
2646
+ },
2647
+ isActive: true
2648
+ },
2649
+ select: {
2650
+ phoneNumber: true,
2651
+ email: true
2652
+ }
2653
+ });
2654
+ staffById = new Map(
2655
+ result.map((s) => [s.id, { email: s.email ?? null, contactNo: s.phoneNumber ?? null, userId: null }])
2656
+ );
2657
+ break;
2658
+ }
2659
+ }
2660
+ return staffById;
2661
+ };
2662
+ async function resolveAllRecipients(args) {
2663
+ const res = initRes();
2506
2664
  const rules = await args.prisma.eventRecipientRule.findMany({
2507
- where: { eventConfigId: args.eventConfig.id, templateType: args.templateType, isActive: true },
2508
- orderBy: { sortOrder: "asc" }
2665
+ where: { eventConfigId: args.eventConfig.id, isActive: true },
2666
+ orderBy: [{ templateType: "asc" }, { sortOrder: "asc" }]
2667
+ });
2668
+ const staffIdsFromStaffRules = /* @__PURE__ */ new Set();
2669
+ const roleIdsNeeded = /* @__PURE__ */ new Set();
2670
+ const level1IdsNeeded = /* @__PURE__ */ new Set();
2671
+ const level2IdsNeeded = /* @__PURE__ */ new Set();
2672
+ const onlyActiveByRuleId = /* @__PURE__ */ new Map();
2673
+ for (const r of rules) {
2674
+ const cfg = r.config ?? {};
2675
+ if (r.sourceType === "STAFFS") {
2676
+ for (const id of toArray(cfg.userIds)) staffIdsFromStaffRules.add(Number(id));
2677
+ }
2678
+ if (r.sourceType === "ROLES") {
2679
+ for (const id of toArray(cfg.roleIds)) roleIdsNeeded.add(Number(id));
2680
+ onlyActiveByRuleId.set(r.id, cfg.onlyActive ?? true);
2681
+ }
2682
+ for (const id of toArray(cfg.level1Ids)) level1IdsNeeded.add(Number(id));
2683
+ for (const id of toArray(cfg.level2Ids)) level2IdsNeeded.add(Number(id));
2684
+ }
2685
+ const staffIdsFromRoleRules = /* @__PURE__ */ new Set();
2686
+ const serviceDomain = args.eventConfig.serviceEvent.serviceDomain;
2687
+ if (roleIdsNeeded.size) {
2688
+ const mappings = await getUsersFromRoleAndLevel1Level2({
2689
+ prisma: args.prisma,
2690
+ roles: Array.from(roleIdsNeeded),
2691
+ level1Ids: Array.from(level1IdsNeeded),
2692
+ level2Ids: Array.from(level2IdsNeeded),
2693
+ serviceDomain
2694
+ });
2695
+ for (const id of mappings) {
2696
+ staffIdsFromRoleRules.add(Number(id));
2697
+ }
2698
+ }
2699
+ const allStaffIds = Array.from(
2700
+ /* @__PURE__ */ new Set([...Array.from(staffIdsFromStaffRules), ...Array.from(staffIdsFromRoleRules)])
2701
+ );
2702
+ const staffById = await getStaffInfoFromStaffIds({
2703
+ prisma: args.prisma,
2704
+ staffIds: allStaffIds,
2705
+ serviceDomain
2509
2706
  });
2510
- const out = [];
2511
2707
  for (const r of rules) {
2708
+ const type = r.templateType;
2512
2709
  const cfg = r.config ?? {};
2513
- const valueField = cfg.valueField ?? defaultValueField(args.templateType);
2710
+ const valueField = cfg.valueField ?? defaultValueField(type);
2514
2711
  if (r.sourceType === "HARDCODE") {
2515
- out.push(...toArray(cfg.recipients).map(String));
2712
+ for (const v of toArray(cfg.recipients)) res[type].push(String(v));
2516
2713
  continue;
2517
2714
  }
2518
2715
  if (r.sourceType === "KEY_VALUE") {
2519
- const keys = toArray(cfg.keys);
2520
- for (const k of keys) {
2716
+ for (const k of toArray(cfg.keys)) {
2521
2717
  const v = args.evtData?.[k];
2522
- if (typeof v === "string") out.push(v);
2523
- if (Array.isArray(v)) out.push(...v.filter((x) => typeof x === "string"));
2718
+ if (typeof v === "string") res[type].push(v);
2719
+ if (Array.isArray(v)) res[type].push(...v.filter((x) => typeof x === "string"));
2524
2720
  }
2525
2721
  continue;
2526
2722
  }
2527
2723
  if (r.sourceType === "STAFFS") {
2528
- const staffIds = toArray(cfg.staffIds);
2529
- const userIds = toArray(cfg.userIds);
2530
- const onlyActive = cfg.onlyActive ?? true;
2531
- let resolvedStaffIds = [];
2532
- if (staffIds.length) {
2533
- resolvedStaffIds = staffIds;
2534
- } else if (userIds.length) {
2535
- const staff = await args.prisma.staff.findMany({
2536
- where: {
2537
- userId: { in: userIds },
2538
- ...onlyActive ? { isActive: 1 } : {}
2539
- },
2540
- select: { id: true }
2541
- });
2542
- resolvedStaffIds = staff.map((s) => s.id);
2724
+ const userIds = toArray(cfg.userIds).map(Number);
2725
+ for (const sid of userIds) {
2726
+ const s = staffById.get(sid);
2727
+ if (!s) continue;
2728
+ res[type].push(pickFromStaffRow(type, valueField, s));
2543
2729
  }
2544
- if (!resolvedStaffIds.length) continue;
2545
- if (onlyActive && staffIds.length) {
2546
- const staff = await args.prisma.staff.findMany({
2547
- where: { id: { in: resolvedStaffIds }, isActive: 1 },
2548
- select: { id: true }
2549
- });
2550
- resolvedStaffIds = staff.map((s) => s.id);
2551
- }
2552
- out.push(...await pickStaffValues(args.prisma, resolvedStaffIds, valueField));
2553
2730
  continue;
2554
2731
  }
2555
2732
  if (r.sourceType === "ROLES") {
2556
- const roleIds = toArray(cfg.roleIds);
2557
- const onlyActive = cfg.onlyActive ?? true;
2558
- if (!roleIds.length) continue;
2559
- const mappings = await args.prisma.staff_roles.findMany({
2560
- where: {
2561
- role_id: { in: roleIds },
2562
- ...onlyActive ? { is_active: 1 } : {}
2563
- },
2564
- select: { staff_id: true }
2565
- });
2566
- let staffIds = mappings.map((m) => m.staff_id).filter(Boolean);
2567
- if (onlyActive && staffIds.length) {
2568
- const staff = await args.prisma.staff.findMany({
2569
- where: { id: { in: staffIds }, isActive: 1 },
2570
- select: { id: true }
2571
- });
2572
- staffIds = staff.map((s) => s.id);
2733
+ for (const sid of staffIdsFromRoleRules) {
2734
+ const s = staffById.get(sid);
2735
+ if (!s) continue;
2736
+ res[type].push(pickFromStaffRow(type, valueField, s));
2573
2737
  }
2574
- if (!staffIds.length) continue;
2575
- out.push(...await pickStaffValues(args.prisma, staffIds, valueField));
2576
2738
  continue;
2577
2739
  }
2578
2740
  }
2579
- const norm = out.map((x) => normalize(args.templateType, String(x || ""))).filter(Boolean);
2580
- return dedupe(norm);
2741
+ for (const t of Object.values(TemplateType)) {
2742
+ res[t] = dedupe(res[t].map((x) => normalizeByType(t, String(x || ""))).filter(Boolean));
2743
+ }
2744
+ return res;
2581
2745
  }
2582
2746
 
2583
2747
  // src/utils/renderer.ts
@@ -2608,17 +2772,22 @@ var NotificationService = class {
2608
2772
  const cfg = await this.loadEventConfigOrThrow(evt);
2609
2773
  const delivery = await this.createDeliveryParent(cfg, evt);
2610
2774
  const tasks = [];
2775
+ const allRecipients = await this.getRecipients(cfg, evt);
2611
2776
  if (this.shouldSendEmail(cfg)) {
2612
- tasks.push(this.processEmailChannel({ cfg, evt, deliveryId: delivery.id }));
2777
+ tasks.push(this.processEmailChannel({ cfg, evt, deliveryId: delivery.id, recipients: allRecipients.EMAIL }));
2613
2778
  }
2614
2779
  if (this.shouldSendSms(cfg)) {
2615
- tasks.push(this.processSmsChannel({ cfg, evt, deliveryId: delivery.id }));
2780
+ tasks.push(this.processSmsChannel({ cfg, evt, deliveryId: delivery.id, recipients: allRecipients.SMS }));
2616
2781
  }
2617
2782
  if (this.shouldSendWhatsapp(cfg)) {
2618
- tasks.push(this.processWhatsappChannel({ cfg, evt, deliveryId: delivery.id }));
2783
+ tasks.push(
2784
+ this.processWhatsappChannel({ cfg, evt, deliveryId: delivery.id, recipients: allRecipients.WHATSAPP })
2785
+ );
2619
2786
  }
2620
2787
  if (this.shouldSendApp(cfg)) {
2621
- tasks.push(this.processAppChannel({ cfg, evt, deliveryId: delivery.id }));
2788
+ tasks.push(
2789
+ this.processAppChannel({ cfg, evt, deliveryId: delivery.id, recipients: allRecipients.APP_NOTIFICATION })
2790
+ );
2622
2791
  }
2623
2792
  const settled = await Promise.allSettled(tasks);
2624
2793
  for (const r of settled) {
@@ -2709,13 +2878,13 @@ var NotificationService = class {
2709
2878
  const { cfg, evt, deliveryId } = args;
2710
2879
  const tpl = await this.prisma.template.findUnique({ where: { id: cfg.emailTemplateId } });
2711
2880
  if (!tpl) return;
2712
- const recipients = await this.getRecipients(cfg.id, "EMAIL" /* EMAIL */, evt);
2881
+ const recipients = args.recipients;
2713
2882
  if (!recipients.length) {
2714
2883
  this.logger.info("[NotificationService] Email: no recipients resolved");
2715
2884
  return;
2716
2885
  }
2717
2886
  const msg = renderEmailTemplate({ body: tpl.bodyHtml ?? "", subject: tpl.subject ?? "" }, evt.data ?? {});
2718
- const provider = new EmailProvider(this.prisma, this.logger, cfg.serviceDomain);
2887
+ const provider = new EmailProvider(this.prisma, this.logger, cfg.serviceEvent.serviceDomain);
2719
2888
  await this.sendPerRecipient({
2720
2889
  deliveryId,
2721
2890
  notificationType: "EMAIL" /* EMAIL */,
@@ -2736,7 +2905,7 @@ var NotificationService = class {
2736
2905
  const { cfg, evt, deliveryId } = args;
2737
2906
  const tpl = await this.prisma.template.findUnique({ where: { id: cfg.smsTemplateId } });
2738
2907
  if (!tpl) return;
2739
- const recipients = await this.getRecipients(cfg.id, "SMS" /* SMS */, evt);
2908
+ const recipients = args.recipients;
2740
2909
  if (!recipients.length) {
2741
2910
  this.logger.info("[NotificationService] SMS: no recipients resolved");
2742
2911
  return;
@@ -2767,7 +2936,7 @@ var NotificationService = class {
2767
2936
  const { cfg, evt, deliveryId } = args;
2768
2937
  const tpl = await this.prisma.template.findUnique({ where: { id: cfg.appNotificationTemplateId } });
2769
2938
  if (!tpl) return;
2770
- const recipients = await this.getRecipients(cfg.id, "APP_NOTIFICATION" /* APP_NOTIFICATION */, evt);
2939
+ const recipients = args.recipients;
2771
2940
  if (!recipients.length) {
2772
2941
  this.logger.info("[NotificationService] APP: no recipients resolved");
2773
2942
  return;
@@ -2795,7 +2964,7 @@ var NotificationService = class {
2795
2964
  const { cfg, evt, deliveryId } = args;
2796
2965
  const tpl = await this.prisma.template.findUnique({ where: { id: cfg.wpTemplateId } });
2797
2966
  if (!tpl) return;
2798
- const recipients = await this.getRecipients(cfg, "WHATSAPP" /* WHATSAPP */, evt);
2967
+ const recipients = args.recipients;
2799
2968
  if (!recipients.length) {
2800
2969
  this.logger.info("[NotificationService] WhatsApp: no recipients resolved");
2801
2970
  return;
@@ -2848,15 +3017,13 @@ var NotificationService = class {
2848
3017
  // --------------------------------------------------------------------------------------
2849
3018
  // Recipient resolution
2850
3019
  // --------------------------------------------------------------------------------------
2851
- async getRecipients(eventConfig, templateType, evt) {
2852
- const recipients = await resolveRecipients({
3020
+ async getRecipients(eventConfig, evt) {
3021
+ const recipients = await resolveAllRecipients({
2853
3022
  prisma: this.prisma,
2854
3023
  eventConfig,
2855
- templateType,
2856
3024
  evtData: evt.data ?? {}
2857
- // serviceDomain/level columns are ignored for now (as requested)
2858
3025
  });
2859
- return Array.from(new Set((recipients ?? []).filter(Boolean)));
3026
+ return recipients;
2860
3027
  }
2861
3028
  // --------------------------------------------------------------------------------------
2862
3029
  // Generic send helpers
package/dist/index.mjs CHANGED
@@ -2146,6 +2146,15 @@ var uinConfigService = (uinDeps) => {
2146
2146
  };
2147
2147
  };
2148
2148
 
2149
+ // src/types/notification.ts
2150
+ var TemplateType = /* @__PURE__ */ ((TemplateType2) => {
2151
+ TemplateType2["EMAIL"] = "EMAIL";
2152
+ TemplateType2["SMS"] = "SMS";
2153
+ TemplateType2["WHATSAPP"] = "WHATSAPP";
2154
+ TemplateType2["APP_NOTIFICATION"] = "APP_NOTIFICATION";
2155
+ return TemplateType2;
2156
+ })(TemplateType || {});
2157
+
2149
2158
  // src/providers/app.provider.ts
2150
2159
  var AppNotificationProvider = class {
2151
2160
  async send(args) {
@@ -2176,7 +2185,7 @@ var AppNotificationProvider = class {
2176
2185
  // src/providers/email.providers.ts
2177
2186
  import nodemailer from "nodemailer";
2178
2187
  var EmailProvider = class {
2179
- constructor(prisma, logger = console, serviceDomain = "FIXUJI", EMAIL_USERNAME = "info@aerialview6.com") {
2188
+ constructor(prisma, logger = console, serviceDomain = "LEVEL2", EMAIL_USERNAME = "info@aerialview6.com") {
2180
2189
  this.prisma = prisma;
2181
2190
  this.logger = logger;
2182
2191
  this.serviceDomain = serviceDomain;
@@ -2433,101 +2442,256 @@ function normalizeEmail(v) {
2433
2442
  function normalizePhone(v) {
2434
2443
  return v.replace(/[^\d]/g, "");
2435
2444
  }
2436
- function normalize(t, v) {
2445
+ function initRes() {
2446
+ return {
2447
+ ["EMAIL" /* EMAIL */]: [],
2448
+ ["SMS" /* SMS */]: [],
2449
+ ["WHATSAPP" /* WHATSAPP */]: [],
2450
+ ["APP_NOTIFICATION" /* APP_NOTIFICATION */]: []
2451
+ };
2452
+ }
2453
+ function normalizeByType(type, v) {
2437
2454
  if (!v) return "";
2438
- if (t === "EMAIL") return normalizeEmail(v);
2439
- if (t === "APP_NOTIFICATION") return v.trim();
2455
+ if (type === "EMAIL" /* EMAIL */) return normalizeEmail(v);
2456
+ if (type === "APP_NOTIFICATION" /* APP_NOTIFICATION */) return v.trim();
2440
2457
  return normalizePhone(v);
2441
2458
  }
2442
- async function pickStaffValues(prisma, staffIds, field) {
2443
- const staff = await prisma.staff.findMany({
2444
- where: { id: { in: staffIds } },
2445
- select: { email: true, contactNo: true, userId: true, isActive: true }
2446
- });
2447
- const out = [];
2448
- for (const s of staff) {
2449
- if (field === "EMAIL") out.push(s.email ?? "");
2450
- if (field === "CONTACT_NO") out.push(s.contactNo ?? "");
2451
- if (field === "USER_ID") out.push(s.userId ? String(s.userId) : "");
2452
- }
2453
- return out;
2459
+ function pickFromStaffRow(type, valueField, row) {
2460
+ if (valueField === "EMAIL") return row.email ?? "";
2461
+ if (valueField === "CONTACT_NO") return row.contactNo ?? "";
2462
+ if (valueField === "USER_ID") return row.userId != null ? String(row.userId) : "";
2463
+ return type === "EMAIL" /* EMAIL */ ? row.email ?? "" : row.contactNo ?? "";
2454
2464
  }
2455
- async function resolveRecipients(args) {
2465
+ var getUsersFromRoleAndLevel1Level2 = async (args) => {
2466
+ switch (args.serviceDomain) {
2467
+ case "FIXUJI":
2468
+ const users = await args.prisma.userAreaMapping.findMany({
2469
+ where: {
2470
+ areaId: args.level1Ids.length ? {
2471
+ in: args.level1Ids
2472
+ } : void 0,
2473
+ isActive: true,
2474
+ userAreaDeptMappings: {
2475
+ some: {
2476
+ deptId: args.level2Ids.length ? {
2477
+ in: args.level2Ids
2478
+ } : void 0,
2479
+ isActive: true,
2480
+ userRoleMappings: {
2481
+ some: {
2482
+ roleId: {
2483
+ in: args.roles
2484
+ },
2485
+ isActive: true
2486
+ }
2487
+ }
2488
+ }
2489
+ }
2490
+ },
2491
+ select: {
2492
+ userId: true
2493
+ },
2494
+ distinct: ["userId"]
2495
+ });
2496
+ const userIds = users.map((r) => r.userId);
2497
+ return userIds;
2498
+ case "AV6": {
2499
+ const { roles, level1Ids } = args;
2500
+ const result = await args.prisma.$queryRawUnsafe(
2501
+ `
2502
+ SELECT
2503
+ distinct scc.staff_id AS staff_id
2504
+ FROM
2505
+ staff_roles sr
2506
+ LEFT JOIN staff_collection_center scc
2507
+ ON
2508
+ scc.staff_id = sr.staff_id
2509
+ AND scc.staff_id = sr.staff_id
2510
+ WHERE
2511
+ sr.is_active = 1
2512
+ and scc.is_active = 1
2513
+ ${roles.length ? `AND sr.role_id IN (${roles.map(() => "?").join(",")})` : ""}
2514
+ ${level1Ids.length ? `AND scc.collection_center_id IN (${level1Ids.map(() => "?").join(",")})` : ""}
2515
+ `,
2516
+ ...roles,
2517
+ ...level1Ids
2518
+ );
2519
+ const staffIds = result.map((r) => r.staff_id);
2520
+ return staffIds;
2521
+ }
2522
+ default: {
2523
+ const users2 = await args.prisma.userLevel1Mapping.findMany({
2524
+ where: {
2525
+ level1Id: {
2526
+ in: args.level1Ids.length ? {
2527
+ in: args.level1Ids
2528
+ } : void 0
2529
+ },
2530
+ isActive: true,
2531
+ userLevel1Level2Mappings: {
2532
+ some: {
2533
+ level2Id: {
2534
+ in: args.level2Ids.length ? {
2535
+ in: args.level2Ids
2536
+ } : void 0
2537
+ },
2538
+ isActive: true,
2539
+ userRoleMappings: {
2540
+ some: {
2541
+ roleId: {
2542
+ in: args.roles
2543
+ },
2544
+ isActive: true
2545
+ }
2546
+ }
2547
+ }
2548
+ }
2549
+ },
2550
+ select: {
2551
+ userId: true
2552
+ },
2553
+ distinct: ["userId"]
2554
+ });
2555
+ const userIds2 = users2.map((r) => r.userId);
2556
+ return userIds2;
2557
+ }
2558
+ }
2559
+ };
2560
+ var getStaffInfoFromStaffIds = async (args) => {
2561
+ let staffById = /* @__PURE__ */ new Map();
2562
+ if (args.staffIds.length) {
2563
+ switch (args.serviceDomain) {
2564
+ case "AV6":
2565
+ const staffRows = await args.prisma.staff.findMany({
2566
+ where: { id: { in: args.staffIds } },
2567
+ select: { id: true, email: true, contactNo: true }
2568
+ });
2569
+ staffById = new Map(
2570
+ staffRows.map((s) => [s.id, { email: s.email ?? null, contactNo: s.contactNo ?? null, userId: null }])
2571
+ );
2572
+ break;
2573
+ case "LEVEL2": {
2574
+ const result2 = await args.prisma.user.findMany({
2575
+ where: {
2576
+ id: {
2577
+ in: args.staffIds
2578
+ },
2579
+ isActive: true
2580
+ },
2581
+ select: {
2582
+ phoneNumber: true,
2583
+ email: true
2584
+ }
2585
+ });
2586
+ staffById = new Map(
2587
+ result2.map((s) => [s.id, { email: s.email ?? null, contactNo: s.phoneNumber ?? null, userId: null }])
2588
+ );
2589
+ break;
2590
+ }
2591
+ default:
2592
+ const result = await args.prisma.user.findMany({
2593
+ where: {
2594
+ id: {
2595
+ in: args.staffIds
2596
+ },
2597
+ isActive: true
2598
+ },
2599
+ select: {
2600
+ phoneNumber: true,
2601
+ email: true
2602
+ }
2603
+ });
2604
+ staffById = new Map(
2605
+ result.map((s) => [s.id, { email: s.email ?? null, contactNo: s.phoneNumber ?? null, userId: null }])
2606
+ );
2607
+ break;
2608
+ }
2609
+ }
2610
+ return staffById;
2611
+ };
2612
+ async function resolveAllRecipients(args) {
2613
+ const res = initRes();
2456
2614
  const rules = await args.prisma.eventRecipientRule.findMany({
2457
- where: { eventConfigId: args.eventConfig.id, templateType: args.templateType, isActive: true },
2458
- orderBy: { sortOrder: "asc" }
2615
+ where: { eventConfigId: args.eventConfig.id, isActive: true },
2616
+ orderBy: [{ templateType: "asc" }, { sortOrder: "asc" }]
2617
+ });
2618
+ const staffIdsFromStaffRules = /* @__PURE__ */ new Set();
2619
+ const roleIdsNeeded = /* @__PURE__ */ new Set();
2620
+ const level1IdsNeeded = /* @__PURE__ */ new Set();
2621
+ const level2IdsNeeded = /* @__PURE__ */ new Set();
2622
+ const onlyActiveByRuleId = /* @__PURE__ */ new Map();
2623
+ for (const r of rules) {
2624
+ const cfg = r.config ?? {};
2625
+ if (r.sourceType === "STAFFS") {
2626
+ for (const id of toArray(cfg.userIds)) staffIdsFromStaffRules.add(Number(id));
2627
+ }
2628
+ if (r.sourceType === "ROLES") {
2629
+ for (const id of toArray(cfg.roleIds)) roleIdsNeeded.add(Number(id));
2630
+ onlyActiveByRuleId.set(r.id, cfg.onlyActive ?? true);
2631
+ }
2632
+ for (const id of toArray(cfg.level1Ids)) level1IdsNeeded.add(Number(id));
2633
+ for (const id of toArray(cfg.level2Ids)) level2IdsNeeded.add(Number(id));
2634
+ }
2635
+ const staffIdsFromRoleRules = /* @__PURE__ */ new Set();
2636
+ const serviceDomain = args.eventConfig.serviceEvent.serviceDomain;
2637
+ if (roleIdsNeeded.size) {
2638
+ const mappings = await getUsersFromRoleAndLevel1Level2({
2639
+ prisma: args.prisma,
2640
+ roles: Array.from(roleIdsNeeded),
2641
+ level1Ids: Array.from(level1IdsNeeded),
2642
+ level2Ids: Array.from(level2IdsNeeded),
2643
+ serviceDomain
2644
+ });
2645
+ for (const id of mappings) {
2646
+ staffIdsFromRoleRules.add(Number(id));
2647
+ }
2648
+ }
2649
+ const allStaffIds = Array.from(
2650
+ /* @__PURE__ */ new Set([...Array.from(staffIdsFromStaffRules), ...Array.from(staffIdsFromRoleRules)])
2651
+ );
2652
+ const staffById = await getStaffInfoFromStaffIds({
2653
+ prisma: args.prisma,
2654
+ staffIds: allStaffIds,
2655
+ serviceDomain
2459
2656
  });
2460
- const out = [];
2461
2657
  for (const r of rules) {
2658
+ const type = r.templateType;
2462
2659
  const cfg = r.config ?? {};
2463
- const valueField = cfg.valueField ?? defaultValueField(args.templateType);
2660
+ const valueField = cfg.valueField ?? defaultValueField(type);
2464
2661
  if (r.sourceType === "HARDCODE") {
2465
- out.push(...toArray(cfg.recipients).map(String));
2662
+ for (const v of toArray(cfg.recipients)) res[type].push(String(v));
2466
2663
  continue;
2467
2664
  }
2468
2665
  if (r.sourceType === "KEY_VALUE") {
2469
- const keys = toArray(cfg.keys);
2470
- for (const k of keys) {
2666
+ for (const k of toArray(cfg.keys)) {
2471
2667
  const v = args.evtData?.[k];
2472
- if (typeof v === "string") out.push(v);
2473
- if (Array.isArray(v)) out.push(...v.filter((x) => typeof x === "string"));
2668
+ if (typeof v === "string") res[type].push(v);
2669
+ if (Array.isArray(v)) res[type].push(...v.filter((x) => typeof x === "string"));
2474
2670
  }
2475
2671
  continue;
2476
2672
  }
2477
2673
  if (r.sourceType === "STAFFS") {
2478
- const staffIds = toArray(cfg.staffIds);
2479
- const userIds = toArray(cfg.userIds);
2480
- const onlyActive = cfg.onlyActive ?? true;
2481
- let resolvedStaffIds = [];
2482
- if (staffIds.length) {
2483
- resolvedStaffIds = staffIds;
2484
- } else if (userIds.length) {
2485
- const staff = await args.prisma.staff.findMany({
2486
- where: {
2487
- userId: { in: userIds },
2488
- ...onlyActive ? { isActive: 1 } : {}
2489
- },
2490
- select: { id: true }
2491
- });
2492
- resolvedStaffIds = staff.map((s) => s.id);
2674
+ const userIds = toArray(cfg.userIds).map(Number);
2675
+ for (const sid of userIds) {
2676
+ const s = staffById.get(sid);
2677
+ if (!s) continue;
2678
+ res[type].push(pickFromStaffRow(type, valueField, s));
2493
2679
  }
2494
- if (!resolvedStaffIds.length) continue;
2495
- if (onlyActive && staffIds.length) {
2496
- const staff = await args.prisma.staff.findMany({
2497
- where: { id: { in: resolvedStaffIds }, isActive: 1 },
2498
- select: { id: true }
2499
- });
2500
- resolvedStaffIds = staff.map((s) => s.id);
2501
- }
2502
- out.push(...await pickStaffValues(args.prisma, resolvedStaffIds, valueField));
2503
2680
  continue;
2504
2681
  }
2505
2682
  if (r.sourceType === "ROLES") {
2506
- const roleIds = toArray(cfg.roleIds);
2507
- const onlyActive = cfg.onlyActive ?? true;
2508
- if (!roleIds.length) continue;
2509
- const mappings = await args.prisma.staff_roles.findMany({
2510
- where: {
2511
- role_id: { in: roleIds },
2512
- ...onlyActive ? { is_active: 1 } : {}
2513
- },
2514
- select: { staff_id: true }
2515
- });
2516
- let staffIds = mappings.map((m) => m.staff_id).filter(Boolean);
2517
- if (onlyActive && staffIds.length) {
2518
- const staff = await args.prisma.staff.findMany({
2519
- where: { id: { in: staffIds }, isActive: 1 },
2520
- select: { id: true }
2521
- });
2522
- staffIds = staff.map((s) => s.id);
2683
+ for (const sid of staffIdsFromRoleRules) {
2684
+ const s = staffById.get(sid);
2685
+ if (!s) continue;
2686
+ res[type].push(pickFromStaffRow(type, valueField, s));
2523
2687
  }
2524
- if (!staffIds.length) continue;
2525
- out.push(...await pickStaffValues(args.prisma, staffIds, valueField));
2526
2688
  continue;
2527
2689
  }
2528
2690
  }
2529
- const norm = out.map((x) => normalize(args.templateType, String(x || ""))).filter(Boolean);
2530
- return dedupe(norm);
2691
+ for (const t of Object.values(TemplateType)) {
2692
+ res[t] = dedupe(res[t].map((x) => normalizeByType(t, String(x || ""))).filter(Boolean));
2693
+ }
2694
+ return res;
2531
2695
  }
2532
2696
 
2533
2697
  // src/utils/renderer.ts
@@ -2558,17 +2722,22 @@ var NotificationService = class {
2558
2722
  const cfg = await this.loadEventConfigOrThrow(evt);
2559
2723
  const delivery = await this.createDeliveryParent(cfg, evt);
2560
2724
  const tasks = [];
2725
+ const allRecipients = await this.getRecipients(cfg, evt);
2561
2726
  if (this.shouldSendEmail(cfg)) {
2562
- tasks.push(this.processEmailChannel({ cfg, evt, deliveryId: delivery.id }));
2727
+ tasks.push(this.processEmailChannel({ cfg, evt, deliveryId: delivery.id, recipients: allRecipients.EMAIL }));
2563
2728
  }
2564
2729
  if (this.shouldSendSms(cfg)) {
2565
- tasks.push(this.processSmsChannel({ cfg, evt, deliveryId: delivery.id }));
2730
+ tasks.push(this.processSmsChannel({ cfg, evt, deliveryId: delivery.id, recipients: allRecipients.SMS }));
2566
2731
  }
2567
2732
  if (this.shouldSendWhatsapp(cfg)) {
2568
- tasks.push(this.processWhatsappChannel({ cfg, evt, deliveryId: delivery.id }));
2733
+ tasks.push(
2734
+ this.processWhatsappChannel({ cfg, evt, deliveryId: delivery.id, recipients: allRecipients.WHATSAPP })
2735
+ );
2569
2736
  }
2570
2737
  if (this.shouldSendApp(cfg)) {
2571
- tasks.push(this.processAppChannel({ cfg, evt, deliveryId: delivery.id }));
2738
+ tasks.push(
2739
+ this.processAppChannel({ cfg, evt, deliveryId: delivery.id, recipients: allRecipients.APP_NOTIFICATION })
2740
+ );
2572
2741
  }
2573
2742
  const settled = await Promise.allSettled(tasks);
2574
2743
  for (const r of settled) {
@@ -2659,13 +2828,13 @@ var NotificationService = class {
2659
2828
  const { cfg, evt, deliveryId } = args;
2660
2829
  const tpl = await this.prisma.template.findUnique({ where: { id: cfg.emailTemplateId } });
2661
2830
  if (!tpl) return;
2662
- const recipients = await this.getRecipients(cfg.id, "EMAIL" /* EMAIL */, evt);
2831
+ const recipients = args.recipients;
2663
2832
  if (!recipients.length) {
2664
2833
  this.logger.info("[NotificationService] Email: no recipients resolved");
2665
2834
  return;
2666
2835
  }
2667
2836
  const msg = renderEmailTemplate({ body: tpl.bodyHtml ?? "", subject: tpl.subject ?? "" }, evt.data ?? {});
2668
- const provider = new EmailProvider(this.prisma, this.logger, cfg.serviceDomain);
2837
+ const provider = new EmailProvider(this.prisma, this.logger, cfg.serviceEvent.serviceDomain);
2669
2838
  await this.sendPerRecipient({
2670
2839
  deliveryId,
2671
2840
  notificationType: "EMAIL" /* EMAIL */,
@@ -2686,7 +2855,7 @@ var NotificationService = class {
2686
2855
  const { cfg, evt, deliveryId } = args;
2687
2856
  const tpl = await this.prisma.template.findUnique({ where: { id: cfg.smsTemplateId } });
2688
2857
  if (!tpl) return;
2689
- const recipients = await this.getRecipients(cfg.id, "SMS" /* SMS */, evt);
2858
+ const recipients = args.recipients;
2690
2859
  if (!recipients.length) {
2691
2860
  this.logger.info("[NotificationService] SMS: no recipients resolved");
2692
2861
  return;
@@ -2717,7 +2886,7 @@ var NotificationService = class {
2717
2886
  const { cfg, evt, deliveryId } = args;
2718
2887
  const tpl = await this.prisma.template.findUnique({ where: { id: cfg.appNotificationTemplateId } });
2719
2888
  if (!tpl) return;
2720
- const recipients = await this.getRecipients(cfg.id, "APP_NOTIFICATION" /* APP_NOTIFICATION */, evt);
2889
+ const recipients = args.recipients;
2721
2890
  if (!recipients.length) {
2722
2891
  this.logger.info("[NotificationService] APP: no recipients resolved");
2723
2892
  return;
@@ -2745,7 +2914,7 @@ var NotificationService = class {
2745
2914
  const { cfg, evt, deliveryId } = args;
2746
2915
  const tpl = await this.prisma.template.findUnique({ where: { id: cfg.wpTemplateId } });
2747
2916
  if (!tpl) return;
2748
- const recipients = await this.getRecipients(cfg, "WHATSAPP" /* WHATSAPP */, evt);
2917
+ const recipients = args.recipients;
2749
2918
  if (!recipients.length) {
2750
2919
  this.logger.info("[NotificationService] WhatsApp: no recipients resolved");
2751
2920
  return;
@@ -2798,15 +2967,13 @@ var NotificationService = class {
2798
2967
  // --------------------------------------------------------------------------------------
2799
2968
  // Recipient resolution
2800
2969
  // --------------------------------------------------------------------------------------
2801
- async getRecipients(eventConfig, templateType, evt) {
2802
- const recipients = await resolveRecipients({
2970
+ async getRecipients(eventConfig, evt) {
2971
+ const recipients = await resolveAllRecipients({
2803
2972
  prisma: this.prisma,
2804
2973
  eventConfig,
2805
- templateType,
2806
2974
  evtData: evt.data ?? {}
2807
- // serviceDomain/level columns are ignored for now (as requested)
2808
2975
  });
2809
- return Array.from(new Set((recipients ?? []).filter(Boolean)));
2976
+ return recipients;
2810
2977
  }
2811
2978
  // --------------------------------------------------------------------------------------
2812
2979
  // Generic send helpers
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "av6-core",
3
- "version": "1.4.8",
3
+ "version": "1.4.10",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",