const EmailClient = require("../core/EmailClient"); const TemplateManager = require("../core/TemplateManager"); /** * CustomerServiceEmailService handles all customer service alert emails * This service is responsible for: * - Sending late return notifications to CS team * - Sending damage report notifications to CS team * - Sending lost item notifications to CS team */ class CustomerServiceEmailService { constructor() { this.emailClient = new EmailClient(); this.templateManager = new TemplateManager(); this.initialized = false; } /** * Initialize the customer service email service * @returns {Promise} */ async initialize() { if (this.initialized) return; await Promise.all([ this.emailClient.initialize(), this.templateManager.initialize(), ]); this.initialized = true; console.log("Customer Service Email Service initialized successfully"); } /** * Send late return notification to customer service * @param {Object} rental - Rental object * @param {number} rental.id - Rental ID * @param {Date} rental.endDateTime - Scheduled end date/time * @param {Date} rental.actualReturnDateTime - Actual return date/time * @param {Object} rental.item - Item object with name property * @param {Object} owner - Owner user object * @param {string} owner.firstName - Owner's first name * @param {string} owner.lastName - Owner's last name * @param {string} owner.email - Owner's email * @param {Object} renter - Renter user object * @param {string} renter.firstName - Renter's first name * @param {string} renter.lastName - Renter's last name * @param {string} renter.email - Renter's email * @param {Object} lateCalculation - Late fee calculation * @param {number} lateCalculation.lateHours - Hours late * @param {number} lateCalculation.lateFee - Late fee amount * @returns {Promise<{success: boolean, messageId?: string, error?: string}>} */ async sendLateReturnToCustomerService(rental, owner, renter, lateCalculation) { if (!this.initialized) { await this.initialize(); } try { const csEmail = process.env.CUSTOMER_SUPPORT_EMAIL; if (!csEmail) { console.warn("No customer service email configured"); return { success: false, error: "No customer service email configured" }; } // Format dates const scheduledEnd = new Date(rental.endDateTime).toLocaleString(); const actualReturn = new Date(rental.actualReturnDateTime).toLocaleString(); const variables = { rentalId: rental.id, itemName: rental.item.name, ownerName: `${owner.firstName} ${owner.lastName}`, ownerEmail: owner.email, renterName: `${renter.firstName} ${renter.lastName}`, renterEmail: renter.email, scheduledEnd, actualReturn, hoursLate: lateCalculation.lateHours.toFixed(1), lateFee: lateCalculation.lateFee.toFixed(2), }; const htmlContent = await this.templateManager.renderTemplate( "lateReturnToCS", variables ); const result = await this.emailClient.sendEmail( csEmail, "Late Return Detected - Action Required", htmlContent ); if (result.success) { console.log( `Late return notification sent to customer service for rental ${rental.id}` ); } return result; } catch (error) { console.error( "Failed to send late return notification to customer service:", error ); return { success: false, error: error.message }; } } /** * Send damage report notification to customer service * @param {Object} rental - Rental object * @param {number} rental.id - Rental ID * @param {Object} rental.item - Item object with name property * @param {Object} owner - Owner user object * @param {string} owner.firstName - Owner's first name * @param {string} owner.lastName - Owner's last name * @param {string} owner.email - Owner's email * @param {Object} renter - Renter user object * @param {string} renter.firstName - Renter's first name * @param {string} renter.lastName - Renter's last name * @param {string} renter.email - Renter's email * @param {Object} damageAssessment - Damage assessment details * @param {string} damageAssessment.description - Damage description * @param {boolean} damageAssessment.canBeFixed - Whether item can be repaired * @param {number} [damageAssessment.repairCost] - Repair cost if applicable * @param {boolean} damageAssessment.needsReplacement - Whether item needs replacement * @param {number} [damageAssessment.replacementCost] - Replacement cost if applicable * @param {Object} damageAssessment.feeCalculation - Fee calculation details * @param {string} damageAssessment.feeCalculation.type - Fee type (repair/replacement) * @param {number} damageAssessment.feeCalculation.amount - Fee amount * @param {Array} [damageAssessment.proofOfOwnership] - Proof of ownership documents * @param {Object} [lateCalculation] - Late fee calculation (optional) * @param {number} [lateCalculation.lateFee] - Late fee amount * @returns {Promise<{success: boolean, messageId?: string, error?: string}>} */ async sendDamageReportToCustomerService( rental, owner, renter, damageAssessment, lateCalculation = null ) { if (!this.initialized) { await this.initialize(); } try { const csEmail = process.env.CUSTOMER_SUPPORT_EMAIL; if (!csEmail) { console.warn("No customer service email configured"); return { success: false, error: "No customer service email configured" }; } // Calculate total fees (ensure numeric values) const damageFee = parseFloat(damageAssessment.feeCalculation.amount) || 0; const lateFee = parseFloat(lateCalculation?.lateFee || 0); const totalFees = damageFee + lateFee; // Determine fee type description let feeTypeDescription = ""; if (damageAssessment.feeCalculation.type === "repair") { feeTypeDescription = "Repair Cost"; } else if (damageAssessment.feeCalculation.type === "replacement") { feeTypeDescription = "Replacement Cost"; } else { feeTypeDescription = "Damage Assessment Fee"; } const variables = { rentalId: rental.id, itemName: rental.item.name, ownerName: `${owner.firstName} ${owner.lastName}`, ownerEmail: owner.email, renterName: `${renter.firstName} ${renter.lastName}`, renterEmail: renter.email, damageDescription: damageAssessment.description, canBeFixed: damageAssessment.canBeFixed ? "Yes" : "No", repairCost: damageAssessment.repairCost ? damageAssessment.repairCost.toFixed(2) : "N/A", needsReplacement: damageAssessment.needsReplacement ? "Yes" : "No", replacementCost: damageAssessment.replacementCost ? damageAssessment.replacementCost.toFixed(2) : "N/A", feeTypeDescription, damageFee: damageFee.toFixed(2), lateFee: lateFee.toFixed(2), totalFees: totalFees.toFixed(2), hasProofOfOwnership: damageAssessment.proofOfOwnership && damageAssessment.proofOfOwnership.length > 0 ? "Yes" : "No", }; const htmlContent = await this.templateManager.renderTemplate( "damageReportToCS", variables ); const result = await this.emailClient.sendEmail( csEmail, "Damage Report Filed - Action Required", htmlContent ); if (result.success) { console.log( `Damage report notification sent to customer service for rental ${rental.id}` ); } return result; } catch (error) { console.error( "Failed to send damage report notification to customer service:", error ); return { success: false, error: error.message }; } } /** * Send lost item notification to customer service * @param {Object} rental - Rental object * @param {number} rental.id - Rental ID * @param {Date} rental.endDateTime - Scheduled return date * @param {Date} rental.itemLostReportedAt - When loss was reported * @param {Object} rental.item - Item object * @param {string} rental.item.name - Item name * @param {number} rental.item.replacementCost - Item replacement cost * @param {Object} owner - Owner user object * @param {string} owner.firstName - Owner's first name * @param {string} owner.lastName - Owner's last name * @param {string} owner.email - Owner's email * @param {Object} renter - Renter user object * @param {string} renter.firstName - Renter's first name * @param {string} renter.lastName - Renter's last name * @param {string} renter.email - Renter's email * @returns {Promise<{success: boolean, messageId?: string, error?: string}>} */ async sendLostItemToCustomerService(rental, owner, renter) { if (!this.initialized) { await this.initialize(); } try { const csEmail = process.env.CUSTOMER_SUPPORT_EMAIL; if (!csEmail) { console.warn("No customer service email configured"); return { success: false, error: "No customer service email configured" }; } // Format dates const reportedAt = new Date(rental.itemLostReportedAt).toLocaleString(); const scheduledReturnDate = new Date(rental.endDateTime).toLocaleString(); const variables = { rentalId: rental.id, itemName: rental.item.name, ownerName: `${owner.firstName} ${owner.lastName}`, ownerEmail: owner.email, renterName: `${renter.firstName} ${renter.lastName}`, renterEmail: renter.email, reportedAt, scheduledReturnDate, replacementCost: parseFloat(rental.item.replacementCost).toFixed(2), }; const htmlContent = await this.templateManager.renderTemplate( "lostItemToCS", variables ); const result = await this.emailClient.sendEmail( csEmail, "Lost Item Claim Filed - Action Required", htmlContent ); if (result.success) { console.log( `Lost item notification sent to customer service for rental ${rental.id}` ); } return result; } catch (error) { console.error( "Failed to send lost item notification to customer service:", error ); return { success: false, error: error.message }; } } } module.exports = CustomerServiceEmailService;