@uniorganization/uni-lib 4.0.38 → 4.0.40
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/entities/inbox/agent-extension.entity.d.ts +16 -0
- package/dist/entities/inbox/agent-extension.entity.js +84 -0
- package/dist/entities/inbox/assignment.entity.d.ts +18 -0
- package/dist/entities/inbox/assignment.entity.js +94 -0
- package/dist/entities/inbox/case-event.entity.d.ts +18 -0
- package/dist/entities/inbox/case-event.entity.js +86 -0
- package/dist/entities/inbox/case-file.entity.d.ts +13 -0
- package/dist/entities/inbox/case-file.entity.js +59 -0
- package/dist/entities/inbox/case-link.entity.d.ts +22 -0
- package/dist/entities/inbox/case-link.entity.js +123 -0
- package/dist/entities/inbox/case-note.entity.d.ts +14 -0
- package/dist/entities/inbox/case-note.entity.js +69 -0
- package/dist/entities/inbox/case-tag.entity.d.ts +12 -0
- package/dist/entities/inbox/case-tag.entity.js +57 -0
- package/dist/entities/inbox/case-text.entity.d.ts +21 -0
- package/dist/entities/inbox/case-text.entity.js +106 -0
- package/dist/entities/inbox/contact-attempt.entity.d.ts +15 -0
- package/dist/entities/inbox/contact-attempt.entity.js +67 -0
- package/dist/entities/inbox/inbound-message.entity.d.ts +22 -0
- package/dist/entities/inbox/inbound-message.entity.js +124 -0
- package/dist/entities/inbox/index.d.ts +14 -0
- package/dist/entities/inbox/index.js +30 -0
- package/dist/entities/inbox/message-case.entity.d.ts +36 -0
- package/dist/entities/inbox/message-case.entity.js +184 -0
- package/dist/entities/inbox/notification.entity.d.ts +16 -0
- package/dist/entities/inbox/notification.entity.js +86 -0
- package/dist/entities/inbox/sla-policy.entity.d.ts +15 -0
- package/dist/entities/inbox/sla-policy.entity.js +94 -0
- package/dist/entities/inbox/tag.entity.d.ts +9 -0
- package/dist/entities/inbox/tag.entity.js +47 -0
- package/dist/entities/index.d.ts +1 -0
- package/dist/entities/index.js +1 -0
- package/dist/entities/service-center.entity.d.ts +0 -2
- package/dist/entities/service-center.entity.js +0 -4
- package/dist/enums/inbox/assignment-type.enum.d.ts +7 -0
- package/dist/enums/inbox/assignment-type.enum.js +11 -0
- package/dist/enums/inbox/case-link-type.enum.d.ts +7 -0
- package/dist/enums/inbox/case-link-type.enum.js +11 -0
- package/dist/enums/inbox/case-link-verification-status.enum.d.ts +6 -0
- package/dist/enums/inbox/case-link-verification-status.enum.js +10 -0
- package/dist/enums/inbox/case-priority.enum.d.ts +6 -0
- package/dist/enums/inbox/case-priority.enum.js +10 -0
- package/dist/enums/inbox/case-status.enum.d.ts +11 -0
- package/dist/enums/inbox/case-status.enum.js +15 -0
- package/dist/enums/inbox/channel-type.enum.d.ts +8 -0
- package/dist/enums/inbox/channel-type.enum.js +12 -0
- package/dist/enums/inbox/contact-attempt-outcome.enum.d.ts +9 -0
- package/dist/enums/inbox/contact-attempt-outcome.enum.js +13 -0
- package/dist/enums/inbox/event-type.enum.d.ts +18 -0
- package/dist/enums/inbox/event-type.enum.js +22 -0
- package/dist/enums/inbox/index.d.ts +14 -0
- package/dist/enums/inbox/index.js +30 -0
- package/dist/enums/inbox/intake-status.enum.d.ts +7 -0
- package/dist/enums/inbox/intake-status.enum.js +11 -0
- package/dist/enums/inbox/note-type.enum.d.ts +5 -0
- package/dist/enums/inbox/note-type.enum.js +9 -0
- package/dist/enums/inbox/notification-status.enum.d.ts +6 -0
- package/dist/enums/inbox/notification-status.enum.js +10 -0
- package/dist/enums/inbox/sla-color.enum.d.ts +6 -0
- package/dist/enums/inbox/sla-color.enum.js +10 -0
- package/dist/enums/inbox/text-type.enum.d.ts +7 -0
- package/dist/enums/inbox/text-type.enum.js +11 -0
- package/dist/enums/inbox/transfer-reason.enum.d.ts +11 -0
- package/dist/enums/inbox/transfer-reason.enum.js +15 -0
- package/dist/enums/index.d.ts +1 -0
- package/dist/enums/index.js +1 -0
- package/dist/enums/ticket-service-center-match-progress-phase.enum.d.ts +12 -0
- package/dist/enums/ticket-service-center-match-progress-phase.enum.js +16 -0
- package/dist/modules/file-storage/file-storage.service.spec.d.ts +1 -0
- package/dist/modules/file-storage/file-storage.service.spec.js +107 -0
- package/dist/utils/ticket-service-center-match-progress.util.d.ts +9 -0
- package/dist/utils/ticket-service-center-match-progress.util.js +46 -0
- package/dist/utils/ticket-service-center-match-progress.util.spec.d.ts +1 -0
- package/dist/utils/ticket-service-center-match-progress.util.spec.js +45 -0
- package/package.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContactAttemptOutcome = void 0;
|
|
4
|
+
var ContactAttemptOutcome;
|
|
5
|
+
(function (ContactAttemptOutcome) {
|
|
6
|
+
ContactAttemptOutcome["CONTACTED"] = "contacted";
|
|
7
|
+
ContactAttemptOutcome["NO_ANSWER"] = "no_answer";
|
|
8
|
+
ContactAttemptOutcome["VOICEMAIL_LEFT"] = "voicemail_left";
|
|
9
|
+
ContactAttemptOutcome["WRONG_NUMBER"] = "wrong_number";
|
|
10
|
+
ContactAttemptOutcome["CALLBACK_SCHEDULED"] = "callback_scheduled";
|
|
11
|
+
ContactAttemptOutcome["CUSTOMER_DECLINED"] = "customer_declined";
|
|
12
|
+
ContactAttemptOutcome["RESOLVED_BY_OTHER_CHANNEL"] = "resolved_by_other_channel";
|
|
13
|
+
})(ContactAttemptOutcome || (exports.ContactAttemptOutcome = ContactAttemptOutcome = {}));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare enum EventType {
|
|
2
|
+
INBOUND_RECEIVED = "inbound_received",
|
|
3
|
+
CREATED = "created",
|
|
4
|
+
OPENED = "opened",
|
|
5
|
+
READ = "read",
|
|
6
|
+
LISTENED = "listened",
|
|
7
|
+
STATUS_CHANGED = "status_changed",
|
|
8
|
+
ASSIGNED = "assigned",
|
|
9
|
+
TRANSFERRED = "transferred",
|
|
10
|
+
NOTE_ADDED = "note_added",
|
|
11
|
+
CONTACT_ATTEMPTED = "contact_attempted",
|
|
12
|
+
MANUAL_LINK_ADDED = "manual_link_added",
|
|
13
|
+
MANUAL_LINK_VERIFIED = "manual_link_verified",
|
|
14
|
+
TAG_ADDED = "tag_added",
|
|
15
|
+
TAG_REMOVED = "tag_removed",
|
|
16
|
+
RESOLVED = "resolved",
|
|
17
|
+
CLOSED_NO_CONTACT = "closed_no_contact"
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventType = void 0;
|
|
4
|
+
var EventType;
|
|
5
|
+
(function (EventType) {
|
|
6
|
+
EventType["INBOUND_RECEIVED"] = "inbound_received";
|
|
7
|
+
EventType["CREATED"] = "created";
|
|
8
|
+
EventType["OPENED"] = "opened";
|
|
9
|
+
EventType["READ"] = "read";
|
|
10
|
+
EventType["LISTENED"] = "listened";
|
|
11
|
+
EventType["STATUS_CHANGED"] = "status_changed";
|
|
12
|
+
EventType["ASSIGNED"] = "assigned";
|
|
13
|
+
EventType["TRANSFERRED"] = "transferred";
|
|
14
|
+
EventType["NOTE_ADDED"] = "note_added";
|
|
15
|
+
EventType["CONTACT_ATTEMPTED"] = "contact_attempted";
|
|
16
|
+
EventType["MANUAL_LINK_ADDED"] = "manual_link_added";
|
|
17
|
+
EventType["MANUAL_LINK_VERIFIED"] = "manual_link_verified";
|
|
18
|
+
EventType["TAG_ADDED"] = "tag_added";
|
|
19
|
+
EventType["TAG_REMOVED"] = "tag_removed";
|
|
20
|
+
EventType["RESOLVED"] = "resolved";
|
|
21
|
+
EventType["CLOSED_NO_CONTACT"] = "closed_no_contact";
|
|
22
|
+
})(EventType || (exports.EventType = EventType = {}));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from './channel-type.enum';
|
|
2
|
+
export * from './intake-status.enum';
|
|
3
|
+
export * from './case-status.enum';
|
|
4
|
+
export * from './case-priority.enum';
|
|
5
|
+
export * from './note-type.enum';
|
|
6
|
+
export * from './text-type.enum';
|
|
7
|
+
export * from './assignment-type.enum';
|
|
8
|
+
export * from './transfer-reason.enum';
|
|
9
|
+
export * from './contact-attempt-outcome.enum';
|
|
10
|
+
export * from './case-link-type.enum';
|
|
11
|
+
export * from './case-link-verification-status.enum';
|
|
12
|
+
export * from './event-type.enum';
|
|
13
|
+
export * from './notification-status.enum';
|
|
14
|
+
export * from './sla-color.enum';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./channel-type.enum"), exports);
|
|
18
|
+
__exportStar(require("./intake-status.enum"), exports);
|
|
19
|
+
__exportStar(require("./case-status.enum"), exports);
|
|
20
|
+
__exportStar(require("./case-priority.enum"), exports);
|
|
21
|
+
__exportStar(require("./note-type.enum"), exports);
|
|
22
|
+
__exportStar(require("./text-type.enum"), exports);
|
|
23
|
+
__exportStar(require("./assignment-type.enum"), exports);
|
|
24
|
+
__exportStar(require("./transfer-reason.enum"), exports);
|
|
25
|
+
__exportStar(require("./contact-attempt-outcome.enum"), exports);
|
|
26
|
+
__exportStar(require("./case-link-type.enum"), exports);
|
|
27
|
+
__exportStar(require("./case-link-verification-status.enum"), exports);
|
|
28
|
+
__exportStar(require("./event-type.enum"), exports);
|
|
29
|
+
__exportStar(require("./notification-status.enum"), exports);
|
|
30
|
+
__exportStar(require("./sla-color.enum"), exports);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IntakeStatus = void 0;
|
|
4
|
+
var IntakeStatus;
|
|
5
|
+
(function (IntakeStatus) {
|
|
6
|
+
IntakeStatus["RECEIVED"] = "received";
|
|
7
|
+
IntakeStatus["CASE_CREATED"] = "case_created";
|
|
8
|
+
IntakeStatus["UNRESOLVED_EXTENSION"] = "unresolved_extension";
|
|
9
|
+
IntakeStatus["REJECTED"] = "rejected";
|
|
10
|
+
IntakeStatus["FAILED"] = "failed";
|
|
11
|
+
})(IntakeStatus || (exports.IntakeStatus = IntakeStatus = {}));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoteType = void 0;
|
|
4
|
+
var NoteType;
|
|
5
|
+
(function (NoteType) {
|
|
6
|
+
NoteType["INTERNAL"] = "internal";
|
|
7
|
+
NoteType["SUPERVISOR"] = "supervisor";
|
|
8
|
+
NoteType["RESOLUTION"] = "resolution";
|
|
9
|
+
})(NoteType || (exports.NoteType = NoteType = {}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NotificationStatus = void 0;
|
|
4
|
+
var NotificationStatus;
|
|
5
|
+
(function (NotificationStatus) {
|
|
6
|
+
NotificationStatus["PENDING"] = "pending";
|
|
7
|
+
NotificationStatus["SENT"] = "sent";
|
|
8
|
+
NotificationStatus["FAILED"] = "failed";
|
|
9
|
+
NotificationStatus["READ"] = "read";
|
|
10
|
+
})(NotificationStatus || (exports.NotificationStatus = NotificationStatus = {}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SlaColor = void 0;
|
|
4
|
+
var SlaColor;
|
|
5
|
+
(function (SlaColor) {
|
|
6
|
+
SlaColor["GREEN"] = "green";
|
|
7
|
+
SlaColor["YELLOW"] = "yellow";
|
|
8
|
+
SlaColor["ORANGE"] = "orange";
|
|
9
|
+
SlaColor["RED"] = "red";
|
|
10
|
+
})(SlaColor || (exports.SlaColor = SlaColor = {}));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TextType = void 0;
|
|
4
|
+
var TextType;
|
|
5
|
+
(function (TextType) {
|
|
6
|
+
TextType["TRANSCRIPT"] = "transcript";
|
|
7
|
+
TextType["CHAT"] = "chat";
|
|
8
|
+
TextType["SMS"] = "sms";
|
|
9
|
+
TextType["EMAIL"] = "email";
|
|
10
|
+
TextType["MANUAL_CORRECTION"] = "manual_correction";
|
|
11
|
+
})(TextType || (exports.TextType = TextType = {}));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare enum TransferReason {
|
|
2
|
+
INITIAL_EXTENSION_MATCH = "initial_extension_match",
|
|
3
|
+
UNRESOLVED_EXTENSION_MANUAL_ASSIGNMENT = "unresolved_extension_manual_assignment",
|
|
4
|
+
AGENT_ABSENT = "agent_absent",
|
|
5
|
+
AGENT_INACTIVE = "agent_inactive",
|
|
6
|
+
VACATION = "vacation",
|
|
7
|
+
WORKLOAD_BALANCE = "workload_balance",
|
|
8
|
+
WRONG_EXTENSION = "wrong_extension",
|
|
9
|
+
SUPERVISOR_DECISION = "supervisor_decision",
|
|
10
|
+
CUSTOMER_REQUESTED_AGENT = "customer_requested_agent"
|
|
11
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransferReason = void 0;
|
|
4
|
+
var TransferReason;
|
|
5
|
+
(function (TransferReason) {
|
|
6
|
+
TransferReason["INITIAL_EXTENSION_MATCH"] = "initial_extension_match";
|
|
7
|
+
TransferReason["UNRESOLVED_EXTENSION_MANUAL_ASSIGNMENT"] = "unresolved_extension_manual_assignment";
|
|
8
|
+
TransferReason["AGENT_ABSENT"] = "agent_absent";
|
|
9
|
+
TransferReason["AGENT_INACTIVE"] = "agent_inactive";
|
|
10
|
+
TransferReason["VACATION"] = "vacation";
|
|
11
|
+
TransferReason["WORKLOAD_BALANCE"] = "workload_balance";
|
|
12
|
+
TransferReason["WRONG_EXTENSION"] = "wrong_extension";
|
|
13
|
+
TransferReason["SUPERVISOR_DECISION"] = "supervisor_decision";
|
|
14
|
+
TransferReason["CUSTOMER_REQUESTED_AGENT"] = "customer_requested_agent";
|
|
15
|
+
})(TransferReason || (exports.TransferReason = TransferReason = {}));
|
package/dist/enums/index.d.ts
CHANGED
package/dist/enums/index.js
CHANGED
|
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./feedback-role.enum"), exports);
|
|
18
18
|
__exportStar(require("./service-center-status.enum"), exports);
|
|
19
19
|
__exportStar(require("./ticket-service-center-match-process-status.enum"), exports);
|
|
20
|
+
__exportStar(require("./inbox"), exports);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare enum TicketServiceCenterMatchProgressPhase {
|
|
2
|
+
PENDING = "PENDING",
|
|
3
|
+
PARSING = "PARSING",
|
|
4
|
+
MATCHING = "MATCHING",
|
|
5
|
+
GENERATING_CSV = "GENERATING_CSV",
|
|
6
|
+
GENERATING_EXCEL = "GENERATING_EXCEL",
|
|
7
|
+
UPLOADING_CSV = "UPLOADING_CSV",
|
|
8
|
+
UPLOADING_EXCEL = "UPLOADING_EXCEL",
|
|
9
|
+
FINALIZING = "FINALIZING",
|
|
10
|
+
COMPLETED = "COMPLETED",
|
|
11
|
+
FAILED = "FAILED"
|
|
12
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TicketServiceCenterMatchProgressPhase = void 0;
|
|
4
|
+
var TicketServiceCenterMatchProgressPhase;
|
|
5
|
+
(function (TicketServiceCenterMatchProgressPhase) {
|
|
6
|
+
TicketServiceCenterMatchProgressPhase["PENDING"] = "PENDING";
|
|
7
|
+
TicketServiceCenterMatchProgressPhase["PARSING"] = "PARSING";
|
|
8
|
+
TicketServiceCenterMatchProgressPhase["MATCHING"] = "MATCHING";
|
|
9
|
+
TicketServiceCenterMatchProgressPhase["GENERATING_CSV"] = "GENERATING_CSV";
|
|
10
|
+
TicketServiceCenterMatchProgressPhase["GENERATING_EXCEL"] = "GENERATING_EXCEL";
|
|
11
|
+
TicketServiceCenterMatchProgressPhase["UPLOADING_CSV"] = "UPLOADING_CSV";
|
|
12
|
+
TicketServiceCenterMatchProgressPhase["UPLOADING_EXCEL"] = "UPLOADING_EXCEL";
|
|
13
|
+
TicketServiceCenterMatchProgressPhase["FINALIZING"] = "FINALIZING";
|
|
14
|
+
TicketServiceCenterMatchProgressPhase["COMPLETED"] = "COMPLETED";
|
|
15
|
+
TicketServiceCenterMatchProgressPhase["FAILED"] = "FAILED";
|
|
16
|
+
})(TicketServiceCenterMatchProgressPhase || (exports.TicketServiceCenterMatchProgressPhase = TicketServiceCenterMatchProgressPhase = {}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
13
|
+
const file_storage_service_1 = require("./file-storage.service");
|
|
14
|
+
const BUCKET_ENV_KEYS = [
|
|
15
|
+
'BUCKET_NAME',
|
|
16
|
+
'BUCKET_REGION',
|
|
17
|
+
'BUCKET_ACCESS_KEY_ID',
|
|
18
|
+
'BUCKET_SECRET_ACCESS_KEY',
|
|
19
|
+
'BUCKET_ENDPOINT',
|
|
20
|
+
];
|
|
21
|
+
describe('FileStorageService', () => {
|
|
22
|
+
let originalBucketEnv;
|
|
23
|
+
let fileRepository;
|
|
24
|
+
let fileTypeRepository;
|
|
25
|
+
let service;
|
|
26
|
+
let send;
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
originalBucketEnv = Object.fromEntries(BUCKET_ENV_KEYS.map((key) => [key, process.env[key]]));
|
|
29
|
+
process.env.BUCKET_NAME = 'documents';
|
|
30
|
+
process.env.BUCKET_REGION = 'us-east-1';
|
|
31
|
+
process.env.BUCKET_ACCESS_KEY_ID = 'access-key';
|
|
32
|
+
process.env.BUCKET_SECRET_ACCESS_KEY = 'secret-key';
|
|
33
|
+
process.env.BUCKET_ENDPOINT = 'https://storage.example.com';
|
|
34
|
+
fileRepository = {
|
|
35
|
+
softDelete: jest.fn().mockResolvedValue({ raw: [], affected: 1 }),
|
|
36
|
+
create: jest.fn(),
|
|
37
|
+
save: jest.fn(),
|
|
38
|
+
};
|
|
39
|
+
fileTypeRepository = { findOne: jest.fn() };
|
|
40
|
+
service = new file_storage_service_1.FileStorageService(fileRepository, fileTypeRepository);
|
|
41
|
+
jest.spyOn(service.logger, 'warn').mockImplementation(() => undefined);
|
|
42
|
+
send = jest.fn().mockResolvedValue({});
|
|
43
|
+
service.s3Client.send = send;
|
|
44
|
+
});
|
|
45
|
+
afterEach(() => {
|
|
46
|
+
jest.restoreAllMocks();
|
|
47
|
+
for (const key of BUCKET_ENV_KEYS) {
|
|
48
|
+
const originalValue = originalBucketEnv[key];
|
|
49
|
+
if (originalValue === undefined) {
|
|
50
|
+
delete process.env[key];
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
process.env[key] = originalValue;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
describe('deleteDocument', () => {
|
|
58
|
+
it('deletes the bucket object before soft-deleting file metadata', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
|
+
yield service.deleteDocument({ id: 44, path: 'outputs/file.csv' });
|
|
60
|
+
expect(send).toHaveBeenCalledTimes(1);
|
|
61
|
+
const command = send.mock.calls[0][0];
|
|
62
|
+
expect(command).toBeInstanceOf(client_s3_1.DeleteObjectCommand);
|
|
63
|
+
expect(command.input).toEqual({
|
|
64
|
+
Bucket: 'documents',
|
|
65
|
+
Key: 'outputs/file.csv',
|
|
66
|
+
});
|
|
67
|
+
expect(fileRepository.softDelete).toHaveBeenCalledWith(44);
|
|
68
|
+
expect(send.mock.invocationCallOrder[0]).toBeLessThan(fileRepository.softDelete.mock.invocationCallOrder[0]);
|
|
69
|
+
}));
|
|
70
|
+
it('rejects without soft-deleting metadata when bucket deletion fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
71
|
+
const deletionError = new Error('bucket unavailable');
|
|
72
|
+
send.mockRejectedValue(deletionError);
|
|
73
|
+
yield expect(service.deleteDocument({ id: 44, path: 'outputs/file.csv' })).rejects.toBe(deletionError);
|
|
74
|
+
expect(fileRepository.softDelete).not.toHaveBeenCalled();
|
|
75
|
+
}));
|
|
76
|
+
});
|
|
77
|
+
describe('uploadDocument', () => {
|
|
78
|
+
it('preserves the DB save error when rollback object deletion fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
79
|
+
const dbSaveError = new Error('distinctive DB save failure');
|
|
80
|
+
const cleanupError = new Error('rollback delete failure');
|
|
81
|
+
const fileRecord = { id: 44, path: 'pending/file.csv' };
|
|
82
|
+
fileTypeRepository.findOne.mockResolvedValue({
|
|
83
|
+
id: 7,
|
|
84
|
+
code: 'SOURCE_FILES',
|
|
85
|
+
});
|
|
86
|
+
fileRepository.create.mockReturnValue(fileRecord);
|
|
87
|
+
fileRepository.save.mockRejectedValue(dbSaveError);
|
|
88
|
+
send.mockImplementation((command) => {
|
|
89
|
+
if (command instanceof client_s3_1.PutObjectCommand) {
|
|
90
|
+
return Promise.resolve({});
|
|
91
|
+
}
|
|
92
|
+
if (command instanceof client_s3_1.DeleteObjectCommand) {
|
|
93
|
+
return Promise.reject(cleanupError);
|
|
94
|
+
}
|
|
95
|
+
throw new Error('Unexpected S3 command');
|
|
96
|
+
});
|
|
97
|
+
yield expect(service.uploadDocument({
|
|
98
|
+
originalname: 'tickets.csv',
|
|
99
|
+
mimetype: 'text/csv',
|
|
100
|
+
buffer: Buffer.from('ticket'),
|
|
101
|
+
}, { fileTypeCode: 'SOURCE_FILES' })).rejects.toBe(dbSaveError);
|
|
102
|
+
expect(send).toHaveBeenCalledTimes(2);
|
|
103
|
+
expect(send.mock.calls[0][0]).toBeInstanceOf(client_s3_1.PutObjectCommand);
|
|
104
|
+
expect(send.mock.calls[1][0]).toBeInstanceOf(client_s3_1.DeleteObjectCommand);
|
|
105
|
+
}));
|
|
106
|
+
});
|
|
107
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TicketServiceCenterMatchProgressPhase } from '../enums/ticket-service-center-match-progress-phase.enum';
|
|
2
|
+
export interface TicketServiceCenterMatchProgressState {
|
|
3
|
+
phase: TicketServiceCenterMatchProgressPhase;
|
|
4
|
+
totalTickets: number | null;
|
|
5
|
+
previousPhase?: TicketServiceCenterMatchProgressPhase;
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const serializeTicketServiceCenterMatchProgress: (state: TicketServiceCenterMatchProgressState) => string;
|
|
9
|
+
export declare const parseTicketServiceCenterMatchProgress: (value: string | null | undefined) => TicketServiceCenterMatchProgressState | null;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseTicketServiceCenterMatchProgress = exports.serializeTicketServiceCenterMatchProgress = void 0;
|
|
4
|
+
const ticket_service_center_match_progress_phase_enum_1 = require("../enums/ticket-service-center-match-progress-phase.enum");
|
|
5
|
+
const progressPhases = new Set(Object.values(ticket_service_center_match_progress_phase_enum_1.TicketServiceCenterMatchProgressPhase));
|
|
6
|
+
const isProgressPhase = (value) => typeof value === 'string' && progressPhases.has(value);
|
|
7
|
+
const isValidTotalTickets = (value) => value === null || (typeof value === 'number' && Number.isInteger(value) && value >= 0);
|
|
8
|
+
const serializeTicketServiceCenterMatchProgress = (state) => JSON.stringify(state);
|
|
9
|
+
exports.serializeTicketServiceCenterMatchProgress = serializeTicketServiceCenterMatchProgress;
|
|
10
|
+
const parseTicketServiceCenterMatchProgress = (value) => {
|
|
11
|
+
if (!value) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const state = JSON.parse(value);
|
|
16
|
+
if (typeof state !== 'object' || state === null || Array.isArray(state)) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const candidate = state;
|
|
20
|
+
const { phase, totalTickets, previousPhase, error } = candidate;
|
|
21
|
+
if (!isProgressPhase(phase) || !isValidTotalTickets(totalTickets)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const progressState = {
|
|
25
|
+
phase,
|
|
26
|
+
totalTickets,
|
|
27
|
+
};
|
|
28
|
+
if (previousPhase !== undefined) {
|
|
29
|
+
if (!isProgressPhase(previousPhase)) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
progressState.previousPhase = previousPhase;
|
|
33
|
+
}
|
|
34
|
+
if (error !== undefined) {
|
|
35
|
+
if (typeof error !== 'string') {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
progressState.error = error;
|
|
39
|
+
}
|
|
40
|
+
return progressState;
|
|
41
|
+
}
|
|
42
|
+
catch (_a) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
exports.parseTicketServiceCenterMatchProgress = parseTicketServiceCenterMatchProgress;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const ticket_service_center_match_progress_phase_enum_1 = require("../enums/ticket-service-center-match-progress-phase.enum");
|
|
4
|
+
const ticket_service_center_match_progress_util_1 = require("./ticket-service-center-match-progress.util");
|
|
5
|
+
describe('ticket service center match progress', () => {
|
|
6
|
+
it('round-trips matching progress', () => {
|
|
7
|
+
const state = {
|
|
8
|
+
phase: ticket_service_center_match_progress_phase_enum_1.TicketServiceCenterMatchProgressPhase.MATCHING,
|
|
9
|
+
totalTickets: 100,
|
|
10
|
+
};
|
|
11
|
+
expect((0, ticket_service_center_match_progress_util_1.parseTicketServiceCenterMatchProgress)((0, ticket_service_center_match_progress_util_1.serializeTicketServiceCenterMatchProgress)(state))).toEqual(state);
|
|
12
|
+
});
|
|
13
|
+
it.each([
|
|
14
|
+
['null', null],
|
|
15
|
+
['empty text', ''],
|
|
16
|
+
['legacy error text', 'Failed to process uploaded ticket file'],
|
|
17
|
+
['malformed JSON', '{"phase":'],
|
|
18
|
+
])('returns null for %s', (_description, value) => {
|
|
19
|
+
expect((0, ticket_service_center_match_progress_util_1.parseTicketServiceCenterMatchProgress)(value)).toBeNull();
|
|
20
|
+
});
|
|
21
|
+
it.each([
|
|
22
|
+
['missing phase', { totalTickets: 10 }],
|
|
23
|
+
['invalid phase', { phase: 'IMPORTING', totalTickets: 10 }],
|
|
24
|
+
['missing totalTickets', { phase: ticket_service_center_match_progress_phase_enum_1.TicketServiceCenterMatchProgressPhase.PARSING }],
|
|
25
|
+
['negative totalTickets', { phase: ticket_service_center_match_progress_phase_enum_1.TicketServiceCenterMatchProgressPhase.PARSING, totalTickets: -1 }],
|
|
26
|
+
['fractional totalTickets', { phase: ticket_service_center_match_progress_phase_enum_1.TicketServiceCenterMatchProgressPhase.PARSING, totalTickets: 1.5 }],
|
|
27
|
+
['string totalTickets', { phase: ticket_service_center_match_progress_phase_enum_1.TicketServiceCenterMatchProgressPhase.PARSING, totalTickets: '10' }],
|
|
28
|
+
[
|
|
29
|
+
'invalid previousPhase',
|
|
30
|
+
{ phase: ticket_service_center_match_progress_phase_enum_1.TicketServiceCenterMatchProgressPhase.FAILED, totalTickets: 10, previousPhase: 'IMPORTING' },
|
|
31
|
+
],
|
|
32
|
+
['non-string error', { phase: ticket_service_center_match_progress_phase_enum_1.TicketServiceCenterMatchProgressPhase.FAILED, totalTickets: 10, error: 500 }],
|
|
33
|
+
])('returns null for a state with %s', (_description, state) => {
|
|
34
|
+
expect((0, ticket_service_center_match_progress_util_1.parseTicketServiceCenterMatchProgress)(JSON.stringify(state))).toBeNull();
|
|
35
|
+
});
|
|
36
|
+
it('retains failure context', () => {
|
|
37
|
+
const state = {
|
|
38
|
+
phase: ticket_service_center_match_progress_phase_enum_1.TicketServiceCenterMatchProgressPhase.FAILED,
|
|
39
|
+
previousPhase: ticket_service_center_match_progress_phase_enum_1.TicketServiceCenterMatchProgressPhase.UPLOADING_EXCEL,
|
|
40
|
+
totalTickets: 12,
|
|
41
|
+
error: 'Excel upload failed',
|
|
42
|
+
};
|
|
43
|
+
expect((0, ticket_service_center_match_progress_util_1.parseTicketServiceCenterMatchProgress)((0, ticket_service_center_match_progress_util_1.serializeTicketServiceCenterMatchProgress)(state))).toEqual(state);
|
|
44
|
+
});
|
|
45
|
+
});
|