2026-06-12 15:12:50 +05:30

122 lines
4.9 KiB
Python

# -*- coding: utf-8 -*-
from odoo.tests.common import TransactionCase
from odoo.fields import Datetime
from datetime import datetime, timedelta
from odoo.exceptions import UserError
class TestEventRental(TransactionCase):
@classmethod
def setUpClass(cls):
super(TestEventRental, cls).setUpClass()
# Create a rental product template first, then get variant
cls.rental_product = cls.env['product.product'].create({
'name': 'Wedding Chair',
'type': 'product',
'is_rental': True,
'rental_price_per_day': 10.0,
})
# Set quantity on hand using Odoo stock.quant
warehouse = cls.env['stock.warehouse'].search([], limit=1)
if warehouse:
location = warehouse.lot_stock_id
cls.env['stock.quant'].with_context(inventory_mode=True).create({
'product_id': cls.rental_product.id,
'location_id': location.id,
'inventory_quantity': 50.0,
}).action_apply_inventory()
# Create a customer partner
cls.partner = cls.env['res.partner'].create({
'name': 'Test Client',
'email': 'client@test.com',
'phone': '1234567890',
})
def test_01_rental_flow(self):
""" Test the complete rental reservation, pricing, approval, payment, and delivery flow """
# Define dates: 3 days rental duration
start_date = datetime.now() + timedelta(days=1)
end_date = start_date + timedelta(days=3)
# Create request
request = self.env['event.rental.request'].create({
'partner_id': self.partner.id,
'start_date': start_date,
'end_date': end_date,
'location': 'Grand Palace Hall',
'event_type': 'wedding',
'delivery_charge': 50.0,
'setup_charge': 30.0,
})
# Create line: booking 10 chairs
line = self.env['event.rental.line'].create({
'request_id': request.id,
'product_id': self.rental_product.id,
'quantity': 10.0,
})
# Verify duration-based pricing: 3 days * $10 per day = $30 per chair unit
self.assertEqual(line.price_unit, 30.0, "Line unit price should be rental_price_per_day * duration")
self.assertEqual(line.price_subtotal, 300.0, "Subtotal should be quantity * price_unit")
# Verify grand total: $300 (subtotal) + $50 (delivery) + $30 (setup) = $380
self.assertEqual(request.amount_total, 380.0, "Grand total is incorrect")
# Check availability
avail = request.check_availability(start_date, end_date, self.rental_product)
self.assertEqual(avail, 50.0, "Before approval, all 50 chairs should be available")
# Approve request
request.action_approve()
# Status should become quotation_sent
self.assertEqual(request.status, 'quotation_sent')
self.assertTrue(request.sale_order_id, "Sales Order should be generated")
self.assertEqual(request.sale_order_id.amount_untaxed, 380.0, "Sales order untaxed total should match rental request total")
# Check availability again: since approved request blocks inventory, available should drop by 10
avail_after_approval = request.check_availability(start_date, end_date, self.rental_product)
self.assertEqual(avail_after_approval, 40.0, "Approved booking should block inventory")
# Confirm Sale Order (simulating payment)
request.sale_order_id.action_confirm()
# Request status should automatically become confirmed
self.assertEqual(request.status, 'confirmed')
# Deliver products
request.action_deliver()
self.assertEqual(request.status, 'delivered')
self.assertEqual(request.delivery_status, 'delivered')
# Return products
request.action_pickup()
self.assertEqual(request.status, 'returned')
self.assertEqual(request.delivery_status, 'picked_up')
def test_02_overbooking_prevention(self):
""" Test that overbooking raises a UserError during approval """
start_date = datetime.now() + timedelta(days=1)
end_date = start_date + timedelta(days=3)
# Request 60 chairs (only 50 are on hand)
request = self.env['event.rental.request'].create({
'partner_id': self.partner.id,
'start_date': start_date,
'end_date': end_date,
'location': 'Venue Hall',
})
self.env['event.rental.line'].create({
'request_id': request.id,
'product_id': self.rental_product.id,
'quantity': 60.0,
})
# Approving should raise UserError
with self.assertRaises(UserError):
request.action_approve()