Files
rentall-app/backend/services/lateReturnService.js

110 lines
3.6 KiB
JavaScript

const { Rental, Item, User } = require("../models");
const emailServices = require("./email");
class LateReturnService {
/**
* Calculate late fees based on actual return time vs scheduled end time
* @param {Object} rental - Rental instance with populated item data
* @param {Date} actualReturnDateTime - When the item was actually returned
* @returns {Object} - { lateHours, lateFee, isLate }
*/
static calculateLateFee(rental, actualReturnDateTime) {
const scheduledEnd = new Date(rental.endDateTime);
const actualReturn = new Date(actualReturnDateTime);
// Calculate hours late
const hoursLate = (actualReturn - scheduledEnd) / (1000 * 60 * 60);
if (hoursLate <= 0) {
return {
lateHours: 0,
lateFee: 0.0,
isLate: false,
};
}
let lateFee = 0;
let pricingType = "daily";
const billableDays = Math.ceil(hoursLate / 24);
// Calculate late fees per day, deriving daily rate from available pricing tiers
if (rental.item?.pricePerDay && rental.item.pricePerDay > 0) {
// Daily pricing - charge per day late
lateFee = billableDays * parseFloat(rental.item.pricePerDay);
} else if (rental.item?.pricePerWeek && rental.item.pricePerWeek > 0) {
// Weekly pricing - derive daily rate and charge per day late
const dailyRate = parseFloat(rental.item.pricePerWeek) / 7;
lateFee = billableDays * dailyRate;
} else if (rental.item?.pricePerMonth && rental.item.pricePerMonth > 0) {
// Monthly pricing - derive daily rate and charge per day late
const dailyRate = parseFloat(rental.item.pricePerMonth) / 30;
lateFee = billableDays * dailyRate;
} else if (rental.item?.pricePerHour && rental.item.pricePerHour > 0) {
// Hourly pricing - derive daily rate and charge per day late
const dailyRate = parseFloat(rental.item.pricePerHour) * 24;
lateFee = billableDays * dailyRate;
} else {
// Free borrows - charge $10 per day late
lateFee = billableDays * 10.0;
}
return {
lateHours: hoursLate,
lateFee: parseFloat(lateFee.toFixed(2)),
isLate: true,
pricingType,
};
}
/**
* Process late return and update rental with fees
* @param {string} rentalId - Rental ID
* @param {Date} actualReturnDateTime - When item was returned
* @returns {Object} - Updated rental with late fee information
*/
static async processLateReturn(rentalId, actualReturnDateTime) {
const rental = await Rental.findByPk(rentalId, {
include: [{ model: Item, as: "item" }],
});
if (!rental) {
throw new Error("Rental not found");
}
if (rental.status !== "active") {
throw new Error("Can only process late returns for active rentals");
}
const lateCalculation = this.calculateLateFee(rental, actualReturnDateTime);
const updates = {
actualReturnDateTime: new Date(actualReturnDateTime),
status: lateCalculation.isLate ? "returned_late" : "completed",
payoutStatus: "pending",
};
const updatedRental = await rental.update(updates);
// Send notification to customer service if late return detected
if (lateCalculation.isLate && lateCalculation.lateFee > 0) {
// Fetch owner and renter user data for email
const owner = await User.findByPk(updatedRental.ownerId);
const renter = await User.findByPk(updatedRental.renterId);
await emailServices.customerService.sendLateReturnToCustomerService(
updatedRental,
owner,
renter,
lateCalculation
);
}
return {
rental: updatedRental,
lateCalculation,
};
}
}
module.exports = LateReturnService;