145 lines
4.0 KiB
JavaScript
145 lines
4.0 KiB
JavaScript
const { Rental, Item, ConditionCheck, User } = require("../models");
|
|
const LateReturnService = require("./lateReturnService");
|
|
const emailServices = require("./email");
|
|
|
|
class DamageAssessmentService {
|
|
/**
|
|
* Process damage assessment and calculate fees
|
|
* @param {string} rentalId - Rental ID
|
|
* @param {Object} damageInfo - Damage assessment information
|
|
* @param {string} userId - Owner reporting the damage
|
|
* @returns {Object} - Updated rental with damage fees
|
|
*/
|
|
static async processDamageAssessment(rentalId, damageInfo, userId) {
|
|
const {
|
|
description,
|
|
canBeFixed,
|
|
repairCost,
|
|
needsReplacement,
|
|
replacementCost,
|
|
proofOfOwnership,
|
|
actualReturnDateTime,
|
|
imageFilenames = [],
|
|
} = damageInfo;
|
|
|
|
const rental = await Rental.findByPk(rentalId, {
|
|
include: [{ model: Item, as: "item" }],
|
|
});
|
|
|
|
if (!rental) {
|
|
throw new Error("Rental not found");
|
|
}
|
|
|
|
if (rental.ownerId !== userId) {
|
|
throw new Error("Only the item owner can report damage");
|
|
}
|
|
|
|
if (rental.status !== "active") {
|
|
throw new Error("Can only assess damage for active rentals");
|
|
}
|
|
|
|
// Validate required fields
|
|
if (!description || description.trim().length === 0) {
|
|
throw new Error("Damage description is required");
|
|
}
|
|
|
|
if (canBeFixed && (!repairCost || repairCost <= 0)) {
|
|
throw new Error("Repair cost is required when item can be fixed");
|
|
}
|
|
|
|
if (needsReplacement && (!replacementCost || replacementCost <= 0)) {
|
|
throw new Error(
|
|
"Replacement cost is required when item needs replacement"
|
|
);
|
|
}
|
|
|
|
// Calculate damage fees
|
|
let damageFees = 0;
|
|
let feeCalculation = {};
|
|
|
|
if (needsReplacement) {
|
|
// Full replacement cost
|
|
damageFees = parseFloat(replacementCost);
|
|
feeCalculation = {
|
|
type: "replacement",
|
|
amount: damageFees,
|
|
originalCost: replacementCost,
|
|
depreciation: 0,
|
|
};
|
|
} else if (canBeFixed && repairCost > 0) {
|
|
// Repair cost
|
|
damageFees = parseFloat(repairCost);
|
|
feeCalculation = {
|
|
type: "repair",
|
|
amount: damageFees,
|
|
repairCost: repairCost,
|
|
};
|
|
}
|
|
|
|
// Process late return if applicable
|
|
let lateFees = 0;
|
|
let lateCalculation = null;
|
|
|
|
if (actualReturnDateTime) {
|
|
const lateReturn = await LateReturnService.processLateReturn(
|
|
rentalId,
|
|
actualReturnDateTime,
|
|
`Item returned damaged: ${description}`
|
|
);
|
|
lateFees = lateReturn.lateCalculation.lateFee;
|
|
lateCalculation = lateReturn.lateCalculation;
|
|
}
|
|
|
|
// Create damage assessment record as metadata
|
|
const damageAssessment = {
|
|
description,
|
|
canBeFixed,
|
|
repairCost: canBeFixed ? parseFloat(repairCost) : null,
|
|
needsReplacement,
|
|
replacementCost: needsReplacement ? parseFloat(replacementCost) : null,
|
|
proofOfOwnership: proofOfOwnership || [],
|
|
imageFilenames,
|
|
assessedAt: new Date(),
|
|
assessedBy: userId,
|
|
feeCalculation,
|
|
};
|
|
|
|
// Update rental
|
|
const updates = {
|
|
status: "damaged",
|
|
damageFees: damageFees,
|
|
damageAssessment: damageAssessment,
|
|
};
|
|
|
|
// Add late fees if applicable
|
|
if (lateFees > 0) {
|
|
updates.lateFees = lateFees;
|
|
updates.actualReturnDateTime = new Date(actualReturnDateTime);
|
|
}
|
|
|
|
const updatedRental = await rental.update(updates);
|
|
|
|
// Fetch owner and renter user data for email
|
|
const owner = await User.findByPk(updatedRental.ownerId);
|
|
const renter = await User.findByPk(updatedRental.renterId);
|
|
|
|
// Send damage report to customer service for review
|
|
await emailServices.customerService.sendDamageReportToCustomerService(
|
|
updatedRental,
|
|
owner,
|
|
renter,
|
|
damageAssessment,
|
|
lateCalculation
|
|
);
|
|
|
|
return {
|
|
rental: updatedRental,
|
|
damageAssessment,
|
|
lateCalculation,
|
|
totalAdditionalFees: damageFees + lateFees,
|
|
};
|
|
}
|
|
}
|
|
|
|
module.exports = DamageAssessmentService;
|