TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/OCA/calendar/llms.txt
Use this file to discover all available pages before exploring further.
calendar_export_ics and calendar_import_ics modules add two transient wizard models for moving calendar data in and out of Odoo using the standard iCalendar (.ics) format. The export wizard (calendar.export.ics) builds a single .ics file containing all future events for a chosen partner, optionally capped by an end date. The import wizard (calendar.import.ics) parses an uploaded .ics file and creates or updates calendar.event records idempotently using each event’s UID property. A lightweight extension to calendar.event adds the event_identifier field that makes idempotent imports possible.
calendar.export.ics
Technical name: calendar.export.icsType:
TransientModelDescription: Calendar Export Ics
Fields
The partner whose calendar is exported. Pre-filled with the current user’s partner by
default_get(). Only events where this partner appears in partner_ids are included.Optional upper bound for event start dates. When set, only events with
start ≤ export_end_date are exported. Combined with a lower bound of today, this produces a date-ranged export.The generated
.ics content, base64-encoded. Populated by button_export() → generate_ics_content(). Empty until the export button is clicked.The suggested filename for the download, formatted as
YYYY-MM-DD_calendar.ics using today’s date.Methods
default_get(fields)
default_get() to pre-fill partner_id with self.env.user.partner_id when the current user has a linked partner record.
button_export()
- Sets
export_ics_filenameto"YYYY-MM-DD_calendar.ics". - Calls
generate_ics_content()and stores the result inexport_ics_file. - Returns an
ir.actions.act_windowaction that re-opens the same wizard record (res_id=self.id,target="new"), allowing the user to download the populated file widget.
generate_ics_content()
- Constructs a search domain:
("start", ">=", date.today())— always excludes past events.("start", "<=", export_end_date)— applied only whenexport_end_dateis set.("partner_ids", "in", [partner_id.id])— scopes to the chosen partner.
- Searches
calendar.eventwith the domain. - Calls the built-in
_get_ics_file()method on the result (returns a dict of{event_id: bytes}). - Parses each individual ICS blob with
vobject.readOne()and merges allVEVENTcomponents into a singlevobject.iCalendar()container. - Serialises the combined calendar to UTF-8 and returns it as a base64-encoded
bytesvalue.
_get_ics_file() is a standard Odoo method on calendar.event. Each call returns one VCALENDAR wrapper per event. generate_ics_content() strips those wrappers and merges all events into one calendar file for a clean single-file download.calendar.import.ics
Technical name: calendar.import.icsType:
TransientModelDescription: Calendar Import Ics
Fields
The
.ics file to upload. The wizard reads this field as a base64-encoded binary and decodes it to a UTF-8 string before parsing.The original filename. Used only to validate that the uploaded file has an
.ics extension; button_import() raises ValidationError if the extension is anything else.Optional filter. When set together with
import_end_date, only events whose DTSTART falls on or after this date and whose DTEND falls on or before import_end_date are imported.Optional filter. See
import_start_date. Both fields must be set for date filtering to apply; if either is absent, all events in the file are processed.Partner to associate with imported events. Falls back to
self.env.user.partner_id inside button_import() if the field is empty and a user session exists.When
True (default), calls _delete_non_imported_events() at the end of the import run to remove previously imported events that did not appear in the current file.Methods
button_import()
- Validates the file extension (must be
.ics). - Falls back to the current user’s partner if
partner_idis empty. - Decodes the binary file to a UTF-8 string and splits it into lines.
- Pre-processes each
DTSTART/DTENDline that contains aTZID=parameter by callingconvert_date_to_z()to normalise them to UTCZ-format. - Iterates line by line, building a
dict(ics_event) perVEVENTblock. OnEND:VEVENT, calls_process_event(). - After processing all events, calls
_delete_non_imported_events()ifdo_remove_old_eventisTrue.
_process_event(ics_event, imported_events)
calendar.event for the parsed VEVENT dict:
- Parses
DTSTARTandDTENDfrom the"%Y%m%dT%H%M%SZ"format. - Applies the date range filter (
import_start_date/import_end_date) if both are set. - Appends
ics_event["UID"]toimported_events(used later by_delete_non_imported_events()). - Searches
calendar.eventbyevent_identifier = UID. If found, calls_update_event(); otherwise calls_create_event().
_create_event(ics_event, event_start_date, event_end_date)
calendar.event with:
| Field | Value |
|---|---|
name | ics_event["SUMMARY"] |
start | parsed event_start_date |
stop | parsed event_end_date |
event_identifier | ics_event["UID"] |
partner_ids | [(4, partner_id.id)] |
_update_event(event, ics_event, event_start_date, event_end_date)
start— if different from the stored value.stop— if different from the stored value.name— ifSUMMARYhas changed.partner_ids— appendspartner_idwith(4, partner_id.id, 0)if not already present.
_delete_non_imported_events(imported_events)
- Searches
calendar.eventwhere:event_identifieris set and not inimported_events.- The partner appears in
partner_ids. start ≥ import_start_dateandstop ≤ import_end_date(when those filters are active).
- Removes
partner_idfrom each stale event’spartner_idsvia(3, partner_id.id). - Unlinks events that now have no remaining partners.
This method only removes the partner’s association with the event, not the event itself, unless the event becomes orphaned (no partners left). This prevents accidentally deleting events shared with other attendees.
convert_date_to_z(line)
DTSTART or DTEND line that carries a TZID= parameter (e.g. DTSTART;TZID=Europe/Paris:20250301T090000) into the UTC Z-suffix format that the parser expects (e.g. DTSTART:20250301T080000Z).
Steps:
- Splits the line on
;TZID=to extract the phase (DTSTARTorDTEND) and timezone ID. - Parses the date/time string with
dateutil.parser.parse(). - Localises it to the named timezone with
pytz.timezone(tz_id).localize(). - Converts to UTC via
.astimezone(pytz.UTC). - Returns the reformatted line.
Extension: calendar.event
Technical name: calendar.event (inherited)Module:
calendar_import_ics
A single field is added to the standard calendar.event model to support idempotent ICS imports.
Stores the
UID property from an imported ICS file. Used by _process_event() to look up an existing event before deciding whether to create or update. Empty for events not created through the import wizard.