orbitx-core-models 11.178.0 → 11.180.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/activity/recorder.d.ts +2 -2
  2. package/dist/activity/recorder.d.ts.map +1 -1
  3. package/dist/activity/recorder.js +4 -7
  4. package/dist/constants/ticketCategories.d.ts +41 -20
  5. package/dist/constants/ticketCategories.d.ts.map +1 -1
  6. package/dist/constants/ticketCategories.js +212 -53
  7. package/dist/helpers/chatAttachments.d.ts +4 -3
  8. package/dist/helpers/chatAttachments.d.ts.map +1 -1
  9. package/dist/helpers/chatAttachments.js +7 -7
  10. package/dist/helpers/emailTemplates.d.ts.map +1 -1
  11. package/dist/helpers/emailTemplates.js +4 -5
  12. package/dist/helpers/ownTickets.d.ts +3 -1
  13. package/dist/helpers/ownTickets.d.ts.map +1 -1
  14. package/dist/helpers/ownTickets.js +30 -11
  15. package/dist/helpers/privateFiles.d.ts +14 -0
  16. package/dist/helpers/privateFiles.d.ts.map +1 -0
  17. package/dist/helpers/privateFiles.js +45 -0
  18. package/dist/helpers/requestInfo.d.ts +47 -0
  19. package/dist/helpers/requestInfo.d.ts.map +1 -0
  20. package/dist/helpers/requestInfo.js +156 -0
  21. package/dist/helpers/s3Storage.d.ts +24 -2
  22. package/dist/helpers/s3Storage.d.ts.map +1 -1
  23. package/dist/helpers/s3Storage.js +73 -5
  24. package/dist/helpers/sessions.d.ts +51 -3
  25. package/dist/helpers/sessions.d.ts.map +1 -1
  26. package/dist/helpers/sessions.js +144 -11
  27. package/dist/index.d.ts +8 -5
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +16 -2
  30. package/dist/interfaces/company.interface.d.ts +2 -0
  31. package/dist/interfaces/company.interface.d.ts.map +1 -1
  32. package/dist/interfaces/session.interface.d.ts +2 -0
  33. package/dist/interfaces/session.interface.d.ts.map +1 -1
  34. package/dist/interfaces/subscription.interface.d.ts +2 -0
  35. package/dist/interfaces/subscription.interface.d.ts.map +1 -1
  36. package/dist/interfaces/ticket.interface.d.ts +30 -26
  37. package/dist/interfaces/ticket.interface.d.ts.map +1 -1
  38. package/dist/interfaces/ticket.interface.js +28 -4
  39. package/dist/interfaces/user.interface.d.ts +4 -0
  40. package/dist/interfaces/user.interface.d.ts.map +1 -1
  41. package/dist/interfaces/vertical.interface.d.ts +1 -1
  42. package/dist/interfaces/vertical.interface.d.ts.map +1 -1
  43. package/dist/models/company.model.d.ts.map +1 -1
  44. package/dist/models/company.model.js +3 -0
  45. package/dist/models/session.model.d.ts.map +1 -1
  46. package/dist/models/session.model.js +4 -0
  47. package/dist/models/subscription.model.d.ts.map +1 -1
  48. package/dist/models/subscription.model.js +4 -0
  49. package/dist/models/ticket.model.d.ts.map +1 -1
  50. package/dist/models/ticket.model.js +24 -38
  51. package/dist/models/user.model.d.ts.map +1 -1
  52. package/dist/models/user.model.js +7 -0
  53. package/dist/models/vertical.model.js +1 -1
  54. package/dist/routing/ticketRouting.d.ts +11 -1
  55. package/dist/routing/ticketRouting.d.ts.map +1 -1
  56. package/dist/routing/ticketRouting.js +82 -33
  57. package/dist/utils/ticketSanitize.d.ts.map +1 -1
  58. package/dist/utils/ticketSanitize.js +4 -0
  59. package/package.json +1 -1
@@ -19,6 +19,10 @@ export interface IUser extends mongoose.Document {
19
19
  groupIds?: mongoose.Types.ObjectId[];
20
20
  /** Support Agent/Manager: cap on open tickets, used by the routing engine's fewest-open pick. */
21
21
  maxOpenTickets?: number;
22
+ /** Ops login: the ticket teams this person works ("billing" / "scripting" / "general"). The
23
+ * routing engine sends each team's tickets to its members; a Support Agent/Manager with none
24
+ * set counts as General Support. */
25
+ ticketTeams?: ("billing" | "scripting" | "general")[];
22
26
  /** Support Agent/Manager: their manager, for the Support Manager's team roll-up. */
23
27
  reportsTo?: mongoose.Types.ObjectId;
24
28
  currentStatus?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"user.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/user.interface.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"user.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/user.interface.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ export interface IVertical {
4
4
  _id?: Types.ObjectId;
5
5
  name: string;
6
6
  type: VerticalType;
7
- host: string;
7
+ host?: string;
8
8
  industry?: string;
9
9
  companyName?: string;
10
10
  companyKey?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"vertical.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/vertical.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,kBAAkB,GAAG,gBAAgB,CAAC;AAE7E,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB"}
1
+ {"version":3,"file":"vertical.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/vertical.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,kBAAkB,GAAG,gBAAgB,CAAC;AAE7E,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB"}
@@ -1 +1 @@
1
- {"version":3,"file":"company.model.d.ts","sourceRoot":"","sources":["../../src/models/company.model.ts"],"names":[],"mappings":"AAAA,OAAO,QAA2B,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AA4Q3D,eAAO,MAAM,OAAO;;;;OAAqD,CAAC;AAC1E,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"company.model.d.ts","sourceRoot":"","sources":["../../src/models/company.model.ts"],"names":[],"mappings":"AAAA,OAAO,QAA2B,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AA+Q3D,eAAO,MAAM,OAAO;;;;OAAqD,CAAC;AAC1E,eAAe,OAAO,CAAC"}
@@ -42,6 +42,9 @@ const companySchema = new mongoose_1.Schema({
42
42
  clientInstructionEnabled: { type: Boolean, default: false },
43
43
  // Ops-controlled: the client can see its own company's Activity log (given on request).
44
44
  activityLogAccess: { type: Boolean, default: false },
45
+ // The month ("2026-09") whose summary email was last sent to the company's main contact; set before
46
+ // sending (an atomic claim), so a restart or a second run never sends the same month twice.
47
+ monthlySummarySentFor: { type: String },
45
48
  // The script folders Ops picked for this company (Account > Script > Insert Vertical), in the
46
49
  // order they were arranged. Agents see exactly these, in this order, when the company's chat
47
50
  // lands, and so does the lead page's View Script panel.
@@ -1 +1 @@
1
- {"version":3,"file":"session.model.d.ts","sourceRoot":"","sources":["../../src/models/session.model.ts"],"names":[],"mappings":"AAAA,OAAO,QAAoB,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAmB3D,eAAO,MAAM,OAAO;;;;OAAqD,CAAC"}
1
+ {"version":3,"file":"session.model.d.ts","sourceRoot":"","sources":["../../src/models/session.model.ts"],"names":[],"mappings":"AAAA,OAAO,QAAoB,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAuB3D,eAAO,MAAM,OAAO;;;;OAAqD,CAAC"}
@@ -43,6 +43,10 @@ const sessionSchema = new mongoose_1.Schema({
43
43
  browser: { type: String },
44
44
  os: { type: String },
45
45
  ipAddress: { type: String },
46
+ // "Lahore, Pakistan" from Cloudflare's visitor-location headers, when the request had them.
47
+ location: { type: String },
48
+ // The name the person gave this device ("Tahir's HP laptop"); carried over to later sign-ins from the same device.
49
+ customName: { type: String, trim: true, maxlength: 40 },
46
50
  userAgent: { type: String },
47
51
  isRevoked: { type: Boolean, default: false },
48
52
  lastActiveAt: { type: Date, default: Date.now },
@@ -1 +1 @@
1
- {"version":3,"file":"subscription.model.d.ts","sourceRoot":"","sources":["../../src/models/subscription.model.ts"],"names":[],"mappings":"AAAA,OAAO,QAAoB,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AA6LrE,eAAO,MAAM,YAAY;;;;OAGxB,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"subscription.model.d.ts","sourceRoot":"","sources":["../../src/models/subscription.model.ts"],"names":[],"mappings":"AAAA,OAAO,QAAoB,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAiMrE,eAAO,MAAM,YAAY;;;;OAGxB,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -85,6 +85,10 @@ const subscriptionSchema = new mongoose_1.Schema({
85
85
  stripeSubscriptionItemId: { type: String },
86
86
  stripePriceId: { type: String },
87
87
  quantity: { type: Number, default: 1, min: 1 },
88
+ // Set when the client removed the add-on on a paid plan: it stays on until this date (the end of the
89
+ // period already paid for) and is taken off then, with no refund. Copied from the Stripe item's
90
+ // metadata on every sync, so the wholesale rebuild of `addons` keeps it.
91
+ removeAt: { type: Date },
88
92
  },
89
93
  ],
90
94
  // Ops-controlled pause list. Kept outside `addons` on purpose: the Stripe sync rebuilds
@@ -1 +1 @@
1
- {"version":3,"file":"ticket.model.d.ts","sourceRoot":"","sources":["../../src/models/ticket.model.ts"],"names":[],"mappings":"AAAA,OAAO,QAAoB,MAAM,UAAU,CAAC;AAE5C,OAAO,EACL,OAAO,EAIR,MAAM,gCAAgC,CAAC;AAsQxC,eAAO,MAAM,MAAM;;;;OAAkD,CAAC;AACtE,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"ticket.model.d.ts","sourceRoot":"","sources":["../../src/models/ticket.model.ts"],"names":[],"mappings":"AAAA,OAAO,QAAoB,MAAM,UAAU,CAAC;AAE5C,OAAO,EACL,OAAO,EASR,MAAM,gCAAgC,CAAC;AAuPxC,eAAO,MAAM,MAAM;;;;OAAkD,CAAC;AACtE,eAAe,MAAM,CAAC"}
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.Ticket = void 0;
37
37
  const mongoose_1 = __importStar(require("mongoose"));
38
38
  const counter_model_1 = require("./counter.model");
39
+ const ticket_interface_1 = require("../interfaces/ticket.interface");
39
40
  const ticketAttachmentSchema = new mongoose_1.Schema({
40
41
  url: { type: String, required: true, trim: true },
41
42
  s3Key: { type: String, required: true, trim: true },
@@ -111,24 +112,15 @@ const ticketSchema = new mongoose_1.Schema({
111
112
  },
112
113
  category: {
113
114
  type: String,
115
+ // Every value that can appear on a ticket: the current Client/Partner lists plus the legacy
116
+ // values old tickets were filed under (never offered on a new ticket).
114
117
  enum: [
115
- // Client -- current taxonomy
116
- "dispute-billable-lead",
117
- "invoice-dispute",
118
- "technical-support",
119
- "account-support",
120
- // Client -- legacy, kept valid for old tickets only (never offered on new-ticket forms)
121
- "chat-dispute",
122
- // Partner -- current taxonomy
123
- "failed-withdrawal",
124
- "failed-transfer",
125
- // "technical-support"/"account-support" above are shared with Client
126
- // Partner -- legacy, kept valid for old tickets only
127
- "dashboard-technical-issue",
128
- "payout-issue",
129
- "referral-issue",
130
- "review-submission-issue",
131
- "other",
118
+ ...new Set([
119
+ ...ticket_interface_1.CLIENT_TICKET_CATEGORIES,
120
+ ...ticket_interface_1.CLIENT_TICKET_CATEGORIES_LEGACY,
121
+ ...ticket_interface_1.PARTNER_TICKET_CATEGORIES,
122
+ ...ticket_interface_1.PARTNER_TICKET_CATEGORIES_LEGACY,
123
+ ]),
132
124
  ],
133
125
  index: true,
134
126
  },
@@ -161,6 +153,13 @@ const ticketSchema = new mongoose_1.Schema({
161
153
  default: "open",
162
154
  index: true,
163
155
  },
156
+ // Which team handles it (billing / scripting / account-manager / general), from its category
157
+ // and sub-category -- see ticketTeamFor in constants/ticketCategories.ts.
158
+ team: {
159
+ type: String,
160
+ enum: ticket_interface_1.TICKET_TEAMS,
161
+ index: true,
162
+ },
164
163
  priority: {
165
164
  type: String,
166
165
  enum: ["urgent", "high", "normal", "low"],
@@ -196,32 +195,19 @@ const ticketSchema = new mongoose_1.Schema({
196
195
  },
197
196
  resolvedAt: Date,
198
197
  isSpam: { type: Boolean, default: false, index: true },
198
+ // Ops team email alerts (ops-dashboard services/ticketAlerts.service.js): when the new-ticket
199
+ // alert and the 24-hour no-reply escalation went out. Each is sent once per ticket.
200
+ teamAlertSentAt: Date,
201
+ slaEscalatedAt: Date,
199
202
  }, {
200
203
  timestamps: true,
201
204
  toJSON: { virtuals: true },
202
205
  toObject: { virtuals: true },
203
206
  });
204
- // "technical-support"/"account-support" are shared category values, valid on both dashboards --
205
- // deliberately listed in both arrays below rather than pulled out, so each array alone still
206
- // reads as "every category this ownerType may use."
207
- const CLIENT_ONLY_CATEGORIES = [
208
- "dispute-billable-lead",
209
- "chat-dispute",
210
- "invoice-dispute",
211
- "technical-support",
212
- "account-support",
213
- ];
214
- const PARTNER_ONLY_CATEGORIES = [
215
- "failed-withdrawal",
216
- "failed-transfer",
217
- "technical-support",
218
- "account-support",
219
- "dashboard-technical-issue",
220
- "payout-issue",
221
- "referral-issue",
222
- "review-submission-issue",
223
- "other",
224
- ];
207
+ // Every category each ownerType may use (current + legacy). Some values -- "dashboard", "account",
208
+ // "something-else" and the legacy "technical-support"/"account-support" -- are valid on both.
209
+ const CLIENT_ONLY_CATEGORIES = [...ticket_interface_1.CLIENT_TICKET_CATEGORIES, ...ticket_interface_1.CLIENT_TICKET_CATEGORIES_LEGACY];
210
+ const PARTNER_ONLY_CATEGORIES = [...ticket_interface_1.PARTNER_TICKET_CATEGORIES, ...ticket_interface_1.PARTNER_TICKET_CATEGORIES_LEGACY];
225
211
  ticketSchema.pre("validate", function () {
226
212
  if (this.source === "dashboard") {
227
213
  if (!this.ownerType || !this.ownerId) {
@@ -1 +1 @@
1
- {"version":3,"file":"user.model.d.ts","sourceRoot":"","sources":["../../src/models/user.model.ts"],"names":[],"mappings":"AAAA,OAAO,QAAoB,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAkSrD,eAAO,MAAM,IAAI;;;;OAA4C,CAAC"}
1
+ {"version":3,"file":"user.model.d.ts","sourceRoot":"","sources":["../../src/models/user.model.ts"],"names":[],"mappings":"AAAA,OAAO,QAAoB,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AA0SrD,eAAO,MAAM,IAAI;;;;OAA4C,CAAC"}
@@ -177,6 +177,13 @@ const userSchema = new mongoose_1.Schema({
177
177
  type: Number,
178
178
  default: 15,
179
179
  },
180
+ // Ticket teams this Ops login works (Billing / Scripting / General Support) -- the routing
181
+ // engine (routing/ticketRouting.ts) sends each team's tickets to its members. A Support
182
+ // Agent/Manager with none set counts as General Support.
183
+ ticketTeams: {
184
+ type: [{ type: String, enum: ["billing", "scripting", "general"] }],
185
+ default: undefined,
186
+ },
180
187
  reportsTo: {
181
188
  type: mongoose_1.Schema.Types.ObjectId,
182
189
  ref: "User",
@@ -46,9 +46,9 @@ const verticalSchema = new mongoose_1.Schema({
46
46
  enum: ["General", "IndustrySpecific", "ClientSpecific"],
47
47
  required: [true, "Vertical type is required"],
48
48
  },
49
+ // No longer asked for (Oct 2026); old folders keep their value, nothing reads it.
49
50
  host: {
50
51
  type: String,
51
- required: [true, "Host (creator/owner) is required"],
52
52
  },
53
53
  industry: {
54
54
  type: String,
@@ -1,15 +1,25 @@
1
1
  import { Types } from "mongoose";
2
- import { TicketOwnerType, TicketCategory } from "../interfaces/ticket.interface";
2
+ import { TicketOwnerType, TicketCategory, TicketTeam } from "../interfaces/ticket.interface";
3
3
  export declare const OPEN_TICKET_STATUSES: readonly ["open", "in_progress", "awaiting_client", "awaiting_internal"];
4
4
  export interface TicketRoutingInput {
5
5
  ownerType: TicketOwnerType;
6
6
  ownerId: Types.ObjectId | string;
7
7
  category?: TicketCategory;
8
+ subCategory?: string;
8
9
  }
9
10
  export interface TicketRoutingResult {
10
11
  assigneeId?: Types.ObjectId;
11
12
  followerIds: Types.ObjectId[];
13
+ /** The team the ticket's category belongs to (undefined while it has no category). */
14
+ team?: TicketTeam;
12
15
  }
13
16
  export declare function pickFromGroup(groupId: Types.ObjectId | string): Promise<Types.ObjectId | undefined>;
17
+ /** Ops logins on a ticket team (General also takes any Support Agent/Manager with no team set). */
18
+ export declare function ticketTeamMembers(team: Exclude<TicketTeam, "account-manager">): Promise<(import("mongoose").FlattenMaps<import("..").IUser> & Required<{
19
+ _id: import("mongoose").FlattenMaps<unknown>;
20
+ }> & {
21
+ __v: number;
22
+ })[]>;
23
+ export declare function pickFromTicketTeam(team: Exclude<TicketTeam, "account-manager">, preferGroupId?: Types.ObjectId | string): Promise<Types.ObjectId | undefined>;
14
24
  export declare function resolveTicketRouting(ticket: TicketRoutingInput): Promise<TicketRoutingResult>;
15
25
  //# sourceMappingURL=ticketRouting.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ticketRouting.d.ts","sourceRoot":"","sources":["../../src/routing/ticketRouting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAMjC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAoBjF,eAAO,MAAM,oBAAoB,0EAKvB,CAAC;AAEX,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC;IAC5B,WAAW,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;CAC/B;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC,CA2BzG;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAmCnG"}
1
+ {"version":3,"file":"ticketRouting.d.ts","sourceRoot":"","sources":["../../src/routing/ticketRouting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAOjC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAsB7F,eAAO,MAAM,oBAAoB,0EAKvB,CAAC;AAIX,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC;IAC5B,WAAW,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC9B,sFAAsF;IACtF,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAoCD,wBAAsB,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC,CAKzG;AAED,mGAAmG;AACnG,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC;;;;MAkBnF;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC,EAC5C,aAAa,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG,MAAM,GACtC,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC,CAErC;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA+CnG"}
@@ -2,40 +2,45 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OPEN_TICKET_STATUSES = void 0;
4
4
  exports.pickFromGroup = pickFromGroup;
5
+ exports.ticketTeamMembers = ticketTeamMembers;
6
+ exports.pickFromTicketTeam = pickFromTicketTeam;
5
7
  exports.resolveTicketRouting = resolveTicketRouting;
6
8
  const company_model_1 = require("../models/company.model");
7
9
  const partner_model_1 = require("../models/partner.model");
8
10
  const group_model_1 = require("../models/group.model");
9
11
  const user_model_1 = require("../models/user.model");
12
+ const role_model_1 = require("../models/role.model");
10
13
  const ticket_model_1 = require("../models/ticket.model");
11
- // Resolves who a ticket should go to, per the support-desk plan's ordered routing rules --
12
- // implemented as far as the real category taxonomy currently allows (a richer category list --
13
- // Technical Support, Account Support and their sub-options -- is still "Planned", so the "Account
14
- // Support goes straight to the Account Manager" rule can't be expressed yet; it becomes a one-line
15
- // addition here once that taxonomy exists).
16
- //
14
+ const ticketCategories_1 = require("../constants/ticketCategories");
15
+ // Resolves who a ticket should go to. Every category (or sub-category) names the team that handles
16
+ // it (constants/ticketCategories.ts -> ticketTeamFor):
17
+ // billing / scripting / general -- the Ops logins on that Ticket Team (User.ticketTeams; a
18
+ // Support Agent/Manager with no team set counts as General)
19
+ // account-manager -- the ticket owner's own Account Manager
17
20
  // Order:
18
- // 1. The ticket owner's own Group (Company.groupId), if active -- e.g. a "Law" group.
19
- // 2. A Group that handles this ticket's category (Group.handlesTicketCategories), if active.
20
- // 3. Otherwise unassigned -- left for the pool, a team lead notices it in "Unassigned" (Phase 28).
21
- // Whoever gets picked is the User in that group's membership (User.groupIds) with the fewest
22
- // currently-open tickets, among those still under their own maxOpenTickets. A Company's own
23
- // Account Manager is always added as a follower, whoever ends up assigned.
21
+ // 1. The ticket's team. Within a team, people already scoped to the owner's Group are preferred.
22
+ // 2. Nobody available there (no Account Manager on the account, nobody on the team, or everyone
23
+ // at their open-ticket limit) -> General Support.
24
+ // 3. Still nobody -> the older Group rules: the owner's own Group, then a Group that handles this
25
+ // category (Group.handlesTicketCategories).
26
+ // 4. Otherwise unassigned -- the new-ticket alert email then goes to every Support Manager.
27
+ // Whoever is picked from a team is the member with the fewest open tickets, among those still under
28
+ // their own maxOpenTickets. A Company's or Partner's Account Manager is always added as a follower.
24
29
  //
25
- // Shared by every backend that creates or re-triages a Ticket (Ops, Client, Partner) so all three
26
- // apply the exact same rule instead of three copies drifting apart -- Ops's own
27
- // `POST /:id/auto-assign` and its triage-time re-route inside `updateTicket` both call this too.
30
+ // Shared by every backend that creates or re-routes a Ticket (Ops, Client, Partner) so all three
31
+ // apply the exact same rule -- Ops's `POST /:id/auto-assign` and its re-route when a ticket's
32
+ // category changes call this too.
28
33
  exports.OPEN_TICKET_STATUSES = [
29
34
  "open",
30
35
  "in_progress",
31
36
  "awaiting_client",
32
37
  "awaiting_internal",
33
38
  ];
34
- async function pickFromGroup(groupId) {
39
+ const GENERAL_SUPPORT_ROLE_KEYS = ["support-agent", "support-manager"];
40
+ // The member with the fewest open tickets who is still under their limit; members already scoped
41
+ // to `preferGroupId` win ties first.
42
+ async function pickLeastBusy(members, preferGroupId) {
35
43
  var _a;
36
- const members = await user_model_1.User.find({ groupIds: groupId, lockedOut: { $ne: true } })
37
- .select("_id maxOpenTickets")
38
- .lean();
39
44
  if (members.length === 0)
40
45
  return undefined;
41
46
  const counts = await ticket_model_1.Ticket.aggregate([
@@ -48,6 +53,7 @@ async function pickFromGroup(groupId) {
48
53
  { $group: { _id: "$assigneeId", count: { $sum: 1 } } },
49
54
  ]);
50
55
  const openByUser = new Map(counts.map((c) => [String(c._id), c.count]));
56
+ const inGroup = (m) => preferGroupId ? (m.groupIds || []).some((g) => String(g) === String(preferGroupId)) : false;
51
57
  const eligible = members
52
58
  .map((m) => {
53
59
  var _a;
@@ -55,12 +61,42 @@ async function pickFromGroup(groupId) {
55
61
  id: m._id,
56
62
  open: openByUser.get(String(m._id)) || 0,
57
63
  limit: (_a = m.maxOpenTickets) !== null && _a !== void 0 ? _a : 15,
64
+ preferred: inGroup(m),
58
65
  });
59
66
  })
60
67
  .filter((m) => m.open < m.limit)
61
- .sort((a, b) => a.open - b.open);
68
+ .sort((a, b) => Number(b.preferred) - Number(a.preferred) || a.open - b.open);
62
69
  return (_a = eligible[0]) === null || _a === void 0 ? void 0 : _a.id;
63
70
  }
71
+ async function pickFromGroup(groupId) {
72
+ const members = await user_model_1.User.find({ groupIds: groupId, lockedOut: { $ne: true } })
73
+ .select("_id maxOpenTickets groupIds")
74
+ .lean();
75
+ return pickLeastBusy(members);
76
+ }
77
+ /** Ops logins on a ticket team (General also takes any Support Agent/Manager with no team set). */
78
+ async function ticketTeamMembers(team) {
79
+ const base = { ownerType: "ORBITXPRO", lockedOut: { $ne: true } };
80
+ if (team !== "general") {
81
+ return user_model_1.User.find({ ...base, ticketTeams: team }).select("_id name email maxOpenTickets groupIds").lean();
82
+ }
83
+ const supportRoles = await role_model_1.Role.find({ key: { $in: GENERAL_SUPPORT_ROLE_KEYS } }).select("_id").lean();
84
+ return user_model_1.User.find({
85
+ ...base,
86
+ $or: [
87
+ { ticketTeams: "general" },
88
+ {
89
+ roleId: { $in: supportRoles.map((r) => r._id) },
90
+ $and: [{ $or: [{ ticketTeams: { $exists: false } }, { ticketTeams: { $size: 0 } }] }],
91
+ },
92
+ ],
93
+ })
94
+ .select("_id name email maxOpenTickets groupIds")
95
+ .lean();
96
+ }
97
+ async function pickFromTicketTeam(team, preferGroupId) {
98
+ return pickLeastBusy((await ticketTeamMembers(team)), preferGroupId);
99
+ }
64
100
  async function resolveTicketRouting(ticket) {
65
101
  var _a, _b;
66
102
  const followerIds = [];
@@ -68,30 +104,43 @@ async function resolveTicketRouting(ticket) {
68
104
  // `any` here deliberately -- Company and Partner are two distinct Mongoose models with
69
105
  // differently-typed findById overloads that TS can't unify through a variable holding either.
70
106
  const Owner = ticket.ownerType === "Partner" ? partner_model_1.Partner : company_model_1.Company;
71
- // Real bug, found and fixed here: this selected a top-level `accountManager` field that
72
- // exists on neither model (Company's is nested at basicInfo.accountManager, Partner's at
73
- // accountInfo.accountManager) -- the Account Manager has never actually been auto-added as a
74
- // ticket follower, on any ticket, since this was built, despite the model's own comment saying
75
- // they always are.
107
+ // Company's Account Manager is nested at basicInfo.accountManager, Partner's at
108
+ // accountInfo.accountManager.
76
109
  const owner = await Owner.findById(ticket.ownerId)
77
110
  .select("groupId basicInfo.accountManager accountInfo.accountManager")
78
111
  .lean();
79
112
  const accountManagerId = ticket.ownerType === "Partner" ? (_a = owner === null || owner === void 0 ? void 0 : owner.accountInfo) === null || _a === void 0 ? void 0 : _a.accountManager : (_b = owner === null || owner === void 0 ? void 0 : owner.basicInfo) === null || _b === void 0 ? void 0 : _b.accountManager;
80
113
  if (accountManagerId)
81
114
  followerIds.push(accountManagerId);
82
- // Rule 1: the owner's own group (Company only today -- Partner has no groupId field yet).
83
- if (ticket.ownerType === "Company" && (owner === null || owner === void 0 ? void 0 : owner.groupId)) {
84
- const group = await group_model_1.Group.findOne({ _id: owner.groupId, isActive: true }).select("_id").lean();
115
+ const team = (0, ticketCategories_1.ticketTeamFor)(ticket.ownerType, ticket.category, ticket.subCategory);
116
+ const preferGroupId = ticket.ownerType === "Company" ? owner === null || owner === void 0 ? void 0 : owner.groupId : undefined;
117
+ // 1. The ticket's own team.
118
+ if (team === "account-manager") {
119
+ if (accountManagerId) {
120
+ const manager = await user_model_1.User.findOne({ _id: accountManagerId, lockedOut: { $ne: true } }).select("_id").lean();
121
+ if (manager)
122
+ assigneeId = manager._id;
123
+ }
124
+ }
125
+ else if (team) {
126
+ assigneeId = await pickFromTicketTeam(team, preferGroupId);
127
+ }
128
+ // 2. General Support picks up anything its own team couldn't take.
129
+ if (!assigneeId && team && team !== "general") {
130
+ assigneeId = await pickFromTicketTeam("general", preferGroupId);
131
+ }
132
+ // 3. The older Group rules.
133
+ if (!assigneeId && preferGroupId) {
134
+ const group = await group_model_1.Group.findOne({ _id: preferGroupId, isActive: true }).select("_id").lean();
85
135
  if (group)
86
136
  assigneeId = await pickFromGroup(group._id);
87
137
  }
88
- // Rule 2: a group that specifically handles this ticket's category.
89
138
  if (!assigneeId && ticket.category) {
90
- const team = await group_model_1.Group.findOne({ isActive: true, handlesTicketCategories: ticket.category })
139
+ const handlingGroup = await group_model_1.Group.findOne({ isActive: true, handlesTicketCategories: ticket.category })
91
140
  .select("_id")
92
141
  .lean();
93
- if (team)
94
- assigneeId = await pickFromGroup(team._id);
142
+ if (handlingGroup)
143
+ assigneeId = await pickFromGroup(handlingGroup._id);
95
144
  }
96
- return { assigneeId, followerIds };
145
+ return { assigneeId, followerIds, team };
97
146
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ticketSanitize.d.ts","sourceRoot":"","sources":["../../src/utils/ticketSanitize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEzE;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAA;CAAE,EACrG,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GAC3B,CAAC,GAAG,IAAI,GAAG,SAAS,CAkBtB"}
1
+ {"version":3,"file":"ticketSanitize.d.ts","sourceRoot":"","sources":["../../src/utils/ticketSanitize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEzE;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAA;CAAE,EACrG,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GAC3B,CAAC,GAAG,IAAI,GAAG,SAAS,CAsBtB"}
@@ -29,5 +29,9 @@ function sanitizeTicketForRequester(ticket) {
29
29
  delete ticket.followerIds;
30
30
  delete ticket.assigneeId;
31
31
  delete ticket.priority;
32
+ // Internal routing and alert bookkeeping.
33
+ delete ticket.team;
34
+ delete ticket.teamAlertSentAt;
35
+ delete ticket.slaEscalatedAt;
32
36
  return ticket;
33
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orbitx-core-models",
3
- "version": "11.178.0",
3
+ "version": "11.180.0",
4
4
  "description": "Shared Mongoose models and interfaces for OrbitX services",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",