diff --git a/event_session/README.rst b/event_session/README.rst new file mode 100644 index 000000000..587a26165 --- /dev/null +++ b/event_session/README.rst @@ -0,0 +1,87 @@ +============== +Event Sessions +============== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fevent-lightgray.png?logo=github + :target: https://github.com/OCA/event/tree/12.0/event_session + :alt: OCA/event +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/event-12-0/event-12-0-event_session + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/199/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to create sessions associated with events. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +You can either: + +* Go to Events > Sessions and create some sessions associated with an event. +* Go to an event and use the sessions wizard to create all your event sessions + according to a given schedule. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* `Tecnativa `__: + + * Sergio Teruel + * David Vidal + +* Nikos Tsirintanis + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/event `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/event_session/__init__.py b/event_session/__init__.py new file mode 100644 index 000000000..1c15bc7ee --- /dev/null +++ b/event_session/__init__.py @@ -0,0 +1,3 @@ +from . import models +from . import wizards +from . import tests diff --git a/event_session/__manifest__.py b/event_session/__manifest__.py new file mode 100644 index 000000000..8dc7f0ab0 --- /dev/null +++ b/event_session/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2017-19 David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Event Sessions", + "version": "13.0.1.0.0", + "author": "Tecnativa, Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/oca/event.git", + "category": "Marketing", + "summary": "Sessions in events", + "depends": ["event_mail"], + "data": [ + "security/ir.model.access.csv", + "security/event_session_security.xml", + "views/event_session_view.xml", + "views/event_view.xml", + "wizards/wizard_event_session_view.xml", + ], + "installable": True, +} diff --git a/event_session/i18n/es.po b/event_session/i18n/es.po new file mode 100644 index 000000000..c1f07f370 --- /dev/null +++ b/event_session/i18n/es.po @@ -0,0 +1,627 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * event_session +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-14 11:25+0000\n" +"PO-Revision-Date: 2017-06-14 13:27+0200\n" +"Last-Translator: David \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"X-Generator: Poedit 1.8.7.1\n" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__cancel_state +msgid " # No of Cancelled Registrations" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__confirm_state +#, fuzzy +msgid " # No of Confirmed Registrations" +msgstr "Reservas de plazas no confirmadas" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__draft_state +#, fuzzy +msgid " # No of Draft Registrations" +msgstr "Registros" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__active +msgid "Active" +msgstr "Activo" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__registration_ids +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Attendees" +msgstr "Asistentes" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Attendees on this session" +msgstr "Asistentes a esta sesión" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_available_expected +msgid "Available Expected Seats" +msgstr "Plazas disponibles previstas" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_available +msgid "Available Seats" +msgstr "Plazas disponibles" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__seats_available_expected +msgid "Available expected seats" +msgstr "Plazas disponibles previstas" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Cancel" +msgstr "Cancelar" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__delete_existing_sessions +msgid "Check in order to delete every previous session for this event" +msgstr "Seleccionar para borrar todas las sesiones existentes en este evento." + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__company_id +msgid "Company" +msgstr "Compañía" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__fridays +msgid "Create sessions on Fridays" +msgstr "Crear sesiones los viernes" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__mondays +msgid "Create sessions on Mondays" +msgstr "Crear sesiones los lunes" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__saturdays +msgid "Create sessions on Saturdays" +msgstr "Crear sesiones los sábados" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__sundays +msgid "Create sessions on Sundays" +msgstr "Crear sesiones los domingos" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__thursdays +msgid "Create sessions on Thursdays" +msgstr "Crear sesiones los jueves" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__tuesdays +msgid "Create sessions on Tuesdays" +msgstr "Crear sesiones los martes" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__wednesdays +msgid "Create sessions on Wednesdays" +msgstr "Crear sesiones los miércoles" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__create_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__create_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__create_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__create_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Dates and event data" +msgstr "Datos de evento y fechas" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__delete_existing_sessions +#, fuzzy +msgid "Delete Existing Sessions" +msgstr "Borrar sesiones existentes" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__display_name +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__display_name +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__display_name +msgid "Display Name" +msgstr "Nombre a mostrar" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Email Schedule" +msgstr "Programación de correo electrónico" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_date_end +msgid "End Date" +msgstr "Fecha finalización" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_end_located +msgid "End Date Located" +msgstr "Fecha de finalización localizada" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__end_time +#, fuzzy +msgid "End Time" +msgstr "Hora de fin" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:323 +#, python-format +msgid "Ending and starting time can't be the same!" +msgstr "La hora de comienzo y de fin no puede ser la misma" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_event +#: model:ir.model.fields,field_description:event_session.field_event_mail__event_id +#: model:ir.model.fields,field_description:event_session.field_event_mail_scheduler_template__event_id +#: model:ir.model.fields,field_description:event_session.field_event_session__event_id +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_id +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Event" +msgstr "Evento" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_mail +msgid "Event Automated Mailing" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_mail__event_mail_template_id +#: model:ir.model.fields,field_description:event_session.field_event_mail_scheduler_template__event_mail_template_id +#, fuzzy +msgid "Event Mail Template" +msgstr "Plantilla de programación de correos" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_registration +#, fuzzy +msgid "Event Registration" +msgstr "Registros" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Event Session" +msgstr "Sesión de evento" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Event Sesssion" +msgstr "Sesión de evento" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_session +msgid "Event session" +msgstr "Sesión" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__fridays +msgid "Fridays" +msgstr "Viernes" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_available_pc +msgid "Full %" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.session_view_event_form +msgid "Generate Sessions" +msgstr "Generar sesiones" + +#. module: event_session +#: model:ir.actions.act_window,name:event_session.act_wizard_event_session +msgid "Generate Sessions Wizard" +msgstr "Asistente para generar sesiones" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Generate sessions" +msgstr "Generar sesiones" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Group By" +msgstr "Agrupar por" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__session_hour_ids +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Hours" +msgstr "Horas" + +#. module: event_session +#: model:ir.model,name:event_session.model_wizard_event_session_hours +msgid "Hours in wich the sessions will run" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__id +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__id +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__id +msgid "ID" +msgstr "ID" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__name +msgid "It will be generated according to given parameters" +msgstr "Se generarán de acuerdo con los parámetros dados" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session____last_update +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session____last_update +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours____last_update +msgid "Last Modified on" +msgstr "Última modificación en" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__write_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__write_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__write_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__write_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: event_session +#: selection:event.session,seats_availability:0 +msgid "Limited" +msgstr "Limitados" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__event_mail_ids +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_mail_template_id +msgid "Mail Schedule" +msgstr "Programación de correo" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_availability +msgid "Maximum Attendees" +msgstr "Asistentes máximos" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_max +msgid "Maximum seats" +msgstr "Número máximo de asistentes" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_min +msgid "Minimum seats" +msgstr "Plazas mínimas" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__mondays +msgid "Mondays" +msgstr "Lunes" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:303 +#, python-format +msgid "No more available seats for this session." +msgstr "No hay más plazas disponibles para esta sesión." + +#. module: event_session +#: code:addons/event_session/models/event.py:99 +#, python-format +msgid "No more seats available for this event." +msgstr "No hay más plazas disponibles para este evento." + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_expected +msgid "Number of Expected Attendees" +msgstr "Número previsto de asistentes" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_used +msgid "Number of Participants" +msgstr "Número de asistentes" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Origin" +msgstr "Origen" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Other options" +msgstr "Otras opciones" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Partner" +msgstr "Empresa" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_mail_registration +msgid "Registration Mail Scheduler" +msgstr "Registro de Programador de Correo Electrónico" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Registrations" +msgstr "Registros" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_reserved +msgid "Reserved Seats" +msgstr "Plazas reservadas" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__saturdays +msgid "Saturdays" +msgstr "Sábados" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Schedule" +msgstr "Programar" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_mail__session_id +#: model:ir.model.fields,field_description:event_session.field_event_mail_scheduler_template__session_id +#: model:ir.model.fields,field_description:event_session.field_event_registration__session_id +#: model:ir.model.fields,field_description:event_session.field_event_session__name +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_calendar +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Session" +msgstr "Sesión" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_end +msgid "Session date end" +msgstr "Fecha de fin de sesión" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:314 +#, python-format +msgid "Session date is out of this event dates range" +msgstr "La fecha de la sesión está fuera del rango de fechas de este evento" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__name +msgid "Session info" +msgstr "Información de la sesión" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_begin +msgid "Session start date" +msgstr "Fecha de inicio de sesión" + +#. module: event_session +#: model:ir.actions.act_window,name:event_session.act_event_session_event_form +#: model:ir.actions.act_window,name:event_session.act_event_session_form +#: model:ir.model.fields,field_description:event_session.field_event_event__session_ids +#: model:ir.ui.menu,name:event_session.event_session_menu +#: model_terms:ir.ui.view,arch_db:event_session.view_event_form +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Sessions" +msgstr "Sesiones" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_form +msgid "Sessions availables for this event" +msgstr "Sesiones disponibles para este evento" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__event_date_begin +msgid "" +"Set it up in the event configurationSessions will be generated from this date" +msgstr "" +"Establécela en la configuración del evento. Se generarán sesiones a partir " +"de esta fecha." + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__event_date_end +#: model:ir.model.fields,help:event_session.field_wizard_event_session__event_date_tz +msgid "" +"Set it up in the event configurationSessions will be generated up to this " +"date" +msgstr "" +"Establécela en la configuración del evento. Se generarán sesiones a hasta " +"esta fecha." + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_date_begin +msgid "Start Date" +msgstr "Fecha de inicio" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_begin_located +msgid "Start Date Located" +msgstr "Fecha de inicio localizada" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__start_time +#, fuzzy +msgid "Start Time" +msgstr "Hora de incio" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "State" +msgstr "Estado" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__sundays +msgid "Sundays" +msgstr "Domingos" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:86 +#: code:addons/event_session/wizards/wizard_event_session.py:91 +#, python-format +msgid "There are overlapping hours!" +msgstr "¡Hay horarios superpuestos!" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:201 +#, python-format +msgid "There are sessions with no duration!" +msgstr "¡Hay horarios con duración nula!" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__thursdays +msgid "Thursdays" +msgstr "Jueves" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_tz +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_date_tz +msgid "Timezone" +msgstr "Zona horaria" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total available expected seats" +msgstr "Total plazas disponibles previstas" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total available seats" +msgstr "Total plazas disponibles" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__sessions_count +#: model:ir.model.fields,field_description:event_session.field_event_registration__event_sessions_count +msgid "Total event sessions" +msgstr "Sesiones de evento totales" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats" +msgstr "Total plazas" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats expected" +msgstr "Total plazas previstas" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats reserved" +msgstr "Total plazas reservadas" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats unconfirmed" +msgstr "Total plazas sin confirmar" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__tuesdays +msgid "Tuesdays" +msgstr "Martes" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_unconfirmed +msgid "Unconfirmed Seat Reservations" +msgstr "Reservas de plazas no confirmadas" + +#. module: event_session +#: selection:event.session,seats_availability:0 +msgid "Unlimited" +msgstr "Ilimitados" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__wednesdays +msgid "Wednesdays" +msgstr "Miércoles" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Weekdays" +msgstr "Días de la semana" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__wizard_event_session_id +#, fuzzy +msgid "Wizard Event Session" +msgstr "Wizard event session id" + +#. module: event_session +#: model:ir.model,name:event_session.model_wizard_event_session +#, fuzzy +msgid "Wizard for ease sessions creation" +msgstr "Wizard event session id" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:224 +#, python-format +msgid "" +"You are trying to delete one or more sessions with active " +"registrations" +msgstr "" + +#. module: event_session +#: code:addons/event_session/tests/test_session.py:179 +#, python-format +msgid "" +"You are trying to delete one or more sessions with active " +"registrations" +msgstr "" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:177 +#, python-format +msgid "You must select at least one weekday" +msgstr "Debes seleccionar al menos un día de la semana" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:210 +#, python-format +msgid "You've entered invalid hours!" +msgstr "¡Las horas introducidas son erróneas!" + +#~ msgid "# of Event Sessions" +#~ msgstr "# de Sesiones del Evento" + +#~ msgid "Attendee" +#~ msgstr "Asistentes" + +#~ msgid "Available seats" +#~ msgstr "Plazas disponibles" + +#~ msgid "Event id" +#~ msgstr "Evento" + +#~ msgid "Seats expected" +#~ msgstr "Plazas previstas" + +#~ msgid "event.mail" +#~ msgstr "event.mail" + +#~ msgid "report.event.registration" +#~ msgstr "report.event.registration" + +#~ msgid "wizard.event.session" +#~ msgstr "wizard.event.session" + +#~ msgid "wizard.event.session.hours" +#~ msgstr "wizard.event.session.hours" diff --git a/event_session/i18n/event_session.pot b/event_session/i18n/event_session.pot new file mode 100644 index 000000000..2810927ae --- /dev/null +++ b/event_session/i18n/event_session.pot @@ -0,0 +1,577 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * event_session +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__cancel_state +msgid " # No of Cancelled Registrations" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__confirm_state +msgid " # No of Confirmed Registrations" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__draft_state +msgid " # No of Draft Registrations" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__active +msgid "Active" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__registration_ids +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Attendees" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Attendees on this session" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_available_expected +msgid "Available Expected Seats" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_available +msgid "Available Seats" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__seats_available_expected +msgid "Available expected seats" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Cancel" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__delete_existing_sessions +msgid "Check in order to delete every previous session for this event" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__company_id +msgid "Company" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__fridays +msgid "Create sessions on Fridays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__mondays +msgid "Create sessions on Mondays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__saturdays +msgid "Create sessions on Saturdays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__sundays +msgid "Create sessions on Sundays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__thursdays +msgid "Create sessions on Thursdays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__tuesdays +msgid "Create sessions on Tuesdays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__wednesdays +msgid "Create sessions on Wednesdays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__create_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__create_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__create_uid +msgid "Created by" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__create_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__create_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__create_date +msgid "Created on" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Dates and event data" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__delete_existing_sessions +msgid "Delete Existing Sessions" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__display_name +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__display_name +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__display_name +msgid "Display Name" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Email Schedule" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_date_end +msgid "End Date" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_end_located +msgid "End Date Located" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__end_time +msgid "End Time" +msgstr "" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:323 +#, python-format +msgid "Ending and starting time can't be the same!" +msgstr "" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_event +#: model:ir.model.fields,field_description:event_session.field_event_mail__event_id +#: model:ir.model.fields,field_description:event_session.field_event_mail_scheduler_template__event_id +#: model:ir.model.fields,field_description:event_session.field_event_session__event_id +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_id +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Event" +msgstr "" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_mail +msgid "Event Automated Mailing" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_mail__event_mail_template_id +#: model:ir.model.fields,field_description:event_session.field_event_mail_scheduler_template__event_mail_template_id +msgid "Event Mail Template" +msgstr "" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_registration +msgid "Event Registration" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Event Session" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Event Sesssion" +msgstr "" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_session +msgid "Event session" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__fridays +msgid "Fridays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_available_pc +msgid "Full %" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.session_view_event_form +msgid "Generate Sessions" +msgstr "" + +#. module: event_session +#: model:ir.actions.act_window,name:event_session.act_wizard_event_session +msgid "Generate Sessions Wizard" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Generate sessions" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Group By" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__session_hour_ids +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Hours" +msgstr "" + +#. module: event_session +#: model:ir.model,name:event_session.model_wizard_event_session_hours +msgid "Hours in wich the sessions will run" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__id +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__id +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__id +msgid "ID" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__name +msgid "It will be generated according to given parameters" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session____last_update +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session____last_update +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours____last_update +msgid "Last Modified on" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__write_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__write_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__write_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__write_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__write_date +msgid "Last Updated on" +msgstr "" + +#. module: event_session +#: selection:event.session,seats_availability:0 +msgid "Limited" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__event_mail_ids +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_mail_template_id +msgid "Mail Schedule" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_availability +msgid "Maximum Attendees" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_max +msgid "Maximum seats" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_min +msgid "Minimum seats" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__mondays +msgid "Mondays" +msgstr "" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:303 +#, python-format +msgid "No more available seats for this session." +msgstr "" + +#. module: event_session +#: code:addons/event_session/models/event.py:99 +#, python-format +msgid "No more seats available for this event." +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_expected +msgid "Number of Expected Attendees" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_used +msgid "Number of Participants" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Origin" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Other options" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Partner" +msgstr "" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_mail_registration +msgid "Registration Mail Scheduler" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Registrations" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_reserved +msgid "Reserved Seats" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__saturdays +msgid "Saturdays" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Schedule" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_mail__session_id +#: model:ir.model.fields,field_description:event_session.field_event_mail_scheduler_template__session_id +#: model:ir.model.fields,field_description:event_session.field_event_registration__session_id +#: model:ir.model.fields,field_description:event_session.field_event_session__name +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_calendar +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Session" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_end +msgid "Session date end" +msgstr "" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:314 +#, python-format +msgid "Session date is out of this event dates range" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__name +msgid "Session info" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_begin +msgid "Session start date" +msgstr "" + +#. module: event_session +#: model:ir.actions.act_window,name:event_session.act_event_session_event_form +#: model:ir.actions.act_window,name:event_session.act_event_session_form +#: model:ir.model.fields,field_description:event_session.field_event_event__session_ids +#: model:ir.ui.menu,name:event_session.event_session_menu +#: model_terms:ir.ui.view,arch_db:event_session.view_event_form +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Sessions" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_form +msgid "Sessions availables for this event" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__event_date_begin +msgid "Set it up in the event configurationSessions will be generated from this date" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__event_date_end +#: model:ir.model.fields,help:event_session.field_wizard_event_session__event_date_tz +msgid "Set it up in the event configurationSessions will be generated up to this date" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_date_begin +msgid "Start Date" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_begin_located +msgid "Start Date Located" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__start_time +msgid "Start Time" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "State" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__sundays +msgid "Sundays" +msgstr "" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:86 +#: code:addons/event_session/wizards/wizard_event_session.py:91 +#, python-format +msgid "There are overlapping hours!" +msgstr "" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:201 +#, python-format +msgid "There are sessions with no duration!" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__thursdays +msgid "Thursdays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_tz +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_date_tz +msgid "Timezone" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total available expected seats" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total available seats" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__sessions_count +#: model:ir.model.fields,field_description:event_session.field_event_registration__event_sessions_count +msgid "Total event sessions" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats expected" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats reserved" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats unconfirmed" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__tuesdays +msgid "Tuesdays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_unconfirmed +msgid "Unconfirmed Seat Reservations" +msgstr "" + +#. module: event_session +#: selection:event.session,seats_availability:0 +msgid "Unlimited" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__wednesdays +msgid "Wednesdays" +msgstr "" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Weekdays" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__wizard_event_session_id +msgid "Wizard Event Session" +msgstr "" + +#. module: event_session +#: model:ir.model,name:event_session.model_wizard_event_session +msgid "Wizard for ease sessions creation" +msgstr "" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:224 +#, python-format +msgid "You are trying to delete one or more sessions with active registrations" +msgstr "" + +#. module: event_session +#: code:addons/event_session/tests/test_session.py:179 +#, python-format +msgid "You are trying to delete one or more sessions with active registrations" +msgstr "" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:177 +#, python-format +msgid "You must select at least one weekday" +msgstr "" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:210 +#, python-format +msgid "You've entered invalid hours!" +msgstr "" + diff --git a/event_session/i18n/nl.po b/event_session/i18n/nl.po new file mode 100644 index 000000000..3a878e24e --- /dev/null +++ b/event_session/i18n/nl.po @@ -0,0 +1,626 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * event_session +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2018-09-20 17:38+0000\n" +"Last-Translator: lfreeke \n" +"Language-Team: none\n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.1.1\n" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__cancel_state +msgid " # No of Cancelled Registrations" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__confirm_state +#, fuzzy +msgid " # No of Confirmed Registrations" +msgstr "Onbevestigd gereserveerde plaatsen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__draft_state +#, fuzzy +msgid " # No of Draft Registrations" +msgstr "Inschrijvingen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__active +msgid "Active" +msgstr "Actief" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__registration_ids +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Attendees" +msgstr "Deelnemers" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Attendees on this session" +msgstr "Deelnemers in deze sessie" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_available_expected +msgid "Available Expected Seats" +msgstr "Verwachte beschikbare plaatsen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_available +msgid "Available Seats" +msgstr "Beschikbare plaatsen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__seats_available_expected +msgid "Available expected seats" +msgstr "Verwachte beschikbare plaatsen" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Cancel" +msgstr "Annuleer" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__delete_existing_sessions +msgid "Check in order to delete every previous session for this event" +msgstr "Vink aan om alle voorgaande sessie voor dit evenement te verwijderen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__company_id +msgid "Company" +msgstr "Bedrijf" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__fridays +msgid "Create sessions on Fridays" +msgstr "Maak sessies aan op vrijdag" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__mondays +msgid "Create sessions on Mondays" +msgstr "Maak sessies aan op maandag" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__saturdays +msgid "Create sessions on Saturdays" +msgstr "Maak sessies aan op zaterdag" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__sundays +msgid "Create sessions on Sundays" +msgstr "Maak sessies aan op zondag" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__thursdays +msgid "Create sessions on Thursdays" +msgstr "Maak sessies aan op donderdag" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__tuesdays +msgid "Create sessions on Tuesdays" +msgstr "Maak sessies aan op dinsdag" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__wednesdays +msgid "Create sessions on Wednesdays" +msgstr "Maak sessies aan op woensdag" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__create_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__create_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__create_uid +msgid "Created by" +msgstr "Aangemaakt door" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__create_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__create_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__create_date +msgid "Created on" +msgstr "Aangemaakt op" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Dates and event data" +msgstr "Datums en evenementgegevens" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__delete_existing_sessions +#, fuzzy +msgid "Delete Existing Sessions" +msgstr "Verwijder bestaande sessies" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__display_name +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__display_name +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__display_name +msgid "Display Name" +msgstr "Weergave naam" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Email Schedule" +msgstr "Email schema" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_date_end +msgid "End Date" +msgstr "Einddatum" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_end_located +msgid "End Date Located" +msgstr "Einddatum locatie" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__end_time +#, fuzzy +msgid "End Time" +msgstr "Eindtijd" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:323 +#, python-format +msgid "Ending and starting time can't be the same!" +msgstr "Eind- en begintijd kunnen niet hetzelfde zijn!" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_event +#: model:ir.model.fields,field_description:event_session.field_event_mail__event_id +#: model:ir.model.fields,field_description:event_session.field_event_mail_scheduler_template__event_id +#: model:ir.model.fields,field_description:event_session.field_event_session__event_id +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_id +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Event" +msgstr "Evenement" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_mail +msgid "Event Automated Mailing" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_mail__event_mail_template_id +#: model:ir.model.fields,field_description:event_session.field_event_mail_scheduler_template__event_mail_template_id +#, fuzzy +msgid "Event Mail Template" +msgstr "Mail planner sjabloon" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_registration +#, fuzzy +msgid "Event Registration" +msgstr "Inschrijvingen" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Event Session" +msgstr "Evenementsessie" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Event Sesssion" +msgstr "Evenementsessie" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_session +msgid "Event session" +msgstr "Evenementsessie" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__fridays +msgid "Fridays" +msgstr "Vrijdag" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_available_pc +msgid "Full %" +msgstr "Volledig %" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.session_view_event_form +msgid "Generate Sessions" +msgstr "Maak sessies aan" + +#. module: event_session +#: model:ir.actions.act_window,name:event_session.act_wizard_event_session +msgid "Generate Sessions Wizard" +msgstr "Maak sessies aan wizard" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Generate sessions" +msgstr "Maak sessies aan" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Group By" +msgstr "Groepeer op" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__session_hour_ids +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Hours" +msgstr "Uren" + +#. module: event_session +#: model:ir.model,name:event_session.model_wizard_event_session_hours +msgid "Hours in wich the sessions will run" +msgstr "" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__id +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__id +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__id +msgid "ID" +msgstr "ID" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__name +msgid "It will be generated according to given parameters" +msgstr "Het zal worden gegenereerd door de gekozen parameters" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session____last_update +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session____last_update +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours____last_update +msgid "Last Modified on" +msgstr "Laatst gewijzigd op" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__write_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__write_uid +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__write_uid +msgid "Last Updated by" +msgstr "Laatst bijgewerkt door" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__write_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__write_date +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__write_date +msgid "Last Updated on" +msgstr "Laatst bijgewerkt op" + +#. module: event_session +#: selection:event.session,seats_availability:0 +msgid "Limited" +msgstr "Gelimiteerd" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__event_mail_ids +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_mail_template_id +msgid "Mail Schedule" +msgstr "Mail planner" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_availability +msgid "Maximum Attendees" +msgstr "Maximaal aantal deelnemers" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_max +msgid "Maximum seats" +msgstr "Maximaal aantal plaatsen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_min +msgid "Minimum seats" +msgstr "Minimaal aantal plaatsen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__mondays +msgid "Mondays" +msgstr "Maandag" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:303 +#, python-format +msgid "No more available seats for this session." +msgstr "Geen plaatsen meer beschikbaar voor deze sessie." + +#. module: event_session +#: code:addons/event_session/models/event.py:99 +#, python-format +msgid "No more seats available for this event." +msgstr "Er zijn geen plaatsen meer beschikbaar voor dit evenement." + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_expected +msgid "Number of Expected Attendees" +msgstr "Aantal verwachtte deelnemers" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_used +msgid "Number of Participants" +msgstr "Aantal deelnemers" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Origin" +msgstr "Bron" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Other options" +msgstr "Andere opties" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Partner" +msgstr "Relatie" + +#. module: event_session +#: model:ir.model,name:event_session.model_event_mail_registration +msgid "Registration Mail Scheduler" +msgstr "Registratiemail planner" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "Registrations" +msgstr "Inschrijvingen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_reserved +msgid "Reserved Seats" +msgstr "Gereserveerde plaatsen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__saturdays +msgid "Saturdays" +msgstr "Zaterdag" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Schedule" +msgstr "Planning" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_mail__session_id +#: model:ir.model.fields,field_description:event_session.field_event_mail_scheduler_template__session_id +#: model:ir.model.fields,field_description:event_session.field_event_registration__session_id +#: model:ir.model.fields,field_description:event_session.field_event_session__name +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_calendar +#: model_terms:ir.ui.view,arch_db:event_session.view_session_search +msgid "Session" +msgstr "Sessie" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_end +msgid "Session date end" +msgstr "Sessie einddatum" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:314 +#, python-format +msgid "Session date is out of this event dates range" +msgstr "Sessiedatum is niet in hetzelfde bereik als de evenementdatum" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__name +msgid "Session info" +msgstr "Sessie info" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_begin +msgid "Session start date" +msgstr "Sessie begindatum" + +#. module: event_session +#: model:ir.actions.act_window,name:event_session.act_event_session_event_form +#: model:ir.actions.act_window,name:event_session.act_event_session_form +#: model:ir.model.fields,field_description:event_session.field_event_event__session_ids +#: model:ir.ui.menu,name:event_session.event_session_menu +#: model_terms:ir.ui.view,arch_db:event_session.view_event_form +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Sessions" +msgstr "Sessies" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_form +msgid "Sessions availables for this event" +msgstr "Beschikbare sessies voor dit evenement" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__event_date_begin +msgid "" +"Set it up in the event configurationSessions will be generated from this date" +msgstr "" +"Instellen in de evenement configuratie. Er worden sessies vanaf deze datum " +"gegenereerd" + +#. module: event_session +#: model:ir.model.fields,help:event_session.field_wizard_event_session__event_date_end +#: model:ir.model.fields,help:event_session.field_wizard_event_session__event_date_tz +msgid "" +"Set it up in the event configurationSessions will be generated up to this " +"date" +msgstr "" +"Instellen in de evenement configuratie. Er worden sessies vanaf deze datum " +"gegenereerd" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_date_begin +msgid "Start Date" +msgstr "Begindatum" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_begin_located +msgid "Start Date Located" +msgstr "Startdatum locatie" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__start_time +#, fuzzy +msgid "Start Time" +msgstr "Begintijd" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_form +msgid "State" +msgstr "Status" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__sundays +msgid "Sundays" +msgstr "Zondag" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:86 +#: code:addons/event_session/wizards/wizard_event_session.py:91 +#, python-format +msgid "There are overlapping hours!" +msgstr "Er zijn overlappende uren!" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:201 +#, python-format +msgid "There are sessions with no duration!" +msgstr "Er zijn sessies zonder tijdsduur!" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__thursdays +msgid "Thursdays" +msgstr "Donderdag" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__date_tz +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__event_date_tz +msgid "Timezone" +msgstr "Tijdzone" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total available expected seats" +msgstr "Totaal aantal verwachte beschikbare plaatsen" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total available seats" +msgstr "Totaal aantal beschikbare plaatsen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_event__sessions_count +#: model:ir.model.fields,field_description:event_session.field_event_registration__event_sessions_count +msgid "Total event sessions" +msgstr "Totaal aantal evenementsessies" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats" +msgstr "Totaal aantal plaatsen" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats expected" +msgstr "Totaal aantal verwachte plaatsen" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats reserved" +msgstr "Totaal aantal gereserveerde plaatsen" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.view_event_session_tree +msgid "Total seats unconfirmed" +msgstr "Totaal aantal onbevestigde plaatsen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__tuesdays +msgid "Tuesdays" +msgstr "Dinsdag" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_event_session__seats_unconfirmed +msgid "Unconfirmed Seat Reservations" +msgstr "Onbevestigd gereserveerde plaatsen" + +#. module: event_session +#: selection:event.session,seats_availability:0 +msgid "Unlimited" +msgstr "Onbeperkt" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session__wednesdays +msgid "Wednesdays" +msgstr "Woensdag" + +#. module: event_session +#: model_terms:ir.ui.view,arch_db:event_session.generator_view_form +msgid "Weekdays" +msgstr "Weekdagen" + +#. module: event_session +#: model:ir.model.fields,field_description:event_session.field_wizard_event_session_hours__wizard_event_session_id +#, fuzzy +msgid "Wizard Event Session" +msgstr "Wizard evenementensessie id" + +#. module: event_session +#: model:ir.model,name:event_session.model_wizard_event_session +#, fuzzy +msgid "Wizard for ease sessions creation" +msgstr "Wizard evenementensessie id" + +#. module: event_session +#: code:addons/event_session/models/event_session.py:224 +#, python-format +msgid "" +"You are trying to delete one or more sessions with active " +"registrations" +msgstr "" + +#. module: event_session +#: code:addons/event_session/tests/test_session.py:179 +#, python-format +msgid "" +"You are trying to delete one or more sessions with active " +"registrations" +msgstr "" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:177 +#, python-format +msgid "You must select at least one weekday" +msgstr "U moet minstens één weekdag selecteren" + +#. module: event_session +#: code:addons/event_session/wizards/wizard_event_session.py:210 +#, python-format +msgid "You've entered invalid hours!" +msgstr "U heeft ongeldig uren ingevoerd!" + +#~ msgid "# of Event Sessions" +#~ msgstr "# of evenementsessies" + +#~ msgid "Attendee" +#~ msgstr "Deelnemer" + +#~ msgid "Available seats" +#~ msgstr "Beschikbare plaatsen" + +#~ msgid "Event id" +#~ msgstr "Evenement id" + +#~ msgid "Seats expected" +#~ msgstr "Verwachte plaatsen" + +#~ msgid "event.mail" +#~ msgstr "event.mail" + +#~ msgid "report.event.registration" +#~ msgstr "report.event.registration" + +#~ msgid "wizard.event.session" +#~ msgstr "wizard.event.session" + +#~ msgid "wizard.event.session.hours" +#~ msgstr "wizard.event.session.hours" diff --git a/event_session/models/__init__.py b/event_session/models/__init__.py new file mode 100644 index 000000000..8df9d719c --- /dev/null +++ b/event_session/models/__init__.py @@ -0,0 +1,3 @@ +from . import event +from . import event_session +from . import event_mail diff --git a/event_session/models/event.py b/event_session/models/event.py new file mode 100644 index 000000000..662cda732 --- /dev/null +++ b/event_session/models/event.py @@ -0,0 +1,98 @@ +# Copyright 2017 David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class EventEvent(models.Model): + _inherit = "event.event" + + session_ids = fields.One2many( + comodel_name="event.session", inverse_name="event_id", string="Sessions", + ) + sessions_count = fields.Integer( + compute="_compute_sessions_count", string="Total event sessions", store=True, + ) + seats_available_expected = fields.Integer( + compute="_compute_seats_available_expected", + string="Available expected seats", + readonly=True, + store=True, + ) + draft_state = fields.Integer( + compute="_compute_state_numbers", + string=" # No of Draft Registrations", + store=True, + ) + cancel_state = fields.Integer( + compute="_compute_state_numbers", + string=" # No of Cancelled Registrations", + store=True, + ) + confirm_state = fields.Integer( + compute="_compute_state_numbers", + string=" # No of Confirmed Registrations", + store=True, + ) + + @api.depends("session_ids") + def _compute_sessions_count(self): + for event in self: + event.sessions_count = len(event.session_ids) + + @api.constrains("seats_max", "seats_available") + def _check_seats_limit(self): + for event in self: + if not event.session_ids: + return super(EventEvent, event)._check_seats_limit() + + @api.depends("seats_max", "seats_expected") + def _compute_seats_available_expected(self): + for this in self: + seats = this.seats_max - this.seats_expected + this.seats_available_expected = seats + + @api.depends("registration_ids.state") + def _compute_state_numbers(self): + for this in self: + this.draft_state = len( + this.registration_ids.filtered(lambda x: x.state == "draft") + ) + this.cancel_state = len( + this.registration_ids.filtered(lambda x: x.state == "cancel") + ) + this.confirm_state = len( + this.registration_ids.filtered(lambda x: x.state == "confirm") + ) + + +class EventRegistration(models.Model): + _inherit = "event.registration" + + event_sessions_count = fields.Integer( + related="event_id.sessions_count", readonly=True, + ) + session_id = fields.Many2one( + comodel_name="event.session", string="Session", ondelete="restrict", + ) + + @api.constrains("event_id", "session_id", "state") + def _check_seats_limit(self): + for registration in self.filtered("session_id"): + if ( + registration.session_id.seats_availability == "limited" + and registration.session_id.seats_available < 1 + and registration.state == "open" + ): + raise ValidationError(_("No more seats available for this event.")) + + def confirm_registration(self): + for reg in self: + if not reg.event_id.session_ids: + super(EventRegistration, reg).confirm_registration() + reg.state = "open" + onsubscribe_schedulers = reg.session_id.event_mail_ids.filtered( + lambda s: s.interval_type == "after_sub" + ) + onsubscribe_schedulers.execute() diff --git a/event_session/models/event_mail.py b/event_session/models/event_mail.py new file mode 100644 index 000000000..98577118d --- /dev/null +++ b/event_session/models/event_mail.py @@ -0,0 +1,94 @@ +# Copyright 2017 David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import logging + +from odoo import api, fields, models + +_logger = logging.getLogger(__name__) + +try: + from odoo.addons.event.models.event_mail import _INTERVALS +except ImportError: + _logger.debug("Can not import events module.") + + +class EventMailScheduler(models.Model): + _inherit = "event.mail" + + event_id = fields.Many2one(required=False) + session_id = fields.Many2one( + comodel_name="event.session", string="Session", ondelete="cascade", + ) + event_mail_template_id = fields.Many2one( + comodel_name="event.mail.template", + string="Event Mail Template", + ondelete="cascade", + ) + + @api.depends( + "mail_sent", + "interval_type", + "event_id.registration_ids", + "mail_registration_ids", + ) + def _compute_done(self): + super()._compute_done() + for event_mail in self: + if event_mail.session_id and event_mail.interval_type not in [ + "before_event", + "after_event", + ]: + event_mail.done = ( + True + if event_mail.event_id.sessions_count > 0 + and not event_mail.session_id + else len(event_mail.mail_registration_ids) + == len(event_mail.session_id.registration_ids) + and all(line.mail_sent for line in event_mail.mail_registration_ids) + ) + + @api.depends( + "event_id.state", + "event_id.date_begin", + "interval_type", + "interval_unit", + "interval_nbr", + ) + def _compute_scheduled_date(self): + super()._compute_scheduled_date() + for event_mail in self: + if not event_mail.session_id: + continue + if event_mail.event_id.state not in ["confirm", "done"]: + event_mail.scheduled_date = False + else: + if event_mail.interval_type == "after_sub": + date, sign = event_mail.session_id.create_date, 1 + elif event_mail.interval_type == "before_event": + date, sign = event_mail.session_id.date_begin, -1 + else: + date, sign = event_mail.session_id.date_end, 1 + event_mail.scheduled_date = date + _INTERVALS[event_mail.interval_unit]( + sign * event_mail.interval_nbr + ) + + +class EventMailRegistration(models.Model): + _inherit = "event.mail.registration" + + @api.depends( + "registration_id", "scheduler_id.interval_unit", "scheduler_id.interval_type" + ) + def _compute_scheduled_date(self): + super()._compute_scheduled_date() + for event_mail_reg in self: + if ( + event_mail_reg.registration_id + and event_mail_reg.registration_id.session_id + ): + date_open = event_mail_reg.registration_id.date_open + date_open_datetime = date_open and date_open or fields.datetime.now() + event_mail_reg.scheduled_date = date_open_datetime + _INTERVALS[ + event_mail_reg.scheduler_id.interval_unit + ](event_mail_reg.scheduler_id.interval_nbr) diff --git a/event_session/models/event_session.py b/event_session/models/event_session.py new file mode 100644 index 000000000..ce131173f --- /dev/null +++ b/event_session/models/event_session.py @@ -0,0 +1,335 @@ +# Copyright 2017 David Vidal +# Copyright 2017 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import babel +from babel.dates import format_datetime, format_time + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +def get_locale(env): + """ + Get the locale from the environment as done in ir.qweb.field + + https://github.com/odoo/odoo/blob/13.0/odoo/addons/base/models + /ir_qweb_fields.py#L238 + """ + lang = env["ir.qweb.field"].user_lang() + locale = babel.Locale.parse(lang.code) + return locale + + +def localized_format(value, formats, locale): + """ + Return a string separated by spaces of the formatted + value based on the locale passed as argument. + """ + values = [dt_format(value, locale) for dt_format in formats] + return " ".join(values) + + +def time_format(dt_format): + """ + Returns a callable that will format a datetime with a locale + using the format_time method of babel. + """ + + def wrap(value, locale): + return format_time(value, dt_format, locale=locale) + + return wrap + + +def datetime_format(dt_format): + """ + Returns a callable that will format a datetime with a locale + using the format_datetime method of babel. + """ + + def wrap(value, locale): + return format_datetime(value, dt_format, locale=locale) + + return wrap + + +class EventSession(models.Model): + _name = "event.session" + _description = "Event session" + + name = fields.Char( + string="Session", + required=True, + compute="_compute_name", + store=True, + default="/", + ) + active = fields.Boolean(default=True,) + company_id = fields.Many2one( + comodel_name="res.company", related="event_id.company_id", store=True, + ) + event_id = fields.Many2one(comodel_name="event.event", string="Event") + seats_min = fields.Integer(string="Minimum seats") + seats_max = fields.Integer(string="Maximum seats") + seats_availability = fields.Selection( + [("limited", "Limited"), ("unlimited", "Unlimited")], + "Maximum Attendees", + required=True, + default="unlimited", + ) + seats_reserved = fields.Integer( + string="Reserved Seats", store=True, readonly=True, compute="_compute_seats", + ) + seats_available = fields.Integer( + string="Available Seats", store=True, readonly=True, compute="_compute_seats", + ) + seats_unconfirmed = fields.Integer( + string="Unconfirmed Seat Reservations", + store=True, + readonly=True, + compute="_compute_seats", + ) + seats_used = fields.Integer( + string="Number of Participants", + store=True, + readonly=True, + compute="_compute_seats", + ) + seats_expected = fields.Integer( + string="Number of Expected Attendees", + readonly=True, + compute="_compute_seats", + store=True, + ) + seats_available_expected = fields.Integer( + string="Available Expected Seats", + readonly=True, + compute="_compute_seats", + store=True, + ) + seats_available_pc = fields.Float( + string="Full %", readonly=True, compute="_compute_seats", compute_sudo=True, + ) + date_tz = fields.Selection(string="Timezone", related="event_id.date_tz") + date_begin = fields.Datetime( + string="Session start date", + required=True, + default=lambda self: self.event_id.date_begin, + ) + date_end = fields.Datetime( + string="Session date end", + required=True, + default=lambda self: self.event_id.date_end, + ) + date_begin_located = fields.Datetime( + string="Start Date Located", compute="_compute_date_begin_located", + ) + date_end_located = fields.Datetime( + string="End Date Located", compute="_compute_date_end_located", + ) + registration_ids = fields.One2many( + comodel_name="event.registration", + inverse_name="session_id", + string="Attendees", + state={"done": [("readonly", True)]}, + ) + event_mail_ids = fields.One2many( + comodel_name="event.mail", + inverse_name="session_id", + string="Mail Schedule", + copy=True, + ) + + @api.depends("date_begin", "date_end") + def _compute_name(self): + locale = get_locale(self.env) + for session in self: + if not (session.date_begin and session.date_end): + session.name = "/" + continue + date_begin = session.date_begin_located + date_end = session.date_end_located + + dt_formats = [datetime_format("EEEE"), datetime_format("short")] + + name = localized_format(date_begin, dt_formats, locale) + + if date_begin.date() == date_end.date(): + dt_formats = [time_format("short")] + + name = "{} - {}".format( + name, localized_format(date_end, dt_formats, locale) + ) + session.name = name + + def _session_mails_from_template(self, event_id, mail_template=None): + vals = [(6, 0, [])] + if not mail_template: + mail_template = self.env["ir.default"].get( + "res.config.settings", "event_mail_template_id" + ) + if not mail_template: + # Not template scheduler defined in event settings + return vals + if isinstance(mail_template, int): + mail_template = self.env["event.mail.template"].browse(mail_template) + for scheduler in mail_template.scheduler_template_ids: + vals.append( + ( + 0, + 0, + { + "event_id": event_id, + "interval_nbr": scheduler.interval_nbr, + "interval_unit": scheduler.interval_unit, + "interval_type": scheduler.interval_type, + "template_id": scheduler.template_id.id, + }, + ) + ) + return vals + + def name_get(self): + """Redefine the name_get method to show the event name with the event + session. + """ + res = [] + for item in self: + res.append((item.id, "[{}] {}".format(item.event_id.name, item.name))) + return res + + @api.model + def create(self, vals): + # Config availabilities based on event + if vals.get("event_id", False): + event = self.env["event.event"].browse(vals.get("event_id")) + vals["seats_availability"] = event.seats_availability + vals["seats_max"] = event.seats_max + if not vals.get("event_mail_ids", False): + vals.update( + {"event_mail_ids": self._session_mails_from_template(vals["event_id"])} + ) + return super().create(vals) + + def unlink(self): + for this in self: + if this.registration_ids: + raise ValidationError( + _( + "You are trying to delete one or more \ + sessions with active registrations" + ) + ) + return super().unlink() + + @api.depends("seats_max", "registration_ids.state") + def _compute_seats(self): + """Determine reserved, available, reserved but unconfirmed and used + seats by session. + """ + # aggregate registrations by event session and by state + if len(self.ids) > 0: + state_field = { + "draft": "seats_unconfirmed", + "open": "seats_reserved", + "done": "seats_used", + } + result = self.env["event.registration"].read_group( + [ + ("session_id", "in", self.ids), + ("state", "in", ["draft", "open", "done"]), + ], + ["state", "session_id"], + ["session_id", "state"], + lazy=False, + ) + for res in result: + session = self.browse(res["session_id"][0]) + session[state_field[res["state"]]] += res["__count"] + # compute seats_available + for session in self: + if session.seats_max > 0: + session.seats_available = session.seats_max - ( + session.seats_reserved + session.seats_used + ) + session.seats_expected = ( + session.seats_unconfirmed + session.seats_reserved + session.seats_used + ) + session.seats_available_expected = ( + session.seats_max - session.seats_expected + ) + if session.seats_max > 0: + session.seats_available_pc = ( + session.seats_expected * 100 / float(session.seats_max) + ) + + @api.depends("date_tz", "date_begin") + def _compute_date_begin_located(self): + for session in self.filtered("date_begin"): + self_in_tz = session.with_context(tz=(session.date_tz or "UTC")) + date_begin = session.date_begin + session.date_begin_located = fields.Datetime.to_string( + fields.Datetime.context_timestamp(self_in_tz, date_begin), + ) + + @api.depends("date_tz", "date_end") + def _compute_date_end_located(self): + for session in self.filtered("date_end"): + self_in_tz = session.with_context(tz=(session.date_tz or "UTC")) + date_end = session.date_end + session.date_end_located = fields.Datetime.to_string( + fields.Datetime.context_timestamp(self_in_tz, date_end), + ) + + @api.onchange("event_id") + def onchange_event_id(self): + self.update( + { + "seats_min": self.event_id.seats_min, + "seats_max": self.event_id.seats_max, + "seats_availability": self.event_id.seats_availability, + "date_begin": self.event_id.date_begin, + "date_end": self.event_id.date_end, + } + ) + + @api.constrains("seats_max", "seats_available") + def _check_seats_limit(self): + for session in self: + if ( + session.seats_availability == "limited" + and session.seats_max + and session.seats_available < 0 + ): + raise ValidationError(_("No more available seats for this session.")) + + @api.constrains("date_begin", "date_end") + def _check_dates(self): + for session in self: + if ( + self.event_id.date_end < session.date_begin + or session.date_begin < self.event_id.date_begin + or self.event_id.date_begin > session.date_end + or session.date_end > self.event_id.date_end + ): + raise ValidationError( + _("Session date is out of this event dates range") + ) + + @api.constrains("date_begin", "date_end") + def _check_zero_duration(self): + for session in self: + if session.date_begin == session.date_end: + raise ValidationError(_("Ending and starting time can't be the same!")) + + def button_open_registration(self): + """Opens session registrations""" + self.ensure_one() + action = self.env.ref("event.act_event_registration_from_event").read()[0] + action["domain"] = [("id", "in", self.registration_ids.ids)] + action["context"] = { + "default_event_id": self.event_id.id, + "default_session_id": self.id, + } + return action diff --git a/event_session/readme/CONTRIBUTORS.rst b/event_session/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..721c0b38a --- /dev/null +++ b/event_session/readme/CONTRIBUTORS.rst @@ -0,0 +1,7 @@ +* `Tecnativa `__: + + * Sergio Teruel + * David Vidal + +* Nikos Tsirintanis +* David Alonso diff --git a/event_session/readme/DESCRIPTION.rst b/event_session/readme/DESCRIPTION.rst new file mode 100644 index 000000000..e148c1672 --- /dev/null +++ b/event_session/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module allows to create sessions associated with events. diff --git a/event_session/readme/USAGE.rst b/event_session/readme/USAGE.rst new file mode 100644 index 000000000..5c70c2d18 --- /dev/null +++ b/event_session/readme/USAGE.rst @@ -0,0 +1,5 @@ +You can either: + +* Go to Events > Sessions and create some sessions associated with an event. +* Go to an event and use the sessions wizard to create all your event sessions + according to a given schedule. diff --git a/event_session/security/event_session_security.xml b/event_session/security/event_session_security.xml new file mode 100644 index 000000000..688fae4d7 --- /dev/null +++ b/event_session/security/event_session_security.xml @@ -0,0 +1,11 @@ + + + + Event Session: multi-company + + + ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id]),] + + diff --git a/event_session/security/ir.model.access.csv b/event_session/security/ir.model.access.csv new file mode 100644 index 000000000..26b364c5d --- /dev/null +++ b/event_session/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_event_session_user,event.session.user,event_session.model_event_session,event.group_event_user,1,0,0,0 +access_event_session_admin,event.session.admin,event_session.model_event_session,event.group_event_manager,1,1,1,1 diff --git a/event_session/static/description/icon.png b/event_session/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/event_session/static/description/icon.png differ diff --git a/event_session/static/description/index.html b/event_session/static/description/index.html new file mode 100644 index 000000000..f0ed08b90 --- /dev/null +++ b/event_session/static/description/index.html @@ -0,0 +1,434 @@ + + + + + + +Event Sessions + + + +
+

Event Sessions

+ + +

Beta License: AGPL-3 OCA/event Translate me on Weblate Try me on Runbot

+

This module allows to create sessions associated with events.

+

Table of contents

+ +
+

Usage

+

You can either:

+
    +
  • Go to Events > Sessions and create some sessions associated with an event.
  • +
  • Go to an event and use the sessions wizard to create all your event sessions +according to a given schedule.
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Tecnativa
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/event project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/event_session/tests/__init__.py b/event_session/tests/__init__.py new file mode 100644 index 000000000..b24bf22b9 --- /dev/null +++ b/event_session/tests/__init__.py @@ -0,0 +1 @@ +from . import test_session diff --git a/event_session/tests/test_session.py b/event_session/tests/test_session.py new file mode 100644 index 000000000..b52a96f39 --- /dev/null +++ b/event_session/tests/test_session.py @@ -0,0 +1,442 @@ +# Copyright 2017-19 Tecnativa - David Vidal +# Copyright 2017 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0). +from datetime import datetime + +from dateutil.relativedelta import relativedelta + +from odoo import _ +from odoo.exceptions import ValidationError +from odoo.tests import common + +from ..models.event_session import ( + datetime_format, + get_locale, + localized_format, + time_format, +) + + +class EventSession(common.SavepointCase): + @classmethod + def setUpClass(cls): + super(EventSession, cls).setUpClass() + cls.event = cls.env["event.event"].create( + { + "name": "Test event", + "date_begin": "2017-05-26 20:00:00", + "date_end": "2017-05-30 22:00:00", + "seats_availability": "limited", + "seats_max": "5", + "seats_min": "1", + } + ) + cls.session = cls.env["event.session"].create( + { + "date_begin": "2017-05-26 20:00:00", + "date_end": "2017-05-26 22:00:00", + "event_id": cls.event.id, + "seats_availability": cls.event.seats_availability, + "seats_max": cls.event.seats_max, + "seats_min": cls.event.seats_min, + } + ) + cls.attendee = cls.env["event.registration"].create( + { + "name": "Test attendee", + "event_id": cls.event.id, + "session_id": cls.session.id, + } + ) + cls.wizard = cls.env["wizard.event.session"].create( + { + "event_id": cls.event.id, + "mondays": True, + "tuesdays": True, + "wednesdays": True, + "thursdays": False, + "fridays": True, + "sundays": True, + "saturdays": True, + "delete_existing_sessions": False, + "session_hour_ids": [(0, 0, {"start_time": 20.0, "end_time": 21.0})], + } + ) + cls.template = cls.env["event.mail.template"].create( + { + "name": "Template test 01", + "scheduler_template_ids": [ + ( + 0, + 0, + { + "interval_nbr": 15, + "interval_unit": "days", + "interval_type": "before_event", + "template_id": cls.env.ref("event.event_reminder").id, + }, + ) + ], + } + ) + cls.scheduler = cls.env["event.mail"].create( + { + "event_id": cls.event.id, + "session_id": cls.session.id, + "interval_type": "after_sub", + "template_id": cls.template.id, + } + ) + cls.mail_registration = cls.env["event.mail.registration"].create( + {"scheduler_id": cls.scheduler.id, "registration_id": cls.attendee.id} + ) + + # Enable all languages used in the tests without loading them + languages = cls.env["res.lang"].search( + [ + ["code", "in", ["en_US", "fr_FR", "fr_CA", "en_CA", "ru_RU"]], + "|", + ["active", "=", True], + ["active", "=", False], + ] + ) + languages.write({"active": True}) + + def test_session_name_get(self): + self.assertEqual( + self.session.name_get()[0][1], "[Test event] " + self.session.name, + ) + + def test_check_beginning_date(self): + self.session.date_begin = "2017-05-26 20:00:00" + with self.assertRaises(ValidationError): + self.session.date_begin = "2017-05-26 19:59:59" + with self.assertRaises(ValidationError): + self.session.date_end = "2017-05-30 22:00:01" + + def test_check_end_date(self): + self.session.date_end = "2017-05-30 22:00:00" + with self.assertRaises(ValidationError): + self.session.date_end = "2017-05-30 22:00:01" + with self.assertRaises(ValidationError): + self.session.date_end = "2017-05-26 19:59:59" + + def test_check_zero_duration(self): + with self.assertRaises(ValidationError), self.cr.savepoint(): + self.session.write( + { + "date_begin": "2017-05-28 22:00:00", + "date_end": "2017-05-28 22:00:00", + } + ) + + def test_open_registrations(self): + # registrations button + res = self.session.button_open_registration() + attendees = self.env["event.registration"].search( + [["session_id", "=", self.session.id]] + ) + self.assertEqual(res["domain"], [("id", "in", attendees.ids)]) + + def test_assign_mail_template(self): + vals = { + "event_mail_ids": self.session._session_mails_from_template(self.event.id) + } + self.session.write(vals) + self.assertEqual(len(self.session.event_mail_ids), 0) + vals = { + "event_mail_ids": self.session._session_mails_from_template( + self.event.id, self.template + ) + } + self.session.write(vals) + self.assertEqual(len(self.session.event_mail_ids), 1) + + def test_session_seats(self): + """ Session seat """ + self.assertEqual(self.event.seats_available, self.session.seats_available) + self.assertEqual(self.event.seats_unconfirmed, self.session.seats_unconfirmed) + self.assertEqual(self.event.seats_used, self.session.seats_used) + with self.assertRaises(ValidationError), self.cr.savepoint(): + # check limit regs + for _i in range(int(self.session.seats_available) + 1): + self.env["event.registration"].create( + { + "name": "Test Attendee", + "event_id": self.event.id, + "session_id": self.session.id, + "state": "open", + } + ) + + def test_compute_name(self): + vals = { + "date_begin": "2017-05-28 22:00:00", + "date_end": "2017-05-28 23:00:00", + } + session = self.env["event.session"].new(vals) + self.assertEqual(session.name, "Sunday 5/28/17, 10:00 PM - 11:00 PM") + session.date_begin = session.date_end = False + self.assertEqual(session.name, "/") + + def test_wizard(self): + """Test Session Generation Wizard""" + self.event.date_end = "2017-06-11 23:59:59" + self.event.date_begin = "2017-06-05 00:00:00" + self.wizard.delete_existing_session = True + self.wizard.action_generate_sessions() + # delete previous sessions + self.wizard.update({"delete_existing_sessions": True}) + self.wizard.update({"event_mail_template_id": self.template}) + with self.assertRaises(ValidationError) as error, self.cr.savepoint(): + self.wizard.action_generate_sessions() + self.assertEqual( + error, + _( + "You are trying to delete one or more \ + sessions with active registrations" + ), + ) + self.attendee.session_id = False + self.wizard.action_generate_sessions() + sessions = self.env["event.session"].search([["event_id", "=", self.event.id]]) + self.assertEqual(len(sessions), 6) + for session in sessions: + self.assertTrue(session.event_mail_ids) + self.assertEqual(session.seats_max, self.event.seats_max) + self.assertEqual(session.seats_availability, self.event.seats_availability) + with self.assertRaises(ValidationError), self.cr.savepoint(): + # session duration = 0 + self.wizard.update( + {"session_hour_ids": [(0, 0, {"start_time": 20.0, "end_time": 20.0})]} + ) + with self.assertRaises(ValidationError), self.cr.savepoint(): + # hour invalidity + self.wizard.update( + {"session_hour_ids": [(0, 0, {"start_time": 24.0, "end_time": 24.1})]} + ) + with self.assertRaises(ValidationError), self.cr.savepoint(): + # schedules overlap + self.wizard.update( + { + "session_hour_ids": [ + (0, 0, {"start_time": 20.0, "end_time": 21.0}), + (0, 0, {"start_time": 20.5, "end_time": 21.5}), + ], + } + ) + with self.assertRaises(ValidationError), self.cr.savepoint(): + self.wizard.update( + { + "session_hour_ids": [ + (0, 0, {"start_time": 20.0, "end_time": 21.0}), + (0, 0, {"start_time": 19.5, "end_time": 21.5}), + ], + } + ) + with self.assertRaises(ValidationError), self.cr.savepoint(): + # weekday not set + self.wizard.update( + { + "mondays": False, + "tuesdays": False, + "wednesdays": False, + "thursdays": False, + "fridays": False, + "sundays": False, + "saturdays": False, + } + ) + self.wizard.action_generate_sessions() + + def test_event_mail_compute_scheduled_date(self): + self.assertFalse(self.scheduler.scheduled_date) + self.scheduler.event_id.update({"state": "confirm"}) + date = self.scheduler.session_id.create_date + relativedelta(hours=+1) + self.assertEqual(self.scheduler.scheduled_date, date) + self.scheduler.update({"interval_type": "before_event"}) + date = self.scheduler.session_id.date_begin + relativedelta(hours=-1) + self.assertEqual(self.scheduler.scheduled_date, date) + self.scheduler.update({"interval_type": "after_event"}) + date = self.scheduler.session_id.date_end + relativedelta(hours=+1) + self.assertEqual(self.scheduler.scheduled_date, date) + + def test_event_mail_registration_compute_scheduled_date(self): + self.scheduler.update({"interval_unit": "days"}) + date = self.mail_registration.registration_id.date_open + relativedelta(days=+1) + self.assertEqual(self.mail_registration.scheduled_date, date) + + def test_get_locale(self): + """ + Check if the locale correctly return from the locale set + in the context of the environment. + """ + session = self.env["event.session"] + # Check a locale that can't be the default one + locale = get_locale(session.with_context(lang="fr_CA").env) + self.assertEqual(locale.language, "fr") + self.assertEqual(locale.territory, "CA") + # Check locale change to en_US + locale = get_locale(session.with_context(lang="en_US").env) + self.assertEqual(locale.language, "en") + self.assertEqual(locale.territory, "US") + # Check locale change to Russian + locale = get_locale(session.with_context(lang="ru_RU").env) + self.assertEqual(locale.language, "ru") + self.assertEqual(locale.territory, "RU") + # Check default locale when lang is None should be en_US + locale = get_locale(session.with_context(lang=None).env) + self.assertEqual(locale.language, "en") + self.assertEqual(locale.territory, "US") + + def test_time_format(self): + session = self.env["event.session"] + datetime_val = datetime(2020, 1, 1, 15, 30) + short_time = time_format("short") + # Create some locales + locale_us = get_locale(session.with_context(lang="en_US").env) + locale_ru = get_locale(session.with_context(lang="ru_RU").env) + locale_enca = get_locale(session.with_context(lang="en_CA").env) + locale_frca = get_locale(session.with_context(lang="fr_CA").env) + locale_frfr = get_locale(session.with_context(lang="fr_FR").env) + # Check that result of short time is indeed the one of the locale + # being passed explicitly as string or as Locale from get_locale + # Check US format + short_time_us = short_time(datetime_val, locale_us) + short_time_us2 = short_time(datetime_val, "en_US") + self.assertEqual(short_time_us, "3:30 PM") + self.assertEqual(short_time_us, short_time_us2) + # Check en_CA format + short_time_enca = short_time(datetime_val, locale_enca) + short_time_enca2 = short_time(datetime_val, "en_CA") + self.assertEqual(short_time_enca, "3:30 p.m.") + self.assertEqual(short_time_enca, short_time_enca2) + # Check fr_CA format + short_time_frca = short_time(datetime_val, locale_frca) + short_time_frca2 = short_time(datetime_val, "fr_CA") + self.assertEqual(short_time_frca, "15 h 30") + self.assertEqual(short_time_frca, short_time_frca2) + # Check fr_FR format + short_time_frfr = short_time(datetime_val, locale_frfr) + short_time_frfr2 = short_time(datetime_val, "fr_FR") + self.assertEqual(short_time_frfr, "15:30") + self.assertEqual(short_time_frfr, short_time_frfr2) + # Check ru_RU format + short_time_ru = short_time(datetime_val, locale_ru) + short_time_ru2 = short_time(datetime_val, "ru_RU") + self.assertEqual(short_time_ru, "15:30") + self.assertEqual(short_time_ru, short_time_ru2) + + def test_datetime_format(self): + """ + Check the datetime_format method works with different locales + """ + session = self.env["event.session"] + datetime_val = datetime(2020, 1, 31, 15, 30) + short_time = datetime_format("short") + weekday_time = datetime_format("EEEE") + # Create some locales + locale_us = get_locale(session.with_context(lang="en_US").env) + locale_ru = get_locale(session.with_context(lang="ru_RU").env) + locale_enca = get_locale(session.with_context(lang="en_CA").env) + locale_frca = get_locale(session.with_context(lang="fr_CA").env) + locale_frfr = get_locale(session.with_context(lang="fr_FR").env) + # Check that result of short time is indeed the one of the locale + # being passed explicitly as string or as Locale from get_locale + # Check US format + short_time_us = short_time(datetime_val, locale_us) + short_time_us2 = short_time(datetime_val, "en_US") + self.assertEqual(short_time_us, "1/31/20, 3:30 PM") + self.assertEqual(short_time_us, short_time_us2) + # Check en_CA format + short_time_enca = short_time(datetime_val, locale_enca) + short_time_enca2 = short_time(datetime_val, "en_CA") + self.assertEqual(short_time_enca, "2020-01-31, 3:30 p.m.") + self.assertEqual(short_time_enca, short_time_enca2) + # Check fr_CA format + short_time_frca = short_time(datetime_val, locale_frca) + short_time_frca2 = short_time(datetime_val, "fr_CA") + self.assertEqual(short_time_frca, "20-01-31 15 h 30") + self.assertEqual(short_time_frca, short_time_frca2) + # Check fr_FR format + short_time_frfr = short_time(datetime_val, locale_frfr) + short_time_frfr2 = short_time(datetime_val, "fr_FR") + self.assertEqual(short_time_frfr, "31/01/2020 15:30") + self.assertEqual(short_time_frfr, short_time_frfr2) + # Check ru_RU format + short_time_ru = short_time(datetime_val, locale_ru) + short_time_ru2 = short_time(datetime_val, "ru_RU") + self.assertEqual(short_time_ru, "31.01.2020, 15:30") + self.assertEqual(short_time_ru, short_time_ru2) + + # Check week days formatted + weekday_us = weekday_time(datetime_val, locale_us) + weekday_us2 = weekday_time(datetime_val, "en_US") + self.assertEqual(weekday_us, "Friday") + self.assertEqual(weekday_us, weekday_us2) + # Check en_CA format + weekday_enca = weekday_time(datetime_val, locale_enca) + weekday_enca2 = weekday_time(datetime_val, "en_CA") + self.assertEqual(weekday_enca, "Friday") + self.assertEqual(weekday_enca, weekday_enca2) + # Check fr_CA format + weekday_frca = weekday_time(datetime_val, locale_frca) + weekday_frca2 = weekday_time(datetime_val, "fr_CA") + self.assertEqual(weekday_frca, "vendredi") + self.assertEqual(weekday_frca, weekday_frca2) + # Check fr_FR format + weekday_frfr = weekday_time(datetime_val, locale_frfr) + weekday_frfr2 = weekday_time(datetime_val, "fr_FR") + self.assertEqual(weekday_frfr, "vendredi") + self.assertEqual(weekday_frfr, weekday_frfr2) + # Check ru_RU + weekday_ru = weekday_time(datetime_val, locale_ru) + weekday_ru2 = weekday_time(datetime_val, "ru_RU") + self.assertEqual(weekday_ru, "пятница") + self.assertEqual(weekday_ru, weekday_ru2) + + def test_check_localized_format(self): + """ + Check that localized_format can format multiple + time format in one string seperated by spaces according + to the context language. + """ + session = self.env["event.session"] + + datetime_val = datetime(2020, 1, 31, 15, 30) + # Create some locales + locale_us = get_locale(session.with_context(lang="en_US").env) + locale_ru = get_locale(session.with_context(lang="ru_RU").env) + locale_enca = get_locale(session.with_context(lang="en_CA").env) + locale_frca = get_locale(session.with_context(lang="fr_CA").env) + locale_frfr = get_locale(session.with_context(lang="fr_FR").env) + + # Create a list of formats to test which result in a string with + # the formated text separated by a space + # "formated1 formated2 formated3" + formats = [ + datetime_format("EEEE"), + datetime_format("short"), + time_format("short"), + ] + + self.assertEqual( + localized_format(datetime_val, formats, locale_us), + "Friday 1/31/20, 3:30 PM 3:30 PM", + ) + self.assertEqual( + localized_format(datetime_val, formats, locale_enca), + "Friday 2020-01-31, 3:30 p.m. 3:30 p.m.", + ) + self.assertEqual( + localized_format(datetime_val, formats, locale_frca), + "vendredi 20-01-31 15 h 30 15 h 30", + ) + self.assertEqual( + localized_format(datetime_val, formats, locale_frfr), + "vendredi 31/01/2020 15:30 15:30", + ) + self.assertEqual( + localized_format(datetime_val, formats, locale_ru), + "пятница 31.01.2020, 15:30 15:30", + ) diff --git a/event_session/views/event_session_view.xml b/event_session/views/event_session_view.xml new file mode 100644 index 000000000..5f1d5044d --- /dev/null +++ b/event_session/views/event_session_view.xml @@ -0,0 +1,198 @@ + + + + event.session.search + event.session + + + + + + + + + + + + event.session.form + event.session + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + event.session.tree + event.session + + + + + + + + + + + + + + + + + + + event.session.calendar + event.session + + + + + + + + + event.session.pivot + event.session + + + + + + + + + + + event.session + Sessions + tree,form,calendar,pivot + + + +
diff --git a/event_session/views/event_view.xml b/event_session/views/event_view.xml new file mode 100644 index 000000000..b5722b001 --- /dev/null +++ b/event_session/views/event_view.xml @@ -0,0 +1,74 @@ + + + + event.registration + + + + + + + + + + event.registration + + + + + + + + + + event.session + Sessions + tree,form,calendar,pivot + {'search_default_event_id': active_id, 'default_event_id': active_id} + + + event.event + + + + + + + {'readonly':[('sessions_count', '<', 1)]} + + + + + + + + event.event + + + + + + + + diff --git a/event_session/wizards/__init__.py b/event_session/wizards/__init__.py new file mode 100644 index 000000000..5a6bb71ae --- /dev/null +++ b/event_session/wizards/__init__.py @@ -0,0 +1 @@ +from . import wizard_event_session diff --git a/event_session/wizards/wizard_event_session.py b/event_session/wizards/wizard_event_session.py new file mode 100644 index 000000000..8723599f9 --- /dev/null +++ b/event_session/wizards/wizard_event_session.py @@ -0,0 +1,178 @@ +# Copyright 2017 David Vidal +# Copyright 2017 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from datetime import datetime, timedelta + +from pytz import timezone, utc + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class WizardEventSession(models.TransientModel): + _name = "wizard.event.session" + _description = "Wizard for ease sessions creation" + + name = fields.Char( + "Session info", + required=True, + help="It will be generated according to given parameters", + default="/", + ) + event_id = fields.Many2one( + comodel_name="event.event", + readonly=True, + on_delete="cascade", + default=lambda self: self.env.context["active_id"], + required=True, + ) + event_date_begin = fields.Datetime( + related="event_id.date_begin", + readonly=True, + help="Set it up in the event configuration" + "Sessions will be generated from this date", + ) + event_date_end = fields.Datetime( + related="event_id.date_end", + readonly=True, + help="Set it up in the event configuration" + "Sessions will be generated up to this date", + ) + event_date_tz = fields.Selection( + related="event_id.date_tz", + readonly=True, + help="Set it up in the event configuration" + "Sessions will be generated up to this date", + ) + mondays = fields.Boolean(help="Create sessions on Mondays") + tuesdays = fields.Boolean(help="Create sessions on Tuesdays") + wednesdays = fields.Boolean(help="Create sessions on Wednesdays") + thursdays = fields.Boolean(help="Create sessions on Thursdays") + fridays = fields.Boolean(help="Create sessions on Fridays") + saturdays = fields.Boolean(help="Create sessions on Saturdays") + sundays = fields.Boolean(help="Create sessions on Sundays") + delete_existing_sessions = fields.Boolean( + default=True, + help="Check in order to delete every previous session for this event", + ) + session_hour_ids = fields.One2many( + comodel_name="wizard.event.session.hours", + inverse_name="wizard_event_session_id", + string="Hours", + ) + event_mail_template_id = fields.Many2one( + comodel_name="event.mail.template", string="Mail Schedule", + ) + + @api.constrains("session_hour_ids") + def _avoid_overlapping_hours(self): + for hour_a in self.session_hour_ids: + for hour_b in self.session_hour_ids: + if hour_a != hour_b: + if hour_a.start_time == hour_b.start_time: + raise ValidationError(_("There are overlapping hours!")) + elif hour_b.start_time < hour_a.start_time < hour_b.end_time: + raise ValidationError(_("There are overlapping hours!")) + + def weekdays(self): + """Generate a tuple with the values for accessing days by index.""" + return ( + self.mondays, + self.tuesdays, + self.wednesdays, + self.thursdays, + self.fridays, + self.saturdays, + self.sundays, + ) + + def existing_sessions(self, date): + """Return existing sessions that match some criteria.""" + # Todo: Improve match + return self.env["event.session"].search( + [ + ("event_id", "=", self.event_id.id), + ("date_begin", "=", date), + ("start_time", "=", self.start_time), + ], + ) + + def _prepare_session_values(self, date_begin, date_end): + vals = { + "event_id": self.event_id.id, + "date_begin": fields.Datetime.to_string(date_begin), + "date_end": fields.Datetime.to_string(date_end), + } + mail_template = self.event_mail_template_id or self.env["ir.default"].get( + "res.config.settings", "event_mail_template_id" + ) + if mail_template: + template_values = self.env["event.session"]._session_mails_from_template( + self.event_id.id, mail_template + ) + vals["event_mail_ids"] = template_values + return vals + + def generate_sessions(self): + self.ensure_one() + session_obj = self.env["event.session"] + event_start = utc.localize(self.event_date_begin) + event_end = utc.localize(self.event_date_end) + weekdays = self.weekdays() + current = event_start + current = current.replace(hour=event_end.hour, minute=event_end.minute) + while current <= event_end: + if not weekdays[current.weekday()]: + current += timedelta(days=1) + continue + for hour in self.session_hour_ids: + start_time = datetime.min + timedelta(hours=hour.start_time) + end_time = datetime.min + timedelta(hours=hour.end_time) + current_start = datetime.combine(current.date(), start_time.time(),) + current_end = datetime.combine(current.date(), end_time.time()) + # Convert to UTC from user TZ + local_tz = timezone(self.env.user.tz) + current_start = local_tz.localize(current_start) + current_start = current_start.astimezone(utc) + current_end = local_tz.localize(current_end) + current_end = current_end.astimezone(utc) + if current_start < event_start or current_end > event_end: + continue + # TODO: Check that no session exists with this data + session_obj.create( + self._prepare_session_values(current_start, current_end) + ) + current += timedelta(days=1) + + def action_generate_sessions(self): + """Here's where magic is triggered""" + weekdays = self.weekdays() + if not any(weekdays): + raise ValidationError(_("You must select at least one weekday")) + if self.delete_existing_sessions: + self.event_id.session_ids.unlink() + self.generate_sessions() + + +class WizardEventSessionHours(models.TransientModel): + _name = "wizard.event.session.hours" + _description = "Hours in wich the sessions will run" + + wizard_event_session_id = fields.Many2one(comodel_name="wizard.event.session") + start_time = fields.Float(required=True) + end_time = fields.Float(required=True) + + # Todo: manage multiday sessions + + @api.constrains("start_time", "end_time") + def _check_zero_duration(self): + for hour in self: + if hour.start_time == hour.end_time: + raise ValidationError(_("There are sessions with no duration!")) + + @api.constrains("start_time", "end_time") + def _check_hour_validity(self): + for hour in self: + if hour.start_time > 23.99 or hour.end_time > 23.99: + raise ValidationError(_("You've entered invalid hours!")) diff --git a/event_session/wizards/wizard_event_session_view.xml b/event_session/wizards/wizard_event_session_view.xml new file mode 100644 index 000000000..5f4eebce1 --- /dev/null +++ b/event_session/wizards/wizard_event_session_view.xml @@ -0,0 +1,71 @@ + + + + + Generate Sessions Wizard + wizard.event.session + form + new + + + event.event + + + +