When creating an event through the quickcreate, the user creating the
event was not set as attendee.
closesodoo/odoo#58631
Taskid: 2334943
X-original-commit: 07d799a5f676ed68fd2ffd9cd9bac3269f947ad1
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
Signed-off-by: Kevin Baptiste <kba@odoo.com>
When more than one parameter is present in a message, it helps the
translation to use named placeholder. This way, the order can be
changed. It also helps the comprehension of the message.
Using a few regex like
\((_\(.*%s.*)(\) % )([\w\[\]][\w .\[\]\(\)'"]*)\)
($1, $3))
Old syntax is still compatible but starts the migration to the new
syntax that catches error.
Historically, it was possible to import addons via a naked import. It is
no more possible since 9e1f13bac, since that commit, the only possible
way to import odoo addons is via the `import odoo.addons' prefix.
closesodoo/odoo#46995
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Create an event with at least one attendee.
Synchronize the event between Odoo and Google.
Add/Remove an attendee in Google.
Observed behavior
-----------------
After synchronisation, the partner is not added/removed in Odoo
Expected behavior
-----------------
The partner should be added/removed
Task 2241572
This commit refactors calendar synchronization between Odoo and Google after the
main calendar application refactoring.
This refactoring takes advantage of two new features from the Google API:
- New way of synchronizing resources efficiently[1]
Incremental sync is performed repeatedly and updates Odoo with all the changes that
happened ever since the previous sync. Each time, Odoo provides the previous sync
token it obtained from Google and stores the new sync token from the response.
- Event metadata[2]
Ability to set hidden key-value pairs with an event, called extended properties.
These extended properties are used to store the related odoo event id and the Odoo
owner id (see known limitations)
Known limitations
=================
- Let A and B be two new users (no tokens available). A creates an event in Odoo and
invites B. A is the owner of the event (user_id). Now B authenticates to his Google Calendar
account and synchronizes his calendar. We cannot send the event to A's calendar since we
don't have any access to his Google Calendar. Hence the event his sent to B's calendar.
This leads to data de-synchronisation: The owner is A in Odoo but B in Google.
The "real" owner (user A) is stored in the Google event's metadata to be able to
reconcile the owner for following synchronizations.
- Let A and B be two users of Odoo and Google Calendar. And let the Google Calendar of B
be private (e.g. if A creates an event in Google Calendar and invites B, B won't see the
event in his calendar). If A creates an event in Odoo and invites B. The event is synced
to Google Calendar of A. Now B can see the event in Odoo but he can't see it in his
Google Calendar.
Task 2126717
PR #42031
PR Enterprise odoo/enterprise#8006
[1] https://developers.google.com/calendar/v3/sync
[2] https://developers.google.com/calendar/extended-properties
The fields `start_datetime` and `stop_datetime` are the exact miror
of fields `start` and `stop` respectively.
The field `display_start` is never used.
Hence those fields are removed.
Task 2126717
PR #42031
PR Enterprise odoo/enterprise#8006
TL;DR A bit of magic and ... Pouf ... all virtual events are now real records.
Purpose
=======
The current implementation of recurring events uses "virtual events" to represents all
events in the recurrence. Only one event is stored in the database. All other events are
dynamically built and sent to the web client which sees them as real records.
This implementation is old, difficult to read (6 years of changes and bug fixes) and
has become more and more difficult to maintain.
A fresh start would be welcome.
Specification
=============
When creating a recurring event, a `calendar.recurrence.rule` record should be created.
This model holds the rrule configuration and is responsible to manage events that result
from the rrule.
When a new recurrence is created, all resulting events are also created (stored in the
database). No more virtual events.
To avoid an explosion of events, a maximum of 720 events is created. With 720 events,
a daily recurrence lasts for 2 years and a weekly recurrence lasts for 15 years.
This strategy is used by Google Calendar and seems acceptable in most cases.
A cron job could eventually be introduced to generated more events as the end comes.
This allows to introduce an new rrule end type: 'Forever'. This is actually a shortcut
to create a recurrence running for 720 events.
Inspired by Google Calendar, new possibilities are introduced when modifying a recurring
event (e.g. change the name, add an attendee):
- Modify only this particular event (the event is still part of the recurrence)
- Modify this and following events (events are still in the same recurrence)
- Modify all events
In a similar way, when updating the rrule of an event (e.g. from every Monday to every
Tuesday), the user can choose to:
- Modify this and following events: the recurrence is split. The first part remains
unchanged but now ends when the second recurrence begins. The second parts is the
updated rrule.
- Modify only this particular event.
- Modify all events: Forbidden (same as Google Calendar)
Note: when events are "moved" because the rrule changed, the events are not actually
moved. They are unlinked and new events are created (See "Some design choices explained"
section).
Some design choices explained
=============================
Where to store the rrule?
-------------------------
Two options were considered.
1) Store the rrule on an event, each event of the recurrence having a Many2one
to the parent_id, aka the Master Event of the recurrence.
2) Store the rrule on another model: `calendar.recurrence.rule`. Each event in the
recurrence having a Many2one to the recurrence record.
Both options have pros & cons. But there is no clear winner.
However the actual business logic of handling the recurrence creation/update
would be the same.
Where the rrule configuration is stored is the only main difference between both options.
And this is probably the easiest part of implementing recurring events.
With that in mind, option 2) is chosen. It allows to clearly separate recurrence
logic from the events themselves. It is also the "correct" way of modeling data to avoid
many empty columns for most records.
Reusing events on rrule update
------------------------------
When an rrule is modified, events should also be updated.
In most cases, current events are unlinked and new events are created from scratch.
Only events exactly at the same time before and after the rrule update are kept.
Trying to reuse other events would require an obscure and arbitrary heuristic.
(Imagine an rrule every Monday that is changed to every Tuesday and every Friday.
What would you do?).
This implies that any change to a specific event (name change, attendee added, chatter
messages) is lost. This tradeoff seems acceptable as updating an rrule should not be
that frequent. Moreover, Google Calendar also works that way so why not Odoo?
Reusing events on events shifts
-------------------------------
On the calendar view, drag and drop an event to shift the entire recurrence.
One way to handle the recurrence shift is to apply the same timedelta to all events.
Now events are correctly positioned... except for events that were specifically
moved. Those outliers needs special handling.
This also introduces some behavior inconsistencies:
when an rrule is directly modified, events are not reused, but when the rrule is
modified by drag & dropping an event, events are reused. This option needs more code to
handle the shift and the behaviors are not consistent.
The chosen option is to find the rrule configuration from the dragged event (this is
easy) and update the recurrence with those new rrule values. This brings us back to
an rrule update (see above): code reusability yeah; one behavior to rule them all yeah.
One downside is that outliers are lost (but Google Calendar also works that way).
Task 2126717
PR #42031
PR Enterprise odoo/enterprise#8006
In a database with many users / events to synchronize, the cron
`ir_cron_sync_all_cals` may time out. Consequently, even if a `commit`
is performed for each user, some users are never synchronized.
In this commit, we first sort the users by last synchronization date,
meaning that all users will ultimately be synchronized, even if the cron
times out. On top of that, we introduce the context key
`last_sync_hours` to prevent the synchronization in case the cron is
restarted after timeout.
opw-2158372
closesodoo/odoo#45032
X-original-commit: 2f21def63c61324e2286dbee6abead091171a041
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Co-authored-by: Nicolas Martinelli <nim@odoo.com>
Activate Google Synchronization, create on OE a recurrent event (no allday)
synchronize the calendar, then delete an event of the recursion on OE,
sync again on OE.
An error will popup in the console. There is a typo in the variable
sent to the google API.
https://developers.google.com/calendar/v3/reference/eventsclosesodoo/odoo#40625
X-original-commit: 299bb8a995fb8058bbc0b9e4d71b67d3e765c6af
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Activate Google Synchronization, create on OE a recurrent event,
synchronize the calendar, then delete an event of the recursion on GC,
sync again on OE.
The event will be deleted from GC but not from OE after sync.
This appens because of this "rewrite" rule
https://github.com/odoo/odoo/blob/12.0/addons/calendar/models/calendar.py#L918
that occur on event creation from OE, altering the event parameters when
is marked "allday".
When an "allday" event is deleted from GC the unlink is triggered in OE with the
default time "00:00:00". During the creation of the exclusion '
_inverse_dates' will be called altering start and stop datetime but not
recurrent_id_date, so the new record will not match the event generating
the recursion and the exclusion will not occur. The problem require
particular carefulness because when a recurrent event is fetched from
google the '_inverse_dates' is not called, so in that case the default
time is fine.
opw-2060526
closesodoo/odoo#39662
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Activate Google Synchronization, create on GC a recurrent event,
synchronize OE, then delete an event of the recursion on GC, sync again
on OE.
The event will be deleted from GC but not from OE after sync.
The exclusion on OE is not correctly working in that particular case,
fixing require also to "suppress" the attendee to avoid that just
created exclusions would be detected as changes to send in a following
synchronization.
closesodoo/odoo#37884closesodoo/odoo#39510
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Create a lot of event (i.e. 300 via recursive events) with attedees. Sync.
Cancel all the events. Sync again. This and all subsequent
synchronization will take a lot of time to complete. The first time is
normal because odoo will cross-check every deleted event for the "syncing" user
with google to ensure that there is match between OE and GC.
This matching will sistematically fail because the json module cannot
serialize a datetime object, so it will be retriggered again and again
stalling the synchronization for minutes. Formatting the datetime before calling the
dump fixes. Moreover the api usage was wrong as 'originalStartTime' is
not a date but a complex object holding the date.
Note: this could have been avoided via logging but error detection was
suppressed.
opw-2052450
closesodoo/odoo#37335
X-original-commit: 951808b2434717d38ab9d562404eb74d8bd40634
Signed-off-by: agr-odoo <agr-odoo@users.noreply.github.com>
During a Google Calendar sync,
exclusive instance of a recurrent event to which you are not the owner and
without an update datetime shouldn't be considered.
See developers.google.com/calendar/v3/reference/events/update
where cancelled status event might have empty fields.
> A cancelled status represents two different states
> depending on the event type:
> Cancelled exceptions of an uncancelled recurring event indicate
> that this instance should no longer be presented to the user.
> Clients should store these events for the lifetime of the parent recurring event.
> Cancelled exceptions are only guaranteed to have values for the id,
> recurringEventId and originalStartTime fields populated. The other fields might be empty.
As you are not the owner, the event shouldn't be deleted from Odoo
as the actual event owner might still attend the meeting.
It should just remove the user who is syncing his calendar from the attendees,
but as the sync currently doesn't support syncing event without an update datetime
from Google, we just choose to ignore the sync of this event.
The attendee will be removed/marked as not attending when the owner of the event
will sync his calendar.
opw-1966309
closesodoo/odoo#34075
Signed-off-by: Denis Ledoux <beledouxdenis@users.noreply.github.com>
Purpose
=======
Fields `customer` and `supplier` on `res.partner`
are mostly used in domains of many2x fields.
Those domains can confuse end users because they don't
see the partner they are looking for; and it's not obvious why.
Some identified problems:
1. It can lead to duplicated partners: the user does not find
the partner, so he creates a new one.
2. The user imports supplier contacts in the Contacts app, so they
don't get the `supplier` flag. Then the user wants to make a purchase order,
and cannot find the new suppliers in the list
3. A user removes the customer flag on a prospect, because they don't think
it's a customer yet - except now they can't make a quote for that customer...
Specification
=============
Remove the two mentioned fields.
Since fields `customer` and `supplier` have been removed, all partners
are now shown in many2one dropdowns.
But in some cases, not all partners are relevant or some are more likely
to be relevant than others. e.g. when creating a PO, top suppliers have a
higher priority than other partners.
So, adapt the places where those fields were used with the new mechanism to
display the searched the partners, according to the number purchase/sales
orders they made.
TaskID: 2031147
Co-authored-by: Yannick Tivisse <yti@odoo.com>
Multi is the default api for methods, it is not necessary to explicitly
decorate methods with it, adds clutter and most people use it because
they see that the rest of the code uses it.
Done with `find . -type f -name '*.py' | xargs sed -i '/@api.multi/d'`
In Odoo, create a user John@example.com (the cap is on purpose)
In Google Calendar, create an event and invite john@example.com
Sync your Google calendar.
Before this revision,
the event created in Odoo did not add John@example.com,
but created a new attendee, john@example.com, because
of the sensitive casing.
Besides, give the priority to partners having
users, so if there are two partners with the same email,
one of them having a user,
e.g. John@example.com (with user) & john@example.com (without user),
set the partner having the user as attendee,
as its the one with the user who use the Odoo calendar,
and potentially the Google sync as well.
opw-1925592
closesodoo/odoo#31111
Purpose of this commit is to rename type column to something matching the
the real business use of the field. That way it is easier to find and grep
in the code. It also lessens potential conflicts with type build-in python
function. It also lessens conflicts when using the field in JS as type
is a build-in attribute.
Renaming type column is a long-living issue. We choose to do it at the
beginning of the v13 development to catch errors as soon as possible.
This commit is linked to task ID 1896245. It is also a subpart of community
PR #27599.
Purpose of this commit is to give description more "business oriented"
because those descriptions appears in Odoo Studio which is supposed to be used by end users, not only by developers.
Related Task ID : 37311
From this commit onwards, Date fields will return datetime.date objects and Datetime fields will return datetime.datetime objects, this implies a number of things that are clearly explained both in the ORM API for master.
This commit also introduces a number of helper functions for dates and datetimes that are exposed in tools.date_utils and fields.Date[time], explained in the documentation as well.
Task-ID: 47189
When an error happen (which may have been intended as such and ignored
down the error pipeline) in google_account/google_calendar there was
some typos that tracebacked.
opw-783271
closes#21263