Skip to content

[ADD] service_event_base: for managing service events and bookings#5

Draft
shsa-odoo wants to merge 9 commits into
mainfrom
master-odoo-fs-app-shsa
Draft

[ADD] service_event_base: for managing service events and bookings#5
shsa-odoo wants to merge 9 commits into
mainfrom
master-odoo-fs-app-shsa

Conversation

@shsa-odoo
Copy link
Copy Markdown
Collaborator

Description in progress.

 Commit 1: Module Foundation + Hooks
- Module structure (`__manifest__.py`, `__init__.py`)
- Pre-init hook (table preparation, SQL cleanup)
- Post-init hook (default data, categories)
- Init function (indexes, SQL views)

Module Structure:

service_event_base/
├── __init__.py              # Module entry point
├── __manifest__.py          # Module metadata and dependencies
├── hooks.py                 # Lifecycle hooks (pre-init, post-init)
├── models/                  # Business models
│   ├── __init__.py
│   ├── service_event_category.py
│   ├── service_event_tag.py
│   ├── service_event.py
│   └── service_booking.py
├── security/                # Access control
│   ├── security.xml
│   └── ir.model.access.csv
├── data/                    # Default data
│   ├── sequences.xml
│   └── categories.xml
├── views/                   # User interface
│   ├── service_event_views.xml
│   ├── service_booking_views.xml
│   └── menus.xml
└── demo/                    # Demo data (optional)
    └── demo_data.xml
Core ORM implementation with relationships, computed fields,
workflow states, constraints, views, and security
Implement service.event and service.booking models with full ORM features:
- service.event: name, description, price, category, tags, bookings
- service.booking: auto-generated numbers, workflow states, validations
- Relationships: Many2one, Many2many, One2many
- Computed fields: booking_count, amount, display_name
- Constraints: SQL (positive prices) and Python (date validation)
- Views: Odoo 18 compatible list/form views with state buttons
- Security: Full CRUD access rights for both models
- Menus: Navigation structure for events and bookings
What We Accomplished:
Service Event Model:

✅ Capacity management (capacity field)
✅ Advanced computed fields:
booking_count_confirmed (stored) - count of confirmed bookings only
total_revenue (stored) - sum of confirmed booking amounts
available_seats (non-stored) - real-time availability calculation
✅ Event scheduling:
start_datetime, end_datetime, duration
Inverse function on end_datetime (bidirectional computation)
✅ Complex Python constraints:
Capacity validation (prevent overbooking)
Datetime range validation
Price consistency checks
✅ SQL constraints (positive capacity, positive duration)
Service Booking Model:

✅ Onchange methods:
_onchange_event_id() - Auto-fill amount, warn about low availability
_onchange_partner_id() - Customer-specific logic placeholder
_onchange_booking_date() - Weekend booking warnings
✅ Default value functions demonstrated
Views:

✅ Event list view: capacity, booking stats, available seats, revenue
✅ Event form view: Capacity & Availability group, Schedule group
Service Event Model Enhancements:
- ✅ Pricing logic
  - Early bird pricing (early_bird_price, early_bird_deadline)
  - Discount percentage (discount_percentage)
  - Final price computation (final_price)
  - Price calculation method (get_applicable_price)
- ✅ Event lifecycle management
  - State workflow (draft → published → registration_closed → completed/cancelled)
  - Lifecycle action methods (publish, close_registration, mark_completed, cancel, reset_to_draft)
  - Registration status (registration_open computed field)
- ✅ Business metrics
  - Fill rate (% of capacity filled)
  - Revenue per seat
  - Cancellation rate
- ✅ Business validation
  - Early bird price must be < regular price
  - Early bird deadline must be before event start
  - Prevent publishing without price/category
  - Check booking allowed method

Service Booking Model Enhancements:
- ✅ Waitlist management
  - Waitlisted state added to workflow
  - Auto-waitlist when event full
  - Waitlist position tracking
  - Auto-promotion when spots open
  - Manual promotion method
- ✅ Enhanced booking validation
  - Check event is published and registration open
  - Prevent duplicate bookings (same customer + event)
  - Auto-populate amount from event price
  - Validate event hasn't started
- ✅ Business logic
  - Cascade cancellation (event cancelled → bookings cancelled)
  - Auto-promotion from waitlist on cancellation

Views Updated:
- ✅ Event list: state badges, pricing fields, business metrics
- ✅ Event form: lifecycle status bar with action buttons, pricing section, metrics dashboard
- ✅ Booking list: waitlist state and position
- ✅ Booking form: waitlist alert, promote button
Security architecture (Odoo 19 privilege-based approach)
2 security groups with permission comparison table
3-layer security implementation (model → record → field)
All 8 record rules documented
Files modified with line counts
Code examples for privilege, record rules, and field security
…, Graph, Pivot)

- Add Kanban views with QWeb templates for events and bookings
- Add Calendar views for event scheduling (month/week/day modes)
- Add Graph (bar charts) and Pivot views for analytics
- Enhance Search views with filters, grouping, and search panels
- Add color field to service.event model for visual categorization
- Update actions to support multiple view modes
Comment thread .gitignore
/src/

# markdown documentation files
*.md No newline at end of file
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add new line after it.

- Created service_event_website module (separate from base)
- Added /events listing page (GET, auth=public)
- Added /events/<id> detail page (model converter)
- Added /events/book submission (POST, CSRF protected)
- Added booking confirmation page
- Implemented sitemap integration for SEO
- Created QWeb templates (listing, detail, confirmation, error)
- Demonstrated: GET/POST methods, auth types, model converters, CSRF protection
Implement 3 JSON-RPC endpoints for dynamic event data retrieval:
- /api/event/price: Get pricing with quantity calculation
- /api/event/availability: Check real-time seat availability
- /api/event/validate: Validate booking data before submission

Features:
- JSON-RPC 2.0 protocol
- CORS support for cross-origin requests
- Standardized response format (success/error structure)
- Public authentication for frontend access
- Comprehensive error handling and validation
Add self-service portal for customers to manage bookings:
- /my/bookings listing with pagination (10 per page)
- /my/booking/<id> detail view with full information
- Sorting: date, name, status
- Filtering: all, draft, confirmed, attended, cancelled
- Security: record rules restrict to own bookings only
- Portal menu integration with booking counter
- Responsive Bootstrap 5 templates

Portal users can:
- View all their bookings
- See booking details and event information
- Access published events only
- Cannot modify or delete bookings through portal

Security features:
- Portal record rules (partner_id matching)
- Access token support for sharing
- Published events only for portal/public
- Read-only access to bookings

execute_safe_sql(
"""
CREATE EXTENSION IF NOT EXISTS pg_trgm;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pg_trgm module provides functions and operators for determining the similarity of alphanumeric text based on trigram matching.
A trigram is a group of three consecutive characters taken from a string.

For example, the set of trigrams in the string “cat” is “ c”, “ ca”, “cat”, and “at ”. The set of trigrams in the string “foo|bar” is “ f”, “ fo”, “foo”, “oo ”, “ b”, “ ba”, “bar”, and “ar ”.

For more refer : https://www.postgresql.org/docs/current/pgtrgm.html

Comment on lines +401 to +407
currency_id = fields.Many2one(
'res.currency',
string='Currency',
related='event_id.currency_id',
store=True,
help='Currency from the event',
)
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

related field is Odoo saying:
“Don’t store your own value. Borrow it from another field.
If the source changes, you change.”
It’s like a mirror. Not a twin. Not a copy. A mirror.
In your case:
Your model does NOT own currency_id
It looks at event_id.currency_id
Whatever currency the event has → this record shows the same one

# ========================================================================

parent_id = fields.Many2one(
comodel_name='service.event.category',
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both are same : )

parent_id = fields.Many2one(
'service.event.category',
string='Parent Category',
)

Comment on lines +126 to +131
child_ids = fields.One2many(
comodel_name='service.event.category',
inverse_name='parent_id',
string='Sub-categories',
help='Child categories under this category',
)
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inverse_name vs inverse function

inverse_name
• Used with One2many fields
• Defines the database relationship
• Points to the Many2one field (foreign key) on the other model
• Is a string (field name)
• Mandatory for One2many
• No Python logic involved
• Works at ORM / SQL relationship level

inverse function
• Used with computed fields
• Handles write-back logic when a computed field is edited
• Is a Python method
• Optional
• Contains business logic
• Does not define any database relationship


<!-- Placeholder: Security groups will be defined in Commit 5 -->

</data>
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate file

<!-- Rule: Service Users - See Only Published Events -->
<record id="service_event_user_rule" model="ir.rule">
<field name="name">Service Event: User - Published Only</field>
<field name="model_id" ref="model_service_event"/>
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check this !

Comment on lines +287 to +296
<record id="service_event_category_manager_rule" model="ir.rule">
<field name="name">Service Event Category: Manager - Full Access</field>
<field name="model_id" ref="model_service_event_category"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[(4, ref('group_service_event_manager'))]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
</record>
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this already done .csv? Then why this?

Ans:
CSV = whether you can touch the model
Rules = which records your fingers are allowed to touch

<record id="service_event_manager_rule" model="ir.rule">
<field name="name">Service Event: Manager - All Events</field>
<field name="model_id" ref="model_service_event"/>
<field name="domain_force">[(1, '=', 1)]</field>
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

domain
• Adds a filter condition
• Is combined (ANDed) with other record rules
• Cannot override other rules
• Respects existing restrictions
• Used for normal / restrictive access
• Safer, additive behavior
Example meaning:
“User can access records that match this condition, along with all other rules.”

Vs

domain_force
• Overrides all other record rule domains
• Replaces the final domain instead of adding to it
• Ignores other restrictive rules
• Used for full access or hard overrides
• Dangerous if misused
Example meaning:
“Forget all other rules — use only this domain.”

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant