Enterprise-grade Resource Booking & Management for Odoo 18
Self-service Portal Booking, Backend Calendar Management, Discussion Channel Integration
Features • Architecture • Installation • Screenshots • Configuration • Security • API • Changelog • 中文文件
Odoo Resource Booking & Reservation is a complete resource booking solution for Odoo 18. It enables Portal users to browse available resources, select time slots, confirm bookings, and collaborate with attendees through built-in discussion channels. Administrators manage all reservations via a backend calendar view with resource configuration, availability schedules, access control, and capacity management.
| Challenge | Solution |
|---|---|
| Complex booking workflows | Portal users self-serve bookings online without contacting admins |
| Double-booking conflicts | SQL row-level locking (FOR UPDATE) prevents concurrent conflicts — 100% collision-free |
| No unified management view | Backend calendar view integration — all bookings at a glance |
| Scattered team communication | Auto-created discussion channel per booking for real-time collaboration |
| Insufficient security | XSS protection, IDOR validation, RPC bypass prevention, Portal record rules |
| Website module dependency | Pure Portal architecture — lightweight deployment, no Website module required |
- Resource Browsing — Card-based interface showing all bookable resources with location, capacity, and description
- Slot Selection — Calendar-style time slot display with booked slots auto-marked, week-by-week navigation
- Booking Confirmation — Enter topic, description, and optionally enable a discussion channel
- My Bookings — View all booking records with filtering (upcoming/all) and sorting (by date)
- Booking Details — Full booking information, cancel booking, re-book, and enter discussion channel
- Discussion Channels — Each booking can create a dedicated channel for real-time communication
- Calendar View — Day/Week/Month/Year viewing modes with color-coded resources
- Resource Management — Create/edit resources with category, location, capacity, slot duration, interval, and advance booking days
- Availability Schedule — Set daily available hours by day of week (e.g., Mon-Fri 09:00-18:00)
- Access Control — "All Portal Users" or "Specific Contacts" modes
- Reservation List — List view for managing all bookings with search, filter, and grouping
- Advanced Settings — Dynamic attributes (native Odoo feature), resource categories, reminder notifications
- XSS Protection — All user input processed via
html_sanitize, templates uset-outinstead oft-raw - Race Condition Prevention — SQL
FOR UPDATErow-level locking prevents concurrent booking conflicts - IDOR Protection — Discussion channel access validation ensures only booking-related users can access
- RPC Bypass Prevention — Model-level constraints (
@api.constrains) block direct RPC calls bypassing controllers - Portal Record Rules — 3
ir.rulerecords restrict Portal user access to authorized resources only - Deletion Protection —
partner_idset toondelete='restrict'to prevent deleting associated bookers
┌─────────────────────────────────────────────────────────────┐
│ Odoo Resource Booking & Reservation │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────┐ ┌────────────────────────┐ │
│ │ Portal Frontend │ │ Backend Admin │ │
│ │ │ │ │ │
│ │ • Resource Browsing │ │ • Calendar View │ │
│ │ • Slot Selection │ │ • Reservation List/Form │ │
│ │ • Booking Confirm │ │ • Resource Config │ │
│ │ • My Bookings │ │ • Category Management │ │
│ │ • Discussion Channels │ │ • Availability Setup │ │
│ └──────────┬─────────────┘ └──────────┬─────────────┘ │
│ │ │ │
│ └───────────┬───────────────┘ │
│ │ │
│ ┌──────────────────────▼──────────────────────────────┐ │
│ │ Core Model Layer │ │
│ │ │ │
│ │ booking.reservation — Booking records │ │
│ │ booking.resource.type — Bookable resources │ │
│ │ booking.resource.category — Resource categories │ │
│ │ booking.resource.availability — Availability slots │ │
│ │ │ │
│ │ Security: │ │
│ │ • SQL FOR UPDATE race condition prevention │ │
│ │ • @api.constrains model-level validation │ │
│ │ • ir.rule Portal record rules │ │
│ │ • html_sanitize XSS protection │ │
│ └──────────────────────┬──────────────────────────────┘ │
│ │ │
├─────────────────────────┼────────────────────────────────────┤
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Odoo 18 Framework │ │
│ │ Portal │ Mail │ Calendar │ ORM │ Security │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────────────────▼───────────────────────────────┐ │
│ │ PostgreSQL │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
odoo_booking_reservation
├── base
├── mail (Discussion channels, email notifications)
├── calendar (Calendar view integration)
├── portal (Portal user interface)
└── cs_portal_discuss (Portal discussion page)
Portal users browse all bookable resources showing name, location, and capacity.
After selecting a resource, available time slots are displayed in calendar style. Booked slots are marked "Your Booking".
Enter booking topic, description, and choose whether to create a discussion channel.
View all booking records with filtering and sorting support.
Full booking information with cancel, re-book, and discussion channel access.
Portal home page shows "My Bookings" and "Book Resources" entry cards.
Administrators view all bookings in month calendar view, color-coded by resource.
Weekly calendar view showing daily slot distribution with resource filter sidebar.
List view for managing all reservations showing name, resource, time, duration, booker, and status.
Reservation form with resource info, time, personnel (organizer/booker/attendees), discussion channel, description, and reminders.
Resource management list showing name, location, capacity, slot duration, access type, and booking count.
Resource form with basic info, booking settings, description, availability schedule, access control, and advanced settings tabs.
Set daily available hours by day of week, e.g., Monday to Friday 09:00-18:00.
Configure resource access type: "All Portal Users" or "Specific Contacts".
- Odoo 18.0 (Community or Enterprise)
- PostgreSQL 13+
- Python 3.10+
- Dependencies:
mail,calendar,portal,cs_portal_discuss
# 1. Clone the module into your Odoo addons path
cd /path/to/odoo/addons/
git clone https://github.com/WOOWTECH/Woow_odoo_internal_booking.git odoo_booking_reservation
# 2. Update module list and install
odoo -u odoo_booking_reservation -d your_database- Go to Apps menu
- Click Update Apps List
- Search for "Resource Booking"
- Click Install
Navigate to Calendar > Configuration > Resource Categories
Create categories (e.g., Meeting Rooms, Equipment, Venues) for organization and filtering.
Navigate to Calendar > Configuration > Booking Resources
| Field | Description |
|---|---|
| Name | Resource name (e.g., Conference Room A) |
| Category | Assigned category |
| Location | Physical location |
| Capacity | Maximum occupancy |
| Slot Duration | Length of each booking slot (hours) |
| Slot Interval | Gap between slots (minimum 0.25 hours) |
| Advance Days | How many days ahead users can book |
On the resource form's "Availability" tab, configure daily available hours by day of week.
On the resource form's "Access Control" tab:
- All Portal Users — Any portal user can book
- Specific Contacts — Only designated contacts can book
The module includes two email templates:
- Booking Confirmed — Sent automatically when a booking is confirmed
- Booking Cancelled — Sent automatically when a booking is cancelled
| Feature | Implementation |
|---|---|
| XSS Protection | html_sanitize() on user input, t-out replaces t-raw |
| Race Condition Prevention | SQL FOR UPDATE row-level locking |
| IDOR Protection | Discussion channel access validation with booking ownership check |
| RPC Bypass Prevention | @api.constrains model-level validation (past slots, overlap, duration) |
| Portal Record Rules | 3 ir.rule records restricting Portal access scope |
| Exception Leak Prevention | Controller catches exceptions, returns generic error codes |
| Deletion Protection | ondelete='restrict' prevents deleting associated bookers |
| Input Validation | Date format validation, range clamping, capacity/interval minimums |
<!-- Portal users can only access active, authorized resources -->
<record id="booking_resource_type_portal_rule" model="ir.rule">
<field name="domain_force">[
('active', '=', True),
'|',
('share_type', '=', 'all'),
('allowed_partner_ids', 'in', [user.partner_id.id]),
]</field>
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
</record>| Model | Description | Key Fields |
|---|---|---|
booking.reservation |
Booking records | resource_type_id, start/end_datetime, partner_id, state, channel_id |
booking.resource.type |
Bookable resources | name, category_id, capacity, slot_duration, slot_interval, share_type |
booking.resource.category |
Resource categories | name, description |
booking.resource.availability |
Availability slots | resource_type_id, dayofweek, hour_from, hour_to |
| Constraint | Description |
|---|---|
_check_no_overlap |
SQL FOR UPDATE prevents double-booking |
_check_duration_matches_slot |
Validates booking duration matches resource slot length |
_check_not_in_past |
Blocks booking past time slots |
_check_capacity |
Resource capacity must be >= 1 |
_check_slot_settings |
Slot interval minimum 0.25 hours |
_check_availability_overlap |
Prevents overlapping availability windows |
_read_groupaggregation — Computed counts use_read_groupinstead oflen(filtered())pattern- Native SQL queries — Overlap checking uses raw SQL +
FOR UPDATEto avoid ORM overhead
All routes require authenticated portal user (auth='user').
| Endpoint | Method | Description |
|---|---|---|
/my/booking/resources |
GET | Browse all available resources |
/my/booking/resources/<id> |
GET | Resource detail with available time slots |
/my/booking/resources/<id>/slots |
JSON | Get available slots (params: date_from, date_to) |
/my/bookings/new |
GET | New booking form |
/my/bookings/confirm |
GET | Booking confirmation page |
/my/bookings/create |
POST | Create a new booking |
/my/bookings |
GET | List user's bookings (params: page, sortby, filterby) |
/my/bookings/<id> |
GET | Booking detail page |
/my/bookings/<id>/cancel |
POST | Cancel a confirmed booking |
/my/bookings/<id>/discuss |
GET | Redirect to booking's discussion channel |
/my/discussions |
GET | Portal discussions list (IDOR-protected) |
# booking.reservation
reservation.action_cancel() # Cancel a confirmed booking
reservation.action_confirm() # Re-confirm a cancelled booking
reservation.action_open_discuss_channel() # Open discussion channel in Discuss
# booking.resource.type
resource._check_partner_access(partner) # Check if partner can book
resource._generate_slots(date_from, date_to) # Generate available time slots
resource.action_view_reservations() # Open reservations calendar view| Template ID | Trigger | Description |
|---|---|---|
mail_template_booking_confirmed |
create() |
Booking confirmation email with resource details, time, and action buttons |
mail_template_booking_cancelled |
action_cancel() |
Cancellation notification with re-booking link |
The module has been through comprehensive testing across multiple phases:
| Phase | Test Items | Pass | Fail | Rate |
|---|---|---|---|---|
| Portal End-to-End | 66 | 66 | 0 | 100% |
| Backend CRUD & Calendar | 48 | 48 | 0 | 100% |
| Security & Edge Cases | 48 | 48 | 0 | 100% |
| Grand Total | 162 | 162 | 0 | 100% |
23-point security and stability audit covering:
| Category | Items | Status |
|---|---|---|
| XSS Protection | Template sanitization, t-out enforcement |
Fixed |
| Race Conditions | SQL FOR UPDATE locking |
Fixed |
| IDOR Validation | Discussion channel access checks | Fixed |
| RPC Bypass Prevention | @api.constrains model-level guards |
Fixed |
| Portal Record Rules | 3 ir.rule records for resource/booking access |
Fixed |
| Input Validation | Past slot blocking, overlap detection, capacity checks | Fixed |
| Deletion Protection | ondelete='restrict' on partner references |
Fixed |
| Performance | _read_group aggregation, SQL optimization |
Fixed |
All 23 findings identified and resolved before production release.
- Security: Pre-production 23-point security audit — XSS, race conditions, IDOR, RPC bypass, record rules all fixed
- Enhancement: Past time slot validation —
@api.constrainsblocks booking past slots - Enhancement: Availability overlap detection — prevents conflicting availability windows on same resource
- Enhancement: Performance optimization —
_read_groupaggregation replaceslen(filtered())pattern - Enhancement: Deletion protection —
ondelete='restrict'onpartner_idprevents orphaned records - Localization: Complete Traditional Chinese interface — all views, templates, controllers, error messages, field labels
- Fix: Discussion channel dialog — pure DOM approach ensures reliable close button behavior
- Fix: Timezone handling — slot generation correctly converts between user timezone and UTC
- Fix: Portal home page card icons and layout alignment
- Feature: Calendar-style booking form with topic, organizer, attendees, and Discussion channel integration
- Feature: Portal brand redesign — Woowtech brand colors and typography applied
- Feature: Discussion channel auto-creation per booking with attendee membership
- Feature: Email notification templates — booking confirmation and cancellation
- Testing: 162/162 comprehensive tests passed (100%)
- Initial Release: Complete resource booking module for Odoo 18
- Feature: Portal self-service resource browsing, slot selection, booking confirmation
- Feature: Backend calendar view with day/week/month/year modes
- Feature: Resource management with categories, capacity, availability schedules, access control
- Feature: Pagination, sorting, filtering on booking lists
This project is licensed under LGPL-3.
- Company: WOOWTECH
- Email: gt.apps.odoo@gmail.com
- Issues: GitHub Issues
Built with care by WOOWTECH • Powered by Odoo 18













