Skip to content

Commit

Permalink
feat: BCGOV fax implementation (#1437)
Browse files Browse the repository at this point in the history
  • Loading branch information
praju-aot authored Jun 18, 2024
1 parent 4fc0d23 commit 04d16de
Show file tree
Hide file tree
Showing 26 changed files with 433 additions and 98 deletions.
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ services:
ORBC_SERVICE_ACCOUNT_CLIENT_ID: ${ORBC_SERVICE_ACCOUNT_CLIENT_ID}
ORBC_SERVICE_ACCOUNT_CLIENT_SECRET: ${ORBC_SERVICE_ACCOUNT_CLIENT_SECRET}
KEYCLOAK_SERVICE_ACCOUNT_AUDIENCE: ${KEYCLOAK_SERVICE_ACCOUNT_AUDIENCE}
BCGOV_FAX_EMAIL: ${BCGOV_FAX_EMAIL}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/"]
interval: 1m30s
Expand Down
127 changes: 113 additions & 14 deletions dops/src/app.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,49 +62,49 @@ export class AppService {
await addToCache(
this.cacheManager,
CacheKey.PAYMENT_AND_REFUND_DETAILED_REPORT,
this.convertFiletoString(
this.convertFileToString(
assetsPath + 'templates/payment-refund-detailed.report.hbs',
),
);

await addToCache(
this.cacheManager,
CacheKey.PAYMENT_AND_REFUND_SUMMARY_REPORT,
this.convertFiletoString(
this.convertFileToString(
assetsPath + 'templates/payment-refund-summary.report.hbs',
),
);

await addToCache(
this.cacheManager,
CacheKey.EMAIL_TEMPLATE_PROFILE_REGISTRATION,
this.convertFiletoString(
this.convertFileToString(
assetsPath + 'templates/profile-registration.email.hbs',
),
);
await addToCache(
this.cacheManager,
CacheKey.EMAIL_TEMPLATE_ISSUE_PERMIT,
this.convertFiletoString(assetsPath + 'templates/issue-permit.email.hbs'),
this.convertFileToString(assetsPath + 'templates/issue-permit.email.hbs'),
);
await addToCache(
this.cacheManager,
CacheKey.EMAIL_TEMPLATE_PAYMENT_RECEIPT,
this.convertFiletoString(
this.convertFileToString(
assetsPath + 'templates/payment-receipt.email.hbs',
),
);
await addToCache(
this.cacheManager,
CacheKey.EMAIL_TEMPLATE_COMPANY_SUSPEND,
this.convertFiletoString(
this.convertFileToString(
assetsPath + 'templates/suspend-company.email.hbs',
),
);
await addToCache(
this.cacheManager,
CacheKey.EMAIL_TEMPLATE_COMPANY_UNSUSPEND,
this.convertFiletoString(
this.convertFileToString(
assetsPath + 'templates/unsuspend-company.email.hbs',
),
);
Expand All @@ -116,6 +116,97 @@ export class AppService {
createCacheMap(featureFlags, 'featureKey', 'featureValue'),
);

await addToCache(
this.cacheManager,
CacheKey.IMG_HEADER_LOGO,
this.convertFileToString(
assetsPath + 'images/BC_Logo_MOTI.png',
true,
'base64',
),
);
await addToCache(
this.cacheManager,
CacheKey.IMG_FOOTER_LOGO,
this.convertFileToString(
assetsPath + 'images/onRouteBC_Logo.png',
true,
'base64',
),
);
await addToCache(
this.cacheManager,
CacheKey.IMG_DARK_MODE_HEADER_LOGO,
this.convertFileToString(
assetsPath + 'images/BC_Logo_Rev_MOTI.png',
true,
'base64',
),
);
await addToCache(
this.cacheManager,
CacheKey.IMG_DARK_MODE_MED_HEADER_LOGO,
this.convertFileToString(
assetsPath + 'images/[email protected]',
true,
'base64',
),
);
await addToCache(
this.cacheManager,
CacheKey.IMG_DARK_MODE_FOOTER_LOGO,
this.convertFileToString(
assetsPath + 'images/onRouteBC_Rev_Logo.png',
true,
'base64',
),
);
await addToCache(
this.cacheManager,
CacheKey.IMG_DARK_MODE_MED_FOOTER_LOGO,
this.convertFileToString(
assetsPath + 'images/[email protected]',
true,
'base64',
),
);
await addToCache(
this.cacheManager,
CacheKey.IMG_WHITE_HEADER_LOGO,
this.convertFileToString(
assetsPath + 'images/BC_Logo_MOTI_White.jpg',
true,
'base64',
),
);
await addToCache(
this.cacheManager,
CacheKey.IMG_WHITE_MED_HEADER_LOGO,
this.convertFileToString(
assetsPath + 'images/[email protected]',
true,
'base64',
),
);
await addToCache(
this.cacheManager,
CacheKey.IMG_WHITE_FOOTER_LOGO,
this.convertFileToString(
assetsPath + 'images/onRouteBC_Logo_White.jpg',
true,
'base64',
),
);
await addToCache(
this.cacheManager,
CacheKey.IMG_WHITE_MED_FOOTER_LOGO,
this.convertFileToString(
assetsPath + 'images/[email protected]',
true,
'base64',
),
);

const endDateTime = new Date();
const processingTime = endDateTime.getTime() - startDateTime.getTime();
this.logger.log(
Expand All @@ -125,12 +216,20 @@ export class AppService {
);
}

private convertFiletoString(filePath: string, encode?: string) {
const file = fs.readFileSync(filePath, 'utf-8');
if (encode) {
return Buffer.from(file).toString('base64');
} else {
return Buffer.from(file).toString();
}
/**
* Converts a file to a string representation.
*
* @param {string} filePath - The path to the file to convert.
* @param {boolean} [treatAsBinary=false] - Flag to indicate if the file should be read as binary.
* @param {BufferEncoding} [encode] - The optional encoding to use for the buffer conversion.
* @returns {string} - The string representation of the file.
*/
private convertFileToString(
filePath: string,
treatAsBinary = false,
encode?: BufferEncoding,
) {
const file = fs.readFileSync(filePath, treatAsBinary ? undefined : 'utf-8');
return Buffer.from(file).toString(encode);
}
}
Binary file added dops/src/assets/images/BC_Logo_MOTI.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dops/src/assets/images/BC_Logo_MOTI_White.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dops/src/assets/images/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dops/src/assets/images/BC_Logo_Rev_MOTI.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dops/src/assets/images/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dops/src/assets/images/onRouteBC_Logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dops/src/assets/images/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dops/src/assets/images/onRouteBC_Rev_Logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dops/src/assets/images/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions dops/src/enum/cache-key.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,14 @@ export enum CacheKey {
PAYMENT_AND_REFUND_DETAILED_REPORT = 'PAYMENT_AND_REFUND_DETAILED_REPORT',
PAYMENT_AND_REFUND_SUMMARY_REPORT = 'PAYMENT_AND_REFUND_SUMMARY_REPORT',
FEATURE_FLAG_TYPE = 'FEATURE_FLAG_TYPE',
IMG_HEADER_LOGO = 'IMG_HEADER_LOGO',
IMG_FOOTER_LOGO = 'IMG_FOOTER_LOGO',
IMG_DARK_MODE_HEADER_LOGO = 'IMG_DARK_MODE_HEADER_LOGO',
IMG_DARK_MODE_MED_HEADER_LOGO = 'IMG_DARK_MODE_MED_HEADER_LOGO',
IMG_DARK_MODE_FOOTER_LOGO = 'IMG_DARK_MODE_FOOTER_LOGO',
IMG_DARK_MODE_MED_FOOTER_LOGO = 'IMG_DARK_MODE_MED_FOOTER_LOGO',
IMG_WHITE_HEADER_LOGO = 'IMG_WHITE_HEADER_LOGO',
IMG_WHITE_MED_HEADER_LOGO = 'IMG_WHITE_MED_HEADER_LOGO',
IMG_WHITE_FOOTER_LOGO = 'IMG_WHITE_FOOTER_LOGO',
IMG_WHITE_MED_FOOTER_LOGO = 'IMG_WHITE_MED_FOOTER_LOGO',
}
4 changes: 4 additions & 0 deletions dops/src/enum/image-type.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum ImageType {
JPG = 'image/jpg',
PNG = 'image/png',
}
148 changes: 148 additions & 0 deletions dops/src/helper/notification.helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { InternalServerErrorException } from '@nestjs/common';
import { CacheKey } from '../enum/cache-key.enum';
import { ImageType } from '../enum/image-type.enum';
import { NotificationTemplate } from '../enum/notification-template.enum';
import { getFromCache } from './cache.helper';
import { Cache } from 'cache-manager';
import * as Handlebars from 'handlebars';

/**
* Retrieves a base64 encoded image string from the cache.
*
* @param imageType - The type of the image to retrieve.
* @param cacheManager - The cache manager instance to use.
* @param cacheKey - The cache key under which the image is stored.
* @returns A promise that resolves to a base64 encoded image string.
*/
export const getBase64Img = async (
imageType: ImageType,
cacheManager: Cache,
cacheKey: CacheKey,
): Promise<string> => {
return `data:${imageType};base64,${await getFromCache(
cacheManager,
cacheKey,
)}`;
};

export const getCacheKeyforEmailTemplate = (
templateName: NotificationTemplate,
): CacheKey => {
switch (templateName) {
case NotificationTemplate.ISSUE_PERMIT:
return CacheKey.EMAIL_TEMPLATE_ISSUE_PERMIT;
case NotificationTemplate.PAYMENT_RECEIPT:
return CacheKey.EMAIL_TEMPLATE_PAYMENT_RECEIPT;
case NotificationTemplate.PROFILE_REGISTRATION:
return CacheKey.EMAIL_TEMPLATE_PROFILE_REGISTRATION;
case NotificationTemplate.COMPANY_SUSPEND:
return CacheKey.EMAIL_TEMPLATE_COMPANY_SUSPEND;
case NotificationTemplate.COMPANY_UNSUSPEND:
return CacheKey.EMAIL_TEMPLATE_COMPANY_UNSUSPEND;
default:
throw new Error('Invalid template name');
}
};

/**
* Compiles an HTML email body from a specified template and data.
*
* This method retrieves an email template by name from the cache, then uses Handlebars to compile the template
* with the provided data object. It automatically adds URLs for various logos based on environment variables
* and returns the compiled HTML as a string.
*
* @param templateName The name of the email template to render.
* @param data The data object to pass to the Handlebars template.
* @param isEmbedBase64Image Whether to embed images as Base64 images.
* @returns A promise that resolves with the compiled HTML string of the email body.
* @throws InternalServerErrorException If the template is not found in the cache.
*/
export const renderTemplate = async (
templateName: NotificationTemplate,
data: object,
cacheManager: Cache,
isEmbedBase64Image = false,
): Promise<string> => {
const template = await getFromCache(
cacheManager,
getCacheKeyforEmailTemplate(templateName),
);
if (!template?.length) {
throw new InternalServerErrorException('Template not found');
}
const compiledTemplate = Handlebars.compile(template);
const htmlBody = compiledTemplate({
...data,
headerLogo: isEmbedBase64Image
? await getBase64Img(
ImageType.PNG,
cacheManager,
CacheKey.IMG_HEADER_LOGO,
)
: process.env.FRONTEND_URL + '/BC_Logo_MOTI.png',
footerLogo: isEmbedBase64Image
? await getBase64Img(
ImageType.PNG,
cacheManager,
CacheKey.IMG_FOOTER_LOGO,
)
: process.env.FRONTEND_URL + '/onRouteBC_Logo.png',
darkModeHeaderLogo: isEmbedBase64Image
? await getBase64Img(
ImageType.PNG,
cacheManager,
CacheKey.IMG_DARK_MODE_HEADER_LOGO,
)
: process.env.FRONTEND_URL + '/BC_Logo_Rev_MOTI.png',
darkModeMedHeaderLogo: isEmbedBase64Image
? await getBase64Img(
ImageType.PNG,
cacheManager,
CacheKey.IMG_DARK_MODE_MED_HEADER_LOGO,
)
: process.env.FRONTEND_URL + '/[email protected]',
darkModeFooterLogo: isEmbedBase64Image
? await getBase64Img(
ImageType.PNG,
cacheManager,
CacheKey.IMG_DARK_MODE_FOOTER_LOGO,
)
: process.env.FRONTEND_URL + '/onRouteBC_Rev_Logo.png',
darkModeMedFooterLogo: isEmbedBase64Image
? await getBase64Img(
ImageType.PNG,
cacheManager,
CacheKey.IMG_DARK_MODE_MED_FOOTER_LOGO,
)
: process.env.FRONTEND_URL + '/[email protected]',
whiteHeaderLogo: isEmbedBase64Image
? await getBase64Img(
ImageType.JPG,
cacheManager,
CacheKey.IMG_WHITE_HEADER_LOGO,
)
: process.env.FRONTEND_URL + '/BC_Logo_MOTI_White.jpg',
whiteMedHeaderLogo: isEmbedBase64Image
? await getBase64Img(
ImageType.JPG,
cacheManager,
CacheKey.IMG_WHITE_MED_HEADER_LOGO,
)
: process.env.FRONTEND_URL + '/[email protected]',
whiteFooterLogo: isEmbedBase64Image
? await getBase64Img(
ImageType.JPG,
cacheManager,
CacheKey.IMG_WHITE_FOOTER_LOGO,
)
: process.env.FRONTEND_URL + '/onRouteBC_Logo_White.jpg',
whiteMedFooterLogo: isEmbedBase64Image
? await getBase64Img(
ImageType.JPG,
cacheManager,
CacheKey.IMG_WHITE_MED_FOOTER_LOGO,
)
: process.env.FRONTEND_URL + '/[email protected]',
});
return htmlBody;
};
2 changes: 2 additions & 0 deletions dops/src/modules/common/common.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ export class CommonService {
);
},
onRetry(retryCount, error, requestConfig) {
/* eslint-disable */
this.logger.error(
`URL: ${requestConfig?.baseURL}, error status: ${error?.status}, Retry Count: ${retryCount}`,
);
/* eslint-enable */
},
});
}
Expand Down
Loading

0 comments on commit 04d16de

Please sign in to comment.