@temboplus/frontend-core 0.2.2 → 0.2.3
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/README.md +62 -0
- package/esm/mod.d.ts +2 -0
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +2 -0
- package/esm/src/config/config_service.d.ts +11 -0
- package/esm/src/config/config_service.d.ts.map +1 -0
- package/esm/src/config/config_service.js +19 -0
- package/esm/src/config/index.d.ts +2 -0
- package/esm/src/config/index.d.ts.map +1 -0
- package/esm/src/config/index.js +1 -0
- package/esm/src/reports/index.d.ts +2 -0
- package/esm/src/reports/index.d.ts.map +1 -0
- package/esm/src/reports/index.js +1 -0
- package/esm/src/reports/report_manager.d.ts +144 -0
- package/esm/src/reports/report_manager.d.ts.map +1 -0
- package/esm/src/reports/report_manager.js +315 -0
- package/package.json +2 -1
- package/script/mod.d.ts +2 -0
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +2 -0
- package/script/src/config/config_service.d.ts +11 -0
- package/script/src/config/config_service.d.ts.map +1 -0
- package/script/src/config/config_service.js +23 -0
- package/script/src/config/index.d.ts +2 -0
- package/script/src/config/index.d.ts.map +1 -0
- package/script/src/config/index.js +17 -0
- package/script/src/reports/index.d.ts +2 -0
- package/script/src/reports/index.d.ts.map +1 -0
- package/script/src/reports/index.js +17 -0
- package/script/src/reports/report_manager.d.ts +144 -0
- package/script/src/reports/report_manager.d.ts.map +1 -0
- package/script/src/reports/report_manager.js +325 -0
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ The library contains:
|
|
|
8
8
|
|
|
9
9
|
* **Utilities**: Ready-to-use helper functions for common development tasks
|
|
10
10
|
* **Data Models**: Standardized structures for handling data like phone numbers, amounts, currencies, countries, and bank details
|
|
11
|
+
* **Report Management**: Tools for generating and downloading reports across different projects
|
|
12
|
+
* **Configuration Service**: Centralized configuration management for application settings
|
|
11
13
|
|
|
12
14
|
## Key Data Models
|
|
13
15
|
|
|
@@ -18,6 +20,66 @@ The library contains:
|
|
|
18
20
|
- **Country**: Standardized country data with ISO codes and validation
|
|
19
21
|
- **Bank**: Standardized bank account information management
|
|
20
22
|
|
|
23
|
+
## Report Management
|
|
24
|
+
|
|
25
|
+
The library includes a `ReportManager` for downloading reports in different formats across various TemboPlus projects:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import {
|
|
29
|
+
ReportManager,
|
|
30
|
+
FileFormat,
|
|
31
|
+
ReportType,
|
|
32
|
+
ProjectType
|
|
33
|
+
} from '@temboplus/frontend-core';
|
|
34
|
+
|
|
35
|
+
// Download a report
|
|
36
|
+
await ReportManager.instance.downloadReport({
|
|
37
|
+
token: "your-auth-token",
|
|
38
|
+
projectType: ProjectType.DASHBOARD,
|
|
39
|
+
reportType: ReportType.MERCHANT_DISBURSEMENT_REPORT,
|
|
40
|
+
fileFormat: FileFormat.PDF,
|
|
41
|
+
query: {
|
|
42
|
+
startDate: "2023-01-01T00:00:00.000Z",
|
|
43
|
+
endDate: "2023-01-31T00:00:00.000Z"
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Get all reports for a specific project
|
|
48
|
+
import { getReportsByProject } from '@temboplus/frontend-core';
|
|
49
|
+
const dashboardReports = getReportsByProject(ProjectType.DASHBOARD);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Available Report Types
|
|
53
|
+
|
|
54
|
+
The library supports the following report types:
|
|
55
|
+
|
|
56
|
+
- **Dashboard Reports**:
|
|
57
|
+
- `MERCHANT_DISBURSEMENT_REPORT`: Detailed breakdown of payments made to merchants
|
|
58
|
+
- `TRANSACTION_REVENUE_SUMMARY`: Summary of all revenue transactions by period
|
|
59
|
+
|
|
60
|
+
- **Afloat Reports**:
|
|
61
|
+
- `CUSTOMER_WALLET_ACTIVITY`: Detailed record of all customer wallet transactions
|
|
62
|
+
- `CUSTOMER_PROFILE_SNAPSHOT`: Current account information and status
|
|
63
|
+
|
|
64
|
+
- **VertoX Reports**:
|
|
65
|
+
- `GATEWAY_TRANSACTION_LOG`: Log of all payment gateway API transactions
|
|
66
|
+
|
|
67
|
+
## Configuration Service
|
|
68
|
+
|
|
69
|
+
The library provides a centralized configuration service for managing application settings:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { ConfigService } from '@temboplus/frontend-core';
|
|
73
|
+
|
|
74
|
+
// Initialize configuration at application startup
|
|
75
|
+
ConfigService.instance.initialize({
|
|
76
|
+
pdfMakerBaseUrl: 'https://api.temboplus.com/pdf-maker'
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Access configuration values throughout your application
|
|
80
|
+
const baseUrl = ConfigService.instance.pdfMakerBaseUrl;
|
|
81
|
+
```
|
|
82
|
+
|
|
21
83
|
## Working with Data Models
|
|
22
84
|
|
|
23
85
|
Each data model in our library comes with three key validation methods:
|
package/esm/mod.d.ts
CHANGED
package/esm/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
|
package/esm/mod.js
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class ConfigService {
|
|
2
|
+
private static _instance;
|
|
3
|
+
private _pdfMakerBaseUrl;
|
|
4
|
+
private constructor();
|
|
5
|
+
static get instance(): ConfigService;
|
|
6
|
+
initialize(config: {
|
|
7
|
+
pdfMakerBaseUrl: string;
|
|
8
|
+
}): void;
|
|
9
|
+
get pdfMakerBaseUrl(): string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=config_service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config_service.d.ts","sourceRoot":"","sources":["../../../src/src/config/config_service.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAgB;IACxC,OAAO,CAAC,gBAAgB,CAAc;IAEtC,OAAO;IAEP,WAAkB,QAAQ,kBAEzB;IAEM,UAAU,CAAC,MAAM,EAAE;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE;IAIrD,IAAW,eAAe,IAAI,MAAM,CAEnC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class ConfigService {
|
|
2
|
+
constructor() {
|
|
3
|
+
Object.defineProperty(this, "_pdfMakerBaseUrl", {
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
writable: true,
|
|
7
|
+
value: ""
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
static get instance() {
|
|
11
|
+
return this._instance || (this._instance = new this());
|
|
12
|
+
}
|
|
13
|
+
initialize(config) {
|
|
14
|
+
this._pdfMakerBaseUrl = config.pdfMakerBaseUrl;
|
|
15
|
+
}
|
|
16
|
+
get pdfMakerBaseUrl() {
|
|
17
|
+
return this._pdfMakerBaseUrl;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./config_service.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/reports/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./report_manager.js";
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Available file formats for reports
|
|
3
|
+
*/
|
|
4
|
+
export declare enum FileFormat {
|
|
5
|
+
/** PDF file format */
|
|
6
|
+
PDF = "pdf",
|
|
7
|
+
/** Excel file format */
|
|
8
|
+
EXCEL = "excel"
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Available project types
|
|
12
|
+
*/
|
|
13
|
+
export declare enum ProjectType {
|
|
14
|
+
/** Tembo Dashboard project */
|
|
15
|
+
DASHBOARD = "dashboard",
|
|
16
|
+
/** Afloat project */
|
|
17
|
+
AFLOAT = "afloat",
|
|
18
|
+
/** VertoX project */
|
|
19
|
+
VERTO_X = "verto_x"
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Available report types with improved naming
|
|
23
|
+
*/
|
|
24
|
+
export declare enum ReportType {
|
|
25
|
+
/** Merchant payout statement (Dashboard) */
|
|
26
|
+
MERCHANT_DISBURSEMENT_REPORT = "merchant_disbursement_report",
|
|
27
|
+
/** Transaction revenue summary (Dashboard) */
|
|
28
|
+
TRANSACTION_REVENUE_SUMMARY = "transaction_revenue_summary",
|
|
29
|
+
/** Customer wallet activity (Afloat) */
|
|
30
|
+
CUSTOMER_WALLET_ACTIVITY = "customer_wallet_activity",
|
|
31
|
+
/** Customer profile information (Afloat) */
|
|
32
|
+
CUSTOMER_PROFILE_SNAPSHOT = "customer_profile_snapshot",
|
|
33
|
+
/** Gateway transaction log (VertoX) */
|
|
34
|
+
GATEWAY_TRANSACTION_LOG = "gateway_transaction_log"
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Report definition interface
|
|
38
|
+
*/
|
|
39
|
+
export interface ReportDefinition {
|
|
40
|
+
/** Unique identifier for the report */
|
|
41
|
+
id: string;
|
|
42
|
+
/** Human-readable report name for UI display */
|
|
43
|
+
displayName: string;
|
|
44
|
+
/** API endpoint path for the report */
|
|
45
|
+
endpoint: string;
|
|
46
|
+
/** Available file formats for the report */
|
|
47
|
+
availableFormats: FileFormat[];
|
|
48
|
+
/** Optional description of the report */
|
|
49
|
+
description?: string;
|
|
50
|
+
/** Project the report belongs to */
|
|
51
|
+
projectType: ProjectType;
|
|
52
|
+
/** Type of the report */
|
|
53
|
+
reportType: ReportType;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Registry of all available reports
|
|
57
|
+
*/
|
|
58
|
+
export declare const REPORTS: {
|
|
59
|
+
merchant_disbursement_report: ReportDefinition;
|
|
60
|
+
transaction_revenue_summary: ReportDefinition;
|
|
61
|
+
customer_wallet_activity: ReportDefinition;
|
|
62
|
+
customer_profile_snapshot: ReportDefinition;
|
|
63
|
+
gateway_transaction_log: ReportDefinition;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Get all reports for a specific project
|
|
67
|
+
* @param projectType The project type to filter by
|
|
68
|
+
* @returns Array of report definitions for the project
|
|
69
|
+
*/
|
|
70
|
+
export declare function getReportsByProject(projectType: ProjectType): ReportDefinition[];
|
|
71
|
+
/**
|
|
72
|
+
* Get a report by its type
|
|
73
|
+
* @param reportType The report type to retrieve
|
|
74
|
+
* @returns The report definition or undefined if not found
|
|
75
|
+
*/
|
|
76
|
+
export declare function getReportByType(reportType: ReportType): ReportDefinition;
|
|
77
|
+
/**
|
|
78
|
+
* Validates if a report type is available for a project
|
|
79
|
+
* @param projectType The project type
|
|
80
|
+
* @param reportType The report type
|
|
81
|
+
* @returns True if the report is available for the project, false otherwise
|
|
82
|
+
*/
|
|
83
|
+
export declare function isReportAvailableForProject(projectType: ProjectType, reportType: ReportType): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Report Manager class for handling report downloads
|
|
86
|
+
*/
|
|
87
|
+
export declare class ReportManager {
|
|
88
|
+
private static _instance;
|
|
89
|
+
private constructor();
|
|
90
|
+
/**
|
|
91
|
+
* Get the singleton instance of ReportManager
|
|
92
|
+
*/
|
|
93
|
+
static get instance(): ReportManager;
|
|
94
|
+
/**
|
|
95
|
+
* Get the base URL for the report API
|
|
96
|
+
* @returns The base URL
|
|
97
|
+
*/
|
|
98
|
+
private getBaseURL;
|
|
99
|
+
/**
|
|
100
|
+
* Downloads a report based on project type and report type
|
|
101
|
+
* @param args Arguments for the report download
|
|
102
|
+
* @returns Promise that resolves when download is complete
|
|
103
|
+
*/
|
|
104
|
+
downloadReport(args: {
|
|
105
|
+
token: string;
|
|
106
|
+
projectType: ProjectType;
|
|
107
|
+
reportType: ReportType;
|
|
108
|
+
fileFormat: FileFormat;
|
|
109
|
+
query?: Record<string, any>;
|
|
110
|
+
}): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Process the download
|
|
113
|
+
* @param response The response from the API
|
|
114
|
+
* @param report The report definition
|
|
115
|
+
* @param fileFormat The requested file format
|
|
116
|
+
*/
|
|
117
|
+
private processDownload;
|
|
118
|
+
/**
|
|
119
|
+
* Handle error responses from the API
|
|
120
|
+
* @param response The response from the API
|
|
121
|
+
* @throws Error with appropriate message
|
|
122
|
+
*/
|
|
123
|
+
private handleErrorResponse;
|
|
124
|
+
/**
|
|
125
|
+
* Generates a default filename based on report and file format
|
|
126
|
+
* @param report The report definition
|
|
127
|
+
* @param fileFormat The requested file format
|
|
128
|
+
* @returns A suitable default filename with proper extension
|
|
129
|
+
*/
|
|
130
|
+
private getDefaultFilename;
|
|
131
|
+
/**
|
|
132
|
+
* Extracts the filename from the Content-Disposition header
|
|
133
|
+
* @param contentDisposition The Content-Disposition header value
|
|
134
|
+
* @returns The extracted filename or null if not found
|
|
135
|
+
*/
|
|
136
|
+
private extractFilenameFromContentDisposition;
|
|
137
|
+
/**
|
|
138
|
+
* Converts a base64 string to a Blob
|
|
139
|
+
* @param base64 The base64 string
|
|
140
|
+
* @returns A Blob
|
|
141
|
+
*/
|
|
142
|
+
private b64toBlob;
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=report_manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report_manager.d.ts","sourceRoot":"","sources":["../../../src/src/reports/report_manager.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,oBAAY,UAAU;IACpB,sBAAsB;IACtB,GAAG,QAAQ;IACX,wBAAwB;IACxB,KAAK,UAAU;CAChB;AAED;;GAEG;AACH,oBAAY,WAAW;IACrB,8BAA8B;IAC9B,SAAS,cAAc;IACvB,qBAAqB;IACrB,MAAM,WAAW;IACjB,qBAAqB;IACrB,OAAO,YAAY;CACpB;AAED;;GAEG;AACH,oBAAY,UAAU;IACpB,4CAA4C;IAC5C,4BAA4B,iCAAiC;IAC7D,8CAA8C;IAC9C,2BAA2B,gCAAgC;IAC3D,wCAAwC;IACxC,wBAAwB,6BAA6B;IACrD,4CAA4C;IAC5C,yBAAyB,8BAA8B;IACvD,uCAAuC;IACvC,uBAAuB,4BAA4B;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,gBAAgB,EAAE,UAAU,EAAE,CAAC;IAC/B,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,WAAW,EAAE,WAAW,CAAC;IACzB,yBAAyB;IACzB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;GAEG;AACH,eAAO,MAAM,OAAO;kCAUb,gBAAgB;iCAUhB,gBAAgB;8BAWhB,gBAAgB;+BAUhB,gBAAgB;6BAWhB,gBAAgB;CACtB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,GACvB,gBAAgB,EAAE,CAIpB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,UAAU,GACrB,OAAO,CAGT;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAgB;IAExC,OAAO;IAEP;;OAEG;IACH,WAAkB,QAAQ,kBAEzB;IAED;;;OAGG;IACH,OAAO,CAAC,UAAU,CAIhB;IAEF;;;;OAIG;IACU,cAAc,CAAC,IAAI,EAAE;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,WAAW,CAAC;QACzB,UAAU,EAAE,UAAU,CAAC;QACvB,UAAU,EAAE,UAAU,CAAC;QAEvB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC7B,GAAG,OAAO,CAAC,IAAI,CAAC;IAmFjB;;;;;OAKG;YACW,eAAe;IAqB7B;;;;OAIG;YACW,mBAAmB;IAwBjC;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;;;OAIG;IACH,OAAO,CAAC,qCAAqC;IA6B7C;;;;OAIG;IACH,OAAO,CAAC,SAAS,CACyB;CAC3C"}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import FileSaver from "file-saver";
|
|
2
|
+
import { ConfigService } from "../config/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Available file formats for reports
|
|
5
|
+
*/
|
|
6
|
+
export var FileFormat;
|
|
7
|
+
(function (FileFormat) {
|
|
8
|
+
/** PDF file format */
|
|
9
|
+
FileFormat["PDF"] = "pdf";
|
|
10
|
+
/** Excel file format */
|
|
11
|
+
FileFormat["EXCEL"] = "excel";
|
|
12
|
+
})(FileFormat || (FileFormat = {}));
|
|
13
|
+
/**
|
|
14
|
+
* Available project types
|
|
15
|
+
*/
|
|
16
|
+
export var ProjectType;
|
|
17
|
+
(function (ProjectType) {
|
|
18
|
+
/** Tembo Dashboard project */
|
|
19
|
+
ProjectType["DASHBOARD"] = "dashboard";
|
|
20
|
+
/** Afloat project */
|
|
21
|
+
ProjectType["AFLOAT"] = "afloat";
|
|
22
|
+
/** VertoX project */
|
|
23
|
+
ProjectType["VERTO_X"] = "verto_x";
|
|
24
|
+
})(ProjectType || (ProjectType = {}));
|
|
25
|
+
/**
|
|
26
|
+
* Available report types with improved naming
|
|
27
|
+
*/
|
|
28
|
+
export var ReportType;
|
|
29
|
+
(function (ReportType) {
|
|
30
|
+
/** Merchant payout statement (Dashboard) */
|
|
31
|
+
ReportType["MERCHANT_DISBURSEMENT_REPORT"] = "merchant_disbursement_report";
|
|
32
|
+
/** Transaction revenue summary (Dashboard) */
|
|
33
|
+
ReportType["TRANSACTION_REVENUE_SUMMARY"] = "transaction_revenue_summary";
|
|
34
|
+
/** Customer wallet activity (Afloat) */
|
|
35
|
+
ReportType["CUSTOMER_WALLET_ACTIVITY"] = "customer_wallet_activity";
|
|
36
|
+
/** Customer profile information (Afloat) */
|
|
37
|
+
ReportType["CUSTOMER_PROFILE_SNAPSHOT"] = "customer_profile_snapshot";
|
|
38
|
+
/** Gateway transaction log (VertoX) */
|
|
39
|
+
ReportType["GATEWAY_TRANSACTION_LOG"] = "gateway_transaction_log";
|
|
40
|
+
})(ReportType || (ReportType = {}));
|
|
41
|
+
/**
|
|
42
|
+
* Registry of all available reports
|
|
43
|
+
*/
|
|
44
|
+
export const REPORTS = {
|
|
45
|
+
// Dashboard Reports
|
|
46
|
+
[ReportType.MERCHANT_DISBURSEMENT_REPORT]: {
|
|
47
|
+
id: "merchant_disbursement_report",
|
|
48
|
+
displayName: "Merchant Disbursement Report",
|
|
49
|
+
endpoint: "/dashboard/merchant_disbursements",
|
|
50
|
+
availableFormats: [FileFormat.PDF, FileFormat.EXCEL],
|
|
51
|
+
projectType: ProjectType.DASHBOARD,
|
|
52
|
+
reportType: ReportType.MERCHANT_DISBURSEMENT_REPORT,
|
|
53
|
+
description: "Detailed breakdown of payments made to merchants",
|
|
54
|
+
},
|
|
55
|
+
[ReportType.TRANSACTION_REVENUE_SUMMARY]: {
|
|
56
|
+
id: "transaction_revenue_summary",
|
|
57
|
+
displayName: "Transaction Revenue Summary",
|
|
58
|
+
endpoint: "/dashboard/revenue_summary",
|
|
59
|
+
availableFormats: [FileFormat.PDF, FileFormat.EXCEL],
|
|
60
|
+
projectType: ProjectType.DASHBOARD,
|
|
61
|
+
reportType: ReportType.TRANSACTION_REVENUE_SUMMARY,
|
|
62
|
+
description: "Summary of all revenue transactions by period",
|
|
63
|
+
},
|
|
64
|
+
// Afloat Reports
|
|
65
|
+
[ReportType.CUSTOMER_WALLET_ACTIVITY]: {
|
|
66
|
+
id: "customer_wallet_activity",
|
|
67
|
+
displayName: "Customer Wallet Activity",
|
|
68
|
+
endpoint: "/afloat/wallet_activity",
|
|
69
|
+
availableFormats: [FileFormat.PDF, FileFormat.EXCEL],
|
|
70
|
+
projectType: ProjectType.AFLOAT,
|
|
71
|
+
reportType: ReportType.CUSTOMER_WALLET_ACTIVITY,
|
|
72
|
+
description: "Detailed record of all customer wallet transactions",
|
|
73
|
+
},
|
|
74
|
+
[ReportType.CUSTOMER_PROFILE_SNAPSHOT]: {
|
|
75
|
+
id: "customer_profile_snapshot",
|
|
76
|
+
displayName: "Customer Profile Snapshot",
|
|
77
|
+
endpoint: "/afloat/profile_snapshot",
|
|
78
|
+
availableFormats: [FileFormat.PDF],
|
|
79
|
+
projectType: ProjectType.AFLOAT,
|
|
80
|
+
reportType: ReportType.CUSTOMER_PROFILE_SNAPSHOT,
|
|
81
|
+
description: "Current account information and status",
|
|
82
|
+
},
|
|
83
|
+
// VertoX Reports
|
|
84
|
+
[ReportType.GATEWAY_TRANSACTION_LOG]: {
|
|
85
|
+
id: "gateway_transaction_log",
|
|
86
|
+
displayName: "Gateway Transaction Log",
|
|
87
|
+
endpoint: "/vertox/gateway_transactions",
|
|
88
|
+
availableFormats: [FileFormat.EXCEL],
|
|
89
|
+
projectType: ProjectType.VERTO_X,
|
|
90
|
+
reportType: ReportType.GATEWAY_TRANSACTION_LOG,
|
|
91
|
+
description: "Log of all payment gateway API transactions",
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Get all reports for a specific project
|
|
96
|
+
* @param projectType The project type to filter by
|
|
97
|
+
* @returns Array of report definitions for the project
|
|
98
|
+
*/
|
|
99
|
+
export function getReportsByProject(projectType) {
|
|
100
|
+
return Object.values(REPORTS).filter((report) => report.projectType === projectType);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get a report by its type
|
|
104
|
+
* @param reportType The report type to retrieve
|
|
105
|
+
* @returns The report definition or undefined if not found
|
|
106
|
+
*/
|
|
107
|
+
export function getReportByType(reportType) {
|
|
108
|
+
return REPORTS[reportType];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Validates if a report type is available for a project
|
|
112
|
+
* @param projectType The project type
|
|
113
|
+
* @param reportType The report type
|
|
114
|
+
* @returns True if the report is available for the project, false otherwise
|
|
115
|
+
*/
|
|
116
|
+
export function isReportAvailableForProject(projectType, reportType) {
|
|
117
|
+
const report = REPORTS[reportType];
|
|
118
|
+
return report !== undefined && report.projectType === projectType;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Report Manager class for handling report downloads
|
|
122
|
+
*/
|
|
123
|
+
export class ReportManager {
|
|
124
|
+
constructor() {
|
|
125
|
+
/**
|
|
126
|
+
* Get the base URL for the report API
|
|
127
|
+
* @returns The base URL
|
|
128
|
+
*/
|
|
129
|
+
Object.defineProperty(this, "getBaseURL", {
|
|
130
|
+
enumerable: true,
|
|
131
|
+
configurable: true,
|
|
132
|
+
writable: true,
|
|
133
|
+
value: () => {
|
|
134
|
+
const url = ConfigService.instance.pdfMakerBaseUrl;
|
|
135
|
+
if (url.endsWith("/"))
|
|
136
|
+
return url.slice(0, -1);
|
|
137
|
+
return url;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
/**
|
|
141
|
+
* Converts a base64 string to a Blob
|
|
142
|
+
* @param base64 The base64 string
|
|
143
|
+
* @returns A Blob
|
|
144
|
+
*/
|
|
145
|
+
Object.defineProperty(this, "b64toBlob", {
|
|
146
|
+
enumerable: true,
|
|
147
|
+
configurable: true,
|
|
148
|
+
writable: true,
|
|
149
|
+
value: (base64) => fetch(base64).then((res) => res.blob())
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get the singleton instance of ReportManager
|
|
154
|
+
*/
|
|
155
|
+
static get instance() {
|
|
156
|
+
return this._instance || (this._instance = new this());
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Downloads a report based on project type and report type
|
|
160
|
+
* @param args Arguments for the report download
|
|
161
|
+
* @returns Promise that resolves when download is complete
|
|
162
|
+
*/
|
|
163
|
+
async downloadReport(args) {
|
|
164
|
+
try {
|
|
165
|
+
// Get the report from the registry
|
|
166
|
+
const report = REPORTS[args.reportType];
|
|
167
|
+
if (!report) {
|
|
168
|
+
throw new Error(`Report type ${args.reportType} not configured`);
|
|
169
|
+
}
|
|
170
|
+
// Validate that the report belongs to the specified project
|
|
171
|
+
if (report.projectType !== args.projectType) {
|
|
172
|
+
throw new Error(`Report type ${args.reportType} does not belong to project ${args.projectType}`);
|
|
173
|
+
}
|
|
174
|
+
// Check if requested format is supported
|
|
175
|
+
if (!report.availableFormats.includes(args.fileFormat)) {
|
|
176
|
+
throw new Error(`File format ${args.fileFormat} not supported for ${report.displayName}`);
|
|
177
|
+
}
|
|
178
|
+
// Build URL using the report's endpoint
|
|
179
|
+
let url = `${this.getBaseURL()}${report.endpoint}`;
|
|
180
|
+
// Create a properly typed query parameters object
|
|
181
|
+
// deno-lint-ignore no-explicit-any
|
|
182
|
+
const queryParams = {
|
|
183
|
+
...(args.query || {}),
|
|
184
|
+
format: args.fileFormat,
|
|
185
|
+
};
|
|
186
|
+
// Build the query string
|
|
187
|
+
const searchParams = new URLSearchParams();
|
|
188
|
+
for (const key in queryParams) {
|
|
189
|
+
if (Object.prototype.hasOwnProperty.call(queryParams, key)) {
|
|
190
|
+
const value = queryParams[key];
|
|
191
|
+
if (value !== undefined && value !== null) {
|
|
192
|
+
if (Array.isArray(value)) {
|
|
193
|
+
value.forEach((item) => {
|
|
194
|
+
searchParams.append(key + "[]", String(item));
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
searchParams.append(key, String(value));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const queryString = searchParams.toString();
|
|
204
|
+
if (queryString) {
|
|
205
|
+
url += `?${queryString}`;
|
|
206
|
+
}
|
|
207
|
+
// Make the request
|
|
208
|
+
const response = await fetch(url, {
|
|
209
|
+
method: "GET",
|
|
210
|
+
headers: {
|
|
211
|
+
"Accept": "*/*",
|
|
212
|
+
"Content-Type": "application/json",
|
|
213
|
+
"Authorization": `Bearer ${args.token}`,
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
if (response.status !== 200) {
|
|
217
|
+
await this.handleErrorResponse(response);
|
|
218
|
+
}
|
|
219
|
+
// Process the download
|
|
220
|
+
await this.processDownload(response, report, args.fileFormat);
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
console.error("Report download failed:", error);
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Process the download
|
|
229
|
+
* @param response The response from the API
|
|
230
|
+
* @param report The report definition
|
|
231
|
+
* @param fileFormat The requested file format
|
|
232
|
+
*/
|
|
233
|
+
async processDownload(response, report, fileFormat) {
|
|
234
|
+
const contentDisposition = response.headers.get("Content-Disposition");
|
|
235
|
+
// Get default filename based on report and file format
|
|
236
|
+
const defaultFilename = this.getDefaultFilename(report, fileFormat);
|
|
237
|
+
// Try to get filename from Content-Disposition, fall back to default
|
|
238
|
+
const fileName = this.extractFilenameFromContentDisposition(contentDisposition) ||
|
|
239
|
+
defaultFilename;
|
|
240
|
+
// Handle the response based on content type
|
|
241
|
+
// deno-lint-ignore no-explicit-any
|
|
242
|
+
const blob = await this.b64toBlob(await response.text());
|
|
243
|
+
FileSaver.saveAs(blob, fileName);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Handle error responses from the API
|
|
247
|
+
* @param response The response from the API
|
|
248
|
+
* @throws Error with appropriate message
|
|
249
|
+
*/
|
|
250
|
+
async handleErrorResponse(response) {
|
|
251
|
+
let errorMessage = "Encountered an error while generating report";
|
|
252
|
+
try {
|
|
253
|
+
// Try to parse as JSON first
|
|
254
|
+
const contentType = response.headers.get("Content-Type");
|
|
255
|
+
if (contentType && contentType.includes("application/json")) {
|
|
256
|
+
const errorData = await response.json();
|
|
257
|
+
errorMessage = errorData.message || errorData.error ||
|
|
258
|
+
errorMessage;
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
// Try to get error as text
|
|
262
|
+
const textError = await response.text();
|
|
263
|
+
if (textError) {
|
|
264
|
+
errorMessage = textError;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
catch (parseError) {
|
|
269
|
+
console.error("Error parsing error response:", parseError);
|
|
270
|
+
}
|
|
271
|
+
throw new Error(errorMessage);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Generates a default filename based on report and file format
|
|
275
|
+
* @param report The report definition
|
|
276
|
+
* @param fileFormat The requested file format
|
|
277
|
+
* @returns A suitable default filename with proper extension
|
|
278
|
+
*/
|
|
279
|
+
getDefaultFilename(report, fileFormat) {
|
|
280
|
+
const date = new Date().toISOString().slice(0, 10); // YYYY-MM-DD format
|
|
281
|
+
// Build the filename with project, report type, and date
|
|
282
|
+
const baseFilename = `${report.id}_${date}`;
|
|
283
|
+
// Add the extension based on the file format
|
|
284
|
+
return fileFormat === FileFormat.PDF
|
|
285
|
+
? `${baseFilename}.pdf`
|
|
286
|
+
: `${baseFilename}.xlsx`;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Extracts the filename from the Content-Disposition header
|
|
290
|
+
* @param contentDisposition The Content-Disposition header value
|
|
291
|
+
* @returns The extracted filename or null if not found
|
|
292
|
+
*/
|
|
293
|
+
extractFilenameFromContentDisposition(contentDisposition) {
|
|
294
|
+
// Check if the header exists
|
|
295
|
+
if (!contentDisposition) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
// Try to match the filename pattern
|
|
299
|
+
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
|
|
300
|
+
const matches = filenameRegex.exec(contentDisposition);
|
|
301
|
+
if (matches && matches[1]) {
|
|
302
|
+
// Clean up the filename by removing quotes if present
|
|
303
|
+
let filename = matches[1].trim();
|
|
304
|
+
// Remove surrounding quotes if they exist
|
|
305
|
+
if (filename.startsWith('"') && filename.endsWith('"')) {
|
|
306
|
+
filename = filename.substring(1, filename.length - 1);
|
|
307
|
+
}
|
|
308
|
+
else if (filename.startsWith("'") && filename.endsWith("'")) {
|
|
309
|
+
filename = filename.substring(1, filename.length - 1);
|
|
310
|
+
}
|
|
311
|
+
return filename;
|
|
312
|
+
}
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@temboplus/frontend-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "A JavaScript/TypeScript package providing common utilities and logic shared across front-end TemboPlus projects.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"private": false,
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"antd": "^5.24.2",
|
|
27
|
+
"file-saver": "^2.0.5",
|
|
27
28
|
"uuid": "^11.1.0"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
package/script/mod.d.ts
CHANGED
package/script/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
|
package/script/mod.js
CHANGED
|
@@ -16,3 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./src/models/index.js"), exports);
|
|
18
18
|
__exportStar(require("./src/utils/index.js"), exports);
|
|
19
|
+
__exportStar(require("./src/reports/index.js"), exports);
|
|
20
|
+
__exportStar(require("./src/config/index.js"), exports);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class ConfigService {
|
|
2
|
+
private static _instance;
|
|
3
|
+
private _pdfMakerBaseUrl;
|
|
4
|
+
private constructor();
|
|
5
|
+
static get instance(): ConfigService;
|
|
6
|
+
initialize(config: {
|
|
7
|
+
pdfMakerBaseUrl: string;
|
|
8
|
+
}): void;
|
|
9
|
+
get pdfMakerBaseUrl(): string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=config_service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config_service.d.ts","sourceRoot":"","sources":["../../../src/src/config/config_service.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAgB;IACxC,OAAO,CAAC,gBAAgB,CAAc;IAEtC,OAAO;IAEP,WAAkB,QAAQ,kBAEzB;IAEM,UAAU,CAAC,MAAM,EAAE;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE;IAIrD,IAAW,eAAe,IAAI,MAAM,CAEnC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConfigService = void 0;
|
|
4
|
+
class ConfigService {
|
|
5
|
+
constructor() {
|
|
6
|
+
Object.defineProperty(this, "_pdfMakerBaseUrl", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: ""
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
static get instance() {
|
|
14
|
+
return this._instance || (this._instance = new this());
|
|
15
|
+
}
|
|
16
|
+
initialize(config) {
|
|
17
|
+
this._pdfMakerBaseUrl = config.pdfMakerBaseUrl;
|
|
18
|
+
}
|
|
19
|
+
get pdfMakerBaseUrl() {
|
|
20
|
+
return this._pdfMakerBaseUrl;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.ConfigService = ConfigService;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
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("./config_service.js"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/reports/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
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("./report_manager.js"), exports);
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Available file formats for reports
|
|
3
|
+
*/
|
|
4
|
+
export declare enum FileFormat {
|
|
5
|
+
/** PDF file format */
|
|
6
|
+
PDF = "pdf",
|
|
7
|
+
/** Excel file format */
|
|
8
|
+
EXCEL = "excel"
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Available project types
|
|
12
|
+
*/
|
|
13
|
+
export declare enum ProjectType {
|
|
14
|
+
/** Tembo Dashboard project */
|
|
15
|
+
DASHBOARD = "dashboard",
|
|
16
|
+
/** Afloat project */
|
|
17
|
+
AFLOAT = "afloat",
|
|
18
|
+
/** VertoX project */
|
|
19
|
+
VERTO_X = "verto_x"
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Available report types with improved naming
|
|
23
|
+
*/
|
|
24
|
+
export declare enum ReportType {
|
|
25
|
+
/** Merchant payout statement (Dashboard) */
|
|
26
|
+
MERCHANT_DISBURSEMENT_REPORT = "merchant_disbursement_report",
|
|
27
|
+
/** Transaction revenue summary (Dashboard) */
|
|
28
|
+
TRANSACTION_REVENUE_SUMMARY = "transaction_revenue_summary",
|
|
29
|
+
/** Customer wallet activity (Afloat) */
|
|
30
|
+
CUSTOMER_WALLET_ACTIVITY = "customer_wallet_activity",
|
|
31
|
+
/** Customer profile information (Afloat) */
|
|
32
|
+
CUSTOMER_PROFILE_SNAPSHOT = "customer_profile_snapshot",
|
|
33
|
+
/** Gateway transaction log (VertoX) */
|
|
34
|
+
GATEWAY_TRANSACTION_LOG = "gateway_transaction_log"
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Report definition interface
|
|
38
|
+
*/
|
|
39
|
+
export interface ReportDefinition {
|
|
40
|
+
/** Unique identifier for the report */
|
|
41
|
+
id: string;
|
|
42
|
+
/** Human-readable report name for UI display */
|
|
43
|
+
displayName: string;
|
|
44
|
+
/** API endpoint path for the report */
|
|
45
|
+
endpoint: string;
|
|
46
|
+
/** Available file formats for the report */
|
|
47
|
+
availableFormats: FileFormat[];
|
|
48
|
+
/** Optional description of the report */
|
|
49
|
+
description?: string;
|
|
50
|
+
/** Project the report belongs to */
|
|
51
|
+
projectType: ProjectType;
|
|
52
|
+
/** Type of the report */
|
|
53
|
+
reportType: ReportType;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Registry of all available reports
|
|
57
|
+
*/
|
|
58
|
+
export declare const REPORTS: {
|
|
59
|
+
merchant_disbursement_report: ReportDefinition;
|
|
60
|
+
transaction_revenue_summary: ReportDefinition;
|
|
61
|
+
customer_wallet_activity: ReportDefinition;
|
|
62
|
+
customer_profile_snapshot: ReportDefinition;
|
|
63
|
+
gateway_transaction_log: ReportDefinition;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Get all reports for a specific project
|
|
67
|
+
* @param projectType The project type to filter by
|
|
68
|
+
* @returns Array of report definitions for the project
|
|
69
|
+
*/
|
|
70
|
+
export declare function getReportsByProject(projectType: ProjectType): ReportDefinition[];
|
|
71
|
+
/**
|
|
72
|
+
* Get a report by its type
|
|
73
|
+
* @param reportType The report type to retrieve
|
|
74
|
+
* @returns The report definition or undefined if not found
|
|
75
|
+
*/
|
|
76
|
+
export declare function getReportByType(reportType: ReportType): ReportDefinition;
|
|
77
|
+
/**
|
|
78
|
+
* Validates if a report type is available for a project
|
|
79
|
+
* @param projectType The project type
|
|
80
|
+
* @param reportType The report type
|
|
81
|
+
* @returns True if the report is available for the project, false otherwise
|
|
82
|
+
*/
|
|
83
|
+
export declare function isReportAvailableForProject(projectType: ProjectType, reportType: ReportType): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Report Manager class for handling report downloads
|
|
86
|
+
*/
|
|
87
|
+
export declare class ReportManager {
|
|
88
|
+
private static _instance;
|
|
89
|
+
private constructor();
|
|
90
|
+
/**
|
|
91
|
+
* Get the singleton instance of ReportManager
|
|
92
|
+
*/
|
|
93
|
+
static get instance(): ReportManager;
|
|
94
|
+
/**
|
|
95
|
+
* Get the base URL for the report API
|
|
96
|
+
* @returns The base URL
|
|
97
|
+
*/
|
|
98
|
+
private getBaseURL;
|
|
99
|
+
/**
|
|
100
|
+
* Downloads a report based on project type and report type
|
|
101
|
+
* @param args Arguments for the report download
|
|
102
|
+
* @returns Promise that resolves when download is complete
|
|
103
|
+
*/
|
|
104
|
+
downloadReport(args: {
|
|
105
|
+
token: string;
|
|
106
|
+
projectType: ProjectType;
|
|
107
|
+
reportType: ReportType;
|
|
108
|
+
fileFormat: FileFormat;
|
|
109
|
+
query?: Record<string, any>;
|
|
110
|
+
}): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Process the download
|
|
113
|
+
* @param response The response from the API
|
|
114
|
+
* @param report The report definition
|
|
115
|
+
* @param fileFormat The requested file format
|
|
116
|
+
*/
|
|
117
|
+
private processDownload;
|
|
118
|
+
/**
|
|
119
|
+
* Handle error responses from the API
|
|
120
|
+
* @param response The response from the API
|
|
121
|
+
* @throws Error with appropriate message
|
|
122
|
+
*/
|
|
123
|
+
private handleErrorResponse;
|
|
124
|
+
/**
|
|
125
|
+
* Generates a default filename based on report and file format
|
|
126
|
+
* @param report The report definition
|
|
127
|
+
* @param fileFormat The requested file format
|
|
128
|
+
* @returns A suitable default filename with proper extension
|
|
129
|
+
*/
|
|
130
|
+
private getDefaultFilename;
|
|
131
|
+
/**
|
|
132
|
+
* Extracts the filename from the Content-Disposition header
|
|
133
|
+
* @param contentDisposition The Content-Disposition header value
|
|
134
|
+
* @returns The extracted filename or null if not found
|
|
135
|
+
*/
|
|
136
|
+
private extractFilenameFromContentDisposition;
|
|
137
|
+
/**
|
|
138
|
+
* Converts a base64 string to a Blob
|
|
139
|
+
* @param base64 The base64 string
|
|
140
|
+
* @returns A Blob
|
|
141
|
+
*/
|
|
142
|
+
private b64toBlob;
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=report_manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report_manager.d.ts","sourceRoot":"","sources":["../../../src/src/reports/report_manager.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,oBAAY,UAAU;IACpB,sBAAsB;IACtB,GAAG,QAAQ;IACX,wBAAwB;IACxB,KAAK,UAAU;CAChB;AAED;;GAEG;AACH,oBAAY,WAAW;IACrB,8BAA8B;IAC9B,SAAS,cAAc;IACvB,qBAAqB;IACrB,MAAM,WAAW;IACjB,qBAAqB;IACrB,OAAO,YAAY;CACpB;AAED;;GAEG;AACH,oBAAY,UAAU;IACpB,4CAA4C;IAC5C,4BAA4B,iCAAiC;IAC7D,8CAA8C;IAC9C,2BAA2B,gCAAgC;IAC3D,wCAAwC;IACxC,wBAAwB,6BAA6B;IACrD,4CAA4C;IAC5C,yBAAyB,8BAA8B;IACvD,uCAAuC;IACvC,uBAAuB,4BAA4B;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,gBAAgB,EAAE,UAAU,EAAE,CAAC;IAC/B,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,WAAW,EAAE,WAAW,CAAC;IACzB,yBAAyB;IACzB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;GAEG;AACH,eAAO,MAAM,OAAO;kCAUb,gBAAgB;iCAUhB,gBAAgB;8BAWhB,gBAAgB;+BAUhB,gBAAgB;6BAWhB,gBAAgB;CACtB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,GACvB,gBAAgB,EAAE,CAIpB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,UAAU,GACrB,OAAO,CAGT;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAgB;IAExC,OAAO;IAEP;;OAEG;IACH,WAAkB,QAAQ,kBAEzB;IAED;;;OAGG;IACH,OAAO,CAAC,UAAU,CAIhB;IAEF;;;;OAIG;IACU,cAAc,CAAC,IAAI,EAAE;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,WAAW,CAAC;QACzB,UAAU,EAAE,UAAU,CAAC;QACvB,UAAU,EAAE,UAAU,CAAC;QAEvB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC7B,GAAG,OAAO,CAAC,IAAI,CAAC;IAmFjB;;;;;OAKG;YACW,eAAe;IAqB7B;;;;OAIG;YACW,mBAAmB;IAwBjC;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;;;OAIG;IACH,OAAO,CAAC,qCAAqC;IA6B7C;;;;OAIG;IACH,OAAO,CAAC,SAAS,CACyB;CAC3C"}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ReportManager = exports.REPORTS = exports.ReportType = exports.ProjectType = exports.FileFormat = void 0;
|
|
7
|
+
exports.getReportsByProject = getReportsByProject;
|
|
8
|
+
exports.getReportByType = getReportByType;
|
|
9
|
+
exports.isReportAvailableForProject = isReportAvailableForProject;
|
|
10
|
+
const file_saver_1 = __importDefault(require("file-saver"));
|
|
11
|
+
const index_js_1 = require("../config/index.js");
|
|
12
|
+
/**
|
|
13
|
+
* Available file formats for reports
|
|
14
|
+
*/
|
|
15
|
+
var FileFormat;
|
|
16
|
+
(function (FileFormat) {
|
|
17
|
+
/** PDF file format */
|
|
18
|
+
FileFormat["PDF"] = "pdf";
|
|
19
|
+
/** Excel file format */
|
|
20
|
+
FileFormat["EXCEL"] = "excel";
|
|
21
|
+
})(FileFormat || (exports.FileFormat = FileFormat = {}));
|
|
22
|
+
/**
|
|
23
|
+
* Available project types
|
|
24
|
+
*/
|
|
25
|
+
var ProjectType;
|
|
26
|
+
(function (ProjectType) {
|
|
27
|
+
/** Tembo Dashboard project */
|
|
28
|
+
ProjectType["DASHBOARD"] = "dashboard";
|
|
29
|
+
/** Afloat project */
|
|
30
|
+
ProjectType["AFLOAT"] = "afloat";
|
|
31
|
+
/** VertoX project */
|
|
32
|
+
ProjectType["VERTO_X"] = "verto_x";
|
|
33
|
+
})(ProjectType || (exports.ProjectType = ProjectType = {}));
|
|
34
|
+
/**
|
|
35
|
+
* Available report types with improved naming
|
|
36
|
+
*/
|
|
37
|
+
var ReportType;
|
|
38
|
+
(function (ReportType) {
|
|
39
|
+
/** Merchant payout statement (Dashboard) */
|
|
40
|
+
ReportType["MERCHANT_DISBURSEMENT_REPORT"] = "merchant_disbursement_report";
|
|
41
|
+
/** Transaction revenue summary (Dashboard) */
|
|
42
|
+
ReportType["TRANSACTION_REVENUE_SUMMARY"] = "transaction_revenue_summary";
|
|
43
|
+
/** Customer wallet activity (Afloat) */
|
|
44
|
+
ReportType["CUSTOMER_WALLET_ACTIVITY"] = "customer_wallet_activity";
|
|
45
|
+
/** Customer profile information (Afloat) */
|
|
46
|
+
ReportType["CUSTOMER_PROFILE_SNAPSHOT"] = "customer_profile_snapshot";
|
|
47
|
+
/** Gateway transaction log (VertoX) */
|
|
48
|
+
ReportType["GATEWAY_TRANSACTION_LOG"] = "gateway_transaction_log";
|
|
49
|
+
})(ReportType || (exports.ReportType = ReportType = {}));
|
|
50
|
+
/**
|
|
51
|
+
* Registry of all available reports
|
|
52
|
+
*/
|
|
53
|
+
exports.REPORTS = {
|
|
54
|
+
// Dashboard Reports
|
|
55
|
+
[ReportType.MERCHANT_DISBURSEMENT_REPORT]: {
|
|
56
|
+
id: "merchant_disbursement_report",
|
|
57
|
+
displayName: "Merchant Disbursement Report",
|
|
58
|
+
endpoint: "/dashboard/merchant_disbursements",
|
|
59
|
+
availableFormats: [FileFormat.PDF, FileFormat.EXCEL],
|
|
60
|
+
projectType: ProjectType.DASHBOARD,
|
|
61
|
+
reportType: ReportType.MERCHANT_DISBURSEMENT_REPORT,
|
|
62
|
+
description: "Detailed breakdown of payments made to merchants",
|
|
63
|
+
},
|
|
64
|
+
[ReportType.TRANSACTION_REVENUE_SUMMARY]: {
|
|
65
|
+
id: "transaction_revenue_summary",
|
|
66
|
+
displayName: "Transaction Revenue Summary",
|
|
67
|
+
endpoint: "/dashboard/revenue_summary",
|
|
68
|
+
availableFormats: [FileFormat.PDF, FileFormat.EXCEL],
|
|
69
|
+
projectType: ProjectType.DASHBOARD,
|
|
70
|
+
reportType: ReportType.TRANSACTION_REVENUE_SUMMARY,
|
|
71
|
+
description: "Summary of all revenue transactions by period",
|
|
72
|
+
},
|
|
73
|
+
// Afloat Reports
|
|
74
|
+
[ReportType.CUSTOMER_WALLET_ACTIVITY]: {
|
|
75
|
+
id: "customer_wallet_activity",
|
|
76
|
+
displayName: "Customer Wallet Activity",
|
|
77
|
+
endpoint: "/afloat/wallet_activity",
|
|
78
|
+
availableFormats: [FileFormat.PDF, FileFormat.EXCEL],
|
|
79
|
+
projectType: ProjectType.AFLOAT,
|
|
80
|
+
reportType: ReportType.CUSTOMER_WALLET_ACTIVITY,
|
|
81
|
+
description: "Detailed record of all customer wallet transactions",
|
|
82
|
+
},
|
|
83
|
+
[ReportType.CUSTOMER_PROFILE_SNAPSHOT]: {
|
|
84
|
+
id: "customer_profile_snapshot",
|
|
85
|
+
displayName: "Customer Profile Snapshot",
|
|
86
|
+
endpoint: "/afloat/profile_snapshot",
|
|
87
|
+
availableFormats: [FileFormat.PDF],
|
|
88
|
+
projectType: ProjectType.AFLOAT,
|
|
89
|
+
reportType: ReportType.CUSTOMER_PROFILE_SNAPSHOT,
|
|
90
|
+
description: "Current account information and status",
|
|
91
|
+
},
|
|
92
|
+
// VertoX Reports
|
|
93
|
+
[ReportType.GATEWAY_TRANSACTION_LOG]: {
|
|
94
|
+
id: "gateway_transaction_log",
|
|
95
|
+
displayName: "Gateway Transaction Log",
|
|
96
|
+
endpoint: "/vertox/gateway_transactions",
|
|
97
|
+
availableFormats: [FileFormat.EXCEL],
|
|
98
|
+
projectType: ProjectType.VERTO_X,
|
|
99
|
+
reportType: ReportType.GATEWAY_TRANSACTION_LOG,
|
|
100
|
+
description: "Log of all payment gateway API transactions",
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Get all reports for a specific project
|
|
105
|
+
* @param projectType The project type to filter by
|
|
106
|
+
* @returns Array of report definitions for the project
|
|
107
|
+
*/
|
|
108
|
+
function getReportsByProject(projectType) {
|
|
109
|
+
return Object.values(exports.REPORTS).filter((report) => report.projectType === projectType);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get a report by its type
|
|
113
|
+
* @param reportType The report type to retrieve
|
|
114
|
+
* @returns The report definition or undefined if not found
|
|
115
|
+
*/
|
|
116
|
+
function getReportByType(reportType) {
|
|
117
|
+
return exports.REPORTS[reportType];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Validates if a report type is available for a project
|
|
121
|
+
* @param projectType The project type
|
|
122
|
+
* @param reportType The report type
|
|
123
|
+
* @returns True if the report is available for the project, false otherwise
|
|
124
|
+
*/
|
|
125
|
+
function isReportAvailableForProject(projectType, reportType) {
|
|
126
|
+
const report = exports.REPORTS[reportType];
|
|
127
|
+
return report !== undefined && report.projectType === projectType;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Report Manager class for handling report downloads
|
|
131
|
+
*/
|
|
132
|
+
class ReportManager {
|
|
133
|
+
constructor() {
|
|
134
|
+
/**
|
|
135
|
+
* Get the base URL for the report API
|
|
136
|
+
* @returns The base URL
|
|
137
|
+
*/
|
|
138
|
+
Object.defineProperty(this, "getBaseURL", {
|
|
139
|
+
enumerable: true,
|
|
140
|
+
configurable: true,
|
|
141
|
+
writable: true,
|
|
142
|
+
value: () => {
|
|
143
|
+
const url = index_js_1.ConfigService.instance.pdfMakerBaseUrl;
|
|
144
|
+
if (url.endsWith("/"))
|
|
145
|
+
return url.slice(0, -1);
|
|
146
|
+
return url;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
/**
|
|
150
|
+
* Converts a base64 string to a Blob
|
|
151
|
+
* @param base64 The base64 string
|
|
152
|
+
* @returns A Blob
|
|
153
|
+
*/
|
|
154
|
+
Object.defineProperty(this, "b64toBlob", {
|
|
155
|
+
enumerable: true,
|
|
156
|
+
configurable: true,
|
|
157
|
+
writable: true,
|
|
158
|
+
value: (base64) => fetch(base64).then((res) => res.blob())
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get the singleton instance of ReportManager
|
|
163
|
+
*/
|
|
164
|
+
static get instance() {
|
|
165
|
+
return this._instance || (this._instance = new this());
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Downloads a report based on project type and report type
|
|
169
|
+
* @param args Arguments for the report download
|
|
170
|
+
* @returns Promise that resolves when download is complete
|
|
171
|
+
*/
|
|
172
|
+
async downloadReport(args) {
|
|
173
|
+
try {
|
|
174
|
+
// Get the report from the registry
|
|
175
|
+
const report = exports.REPORTS[args.reportType];
|
|
176
|
+
if (!report) {
|
|
177
|
+
throw new Error(`Report type ${args.reportType} not configured`);
|
|
178
|
+
}
|
|
179
|
+
// Validate that the report belongs to the specified project
|
|
180
|
+
if (report.projectType !== args.projectType) {
|
|
181
|
+
throw new Error(`Report type ${args.reportType} does not belong to project ${args.projectType}`);
|
|
182
|
+
}
|
|
183
|
+
// Check if requested format is supported
|
|
184
|
+
if (!report.availableFormats.includes(args.fileFormat)) {
|
|
185
|
+
throw new Error(`File format ${args.fileFormat} not supported for ${report.displayName}`);
|
|
186
|
+
}
|
|
187
|
+
// Build URL using the report's endpoint
|
|
188
|
+
let url = `${this.getBaseURL()}${report.endpoint}`;
|
|
189
|
+
// Create a properly typed query parameters object
|
|
190
|
+
// deno-lint-ignore no-explicit-any
|
|
191
|
+
const queryParams = {
|
|
192
|
+
...(args.query || {}),
|
|
193
|
+
format: args.fileFormat,
|
|
194
|
+
};
|
|
195
|
+
// Build the query string
|
|
196
|
+
const searchParams = new URLSearchParams();
|
|
197
|
+
for (const key in queryParams) {
|
|
198
|
+
if (Object.prototype.hasOwnProperty.call(queryParams, key)) {
|
|
199
|
+
const value = queryParams[key];
|
|
200
|
+
if (value !== undefined && value !== null) {
|
|
201
|
+
if (Array.isArray(value)) {
|
|
202
|
+
value.forEach((item) => {
|
|
203
|
+
searchParams.append(key + "[]", String(item));
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
searchParams.append(key, String(value));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const queryString = searchParams.toString();
|
|
213
|
+
if (queryString) {
|
|
214
|
+
url += `?${queryString}`;
|
|
215
|
+
}
|
|
216
|
+
// Make the request
|
|
217
|
+
const response = await fetch(url, {
|
|
218
|
+
method: "GET",
|
|
219
|
+
headers: {
|
|
220
|
+
"Accept": "*/*",
|
|
221
|
+
"Content-Type": "application/json",
|
|
222
|
+
"Authorization": `Bearer ${args.token}`,
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
if (response.status !== 200) {
|
|
226
|
+
await this.handleErrorResponse(response);
|
|
227
|
+
}
|
|
228
|
+
// Process the download
|
|
229
|
+
await this.processDownload(response, report, args.fileFormat);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
console.error("Report download failed:", error);
|
|
233
|
+
throw error;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Process the download
|
|
238
|
+
* @param response The response from the API
|
|
239
|
+
* @param report The report definition
|
|
240
|
+
* @param fileFormat The requested file format
|
|
241
|
+
*/
|
|
242
|
+
async processDownload(response, report, fileFormat) {
|
|
243
|
+
const contentDisposition = response.headers.get("Content-Disposition");
|
|
244
|
+
// Get default filename based on report and file format
|
|
245
|
+
const defaultFilename = this.getDefaultFilename(report, fileFormat);
|
|
246
|
+
// Try to get filename from Content-Disposition, fall back to default
|
|
247
|
+
const fileName = this.extractFilenameFromContentDisposition(contentDisposition) ||
|
|
248
|
+
defaultFilename;
|
|
249
|
+
// Handle the response based on content type
|
|
250
|
+
// deno-lint-ignore no-explicit-any
|
|
251
|
+
const blob = await this.b64toBlob(await response.text());
|
|
252
|
+
file_saver_1.default.saveAs(blob, fileName);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Handle error responses from the API
|
|
256
|
+
* @param response The response from the API
|
|
257
|
+
* @throws Error with appropriate message
|
|
258
|
+
*/
|
|
259
|
+
async handleErrorResponse(response) {
|
|
260
|
+
let errorMessage = "Encountered an error while generating report";
|
|
261
|
+
try {
|
|
262
|
+
// Try to parse as JSON first
|
|
263
|
+
const contentType = response.headers.get("Content-Type");
|
|
264
|
+
if (contentType && contentType.includes("application/json")) {
|
|
265
|
+
const errorData = await response.json();
|
|
266
|
+
errorMessage = errorData.message || errorData.error ||
|
|
267
|
+
errorMessage;
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
// Try to get error as text
|
|
271
|
+
const textError = await response.text();
|
|
272
|
+
if (textError) {
|
|
273
|
+
errorMessage = textError;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
catch (parseError) {
|
|
278
|
+
console.error("Error parsing error response:", parseError);
|
|
279
|
+
}
|
|
280
|
+
throw new Error(errorMessage);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Generates a default filename based on report and file format
|
|
284
|
+
* @param report The report definition
|
|
285
|
+
* @param fileFormat The requested file format
|
|
286
|
+
* @returns A suitable default filename with proper extension
|
|
287
|
+
*/
|
|
288
|
+
getDefaultFilename(report, fileFormat) {
|
|
289
|
+
const date = new Date().toISOString().slice(0, 10); // YYYY-MM-DD format
|
|
290
|
+
// Build the filename with project, report type, and date
|
|
291
|
+
const baseFilename = `${report.id}_${date}`;
|
|
292
|
+
// Add the extension based on the file format
|
|
293
|
+
return fileFormat === FileFormat.PDF
|
|
294
|
+
? `${baseFilename}.pdf`
|
|
295
|
+
: `${baseFilename}.xlsx`;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Extracts the filename from the Content-Disposition header
|
|
299
|
+
* @param contentDisposition The Content-Disposition header value
|
|
300
|
+
* @returns The extracted filename or null if not found
|
|
301
|
+
*/
|
|
302
|
+
extractFilenameFromContentDisposition(contentDisposition) {
|
|
303
|
+
// Check if the header exists
|
|
304
|
+
if (!contentDisposition) {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
// Try to match the filename pattern
|
|
308
|
+
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
|
|
309
|
+
const matches = filenameRegex.exec(contentDisposition);
|
|
310
|
+
if (matches && matches[1]) {
|
|
311
|
+
// Clean up the filename by removing quotes if present
|
|
312
|
+
let filename = matches[1].trim();
|
|
313
|
+
// Remove surrounding quotes if they exist
|
|
314
|
+
if (filename.startsWith('"') && filename.endsWith('"')) {
|
|
315
|
+
filename = filename.substring(1, filename.length - 1);
|
|
316
|
+
}
|
|
317
|
+
else if (filename.startsWith("'") && filename.endsWith("'")) {
|
|
318
|
+
filename = filename.substring(1, filename.length - 1);
|
|
319
|
+
}
|
|
320
|
+
return filename;
|
|
321
|
+
}
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
exports.ReportManager = ReportManager;
|