billing - pdf document - code simplified
MODIFY
src/integration/billing/BillingIntegration.ts
src/integration/billing/BillingIntegration.ts
-import { BillingChargeInvoiceAction, BillingDataTransactionStart, BillingDataTransactionStop, BillingDataTransactionUpdate, BillingInvoice, BillingInvoiceDocument, BillingInvoiceItem, BillingInvoiceStatus, BillingOperationResult, BillingPaymentMethod, BillingTax, BillingUser, BillingUserSynchronizeAction } from '../../types/Billing';
+import { BillingChargeInvoiceAction, BillingDataTransactionStart, BillingDataTransactionStop, BillingDataTransactionUpdate, BillingInvoice, BillingInvoiceItem, BillingInvoiceStatus, BillingOperationResult, BillingPaymentMethod, BillingTax, BillingUser, BillingUserSynchronizeAction } from '../../types/Billing';
import FeatureToggles, { Feature } from '../../utils/FeatureToggles';
import User, { UserStatus } from '../../types/User';
@@ -395,7 +395,7 @@ export default abstract class BillingIntegration {
abstract billInvoiceItem(user: User, billingInvoiceItems: BillingInvoiceItem, idemPotencyKey?: string): Promise<BillingInvoice>;
- abstract downloadInvoiceDocument(invoice: BillingInvoice): Promise<BillingInvoiceDocument>;
+ abstract downloadInvoiceDocument(invoice: BillingInvoice): Promise<Buffer>;
abstract chargeInvoice(invoice: BillingInvoice): Promise<BillingInvoice>;

MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
/* eslint-disable @typescript-eslint/member-ordering */
-import { BillingDataTransactionStart, BillingDataTransactionStop, BillingDataTransactionUpdate, BillingInvoice, BillingInvoiceDocument, BillingInvoiceItem, BillingInvoiceStatus, BillingOperationResult, BillingPaymentMethod, BillingStatus, BillingTax, BillingUser, BillingUserData } from '../../../types/Billing';
-import { DocumentEncoding, DocumentType } from '../../../types/GlobalType';
+import { BillingDataTransactionStart, BillingDataTransactionStop, BillingDataTransactionUpdate, BillingInvoice, BillingInvoiceItem, BillingInvoiceStatus, BillingOperationResult, BillingPaymentMethod, BillingStatus, BillingTax, BillingUser, BillingUserData } from '../../../types/Billing';
import FeatureToggles, { Feature } from '../../../utils/FeatureToggles';
import AxiosFactory from '../../../utils/AxiosFactory';
@@ -332,22 +331,14 @@ export default class StripeBillingIntegration extends BillingIntegration {
return []; // No tax rates so far!
}
- public async downloadInvoiceDocument(invoice: BillingInvoice): Promise<BillingInvoiceDocument> {
+ public async downloadInvoiceDocument(invoice: BillingInvoice): Promise<Buffer> {
if (invoice.downloadUrl) {
// Get document
const response = await this.axiosInstance.get(invoice.downloadUrl, {
responseType: 'arraybuffer'
});
// Convert
- const base64Image = Buffer.from(response.data).toString('base64');
- const content = 'data:' + response.headers['content-type'] + ';base64,' + base64Image;
- return {
- id: invoice.id,
- invoiceID: invoice.invoiceID,
- content: content,
- type: DocumentType.PDF,
- encoding: DocumentEncoding.BASE64
- };
+ return Buffer.from(response.data);
}
}

MODIFY
src/server/rest/v1/service/BillingService.ts
src/server/rest/v1/service/BillingService.ts
@@ -638,7 +638,7 @@ export default class BillingService {
next();
}
- public static async handleDownloadInvoice(action: ServerAction, req: Request, res: Response): Promise<void> {
+ public static async handleDownloadInvoice(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
// Check if component is active
UtilsService.assertComponentIsActiveFromToken(req.user, TenantComponents.BILLING,
Action.DOWNLOAD, Entity.BILLING, MODULE_NAME, 'handleDownloadInvoice');
@@ -669,31 +669,22 @@ export default class BillingService {
user: req.user
});
}
- // Get the PDF document directly from the Invoice
- const invoiceDocument = await billingImpl.downloadInvoiceDocument(billingInvoice);
- // Send the Document
- if (invoiceDocument && invoiceDocument.content) {
- const base64RawData = invoiceDocument.content.split(`;${invoiceDocument.encoding},`).pop();
- const filename = 'invoice_' + billingInvoice.number + '.' + invoiceDocument.type;
- fs.writeFile(filename, base64RawData, { encoding: invoiceDocument.encoding }, (err) => {
- if (err) {
- console.error(err);
- throw err;
- }
- res.download(filename, (err2) => {
- if (err2) {
- console.error(err2);
- throw err2;
- }
- fs.unlink(filename, (err3) => {
- if (err3) {
- console.error(err3);
- throw err3;
- }
- });
- });
+
+ const buffer = await billingImpl.downloadInvoiceDocument(billingInvoice);
+ if (!billingInvoice.number || !buffer) {
+ throw new AppError({
+ source: Constants.CENTRAL_SERVER,
+ errorCode: HTTPError.GENERAL_ERROR,
+ message: 'Invoice document not found',
+ module: MODULE_NAME, method: 'handleDownloadInvoice',
+ action: action,
+ user: req.user
});
}
+ const fileName = 'invoice_' + billingInvoice.number + '.pdf';
+ res.attachment(fileName);
+ res.setHeader('Content-Type', 'application/pdf');
+ res.end(buffer, 'binary');
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/require-await

MODIFY
src/types/Billing.ts
src/types/Billing.ts
-import { ActionsResponse, DocumentEncoding, DocumentType } from './GlobalType';
-
+import { ActionsResponse } from './GlobalType';
import User from './User';
export interface BillingTransactionData {
@@ -113,14 +112,6 @@ export enum BillingInvoiceStatus {
DRAFT = 'draft',
}
-export interface BillingInvoiceDocument {
- id: string;
- invoiceID: string;
- content: string; // Base64 format
- type: DocumentType;
- encoding: DocumentEncoding;
-}
-
export interface BillingOperationResult {
succeeded: boolean
error?: Error

MODIFY
src/types/GlobalType.ts
src/types/GlobalType.ts
@@ -30,20 +30,11 @@ export interface ActionsResponse {
inError: number;
}
-export enum DocumentType {
- PDF = 'pdf',
-}
-
-export enum DocumentEncoding {
- BASE64 = 'base64',
-}
-
export enum ImportStatus {
READY = 'R',
ERROR = 'E',
}
-
interface TSGlobal extends Global {
database: MongoDBStorage;
appRoot: string;

billing - pdf document - code simplified