orbitx-core-models 11.178.0 → 11.179.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.
- package/dist/activity/recorder.d.ts +2 -2
- package/dist/activity/recorder.d.ts.map +1 -1
- package/dist/activity/recorder.js +4 -7
- package/dist/constants/ticketCategories.d.ts +41 -20
- package/dist/constants/ticketCategories.d.ts.map +1 -1
- package/dist/constants/ticketCategories.js +212 -53
- package/dist/helpers/emailTemplates.d.ts.map +1 -1
- package/dist/helpers/emailTemplates.js +4 -5
- package/dist/helpers/ownTickets.d.ts.map +1 -1
- package/dist/helpers/ownTickets.js +13 -6
- package/dist/helpers/requestInfo.d.ts +47 -0
- package/dist/helpers/requestInfo.d.ts.map +1 -0
- package/dist/helpers/requestInfo.js +156 -0
- package/dist/helpers/sessions.d.ts +44 -3
- package/dist/helpers/sessions.d.ts.map +1 -1
- package/dist/helpers/sessions.js +126 -11
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -2
- package/dist/interfaces/session.interface.d.ts +2 -0
- package/dist/interfaces/session.interface.d.ts.map +1 -1
- package/dist/interfaces/subscription.interface.d.ts +2 -0
- package/dist/interfaces/subscription.interface.d.ts.map +1 -1
- package/dist/interfaces/ticket.interface.d.ts +30 -26
- package/dist/interfaces/ticket.interface.d.ts.map +1 -1
- package/dist/interfaces/ticket.interface.js +28 -4
- package/dist/interfaces/user.interface.d.ts +4 -0
- package/dist/interfaces/user.interface.d.ts.map +1 -1
- package/dist/interfaces/vertical.interface.d.ts +1 -1
- package/dist/interfaces/vertical.interface.d.ts.map +1 -1
- package/dist/models/session.model.d.ts.map +1 -1
- package/dist/models/session.model.js +4 -0
- package/dist/models/subscription.model.d.ts.map +1 -1
- package/dist/models/subscription.model.js +4 -0
- package/dist/models/ticket.model.d.ts.map +1 -1
- package/dist/models/ticket.model.js +24 -38
- package/dist/models/user.model.d.ts.map +1 -1
- package/dist/models/user.model.js +7 -0
- package/dist/models/vertical.model.js +1 -1
- package/dist/routing/ticketRouting.d.ts +11 -1
- package/dist/routing/ticketRouting.d.ts.map +1 -1
- package/dist/routing/ticketRouting.js +82 -33
- package/dist/utils/ticketSanitize.d.ts.map +1 -1
- package/dist/utils/ticketSanitize.js +4 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ActivityDashboard, IActivityChange } from "../interfaces/activityLog.interface";
|
|
2
|
+
import { clientIp } from "../helpers/requestInfo";
|
|
2
3
|
export type ActivityActor = {
|
|
3
4
|
kind: "ops" | "agent" | "client" | "partner" | "system";
|
|
4
5
|
id?: unknown;
|
|
@@ -72,7 +73,6 @@ export interface ActivityRecorderOptions {
|
|
|
72
73
|
ignore?: RegExp[];
|
|
73
74
|
sessionOf?: (req: Req) => string | undefined;
|
|
74
75
|
}
|
|
75
|
-
export
|
|
76
|
+
export { clientIp };
|
|
76
77
|
export declare function activityRecorder(options: ActivityRecorderOptions): (req: Req, res: Res, next: () => void) => void;
|
|
77
|
-
export {};
|
|
78
78
|
//# sourceMappingURL=recorder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/activity/recorder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/activity/recorder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clientIp = void 0;
|
|
3
4
|
exports.recordActivity = recordActivity;
|
|
4
|
-
exports.clientIp = clientIp;
|
|
5
5
|
exports.activityRecorder = activityRecorder;
|
|
6
6
|
const mongoose_1 = require("mongoose");
|
|
7
7
|
const activityLog_model_1 = require("../models/activityLog.model");
|
|
8
|
+
const requestInfo_1 = require("../helpers/requestInfo");
|
|
9
|
+
Object.defineProperty(exports, "clientIp", { enumerable: true, get: function () { return requestInfo_1.clientIp; } });
|
|
8
10
|
const asId = (v) => (v && mongoose_1.Types.ObjectId.isValid(String(v)) ? new mongoose_1.Types.ObjectId(String(v)) : undefined);
|
|
9
11
|
const clip = (v, n) => (v == null ? undefined : String(v).slice(0, n));
|
|
10
12
|
/** Writes one record. Never throws; a failure is only logged. */
|
|
@@ -60,11 +62,6 @@ function humanize(path) {
|
|
|
60
62
|
.map((p) => p.replace(/[-_]/g, " "))
|
|
61
63
|
.join(" › ");
|
|
62
64
|
}
|
|
63
|
-
function clientIp(req) {
|
|
64
|
-
var _a, _b, _c;
|
|
65
|
-
const fwd = String(((_a = req.headers) === null || _a === void 0 ? void 0 : _a["x-forwarded-for"]) || "").split(",")[0].trim();
|
|
66
|
-
return fwd || ((_b = req.headers) === null || _b === void 0 ? void 0 : _b["x-real-ip"]) || ((_c = req.socket) === null || _c === void 0 ? void 0 : _c.remoteAddress) || undefined;
|
|
67
|
-
}
|
|
68
65
|
function activityRecorder(options) {
|
|
69
66
|
const rules = options.rules.map((r) => ({
|
|
70
67
|
...r,
|
|
@@ -120,7 +117,7 @@ function activityRecorder(options) {
|
|
|
120
117
|
record: (_h = rule === null || rule === void 0 ? void 0 : rule.record) === null || _h === void 0 ? void 0 : _h.call(rule, ctx),
|
|
121
118
|
outcome,
|
|
122
119
|
sensitive: !!(rule === null || rule === void 0 ? void 0 : rule.sensitive) || outcome !== "success",
|
|
123
|
-
ip: clientIp(req),
|
|
120
|
+
ip: (0, requestInfo_1.clientIp)(req),
|
|
124
121
|
userAgent: (_j = req.headers) === null || _j === void 0 ? void 0 : _j["user-agent"],
|
|
125
122
|
sessionId: (_k = options.sessionOf) === null || _k === void 0 ? void 0 : _k.call(options, req),
|
|
126
123
|
method,
|
|
@@ -1,30 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Single source of truth for the
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* a real settings-editable admin screen. That screen (add/edit a category without a code
|
|
6
|
-
* release) was asked for in the same Phase 28 batch and is deliberately NOT built here -- it's
|
|
7
|
-
* its own admin CRUD + cache-invalidation feature across three frontends, left for a dedicated
|
|
8
|
-
* pass. This file is the interim single source instead of four separate hardcoded copies.
|
|
2
|
+
* Single source of truth for the ticket category taxonomy -- the Client and Partner New Ticket
|
|
3
|
+
* forms, both backends' validation, Ops's ticket screens and Settings, and the routing engine all
|
|
4
|
+
* read these lists.
|
|
9
5
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
6
|
+
* Oct 2 2026 redesign: categories are named by topic, in the requester's own words, and every
|
|
7
|
+
* category says which team handles it (`team`; a sub-category can override it). The routing
|
|
8
|
+
* engine (routing/ticketRouting.ts) sends the ticket to that team:
|
|
9
|
+
* billing -- the Billing Team (Ops logins whose Ticket Team includes Billing)
|
|
10
|
+
* scripting -- the Scripting Team
|
|
11
|
+
* account-manager -- the Company's / Partner's own Account Manager
|
|
12
|
+
* general -- General Support
|
|
13
|
+
* Sub-categories an Ops admin adds from Settings have no team of their own and use their
|
|
14
|
+
* category's.
|
|
15
|
+
*
|
|
16
|
+
* Old tickets keep whatever category they were filed under; those values are listed below as
|
|
17
|
+
* Legacy (shown with "(Legacy)", never offered on a new ticket) per the "no remapping" decision.
|
|
14
18
|
*/
|
|
19
|
+
import type { TicketTeam } from "../interfaces/ticket.interface";
|
|
15
20
|
export interface TicketSubCategoryOption {
|
|
16
21
|
value: string;
|
|
17
22
|
label: string;
|
|
23
|
+
/** Overrides the category's team for this one sub-category. */
|
|
24
|
+
team?: TicketTeam;
|
|
18
25
|
}
|
|
19
26
|
export interface TicketCategoryOption {
|
|
20
27
|
value: string;
|
|
21
28
|
label: string;
|
|
29
|
+
/** One line shown under the category name on the New Ticket form, in the requester's words. */
|
|
30
|
+
description?: string;
|
|
31
|
+
/** Who handles tickets in this category (a sub-category's own team wins). */
|
|
32
|
+
team?: TicketTeam;
|
|
22
33
|
/** Shown under the category as its own dropdown when present; omitted categories skip it. */
|
|
23
34
|
subCategories?: TicketSubCategoryOption[];
|
|
24
35
|
/** The requester picks their own Chat/Lead ID from their own records (locked, not free text). */
|
|
25
36
|
requiresChatId?: boolean;
|
|
26
|
-
/** The requester
|
|
37
|
+
/** The requester gives an invoice / transaction reference (stored in the ticket's invoiceId). */
|
|
27
38
|
requiresInvoiceId?: boolean;
|
|
39
|
+
/** The label of that reference field ("Invoice ID" when unset). */
|
|
40
|
+
referenceLabel?: string;
|
|
28
41
|
}
|
|
29
42
|
export declare const CLIENT_TICKET_CATEGORY_OPTIONS: TicketCategoryOption[];
|
|
30
43
|
export declare const PARTNER_TICKET_CATEGORY_OPTIONS: TicketCategoryOption[];
|
|
@@ -33,18 +46,26 @@ export declare const PARTNER_TICKET_CATEGORY_OPTIONS: TicketCategoryOption[];
|
|
|
33
46
|
* accept and display these so an old ticket can be looked at, filtered and re-triaged. */
|
|
34
47
|
export declare const CLIENT_TICKET_CATEGORY_OPTIONS_LEGACY: TicketCategoryOption[];
|
|
35
48
|
export declare const PARTNER_TICKET_CATEGORY_OPTIONS_LEGACY: TicketCategoryOption[];
|
|
36
|
-
/** Every category value that can appear on any ticket, old or new -- what
|
|
37
|
-
* "handles these ticket categories" checkbox list
|
|
38
|
-
* category on an old, not-yet-resolved ticket as well as the new taxonomy. */
|
|
49
|
+
/** Every category value that can appear on any ticket, old or new, each listed once -- what Ops's
|
|
50
|
+
* category filters and a Group's "handles these ticket categories" checkbox list offer. */
|
|
39
51
|
export declare const ALL_TICKET_CATEGORY_OPTIONS: TicketCategoryOption[];
|
|
40
52
|
/** Looks a category value up across every list (new + legacy, client + partner) -- for anywhere
|
|
41
|
-
* that just needs the label/shape without caring which dashboard it came from.
|
|
53
|
+
* that just needs the label/shape without caring which dashboard it came from. A value both
|
|
54
|
+
* portals use is defined once, so it reads the same either way. */
|
|
42
55
|
export declare function findTicketCategoryOption(value?: string | null): TicketCategoryOption | undefined;
|
|
56
|
+
/** The category list (current + legacy) for one owner type. */
|
|
57
|
+
export declare function ticketCategoryOptionsFor(ownerType?: "Company" | "Partner" | null): TicketCategoryOption[];
|
|
58
|
+
/** A category as one owner type sees it (falls back to any list for a value it doesn't have). */
|
|
59
|
+
export declare function findTicketCategoryOptionFor(ownerType: "Company" | "Partner" | null | undefined, value?: string | null): TicketCategoryOption | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Which team handles a ticket in this category / sub-category: the sub-category's own team, else
|
|
62
|
+
* the category's, else General Support. Undefined only when there is no category yet (an email
|
|
63
|
+
* ticket nobody has categorised).
|
|
64
|
+
*/
|
|
65
|
+
export declare function ticketTeamFor(ownerType: "Company" | "Partner" | null | undefined, category?: string | null, subCategory?: string | null): TicketTeam | undefined;
|
|
43
66
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* category here (invoice-dispute, failed-withdrawal, failed-transfer -- the requiresInvoiceId
|
|
47
|
-
* ones with no subCategories array at all) has no sub-categories to edit in the first place.
|
|
67
|
+
* The "Category lists kept in settings" admin screen -- the categories whose SUB-categories an
|
|
68
|
+
* admin can edit (never the category itself). Every current category that has sub-categories.
|
|
48
69
|
*/
|
|
49
70
|
export declare const EDITABLE_SUBCATEGORY_KEYS: {
|
|
50
71
|
ownerType: "Company" | "Partner";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ticketCategories.d.ts","sourceRoot":"","sources":["../../src/constants/ticketCategories.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ticketCategories.d.ts","sourceRoot":"","sources":["../../src/constants/ticketCategories.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAEjE,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,+FAA+F;IAC/F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAC1C,iGAAiG;IACjG,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iGAAiG;IACjG,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAoCD,eAAO,MAAM,8BAA8B,EAAE,oBAAoB,EAoGhE,CAAC;AAEF,eAAO,MAAM,+BAA+B,EAAE,oBAAoB,EAwDjE,CAAC;AA6BF;;0FAE0F;AAC1F,eAAO,MAAM,qCAAqC,EAAE,oBAAoB,EAGvE,CAAC;AAEF,eAAO,MAAM,sCAAsC,EAAE,oBAAoB,EAOxE,CAAC;AAEF;2FAC2F;AAC3F,eAAO,MAAM,2BAA2B,EAAE,oBAAoB,EAKc,CAAC;AAO7E;;mEAEmE;AACnE,wBAAgB,wBAAwB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,oBAAoB,GAAG,SAAS,CAEhG;AAED,+DAA+D;AAC/D,wBAAgB,wBAAwB,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,GAAG,oBAAoB,EAAE,CAIzG;AAED,iGAAiG;AACjG,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS,EACnD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACpB,oBAAoB,GAAG,SAAS,CAElC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS,EACnD,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,UAAU,GAAG,SAAS,CAKxB;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE;IAAE,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EASlG,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,oBAAoB,EAAE,EAChC,SAAS,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,uBAAuB,EAAE,CAAA;CAAE,EAAE,GAC/E,oBAAoB,EAAE,CAOxB"}
|
|
@@ -1,26 +1,61 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Single source of truth for the Phase 28 ticket category taxonomy -- imported by the Client and
|
|
4
|
-
* Partner ticket-creation forms, both dashboards' ticket controllers (validation), and Ops's
|
|
5
|
-
* Group "handles these ticket categories" checkbox list, so all four places stay in sync without
|
|
6
|
-
* a real settings-editable admin screen. That screen (add/edit a category without a code
|
|
7
|
-
* release) was asked for in the same Phase 28 batch and is deliberately NOT built here -- it's
|
|
8
|
-
* its own admin CRUD + cache-invalidation feature across three frontends, left for a dedicated
|
|
9
|
-
* pass. This file is the interim single source instead of four separate hardcoded copies.
|
|
10
|
-
*
|
|
11
|
-
* Old tickets keep whatever legacy category they were filed under (chat-dispute,
|
|
12
|
-
* dashboard-technical-issue, payout-issue, referral-issue, review-submission-issue, other) --
|
|
13
|
-
* see CLIENT_TICKET_CATEGORIES_LEGACY/PARTNER_TICKET_CATEGORIES_LEGACY in ticket.interface.ts.
|
|
14
|
-
* Per the "no remapping" decision, those are shown as Legacy and never migrated.
|
|
15
|
-
*/
|
|
16
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
3
|
exports.EDITABLE_SUBCATEGORY_KEYS = exports.ALL_TICKET_CATEGORY_OPTIONS = exports.PARTNER_TICKET_CATEGORY_OPTIONS_LEGACY = exports.CLIENT_TICKET_CATEGORY_OPTIONS_LEGACY = exports.PARTNER_TICKET_CATEGORY_OPTIONS = exports.CLIENT_TICKET_CATEGORY_OPTIONS = void 0;
|
|
18
4
|
exports.findTicketCategoryOption = findTicketCategoryOption;
|
|
5
|
+
exports.ticketCategoryOptionsFor = ticketCategoryOptionsFor;
|
|
6
|
+
exports.findTicketCategoryOptionFor = findTicketCategoryOptionFor;
|
|
7
|
+
exports.ticketTeamFor = ticketTeamFor;
|
|
19
8
|
exports.applySubCategoryOverrides = applySubCategoryOverrides;
|
|
9
|
+
// Categories both portals offer, defined once so a shared value always means the same thing.
|
|
10
|
+
const DASHBOARD_PROBLEM = {
|
|
11
|
+
value: "dashboard",
|
|
12
|
+
label: "Dashboard Problem",
|
|
13
|
+
description: "Something in this dashboard is broken or slow",
|
|
14
|
+
team: "general",
|
|
15
|
+
subCategories: [
|
|
16
|
+
{ value: "error", label: "Error or Something Broken" },
|
|
17
|
+
{ value: "slow", label: "Slow or Not Loading" },
|
|
18
|
+
{ value: "other", label: "Other Dashboard Issue" },
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
const ACCOUNT_AND_LOGIN = {
|
|
22
|
+
value: "account",
|
|
23
|
+
label: "Account & Login",
|
|
24
|
+
description: "Signing in, users, your business details or account security",
|
|
25
|
+
team: "general",
|
|
26
|
+
subCategories: [
|
|
27
|
+
{ value: "login", label: "Can't Sign In" },
|
|
28
|
+
{ value: "users-permissions", label: "Users & Permissions" },
|
|
29
|
+
{ value: "business-details", label: "Business Details" },
|
|
30
|
+
{ value: "security", label: "Security / Unauthorized Access" },
|
|
31
|
+
{ value: "other", label: "Other Account Question" },
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
const SOMETHING_ELSE = {
|
|
35
|
+
value: "something-else",
|
|
36
|
+
label: "Something Else",
|
|
37
|
+
description: "Anything not listed above",
|
|
38
|
+
team: "general",
|
|
39
|
+
};
|
|
20
40
|
exports.CLIENT_TICKET_CATEGORY_OPTIONS = [
|
|
41
|
+
{
|
|
42
|
+
value: "leads",
|
|
43
|
+
label: "Leads & Lead Form",
|
|
44
|
+
description: "A lead you didn't get, lead emails, lead details or your lead form",
|
|
45
|
+
team: "account-manager",
|
|
46
|
+
subCategories: [
|
|
47
|
+
{ value: "lead-not-received", label: "Lead Not Received" },
|
|
48
|
+
{ value: "lead-emails", label: "Lead Emails Not Arriving" },
|
|
49
|
+
{ value: "lead-details", label: "Wrong or Missing Lead Details" },
|
|
50
|
+
{ value: "lead-form", label: "Lead Form / Lead Fields" },
|
|
51
|
+
{ value: "other", label: "Other Lead Question" },
|
|
52
|
+
],
|
|
53
|
+
},
|
|
21
54
|
{
|
|
22
55
|
value: "dispute-billable-lead",
|
|
23
|
-
label: "Dispute
|
|
56
|
+
label: "Dispute a Lead Charge",
|
|
57
|
+
description: "You were charged for a lead that shouldn't count",
|
|
58
|
+
team: "billing",
|
|
24
59
|
requiresChatId: true,
|
|
25
60
|
subCategories: [
|
|
26
61
|
{ value: "out-of-service", label: "Out of Service" },
|
|
@@ -28,47 +63,144 @@ exports.CLIENT_TICKET_CATEGORY_OPTIONS = [
|
|
|
28
63
|
{ value: "invalid", label: "Invalid" },
|
|
29
64
|
],
|
|
30
65
|
},
|
|
66
|
+
{
|
|
67
|
+
value: "billing",
|
|
68
|
+
label: "Billing & Payments",
|
|
69
|
+
description: "Payments, your card, your plan, add-ons or receipts",
|
|
70
|
+
team: "billing",
|
|
71
|
+
subCategories: [
|
|
72
|
+
{ value: "payment-failed", label: "Payment Failed / Card Issue" },
|
|
73
|
+
{ value: "plan-change", label: "Plan Change or Cancellation" },
|
|
74
|
+
{ value: "add-ons", label: "Add-ons" },
|
|
75
|
+
{ value: "invoice-question", label: "Invoice or Receipt Question" },
|
|
76
|
+
{ value: "other", label: "Other Billing Question" },
|
|
77
|
+
],
|
|
78
|
+
},
|
|
31
79
|
{
|
|
32
80
|
value: "invoice-dispute",
|
|
33
|
-
label: "Invoice
|
|
81
|
+
label: "Dispute an Invoice",
|
|
82
|
+
description: "Something on a specific invoice is wrong",
|
|
83
|
+
team: "billing",
|
|
34
84
|
requiresInvoiceId: true,
|
|
35
85
|
},
|
|
36
86
|
{
|
|
37
|
-
value: "
|
|
38
|
-
label: "
|
|
87
|
+
value: "scripts",
|
|
88
|
+
label: "Scripts & Chat Answers",
|
|
89
|
+
description: "What our agents say to your website visitors",
|
|
90
|
+
team: "scripting",
|
|
39
91
|
subCategories: [
|
|
40
|
-
{ value: "
|
|
41
|
-
{ value: "
|
|
42
|
-
{ value: "
|
|
43
|
-
{ value: "
|
|
44
|
-
{ value: "other", label: "Other" },
|
|
92
|
+
{ value: "wrong-answer", label: "Wrong or Outdated Answer" },
|
|
93
|
+
{ value: "missing-info", label: "Missing Information" },
|
|
94
|
+
{ value: "script-not-followed", label: "Agent Didn't Follow the Script" },
|
|
95
|
+
{ value: "templates", label: "Message Templates" },
|
|
96
|
+
{ value: "other", label: "Other Script Issue" },
|
|
45
97
|
],
|
|
46
98
|
},
|
|
47
99
|
{
|
|
48
|
-
value: "
|
|
49
|
-
label: "
|
|
100
|
+
value: "widget",
|
|
101
|
+
label: "Chat Widget & Website",
|
|
102
|
+
description: "The chat on your website, its look or the exit pop-up",
|
|
103
|
+
team: "general",
|
|
50
104
|
subCategories: [
|
|
51
|
-
{ value: "
|
|
52
|
-
{ value: "
|
|
53
|
-
{ value: "
|
|
54
|
-
{ value: "
|
|
105
|
+
{ value: "widget-not-showing", label: "Widget Not Showing" },
|
|
106
|
+
{ value: "widget-looks-wrong", label: "Widget Looks Wrong" },
|
|
107
|
+
{ value: "chat-not-working", label: "Chat Not Working Properly" },
|
|
108
|
+
{ value: "exit-popup", label: "Exit Pop-up" },
|
|
109
|
+
{ value: "other", label: "Other Widget Issue" },
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
value: "call-connect",
|
|
114
|
+
label: "Call Connect & SMS",
|
|
115
|
+
description: "Calls and text messages to your leads",
|
|
116
|
+
team: "account-manager",
|
|
117
|
+
subCategories: [
|
|
118
|
+
{ value: "calls-not-connecting", label: "Calls Not Connecting" },
|
|
119
|
+
{ value: "sms", label: "Text Messages (SMS)" },
|
|
120
|
+
{ value: "settings", label: "Call Connect Settings" },
|
|
121
|
+
{ value: "other", label: "Other Call Connect Question" },
|
|
55
122
|
],
|
|
56
123
|
},
|
|
124
|
+
{
|
|
125
|
+
value: "integrations",
|
|
126
|
+
label: "Integrations",
|
|
127
|
+
description: "Your CRM, calendar, retainer signing or Google Analytics",
|
|
128
|
+
team: "general",
|
|
129
|
+
subCategories: [
|
|
130
|
+
{ value: "crm", label: "CRM (HubSpot, Salesforce, Zoho)" },
|
|
131
|
+
{ value: "calendar", label: "Calendar / Appointments" },
|
|
132
|
+
{ value: "retainer", label: "Retainer Signing" },
|
|
133
|
+
{ value: "analytics", label: "Google Analytics" },
|
|
134
|
+
{ value: "other", label: "Other Integration" },
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
DASHBOARD_PROBLEM,
|
|
138
|
+
ACCOUNT_AND_LOGIN,
|
|
139
|
+
SOMETHING_ELSE,
|
|
57
140
|
];
|
|
58
141
|
exports.PARTNER_TICKET_CATEGORY_OPTIONS = [
|
|
142
|
+
{
|
|
143
|
+
value: "commissions",
|
|
144
|
+
label: "Commissions & Earnings",
|
|
145
|
+
description: "Your commission, wallet, monthly report or Stripe payout account",
|
|
146
|
+
team: "billing",
|
|
147
|
+
subCategories: [
|
|
148
|
+
{ value: "commission-missing", label: "Commission Missing" },
|
|
149
|
+
{ value: "commission-wrong", label: "Commission Amount Looks Wrong" },
|
|
150
|
+
{ value: "monthly-report", label: "Monthly Report Question" },
|
|
151
|
+
{ value: "payout-account", label: "Payout Account (Stripe)" },
|
|
152
|
+
{ value: "other", label: "Other Earnings Question" },
|
|
153
|
+
],
|
|
154
|
+
},
|
|
59
155
|
{
|
|
60
156
|
value: "failed-withdrawal",
|
|
61
157
|
label: "Failed Withdrawal",
|
|
158
|
+
description: "Money you withdrew from your wallet didn't arrive",
|
|
159
|
+
team: "billing",
|
|
62
160
|
requiresInvoiceId: true,
|
|
161
|
+
referenceLabel: "Transaction ID",
|
|
63
162
|
},
|
|
64
163
|
{
|
|
65
164
|
value: "failed-transfer",
|
|
66
|
-
label: "Failed
|
|
165
|
+
label: "Failed Commission Payment",
|
|
166
|
+
description: "A monthly commission payment failed or was reversed",
|
|
167
|
+
team: "billing",
|
|
67
168
|
requiresInvoiceId: true,
|
|
169
|
+
referenceLabel: "Reference ID",
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
value: "referrals",
|
|
173
|
+
label: "Referrals & Tier",
|
|
174
|
+
description: "A referral that wasn't credited, your referral link or your partner tier",
|
|
175
|
+
team: "account-manager",
|
|
176
|
+
subCategories: [
|
|
177
|
+
{ value: "referral-not-credited", label: "Referral Not Credited" },
|
|
178
|
+
{ value: "tier", label: "Tier Not Updated" },
|
|
179
|
+
{ value: "referral-link", label: "Referral Link" },
|
|
180
|
+
{ value: "other", label: "Other Referral Question" },
|
|
181
|
+
],
|
|
68
182
|
},
|
|
183
|
+
{
|
|
184
|
+
value: "reviews",
|
|
185
|
+
label: "Reviews",
|
|
186
|
+
description: "Image or video reviews you submitted",
|
|
187
|
+
team: "account-manager",
|
|
188
|
+
subCategories: [
|
|
189
|
+
{ value: "submission-problem", label: "Problem Submitting a Review" },
|
|
190
|
+
{ value: "review-rejected", label: "Review Rejected" },
|
|
191
|
+
{ value: "other", label: "Other Review Question" },
|
|
192
|
+
],
|
|
193
|
+
},
|
|
194
|
+
DASHBOARD_PROBLEM,
|
|
195
|
+
ACCOUNT_AND_LOGIN,
|
|
196
|
+
SOMETHING_ELSE,
|
|
197
|
+
];
|
|
198
|
+
// The Phase 28 (Sep 22) categories, retired on Oct 2 -- same lists for both portals.
|
|
199
|
+
const PHASE28_LEGACY = [
|
|
69
200
|
{
|
|
70
201
|
value: "technical-support",
|
|
71
|
-
label: "Technical Support",
|
|
202
|
+
label: "Technical Support (Legacy)",
|
|
203
|
+
team: "general",
|
|
72
204
|
subCategories: [
|
|
73
205
|
{ value: "login-access", label: "Login / Access" },
|
|
74
206
|
{ value: "bug-error", label: "Bug / Error" },
|
|
@@ -79,9 +211,10 @@ exports.PARTNER_TICKET_CATEGORY_OPTIONS = [
|
|
|
79
211
|
},
|
|
80
212
|
{
|
|
81
213
|
value: "account-support",
|
|
82
|
-
label: "Account Support",
|
|
214
|
+
label: "Account Support (Legacy)",
|
|
215
|
+
team: "general",
|
|
83
216
|
subCategories: [
|
|
84
|
-
{ value: "billing-invoice", label: "Billing / Invoice" },
|
|
217
|
+
{ value: "billing-invoice", label: "Billing / Invoice", team: "billing" },
|
|
85
218
|
{ value: "profile-settings", label: "Profile / Settings" },
|
|
86
219
|
{ value: "users-permissions", label: "Users & Permissions" },
|
|
87
220
|
{ value: "other", label: "Other" },
|
|
@@ -92,46 +225,72 @@ exports.PARTNER_TICKET_CATEGORY_OPTIONS = [
|
|
|
92
225
|
* "create a new ticket" form again. Ops's category dropdowns (triage/reassign) still need to
|
|
93
226
|
* accept and display these so an old ticket can be looked at, filtered and re-triaged. */
|
|
94
227
|
exports.CLIENT_TICKET_CATEGORY_OPTIONS_LEGACY = [
|
|
95
|
-
{ value: "chat-dispute", label: "Chat Dispute (Legacy)", requiresChatId: true },
|
|
228
|
+
{ value: "chat-dispute", label: "Chat Dispute (Legacy)", team: "billing", requiresChatId: true },
|
|
229
|
+
...PHASE28_LEGACY,
|
|
96
230
|
];
|
|
97
231
|
exports.PARTNER_TICKET_CATEGORY_OPTIONS_LEGACY = [
|
|
98
|
-
{ value: "dashboard-technical-issue", label: "Dashboard / Technical Issue (Legacy)" },
|
|
99
|
-
{ value: "payout-issue", label: "Payout Issue (Legacy)" },
|
|
100
|
-
{ value: "referral-issue", label: "Referral Issue (Legacy)" },
|
|
101
|
-
{ value: "review-submission-issue", label: "Review Submission Error (Legacy)" },
|
|
102
|
-
{ value: "other", label: "Other (Legacy)" },
|
|
232
|
+
{ value: "dashboard-technical-issue", label: "Dashboard / Technical Issue (Legacy)", team: "general" },
|
|
233
|
+
{ value: "payout-issue", label: "Payout Issue (Legacy)", team: "billing" },
|
|
234
|
+
{ value: "referral-issue", label: "Referral Issue (Legacy)", team: "account-manager" },
|
|
235
|
+
{ value: "review-submission-issue", label: "Review Submission Error (Legacy)", team: "account-manager" },
|
|
236
|
+
{ value: "other", label: "Other (Legacy)", team: "general" },
|
|
237
|
+
...PHASE28_LEGACY,
|
|
103
238
|
];
|
|
104
|
-
/** Every category value that can appear on any ticket, old or new -- what
|
|
105
|
-
* "handles these ticket categories" checkbox list
|
|
106
|
-
* category on an old, not-yet-resolved ticket as well as the new taxonomy. */
|
|
239
|
+
/** Every category value that can appear on any ticket, old or new, each listed once -- what Ops's
|
|
240
|
+
* category filters and a Group's "handles these ticket categories" checkbox list offer. */
|
|
107
241
|
exports.ALL_TICKET_CATEGORY_OPTIONS = [
|
|
108
242
|
...exports.CLIENT_TICKET_CATEGORY_OPTIONS,
|
|
109
243
|
...exports.PARTNER_TICKET_CATEGORY_OPTIONS,
|
|
110
244
|
...exports.CLIENT_TICKET_CATEGORY_OPTIONS_LEGACY,
|
|
111
245
|
...exports.PARTNER_TICKET_CATEGORY_OPTIONS_LEGACY,
|
|
112
|
-
];
|
|
246
|
+
].filter((opt, i, all) => all.findIndex((o) => o.value === opt.value) === i);
|
|
113
247
|
function findOption(list, value) {
|
|
114
248
|
if (!value)
|
|
115
249
|
return undefined;
|
|
116
250
|
return list.find((o) => o.value === value);
|
|
117
251
|
}
|
|
118
252
|
/** Looks a category value up across every list (new + legacy, client + partner) -- for anywhere
|
|
119
|
-
* that just needs the label/shape without caring which dashboard it came from.
|
|
253
|
+
* that just needs the label/shape without caring which dashboard it came from. A value both
|
|
254
|
+
* portals use is defined once, so it reads the same either way. */
|
|
120
255
|
function findTicketCategoryOption(value) {
|
|
121
256
|
return findOption(exports.ALL_TICKET_CATEGORY_OPTIONS, value);
|
|
122
257
|
}
|
|
258
|
+
/** The category list (current + legacy) for one owner type. */
|
|
259
|
+
function ticketCategoryOptionsFor(ownerType) {
|
|
260
|
+
return ownerType === "Partner"
|
|
261
|
+
? [...exports.PARTNER_TICKET_CATEGORY_OPTIONS, ...exports.PARTNER_TICKET_CATEGORY_OPTIONS_LEGACY]
|
|
262
|
+
: [...exports.CLIENT_TICKET_CATEGORY_OPTIONS, ...exports.CLIENT_TICKET_CATEGORY_OPTIONS_LEGACY];
|
|
263
|
+
}
|
|
264
|
+
/** A category as one owner type sees it (falls back to any list for a value it doesn't have). */
|
|
265
|
+
function findTicketCategoryOptionFor(ownerType, value) {
|
|
266
|
+
return findOption(ticketCategoryOptionsFor(ownerType), value) || findTicketCategoryOption(value);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Which team handles a ticket in this category / sub-category: the sub-category's own team, else
|
|
270
|
+
* the category's, else General Support. Undefined only when there is no category yet (an email
|
|
271
|
+
* ticket nobody has categorised).
|
|
272
|
+
*/
|
|
273
|
+
function ticketTeamFor(ownerType, category, subCategory) {
|
|
274
|
+
var _a;
|
|
275
|
+
if (!category)
|
|
276
|
+
return undefined;
|
|
277
|
+
const option = findTicketCategoryOptionFor(ownerType, category);
|
|
278
|
+
const sub = subCategory ? (_a = option === null || option === void 0 ? void 0 : option.subCategories) === null || _a === void 0 ? void 0 : _a.find((s) => s.value === subCategory) : undefined;
|
|
279
|
+
return (sub === null || sub === void 0 ? void 0 : sub.team) || (option === null || option === void 0 ? void 0 : option.team) || "general";
|
|
280
|
+
}
|
|
123
281
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* category here (invoice-dispute, failed-withdrawal, failed-transfer -- the requiresInvoiceId
|
|
127
|
-
* ones with no subCategories array at all) has no sub-categories to edit in the first place.
|
|
282
|
+
* The "Category lists kept in settings" admin screen -- the categories whose SUB-categories an
|
|
283
|
+
* admin can edit (never the category itself). Every current category that has sub-categories.
|
|
128
284
|
*/
|
|
129
285
|
exports.EDITABLE_SUBCATEGORY_KEYS = [
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
286
|
+
...exports.CLIENT_TICKET_CATEGORY_OPTIONS.filter((o) => o.subCategories).map((o) => ({
|
|
287
|
+
ownerType: "Company",
|
|
288
|
+
categoryValue: o.value,
|
|
289
|
+
})),
|
|
290
|
+
...exports.PARTNER_TICKET_CATEGORY_OPTIONS.filter((o) => o.subCategories).map((o) => ({
|
|
291
|
+
ownerType: "Partner",
|
|
292
|
+
categoryValue: o.value,
|
|
293
|
+
})),
|
|
135
294
|
];
|
|
136
295
|
/**
|
|
137
296
|
* Merges DB overrides onto the hardcoded defaults -- replaces just a matching category's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emailTemplates.d.ts","sourceRoot":"","sources":["../../src/helpers/emailTemplates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,kEAAkE,uBAAuB,KAAG,MA4H9H,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,GAAG,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"emailTemplates.d.ts","sourceRoot":"","sources":["../../src/helpers/emailTemplates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,kEAAkE,uBAAuB,KAAG,MA4H9H,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,GAAG,MAAM,KAAG,MA0I1D,CAAC"}
|
|
@@ -117,11 +117,11 @@ ${noteHtml}${buttonHtml}
|
|
|
117
117
|
</p>
|
|
118
118
|
<a href="https://www.orbitxpro.com" style="color:#FE5E17;text-decoration:none;font-weight:700;font-size:14px;display:block;margin-bottom:6px;${FONT}">www.orbitxpro.com</a>
|
|
119
119
|
<p style="font-size:12px;color:#999999;margin:0 0 20px 0;${FONT}">
|
|
120
|
-
Questions? Email <a href="mailto:support@orbitxpro.com" style="color:#999999;font-weight:700;text-decoration:none;">support@orbitxpro.com</a
|
|
120
|
+
Questions? Email us at <a href="mailto:support@orbitxpro.com" style="color:#999999;font-weight:700;text-decoration:none;">support@orbitxpro.com</a>.
|
|
121
121
|
</p>
|
|
122
122
|
<p style="font-size:11px;color:#999999;line-height:1.6;border-top:1px solid #eeeeee;padding-top:20px;margin:0;${FONT}">
|
|
123
123
|
This lead was forwarded through ORBITXPRO. To respond, contact the person who forwarded it; replies to this email aren't monitored.<br>
|
|
124
|
-
©
|
|
124
|
+
© ${new Date().getFullYear()} ORBITXPRO LLC | All rights reserved.
|
|
125
125
|
</p>
|
|
126
126
|
</td>
|
|
127
127
|
</tr>
|
|
@@ -258,11 +258,10 @@ const resetPasswordEmail = (code) => {
|
|
|
258
258
|
</div>
|
|
259
259
|
<a href="https://www.orbitxpro.com" class="website-link">www.orbitxpro.com</a>
|
|
260
260
|
<div class="support-container">
|
|
261
|
-
Didn't request this?
|
|
262
|
-
<a href="mailto:support@orbitxpro.com" class="support-link">Contact Customer Support</a>
|
|
261
|
+
Didn't request this? Email us at <a href="mailto:support@orbitxpro.com" class="support-link">support@orbitxpro.com</a>.
|
|
263
262
|
</div>
|
|
264
263
|
<div class="compliance-text">
|
|
265
|
-
©
|
|
264
|
+
© ${new Date().getFullYear()} ORBITXPRO LLC | Security Notification <br>
|
|
266
265
|
<strong>Please do not reply directly to this email.</strong>
|
|
267
266
|
</div>
|
|
268
267
|
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ownTickets.d.ts","sourceRoot":"","sources":["../../src/helpers/ownTickets.ts"],"names":[],"mappings":"AAuBA,wBAAgB,0BAA0B,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,YAAY,EAAE,EAAE;IAC9H,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IACjC,eAAe,EAAE,GAAG,EAAE,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAClE,6EAA6E;IAC7E,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CACvH;;;;;;
|
|
1
|
+
{"version":3,"file":"ownTickets.d.ts","sourceRoot":"","sources":["../../src/helpers/ownTickets.ts"],"names":[],"mappings":"AAuBA,wBAAgB,0BAA0B,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,YAAY,EAAE,EAAE;IAC9H,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;IACjC,eAAe,EAAE,GAAG,EAAE,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAClE,6EAA6E;IAC7E,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CACvH;;;;;;EAwJA"}
|
|
@@ -55,20 +55,27 @@ function createOwnTicketsController({ ownerType, categoryOptions, fallbackAuthor
|
|
|
55
55
|
console.error(`[Ticket ${ticket._id}] Failed to write assignment update:`, err.message);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
// Routes a new ticket the
|
|
59
|
-
//
|
|
58
|
+
// Routes a new ticket to the team its category belongs to (billing / scripting / the account's Account Manager /
|
|
59
|
+
// general support -- see routing/ticketRouting.ts). Routing is a convenience: an unrouted ticket just waits for Ops
|
|
60
|
+
// to pick it up (and its new-ticket alert goes to every Support Manager).
|
|
60
61
|
async function routeNewTicket(ticket) {
|
|
61
62
|
try {
|
|
62
63
|
const routing = await (0, ticketRouting_1.resolveTicketRouting)(ticket);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
const update = { $set: {}, $push: {} };
|
|
65
|
+
if (routing.team)
|
|
66
|
+
update.$set.team = routing.team;
|
|
66
67
|
if (routing.assigneeId) {
|
|
67
|
-
update.$set =
|
|
68
|
+
update.$set.assigneeId = routing.assigneeId;
|
|
68
69
|
update.$push.activityLog = { action: "assigned", actorName: "Routing Engine", to: String(routing.assigneeId), createdAt: new Date() };
|
|
69
70
|
}
|
|
70
71
|
if (routing.followerIds.length)
|
|
71
72
|
update.$push.followerIds = { $each: routing.followerIds };
|
|
73
|
+
if (!Object.keys(update.$push).length)
|
|
74
|
+
delete update.$push;
|
|
75
|
+
if (!Object.keys(update.$set).length)
|
|
76
|
+
delete update.$set;
|
|
77
|
+
if (!update.$set && !update.$push)
|
|
78
|
+
return;
|
|
72
79
|
await TicketModel.updateOne({ _id: ticket._id }, update);
|
|
73
80
|
await notifyAssignee(routing.assigneeId, ticket);
|
|
74
81
|
}
|