122 lines
4.9 KiB
Python
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()
|