Files
rentall-app/backend/services/email/domain/PaymentEmailService.js

177 lines
5.6 KiB
JavaScript

const EmailClient = require("../core/EmailClient");
const TemplateManager = require("../core/TemplateManager");
/**
* PaymentEmailService handles payment-related emails
* This service is responsible for:
* - Sending payment declined notifications to renters
* - Sending payment method updated notifications to owners
*/
class PaymentEmailService {
constructor() {
this.emailClient = new EmailClient();
this.templateManager = new TemplateManager();
this.initialized = false;
}
/**
* Initialize the payment email service
* @returns {Promise<void>}
*/
async initialize() {
if (this.initialized) return;
await Promise.all([
this.emailClient.initialize(),
this.templateManager.initialize(),
]);
this.initialized = true;
console.log("Payment Email Service initialized successfully");
}
/**
* Send payment declined notification to renter
* @param {string} renterEmail - Renter's email address
* @param {Object} params - Email parameters
* @param {string} params.renterFirstName - Renter's first name
* @param {string} params.itemName - Item name
* @param {string} params.declineReason - User-friendly decline reason
* @param {string} params.rentalId - Rental ID
* @param {string} params.updatePaymentUrl - URL to update payment method
* @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
*/
async sendPaymentDeclinedNotification(renterEmail, params) {
if (!this.initialized) {
await this.initialize();
}
try {
const {
renterFirstName,
itemName,
declineReason,
updatePaymentUrl,
} = params;
const variables = {
renterFirstName: renterFirstName || "there",
itemName: itemName || "the item",
declineReason: declineReason || "Your payment could not be processed.",
updatePaymentUrl: updatePaymentUrl,
};
const htmlContent = await this.templateManager.renderTemplate(
"paymentDeclinedToRenter",
variables
);
return await this.emailClient.sendEmail(
renterEmail,
`Action Required: Payment Issue - ${itemName || "Your Rental"}`,
htmlContent
);
} catch (error) {
console.error("Failed to send payment declined notification:", error);
return { success: false, error: error.message };
}
}
/**
* Send payment method updated notification to owner
* @param {string} ownerEmail - Owner's email address
* @param {Object} params - Email parameters
* @param {string} params.ownerFirstName - Owner's first name
* @param {string} params.itemName - Item name
* @param {string} params.rentalId - Rental ID
* @param {string} params.approvalUrl - URL to approve the rental
* @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
*/
async sendPaymentMethodUpdatedNotification(ownerEmail, params) {
if (!this.initialized) {
await this.initialize();
}
try {
const { ownerFirstName, itemName, approvalUrl } = params;
const variables = {
ownerFirstName: ownerFirstName || "there",
itemName: itemName || "the item",
approvalUrl: approvalUrl,
};
const htmlContent = await this.templateManager.renderTemplate(
"paymentMethodUpdatedToOwner",
variables
);
return await this.emailClient.sendEmail(
ownerEmail,
`Payment Method Updated - ${itemName || "Your Item"}`,
htmlContent
);
} catch (error) {
console.error("Failed to send payment method updated notification:", error);
return { success: false, error: error.message };
}
}
/**
* Send payout failed notification to owner
* @param {string} ownerEmail - Owner's email address
* @param {Object} params - Email parameters
* @param {string} params.ownerName - Owner's name
* @param {number} params.payoutAmount - Payout amount in dollars
* @param {string} params.failureMessage - User-friendly failure message
* @param {string} params.actionRequired - Action the owner needs to take
* @param {string} params.failureCode - The Stripe failure code
* @param {boolean} params.requiresBankUpdate - Whether bank account update is needed
* @param {string} params.payoutSettingsUrl - URL to payout settings
* @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
*/
async sendPayoutFailedNotification(ownerEmail, params) {
if (!this.initialized) {
await this.initialize();
}
try {
const {
ownerName,
payoutAmount,
failureMessage,
actionRequired,
failureCode,
requiresBankUpdate,
payoutSettingsUrl,
} = params;
const variables = {
ownerName: ownerName || "there",
payoutAmount: payoutAmount?.toFixed(2) || "0.00",
failureMessage: failureMessage || "There was an issue with your payout.",
actionRequired: actionRequired || "Please check your bank account details.",
failureCode: failureCode || "unknown",
requiresBankUpdate: requiresBankUpdate || false,
payoutSettingsUrl: payoutSettingsUrl || process.env.FRONTEND_URL + "/settings/payouts",
};
const htmlContent = await this.templateManager.renderTemplate(
"payoutFailedToOwner",
variables
);
return await this.emailClient.sendEmail(
ownerEmail,
"Action Required: Payout Issue - Village Share",
htmlContent
);
} catch (error) {
console.error("Failed to send payout failed notification:", error);
return { success: false, error: error.message };
}
}
}
module.exports = PaymentEmailService;