Fixed bug where could not rent 3-4 and 4-5PM
This commit is contained in:
@@ -273,37 +273,20 @@ router.post("/", authenticateToken, requireVerifiedEmail, async (req, res) => {
|
||||
|
||||
// Check for overlapping rentals using datetime ranges
|
||||
// Note: "active" rentals are stored as "confirmed" with startDateTime in the past
|
||||
// Two ranges [A,B] and [C,D] overlap if and only if A < D AND C < B
|
||||
// Here: existing rental [existingStart, existingEnd], new rental [rentalStartDateTime, rentalEndDateTime]
|
||||
// Overlap: existingStart < rentalEndDateTime AND rentalStartDateTime < existingEnd
|
||||
const overlappingRental = await Rental.findOne({
|
||||
where: {
|
||||
itemId,
|
||||
status: "confirmed",
|
||||
[Op.or]: [
|
||||
{
|
||||
[Op.and]: [
|
||||
{ startDateTime: { [Op.not]: null } },
|
||||
{ endDateTime: { [Op.not]: null } },
|
||||
{
|
||||
[Op.or]: [
|
||||
{
|
||||
startDateTime: {
|
||||
[Op.between]: [rentalStartDateTime, rentalEndDateTime],
|
||||
},
|
||||
},
|
||||
{
|
||||
endDateTime: {
|
||||
[Op.between]: [rentalStartDateTime, rentalEndDateTime],
|
||||
},
|
||||
},
|
||||
{
|
||||
[Op.and]: [
|
||||
{ startDateTime: { [Op.lte]: rentalStartDateTime } },
|
||||
{ endDateTime: { [Op.gte]: rentalEndDateTime } },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
startDateTime: { [Op.not]: null },
|
||||
endDateTime: { [Op.not]: null },
|
||||
[Op.and]: [
|
||||
// existingStart < newEnd (existing rental starts before new one ends)
|
||||
{ startDateTime: { [Op.lt]: rentalEndDateTime } },
|
||||
// existingEnd > newStart (existing rental ends after new one starts)
|
||||
{ endDateTime: { [Op.gt]: rentalStartDateTime } },
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -1087,6 +1070,27 @@ router.post("/cost-preview", authenticateToken, async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
// Check for overlapping rentals (same logic as in POST /rentals)
|
||||
// Two ranges overlap if: existingStart < newEnd AND existingEnd > newStart
|
||||
const overlappingRental = await Rental.findOne({
|
||||
where: {
|
||||
itemId,
|
||||
status: "confirmed",
|
||||
startDateTime: { [Op.not]: null },
|
||||
endDateTime: { [Op.not]: null },
|
||||
[Op.and]: [
|
||||
{ startDateTime: { [Op.lt]: rentalEndDateTime } },
|
||||
{ endDateTime: { [Op.gt]: rentalStartDateTime } },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
if (overlappingRental) {
|
||||
return res
|
||||
.status(400)
|
||||
.json({ error: "Item is already booked for these dates" });
|
||||
}
|
||||
|
||||
// Calculate rental cost using duration calculator
|
||||
const totalAmount = RentalDurationCalculator.calculateRentalCost(
|
||||
rentalStartDateTime,
|
||||
|
||||
@@ -420,6 +420,20 @@ const RentItem: React.FC = () => {
|
||||
<i className="bi bi-exclamation-triangle me-2"></i>
|
||||
{dateValidationError}
|
||||
</div>
|
||||
) : costError ? (
|
||||
<div className="alert alert-danger">
|
||||
<i className="bi bi-exclamation-triangle me-2"></i>
|
||||
{costError}
|
||||
<div className="mt-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-secondary btn-sm"
|
||||
onClick={() => navigate(`/items/${id}`)}
|
||||
>
|
||||
Choose Different Dates
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : !rentalDates.startDateTime ||
|
||||
!rentalDates.endDateTime ||
|
||||
!getRentalData() ? (
|
||||
|
||||
Reference in New Issue
Block a user