[v2 review] [19.0][MIG] resource_booking: full commit history rebuild#6
Closed
dnplkndll wants to merge 133 commits into
Closed
[v2 review] [19.0][MIG] resource_booking: full commit history rebuild#6dnplkndll wants to merge 133 commits into
dnplkndll wants to merge 133 commits into
Conversation
This module adds a new app to allow you to book resource combinations in given schedules. Example use cases: * Management of consultations in a clinic. * Salesman appointments. * Classroom and projector reservations. * Hotel room booking. Among the things you can do: * Specify the type of booking, which includes a calendar of availability. * Specify which resources can be booked together. All of them must be free to be booked. * Place pending bookings, effectively giving permissions to someone to see the availability calendar and choose one slot. * Partners can do that from their portals. * If a partner has no user, he can still do the same via a tokenized URL. * Backend users can also do that from the backend. * Booking lifecycle with computed states. * Automatic meeting creation and deletion. * Automatic conflict detection. * Deadline to block modifications. @Tecnativa TT28201
Currently translated at 100.0% (190 of 190 strings) Translation: calendar-12.0/calendar-12.0-resource_booking Translate-URL: https://translation.odoo-community.org/projects/calendar-12-0/calendar-12-0-resource_booking/es/
…ating calendars Without this patch, users couldn't change a calendar schedule if there were past or unconfirmed bookings that wouldn't fit in it. Excluding those bookings from the check fixes the situation. We also check that, to confirm a booking, it must fit in the calendar (because now it can happen that, in the time that has passed since the booking was scheduled until it is confirmed, the calendar changes). @Tecnativa TT29509
The notifications emitted to the resource booking requester must always be in the same TZ as the resource booking itself. For example, if you book one hotel room in the other side of the world, a notification in your own TZ is confusing. Besides, res.partner created from website_sale are created with `tz=False`, making it even more confusing. @Tecnativa TT30331
The constraint that checks the schedule of a resource booking is currently being applied to all the bookings, including past ones. As the resource combination or associated calendars might change regularly and trigger a recomputation of this, such change might take a very long time. Plus, the calendar restrictions might change, trigger a recompute of the constraint and detect bookings that can't be assigned, which makes no sense when they already happened. This applies it only to future bookings, ignoring past ones. TT30478
It's very unlikely that you need to book resources in a seconds-based precision. This simplifies portal UI. Still, declared as a variable in case you need some customizations downstream. @Tecnativa TT31063
- Standard v13 changes. - Some onchanges removed in favor of computes. @Tecnativa TT30987
From now on, `resource.booking.type` duration represents the default duration that will be applied to new `resource.booking` of that type, instead of the hardcoded duration for every new booking. This means that you can create a new booking in pending state and define a custom duration before sending the portal link to customer. Thus, the available schedule slots in portal will be based on the type duration, whereas only those that have enough time left to complete the booking duration will be displayed. @Tecnativa TT30987
…cation Thanks to this patch, you will be able to more predictably block the chosen resource combination, with the added checkbox. Also, the location field is propagated to `resource.booking` records, and synced from there to `calendar.event` if needed. This way, you can alter the location before sending the portal invitation. @Tecnativa TT30987
The filter wasn't working fine due to the `auto_join=True` set in `meeting_id`. It was never displaying pending bookings. Besides, it wasn't necessary to keep it as a field because it was displayed nowhere and the search could be done directly in the view. This way, there's less python code to maintain and we disable the possibility of having a negative domain, which enters doomed scenarios when x2many fields are involved (see odoo/odoo#43957). @Tecnativa TT30987
Adding `.with_context(exclude_public_holidays=True)` in needed places to let `hr_holidays_public` do its magic and never allow allocating a booking during a public holidays when that module is properly installed and configured. @Tecnativa TT30987
- Allow users to optionally define a name for the resource booking. - Display that name in portal if set. - Sync it with meeting name when creating it. @Tecnativa TT30987
Without this patch, when entering the Resource Bookings menu, if the current user attended any recurrent meeting, it failed with this error:
```
Server application error
Error code: 200
Error message: Odoo Server Error
Error data message:
invalid input syntax for integer: "82-20210726143000"
LINE 1: ... AND ("resource_booking"."meeting_id" in (3,5,81,'82-202107...
^
Error data debug:
Traceback (most recent call last):
File "/opt/odoo/custom/src/odoo/odoo/http.py", line 624, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/opt/odoo/custom/src/odoo/odoo/http.py", line 310, in _handle_exception
raise pycompat.reraise(type(exception), exception, sys.exc_info()[2])
File "/opt/odoo/custom/src/odoo/odoo/tools/pycompat.py", line 14, in reraise
raise value
File "/opt/odoo/custom/src/odoo/odoo/http.py", line 669, in dispatch
result = self._call_function(**self.params)
File "/opt/odoo/custom/src/odoo/odoo/http.py", line 350, in _call_function
return checked_call(self.db, *args, **kwargs)
File "/opt/odoo/custom/src/odoo/odoo/service/model.py", line 94, in wrapper
return f(dbname, *args, **kwargs)
File "/opt/odoo/custom/src/odoo/odoo/http.py", line 339, in checked_call
result = self.endpoint(*a, **kw)
File "/opt/odoo/custom/src/odoo/odoo/http.py", line 915, in __call__
return self.method(*args, **kw)
File "/opt/odoo/custom/src/odoo/odoo/http.py", line 515, in response_wrap
response = f(*args, **kw)
File "/opt/odoo/auto/addons/web/controllers/main.py", line 1339, in call_kw
return self._call_kw(model, method, args, kwargs)
File "/opt/odoo/auto/addons/web/controllers/main.py", line 1331, in _call_kw
return call_kw(request.env[model], method, args, kwargs)
File "/opt/odoo/custom/src/odoo/odoo/api.py", line 383, in call_kw
result = _call_kw_model(method, model, args, kwargs)
File "/opt/odoo/custom/src/odoo/odoo/api.py", line 356, in _call_kw_model
result = method(recs, *args, **kwargs)
File "/opt/odoo/custom/src/odoo/odoo/models.py", line 4936, in search_read
records = self.search(domain or [], offset=offset, limit=limit, order=order)
File "/opt/odoo/custom/src/odoo/odoo/models.py", line 1648, in search
res = self._search(args, offset=offset, limit=limit, order=order, count=count)
File "/opt/odoo/custom/src/odoo/odoo/models.py", line 4499, in _search
self._cr.execute(query_str, where_clause_params)
File "/opt/odoo/custom/src/odoo/odoo/sql_db.py", line 173, in wrapper
return f(self, *args, **kwargs)
File "/opt/odoo/custom/src/odoo/odoo/sql_db.py", line 250, in execute
res = self._obj.execute(query, params)
psycopg2.DataError: invalid input syntax for integer: "82-20210726143000"
LINE 1: ... AND ("resource_booking"."meeting_id" in (3,5,81,'82-202107...
^
```
@Tecnativa TT30987
Upstream ``unlink`` method in calendar.event adds this keyword argument.
When a user had no resource_booking permissions and opened a calendar event linked to a resource booking, he got an unnecessary access error. @Tecnativa TT31238
When `_leave_intervals_batch()` in `resource.calendar` is extended by other modules that add more leaves for any reason, the returned recordset must be of the `resource.calendar.leaves` model. Otherwise, Odoo fails with:
TypeError: '<' not supported between instances of 'resource.resource' and 'resource.calendar.leaves'
The resource didn't have a meaning here, so changing it to avoid bug.
@Tecnativa TT31249
Missing part from OCA#34: - Display booking duration and location on portal, even on pending state. - Improve portal test to contemplate new behaviors. @Tecnativa TT31250
- If RBC (resource.booking.combination) was auto-assigned, attendees generated from RBC human resources are expected to confirm attendance manually. - If RBC was handpicked, those attendees are auto-confirmed. - All those confirmations are done before sending invitations, so invitations contain the correct attendance status. - If requester books from portal view, he's also confirmed before sending invitation, for the same reason. @Tecnativa TT31239
This allows better filtering while in the normal calendar view. By default, the organizer will be whoever created the booking. Calendar invitations will go out in his name. Also, avoid sending calendar event modification notifications if the modification isn't the schedule. @Tecnativa TT31240 resource_booking 13.0.2.3.0
Includes those coming from requester and from resource combination. @Tecnativa TT31901
Currently translated at 97.0% (196 of 202 strings) Translation: calendar-13.0/calendar-13.0-resource_booking Translate-URL: https://translation.odoo-community.org/projects/calendar-13-0/calendar-13-0-resource_booking/fr_FR/
Currently translated at 1.4% (3 of 202 strings) Translation: calendar-13.0/calendar-13.0-resource_booking Translate-URL: https://translation.odoo-community.org/projects/calendar-13-0/calendar-13-0-resource_booking/fr/
When some partner is a resource assigned to a booking, he should get auto-subscribed. Inspired in OCA#42, but I'm changing that behavior. @Tecnativa TT32148
By using the upstream `mail.message_user_assigned` template, we were getting this exception:
```
odoo.addons.base.models.qweb.QWebException: 'resource.booking' object has no attribute 'user_id'
Traceback (most recent call last):
File "/opt/odoo/custom/src/odoo/odoo/addons/base/models/qweb.py", line 348, in _compiled_fn
return compiled(self, append, new, options, log)
File "<template>", line 1, in template_2601_10519
AttributeError: 'resource.booking' object has no attribute 'user_id'
```
So I provide a specific template for this kind of subscription notification, which doesn't use that `user_id` field. Besides, it explains better why you're getting it.
@Tecnativa TT32190
Forward-port of OCA#51. Includes a modification for the migration script of 13.0.1.0.0 (if you migrate from v12, you'll need it; if you migrate from v13, it will be automatic). @Tecnativa TT31901
Without this patch, if you create a resource booking for a type that has categories (tags), it will fail with `CacheMiss` error. @Tecnativa TT32552
If I'm creating bookings for my colleagues, I'll be the owner of all of the meetings. But that doesn't mean I'll be busy. With this patch, only when I'm a booked resource will the event be set as busy. @Tecnativa TT32666
Currently translated at 100.0% (218 of 218 strings) Translation: calendar-18.0/calendar-18.0-resource_booking Translate-URL: https://translation.odoo-community.org/projects/calendar-18-0/calendar-18-0-resource_booking/es/
Currently translated at 6.8% (15 of 218 strings) Translation: calendar-18.0/calendar-18.0-resource_booking Translate-URL: https://translation.odoo-community.org/projects/calendar-18-0/calendar-18-0-resource_booking/ca/
Currently translated at 100.0% (217 of 217 strings) Translation: calendar-18.0/calendar-18.0-resource_booking Translate-URL: https://translation.odoo-community.org/projects/calendar-18-0/calendar-18-0-resource_booking/it/
Odoo added this new key in commit odoo/odoo@c840bde. To prevent the test from failing, we updated the data accordingly.
…ission issues Steps to reproduce: - Install `resource_booking` and `hr` modules. - Create a user with "Employee Officer: Manage all employees" rights (without the "Resource Booking User" role). - Go to Employees and create a record. Since `hr.employee` inherits from `resource.resource`, the constraint `_check_bookings_scheduling` is executed. When the search is performed, an error is raised due to missing permissions. This commit fixes the issue by using `sudo()` for booking searches.
…ctly When using a booking type with a resource calendar that has a different time zone than the resource itself, the slots are returned with mixed time zones. This commit normalizes the behavior and ensures that slots are always returned in the time zone of the booking type. Steps to reproduce: Create a resource with the time zone America/Guayaquil, and a calendar that starts from 06:00 to 15:00. Create a resource booking type with a new calendar that starts from 09:00 to 16:00, and set the time zone to Europe/Madrid. Before this commit, the slot displayed in the portal was 06:00, but it should have been 12:00. After this commit, the slot is displayed in the correct time zone (Madrid) at 12:00. Note: The 06:00 in America/Guayaquil corresponds to 12:00 in Madrid standard time, not during daylight saving time. The tests use a freeze date in February.
The resources parameter must be a recordset, not a list. Before this commit, this was not a problem, but in this commit odoo/odoo@79a559c , Odoo began expecting a recordset to call the function _get_calendar_att. This change was introduced during the migration to V15 in this commit OCA@b7a6f5b , so we updated the parameter to pass it as a record.
following same logic as in 16.0
When a user had no resource_booking permissions and opened a calendar event linked to a resource booking, he got an unnecessary access error.
…he field is set For a curious reason, the test_resource_booking_schedule_unschedule test fails after this PR: odoo/odoo#223875 The requester_advice field is of type Text, but in calendar.event the description field is HTML. I tried changing the field type to HTML, but the error still occurs, so another approach is to only pass the field when it is filled.
…t read access
A user landing on /my that lacks resource.booking read access (e.g. an
internal user not in resource_booking.group_user, an internal account
created by another website-facing module) used to hit a hard AccessError:
- _prepare_home_portal_values called search_count([]) unguarded, breaking
the entire portal home page when "booking_count" was in counters.
- portal_my_bookings called search_count([]) unguarded, breaking the
/my/bookings listing for the same users.
Both paths now check Booking.has_access("read") and degrade gracefully
(zero counter, empty list page) instead of raising. Portal users with
the dedicated ACL row keep the existing behavior unchanged.
Distinct from upstream 1c59c21 ([FIX] resource_booking: access error on
normal calendar) which fixed a different surface: the calendar event
form's resource_booking_ids field now hidden via groups= for users
without booking permissions. The portal AccessError addressed here is
a separate bug.
Co-Authored-By: Brenden Eshbach <brenden@techsystech.com>
…slots All-day calendar events store dates in start_date/stop_date and may have no start/stop datetimes (or values outside the analyzer's UTC window once timezone-shifted). The previous busy-events query filtered solely on start/stop, so a user's all-day event (PTO, off-site, etc.) would not block booking slots on that day. Extend the conflicting-events search with an OR predicate on start_date/stop_date for allday events, and render their busy interval from start_date through stop_date+1 in the analyzer's tz so a single all-day event blocks the full local day across calendar tz boundaries. Co-Authored-By: Brenden Eshbach <brenden@techsystech.com>
…ests Two follow-ups from review of the no-access fix: - portal_my_bookings: unify the no-access branch with the normal path. Previously the no-access branch returned an empty dict for `pager`, which is technically harmless because the current template doesn't read pager, but is fragile against future template inheritance. Now has_access is computed once, search_count is gated, and the rest of the function (real portal.pager(total=0), recordset, session, render) runs through the single existing code path. - Tests: replace fragile "no Traceback in response" assertions with positive DOM markers. Home test now asserts the .o_portal_my_home / .o_portal_wrap wrapper renders; listing test asserts the empty-state alert string from the QWeb template appears. Both confirm the template actually rendered rather than just "did not crash".
Signed-off-by: Don Kendall <dkendall@ledoweb.com>
Signed-off-by: Don Kendall <dkendall@ledoweb.com>
ec4b7f0 to
f8c5ec4
Compare
Author
|
v2 rebuild landed on the original 19.0-mig-resource_booking branch — OCA#217 now reflects the rebuilt history. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Port of
resource_bookingfrom 18.0 to 19.0. Follows the OCA migration guide.Supersedes OCA#187 (open since 2025-10-19, original author unreachable).
Non-mechanical adaptations worth flagging:
Intervalsmoved fromodoo.addons.resource.models.utils→odoo.tools.intervals._sql_constraintslist rewritten asmodels.Constraint(...)declarations (Odoo 19 SQL constraint API).datetime.utcfromtimestamp(deprecated in Python 3.12) fordatetime.fromtimestamp(..., tz=timezone.utc).replace(tzinfo=None).t-field="meeting.display_time"switched tot-outcalling a newbooking._get_portal_display_time()helper — Odoo 19 dropped the computedcalendar.event.display_timefield.resource_booking_tour.esm.jsannotated withexpectUnloadPage: trueper Odoo 19's tour framework's new contract for click-triggers that navigate.