From adcde261d772f665fcf425453edd557fff80754f Mon Sep 17 00:00:00 2001 From: Roman <72063601+folix-01@users.noreply.github.com> Date: Thu, 4 Jan 2024 12:32:31 +0100 Subject: [PATCH] Notifications heavy refactoring + booking reminder from #130 pr (#135) * Booking notfications refactor + reminders * Some fixes and removed old appIO field (#142) * remove unused field for appIO * fix some logic and typos * Update sms limit * Refactoring * Refactoring * Notifications labels fix (#145) * initial fixes * fix labels * improved email notifications labels and default values * handle missing config * fix labels and translations * fix labels * Revert "initial fixes" This reverts commit cb95522b509a74b83532632762b6470e62de4ddb. * fix translations * fix fieldsets * Refactoring * Update readme * Fix readme * Update schema * Fux AppIO call * Fix AppIO call * Fix AppIO subscription check * Fix AppIO call * Use the logstorage for appio api call * Update notification_sms.py * Update locales * Update locales * Fix notifications supervisor logics * Fix * Update messages * Fix * Fix code * Fix locales * Remove sms max length * Fix * Fix locales * Force booking notification to managers * Turn off the AppIO notifications integration by default * Fix naming * Fix naming * Fix namin g * Update readme * Update readme * typo * version * fix tests * fix tests * cleanup * fix readme + demo profile * locales * zpretty * logging * fix demo + readme * sms_locales * remove unused content rules * rename * add sms notify tests * rename * zpretty * fix notifiche sms move * changelog * black --------- Co-authored-by: Andrea Cecchi Co-authored-by: Mauro Amico --- CHANGES.rst | 17 +- README.rst | 111 +- setup.py | 4 +- .../prenotazioni/adapters/configure.zcml | 22 - .../behaviors/booking_folder/__init__.py | 65 + .../booking_folder/appio/__init__.py | 308 +++++ .../booking_folder/appio/adapters.py | 101 ++ .../booking_folder/appio/configure.zcml | 66 + .../behaviors/booking_folder/appio/events.py | 82 ++ .../appio/notfication_appio_message.py | 98 ++ .../booking_folder/appio/voc_service_keys.py | 33 + .../behaviors/booking_folder/configure.zcml | 26 + .../contacts.py} | 0 .../booking_folder/email/__init__.py | 283 ++++ .../booking_folder/email/adapters.py | 35 + .../booking_folder/email/configure.zcml | 60 + .../behaviors/booking_folder/email/events.py | 114 ++ .../email/notification_email_message.py} | 56 +- .../behaviors/booking_folder/sms/__init__.py | 165 +++ .../behaviors/booking_folder/sms/adapters.py | 31 + .../booking_folder/sms/configure.zcml | 50 + .../behaviors/booking_folder/sms/events.py | 87 ++ .../behaviors/booking_folder/sms/message.py | 68 + .../prenotazioni/behaviors/configure.zcml | 11 +- .../prenotazioni/browser/configure.zcml | 1 + .../prenotazioni/browser/prenotazione_move.py | 3 - .../browser/prenotazioni_context_state.py | 6 +- .../utilities}/__init__.py | 0 .../utilities}/configure.zcml | 10 +- .../utilities/notify_upcoming_bookings.py | 48 + src/redturtle/prenotazioni/configure.zcml | 13 +- .../content/prenotazioni_folder.py | 248 +--- .../prenotazioni/contentrules/__init__.py | 1 - .../prenotazioni/contentrules/configure.zcml | 59 - .../prenotazioni/contentrules/handlers.py | 9 - .../contentrules/sendMovedPrenotazione.py | 194 --- src/redturtle/prenotazioni/events/__init__.py | 9 + .../prenotazioni/events/configure.zcml | 20 +- .../prenotazioni/events/prenotazione.py | 77 -- src/redturtle/prenotazioni/interfaces.py | 32 +- .../{scripts => }/io_tools/README.md | 0 .../{scripts => }/io_tools/__init__.py | 0 .../{scripts => }/io_tools/api.py | 73 +- .../{scripts => }/io_tools/cli.py | 0 .../prenotazioni/{scripts => }/io_tools/io.db | Bin .../{scripts => }/io_tools/io_tools.py | 0 .../{scripts => }/io_tools/monkey.py | 0 .../{scripts => }/io_tools/rdbms.py | 0 .../{scripts => }/io_tools/spec.yaml | 0 .../{scripts => }/io_tools/storage.py | 0 .../en/LC_MESSAGES/redturtle.prenotazioni.po | 1067 ++++++++------- .../it/LC_MESSAGES/redturtle.prenotazioni.po | 1171 ++++++++++------- .../locales/redturtle.prenotazioni.pot | 1071 ++++++++------- src/redturtle/prenotazioni/locales/update.sh | 4 +- .../profiles/default/metadata.xml | 2 +- .../default/types/PrenotazioniFolder.xml | 1 + .../services/booking/notify_about_confirm.py | 11 +- src/redturtle/prenotazioni/scripts/app_io.py | 223 ---- .../scripts/notify_upcoming_bookings.py | 36 + .../prenotazioni/staging/__init__.py | 4 + .../prenotazioni/staging/configure.zcml | 32 + .../prenotazioni/staging/interfaces.py | 6 + .../staging/profiles/default/browserlayer.xml | 6 + .../staging/profiles/default/metadata.xml | 4 + .../profiles/uninstall/browserlayer.xml | 6 + .../prenotazioni/staging/setuphandlers.py | 22 + src/redturtle/prenotazioni/staging/smsdemo.py | 34 + .../tests/test_available_slots.py | 13 +- ...m_by_endoint.py => test_booking_notify.py} | 91 +- ...wser_utilities_notify_upcoming_bookings.py | 193 +++ .../tests/test_delete_booking_api.py | 9 +- .../test_notification_supervisor_utility.py | 160 +++ .../tests/test_prenotazione_events.py | 21 +- src/redturtle/prenotazioni/upgrades.py | 105 +- src/redturtle/prenotazioni/upgrades.zcml | 10 + .../prenotazioni/utilities/__init__.py | 2 + src/redturtle/prenotazioni/utilities/email.py | 18 + .../prenotazioni/utilities/log_errors.py | 18 + src/redturtle/prenotazioni/viewlets/app_io.py | 14 - .../prenotazioni/viewlets/templates/app_io.pt | 33 - .../prenotazioni/vocabularies/tipologies.py | 3 +- test-5.2.x-py27.cfg | 10 - 82 files changed, 4631 insertions(+), 2465 deletions(-) create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/__init__.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/appio/__init__.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/appio/adapters.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/appio/configure.zcml create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/appio/events.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/appio/notfication_appio_message.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/appio/voc_service_keys.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/configure.zcml rename src/redturtle/prenotazioni/behaviors/{booking_folder.py => booking_folder/contacts.py} (100%) create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/email/__init__.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/email/adapters.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/email/configure.zcml create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/email/events.py rename src/redturtle/prenotazioni/{adapters/prenotazione_email_message.py => behaviors/booking_folder/email/notification_email_message.py} (84%) create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/sms/__init__.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/sms/adapters.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/sms/configure.zcml create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/sms/events.py create mode 100644 src/redturtle/prenotazioni/behaviors/booking_folder/sms/message.py rename src/redturtle/prenotazioni/{viewlets => browser/utilities}/__init__.py (100%) rename src/redturtle/prenotazioni/{viewlets => browser/utilities}/configure.zcml (54%) create mode 100644 src/redturtle/prenotazioni/browser/utilities/notify_upcoming_bookings.py delete mode 100644 src/redturtle/prenotazioni/contentrules/__init__.py delete mode 100644 src/redturtle/prenotazioni/contentrules/configure.zcml delete mode 100644 src/redturtle/prenotazioni/contentrules/handlers.py delete mode 100644 src/redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py rename src/redturtle/prenotazioni/{scripts => }/io_tools/README.md (100%) rename src/redturtle/prenotazioni/{scripts => }/io_tools/__init__.py (100%) rename src/redturtle/prenotazioni/{scripts => }/io_tools/api.py (88%) rename src/redturtle/prenotazioni/{scripts => }/io_tools/cli.py (100%) rename src/redturtle/prenotazioni/{scripts => }/io_tools/io.db (100%) rename src/redturtle/prenotazioni/{scripts => }/io_tools/io_tools.py (100%) rename src/redturtle/prenotazioni/{scripts => }/io_tools/monkey.py (100%) rename src/redturtle/prenotazioni/{scripts => }/io_tools/rdbms.py (100%) rename src/redturtle/prenotazioni/{scripts => }/io_tools/spec.yaml (100%) rename src/redturtle/prenotazioni/{scripts => }/io_tools/storage.py (100%) delete mode 100644 src/redturtle/prenotazioni/scripts/app_io.py create mode 100644 src/redturtle/prenotazioni/scripts/notify_upcoming_bookings.py create mode 100644 src/redturtle/prenotazioni/staging/__init__.py create mode 100644 src/redturtle/prenotazioni/staging/configure.zcml create mode 100644 src/redturtle/prenotazioni/staging/interfaces.py create mode 100644 src/redturtle/prenotazioni/staging/profiles/default/browserlayer.xml create mode 100644 src/redturtle/prenotazioni/staging/profiles/default/metadata.xml create mode 100644 src/redturtle/prenotazioni/staging/profiles/uninstall/browserlayer.xml create mode 100644 src/redturtle/prenotazioni/staging/setuphandlers.py create mode 100644 src/redturtle/prenotazioni/staging/smsdemo.py rename src/redturtle/prenotazioni/tests/{test_booking_notify_on_confirm_by_endoint.py => test_booking_notify.py} (50%) create mode 100644 src/redturtle/prenotazioni/tests/test_browser_utilities_notify_upcoming_bookings.py create mode 100644 src/redturtle/prenotazioni/tests/test_notification_supervisor_utility.py create mode 100644 src/redturtle/prenotazioni/utilities/email.py create mode 100644 src/redturtle/prenotazioni/utilities/log_errors.py delete mode 100644 src/redturtle/prenotazioni/viewlets/app_io.py delete mode 100644 src/redturtle/prenotazioni/viewlets/templates/app_io.pt delete mode 100644 test-5.2.x-py27.cfg diff --git a/CHANGES.rst b/CHANGES.rst index 2868ca03..eae1089d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,10 +2,17 @@ Changelog ========= -2.3.3 (unreleased) +2.4.0 (unreleased) ------------------ -- Nothing changed yet. +- Split booking notification gateways to 'App IO', 'Email' and 'SMS' + [folix-01] + +- remove unused contentrules + [mamico] + +- Add booking reminder emails. + [folix-01] 2.3.2 (2024-01-03) @@ -83,6 +90,7 @@ Changelog - Set PrenotazioniFolder and PrenotazioneType as not searchable (types_not_searched). [cekk] + - Send ical also for manager notifications. [cekk] @@ -120,7 +128,7 @@ Changelog - Add booking_refuse_message to Prenotazione stringinterp variables. [folix-01] - + - Extended PrenotaizoniFolder email templates var list. [folix-01] @@ -340,8 +348,9 @@ Changelog - Handle contentrules by the plone events and do not use contentrules anymore. [folix-01] + - Change "day" type in week_table (TODO: need an upgrade step?). - [mauro] + [mamico] 2.0.0.dev2 (2023-06-30) ----------------------- diff --git a/README.rst b/README.rst index 79a81c7f..298d3a39 100644 --- a/README.rst +++ b/README.rst @@ -155,24 +155,27 @@ Managers can confirm a Booking using workflow transitions. The workflow transition triggers an email to be sent to the booker (see below). -Booking event notifications ---------------------------- +Booking Notifications +--------------------- -There are addional automated email be used to notify booking owner when his booking has been created, accepted -or re-scheduled. +There are automated notifications implementend by the following behaviors: -Rules are **NOT automatically** enabled in every Booking Folder. -If you want to send some notification, you only need to enable them from the Booking folder. +* `redturtle.prenotazioni.behavior.notification_appio` (Notify via AppIO gateway) +* `redturtle.prenotazioni.behavior.notification_email` (Notify via Email gateway) +* `redturtle.prenotazioni.behavior.notification_sms` (Notify via SMS gateway) -The rules which are available by default: +Each behavior is implementing the following notification types: +* `booking-accepted` (An notification if the booking had been accepted) +* `booking-moved` (An notification if the booking had been moved) +* `booking-created` (An notification if the booking had been created) +* `booking-refuse` (An notification if the booking had been refused) +* `booking-reminder` (An notification reminder) -* `booking-accepted` (Invia un'email all'utente quando la prenotazione è stata accettata) -* `booking-moved` (Invia un'email all'utente quando la data della prenotazione viene cambiata) -* `booking-created-user` (Invia un'email all'utente quando la prenotazione è stata creata) -* `booking-refuse` (Invia un'email all'utente quando la prenotazione è stata rifiutata) -* `booking-confirm` (Conferma automatica prenotazioni) +Notifications are **NOT automatically** enabled in every Booking Folder. +If you want to send some notification, you only need to enable them by assigning the behavior to PrenotazioniFolder c.t. -You can also use some placeholders that will be replaced with some booking infos. Here is a list: +You can create your own notification templates for the booking events(confirm, refuse, create, delete, reminder). +The temlates are being saved in the PrenotazioniFolder object. The template variables list: @@ -200,6 +203,40 @@ The template variables list: * ``${prenotazioni_folder_title}`` - Booking folder title. * ``${booking_requirements}`` - Related PrenotazioneType.booking_requirements field +Note that the sms can be used only if you implement an own sender adapter +Example: + +You just need to register a new adapter:: + + + +And here the `send` method must be implementend:: + + from zope.component import adapter + from zope.interface import implementer + + from redturtle.prenotazioni.content.prenotazione import IPrenotazione + from redturtle.prenotazioni.interfaces import IBookingNotificationSender + from redturtle.prenotazioni.interfaces import IBookingSMSMessage + from redturtle.prenotazioni.behaviors.booking_folder.sms.adapters import BookingNotificationSender + + + @implementer(IBookingNotificationSender) + @adapter(IBookingSMSMessage5, IPrenotazione, YourAddonLayerInterface) + class CustomSMSSenderAdapter(BookingNotificationSender): + + def send(self): + if self.is_notification_allowed(): + # the message is automatically generated basing on the event type + message = self.message_adapter.message + phone = self.booking.phone + + # Your custom send logics integration below + custom_send_function(message, phone) + Vacations --------- @@ -656,6 +693,54 @@ Example:: Response:: Binary file +@@send-booking-reminders +------------------------ + +This view sends a booking reminder email to all the bookings inside PrenotazioniFolders that +have the Reminder Notification Gap field populated. If you intend to set up a cronjob to call this view, you might use a special script call. +The script is located at src/redturtle/prenotazioni/scripts/notify_upcoming_bookings.py. + + + +Scripts +======= + +notify_upcoming_bookings +------------------------ + +The script is supposed to be used to call the **@@send-booking-reminders** view. +It is supposed to be ran once a day otherwise, duplicate emails will be sent. + +Usage:: + + bin/instance1 -OPlone run bin/notify_upcoming_bookings + +Buildout config example:: + + [buildout] + + parts += + notify-upcoming-bookings + + [notify-upcoming-bookings] + recipe = z3c.recipe.usercrontab + times = 0 3 * * * + command = ${buildout:directory}/bin/notify_upcoming_bookings + + +Behaviors +========= + +redturtle.prenotazioni.behavior.notification_appio +-------------------------------------------------- + +If you mind to use this behavior note that first of all you also need to assign +this **redturtle.prenotazioni.behavior.notification_appio_booking_type** to PrenotazioneType c.t. + +To send the messages via AppIO gateway the **service_code** field defined by **redturtle.prenotazioni.behavior.notification_appio_booking_type** +must be compiled in the PrenotazioniType object. All the possible values of this field are being +taken from the environmennt variables which have the following syntax **REDTURTLE_PRENOTAZIONI_APPIO_KEY_=** + Content-transfer-encoding ========================= diff --git a/setup.py b/setup.py index e1dca4b0..19a9aca0 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ setup( name="redturtle.prenotazioni", - version="2.3.3.dev0", + version="2.4.0.dev0", description="An add-on for Plone", long_description=long_description, # Get more from https://pypi.python.org/pypi?%3Aaction=list_classifiers @@ -66,6 +66,7 @@ # FIXME: se si rimuove il profilo di caching da qui (perchè c'è?), si può togliere anche questo pin # 3.0.0a14 e successive richiedono plone.base che è solo su plone 6 "plone.app.caching>=3.0.0a1", + "bravado", ], extras_require={ "test": [ @@ -91,5 +92,6 @@ [console_scripts] update_locale = redturtle.prenotazioni.locales.update:update_locale app_io = redturtle.prenotazioni.scripts.app_io:main + notify_upcoming_bookings = redturtle.prenotazioni.scripts.notify_upcoming_bookings:main """, ) diff --git a/src/redturtle/prenotazioni/adapters/configure.zcml b/src/redturtle/prenotazioni/adapters/configure.zcml index efe912df..da97a121 100644 --- a/src/redturtle/prenotazioni/adapters/configure.zcml +++ b/src/redturtle/prenotazioni/adapters/configure.zcml @@ -190,27 +190,5 @@ for="redturtle.prenotazioni.content.prenotazione.IPrenotazione" /> - - - - - - - - - - diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/__init__.py b/src/redturtle/prenotazioni/behaviors/booking_folder/__init__.py new file mode 100644 index 00000000..54d75d4f --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/__init__.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +from .appio.adapters import app_io_allowed_for + + +def get_booking_folder_notification_flags(booking_folder): + return { + i: getattr(booking_folder, f"notify_on_{i}", False) + for i in ("confirm", "submit", "refuse") + } + + +class BookingNotificationSupervisorUtility: + """Supervisor to allow/deny the specific + notification type according to business logic""" + + def is_email_message_allowed(self, booking): + if getattr( + booking.getPrenotazioniFolder(), "notifications_email_enabled", False + ) and getattr(booking, "email", None): + return True + + return False + + # NOTE: Will be extended in the future + def is_appio_message_allowed(self, booking): + if not getattr( + booking.getPrenotazioniFolder(), "notifications_appio_enabled", False + ): + return False + + if not booking.fiscalcode: + return False + + return True + + def app_io_allowed_for(sefl, fiscalcode, service_code): + return app_io_allowed_for(fiscalcode, service_code=service_code) + + def is_sms_message_allowed(self, booking): + if not getattr( + booking.getPrenotazioniFolder(), "notifications_sms_enabled", False + ): + return False + + if not booking.phone: + return False + + if self.is_email_message_allowed(booking): + return False + + # if user is potentially notified by App IO, do not send sms + if self.is_appio_message_allowed(booking): + # XXX: questo sarebbe dovuto essere nell'adapter per App IO, ma l'adapter + # richiede a suo volta un message_adapter ... + booking_type = booking.get_booking_type() + service_code = getattr(booking_type, "service_code", None) + fiscalcode = getattr(booking, "fiscalcode", None) + if ( + fiscalcode + and service_code + and self.app_io_allowed_for(fiscalcode, service_code) + ): + return False + + return True diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/appio/__init__.py b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/__init__.py new file mode 100644 index 00000000..64ab14eb --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/__init__.py @@ -0,0 +1,308 @@ +# -*- coding: utf-8 -*- +from plone import api +from plone.autoform.interfaces import IFormFieldProvider +from plone.dexterity.interfaces import IDexterityContent +from plone.supermodel import model +from zope import schema +from zope.component import adapter +from zope.interface import implementer +from zope.interface import provider +from zope.schema.interfaces import IContextAwareDefaultFactory + +from redturtle.prenotazioni import _ + + +@provider(IContextAwareDefaultFactory) +def notify_on_submit_appio_subject_default_factory(context): + return api.portal.translate( + _( + "notify_on_submit_appio_subject_default_value", + "[${prenotazioni_folder_title}] Booking created", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_submit_appio_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_submit_appio_message_default_value", + "Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.

You can see details and print a reminder following this [${booking_print_url}](link).", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_confirm_appio_subject_default_factory(context): + return api.portal.translate( + _( + "notify_on_confirm_appio_subject_default_value", + "[${prenotazioni_folder_title}] Booking of ${booking_date} at ${booking_time} was accepted", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_confirm_appio_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_confirm_appio_message_default_value", + "The booking ${booking_type} for ${title} has been confirmed." + "

You can see details and print a reminder following this [link](${booking_print_url}).", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_move_appio_subject_default_factory(context): + return api.portal.translate( + _( + "notify_on_move_appio_subject_default_value", + "[${prenotazioni_folder_title}] Booking date modified for ${title}", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_move_appio_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_move_appio_message_default_value", + "The booking scheduling for ${booking_type} was modified." + "

The new one is on ${booking_date} at ${booking_time}." + "

You can see details and print a reminder following this [link](${booking_print_url}).", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_refuse_appio_subject_default_factory(context): + return api.portal.translate( + _( + "notify_on_refuse_appio_subject_default_value", + "[${prenotazioni_folder_title}] Booking refused for ${title}", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_refuse_appio_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_refuse_appio_message_default_value", + "The booking ${booking_type} of ${booking_date} at ${booking_time} was refused.", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_as_reminder_appio_subject_default_factory(context): + return api.portal.translate( + _( + "notify_as_reminder_appio_subject_default_value", + "[${prenotazioni_folder_title}] Booking reminder on ${booking_date}", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_as_reminder_appio_message_default_factory(context): + return api.portal.translate( + _( + "notify_as_reminder_appio_message_default_value", + "This is an automatic reminder about your booking on ${date} for ${booking_type}." + "

You can see details and print a reminder following this [link](${booking_print_url}).", + ) + ) + + +@provider(IFormFieldProvider) +class INotificationAppIO(model.Schema): + notifications_appio_enabled = schema.Bool( + title=_("notifications_appio_enabled_label", default="AppIO notifications"), + description=_( + "notifications_appio_enabled_help", + default="Enable AppIO notifications.", + ), + default=False, + required=False, + ) + notify_on_submit_appio_subject = schema.TextLine( + title=_( + "notify_on_submit_subject", + default="[Created] subject", + ), + description=_( + "notify_on_submit_subject_help", + default="The message subject when a booking has been created.", + ), + defaultFactory=notify_on_submit_appio_subject_default_factory, + required=False, + ) + notify_on_submit_appio_message = schema.Text( + title=_( + "notify_on_submit_message", + default="[Created] message", + ), + description=_( + "notify_on_submit_message_help", + default="The message text when a booking has been created.", + ), + defaultFactory=notify_on_submit_appio_message_default_factory, + required=False, + ) + notify_on_confirm_appio_subject = schema.Text( + title=_( + "notify_on_confirm_subject", + default="[Confirm] subject", + ), + description=_( + "notify_on_confirm_subject_help", + default="The message subject when a booking has been confirmed.", + ), + defaultFactory=notify_on_confirm_appio_subject_default_factory, + required=False, + ) + notify_on_confirm_appio_message = schema.Text( + title=_( + "notify_on_confirm_message", + default="[Confirmed] message", + ), + description=_( + "notify_on_confirm_message_help", + default="The message text when a booking has been confirmed.", + ), + defaultFactory=notify_on_confirm_appio_message_default_factory, + required=False, + ) + notify_on_move_appio_subject = schema.Text( + title=_( + "notify_on_move_subject", + default="[Move] subject", + ), + description=_( + "notify_on_move_subject_help", + default="The message subject when a booking has been moved.", + ), + defaultFactory=notify_on_move_appio_subject_default_factory, + required=False, + ) + notify_on_move_appio_message = schema.Text( + title=_( + "notify_on_move_message", + default="[Move] message", + ), + description=_( + "notify_on_move_message_help", + default="The message text when a booking has been moved.", + ), + defaultFactory=notify_on_move_appio_message_default_factory, + required=False, + ) + notify_on_refuse_appio_subject = schema.Text( + title=_( + "notify_on_refuse_subject", + default="[Refuse] subject", + ), + description=_( + "notify_on_refuse_subject_help", + default="The message subject when a booking has been refused.", + ), + defaultFactory=notify_on_refuse_appio_subject_default_factory, + required=False, + ) + notify_on_refuse_appio_message = schema.Text( + title=_( + "notify_on_refuse_message", + default="[Refuse] message", + ), + description=_( + "notify_on_refuse_message_help", + default="The message text when a booking has been refused.", + ), + defaultFactory=notify_on_refuse_appio_message_default_factory, + required=False, + ) + notify_as_reminder_appio_subject = schema.Text( + title=_( + "notify_as_reminder_subject", + default="[Reminder] subject", + ), + description=_( + "notify_as_reminder_appio_subject_help", + default="The message subject when a reminder will be sent.", + ), + defaultFactory=notify_as_reminder_appio_subject_default_factory, + required=False, + ) + notify_as_reminder_appio_message = schema.Text( + title=_( + "notify_as_reminder_message", + default="[Reminder] message", + ), + description=_( + "notify_as_reminder_message_help", + default="The message text when a reminder will be sent.", + ), + defaultFactory=notify_as_reminder_appio_message_default_factory, + required=False, + ) + + model.fieldset( + "appio_notifications", + label=_( + "bookings_appio_templates_label", + default="AppIO Notifications", + ), + description=_( + "bookings_appio_templates_help", + default="Set message text for all available notification events.", + ), + fields=[ + "notifications_appio_enabled", + "notify_on_submit_appio_subject", + "notify_on_submit_appio_message", + "notify_on_confirm_appio_subject", + "notify_on_confirm_appio_message", + "notify_on_move_appio_subject", + "notify_on_move_appio_message", + "notify_on_refuse_appio_subject", + "notify_on_refuse_appio_message", + "notify_as_reminder_appio_subject", + "notify_as_reminder_appio_message", + ], + ) + + +@implementer(INotificationAppIO) +@adapter(IDexterityContent) +class NotificationAppIO(object): + """ """ + + def __init__(self, context): + self.context = context + + +@provider(IFormFieldProvider) +class INotificationAppioBookingType(model.Schema): + service_code = schema.Choice( + title=_( + "service_code_label", + default="AppIO service code.", + ), + description=_( + "service_code_help", + default="AppIO service code related to the current booking type", + ), + required=False, + vocabulary="redturtle.prenotazioni.appio_services", + ) + + +@implementer(INotificationAppioBookingType) +@adapter(IDexterityContent) +class NotificationAppIOBookingType(object): + """ """ + + def __init__(self, context): + self.context = context diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/appio/adapters.py b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/adapters.py new file mode 100644 index 00000000..73e79b40 --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/adapters.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +import os + +from zope.component import adapter +from zope.component import getUtility +from zope.interface import implementer + +from redturtle.prenotazioni import logger +from redturtle.prenotazioni.content.prenotazione import IPrenotazione +from redturtle.prenotazioni.interfaces import IBookingAPPIoMessage +from redturtle.prenotazioni.interfaces import IBookingNotificationSender +from redturtle.prenotazioni.interfaces import IBookingNotificatorSupervisorUtility +from redturtle.prenotazioni.interfaces import IRedturtlePrenotazioniLayer +from redturtle.prenotazioni.io_tools.api import Api +from redturtle.prenotazioni.io_tools.storage import logstorage + + +# TODO: ramcache ? +def app_io_allowed_for(fiscalcode, service_code): + """Check if the user is allowed to receive App IO notifications for the given service code""" + if not fiscalcode: + return False + + if not service_code: + return False + + api_key = os.environ.get(service_code) + if not api_key: + logger.warning("No App IO API key found for service code %s", service_code) + return False + + api = Api(secret=api_key) + return api.is_service_activated(fiscalcode) + + +@implementer(IBookingNotificationSender) +@adapter(IBookingAPPIoMessage, IPrenotazione, IRedturtlePrenotazioniLayer) +class BookingTransitionAPPIoSender: + def __init__(self, message_adapter, booking, request) -> None: + self.message_adapter = message_adapter + self.booking = booking + self.request = request + + def send(self) -> bool: + supervisor = getUtility(IBookingNotificatorSupervisorUtility) + if supervisor.is_appio_message_allowed(self.booking): + message = self.message_adapter.message + subject = self.message_adapter.subject + booking_type = self.booking.get_booking_type() + service_code = getattr(booking_type, "service_code", None) + + if not self.booking.fiscalcode: + logger.warning( + "No fiscal code found for booking %s", self.booking.UID() + ) + return False + + if not service_code: + logger.warning( + "No App IO service code found for booking type %s", booking_type + ) + return False + + api_key = os.environ.get(service_code) + if not api_key: + logger.warning( + "No App IO API key found for service code %s booking type %s", + service_code, + booking_type, + ) + return False + + api = Api(secret=api_key, storage=logstorage) + + # XXX: qui si usa supervisor perchè nei test c'è un mock su questo + # if not api.is_service_activated(self.booking.fiscalcode): + if not supervisor.app_io_allowed_for(self.booking.fiscalcode, service_code): + logger.info( + "App IO service %s is not activated for fiscal code %s", + service_code, + self.booking.fiscalcode, + ) + return False + + msgid = api.send_message( + fiscal_code=self.booking.fiscalcode, + subject=subject, + body=message, + ) + + if not msgid: + logger.error("Could not send notification via AppIO gateway") + return False + + logger.info( + "Sent the notification <%s>(`%s`) via AppIO gateway, id returned: %s", + self.booking.UID(), + subject, + msgid, + ) + return True diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/appio/configure.zcml b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/configure.zcml new file mode 100644 index 00000000..973c1dc4 --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/configure.zcml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/appio/events.py b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/events.py new file mode 100644 index 00000000..77a0fd87 --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/events.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- + +from zope.component import getMultiAdapter +from zope.globalrequest import getRequest + +from redturtle.prenotazioni.interfaces import IBookingAPPIoMessage +from redturtle.prenotazioni.interfaces import IBookingNotificationSender +from redturtle.prenotazioni.utilities import handle_exception_by_log + +from . import INotificationAppIO + + +def booking_folder_provides_current_behavior(booking): + return INotificationAppIO.providedBy(booking.getPrenotazioniFolder()) + + +@handle_exception_by_log +def send_notification_on_transition(context, event) -> None: + if not booking_folder_provides_current_behavior(context): + return + + booking_folder = context.getPrenotazioniFolder() + flags = booking_folder.get_notification_flags() + + if flags["confirm"] and getattr(booking_folder, "auto_confirm", False): + flags["submit"] = False + + if event.transition and flags.get(event.transition.__name__): + message_adapter = getMultiAdapter( + (context, event), + IBookingAPPIoMessage, + ) + + if message_adapter and message_adapter.message: + sender_adapter = getMultiAdapter( + (message_adapter, context, getRequest()), + IBookingNotificationSender, + name="booking_transition_appio_sender", + ) + sender_adapter.send() + + +@handle_exception_by_log +def notify_on_move(context, event): + if not booking_folder_provides_current_behavior(context): + return + + booking_folder = context.getPrenotazioniFolder() + if not getattr(booking_folder, "notify_on_move", False): + return + + message_adapter = getMultiAdapter( + (context, event), + IBookingAPPIoMessage, + ) + if message_adapter and message_adapter.message: + sender_adapter = getMultiAdapter( + (message_adapter, context, getRequest()), + IBookingNotificationSender, + name="booking_transition_appio_sender", + ) + sender_adapter.send() + + +@handle_exception_by_log +def send_booking_reminder(context, event): + if not booking_folder_provides_current_behavior(context): + return + + message_adapter = getMultiAdapter( + (context, event), + IBookingAPPIoMessage, + name="reminder_notification_appio_message", + ) + + if message_adapter and message_adapter.message: + sender_adapter = getMultiAdapter( + (message_adapter, context, getRequest()), + IBookingNotificationSender, + name="booking_transition_appio_sender", + ) + sender_adapter.send() diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/appio/notfication_appio_message.py b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/notfication_appio_message.py new file mode 100644 index 00000000..7d962aba --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/notfication_appio_message.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +"""AppIO notification templates""" + +from plone.stringinterp.interfaces import IContextWrapper +from plone.stringinterp.interfaces import IStringInterpolator +from Products.DCWorkflow.interfaces import IAfterTransitionEvent +from zope.component import adapter +from zope.interface import implementer + +from redturtle.prenotazioni.content.prenotazione import IPrenotazione +from redturtle.prenotazioni.interfaces import IBookingAPPIoMessage +from redturtle.prenotazioni.interfaces import IBookingReminderEvent +from redturtle.prenotazioni.prenotazione_event import IMovedPrenotazione + + +class PrenotazioneAPPIoMessage: + prenotazione = None + event = None + + def __init__(self, prenotazione, event): + self.prenotazione = prenotazione + self.event = event + + @property + def message(self) -> str: + NotImplementedError + + +@implementer(IBookingAPPIoMessage) +@adapter(IPrenotazione, IMovedPrenotazione) +class PrenotazioneMovedAPPIoMessage(PrenotazioneAPPIoMessage): + @property + def message(self) -> str: + return IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + "notify_on_move_appio_message", + None, + ) + ) + + @property + def subject(self) -> str: + return IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + "notify_on_move_appio_subject", + "", + ) + ) + + +@implementer(IBookingAPPIoMessage) +@adapter(IPrenotazione, IAfterTransitionEvent) +class PrenotazioneAfterTransitionAPPIoMessage(PrenotazioneAPPIoMessage): + @property + def message(self) -> str: + return IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + f"notify_on_{self.event.transition and self.event.transition.__name__}_appio_message", + None, + ) + ) + + @property + def subject(self) -> str: + return IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + f"notify_on_{self.event.transition and self.event.transition.__name__}_appio_subject", + None, + ) + ) + + +@implementer(IBookingAPPIoMessage) +@adapter(IPrenotazione, IBookingReminderEvent) +class PrenotazioneReminderAppIOMessage(PrenotazioneAPPIoMessage): + @property + def message(self) -> str: + return IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + "notify_as_reminder_appio_message", + "", + ) + ) + + @property + def subject(self) -> str: + return IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + "notify_as_reminder_appio_subject", + "", + ) + ) diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/appio/voc_service_keys.py b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/voc_service_keys.py new file mode 100644 index 00000000..597b3175 --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/appio/voc_service_keys.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +import os +import re + +from zope.interface import implementer +from zope.schema.interfaces import IVocabularyFactory +from zope.schema.vocabulary import SimpleTerm +from zope.schema.vocabulary import SimpleVocabulary + + +@implementer(IVocabularyFactory) +class VocPrenotazioneTypeGatesFactory(object): + """ """ + + def __call__(self, context): + terms = [] + + myPattern = re.compile(r"REDTURTLE_PRENOTAZIONI_APPIO_KEY_\w+") + + for key in os.environ.keys(): + if myPattern.match(key): + terms.append( + SimpleTerm( + value=key, + token=key, + title=key.replace("REDTURTLE_PRENOTAZIONI_APPIO_KEY_", ""), + ) + ) + + return SimpleVocabulary(terms) + + +VocPrenotazioneTypeGatesFactory = VocPrenotazioneTypeGatesFactory() diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/configure.zcml b/src/redturtle/prenotazioni/behaviors/booking_folder/configure.zcml new file mode 100644 index 00000000..18a0aed6 --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/configure.zcml @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder.py b/src/redturtle/prenotazioni/behaviors/booking_folder/contacts.py similarity index 100% rename from src/redturtle/prenotazioni/behaviors/booking_folder.py rename to src/redturtle/prenotazioni/behaviors/booking_folder/contacts.py diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/email/__init__.py b/src/redturtle/prenotazioni/behaviors/booking_folder/email/__init__.py new file mode 100644 index 00000000..c1995c9e --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/email/__init__.py @@ -0,0 +1,283 @@ +# -*- coding: utf-8 -*- +from plone import api +from plone.autoform.interfaces import IFormFieldProvider +from plone.dexterity.interfaces import IDexterityContent +from plone.supermodel import model +from zope import schema +from zope.component import adapter +from zope.interface import implementer +from zope.interface import provider +from zope.schema.interfaces import IContextAwareDefaultFactory + +from redturtle.prenotazioni import _ + + +@provider(IContextAwareDefaultFactory) +def notify_on_submit_subject_default_factory(context): + return api.portal.translate( + _( + "notify_on_submit_subject_default_value", + "[${prenotazioni_folder_title}] Booking created", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_submit_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_submit_message_default_value", + "Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.

You can see details and print a reminder following this link.", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_confirm_subject_default_factory(context): + return api.portal.translate( + _( + "notify_on_confirm_subject_default_value", + "[${prenotazioni_folder_title}] Booking of ${booking_date} at ${booking_time} was accepted", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_confirm_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_confirm_message_default_value", + "The booking ${booking_type} for ${title} has been confirmed." + "

You can see details and print a reminder following this link.", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_move_subject_default_factory(context): + return api.portal.translate( + _( + "notify_on_move_subject_default_value", + "[${prenotazioni_folder_title}] Booking date modified for ${title}", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_move_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_move_message_default_value", + "The booking scheduling for ${booking_type} was modified." + "

The new one is on ${booking_date} at ${booking_time}." + "

You can see details and print a reminder following this link.", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_refuse_subject_default_factory(context): + return api.portal.translate( + _( + "notify_on_refuse_subject_default_value", + "[${prenotazioni_folder_title}] Booking refused for ${title}", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_refuse_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_refuse_message_default_value", + "The booking ${booking_type} of ${booking_date} at ${booking_time} was refused.", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_as_reminder_subject_default_factory(context): + return api.portal.translate( + _( + "notify_as_reminder_subject_default_value", + "[${prenotazioni_folder_title}] Booking reminder on ${booking_date}", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_as_reminder_message_default_factory(context): + return api.portal.translate( + _( + "notify_as_reminder_message_default_value", + "This is an automatic reminder about your booking on ${date} for ${booking_type}." + "

You can see details and print a reminder following this link.", + ) + ) + + +@provider(IFormFieldProvider) +class INotificationEmail(model.Schema): + notifications_email_enabled = schema.Bool( + title=_("notifications_email_enabled_label", default="Email notifications"), + description=_( + "notifications_email_enabled_help", + default="Enable Email notifications.", + ), + default=True, + required=False, + ) + notify_on_submit_subject = schema.TextLine( + title=_( + "notify_on_submit_subject", + default="[Created] subject", + ), + description=_( + "notify_on_submit_subject_help", + default="The message subject when a booking has been created.", + ), + defaultFactory=notify_on_submit_subject_default_factory, + required=False, + ) + notify_on_submit_message = schema.Text( + title=_( + "notify_on_submit_message", + default="[Created] message", + ), + description=_( + "notify_on_submit_message_help", + default="The message text when a booking has been created.", + ), + defaultFactory=notify_on_submit_message_default_factory, + required=False, + ) + notify_on_confirm_subject = schema.TextLine( + title=_( + "notify_on_confirm_subject", + default="[Confirm] subject", + ), + description=_( + "notify_on_confirm_subject_help", + default="The message subject when a booking has been confirmed.", + ), + defaultFactory=notify_on_confirm_subject_default_factory, + required=False, + ) + notify_on_confirm_message = schema.Text( + title=_( + "notify_on_confirm_message", + default="[Confirmed] message", + ), + description=_( + "notify_on_confirm_message_help", + default="The message text when a booking has been confirmed.", + ), + defaultFactory=notify_on_confirm_message_default_factory, + required=False, + ) + notify_on_move_subject = schema.TextLine( + title=_( + "notify_on_move_subject", + default="[Move] subject", + ), + description=_( + "notify_on_move_subject_help", + default="The message subject when a booking has been moved.", + ), + defaultFactory=notify_on_move_subject_default_factory, + required=False, + ) + notify_on_move_message = schema.Text( + title=_( + "notify_on_move_message", + default="[Move] message", + ), + description=_( + "notify_on_move_message_help", + default="The message text when a booking has been moved.", + ), + defaultFactory=notify_on_move_message_default_factory, + required=False, + ) + notify_on_refuse_subject = schema.TextLine( + title=_( + "notify_on_refuse_subject", + default="[Refuse] subject", + ), + description=_( + "notify_on_refuse_subject_help", + default="The message subject when a booking has been refused.", + ), + defaultFactory=notify_on_refuse_subject_default_factory, + required=False, + ) + notify_on_refuse_message = schema.Text( + title=_( + "notify_on_refuse_message", + default="[Refuse] message", + ), + description=_( + "notify_on_refuse_message_help", + default="The message text when a booking has been refused.", + ), + defaultFactory=notify_on_refuse_message_default_factory, + required=False, + ) + notify_as_reminder_subject = schema.TextLine( + title=_( + "notify_as_reminder_subject", + default="[Reminder] subject", + ), + description=_( + "notify_as_reminder_subject_help", + default="The message subject when a reminder will be sent.", + ), + defaultFactory=notify_as_reminder_subject_default_factory, + required=False, + ) + notify_as_reminder_message = schema.Text( + title=_( + "notify_as_reminder_message", + default="[Reminder] message", + ), + description=_( + "notify_as_reminder_message_help", + default="The message text when a reminder will be sent.", + ), + defaultFactory=notify_as_reminder_message_default_factory, + required=False, + ) + + model.fieldset( + "email_notifications", + label=_( + "bookings_email_templates_label", + default="Email Notifications", + ), + description=_( + "bookings_email_templates_help", + default="Set message text for all available notification events.", + ), + fields=[ + "notifications_email_enabled", + "notify_on_submit_subject", + "notify_on_submit_message", + "notify_on_confirm_subject", + "notify_on_confirm_message", + "notify_on_move_subject", + "notify_on_move_message", + "notify_on_refuse_subject", + "notify_on_refuse_message", + "notify_as_reminder_subject", + "notify_as_reminder_message", + ], + ) + + +@implementer(INotificationEmail) +@adapter(IDexterityContent) +class NotificationEmail(object): + """ """ + + def __init__(self, context): + self.context = context diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/email/adapters.py b/src/redturtle/prenotazioni/behaviors/booking_folder/email/adapters.py new file mode 100644 index 00000000..3375e3dd --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/email/adapters.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +from zope.component import adapter +from zope.component import getUtility +from zope.interface import implementer + +from redturtle.prenotazioni import logger +from redturtle.prenotazioni.content.prenotazione import IPrenotazione +from redturtle.prenotazioni.interfaces import IBookingEmailMessage +from redturtle.prenotazioni.interfaces import IBookingNotificationSender +from redturtle.prenotazioni.interfaces import IBookingNotificatorSupervisorUtility +from redturtle.prenotazioni.interfaces import IRedturtlePrenotazioniLayer +from redturtle.prenotazioni.utilities import send_email + + +@implementer(IBookingNotificationSender) +@adapter(IBookingEmailMessage, IPrenotazione, IRedturtlePrenotazioniLayer) +class BookingTransitionEmailSender: + def __init__(self, message_adapter, booking, request) -> None: + self.message_adapter = message_adapter + self.booking = booking + self.request = request + + def send(self, force=False): + message = self.message_adapter.message + + if force or getUtility( + IBookingNotificatorSupervisorUtility + ).is_email_message_allowed(self.booking): + logger.debug( + f"Sending the notification <{self.booking.UID()}>(`{message}`) via Email gateway" + ) + logger.info( + f"Sending the notification <{self.booking.UID()}> via Email gateway" + ) + send_email(message) diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/email/configure.zcml b/src/redturtle/prenotazioni/behaviors/booking_folder/email/configure.zcml new file mode 100644 index 00000000..2029e6c0 --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/email/configure.zcml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/email/events.py b/src/redturtle/prenotazioni/behaviors/booking_folder/email/events.py new file mode 100644 index 00000000..84cd645f --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/email/events.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- + +from zope.component import getMultiAdapter +from zope.globalrequest import getRequest + +from redturtle.prenotazioni import is_migration +from redturtle.prenotazioni.interfaces import IBookingEmailMessage +from redturtle.prenotazioni.interfaces import IBookingNotificationSender +from redturtle.prenotazioni.utilities import handle_exception_by_log + +from . import INotificationEmail + + +def booking_folder_provides_current_behavior(booking): + return INotificationEmail.providedBy(booking.getPrenotazioniFolder()) + + +@handle_exception_by_log +def send_email_notification_on_transition(context, event) -> None: + if not booking_folder_provides_current_behavior(context): + return + + booking_folder = context.getPrenotazioniFolder() + flags = booking_folder.get_notification_flags() + + if flags["confirm"] and getattr(booking_folder, "auto_confirm", False): + flags["submit"] = False + + if flags.get( + event.transition and event.transition.__name__ or "", + False, + ): + if not getattr(context, "email", ""): + # booking does not have an email set + return + message_adapter = getMultiAdapter( + (context, event), + IBookingEmailMessage, + ) + + if message_adapter and message_adapter.message: + sender_adapter = getMultiAdapter( + (message_adapter, context, getRequest()), + IBookingNotificationSender, + name="booking_transition_email_sender", + ) + sender_adapter.send() + + +# TODO: use the notify_on_after_transition_event method techique instead +@handle_exception_by_log +def notify_on_move(context, event): + if not booking_folder_provides_current_behavior(context): + return + + booking_folder = context.getPrenotazioniFolder() + if not getattr(booking_folder, "notify_on_move", False): + return + if not getattr(context, "email", ""): + # booking does not have an email set + return + message_adapter = getMultiAdapter((context, event), IBookingEmailMessage) + sender_adapter = getMultiAdapter( + (message_adapter, context, getRequest()), + IBookingNotificationSender, + name="booking_transition_email_sender", + ) + + sender_adapter.send() + + +@handle_exception_by_log +def send_booking_reminder(context, event): + if not booking_folder_provides_current_behavior(context): + return + + message_adapter = getMultiAdapter( + (context, event), + IBookingEmailMessage, + name="reminder_notification_email_message", + ) + sender_adapter = getMultiAdapter( + (message_adapter, context, getRequest()), + IBookingNotificationSender, + name="booking_transition_email_sender", + ) + + sender_adapter.send() + + +@handle_exception_by_log +def send_email_to_managers(booking, event): + if not booking_folder_provides_current_behavior(booking): + return + + # skip email for vacation/out-of-office + if is_migration(): + return + + if booking.isVacation(): + return + if not getattr(booking, "email_responsabile", []): + return + + message_adapter = getMultiAdapter( + (booking, event), IBookingEmailMessage, name="notify_manager" + ) + sender_adapter = getMultiAdapter( + (message_adapter, booking, getRequest()), + IBookingNotificationSender, + name="booking_transition_email_sender", + ) + + sender_adapter.send(force=True) diff --git a/src/redturtle/prenotazioni/adapters/prenotazione_email_message.py b/src/redturtle/prenotazioni/behaviors/booking_folder/email/notification_email_message.py similarity index 84% rename from src/redturtle/prenotazioni/adapters/prenotazione_email_message.py rename to src/redturtle/prenotazioni/behaviors/booking_folder/email/notification_email_message.py index 84b1341d..aafc3545 100644 --- a/src/redturtle/prenotazioni/adapters/prenotazione_email_message.py +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/email/notification_email_message.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -"""In this module we implemented the booking email templates which were used - by plone contenttrules in previous verisions of the package""" +"""Email notification templates""" import os from email.charset import Charset @@ -22,13 +21,14 @@ from redturtle.prenotazioni import logger from redturtle.prenotazioni.content.prenotazione import IPrenotazione -from redturtle.prenotazioni.interfaces import IPrenotazioneEmailMessage +from redturtle.prenotazioni.interfaces import IBookingEmailMessage +from redturtle.prenotazioni.interfaces import IBookingReminderEvent from redturtle.prenotazioni.prenotazione_event import IMovedPrenotazione CTE = os.environ.get("MAIL_CONTENT_TRANSFER_ENCODING", None) -class PrenotazioneEventEmailMessage: +class PrenotazioneEmailMessage: prenotazione = None event = None @@ -100,10 +100,10 @@ def message(self, *args, **kwargs): return message -@implementer(IPrenotazioneEmailMessage) +@implementer(IBookingEmailMessage) @adapter(IPrenotazione, IMovedPrenotazione) class PrenotazioneMovedICalEmailMessage( - PrenotazioneEventMessageICalMixIn, PrenotazioneEventEmailMessage + PrenotazioneEventMessageICalMixIn, PrenotazioneEmailMessage ): @property def message_subject(self) -> str: @@ -132,9 +132,9 @@ def message_text(self) -> MIMEText: return MIMEText(text, "html") -@implementer(IPrenotazioneEmailMessage) +@implementer(IBookingEmailMessage) @adapter(IPrenotazione, IAfterTransitionEvent) -class PrenotazioneAfterTransitionEmailMessage(PrenotazioneEventEmailMessage): +class PrenotazioneAfterTransitionEmailMessage(PrenotazioneEmailMessage): @property def message_subject(self) -> str: return IStringInterpolator(IContextWrapper(self.prenotazione)())( @@ -162,7 +162,7 @@ def message_text(self) -> MIMEText: return MIMEText(text, "html") -@implementer(IPrenotazioneEmailMessage) +@implementer(IBookingEmailMessage) @adapter(IPrenotazione, IAfterTransitionEvent) class PrenotazioneAfterTransitionEmailICalMessage( PrenotazioneEventMessageICalMixIn, PrenotazioneAfterTransitionEmailMessage @@ -170,9 +170,11 @@ class PrenotazioneAfterTransitionEmailICalMessage( pass -@implementer(IPrenotazioneEmailMessage) +@implementer(IBookingEmailMessage) @adapter(IPrenotazione, IObjectAddedEvent) -class PrenotazioneManagerEmailMessage(PrenotazioneEventEmailMessage): +class PrenotazioneManagerEmailMessage( + PrenotazioneEventMessageICalMixIn, PrenotazioneEmailMessage +): def __init__(self, prenotazione, event): super().__init__(prenotazione=prenotazione, event=event) @@ -222,7 +224,7 @@ def message_subject(self) -> str: return subject """ booking_type = getattr(self.prenotazione, "booking_type", "") - booking_code = getattr(self.prenotazione, "booking_code", "") + booking_code = self.prenotazione.getBookingCode() date = self.prenotazione.booking_date.strftime("%d-%m-%Y %H:%M") return f"[{booking_type}] {date} {booking_code}" @@ -267,3 +269,33 @@ def message_text(self) -> MIMEText: return MIMEText(text, "html", cs) else: return MIMEText(text, "html") + + +@implementer(IBookingEmailMessage) +@adapter(IPrenotazione, IBookingReminderEvent) +class PrenotazioneReminderEmailMessage(PrenotazioneEmailMessage): + @property + def message_subject(self) -> str: + return IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + "notify_as_reminder_subject", + "", + ) + ) + + @property + def message_text(self) -> MIMEText: + text = IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + "notify_as_reminder_message", + None, + ), + ) + if CTE: + cs = Charset("utf-8") + cs.body_encoding = CTE # e.g. 'base64' + return MIMEText(text, "html", cs) + else: + return MIMEText(text, "html") diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/sms/__init__.py b/src/redturtle/prenotazioni/behaviors/booking_folder/sms/__init__.py new file mode 100644 index 00000000..0614db08 --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/sms/__init__.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +from plone import api +from plone.autoform.interfaces import IFormFieldProvider +from plone.dexterity.interfaces import IDexterityContent +from plone.supermodel import model +from zope import schema +from zope.component import adapter +from zope.interface import implementer +from zope.interface import provider +from zope.schema.interfaces import IContextAwareDefaultFactory + +from redturtle.prenotazioni import _ + + +@provider(IContextAwareDefaultFactory) +def notify_on_submit_sms_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_submit_sms_message_default_value", + "[${prenotazioni_folder_title}]: Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.\nSee details or delete it: ${booking_print_url}.", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_confirm_sms_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_confirm_sms_message_default_value", + "[${prenotazioni_folder_title}]: Booking of ${booking_date} at ${booking_time} has been accepted.\nSee details or delete it: ${booking_print_url}.", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_move_sms_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_move_sms_message_default_value", + "[${prenotazioni_folder_title}]: The booking scheduling for ${booking_type} was modified.\nThe new one is on ${booking_date} at ${booking_time}.\nSee details or delete it: ${booking_print_url}.", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_on_refuse_sms_message_default_factory(context): + return api.portal.translate( + _( + "notify_on_refuse_sms_message_default_value", + "[${prenotazioni_folder_title}]: The booking ${booking_type} of ${booking_date} at ${booking_time} was refused.", + ) + ) + + +@provider(IContextAwareDefaultFactory) +def notify_as_reminder_sms_message_default_factory(context): + return api.portal.translate( + _( + "notify_as_reminder_sms_message_default_value", + "[${prenotazioni_folder_title}]: This is an automatic reminder about your booking on ${date} for ${booking_type}." + "\nSee details or delete it: ${booking_print_url}.", + ) + ) + + +@provider(IFormFieldProvider) +class INotificationSMS(model.Schema): + notifications_sms_enabled = schema.Bool( + title=_("notifications_sms_enabled_label", default="SMS notifications"), + description=_( + "notifications_sms_enabled_help", + default="Enable SMS notifications.", + ), + default=False, + required=False, + ) + notify_on_submit_sms_message = schema.Text( + title=_( + "notify_on_submit_message", + default="[Created] message", + ), + description=_( + "notify_on_submit_message_help", + default="The message text when a booking has been created.", + ), + defaultFactory=notify_on_submit_sms_message_default_factory, + required=False, + ) + notify_on_confirm_sms_message = schema.Text( + title=_( + "notify_on_confirm_message", + default="[Confirmed] message", + ), + description=_( + "notify_on_confirm_message_help", + default="The message text when a booking has been confirmed.", + ), + defaultFactory=notify_on_confirm_sms_message_default_factory, + required=False, + ) + notify_on_move_sms_message = schema.Text( + title=_( + "notify_on_move_message", + default="[Move] message", + ), + description=_( + "notify_on_move_message_help", + default="The message text when a booking has been moved.", + ), + defaultFactory=notify_on_move_sms_message_default_factory, + required=False, + ) + notify_on_refuse_sms_message = schema.Text( + title=_( + "notify_on_refuse_message", + default="[Refuse] message", + ), + description=_( + "notify_on_refuse_message_help", + default="The message text when a booking has been refused.", + ), + defaultFactory=notify_on_refuse_sms_message_default_factory, + required=False, + ) + notify_as_reminder_sms_message = schema.Text( + title=_( + "notify_as_reminder_message", + default="[Reminder] message", + ), + description=_( + "notify_as_reminder_message_help", + default="The message text when a reminder will be sent.", + ), + defaultFactory=notify_as_reminder_sms_message_default_factory, + required=False, + ) + + model.fieldset( + "sms_notifications", + label=_( + "bookings_sms_templates_label", + default="SMS Notifications", + ), + description=_( + "bookings_sms_templates_help", + default="Set message text for all available notification events. Remember that SMS has a 160 characters limit. Depending on your gateway service, it can split messages, if you exceed that limit.", + ), + fields=[ + "notifications_sms_enabled", + "notify_on_submit_sms_message", + "notify_on_confirm_sms_message", + "notify_on_move_sms_message", + "notify_on_refuse_sms_message", + "notify_as_reminder_sms_message", + ], + ) + + +@implementer(INotificationSMS) +@adapter(IDexterityContent) +class NotificationSMS(object): + """ """ + + def __init__(self, context): + self.context = context diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/sms/adapters.py b/src/redturtle/prenotazioni/behaviors/booking_folder/sms/adapters.py new file mode 100644 index 00000000..fb734e9d --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/sms/adapters.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- + +from zope.component import adapter +from zope.component import getUtility +from zope.interface import Interface +from zope.interface import implementer + +from redturtle.prenotazioni.content.prenotazione import IPrenotazione +from redturtle.prenotazioni.interfaces import IBookingNotificationSender +from redturtle.prenotazioni.interfaces import IBookingNotificatorSupervisorUtility +from redturtle.prenotazioni.interfaces import IBookingSMSMessage + + +@implementer(IBookingNotificationSender) +@adapter(IBookingSMSMessage, IPrenotazione, Interface) +class BookingNotificationSender: + def __init__(self, message_adapter, booking, request) -> None: + self.message_adapter = message_adapter + self.booking = booking + self.request = request + + def send(self): + if self.is_notification_allowed(): + raise NotImplementedError("The method was not implemented") + + def is_notification_allowed(self): + if getUtility( + IBookingNotificatorSupervisorUtility, + ).is_sms_message_allowed(self.booking): + return True + return False diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/sms/configure.zcml b/src/redturtle/prenotazioni/behaviors/booking_folder/sms/configure.zcml new file mode 100644 index 00000000..e31f5ee7 --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/sms/configure.zcml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/sms/events.py b/src/redturtle/prenotazioni/behaviors/booking_folder/sms/events.py new file mode 100644 index 00000000..23f4bb4a --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/sms/events.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- + +from zope.component import getMultiAdapter +from zope.globalrequest import getRequest + +from redturtle.prenotazioni.interfaces import IBookingNotificationSender +from redturtle.prenotazioni.interfaces import IBookingSMSMessage +from redturtle.prenotazioni.utilities import handle_exception_by_log + +from . import INotificationSMS + + +def booking_folder_provides_current_behavior(booking): + return INotificationSMS.providedBy(booking.getPrenotazioniFolder()) + + +@handle_exception_by_log +def send_notification_on_transition(context, event) -> None: + if not booking_folder_provides_current_behavior(context): + return + + booking_folder = context.getPrenotazioniFolder() + flags = booking_folder.get_notification_flags() + + if flags["confirm"] and getattr(booking_folder, "auto_confirm", False): + flags["submit"] = False + + if event.transition and flags.get(event.transition.__name__): + if not getattr(context, "phone", ""): + # booking does not have an phone set + return + + message_adapter = getMultiAdapter( + (context, event), + IBookingSMSMessage, + ) + + if message_adapter and message_adapter.message: + sender_adapter = getMultiAdapter( + (message_adapter, context, getRequest()), + IBookingNotificationSender, + name="booking_transition_sms_sender", + ) + sender_adapter.send() + + +@handle_exception_by_log +def notify_on_move(context, event): + if not booking_folder_provides_current_behavior(context): + return + + booking_folder = context.getPrenotazioniFolder() + if not getattr(booking_folder, "notify_on_move", False): + return + # XXX: il controllo immagino sia altrove e deve controllare + # non solo se l'email è presente ma anche se le notifiche email + # sono attive + # if not getattr(context, "email", ""): + # # booking does not have an email set + # return + message_adapter = getMultiAdapter((context, event), IBookingSMSMessage) + if message_adapter and message_adapter.message: + sender_adapter = getMultiAdapter( + (message_adapter, context, getRequest()), + IBookingNotificationSender, + name="booking_transition_sms_sender", + ) + sender_adapter.send() + + +@handle_exception_by_log +def send_booking_reminder(context, event): + if not booking_folder_provides_current_behavior(context): + return + + message_adapter = getMultiAdapter( + (context, event), + IBookingSMSMessage, + name="reminder_notification_sms_message", + ) + if message_adapter and message_adapter.message: + sender_adapter = getMultiAdapter( + (message_adapter, context, getRequest()), + IBookingNotificationSender, + name="booking_transition_sms_sender", + ) + sender_adapter.send() diff --git a/src/redturtle/prenotazioni/behaviors/booking_folder/sms/message.py b/src/redturtle/prenotazioni/behaviors/booking_folder/sms/message.py new file mode 100644 index 00000000..95067fa3 --- /dev/null +++ b/src/redturtle/prenotazioni/behaviors/booking_folder/sms/message.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +"""SMS Notification Templates""" + +from plone.stringinterp.interfaces import IContextWrapper +from plone.stringinterp.interfaces import IStringInterpolator +from Products.DCWorkflow.interfaces import IAfterTransitionEvent +from zope.component import adapter +from zope.interface import implementer + +from redturtle.prenotazioni.content.prenotazione import IPrenotazione +from redturtle.prenotazioni.interfaces import IBookingReminderEvent +from redturtle.prenotazioni.interfaces import IBookingSMSMessage +from redturtle.prenotazioni.prenotazione_event import IMovedPrenotazione + + +class PrenotazioneSMSMessage: + prenotazione = None + event = None + + def __init__(self, prenotazione, event): + self.prenotazione = prenotazione + self.event = event + + @property + def message(self) -> str: + NotImplementedError + + +@implementer(IBookingSMSMessage) +@adapter(IPrenotazione, IMovedPrenotazione) +class PrenotazioneMovedSMSMessage(PrenotazioneSMSMessage): + @property + def message(self) -> str: + return IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + "notify_on_move_sms_message", + None, + ), + ) + + +@implementer(IBookingSMSMessage) +@adapter(IPrenotazione, IAfterTransitionEvent) +class PrenotazioneAfterTransitionSMSMessage(PrenotazioneSMSMessage): + @property + def message(self) -> str: + return IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + f"notify_on_{self.event.transition and self.event.transition.__name__}_sms_message", + None, + ), + ) + + +@implementer(IBookingSMSMessage) +@adapter(IPrenotazione, IBookingReminderEvent) +class PrenotazioneReminderSMSMessage(PrenotazioneSMSMessage): + @property + def message(self) -> str: + return IStringInterpolator(IContextWrapper(self.prenotazione)())( + getattr( + self.prenotazione.getPrenotazioniFolder(), + "notify_as_reminder_sms_message", + "", + ) + ) diff --git a/src/redturtle/prenotazioni/behaviors/configure.zcml b/src/redturtle/prenotazioni/behaviors/configure.zcml index 8377dacb..cd2bd157 100644 --- a/src/redturtle/prenotazioni/behaviors/configure.zcml +++ b/src/redturtle/prenotazioni/behaviors/configure.zcml @@ -4,18 +4,11 @@ i18n_domain="redturtle.prenotazioni" > + + - diff --git a/src/redturtle/prenotazioni/browser/configure.zcml b/src/redturtle/prenotazioni/browser/configure.zcml index d7a1aaeb..c52cbe89 100644 --- a/src/redturtle/prenotazioni/browser/configure.zcml +++ b/src/redturtle/prenotazioni/browser/configure.zcml @@ -24,6 +24,7 @@ /> + diff --git a/src/redturtle/prenotazioni/browser/prenotazione_move.py b/src/redturtle/prenotazioni/browser/prenotazione_move.py index 3eb63ebd..0c431598 100644 --- a/src/redturtle/prenotazioni/browser/prenotazione_move.py +++ b/src/redturtle/prenotazioni/browser/prenotazione_move.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -import logging from plone import api from plone.memoize.view import memoize @@ -22,8 +21,6 @@ from redturtle.prenotazioni.adapters.booker import IBooker from redturtle.prenotazioni.utilities.urls import urlify -logger = logging.getLogger(__name__) - class IMoveForm(Interface): diff --git a/src/redturtle/prenotazioni/browser/prenotazioni_context_state.py b/src/redturtle/prenotazioni/browser/prenotazioni_context_state.py index 307493c0..ed06d178 100644 --- a/src/redturtle/prenotazioni/browser/prenotazioni_context_state.py +++ b/src/redturtle/prenotazioni/browser/prenotazioni_context_state.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import itertools import json -import logging from datetime import date from datetime import datetime from datetime import timedelta @@ -16,6 +15,7 @@ from redturtle.prenotazioni import _ from redturtle.prenotazioni import get_or_create_obj +from redturtle.prenotazioni import logger from redturtle.prenotazioni import tznow from redturtle.prenotazioni.adapters.booker import IBooker from redturtle.prenotazioni.adapters.conflict import IConflictManager @@ -29,8 +29,6 @@ from redturtle.prenotazioni.utilities.dateutils import hm2seconds from redturtle.prenotazioni.utilities.urls import urlify -logger = logging.getLogger(__name__) - class PrenotazioniContextState(BrowserView): @@ -316,8 +314,10 @@ def get_booking_urls(self, day, slot, slot_min_size=0, gate=None): slot_min_size: seconds """ # we have some conditions to check + # XXX: ma questo non si poteva fare prima... molto prima... di arrivare fin qui ? if not self.is_valid_day(day): return [] + # XXX: ma questo non si poteva fare prima... molto prima... di arrivare fin qui ? if self.maximum_bookable_date: if day > self.maximum_bookable_date.date(): return [] diff --git a/src/redturtle/prenotazioni/viewlets/__init__.py b/src/redturtle/prenotazioni/browser/utilities/__init__.py similarity index 100% rename from src/redturtle/prenotazioni/viewlets/__init__.py rename to src/redturtle/prenotazioni/browser/utilities/__init__.py diff --git a/src/redturtle/prenotazioni/viewlets/configure.zcml b/src/redturtle/prenotazioni/browser/utilities/configure.zcml similarity index 54% rename from src/redturtle/prenotazioni/viewlets/configure.zcml rename to src/redturtle/prenotazioni/browser/utilities/configure.zcml index d15d3021..5036b614 100644 --- a/src/redturtle/prenotazioni/viewlets/configure.zcml +++ b/src/redturtle/prenotazioni/browser/utilities/configure.zcml @@ -6,12 +6,10 @@ i18n_domain="redturtle.prenotazioni" > - diff --git a/src/redturtle/prenotazioni/browser/utilities/notify_upcoming_bookings.py b/src/redturtle/prenotazioni/browser/utilities/notify_upcoming_bookings.py new file mode 100644 index 00000000..7a638dc8 --- /dev/null +++ b/src/redturtle/prenotazioni/browser/utilities/notify_upcoming_bookings.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +from datetime import datetime +from datetime import timedelta + +from plone import api +from Products.Five.browser import BrowserView +from zope.event import notify + +from redturtle.prenotazioni import logger +from redturtle.prenotazioni.events import BookingReminderEvent + + +class NotifyUpcomingBookings(BrowserView): + """View to notify about the upcomming bookings""" + + def __call__(self): + today = datetime.now().replace(hour=0, minute=0) + catalog = api.portal.get_tool("portal_catalog") + + for brain in catalog(portal_type="PrenotazioniFolder"): + booking_folder = brain.getObject() + reminder_notification_gap = getattr( + booking_folder, "reminder_notification_gap", None + ) + + if not reminder_notification_gap: + logger.info( + f"No notification gap was found for the <{brain.getPath()}>" + ) + continue + + for booking in catalog( + portal_type="Prenotazione", + path=brain.getPath(), + Date={ + "query": ( + today + timedelta(days=reminder_notification_gap), + today + + timedelta( + days=reminder_notification_gap, hours=23, minutes=59 + ), + ), + "range": "min:max", + }, + review_state="confirmed", + ): + notify(BookingReminderEvent(booking.getObject())) + logger.info(f"A reminder to {booking.getPath()} has been sent") diff --git a/src/redturtle/prenotazioni/configure.zcml b/src/redturtle/prenotazioni/configure.zcml index 02c24264..2b233101 100644 --- a/src/redturtle/prenotazioni/configure.zcml +++ b/src/redturtle/prenotazioni/configure.zcml @@ -9,13 +9,12 @@ + - - @@ -48,17 +47,11 @@ directory="profiles/to_1500" /> - - + + diff --git a/src/redturtle/prenotazioni/content/prenotazioni_folder.py b/src/redturtle/prenotazioni/content/prenotazioni_folder.py index e1c41e16..a999b523 100644 --- a/src/redturtle/prenotazioni/content/prenotazioni_folder.py +++ b/src/redturtle/prenotazioni/content/prenotazioni_folder.py @@ -12,12 +12,9 @@ from z3c.form.browser.checkbox import CheckBoxFieldWidget from zope import schema from zope.component import provideAdapter -from zope.i18n import translate from zope.interface import Invalid from zope.interface import implementer from zope.interface import invariant -from zope.interface import provider -from zope.schema.interfaces import IContextAwareDefaultFactory from zope.schema.vocabulary import SimpleTerm from zope.schema.vocabulary import SimpleVocabulary @@ -131,84 +128,6 @@ class IPauseTableRow(model.Schema): ) -@provider(IContextAwareDefaultFactory) -def notify_on_submit_subject_default_factory(context): - return getattr(context, "translate", translate)( - _("notify_on_submit_subject_default_value", "Booking created ${title}") - ) - - -@provider(IContextAwareDefaultFactory) -def notify_on_submit_message_default_factory(context): - return getattr(context, "translate", translate)( - _( - "notify_on_submit_message_default_value", - "Booking ${booking_type} for ${booking_date} at ${booking_time} was created.Link", - ) - ) - - -@provider(IContextAwareDefaultFactory) -def notify_on_confirm_subject_default_factory(context): - return getattr(context, "translate", translate)( - _( - "notify_on_confirm_subject_default_value", - "Booking of ${booking_date} at ${booking_time} was accepted", - ) - ) - - -@provider(IContextAwareDefaultFactory) -def notify_on_confirm_message_default_factory(context): - return getattr(context, "translate", translate)( - _( - "notify_on_confirm_message_default_value", - "The booking${booking_type} for ${title} was confirmed! Link", - ) - ) - - -@provider(IContextAwareDefaultFactory) -def notify_on_move_subject_default_factory(context): - return getattr(context, "translate", translate)( - _( - "notify_on_move_subject_default_value", - "Modified the boolking date for ${title}", - ) - ) - - -@provider(IContextAwareDefaultFactory) -def notify_on_move_message_default_factory(context): - return getattr(context, "translate", translate)( - _( - "notify_on_move_message_default_value", - "The booking scheduling of ${booking_type} was modified." - "The new one is on ${booking_date} at ${booking_time}. Link.", - ) - ) - - -@provider(IContextAwareDefaultFactory) -def notify_on_refuse_subject_default_factory(context): - return getattr(context, "translate", translate)( - _( - "notify_on_refuse_subject_default_value", - "Booking refused for ${title}", - ) - ) - - -@provider(IContextAwareDefaultFactory) -def notify_on_refuse_message_default_factory(context): - return getattr(context, "translate", translate)( - _( - "notify_on_refuse_message_default_value", - "The booking ${booking_type} of ${booking_date} at ${booking_time} was refused.", - ) - ) - - class IPrenotazioniFolder(model.Schema): """Marker interface and Dexterity Python Schema for PrenotazioniFolder""" @@ -486,14 +405,6 @@ def data_validation(data): if interval["afternoon_start"] > interval["afternoon_end"]: raise Invalid(_("Afternoon start should not be greater than end.")) - # TODO: definire o descrivere quando avviee la notifica - # TODO: inserire qui la chiave IO ? o su un config in zope.conf/environment ? - app_io_enabled = schema.Bool( - title=_("App IO notification"), - default=False, - required=False, - ) - notify_on_submit = schema.Bool( title=_("notify_on_submit", default="Notify when created."), description=_( @@ -530,79 +441,6 @@ def data_validation(data): default=False, required=False, ) - notify_on_submit_subject = schema.TextLine( - title=_( - "notify_on_submit_subject", - default="Prenotazione created notification subject.", - ), - description=_("notify_on_submit_subject_help", default=""), - defaultFactory=notify_on_submit_subject_default_factory, - required=False, - ) - notify_on_submit_message = schema.Text( - title=_( - "notify_on_submit_message", - default="Prenotazione created notification message.", - ), - description=_("notify_on_submit_message_help", default=""), - defaultFactory=notify_on_submit_message_default_factory, - required=False, - ) - notify_on_confirm_subject = schema.TextLine( - title=_( - "notify_on_confirm_subject", - default="Prenotazione confirmed notification subject.", - ), - description=_("notify_on_confirm_subject_help", default=""), - defaultFactory=notify_on_confirm_subject_default_factory, - required=False, - ) - notify_on_confirm_message = schema.Text( - title=_( - "notify_on_confirm_message", - default="Prenotazione confirmed notification message.", - ), - description=_("notify_on_confirm_message_help", default=""), - defaultFactory=notify_on_confirm_message_default_factory, - required=False, - ) - notify_on_move_subject = schema.TextLine( - title=_( - "notify_on_move_subject", - default="Prenotazione moved notification subject.", - ), - description=_("notify_on_move_subject_help", default=""), - defaultFactory=notify_on_move_subject_default_factory, - required=False, - ) - notify_on_move_message = schema.Text( - title=_( - "notify_on_move_message", - default="Prenotazione moved notification message.", - ), - description=_("notify_on_move_message_help", default=""), - defaultFactory=notify_on_move_message_default_factory, - required=False, - ) - notify_on_refuse_subject = schema.TextLine( - title=_( - "notify_on_refuse_subject", - default="Prenotazione refused notification subject.", - ), - description=_("notify_on_refuse_subject_help", default=""), - defaultFactory=notify_on_refuse_subject_default_factory, - required=False, - ) - notify_on_refuse_message = schema.Text( - title=_( - "notify_on_refuse_message", - default="Prenotazione created notification message.", - ), - description=_("notify_on_refuse_message_help", default=""), - defaultFactory=notify_on_refuse_message_default_factory, - required=False, - ) - max_bookings_allowed = schema.Int( title=_( "max_bookings_allowed_label", @@ -615,6 +453,18 @@ def data_validation(data): required=False, default=0, ) + reminder_notification_gap = schema.Int( + title=_( + "reminder_notification_gap_label", + default="Booking reminder days", + ), + description=_( + "reminder_notification_gap_description", + default="Set how many days before of a booking date the user will be notified about it.", + ), + required=False, + default=3, + ) model.fieldset( "dates", @@ -645,72 +495,26 @@ def data_validation(data): "week_table_overrides", ], ) - model.fieldset( - "Notifications", + "fields", + label=_("booking_fields_label", default="Booking fields"), + fields=[ + "visible_booking_fields", + "required_booking_fields", + ], + ) + model.fieldset( + "notifications", label=_("notifications_label", default="Notifications"), fields=[ + "email_responsabile", + "reminder_notification_gap", "notify_on_submit", "notify_on_confirm", "notify_on_move", "notify_on_refuse", ], ) - model.fieldset( - "Prenotazioni Email Templates", - label=_( - "prenotazioni_email_templates_label", - default="Testo delle email di notifica", - ), - # TODO: Use custom frontend widget for the new - # field where we must render the html of field's description - # description=_( - # "templates_usage_default_value", - # "${title} - title." - # "${booking_gate} - booking gate." - # "${booking_human_readable_start} - booking human readable start." - # "${booking_date} - booking date." - # "${booking_end_date} - booking end date." - # "${booking_time} - booking time." - # "${booking_time_end} - booking time end." - # "${booking_code} - booking code." - # "${booking_type} - booking type." - # "${booking_print_url} - booking print url." - # "${booking_url_with_delete_token} - booking url with delete token." - # "${booking_user_phone} - booking user phone." - # "${booking_user_email} - booking user email." - # "${booking_user_details} - booking user details." - # "${booking_office_contact_phone} - booking office contact phone." - # "${booking_office_contact_pec} - booking office contact pec." - # "${booking_office_contact_fax} - booking office contact fax." - # "${booking_how_to_get_to_office} - booking how to get to office." - # "${booking_office_complete_address} - booking office complete address.", - # "${booking_user_details} - booking user details", - # "${booking_requirements} - booking requeirements.", - # "${prenotazioni_folder_title} - prenotazioni folder title.", - # ), - # description=_( - # "prenotazioni_email_templates_description", - # default="", - # ), - fields=[ - "notify_on_submit_subject", - "notify_on_submit_message", - "notify_on_confirm_subject", - "notify_on_confirm_message", - "notify_on_move_subject", - "notify_on_move_message", - "notify_on_refuse_subject", - "notify_on_refuse_message", - ], - ) - model.fieldset( - "Reminders", - label=_("reminders_label", default="Reminders"), - fields=[ - "app_io_enabled", - ], - ) validator.WidgetValidatorDiscriminators( @@ -746,6 +550,12 @@ def get_booking_types(self) -> Generator[PrenotazioneType, None, None]: contentFilter={"portal_type": "PrenotazioneType"} ) + def get_notification_flags(self): + return { + action: getattr(self, f"notify_on_{action}", False) + for action in ("confirm", "submit", "refuse") + } + # BBB: compatibility with old code (booking_types was a List of IBookingTypeRow) @property def booking_types(self): diff --git a/src/redturtle/prenotazioni/contentrules/__init__.py b/src/redturtle/prenotazioni/contentrules/__init__.py deleted file mode 100644 index 40a96afc..00000000 --- a/src/redturtle/prenotazioni/contentrules/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/redturtle/prenotazioni/contentrules/configure.zcml b/src/redturtle/prenotazioni/contentrules/configure.zcml deleted file mode 100644 index b7b283fa..00000000 --- a/src/redturtle/prenotazioni/contentrules/configure.zcml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/src/redturtle/prenotazioni/contentrules/handlers.py b/src/redturtle/prenotazioni/contentrules/handlers.py deleted file mode 100644 index 86680696..00000000 --- a/src/redturtle/prenotazioni/contentrules/handlers.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- -from plone.app.contentrules.handlers import execute_rules - - -def moved(event): - """ - When a booking is moved, execute the rules assigned to his parent. - """ - execute_rules(event) diff --git a/src/redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py b/src/redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py deleted file mode 100644 index 152afdd4..00000000 --- a/src/redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py +++ /dev/null @@ -1,194 +0,0 @@ -# -*- coding: utf-8 -*- -import six -from Acquisition import aq_inner -from OFS.SimpleItem import SimpleItem -from plone.app.contentrules.actions import ActionAddForm -from plone.app.contentrules.actions import ActionEditForm -from plone.app.contentrules.browser.formhelper import ContentRuleFormWrapper -from plone.app.contentrules.browser.formhelper import EditForm -from plone.contentrules.rule.interfaces import IExecutable -from plone.contentrules.rule.interfaces import IRuleElementData -from Products.CMFCore.utils import getToolByName -from zope import schema -from zope.component import adapter -from zope.interface import Interface -from zope.interface import implementer -from zope.interface.interfaces import ComponentLookupError - -from redturtle.prenotazioni import _ - - -class IMovedPrenotazioneAction(Interface): - - """Definition of the configuration available for a mail action""" - - subject = schema.TextLine( - title=_("Subject"), - description=_("Subject of the message"), - required=True, - ) - - source = schema.TextLine( - title=_("Sender email"), - description=_( - "source_help", - default="The email address that sends the email. If no email is " - "provided here, it will use the address from portal.", - ), - required=False, - ) - - message = schema.Text( - title=_("Message"), - description=_( - "message_help", - default="Type in here the message that you want to mail. Some " - "defined content can be replaced: ${title} will be replaced with" - " booking title (user fullname). ${date} will be replaced with " - "booking new date. ${url} will be replaced by the booking url. " - "${portal} will be replaced by the title " - "of the portal.", - ), - required=True, - ) - - -@implementer(IMovedPrenotazioneAction, IRuleElementData) -class MovedPrenotazioneAction(SimpleItem): - - """ - The implementation of the action defined before - """ - - subject = "" - source = "" - message = "" - dest_addr = "" # XXX ? - - element = "redturtle.prenotazioni.actions.MovedPrenotazione" - - @property - def summary(self): - return _("Email report to prenotazione owner") - - -@implementer(IExecutable) -@adapter(Interface, IMovedPrenotazioneAction, Interface) -class MailActionExecutor(object): - - """ - The executor for this action. - """ - - def __init__(self, context, element, event): - self.context = context - self.element = element - self.event = event - - def check_uni(self, value): - """ - Verifica il contenuto da rimpiazzare ed effettua la conversione unicode - se necessario - """ - if not isinstance(value, six.text_type): - value = value.decode("utf-8") - return value - - def __call__(self): - mailhost = getToolByName(aq_inner(self.context), "MailHost") - if not mailhost: - raise ComponentLookupError( - "You must have a Mailhost utility to " "execute this action" - ) - source = self.element.source - urltool = getToolByName(aq_inner(self.context), "portal_url") - portal = urltool.getPortalObject() - email_charset = portal.getProperty("email_charset") - if not source: - # no source provided, looking for the site wide from email - # address - from_address = portal.getProperty("email_from_address") - if not from_address: - raise ValueError( - "You must provide a source address for this " - "action or enter an email in the portal properties" - ) - from_name = portal.getProperty("email_from_name") - source = "%s <%s>" % (from_name, from_address) - plone_view = portal.restrictedTraverse("@@plone") - obj = self.event.object - dest = obj.getEmail() - message = self.element.message - message = message.replace( - "${date}", plone_view.toLocalizedTime(obj.getBooking_date()) - ) - message = message.replace("${url}", obj.absolute_url()) - message = message.replace("${title}", self.check_uni(obj.Title())) - message = message.replace("${portal}", self.check_uni(portal.Title())) - subject = self.element.subject - subject = subject.replace("${url}", obj.absolute_url()) - subject = subject.replace("${title}", self.check_uni(obj.Title())) - subject = subject.replace("${portal}", self.check_uni(portal.Title())) - - self.context.plone_log("sending to: %s" % dest) - try: - # sending mail in Plone 4 - mailhost.send( - message, - mto=dest, - mfrom=source, - subject=subject, - charset=email_charset, - ) - except Exception: - # sending mail in Plone 3 - mailhost.secureSend( - message, - dest, - source, - subject=subject, - subtype="plain", - charset=email_charset, - debug=False, - ) - - return True - - -class MovedPrenotazioneAddForm(ActionAddForm): - - """ - An add form for the mail action - """ - - schema = IMovedPrenotazioneAction - label = _("Add moved booking Mail Action") - description = _( - "A mail action that sends email notify when a booking is moved " - "in an other slot." - ) - form_name = _("Configure element") - Type = MovedPrenotazioneAction - - -class MovedPrenotazioneAddFormView(ContentRuleFormWrapper): - form = MovedPrenotazioneAddForm - - -class MovedPrenotazioneEditForm(EditForm): - - """ - An edit form for the mail action - """ - - schema = IMovedPrenotazioneAction - label = _("Edit moved booking Mail Action") - description = _( - "A mail action that sends email notify when a booking is moved in " - "an other slot." - ) - form_name = _("Configure element") - - -class MovedPrenotazioneEditFormView(ActionEditForm): - form = MovedPrenotazioneEditForm diff --git a/src/redturtle/prenotazioni/events/__init__.py b/src/redturtle/prenotazioni/events/__init__.py index 40a96afc..64dba0e1 100644 --- a/src/redturtle/prenotazioni/events/__init__.py +++ b/src/redturtle/prenotazioni/events/__init__.py @@ -1 +1,10 @@ # -*- coding: utf-8 -*- +from zope.interface import implementer +from zope.interface.interfaces import ObjectEvent + +from redturtle.prenotazioni.interfaces import IBookingReminderEvent + + +@implementer(IBookingReminderEvent) +class BookingReminderEvent(ObjectEvent): + pass diff --git a/src/redturtle/prenotazioni/events/configure.zcml b/src/redturtle/prenotazioni/events/configure.zcml index 9db2ae8d..837a9b4f 100644 --- a/src/redturtle/prenotazioni/events/configure.zcml +++ b/src/redturtle/prenotazioni/events/configure.zcml @@ -25,16 +25,10 @@ - - @@ -53,22 +47,10 @@ zope.lifecycleevent.IObjectModifiedEvent" handler=".prenotazioni_folder.sort_on_creation_or_change" /> - - - - diff --git a/src/redturtle/prenotazioni/events/prenotazione.py b/src/redturtle/prenotazioni/events/prenotazione.py index aa9cb50c..10a5eb72 100644 --- a/src/redturtle/prenotazioni/events/prenotazione.py +++ b/src/redturtle/prenotazioni/events/prenotazione.py @@ -2,19 +2,14 @@ import hashlib from email.utils import formataddr from email.utils import parseaddr -from logging import getLogger from plone import api from plone.registry.interfaces import IRegistry from Products.CMFPlone.interfaces.controlpanel import IMailSchema -from zope.component import getMultiAdapter from zope.component import getUtility from redturtle.prenotazioni import is_migration from redturtle.prenotazioni.adapters.booker import IBooker -from redturtle.prenotazioni.interfaces import IPrenotazioneEmailMessage - -logger = getLogger(__name__) def reallocate_gate(obj): @@ -45,34 +40,6 @@ def reallocate_container(obj): IBooker(container).fix_container(obj.object) -def notify_on_after_transition_event(context, event): - """The messages are being send only if the following flags on the PrenotazioniFolder are set""" - if is_migration(): - return - booking_folder = context.getPrenotazioniFolder() - flags = { - i: getattr(booking_folder, f"notify_on_{i}", False) - for i in ("confirm", "submit", "refuse") - } - - if flags["confirm"] and getattr(booking_folder, "auto_confirm", False): - flags["submit"] = False - - if flags.get(event.transition and event.transition.__name__ or "", False): - if not getattr(context, "email", ""): - # booking does not have an email set - return - adapter = getMultiAdapter( - (context, event), - IPrenotazioneEmailMessage, - name=event.transition.__name__, - ) - - if adapter: - if adapter.message: - send_email(adapter.message) - - def autoconfirm(booking, event): if api.content.get_state(obj=booking, default=None) == "pending": if getattr(booking.getPrenotazioniFolder(), "auto_confirm", False): @@ -80,31 +47,6 @@ def autoconfirm(booking, event): booking.reindexObject(idxs="review_state") -# TODO: use the notify_on_after_transition_event method techique instead -def notify_on_move(booking, event): - if not getattr(booking.getPrenotazioniFolder(), "notify_on_move", False): - return - if not getattr(booking, "email", ""): - # booking does not have an email set - return - adapter = getMultiAdapter((booking, event), IPrenotazioneEmailMessage) - if adapter: - if adapter.message: - send_email(adapter.message) - - -# TODO: sosituire con plone.api.portal.send_email -def send_email(msg): - if not msg: - logger.error("Could not send email due to no message was provided") - return - - host = api.portal.get_tool(name="MailHost") - registry = getUtility(IRegistry) - encoding = registry.get("plone.email_charset", "utf-8") - host.send(msg, charset=encoding) - - def get_mail_from_address(): registry = getUtility(IRegistry) mail_settings = registry.forInterface(IMailSchema, prefix="plone", check=False) @@ -120,25 +62,6 @@ def get_mail_from_address(): return mfrom -def send_email_to_managers(booking, event): - # skip email for vacation/out-of-office - if is_migration(): - return - - if booking.isVacation(): - return - if not getattr(booking, "email_responsabile", []): - return - - adapter = getMultiAdapter( - (booking, event), IPrenotazioneEmailMessage, name="notify_manager" - ) - - if adapter: - if adapter.message: - send_email(adapter.message) - - def set_booking_code(booking, event): """ set booking code. skip if we are importing old booking diff --git a/src/redturtle/prenotazioni/interfaces.py b/src/redturtle/prenotazioni/interfaces.py index d83d8511..07d3ec4d 100644 --- a/src/redturtle/prenotazioni/interfaces.py +++ b/src/redturtle/prenotazioni/interfaces.py @@ -2,6 +2,7 @@ """Module where all interfaces, events and exceptions live.""" from zope.interface import Interface +from zope.interface.interfaces import IObjectEvent from zope.publisher.interfaces.browser import IDefaultBrowserLayer @@ -17,9 +18,32 @@ class ISerializeToPrenotazioneSearchableItem(Interface): """Prenotazione searchable item serializer interface""" -class IPrenotazioneEmailMessage(Interface): - """Prenotazione email message""" - - class ISerializeToRetroCompatibleJson(Interface): """Interface used to cereate the TEMPORARY retrocomattible serializers""" + + +class IBookingReminderEvent(IObjectEvent): + """Booking reminder time arrived event""" + + +class IBookingNotificationSender(Interface): + """Booking notification sender""" + + +class IBookingEmailMessage(Interface): + """Prenotazione email message which is being used by the email gateway""" + + +class IBookingSMSMessage(Interface): + """Prenotazione SMS message adapter which is being used by the SMS gateway""" + + +class IBookingAPPIoMessage(Interface): + """Prenotazione AppIO message adapter which being used by the App IO gateway""" + + +class IBookingNotificatorSupervisorUtility(Interface): + """Bookign notificator supervisor + basically contains the business logic to allow/disallow the + notification sending to gateways + """ diff --git a/src/redturtle/prenotazioni/scripts/io_tools/README.md b/src/redturtle/prenotazioni/io_tools/README.md similarity index 100% rename from src/redturtle/prenotazioni/scripts/io_tools/README.md rename to src/redturtle/prenotazioni/io_tools/README.md diff --git a/src/redturtle/prenotazioni/scripts/io_tools/__init__.py b/src/redturtle/prenotazioni/io_tools/__init__.py similarity index 100% rename from src/redturtle/prenotazioni/scripts/io_tools/__init__.py rename to src/redturtle/prenotazioni/io_tools/__init__.py diff --git a/src/redturtle/prenotazioni/scripts/io_tools/api.py b/src/redturtle/prenotazioni/io_tools/api.py similarity index 88% rename from src/redturtle/prenotazioni/scripts/io_tools/api.py rename to src/redturtle/prenotazioni/io_tools/api.py index 5301473b..343ee51c 100644 --- a/src/redturtle/prenotazioni/scripts/io_tools/api.py +++ b/src/redturtle/prenotazioni/io_tools/api.py @@ -46,11 +46,12 @@ class Api(object): def __init__(self, secret, storage=None): self.storage = storage - header = "Ocp-Apim-Subscription-Key" http_client = RequestsClient() - http_client.set_api_key( - "api.io.italia.it", secret, param_name=header, param_in="header" - ) + http_client.session.headers = { + "Ocp-Apim-Subscription-Key": f"{secret}", + "Content-Type": "application/json", + } + # TODO: cache delle specifiche openapi self.api = SwaggerClient.from_url( "https://raw.githubusercontent.com/teamdigitale/io-functions-services/master/openapi/index.yaml", @@ -139,22 +140,12 @@ def send_message( key, fiscal_code, subject, body, payment_data, due_date ) # 2. verifica se il destinatario è abilitato o meno a ricevere il messaggio - try: - profile = ( - self.api.profiles.getProfile(fiscal_code=fiscal_code).response().result - ) - except HTTPForbidden: - self.storage.update_message(key, status=PROFILE_NOT_FOUND) - logger.error( - "profile for user %s not found (access forbidden to api)", fiscal_code - ) - return None - except Exception: + + profile = self.get_profile(fiscal_code=fiscal_code) + + if not profile: self.storage.update_message(key, status=PROFILE_NOT_FOUND) - logger.exception( - "profile for user %s not found (generic error)", fiscal_code - ) - return None + if profile and profile.sender_allowed: # PaymentData non definito nello swagger, payment_data come dizionario # è comunque sufficiente @@ -206,3 +197,47 @@ def send_message( self.storage.update_message(key, status=SENDER_NOT_ALLOWED) logger.warning("message for user %s not allowed", fiscal_code) return None + + def get_profile(self, fiscal_code): + try: + return ( + self.api.profiles.getProfile(fiscal_code=fiscal_code).response().result + ) + except HTTPForbidden: + logger.error( + "profile for user %s not found (access forbidden to api)", fiscal_code + ) + + except Exception: + logger.exception( + "profile for user %s not found (generic error)", fiscal_code + ) + + return None + + def is_service_activated(self, fiscal_code): + """Check if the service is activated for a user""" + + if not self.get_profile(fiscal_code): + return None + + fiscal_code = self.api.get_model("FiscalCodePayload")(fiscal_code=fiscal_code) + + try: + return getattr( + self.api.profiles.getProfileByPOST(payload=fiscal_code).result(), + "sender_allowed", + False, + ) + + except HTTPForbidden: + logger.error( + "subsctiprion not found for user %s (access forbidden to api)", + fiscal_code, + ) + + except Exception: + logger.exception( + "subsctiprion not found for user %s (generic error)", + fiscal_code, + ) diff --git a/src/redturtle/prenotazioni/scripts/io_tools/cli.py b/src/redturtle/prenotazioni/io_tools/cli.py similarity index 100% rename from src/redturtle/prenotazioni/scripts/io_tools/cli.py rename to src/redturtle/prenotazioni/io_tools/cli.py diff --git a/src/redturtle/prenotazioni/scripts/io_tools/io.db b/src/redturtle/prenotazioni/io_tools/io.db similarity index 100% rename from src/redturtle/prenotazioni/scripts/io_tools/io.db rename to src/redturtle/prenotazioni/io_tools/io.db diff --git a/src/redturtle/prenotazioni/scripts/io_tools/io_tools.py b/src/redturtle/prenotazioni/io_tools/io_tools.py similarity index 100% rename from src/redturtle/prenotazioni/scripts/io_tools/io_tools.py rename to src/redturtle/prenotazioni/io_tools/io_tools.py diff --git a/src/redturtle/prenotazioni/scripts/io_tools/monkey.py b/src/redturtle/prenotazioni/io_tools/monkey.py similarity index 100% rename from src/redturtle/prenotazioni/scripts/io_tools/monkey.py rename to src/redturtle/prenotazioni/io_tools/monkey.py diff --git a/src/redturtle/prenotazioni/scripts/io_tools/rdbms.py b/src/redturtle/prenotazioni/io_tools/rdbms.py similarity index 100% rename from src/redturtle/prenotazioni/scripts/io_tools/rdbms.py rename to src/redturtle/prenotazioni/io_tools/rdbms.py diff --git a/src/redturtle/prenotazioni/scripts/io_tools/spec.yaml b/src/redturtle/prenotazioni/io_tools/spec.yaml similarity index 100% rename from src/redturtle/prenotazioni/scripts/io_tools/spec.yaml rename to src/redturtle/prenotazioni/io_tools/spec.yaml diff --git a/src/redturtle/prenotazioni/scripts/io_tools/storage.py b/src/redturtle/prenotazioni/io_tools/storage.py similarity index 100% rename from src/redturtle/prenotazioni/scripts/io_tools/storage.py rename to src/redturtle/prenotazioni/io_tools/storage.py diff --git a/src/redturtle/prenotazioni/locales/en/LC_MESSAGES/redturtle.prenotazioni.po b/src/redturtle/prenotazioni/locales/en/LC_MESSAGES/redturtle.prenotazioni.po index 63d2dc05..15b22416 100644 --- a/src/redturtle/prenotazioni/locales/en/LC_MESSAGES/redturtle.prenotazioni.po +++ b/src/redturtle/prenotazioni/locales/en/LC_MESSAGES/redturtle.prenotazioni.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2023-12-14 13:19+0000\n" +"POT-Creation-Date: 2024-01-04 01:37+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -14,1445 +14,1614 @@ msgstr "" "Preferred-Encodings: utf-8 latin1\n" "Domain: DOMAIN\n" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:63 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:46 -#: redturtle/prenotazioni/browser/vacations.py:74 +#: ../browser/prenotazioni_search.py:63 +#: ../browser/stats/booking_stats.py:46 +#: ../browser/vacations.py:74 msgid " format (YYYY-MM-DD)" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniFolder.xml +#: ../profiles/default/types/PrenotazioniFolder.xml msgid "A folder that will contain booking" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "A folder that will contain booking for this day" msgstr "" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:166 -msgid "A mail action that sends email notify when a booking is moved in an other slot." -msgstr "" - -msgid "Add" -msgstr "" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:165 -msgid "Add moved booking Mail Action" -msgstr "" - -#: redturtle/prenotazioni/content/prenotazioni_folder.py:478 -#: redturtle/prenotazioni/content/validators.py:213 +#: ../content/prenotazioni_folder.py:406 +#: ../content/validators.py:213 msgid "Afternoon start should not be greater than end." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:483 -msgid "App IO notification" -msgstr "" - -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:29 +#: ../browser/templates/prenotazione.pt:29 msgid "Attention" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:27 +#: ../adapters/stringinterp.py:27 msgid "Booking" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniFolder.xml +#: ../profiles/default/types/PrenotazioniFolder.xml msgid "Booking Folder" -msgstr "" +msgstr "Prenotazioni Folder" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioneType.xml +#: ../profiles/default/types/PrenotazioneType.xml msgid "Booking Type" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniWeek.xml +#: ../profiles/default/types/PrenotazioniWeek.xml msgid "Booking Week Folder" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniYear.xml +#: ../profiles/default/types/PrenotazioniYear.xml msgid "Booking Year Folder" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:44 +#: ../behaviors/booking_folder/appio/configure.zcml:17 +msgid "Booking folder notification appio" +msgstr "" + +#: ../behaviors/booking_folder/email/configure.zcml:17 +msgid "Booking folder notification email" +msgstr "" + +#: ../behaviors/booking_folder/sms/configure.zcml:17 +msgid "Booking folder notification sms" +msgstr "" + +#: ../browser/templates/prenotazione.pt:44 msgid "Booking for" msgstr "" -#: redturtle/prenotazioni/contentrules/configure.zcml:30 -msgid "Booking moved" +#: ../behaviors/booking_folder/appio/configure.zcml:27 +msgid "Booking type notification appio" msgstr "" #. Default: "Change date/time" -#: redturtle/prenotazioni/profiles/default/actions.xml +#: ../profiles/default/actions.xml msgid "Change date/time" msgstr "" #. Default: "Complete address" -#: redturtle/prenotazioni/behaviors/booking_folder.py:43 +#: ../behaviors/booking_folder/contacts.py:43 msgid "Complete address" msgstr "" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:170 -msgid "Configure element" -msgstr "" - -#: redturtle/prenotazioni/behaviors/booking_folder.py:36 +#: ../behaviors/booking_folder/contacts.py:36 msgid "Contact PEC" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:30 +#: ../behaviors/booking_folder/contacts.py:30 msgid "Contact fax" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:24 +#: ../behaviors/booking_folder/contacts.py:24 msgid "Contact phone" msgstr "" -#: redturtle/prenotazioni/behaviors/configure.zcml:19 +#: ../behaviors/booking_folder/configure.zcml:19 msgid "Contacts fields." msgstr "" -#: redturtle/prenotazioni/behaviors/configure.zcml:19 +#: ../behaviors/booking_folder/configure.zcml:19 msgid "Contatti cartella prenotazioni" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:46 +#: ../browser/templates/prenotazioni_search.pt:46 msgid "Content listing" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:262 +#: ../content/prenotazioni_folder.py:181 msgid "Data fine validità" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:259 +#: ../content/prenotazioni_folder.py:178 msgid "Data inizio validità" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:612 +#: ../content/prenotazioni_folder.py:471 msgid "Date validità" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:421 +#: ../content/prenotazioni_folder.py:340 msgid "Days booking is not allowed before" msgstr "" -msgid "Delete" -msgstr "" - #. Default: "Descrizione Agenda" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:218 +#: ../content/prenotazioni_folder.py:137 msgid "Descrizione Agenda" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioneType.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/PrenotazioneType.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "Edit" msgstr "" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:185 -msgid "Edit moved booking Mail Action" -msgstr "" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:72 -msgid "Email report to prenotazione owner" -msgstr "" - -#: redturtle/prenotazioni/content/prenotazione.py:175 +#: ../content/prenotazione.py:175 msgid "Expiration date booking" msgstr "" #. Default: "Campo" -#: redturtle/prenotazioni/browser/z3c_custom_widget.py:150 +#: ../browser/z3c_custom_widget.py:150 msgid "Field" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:116 +#: ../content/prenotazioni_folder.py:113 msgid "Friday" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:107 -#: redturtle/prenotazioni/content/prenotazione.py:170 +#: ../browser/templates/prenotazione.pt:107 +#: ../content/prenotazione.py:170 msgid "Gate" msgstr "" -msgid "Group" -msgstr "" - #. Default: "How to get here" -#: redturtle/prenotazioni/behaviors/booking_folder.py:19 +#: ../behaviors/booking_folder/contacts.py:19 msgid "How to get here" msgstr "" -#: redturtle/prenotazioni/content/validators.py:136 +#: ../content/validators.py:136 msgid "In the same day there are overlapping intervals" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/Prenotazione.xml msgid "Informations about a single booking" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:219 +#: ../content/prenotazioni_folder.py:138 msgid "Inserire il testo di presentazione dell'agenda corrente" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:450 +#: ../content/prenotazioni_folder.py:378 msgid "Insert a list of email addresses that will be notified when new bookings get created." msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:20 +#: ../behaviors/booking_folder/contacts.py:20 msgid "Insert here indications on how to reach the office" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:44 +#: ../behaviors/booking_folder/contacts.py:44 msgid "Insert here the complete office address" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:37 +#: ../behaviors/booking_folder/contacts.py:37 msgid "Insert here the contact PEC" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:31 +#: ../behaviors/booking_folder/contacts.py:31 msgid "Insert here the contact fax" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:25 +#: ../behaviors/booking_folder/contacts.py:25 msgid "Insert here the contact phone" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:372 +#: ../content/prenotazioni_folder.py:291 msgid "Insert pause table schema." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:295 +#: ../content/prenotazioni_folder.py:214 msgid "Insert week table schema." msgstr "" -#: redturtle/prenotazioni/configure.zcml:32 +#: ../configure.zcml:31 msgid "Installs the redturtle.prenotazioni add-on." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:409 -msgid "Max days in the future" +#: ../staging/configure.zcml:16 +msgid "Installs the redturtle.prenotazioni.staging add-on (demo site purpose only)." msgstr "" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:42 -msgid "Message" +#: ../content/prenotazioni_folder.py:328 +msgid "Max days in the future" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:112 +#: ../content/prenotazioni_folder.py:109 msgid "Monday" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:475 -#: redturtle/prenotazioni/content/validators.py:208 +#: ../content/prenotazioni_folder.py:403 +#: ../content/validators.py:208 msgid "Morning start should not be greater than end." msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:152 +#: ../browser/templates/prenotazione.pt:152 msgid "Move booking" msgstr "" -msgid "Move down" +#: ../restapi/services/booking/vacation.py:27 +msgid "Nessuno slot creato, verificare la corretteza dei dati inseriti" msgstr "" -msgid "Move up" +#: ../content/prenotazioni_folder.py:193 +msgid "No" msgstr "" -#: redturtle/prenotazioni/restapi/services/booking/vacation.py:27 -msgid "Nessuno slot creato, verificare la corretteza dei dati inseriti" +#: ../behaviors/booking_folder/appio/configure.zcml:17 +msgid "Notification APPIo" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:274 -msgid "No" +#: ../behaviors/booking_folder/appio/configure.zcml:27 +msgid "Notification APPIo for PrenotazioneType c.t." +msgstr "" + +#: ../behaviors/booking_folder/sms/configure.zcml:17 +msgid "Notification SMS" +msgstr "" + +#: ../behaviors/booking_folder/email/configure.zcml:17 +msgid "Notification email templates" msgstr "" -#: redturtle/prenotazioni/content/pause.py:43 +#: ../content/pause.py:43 msgid "Pause" msgstr "" -#: redturtle/prenotazioni/content/validators.py:100 +#: ../content/validators.py:100 msgid "Pause end should be greater than pause start" msgstr "" -#: redturtle/prenotazioni/content/validators.py:121 +#: ../content/validators.py:121 msgid "Pause should be included in morning slot or afternoon slot" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:371 +#: ../content/prenotazioni_folder.py:290 msgid "Pause table" msgstr "" -#: redturtle/prenotazioni/browser/prenotazione_add.py:221 +#: ../browser/prenotazione_add.py:221 msgid "Please provide a booking date" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/Prenotazione.xml msgid "Prenotazione" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "PrenotazioniDay" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniWeek.xml +#: ../profiles/default/types/PrenotazioniWeek.xml msgid "PrenotazioniWeek" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniYear.xml +#: ../profiles/default/types/PrenotazioniYear.xml msgid "PrenotazioniYear" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazione_print.pt:129 +#: ../browser/templates/prenotazione_print.pt:129 msgid "Print" msgstr "" -#: redturtle/prenotazioni/configure.zcml:57 -msgid "Profile create to add the new default content rule: booking-confirm" -msgstr "" - -#: redturtle/prenotazioni/restapi/services/booking/add.py:72 +#: ../restapi/services/booking/add.py:77 msgid "Required input '${field}' is missing." msgstr "" -#: redturtle/prenotazioni/browser/prenotazione_add.py:217 +#: ../browser/prenotazione_add.py:217 msgid "Required input is missing." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:449 +#: ../content/prenotazioni_folder.py:377 msgid "Responsible email" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:117 +#: ../content/prenotazioni_folder.py:114 msgid "Saturday" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:16 +#: ../browser/templates/prenotazioni_search.pt:16 msgid "Search for" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:111 +#: ../content/prenotazioni_folder.py:108 msgid "Select a day" msgstr "" -#: redturtle/prenotazioni/contentrules/configure.zcml:57 -msgid "Send Email to booking owner when a booking is moved" -msgstr "" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:32 -msgid "Sender email" -msgstr "" - -#: redturtle/prenotazioni/adapters/booker.py:234 -#: redturtle/prenotazioni/restapi/services/booking/add.py:57 +#: ../adapters/booker.py:249 +#: ../restapi/services/booking/add.py:58 msgid "Sorry, this slot is not available anymore." msgstr "" -#: redturtle/prenotazioni/adapters/booker.py:273 +#: ../adapters/booker.py:292 msgid "Sorry, this slot is not available or does not fit your booking." msgstr "" -#: redturtle/prenotazioni/adapters/booker.py:239 +#: ../adapters/booker.py:143 msgid "Sorry, you can not book this slot for now." msgstr "" -#: redturtle/prenotazioni/content/prenotazione.py:171 +#: ../content/prenotazione.py:171 msgid "Sportello a cui presentarsi" msgstr "" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:26 -msgid "Subject" -msgstr "" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:27 -msgid "Subject of the message" -msgstr "" - -#: redturtle/prenotazioni/content/prenotazioni_folder.py:118 +#: ../content/prenotazioni_folder.py:115 msgid "Sunday" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:37 +#: ../adapters/stringinterp.py:37 msgid "The booked date." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:50 +#: ../adapters/stringinterp.py:50 msgid "The booked end date." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:63 +#: ../adapters/stringinterp.py:63 msgid "The booked time." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:96 +#: ../adapters/stringinterp.py:96 msgid "The booking code." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:291 +#: ../adapters/stringinterp.py:291 msgid "The booking folder title" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:211 +#: ../adapters/stringinterp.py:211 msgid "The booking human readable date" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:177 +#: ../adapters/stringinterp.py:177 msgid "The booking office contact fax." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:167 +#: ../adapters/stringinterp.py:167 msgid "The booking office contact pec address." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:157 +#: ../adapters/stringinterp.py:157 msgid "The booking office contact phone." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:250 +#: ../adapters/stringinterp.py:250 msgid "The booking operator url" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:108 +#: ../adapters/stringinterp.py:108 msgid "The booking print url." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:259 +#: ../adapters/stringinterp.py:259 msgid "The booking refuse message" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:280 +#: ../adapters/stringinterp.py:280 msgid "The booking requirements url" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:75 +#: ../adapters/stringinterp.py:75 msgid "The booking time end." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:87 +#: ../adapters/stringinterp.py:87 msgid "The booking type." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:238 +#: ../adapters/stringinterp.py:238 msgid "The booking url with delete token" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:199 +#: ../adapters/stringinterp.py:199 msgid "The complete address information of the office whereuser book a reservation" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:139 +#: ../adapters/stringinterp.py:139 msgid "The email address of the user who made the reservation." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:28 +#: ../adapters/stringinterp.py:28 msgid "The gate booked." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:187 +#: ../adapters/stringinterp.py:187 msgid "The information to reach the office where user book a reservation" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:130 +#: ../adapters/stringinterp.py:130 msgid "The phone number of the user who made the reservation." msgstr "" -#: redturtle/prenotazioni/adapters/booker.py:325 +#: ../adapters/booker.py:341 msgid "This day is not valid." msgstr "" -#: redturtle/prenotazioni/adapters/booker.py:320 +#: ../adapters/booker.py:336 msgid "This gate has some booking schedule in this time period." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:115 +#: ../content/prenotazioni_folder.py:112 msgid "Thursday" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:113 +#: ../content/prenotazioni_folder.py:110 msgid "Tuesday" msgstr "" -#: redturtle/prenotazioni/configure.zcml:41 +#: ../configure.zcml:40 msgid "Uninstalls the redturtle.prenotazioni add-on." msgstr "" -#: redturtle/prenotazioni/restapi/services/booking/add.py:108 -msgid "Unknown booking type '${booking_type}'." +#: ../staging/configure.zcml:25 +msgid "Uninstalls the redturtle.prenotazioni.staging add-on (demo site purpose only)." msgstr "" -#: redturtle/prenotazioni/configure.zcml:57 -msgid "Used to add new contentrules" +#: ../restapi/services/booking/add.py:113 +msgid "Unknown booking type '${booking_type}'." msgstr "" -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioneType.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/PrenotazioneType.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "View" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:114 +#: ../content/prenotazioni_folder.py:111 msgid "Wednesday" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:294 +#: ../content/prenotazioni_folder.py:213 msgid "Week table" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:273 +#: ../content/prenotazioni_folder.py:192 msgid "Yes" msgstr "" -#: redturtle/prenotazioni/restapi/services/booking/add.py:45 +#: ../restapi/services/booking/add.py:70 msgid "You are not allowed to force the gate." msgstr "" -#: redturtle/prenotazioni/content/validators.py:92 +#: ../content/validators.py:92 msgid "You must set both start and end" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:472 -#: redturtle/prenotazioni/content/validators.py:203 +#: ../content/prenotazioni_folder.py:400 +#: ../content/validators.py:203 msgid "You should set a start time for afternoon." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:468 -#: redturtle/prenotazioni/content/validators.py:195 +#: ../content/prenotazioni_folder.py:396 +#: ../content/validators.py:195 msgid "You should set a start time for morning." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:470 -#: redturtle/prenotazioni/content/validators.py:199 +#: ../content/prenotazioni_folder.py:398 +#: ../content/validators.py:199 msgid "You should set an end time for afternoon." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:466 -#: redturtle/prenotazioni/content/validators.py:191 +#: ../content/prenotazioni_folder.py:394 +#: ../content/validators.py:191 msgid "You should set an end time for morning." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:124 +#: ../adapters/stringinterp.py:124 msgid "[DEPRECATED] The booking print url with delete token." msgstr "" #. Default: "Leave empty, and this Booking Folder will never expire" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:263 +#: ../content/prenotazioni_folder.py:182 msgid "aData_help" msgstr "" #. Default: "Book" -#: redturtle/prenotazioni/browser/prenotazione_add.py:199 -#: redturtle/prenotazioni/browser/vacations.py:207 +#: ../browser/prenotazione_add.py:199 +#: ../browser/vacations.py:207 msgid "action_book" msgstr "" #. Default: "Cancel" -#: redturtle/prenotazioni/browser/prenotazione_add.py:252 -#: redturtle/prenotazioni/browser/prenotazione_move.py:150 -#: redturtle/prenotazioni/browser/vacations.py:232 +#: ../browser/prenotazione_add.py:252 +#: ../browser/prenotazione_move.py:147 +#: ../browser/vacations.py:232 msgid "action_cancel" msgstr "" #. Default: "Move" -#: redturtle/prenotazioni/browser/prenotazione_move.py:125 +#: ../browser/prenotazione_move.py:122 msgid "action_move" msgstr "" #. Default: "Search" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:250 +#: ../browser/prenotazioni_search.py:250 msgid "action_search" msgstr "" #. Default: "End time in the afternoon" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:99 +#: ../content/prenotazioni_folder.py:96 msgid "afternoon_end_label" msgstr "" #. Default: "Start time in the afternoon" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:93 +#: ../content/prenotazioni_folder.py:90 msgid "afternoon_start_label" msgstr "" #. Default: "All" -#: redturtle/prenotazioni/vocabularies/voc_booking_type_gates.py:22 +#: ../vocabularies/voc_booking_type_gates.py:16 msgid "all" msgstr "" #. Default: "Automatically confirm." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:439 +#: ../content/prenotazioni_folder.py:358 msgid "auto_confirm" msgstr "" #. Default: "All bookings will be automatically accepted." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:440 +#: ../content/prenotazioni_folder.py:359 msgid "auto_confirm_help" msgstr "" #. Default: "Automatically confirmfor managers." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:448 +#: ../content/prenotazioni_folder.py:367 msgid "auto_confirm_manager" msgstr "" #. Default: "All bookings created by Managers will be automatically accepted." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:449 +#: ../content/prenotazioni_folder.py:368 msgid "auto_confirm_manager_help" msgstr "" #. Default: "End date should be greater than start." -#: redturtle/prenotazioni/restapi/services/available_slots/get.py:44 +#: ../restapi/services/available_slots/get.py:44 msgid "available_slots_wrong_dates" msgstr "" #. Default: "Please select a booking slot." -#: redturtle/prenotazioni/browser/templates/week.pt:40 +#: ../browser/templates/week.pt:40 msgid "book_it" msgstr "" #. Default: "Bookable time" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:454 +#: ../browser/templates/prenotazione_macros.pt:454 msgid "bookable_time" msgstr "" #. Default: "${day}, ore ${booking_time}, prenotato da ${booked_by}, prenotazione: ${booking_type} durata: ${duration} minuti" -#: redturtle/prenotazioni/browser/week.py:276 +#: ../browser/week.py:276 msgid "booked_prenotation_message" msgstr "" #. Default: "Booking confirmed" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:456 +#: ../browser/templates/prenotazione_macros.pt:456 msgid "booking_confirmed" msgstr "" -#: redturtle/prenotazioni/browser/prenotazione_add.py:231 -#: redturtle/prenotazioni/browser/vacations.py:204 +#: ../browser/prenotazione_add.py:231 +#: ../browser/vacations.py:204 msgid "booking_created" msgstr "" #. Default: "Your booking has been deleted." -#: redturtle/prenotazioni/browser/delete_reservation.py:114 +#: ../browser/delete_reservation.py:114 msgid "booking_deleted_success" msgstr "" -#: redturtle/prenotazioni/browser/prenotazione_move.py:140 +#. Default: "Booking fields" +#: ../content/prenotazioni_folder.py:500 +msgid "booking_fields_label" +msgstr "" + +#: ../browser/prenotazione_move.py:137 msgid "booking_moved" msgstr "" #. Default: "Booking pending" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:458 +#: ../browser/templates/prenotazione_macros.pt:458 msgid "booking_pending" msgstr "" #. Default: "Booking refused" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:460 +#: ../browser/templates/prenotazione_macros.pt:460 msgid "booking_refused" msgstr "" #. Default: "Duration value" -#: redturtle/prenotazioni/content/prenotazione_type.py:15 +#: ../content/prenotazione_type.py:15 msgid "booking_type_duration_label" msgstr "" #. Default: "Name" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:427 +#: ../browser/templates/prenotazione_macros.pt:427 msgid "booking_type_name" msgstr "" #. Default: "List of requirements to recieve the service" -#: redturtle/prenotazioni/content/prenotazione_type.py:23 +#: ../content/prenotazione_type.py:23 msgid "booking_type_requirements_help" msgstr "" #. Default: "Requirements" -#: redturtle/prenotazioni/content/prenotazione_type.py:22 +#: ../content/prenotazione_type.py:22 msgid "booking_type_requirements_labled" msgstr "" #. Default: "Value" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:428 +#: ../browser/templates/prenotazione_macros.pt:428 msgid "booking_type_value" msgstr "" #. Default: "You may want to select another time slot to book one of these." -#: redturtle/prenotazioni/browser/templates/booking_type_radio_widget.pt:77 +#: ../browser/templates/booking_type_radio_widget.pt:77 msgid "booking_type_widget_suggest_reselect" msgstr "" #. Default: "The following tipologies will not fit the time you selected:" -#: redturtle/prenotazioni/browser/templates/booking_type_radio_widget.pt:65 +#: ../browser/templates/booking_type_radio_widget.pt:65 msgid "booking_type_widget_warn_unavailable" msgstr "" +#. Default: "Set message text for all available notification events." +#: ../behaviors/booking_folder/appio/__init__.py:257 +msgid "bookings_appio_templates_help" +msgstr "" + +#. Default: "AppIO Notifications" +#: ../behaviors/booking_folder/appio/__init__.py:253 +msgid "bookings_appio_templates_label" +msgstr "" + +#. Default: "Set message text for all available notification events." +#: ../behaviors/booking_folder/email/__init__.py:257 +msgid "bookings_email_templates_help" +msgstr "" + +#. Default: "Email Notifications" +#: ../behaviors/booking_folder/email/__init__.py:253 +msgid "bookings_email_templates_label" +msgstr "" + #. Default: "Booking limit({limit}) for the {booking_type} type is exceed for the current user" -#: redturtle/prenotazioni/exceptions/booker.py:15 +#: ../exceptions/booker.py:15 msgid "bookings_limit_exceeded_exception" msgstr "" #. Default: "Bookings not in agenda" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:111 +#: ../browser/templates/prenotazione_macros.pt:111 msgid "bookings_not_in_agenda" msgstr "" +#. Default: "Set message text for all available notification events. Remember that SMS has a 160 characters limit. Depending on your gateway service, it can split messages, if you exceed that limit." +#: ../behaviors/booking_folder/sms/__init__.py:144 +msgid "bookings_sms_templates_help" +msgstr "" + +#. Default: "SMS Notifications" +#: ../behaviors/booking_folder/sms/__init__.py:140 +msgid "bookings_sms_templates_label" +msgstr "" + #. Default: "Busy" -#: redturtle/prenotazioni/browser/prenotazioni_context_state.py:47 +#: ../browser/prenotazioni_context_state.py:45 msgid "busy" msgstr "" #. Default: "Your booking has been confirmed." -#: redturtle/prenotazioni/browser/prenotazione_print.py:28 +#: ../browser/prenotazione_print.py:28 msgid "confirm_booking_confirmed_message" msgstr "" #. Default: "Your booking has been refused." -#: redturtle/prenotazioni/browser/prenotazione_print.py:32 +#: ../browser/prenotazione_print.py:32 msgid "confirm_booking_refused_message" msgstr "" #. Default: "Your booking has to be confirmed by the administrators." -#: redturtle/prenotazioni/browser/prenotazione_print.py:24 +#: ../browser/prenotazione_print.py:24 msgid "confirm_booking_waiting_message" msgstr "" #. Default: "Show here contacts information that will be used by authomatic mail system" -#: redturtle/prenotazioni/behaviors/booking_folder.py:49 +#: ../behaviors/booking_folder/contacts.py:49 msgid "contacts_help" msgstr "" #. Default: "Contacts" -#: redturtle/prenotazioni/behaviors/booking_folder.py:48 +#: ../behaviors/booking_folder/contacts.py:48 msgid "contacts_label" msgstr "" #. Default: "This day is not valid." -#: redturtle/prenotazioni/browser/vacations.py:224 +#: ../browser/vacations.py:224 msgid "day_error" msgstr "" #. Default: "Day of week" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:73 +#: ../content/prenotazioni_folder.py:70 msgid "day_label" msgstr "" #. Default: "You can't delete your reservation; it's too late." -#: redturtle/prenotazioni/browser/delete_reservation.py:138 +#: ../browser/delete_reservation.py:138 msgid "delete_expired_booking" msgstr "" #. Default: "Delete reservation request for: ${name}" -#: redturtle/prenotazioni/browser/delete_reservation.py:61 +#: ../browser/delete_reservation.py:61 msgid "delete_reservation_request" msgstr "" #. Default: "Unique booking code" -#: redturtle/prenotazioni/content/prenotazione.py:181 +#: ../content/prenotazione.py:181 msgid "description_booking_code" msgstr "" #. Default: "If you work for a company, please specify its name." -#: redturtle/prenotazioni/content/prenotazione.py:161 +#: ../content/prenotazione.py:161 msgid "description_company" msgstr "" #. Default: "The gate that will be unavailable" -#: redturtle/prenotazioni/browser/vacations.py:68 +#: ../browser/vacations.py:68 msgid "description_gate" msgstr "" #. Default: "This text will appear in the calendar cells" -#: redturtle/prenotazioni/browser/vacations.py:61 +#: ../browser/vacations.py:61 msgid "description_title" msgstr "" #. Default: "Foreseen booking time: ${booking_time}" -#: redturtle/prenotazioni/browser/week.py:225 +#: ../browser/week.py:225 msgid "foreseen_booking_time" msgstr "" #. Default: "${booking_time}, Orario non disponibile" -#: redturtle/prenotazioni/browser/week.py:244 +#: ../browser/week.py:244 msgid "foreseen_busy_time" msgstr "" -msgid "from_label" -msgstr "" - #. Default: "You should set a start range." -#: redturtle/prenotazioni/content/validators.py:160 +#: ../content/validators.py:160 msgid "from_month_error" msgstr "" #. Default: "Selected day is too big for that month for \"from\" field." -#: redturtle/prenotazioni/content/validators.py:167 +#: ../content/validators.py:167 msgid "from_month_too_days_error" msgstr "" #. Default: "Fullname" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:55 +#: ../browser/templates/prenotazione.pt:55 msgid "fullname" msgstr "" #. Default: "Limit booking in the future to an amount of days in the future starting from the current day. \nKeep 0 to give no limits." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:410 +#: ../content/prenotazioni_folder.py:329 msgid "futureDays" msgstr "" #. Default: "Put gates here (one per line)." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:432 +#: ../content/prenotazioni_folder.py:351 msgid "gates_help" msgstr "" #. Default: "Gates" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:431 +#: ../content/prenotazioni_folder.py:350 msgid "gates_label" msgstr "" -#: redturtle/prenotazioni/browser/prenotazione_add.py:156 +#: ../browser/prenotazione_add.py:156 msgid "help_prenotazione_add" msgstr "" #. Default: "User will not be able to add a booking unless those fields are filled. Remember that, whatever you selected in this list, users have to supply at least one of \"Email\", \"Mobile\", or \"Telephone\"" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:245 +#: ../content/prenotazioni_folder.py:164 msgid "help_required_booking_fields" msgstr "" #. Default: "States if it is not allowed to reserve a booking during the current day" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:284 +#: ../content/prenotazioni_folder.py:203 msgid "help_same_day_booking_disallowed" msgstr "" #. Default: "List of available reservation type for the current agenda" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:424 +#: ../browser/templates/prenotazione_macros.pt:424 msgid "help_tipologies" msgstr "" #. Default: "User will not be able to add a booking unless those fields are filled. Remember that, whatever you selected in this list, users have to supply at least one of \"Email\" or \"Telephone\"" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:227 +#: ../content/prenotazioni_folder.py:146 msgid "help_visible_booking_fields" msgstr "" #. Default: "Set holidays (one for line) in DD/MM/YYYY. you can write * for the year, if this event is yearly." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:385 +#: ../content/prenotazioni_folder.py:304 msgid "holidays_help" msgstr "" #. Default: "Holidays" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:384 +#: ../content/prenotazioni_folder.py:303 msgid "holidays_label" msgstr "" #. Default: "Booking for ${title}" -#: redturtle/prenotazioni/adapters/ical.py:84 +#: ../adapters/ical.py:84 msgid "ical_booking_label" msgstr "" -#: redturtle/prenotazioni/browser/vacations.py:32 +#: ../browser/vacations.py:32 msgid "invalid_date" msgstr "" #. Default: "Invalid email address" -#: redturtle/prenotazioni/content/prenotazione.py:32 +#: ../content/prenotazione.py:32 msgid "invalid_email_address" msgstr "" #. Default: "Invalid start or end date" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:40 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:26 +#: ../browser/prenotazioni_search.py:40 +#: ../browser/stats/booking_stats.py:26 msgid "invalid_end:search_date" msgstr "" #. Default: "Invalid fiscal code" -#: redturtle/prenotazioni/content/prenotazione.py:40 +#: ../content/prenotazione.py:40 msgid "invalid_fiscalcode" msgstr "" #. Default: "Invalid phone number" -#: redturtle/prenotazioni/content/prenotazione.py:28 +#: ../content/prenotazione.py:28 msgid "invalid_phone_number" msgstr "" -#: redturtle/prenotazioni/browser/vacations.py:36 +#: ../browser/vacations.py:36 msgid "invalid_time" msgstr "" #. Default: "This date is past" -#: redturtle/prenotazioni/content/prenotazione.py:36 +#: ../content/prenotazione.py:36 msgid "is_not_future_date" msgstr "" #. Default: "Booking code" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:106 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:123 -#: redturtle/prenotazioni/browser/templates/prenotazione_print.pt:110 +#: ../browser/templates/delete_reservation.pt:106 +#: ../browser/templates/prenotazione.pt:123 +#: ../browser/templates/prenotazione_print.pt:110 msgid "label_booking_code" msgstr "" #. Default: "Company" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:62 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:38 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:75 +#: ../browser/templates/delete_reservation.pt:62 +#: ../browser/templates/manager_notification_mail.pt:38 +#: ../browser/templates/prenotazione.pt:75 msgid "label_booking_company" msgstr "" #. Default: "Booking date" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:80 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:50 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:87 +#: ../browser/templates/delete_reservation.pt:80 +#: ../browser/templates/manager_notification_mail.pt:50 +#: ../browser/templates/prenotazione.pt:87 msgid "label_booking_date" msgstr "" #. Default: "${from_date} at ${at}" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:92 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:54 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:98 +#: ../browser/templates/delete_reservation.pt:92 +#: ../browser/templates/manager_notification_mail.pt:54 +#: ../browser/templates/prenotazione.pt:98 msgid "label_booking_date_range" msgstr "" #. Default: "Subject" -#: redturtle/prenotazioni/browser/prenotazione_add.py:41 -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:74 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:46 +#: ../browser/prenotazione_add.py:41 +#: ../browser/templates/delete_reservation.pt:74 +#: ../browser/templates/manager_notification_mail.pt:46 msgid "label_booking_description" msgstr "" #. Default: "Email" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:50 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:30 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:63 +#: ../browser/templates/delete_reservation.pt:50 +#: ../browser/templates/manager_notification_mail.pt:30 +#: ../browser/templates/prenotazione.pt:63 msgid "label_booking_email" msgstr "" #. Default: "Fiscal code" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:68 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:42 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:79 +#: ../browser/templates/delete_reservation.pt:68 +#: ../browser/templates/manager_notification_mail.pt:42 +#: ../browser/templates/prenotazione.pt:79 msgid "label_booking_fiscalcode" msgstr "" #. Default: "Phone number" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:56 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:34 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:71 +#: ../browser/templates/delete_reservation.pt:56 +#: ../browser/templates/manager_notification_mail.pt:34 +#: ../browser/templates/prenotazione.pt:71 msgid "label_booking_phone" msgstr "" #. Default: "Staff notes" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:113 -#: redturtle/prenotazioni/content/prenotazione.py:186 +#: ../browser/templates/prenotazione.pt:113 +#: ../content/prenotazione.py:186 msgid "label_booking_staff_notes" msgstr "" #. Default: "Booking time" -#: redturtle/prenotazioni/browser/prenotazione_move.py:34 -#: redturtle/prenotazioni/content/prenotazione.py:126 +#: ../browser/prenotazione_move.py:31 +#: ../content/prenotazione.py:126 msgid "label_booking_time" msgstr "" #. Default: "Fullname" -#: redturtle/prenotazioni/browser/prenotazione_add.py:38 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:22 -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:52 +#: ../browser/prenotazione_add.py:38 +#: ../browser/templates/manager_notification_mail.pt:22 +#: ../browser/templates/prenotazioni_search.pt:52 msgid "label_booking_title" msgstr "" #. Default: "Booking type" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:44 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:26 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:59 +#: ../browser/templates/delete_reservation.pt:44 +#: ../browser/templates/manager_notification_mail.pt:26 +#: ../browser/templates/prenotazione.pt:59 msgid "label_booking_type" msgstr "" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:293 -#: redturtle/prenotazioni/vocabularies/requirable_booking_fields.py:24 +#: ../browser/prenotazioni_search.py:293 +#: ../vocabularies/requirable_booking_fields.py:24 msgid "label_booking_{}" msgstr "" #. Default: "End date" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:68 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:52 +#: ../browser/prenotazioni_search.py:68 +#: ../browser/stats/booking_stats.py:52 msgid "label_end" msgstr "" #. Default: "End time" -#: redturtle/prenotazioni/browser/vacations.py:84 +#: ../browser/vacations.py:84 msgid "label_end_time" msgstr "" #. Default: "Gate" -#: redturtle/prenotazioni/browser/prenotazione_move.py:35 -#: redturtle/prenotazioni/browser/prenotazioni_search.py:56 -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:100 +#: ../browser/prenotazione_move.py:32 +#: ../browser/prenotazioni_search.py:56 +#: ../browser/templates/delete_reservation.pt:100 msgid "label_gate" msgstr "" #. Default: "Go to the booking to see more details and manage it: ${url}" -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:65 +#: ../browser/templates/manager_notification_mail.pt:65 msgid "label_new_booking_notify_link" msgstr "" #. Default: "Required booking fields" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:244 +#: ../content/prenotazioni_folder.py:163 msgid "label_required_booking_fields" msgstr "" #. Default: "Disallow same day booking" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:280 +#: ../content/prenotazioni_folder.py:199 msgid "label_same_day_booking_disallowed" msgstr "" #. Default: "Selected date: ${date} — Time: ${slot}" -#: redturtle/prenotazioni/browser/prenotazione_add.py:141 +#: ../browser/prenotazione_add.py:141 msgid "label_selected_date" msgstr "" #. Default: "Start date " -#: redturtle/prenotazioni/browser/prenotazioni_search.py:62 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:45 -#: redturtle/prenotazioni/browser/vacations.py:73 +#: ../browser/prenotazioni_search.py:62 +#: ../browser/stats/booking_stats.py:45 +#: ../browser/vacations.py:73 msgid "label_start" msgstr "" #. Default: "Start time" -#: redturtle/prenotazioni/browser/vacations.py:78 +#: ../browser/vacations.py:78 msgid "label_start_time" msgstr "" #. Default: "Text to search" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:48 +#: ../browser/prenotazioni_search.py:48 msgid "label_text" msgstr "" #. Default: "Reservation types" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:423 +#: ../browser/templates/prenotazione_macros.pt:423 msgid "label_tipologies" msgstr "" #. Default: "Title" -#: redturtle/prenotazioni/browser/vacations.py:60 +#: ../browser/vacations.py:60 msgid "label_title" msgstr "" #. Default: "User" -#: redturtle/prenotazioni/browser/stats/booking_stats.py:43 +#: ../browser/stats/booking_stats.py:43 msgid "label_user" msgstr "" #. Default: "Visible booking fields" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:226 +#: ../content/prenotazioni_folder.py:145 msgid "label_visible_booking_fields" msgstr "" #. Default: "Legend" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:447 +#: ../browser/templates/prenotazione_macros.pt:447 msgid "legend" msgstr "" #. Default: "Short description of available action for the booking board" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:448 +#: ../browser/templates/prenotazione_macros.pt:448 msgid "legend_description" msgstr "" #. Default: "The minimum value of a single slot is 5 minutes. You cannot book a reservation when the needed time exceeds the available time." -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:469 +#: ../browser/templates/prenotazione_macros.pt:469 msgid "legend_note" msgstr "" #. Default: "The number of simultaneous bookings allowed for the same user." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:602 +#: ../content/prenotazioni_folder.py:449 msgid "max_bookings_allowed_description" msgstr "" #. Default: "Maximum bookings number allowed" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:598 +#: ../content/prenotazioni_folder.py:445 msgid "max_bookings_allowed_label" msgstr "" -#. Default: "Type in here the message that you want to mail. Some defined content can be replaced: ${title} will be replaced with booking title (user fullname). ${date} will be replaced with booking new date. ${url} will be replaced by the booking url. ${portal} will be replaced by the title of the portal." -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:43 -msgid "message_help" -msgstr "" - #. Default: "Unable to find a booking with the givend id: ${uid}." -#: redturtle/prenotazioni/browser/delete_reservation.py:44 +#: ../browser/delete_reservation.py:44 msgid "missing_booking" msgstr "" #. Default: "You need to provide a reservation id." -#: redturtle/prenotazioni/browser/delete_reservation.py:38 +#: ../browser/delete_reservation.py:38 msgid "missing_uid" msgstr "" -msgid "month_label" -msgstr "" - #. Default: "End time in the morning" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:87 +#: ../content/prenotazioni_folder.py:84 msgid "morning_end_label" msgstr "" #. Default: "Start time in the morning" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:82 +#: ../content/prenotazioni_folder.py:79 msgid "morning_start_label" msgstr "" #. Default: "Go back to the calendar" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:260 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:192 -#: redturtle/prenotazioni/browser/templates/prenotazione_add.pt:127 +#: ../browser/prenotazioni_search.py:260 +#: ../browser/templates/prenotazione.pt:192 +#: ../browser/templates/prenotazione_add.pt:127 msgid "move_back_message" msgstr "" #. Default: "Move booking" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:163 +#: ../browser/templates/prenotazione.pt:163 msgid "move_booking" msgstr "" #. Default: "Please move this booking into a new available slot or" -#: redturtle/prenotazioni/browser/templates/prenotazione_move.pt:39 +#: ../browser/templates/prenotazione_move.pt:39 msgid "move_message" msgstr "" #. Default: "next week" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:39 +#: ../browser/templates/prenotazione_macros.pt:39 msgid "next-week" msgstr "" #. Default: "Booking is not allowed before the amount of days specified. \nKeep 0 to give no limits." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:422 +#: ../content/prenotazioni_folder.py:341 msgid "notBeforeDays" msgstr "" +#. Default: "Enable AppIO notifications." +#: ../behaviors/booking_folder/appio/__init__.py:123 +msgid "notifications_appio_enabled_help" +msgstr "" + +#. Default: "AppIO notifications" +#: ../behaviors/booking_folder/appio/__init__.py:122 +msgid "notifications_appio_enabled_label" +msgstr "" + +#. Default: "Enable Email notifications." +#: ../behaviors/booking_folder/email/__init__.py:123 +msgid "notifications_email_enabled_help" +msgstr "" + +#. Default: "Email notifications" +#: ../behaviors/booking_folder/email/__init__.py:122 +msgid "notifications_email_enabled_label" +msgstr "" + #. Default: "Notifications" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:642 +#: ../content/prenotazioni_folder.py:508 msgid "notifications_label" msgstr "" +#. Default: "Enable SMS notifications." +#: ../behaviors/booking_folder/sms/__init__.py:70 +msgid "notifications_sms_enabled_help" +msgstr "" + +#. Default: "SMS notifications" +#: ../behaviors/booking_folder/sms/__init__.py:69 +msgid "notifications_sms_enabled_label" +msgstr "" + +#. Default: "This is an automatic reminder about your booking on ${date} for ${booking_type}.

You can see details and print a reminder following this [link](${booking_print_url})." +#: ../behaviors/booking_folder/appio/__init__.py:111 +msgid "notify_as_reminder_appio_message_default_value" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking reminder on ${booking_date}" +#: ../behaviors/booking_folder/appio/__init__.py:101 +msgid "notify_as_reminder_appio_subject_default_value" +msgstr "" + +#. Default: "The message subject when a reminder will be sent." +#: ../behaviors/booking_folder/appio/__init__.py:231 +msgid "notify_as_reminder_appio_subject_help" +msgstr "" + +#. Default: "[Reminder] message" +#: ../behaviors/booking_folder/appio/__init__.py:239 +#: ../behaviors/booking_folder/email/__init__.py:239 +#: ../behaviors/booking_folder/sms/__init__.py:126 +msgid "notify_as_reminder_message" +msgstr "" + +#. Default: "This is an automatic reminder about your booking on ${date} for ${booking_type}.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:111 +msgid "notify_as_reminder_message_default_value" +msgstr "" + +#. Default: "The message text when a reminder will be sent." +#: ../behaviors/booking_folder/appio/__init__.py:243 +#: ../behaviors/booking_folder/email/__init__.py:243 +#: ../behaviors/booking_folder/sms/__init__.py:130 +msgid "notify_as_reminder_message_help" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}]: This is an automatic reminder about your booking on ${date} for ${booking_type}.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:58 +msgid "notify_as_reminder_sms_message_default_value" +msgstr "" + +#. Default: "[Reminder] subject" +#: ../behaviors/booking_folder/appio/__init__.py:227 +#: ../behaviors/booking_folder/email/__init__.py:227 +msgid "notify_as_reminder_subject" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking reminder on ${booking_date}" +#: ../behaviors/booking_folder/email/__init__.py:101 +msgid "notify_as_reminder_subject_default_value" +msgstr "" + +#. Default: "The message subject when a reminder will be sent." +#: ../behaviors/booking_folder/email/__init__.py:231 +msgid "notify_as_reminder_subject_help" +msgstr "" + #. Default: "Notify when confirmed." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:498 +#: ../content/prenotazioni_folder.py:418 msgid "notify_on_confirm" msgstr "" +#. Default: "The booking ${booking_type} for ${title} has been confirmed.

You can see details and print a reminder following this [link](${booking_print_url})." +#: ../behaviors/booking_folder/appio/__init__.py:48 +msgid "notify_on_confirm_appio_message_default_value" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking of ${booking_date} at ${booking_time} was accepted" +#: ../behaviors/booking_folder/appio/__init__.py:38 +msgid "notify_on_confirm_appio_subject_default_value" +msgstr "" + #. Default: "Notify via mail the user when his booking has been confirmed." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:499 +#: ../content/prenotazioni_folder.py:419 msgid "notify_on_confirm_help" msgstr "" -#. Default: "Prenotazione confirmed notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:552 +#. Default: "[Confirmed] message" +#: ../behaviors/booking_folder/appio/__init__.py:167 +#: ../behaviors/booking_folder/email/__init__.py:167 +#: ../behaviors/booking_folder/sms/__init__.py:90 msgid "notify_on_confirm_message" msgstr "" -#. Default: "The booking${booking_type} for ${title} was confirmed! Link" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:164 -#: redturtle/prenotazioni/upgrades.py:257 +#. Default: "The booking ${booking_type} for ${title} has been confirmed.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:48 msgid "notify_on_confirm_message_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:556 +#. Default: "The message text when a booking has been confirmed." +#: ../behaviors/booking_folder/appio/__init__.py:171 +#: ../behaviors/booking_folder/email/__init__.py:171 +#: ../behaviors/booking_folder/sms/__init__.py:94 msgid "notify_on_confirm_message_help" msgstr "" -#. Default: "Prenotazione confirmed notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:543 +#. Default: "[${prenotazioni_folder_title}]: Booking of ${booking_date} at ${booking_time} has been accepted.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:28 +msgid "notify_on_confirm_sms_message_default_value" +msgstr "" + +#. Default: "[Confirm] subject" +#: ../behaviors/booking_folder/appio/__init__.py:155 +#: ../behaviors/booking_folder/email/__init__.py:155 msgid "notify_on_confirm_subject" msgstr "" -#. Default: "Booking of ${booking_date} at ${booking_time} was accepted" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:154 -#: redturtle/prenotazioni/upgrades.py:250 +#. Default: "[${prenotazioni_folder_title}] Booking of ${booking_date} at ${booking_time} was accepted" +#: ../behaviors/booking_folder/email/__init__.py:38 msgid "notify_on_confirm_subject_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:547 +#. Default: "The message subject when a booking has been confirmed." +#: ../behaviors/booking_folder/appio/__init__.py:159 +#: ../behaviors/booking_folder/email/__init__.py:159 msgid "notify_on_confirm_subject_help" msgstr "" #. Default: "Notify when moved." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:507 +#: ../content/prenotazioni_folder.py:427 msgid "notify_on_move" msgstr "" +#. Default: "The booking scheduling for ${booking_type} was modified.

The new one is on ${booking_date} at ${booking_time}.

You can see details and print a reminder following this [link](${booking_print_url})." +#: ../behaviors/booking_folder/appio/__init__.py:69 +msgid "notify_on_move_appio_message_default_value" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking date modified for ${title}" +#: ../behaviors/booking_folder/appio/__init__.py:59 +msgid "notify_on_move_appio_subject_default_value" +msgstr "" + #. Default: "Notify via mail the user when his booking has been moved." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:508 +#: ../content/prenotazioni_folder.py:428 msgid "notify_on_move_help" msgstr "" -#. Default: "Prenotazione moved notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:570 +#. Default: "[Move] message" +#: ../behaviors/booking_folder/appio/__init__.py:191 +#: ../behaviors/booking_folder/email/__init__.py:191 +#: ../behaviors/booking_folder/sms/__init__.py:102 msgid "notify_on_move_message" msgstr "" -#. Default: "The booking scheduling of ${booking_type} was modified.The new one is on ${booking_date} at ${booking_time}. Link." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:184 -#: redturtle/prenotazioni/upgrades.py:271 +#. Default: "The booking scheduling for ${booking_type} was modified.

The new one is on ${booking_date} at ${booking_time}.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:69 msgid "notify_on_move_message_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:574 +#. Default: "The message text when a booking has been moved." +#: ../behaviors/booking_folder/appio/__init__.py:195 +#: ../behaviors/booking_folder/email/__init__.py:195 +#: ../behaviors/booking_folder/sms/__init__.py:106 msgid "notify_on_move_message_help" msgstr "" -#. Default: "Prenotazione moved notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:561 +#. Default: "[${prenotazioni_folder_title}]: The booking scheduling for ${booking_type} was modified.\nThe new one is on ${booking_date} at ${booking_time}.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:38 +msgid "notify_on_move_sms_message_default_value" +msgstr "" + +#. Default: "[Move] subject" +#: ../behaviors/booking_folder/appio/__init__.py:179 +#: ../behaviors/booking_folder/email/__init__.py:179 msgid "notify_on_move_subject" msgstr "" -#. Default: "Modified the boolking date for ${title}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:174 -#: redturtle/prenotazioni/upgrades.py:264 +#. Default: "[${prenotazioni_folder_title}] Booking date modified for ${title}" +#: ../behaviors/booking_folder/email/__init__.py:59 msgid "notify_on_move_subject_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:565 +#. Default: "The message subject when a booking has been moved." +#: ../behaviors/booking_folder/appio/__init__.py:183 +#: ../behaviors/booking_folder/email/__init__.py:183 msgid "notify_on_move_subject_help" msgstr "" #. Default: "Notify when rejected." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:516 +#: ../content/prenotazioni_folder.py:436 msgid "notify_on_refuse" msgstr "" +#. Default: "The booking ${booking_type} of ${booking_date} at ${booking_time} was refused." +#: ../behaviors/booking_folder/appio/__init__.py:91 +msgid "notify_on_refuse_appio_message_default_value" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking refused for ${title}" +#: ../behaviors/booking_folder/appio/__init__.py:81 +msgid "notify_on_refuse_appio_subject_default_value" +msgstr "" + #. Default: "Notify via mail the user when his booking has been rejected." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:517 +#: ../content/prenotazioni_folder.py:437 msgid "notify_on_refuse_help" msgstr "" -#. Default: "Prenotazione created notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:588 +#. Default: "[Refuse] message" +#: ../behaviors/booking_folder/appio/__init__.py:215 +#: ../behaviors/booking_folder/email/__init__.py:215 +#: ../behaviors/booking_folder/sms/__init__.py:114 msgid "notify_on_refuse_message" msgstr "" #. Default: "The booking ${booking_type} of ${booking_date} at ${booking_time} was refused." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:205 -#: redturtle/prenotazioni/upgrades.py:286 +#: ../behaviors/booking_folder/email/__init__.py:91 msgid "notify_on_refuse_message_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:592 +#. Default: "The message text when a booking has been refused." +#: ../behaviors/booking_folder/appio/__init__.py:219 +#: ../behaviors/booking_folder/email/__init__.py:219 +#: ../behaviors/booking_folder/sms/__init__.py:118 msgid "notify_on_refuse_message_help" msgstr "" -#. Default: "Prenotazione refused notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:579 +#. Default: "[${prenotazioni_folder_title}]: The booking ${booking_type} of ${booking_date} at ${booking_time} was refused." +#: ../behaviors/booking_folder/sms/__init__.py:48 +msgid "notify_on_refuse_sms_message_default_value" +msgstr "" + +#. Default: "[Refuse] subject" +#: ../behaviors/booking_folder/appio/__init__.py:203 +#: ../behaviors/booking_folder/email/__init__.py:203 msgid "notify_on_refuse_subject" msgstr "" -#. Default: "Booking refused for ${title}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:195 -#: redturtle/prenotazioni/upgrades.py:279 +#. Default: "[${prenotazioni_folder_title}] Booking refused for ${title}" +#: ../behaviors/booking_folder/email/__init__.py:81 msgid "notify_on_refuse_subject_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:583 +#. Default: "The message subject when a booking has been refused." +#: ../behaviors/booking_folder/appio/__init__.py:207 +#: ../behaviors/booking_folder/email/__init__.py:207 msgid "notify_on_refuse_subject_help" msgstr "" #. Default: "Notify when created." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:489 +#: ../content/prenotazioni_folder.py:409 msgid "notify_on_submit" msgstr "" +#. Default: "Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.

You can see details and print a reminder following this [${booking_print_url}](link)." +#: ../behaviors/booking_folder/appio/__init__.py:28 +msgid "notify_on_submit_appio_message_default_value" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking created" +#: ../behaviors/booking_folder/appio/__init__.py:18 +msgid "notify_on_submit_appio_subject_default_value" +msgstr "" + #. Default: "Notify via mail the user when his booking has been created. If auto-confirm flag is selected and confirm notify is selected, this one will be ignored." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:490 +#: ../content/prenotazioni_folder.py:410 msgid "notify_on_submit_help" msgstr "" -#. Default: "Prenotazione created notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:534 +#. Default: "[Created] message" +#: ../behaviors/booking_folder/appio/__init__.py:143 +#: ../behaviors/booking_folder/email/__init__.py:143 +#: ../behaviors/booking_folder/sms/__init__.py:78 msgid "notify_on_submit_message" msgstr "" -#. Default: "Booking ${booking_type} for ${booking_date} at ${booking_time} was created.Link" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:144 -#: redturtle/prenotazioni/upgrades.py:243 +#. Default: "Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:28 msgid "notify_on_submit_message_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:538 +#. Default: "The message text when a booking has been created." +#: ../behaviors/booking_folder/appio/__init__.py:147 +#: ../behaviors/booking_folder/email/__init__.py:147 +#: ../behaviors/booking_folder/sms/__init__.py:82 msgid "notify_on_submit_message_help" msgstr "" -#. Default: "Prenotazione created notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:525 +#. Default: "[${prenotazioni_folder_title}]: Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:18 +msgid "notify_on_submit_sms_message_default_value" +msgstr "" + +#. Default: "[Created] subject" +#: ../behaviors/booking_folder/appio/__init__.py:131 +#: ../behaviors/booking_folder/email/__init__.py:131 msgid "notify_on_submit_subject" msgstr "" -#. Default: "Booking created ${title}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:137 -#: redturtle/prenotazioni/upgrades.py:239 +#. Default: "[${prenotazioni_folder_title}] Booking created" +#: ../behaviors/booking_folder/email/__init__.py:18 msgid "notify_on_submit_subject_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:529 +#. Default: "The message subject when a booking has been created." +#: ../behaviors/booking_folder/appio/__init__.py:135 +#: ../behaviors/booking_folder/email/__init__.py:135 msgid "notify_on_submit_subject_help" msgstr "" #. Default: "Pause end" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:128 +#: ../content/prenotazioni_folder.py:125 msgid "pause_end_label" msgstr "" #. Default: "Pause start" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:123 +#: ../content/prenotazioni_folder.py:120 msgid "pause_start_label" msgstr "" #. Default: "Please select a time slot" -#: redturtle/prenotazioni/browser/prenotazione_add.py:280 +#: ../browser/prenotazione_add.py:280 msgid "please_pick_a_date" msgstr "" #. Default: "${day}, ore ${booking_time}" -#: redturtle/prenotazioni/browser/week.py:256 +#: ../browser/week.py:256 msgid "prenotation_slot_message" msgstr "" -#. Default: "Testo delle email di notifica" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:652 -msgid "prenotazioni_email_templates_label" -msgstr "" - #. Default: "prenotazioni_search" -#: redturtle/prenotazioni/profiles/default/actions.xml +#: ../profiles/default/actions.xml msgid "prenotazioni_search" msgstr "" #. Default: "previous week" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:14 +#: ../browser/templates/prenotazione_macros.pt:14 msgid "previous-week" msgstr "" -#: redturtle/prenotazioni/configure.zcml:32 +#: ../configure.zcml:31 msgid "redturtle.prenotazioni" msgstr "" -#: redturtle/prenotazioni/configure.zcml:49 +#: ../configure.zcml:48 msgid "redturtle.prenotazioni (to_1500)" msgstr "" -#: redturtle/prenotazioni/configure.zcml:41 +#: ../configure.zcml:40 +#: ../staging/configure.zcml:25 msgid "redturtle.prenotazioni (uninstall)" msgstr "" -#: redturtle/prenotazioni/configure.zcml:49 +#: ../configure.zcml:48 msgid "redturtle.prenotazioni to 1500." msgstr "" +#: ../staging/configure.zcml:16 +msgid "redturtle.prenotazioni.staging" +msgstr "" + #. Default: "The booking state is \"refused\". If you change it, the booking time may conflict with another one." -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:30 +#: ../browser/templates/prenotazione.pt:30 msgid "refused-review-state-warning" msgstr "" #. Default: "Reject booking" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:176 +#: ../browser/templates/prenotazione.pt:176 msgid "reject_booking" msgstr "" -#. Default: "Reminders" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:700 -msgid "reminders_label" +#. Default: "Set how many days before of a booking date the user will be notified about it." +#: ../content/prenotazioni_folder.py:461 +msgid "reminder_notification_gap_description" +msgstr "" + +#. Default: "Booking reminder days" +#: ../content/prenotazioni_folder.py:457 +msgid "reminder_notification_gap_label" msgstr "" #. Default: "Code" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:58 +#: ../browser/templates/prenotazioni_search.pt:58 msgid "reservation_code" msgstr "" #. Default: "Reservation date" -#: redturtle/prenotazioni/browser/templates/prenotazione_move.pt:33 -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:57 +#: ../browser/templates/prenotazione_move.pt:33 +#: ../browser/templates/prenotazioni_search.pt:57 msgid "reservation_date" msgstr "" #. Default: "Booking request for: ${name}" -#: redturtle/prenotazioni/browser/prenotazione_print.py:44 +#: ../browser/prenotazione_print.py:44 msgid "reservation_request" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:30 +#: ../browser/templates/prenotazione_macros.pt:30 msgid "resize" msgstr "" #. Default: "items matching your search terms." -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:30 +#: ../browser/templates/prenotazioni_search.pt:30 msgid "result_number" msgstr "" #. Default: "You need to provide a booking date to get the schema and available types." -#: redturtle/prenotazioni/restapi/services/booking_schema/get.py:71 +#: ../restapi/services/booking_schema/get.py:71 msgid "schema_missing_date" msgstr "" #. Default: "Search by gate" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:465 +#: ../browser/templates/prenotazione_macros.pt:465 msgid "search-by-gate" msgstr "" #. Default: "Search result" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:12 +#: ../browser/templates/prenotazioni_search.pt:12 msgid "search_result_message" msgstr "" #. Default: "seleziona l'opzione desiderata dal gruppo di radio button seguente" -#: redturtle/prenotazioni/browser/z3c_custom_widget.py:153 +#: ../browser/z3c_custom_widget.py:153 msgid "select-option" msgstr "" -#. Default: "This gate has some booking schedule in this time period." -#: redturtle/prenotazioni/browser/vacations.py:217 -msgid "slot_conflict_error" +#. Default: "AppIO service code related to the current booking type" +#: ../behaviors/booking_folder/appio/__init__.py:293 +msgid "service_code_help" msgstr "" -#. Default: "The email address that sends the email. If no email is provided here, it will use the address from portal." -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:33 -msgid "source_help" +#. Default: "AppIO service code." +#: ../behaviors/booking_folder/appio/__init__.py:289 +msgid "service_code_label" msgstr "" -#. Default: "You cannot book any booking_type at this time" -#: redturtle/prenotazioni/browser/prenotazione_add.py:284 -msgid "time_slot_to_short" +#. Default: "This gate has some booking schedule in this time period." +#: ../browser/vacations.py:217 +msgid "slot_conflict_error" msgstr "" -msgid "to_label" +#. Default: "You cannot book any booking_type at this time" +#: ../browser/prenotazione_add.py:284 +msgid "time_slot_to_short" msgstr "" #. Default: "You should set an end range." -#: redturtle/prenotazioni/content/validators.py:175 +#: ../content/validators.py:175 msgid "to_month_error" msgstr "" #. Default: "Selected day is too big for that month for \"to\" field." -#: redturtle/prenotazioni/content/validators.py:182 +#: ../content/validators.py:182 msgid "to_month_too_days_error" msgstr "" #. Default: "You can't add a booking with type '${booking_type}'." -#: redturtle/prenotazioni/restapi/services/booking/add.py:84 +#: ../restapi/services/booking/add.py:89 msgid "unauthorized_add_vacation" msgstr "" #. Default: "Unbookable time" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:452 +#: ../browser/templates/prenotazione_macros.pt:452 msgid "unbookable_time" msgstr "" #. Default: "vacation_booking" -#: redturtle/prenotazioni/profiles/default/actions.xml +#: ../profiles/default/actions.xml msgid "vacation_booking" msgstr "" #. Default: "View booking" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:143 -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:463 +#: ../browser/templates/prenotazione.pt:143 +#: ../browser/templates/prenotazione_macros.pt:463 msgid "view_booking" msgstr "" #. Default: "Insert here week schema for some custom date intervals." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:362 +#: ../content/prenotazioni_folder.py:281 msgid "week_table_overrides_help" msgstr "" #. Default: "Week table overrides" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:361 +#: ../content/prenotazioni_folder.py:280 msgid "week_table_overrides_label" msgstr "" #. Default: "You tried to delete booking with a wrong action." -#: redturtle/prenotazioni/browser/delete_reservation.py:97 +#: ../browser/delete_reservation.py:97 msgid "wrong_authenticator" msgstr "" diff --git a/src/redturtle/prenotazioni/locales/it/LC_MESSAGES/redturtle.prenotazioni.po b/src/redturtle/prenotazioni/locales/it/LC_MESSAGES/redturtle.prenotazioni.po index f2c593e2..5c508e94 100644 --- a/src/redturtle/prenotazioni/locales/it/LC_MESSAGES/redturtle.prenotazioni.po +++ b/src/redturtle/prenotazioni/locales/it/LC_MESSAGES/redturtle.prenotazioni.po @@ -1,8 +1,7 @@ -# Alessandro Pisa , 2013, 2014. msgid "" msgstr "" "Project-Id-Version: \n" -"POT-Creation-Date: 2023-12-14 13:19+0000\n" +"POT-Creation-Date: 2024-01-04 01:37+0000\n" "PO-Revision-Date: 2014-05-27 17:36+0200\n" "Last-Translator: Alessandro Pisa \n" "Language-Team: American English \n" @@ -17,1448 +16,1632 @@ msgstr "" "Language: en_US\n" "X-Generator: Lokalize 1.5\n" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:63 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:46 -#: redturtle/prenotazioni/browser/vacations.py:74 +#: ../browser/prenotazioni_search.py:63 +#: ../browser/stats/booking_stats.py:46 +#: ../browser/vacations.py:74 msgid " format (YYYY-MM-DD)" msgstr "Formato (AAAA-MM-GG)" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniFolder.xml +#: ../profiles/default/types/PrenotazioniFolder.xml msgid "A folder that will contain booking" msgstr "Una cartella che conterrà le prenotazioni" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "A folder that will contain booking for this day" msgstr "Una cartella che conterrà le prenotazioni per questo day" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:166 -msgid "A mail action that sends email notify when a booking is moved in an other slot." -msgstr "Un'azione che spedisce una mail di notifica quando una prenotazione è spostata un un altro slot." - -msgid "Add" -msgstr "Aggiungi" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:165 -msgid "Add moved booking Mail Action" -msgstr "Aggiungi Mail Action per lo spostamento delle prenotazioni" - -#: redturtle/prenotazioni/content/prenotazioni_folder.py:478 -#: redturtle/prenotazioni/content/validators.py:213 +#: ../content/prenotazioni_folder.py:406 +#: ../content/validators.py:213 msgid "Afternoon start should not be greater than end." msgstr "L'orario di inizio del pomeriggio non può essere successivo alla chiusura." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:483 -msgid "App IO notification" -msgstr "Notifiche App IO" - -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:29 +#: ../browser/templates/prenotazione.pt:29 msgid "Attention" msgstr "Attenzione!" -#: redturtle/prenotazioni/adapters/stringinterp.py:27 +#: ../adapters/stringinterp.py:27 msgid "Booking" msgstr "Prenotazioni" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniFolder.xml +#: ../profiles/default/types/PrenotazioniFolder.xml msgid "Booking Folder" msgstr "Cartella prenotazioni" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioneType.xml +#: ../profiles/default/types/PrenotazioneType.xml msgid "Booking Type" msgstr "Tipologia Prenotazione" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniWeek.xml +#: ../profiles/default/types/PrenotazioniWeek.xml msgid "Booking Week Folder" msgstr "Cartella settimana prenotazioni" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniYear.xml +#: ../profiles/default/types/PrenotazioniYear.xml msgid "Booking Year Folder" msgstr "Cartella anno prenotazioni" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:44 +#: ../behaviors/booking_folder/appio/configure.zcml:17 +msgid "Booking folder notification appio" +msgstr "" + +#: ../behaviors/booking_folder/email/configure.zcml:17 +msgid "Booking folder notification email" +msgstr "" + +#: ../behaviors/booking_folder/sms/configure.zcml:17 +msgid "Booking folder notification sms" +msgstr "" + +#: ../browser/templates/prenotazione.pt:44 msgid "Booking for" msgstr "Prenotazione di" -#: redturtle/prenotazioni/contentrules/configure.zcml:30 -msgid "Booking moved" -msgstr "Prenotazione spostata" +#: ../behaviors/booking_folder/appio/configure.zcml:27 +msgid "Booking type notification appio" +msgstr "" #. Default: "Change date/time" -#: redturtle/prenotazioni/profiles/default/actions.xml +#: ../profiles/default/actions.xml msgid "Change date/time" msgstr "Cambia la data di prenotazione." #. Default: "Complete address" -#: redturtle/prenotazioni/behaviors/booking_folder.py:43 +#: ../behaviors/booking_folder/contacts.py:43 msgid "Complete address" msgstr "Indirizzo completo" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:170 -msgid "Configure element" -msgstr "Configura elemento" - -#: redturtle/prenotazioni/behaviors/booking_folder.py:36 +#: ../behaviors/booking_folder/contacts.py:36 msgid "Contact PEC" msgstr "Indirizzo PEC per il contatto" -#: redturtle/prenotazioni/behaviors/booking_folder.py:30 +#: ../behaviors/booking_folder/contacts.py:30 msgid "Contact fax" msgstr "Numero di FAX per il contatto" -#: redturtle/prenotazioni/behaviors/booking_folder.py:24 +#: ../behaviors/booking_folder/contacts.py:24 msgid "Contact phone" msgstr "Numero di telefono per il contatto" -#: redturtle/prenotazioni/behaviors/configure.zcml:19 +#: ../behaviors/booking_folder/configure.zcml:19 msgid "Contacts fields." -msgstr "" +msgstr "Campi di contatto." -#: redturtle/prenotazioni/behaviors/configure.zcml:19 +#: ../behaviors/booking_folder/configure.zcml:19 msgid "Contatti cartella prenotazioni" -msgstr "" +msgstr "Contatti cartella prenotazioni" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:46 +#: ../browser/templates/prenotazioni_search.pt:46 msgid "Content listing" msgstr "Elenco dei contenuti" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:262 +#: ../content/prenotazioni_folder.py:181 msgid "Data fine validità" msgstr "Data fine validità" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:259 +#: ../content/prenotazioni_folder.py:178 msgid "Data inizio validità" msgstr "Data inizio validità" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:612 +#: ../content/prenotazioni_folder.py:471 msgid "Date validità" -msgstr "" +msgstr "Date Validità" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:421 +#: ../content/prenotazioni_folder.py:340 msgid "Days booking is not allowed before" msgstr "Giorni da cui si può effettuare una prenotazione" -msgid "Delete" -msgstr "Elimina" - #. Default: "Descrizione Agenda" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:218 +#: ../content/prenotazioni_folder.py:137 msgid "Descrizione Agenda" msgstr "Descrizione Agenda" -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioneType.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/PrenotazioneType.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "Edit" msgstr "Modifica" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:185 -msgid "Edit moved booking Mail Action" -msgstr "Modifica Mail Action per lo spostamento delle prenotazioni" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:72 -msgid "Email report to prenotazione owner" -msgstr "Report email al creatore della prenotazione" - -#: redturtle/prenotazioni/content/prenotazione.py:175 +#: ../content/prenotazione.py:175 msgid "Expiration date booking" msgstr "Data scandenza prenotazione" #. Default: "Campo" -#: redturtle/prenotazioni/browser/z3c_custom_widget.py:150 +#: ../browser/z3c_custom_widget.py:150 msgid "Field" msgstr "Campo" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:116 +#: ../content/prenotazioni_folder.py:113 msgid "Friday" msgstr "Venerdì" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:107 -#: redturtle/prenotazioni/content/prenotazione.py:170 +#: ../browser/templates/prenotazione.pt:107 +#: ../content/prenotazione.py:170 msgid "Gate" msgstr "Postazione" -msgid "Group" -msgstr "Gruppo" - #. Default: "How to get here" -#: redturtle/prenotazioni/behaviors/booking_folder.py:19 +#: ../behaviors/booking_folder/contacts.py:19 msgid "How to get here" msgstr "Indicazioni su come raggiungere l'ufficio" -#: redturtle/prenotazioni/content/validators.py:136 +#: ../content/validators.py:136 msgid "In the same day there are overlapping intervals" msgstr "Ci sono pause che si sovrappongono nello stesso giorno" -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/Prenotazione.xml msgid "Informations about a single booking" msgstr "Informazioni relativa ad una singola prenotazione" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:219 +#: ../content/prenotazioni_folder.py:138 msgid "Inserire il testo di presentazione dell'agenda corrente" msgstr "Inserire il testo di presentazione dell'agenda corrente" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:450 +#: ../content/prenotazioni_folder.py:378 msgid "Insert a list of email addresses that will be notified when new bookings get created." msgstr "Inserisci una lista di indirizzi email che verranno notificati alla creazione di una nuova prenotazione." -#: redturtle/prenotazioni/behaviors/booking_folder.py:20 +#: ../behaviors/booking_folder/contacts.py:20 msgid "Insert here indications on how to reach the office" msgstr "Scrivere le indicazioni complete per raggiungere l'ufficio" -#: redturtle/prenotazioni/behaviors/booking_folder.py:44 +#: ../behaviors/booking_folder/contacts.py:44 msgid "Insert here the complete office address" msgstr "Inserire l'indirizzo dell'ufficio" -#: redturtle/prenotazioni/behaviors/booking_folder.py:37 +#: ../behaviors/booking_folder/contacts.py:37 msgid "Insert here the contact PEC" msgstr "Inserire l'indirizzo di posta PEC per contattare l'ufficio" -#: redturtle/prenotazioni/behaviors/booking_folder.py:31 +#: ../behaviors/booking_folder/contacts.py:31 msgid "Insert here the contact fax" msgstr "Inserire il numero di FAX per per contattare l'ufficio" -#: redturtle/prenotazioni/behaviors/booking_folder.py:25 +#: ../behaviors/booking_folder/contacts.py:25 msgid "Insert here the contact phone" msgstr "Inserire il numero di telefono per contattare l'ufficio" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:372 +#: ../content/prenotazioni_folder.py:291 msgid "Insert pause table schema." msgstr "Inserisci le pause giornaliere. Esistono tre tipi di vincolo: una data di termine pausa deve essere maggiore della data di inizio pausa; le pause nello stesso giorno non possono sovrapporsi; le pause devono essere comprese fra l'inizio e la fine dell'orario di lavoro." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:295 +#: ../content/prenotazioni_folder.py:214 msgid "Insert week table schema." msgstr "Compila la tabella degli orari della settimana." -#: redturtle/prenotazioni/configure.zcml:32 +#: ../configure.zcml:31 msgid "Installs the redturtle.prenotazioni add-on." msgstr "Install redturtle.prenotazioni" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:409 +#: ../staging/configure.zcml:16 +msgid "Installs the redturtle.prenotazioni.staging add-on (demo site purpose only)." +msgstr "" + +#: ../content/prenotazioni_folder.py:328 msgid "Max days in the future" msgstr "Massimi giorni nel futuro" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:42 -msgid "Message" -msgstr "Messaggio" - -#: redturtle/prenotazioni/content/prenotazioni_folder.py:112 +#: ../content/prenotazioni_folder.py:109 msgid "Monday" msgstr "Lunedì" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:475 -#: redturtle/prenotazioni/content/validators.py:208 +#: ../content/prenotazioni_folder.py:403 +#: ../content/validators.py:208 msgid "Morning start should not be greater than end." msgstr "L'orario di inizio della mattina non può essere successivo alla fine." -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:152 +#: ../browser/templates/prenotazione.pt:152 msgid "Move booking" msgstr "Sposta la prenotazione" -msgid "Move down" -msgstr "Sposta in giù" - -msgid "Move up" -msgstr "Sposta in su" - -#: redturtle/prenotazioni/restapi/services/booking/vacation.py:27 +#: ../restapi/services/booking/vacation.py:27 msgid "Nessuno slot creato, verificare la corretteza dei dati inseriti" -msgstr "" +msgstr "Nessuno slot creato, verificare la corretteza dei dati inseriti" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:274 +#: ../content/prenotazioni_folder.py:193 msgid "No" msgstr "No" -#: redturtle/prenotazioni/content/pause.py:43 +#: ../behaviors/booking_folder/appio/configure.zcml:17 +msgid "Notification APPIo" +msgstr "" + +#: ../behaviors/booking_folder/appio/configure.zcml:27 +msgid "Notification APPIo for PrenotazioneType c.t." +msgstr "" + +#: ../behaviors/booking_folder/sms/configure.zcml:17 +msgid "Notification SMS" +msgstr "" + +#: ../behaviors/booking_folder/email/configure.zcml:17 +msgid "Notification email templates" +msgstr "" + +#: ../content/pause.py:43 msgid "Pause" msgstr "Pausa" -#: redturtle/prenotazioni/content/validators.py:100 +#: ../content/validators.py:100 msgid "Pause end should be greater than pause start" msgstr "Il termine della pausa non può avvenire prima del suo inizio" -#: redturtle/prenotazioni/content/validators.py:121 +#: ../content/validators.py:121 msgid "Pause should be included in morning slot or afternoon slot" msgstr "Le pause devono essere comprese tra l'orario di inizio o di termine dell'intervallo di orari di lavoro" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:371 +#: ../content/prenotazioni_folder.py:290 msgid "Pause table" msgstr "Schedulazione delle pause" -#: redturtle/prenotazioni/browser/prenotazione_add.py:221 +#: ../browser/prenotazione_add.py:221 msgid "Please provide a booking date" msgstr "Per favore seleziona una data." -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/Prenotazione.xml msgid "Prenotazione" msgstr "Prenotazione" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "PrenotazioniDay" msgstr "PrenotazioniDay" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniWeek.xml +#: ../profiles/default/types/PrenotazioniWeek.xml msgid "PrenotazioniWeek" msgstr "PrenotazioniWeek" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniYear.xml +#: ../profiles/default/types/PrenotazioniYear.xml msgid "PrenotazioniYear" msgstr "PrenotazioniYear" -#: redturtle/prenotazioni/browser/templates/prenotazione_print.pt:129 +#: ../browser/templates/prenotazione_print.pt:129 msgid "Print" msgstr "Stampa" -#: redturtle/prenotazioni/configure.zcml:57 -msgid "Profile create to add the new default content rule: booking-confirm" -msgstr "Profilo per creare una content-rule di default: booking-confirm" - -#: redturtle/prenotazioni/restapi/services/booking/add.py:72 +#: ../restapi/services/booking/add.py:77 msgid "Required input '${field}' is missing." msgstr "Campo obbligatorio '${field}' mancante." -#: redturtle/prenotazioni/browser/prenotazione_add.py:217 +#: ../browser/prenotazione_add.py:217 msgid "Required input is missing." msgstr "Manca l'input obbligatorio." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:449 +#: ../content/prenotazioni_folder.py:377 msgid "Responsible email" msgstr "Email del responsabile" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:117 +#: ../content/prenotazioni_folder.py:114 msgid "Saturday" msgstr "Sabato" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:16 +#: ../browser/templates/prenotazioni_search.pt:16 msgid "Search for" msgstr "Parametri di ricerca" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:111 +#: ../content/prenotazioni_folder.py:108 msgid "Select a day" msgstr "Seleziona un giorno" -#: redturtle/prenotazioni/contentrules/configure.zcml:57 -msgid "Send Email to booking owner when a booking is moved" -msgstr "Invia un'email al creatore della prenotazione quando la prenotazione viene spostata." - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:32 -msgid "Sender email" -msgstr "Indirizzo mittente" - -#: redturtle/prenotazioni/adapters/booker.py:234 -#: redturtle/prenotazioni/restapi/services/booking/add.py:57 +#: ../adapters/booker.py:249 +#: ../restapi/services/booking/add.py:58 msgid "Sorry, this slot is not available anymore." msgstr "Ci dispiace, ma questo intervallo di tempo non è più disponibile" -#: redturtle/prenotazioni/adapters/booker.py:273 +#: ../adapters/booker.py:292 msgid "Sorry, this slot is not available or does not fit your booking." msgstr "Ci dispiace questo intervallo di tempo non è disponibile o non è adatto alla tua prenotazione." -#: redturtle/prenotazioni/adapters/booker.py:239 +#: ../adapters/booker.py:143 msgid "Sorry, you can not book this slot for now." msgstr "Ci dispiace, ma questo intervallo di tempo non è al momento disponibile" -#: redturtle/prenotazioni/content/prenotazione.py:171 +#: ../content/prenotazione.py:171 msgid "Sportello a cui presentarsi" msgstr "Postazione a cui presentarsi" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:26 -msgid "Subject" -msgstr "Note" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:27 -msgid "Subject of the message" -msgstr "Oggetto del messaggio" - -#: redturtle/prenotazioni/content/prenotazioni_folder.py:118 +#: ../content/prenotazioni_folder.py:115 msgid "Sunday" msgstr "Domenica" -#: redturtle/prenotazioni/adapters/stringinterp.py:37 +#: ../adapters/stringinterp.py:37 msgid "The booked date." msgstr "La data di prenotazione." -#: redturtle/prenotazioni/adapters/stringinterp.py:50 +#: ../adapters/stringinterp.py:50 msgid "The booked end date." msgstr "La data di fine prenotazione" -#: redturtle/prenotazioni/adapters/stringinterp.py:63 +#: ../adapters/stringinterp.py:63 msgid "The booked time." msgstr "L'orario di prenotazione" -#: redturtle/prenotazioni/adapters/stringinterp.py:96 +#: ../adapters/stringinterp.py:96 msgid "The booking code." msgstr "Il codice di prenotazione" -#: redturtle/prenotazioni/adapters/stringinterp.py:291 +#: ../adapters/stringinterp.py:291 msgid "The booking folder title" -msgstr "" +msgstr "Il titolo della cartella prenotazioni" -#: redturtle/prenotazioni/adapters/stringinterp.py:211 +#: ../adapters/stringinterp.py:211 msgid "The booking human readable date" msgstr "La data di prenotazione in formato leggibile" -#: redturtle/prenotazioni/adapters/stringinterp.py:177 +#: ../adapters/stringinterp.py:177 msgid "The booking office contact fax." msgstr "Il Fax per contattare l'ufficio" -#: redturtle/prenotazioni/adapters/stringinterp.py:167 +#: ../adapters/stringinterp.py:167 msgid "The booking office contact pec address." msgstr "L'indirizzo PEC per contattare l'ufficio" -#: redturtle/prenotazioni/adapters/stringinterp.py:157 +#: ../adapters/stringinterp.py:157 msgid "The booking office contact phone." msgstr "Il telefono per contattare l'ufficio" -#: redturtle/prenotazioni/adapters/stringinterp.py:250 +#: ../adapters/stringinterp.py:250 msgid "The booking operator url" -msgstr "" +msgstr "L'url della prenotazione per gli operatori" -#: redturtle/prenotazioni/adapters/stringinterp.py:108 +#: ../adapters/stringinterp.py:108 msgid "The booking print url." msgstr "L'url per stampare la prenotazione" -#: redturtle/prenotazioni/adapters/stringinterp.py:259 +#: ../adapters/stringinterp.py:259 msgid "The booking refuse message" -msgstr "" +msgstr "Il messaggio di rifiuto della prenotazione" -#: redturtle/prenotazioni/adapters/stringinterp.py:280 +#: ../adapters/stringinterp.py:280 msgid "The booking requirements url" -msgstr "" +msgstr "L'url per il cosa server" -#: redturtle/prenotazioni/adapters/stringinterp.py:75 +#: ../adapters/stringinterp.py:75 msgid "The booking time end." msgstr "L'orario di fine prenotazione" -#: redturtle/prenotazioni/adapters/stringinterp.py:87 +#: ../adapters/stringinterp.py:87 msgid "The booking type." msgstr "La tipologia della prenotazione." -#: redturtle/prenotazioni/adapters/stringinterp.py:238 +#: ../adapters/stringinterp.py:238 msgid "The booking url with delete token" msgstr "L'url della prenotazione con il token per la cancellazione" -#: redturtle/prenotazioni/adapters/stringinterp.py:199 +#: ../adapters/stringinterp.py:199 msgid "The complete address information of the office whereuser book a reservation" msgstr "L'indirizzo completo dell'ufficio presso cui si prenota" -#: redturtle/prenotazioni/adapters/stringinterp.py:139 +#: ../adapters/stringinterp.py:139 msgid "The email address of the user who made the reservation." msgstr "L'indirizzo email dell'utente che ha fatto la prenotazione" -#: redturtle/prenotazioni/adapters/stringinterp.py:28 +#: ../adapters/stringinterp.py:28 msgid "The gate booked." msgstr "La postazione prenotata." -#: redturtle/prenotazioni/adapters/stringinterp.py:187 +#: ../adapters/stringinterp.py:187 msgid "The information to reach the office where user book a reservation" msgstr "Le informazioni per raggiungere l'ufficio presso cui si prenota" -#: redturtle/prenotazioni/adapters/stringinterp.py:130 +#: ../adapters/stringinterp.py:130 msgid "The phone number of the user who made the reservation." msgstr "Il numero di telefono di chi ha prenotato" -#: redturtle/prenotazioni/adapters/booker.py:325 +#: ../adapters/booker.py:341 msgid "This day is not valid." msgstr "Il giorno inserito non è valido." -#: redturtle/prenotazioni/adapters/booker.py:320 +#: ../adapters/booker.py:336 msgid "This gate has some booking schedule in this time period." msgstr "Lo sportello selezionato ha già delle prenotazioni nel periodo indicato." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:115 +#: ../content/prenotazioni_folder.py:112 msgid "Thursday" msgstr "Giovedì" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:113 +#: ../content/prenotazioni_folder.py:110 msgid "Tuesday" msgstr "Martedì" -#: redturtle/prenotazioni/configure.zcml:41 +#: ../configure.zcml:40 msgid "Uninstalls the redturtle.prenotazioni add-on." msgstr "Disinstall redturtle.prenotazioni" -#: redturtle/prenotazioni/restapi/services/booking/add.py:108 +#: ../staging/configure.zcml:25 +msgid "Uninstalls the redturtle.prenotazioni.staging add-on (demo site purpose only)." +msgstr "" + +#: ../restapi/services/booking/add.py:113 msgid "Unknown booking type '${booking_type}'." msgstr "Tipologia di prenotazione sconosciuta '${booking_type}'." -#: redturtle/prenotazioni/configure.zcml:57 -msgid "Used to add new contentrules" -msgstr "Aggiunge una nuova contentrule" - -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioneType.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/PrenotazioneType.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "View" msgstr "Vista" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:114 +#: ../content/prenotazioni_folder.py:111 msgid "Wednesday" msgstr "Mercoledì" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:294 +#: ../content/prenotazioni_folder.py:213 msgid "Week table" -msgstr "Schedulazione settimanale" +msgstr "Schedulazione Settimanale" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:273 +#: ../content/prenotazioni_folder.py:192 msgid "Yes" msgstr "Si" -#: redturtle/prenotazioni/restapi/services/booking/add.py:45 +#: ../restapi/services/booking/add.py:70 msgid "You are not allowed to force the gate." -msgstr "" +msgstr "Non hai i permessi necessari a forzare lo sportello." -#: redturtle/prenotazioni/content/validators.py:92 +#: ../content/validators.py:92 msgid "You must set both start and end" msgstr "Devi impostare sia un orario di inizio che di termine della pausa" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:472 -#: redturtle/prenotazioni/content/validators.py:203 +#: ../content/prenotazioni_folder.py:400 +#: ../content/validators.py:203 msgid "You should set a start time for afternoon." msgstr "Devi impostare una data di inizio per il pomeriggio." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:468 -#: redturtle/prenotazioni/content/validators.py:195 +#: ../content/prenotazioni_folder.py:396 +#: ../content/validators.py:195 msgid "You should set a start time for morning." msgstr "Devi impostare una data di inizio per la mattina." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:470 -#: redturtle/prenotazioni/content/validators.py:199 +#: ../content/prenotazioni_folder.py:398 +#: ../content/validators.py:199 msgid "You should set an end time for afternoon." msgstr "Devi impostare una data di fine per il pomeriggio." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:466 -#: redturtle/prenotazioni/content/validators.py:191 +#: ../content/prenotazioni_folder.py:394 +#: ../content/validators.py:191 msgid "You should set an end time for morning." msgstr "Devi impostare una data di fine per la mattina." -#: redturtle/prenotazioni/adapters/stringinterp.py:124 +#: ../adapters/stringinterp.py:124 msgid "[DEPRECATED] The booking print url with delete token." msgstr "[DEPRECATO] L'url della prenotazione con il token per la cancellazione." #. Default: "Leave empty, and this Booking Folder will never expire" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:263 +#: ../content/prenotazioni_folder.py:182 msgid "aData_help" msgstr "Lascia vuoto, e questa Cartella Prenotazioni non avrà scadenza" #. Default: "Book" -#: redturtle/prenotazioni/browser/prenotazione_add.py:199 -#: redturtle/prenotazioni/browser/vacations.py:207 +#: ../browser/prenotazione_add.py:199 +#: ../browser/vacations.py:207 msgid "action_book" msgstr "Prenota" #. Default: "Cancel" -#: redturtle/prenotazioni/browser/prenotazione_add.py:252 -#: redturtle/prenotazioni/browser/prenotazione_move.py:150 -#: redturtle/prenotazioni/browser/vacations.py:232 +#: ../browser/prenotazione_add.py:252 +#: ../browser/prenotazione_move.py:147 +#: ../browser/vacations.py:232 msgid "action_cancel" msgstr "Cancella" #. Default: "Move" -#: redturtle/prenotazioni/browser/prenotazione_move.py:125 +#: ../browser/prenotazione_move.py:122 msgid "action_move" msgstr "Sposta" #. Default: "Search" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:250 +#: ../browser/prenotazioni_search.py:250 msgid "action_search" msgstr "Cerca" #. Default: "End time in the afternoon" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:99 +#: ../content/prenotazioni_folder.py:96 msgid "afternoon_end_label" msgstr "Chiusura pomeriggio" #. Default: "Start time in the afternoon" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:93 +#: ../content/prenotazioni_folder.py:90 msgid "afternoon_start_label" msgstr "Apertura pomeriggio" #. Default: "All" -#: redturtle/prenotazioni/vocabularies/voc_booking_type_gates.py:22 +#: ../vocabularies/voc_booking_type_gates.py:16 msgid "all" msgstr "Tutti" #. Default: "Automatically confirm." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:439 +#: ../content/prenotazioni_folder.py:358 msgid "auto_confirm" msgstr "Conferma automatica delle prenotazioni" #. Default: "All bookings will be automatically accepted." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:440 +#: ../content/prenotazioni_folder.py:359 msgid "auto_confirm_help" msgstr "Tutte le prenotazioni verranno accettate automaticamente" #. Default: "Automatically confirmfor managers." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:448 +#: ../content/prenotazioni_folder.py:367 msgid "auto_confirm_manager" msgstr "Conferma automatica delle prenotazioni dei Gestori" #. Default: "All bookings created by Managers will be automatically accepted." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:449 +#: ../content/prenotazioni_folder.py:368 msgid "auto_confirm_manager_help" msgstr "Tutte le prenotazioni create dai Gestori verranno accettate automaticamente." #. Default: "End date should be greater than start." -#: redturtle/prenotazioni/restapi/services/available_slots/get.py:44 +#: ../restapi/services/available_slots/get.py:44 msgid "available_slots_wrong_dates" -msgstr "" +msgstr "La data di fine prenotazione deve essere maggiore della data di inizio." #. Default: "Please select a booking slot." -#: redturtle/prenotazioni/browser/templates/week.pt:40 +#: ../browser/templates/week.pt:40 msgid "book_it" msgstr "Per favore seleziona uno slot per la prenotazione" #. Default: "Bookable time" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:454 +#: ../browser/templates/prenotazione_macros.pt:454 msgid "bookable_time" msgstr "Tempo prenotabile " #. Default: "${day}, ore ${booking_time}, prenotato da ${booked_by}, prenotazione: ${booking_type} durata: ${duration} minuti" -#: redturtle/prenotazioni/browser/week.py:276 +#: ../browser/week.py:276 msgid "booked_prenotation_message" msgstr "${day}, ore ${booking_time}, prenotato da ${booked_by}, prenotazione: ${booking_type} durata: ${duration} minuti" #. Default: "Booking confirmed" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:456 +#: ../browser/templates/prenotazione_macros.pt:456 msgid "booking_confirmed" msgstr "Prenotazione confermata" #. Default: "Booking created" -#: redturtle/prenotazioni/browser/prenotazione_add.py:231 -#: redturtle/prenotazioni/browser/vacations.py:204 +#: ../browser/prenotazione_add.py:231 +#: ../browser/vacations.py:204 msgid "booking_created" msgstr "Prenotazione creata" #. Default: "Your booking has been deleted." -#: redturtle/prenotazioni/browser/delete_reservation.py:114 +#: ../browser/delete_reservation.py:114 msgid "booking_deleted_success" msgstr "La tua prenotazione è stata cancellata." -#: redturtle/prenotazioni/browser/prenotazione_move.py:140 +#. Default: "Booking fields" +#: ../content/prenotazioni_folder.py:500 +msgid "booking_fields_label" +msgstr "Campi Prenotazioni" + +#: ../browser/prenotazione_move.py:137 msgid "booking_moved" msgstr "Prenotazione spostata correttamente" #. Default: "Booking pending" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:458 +#: ../browser/templates/prenotazione_macros.pt:458 msgid "booking_pending" msgstr "Prenotazione da confermare" #. Default: "Booking refused" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:460 +#: ../browser/templates/prenotazione_macros.pt:460 msgid "booking_refused" msgstr "Prenotazione rifiutata " #. Default: "Duration value" -#: redturtle/prenotazioni/content/prenotazione_type.py:15 +#: ../content/prenotazione_type.py:15 msgid "booking_type_duration_label" msgstr "Durata" #. Default: "Name" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:427 +#: ../browser/templates/prenotazione_macros.pt:427 msgid "booking_type_name" msgstr "Nome" #. Default: "List of requirements to recieve the service" -#: redturtle/prenotazioni/content/prenotazione_type.py:23 +#: ../content/prenotazione_type.py:23 msgid "booking_type_requirements_help" msgstr "Elencare le informazioni utili per il giorno della prenotazione, come ad esempio i documenti da presentare." #. Default: "Requirements" -#: redturtle/prenotazioni/content/prenotazione_type.py:22 +#: ../content/prenotazione_type.py:22 msgid "booking_type_requirements_labled" msgstr "Cosa serve" #. Default: "Value" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:428 +#: ../browser/templates/prenotazione_macros.pt:428 msgid "booking_type_value" msgstr "Durata" #. Default: "You may want to select another time slot to book one of these." -#: redturtle/prenotazioni/browser/templates/booking_type_radio_widget.pt:77 +#: ../browser/templates/booking_type_radio_widget.pt:77 msgid "booking_type_widget_suggest_reselect" msgstr "Prova a selezionare un'orario differente per prenotarle." #. Default: "The following tipologies will not fit the time you selected:" -#: redturtle/prenotazioni/browser/templates/booking_type_radio_widget.pt:65 +#: ../browser/templates/booking_type_radio_widget.pt:65 msgid "booking_type_widget_warn_unavailable" msgstr "Le seguenti tipologie non sono selezionabili nell'orario selezionato:" +#. Default: "Set message text for all available notification events." +#: ../behaviors/booking_folder/appio/__init__.py:257 +msgid "bookings_appio_templates_help" +msgstr "Imposta i testi dei messaggi per i vari tipi di notifiche disponibili." + +#. Default: "AppIO Notifications" +#: ../behaviors/booking_folder/appio/__init__.py:253 +msgid "bookings_appio_templates_label" +msgstr "Notifiche AppIO" + +#. Default: "Set message text for all available notification events." +#: ../behaviors/booking_folder/email/__init__.py:257 +msgid "bookings_email_templates_help" +msgstr "Imposta i testi dei messaggi per i vari tipi di notifiche disponibili." + +#. Default: "Email Notifications" +#: ../behaviors/booking_folder/email/__init__.py:253 +msgid "bookings_email_templates_label" +msgstr "Notifiche E-mail" + #. Default: "Booking limit({limit}) for the {booking_type} type is exceed for the current user" -#: redturtle/prenotazioni/exceptions/booker.py:15 +#: ../exceptions/booker.py:15 msgid "bookings_limit_exceeded_exception" msgstr "Attenzione: hai superato il massimo di {limit} prenotazioni per la tipologia {booking_type}. Potrai richiedere nuove prenotazioni ad appuntamento avvenuto" #. Default: "Bookings not in agenda" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:111 +#: ../browser/templates/prenotazione_macros.pt:111 msgid "bookings_not_in_agenda" msgstr "Prenotazioni non in agenda" +#. Default: "Set message text for all available notification events. Remember that SMS has a 160 characters limit. Depending on your gateway service, it can split messages, if you exceed that limit." +#: ../behaviors/booking_folder/sms/__init__.py:144 +msgid "bookings_sms_templates_help" +msgstr "Imposta i testi dei messaggi per i vari tipi di notifiche disponibili. Gli sms hanno un limite di 160 caratteri. A seconda del gateway per l'invio utilizzato, i messaggi più lunghi potrebbero venire spezzati in più parti." + +#. Default: "SMS Notifications" +#: ../behaviors/booking_folder/sms/__init__.py:140 +msgid "bookings_sms_templates_label" +msgstr "Notifiche SMS" + #. Default: "Busy" -#: redturtle/prenotazioni/browser/prenotazioni_context_state.py:47 +#: ../browser/prenotazioni_context_state.py:45 msgid "busy" msgstr "Occupato" #. Default: "Your booking has been confirmed." -#: redturtle/prenotazioni/browser/prenotazione_print.py:28 +#: ../browser/prenotazione_print.py:28 msgid "confirm_booking_confirmed_message" msgstr "La tua prenotazione è confermata." #. Default: "Your booking has been refused." -#: redturtle/prenotazioni/browser/prenotazione_print.py:32 +#: ../browser/prenotazione_print.py:32 msgid "confirm_booking_refused_message" msgstr "La tua prenotazione è stata rifiutata." #. Default: "Your booking has to be confirmed by the administrators." -#: redturtle/prenotazioni/browser/prenotazione_print.py:24 +#: ../browser/prenotazione_print.py:24 msgid "confirm_booking_waiting_message" msgstr "La tua prenotazione deve essere confermata dagli amministratori." #. Default: "Show here contacts information that will be used by authomatic mail system" -#: redturtle/prenotazioni/behaviors/booking_folder.py:49 +#: ../behaviors/booking_folder/contacts.py:49 msgid "contacts_help" msgstr "Indicare tutte le informazioni di contatto che saranno usate dal sistema di mailing. Queste informazioni saranno usate tramite sostituzione di un testo di markup nelle \"Regole di contenuto\" pertanto qui ci sarà da inserire dei testi che si possano integrare correttamente con i testi delle regole." #. Default: "Contacts" -#: redturtle/prenotazioni/behaviors/booking_folder.py:48 +#: ../behaviors/booking_folder/contacts.py:48 msgid "contacts_label" msgstr "Contatti" #. Default: "This day is not valid." -#: redturtle/prenotazioni/browser/vacations.py:224 +#: ../browser/vacations.py:224 msgid "day_error" msgstr "Questo day non è valido" #. Default: "Day of week" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:73 +#: ../content/prenotazioni_folder.py:70 msgid "day_label" msgstr "Giorno" #. Default: "You can't delete your reservation; it's too late." -#: redturtle/prenotazioni/browser/delete_reservation.py:138 +#: ../browser/delete_reservation.py:138 msgid "delete_expired_booking" msgstr "Non puoi cancellare questa prenotazione; è troppo tardi." #. Default: "Delete reservation request for: ${name}" -#: redturtle/prenotazioni/browser/delete_reservation.py:61 +#: ../browser/delete_reservation.py:61 msgid "delete_reservation_request" msgstr "Cancella la richiesta di prenotazione per: ${name}" #. Default: "Unique booking code" -#: redturtle/prenotazioni/content/prenotazione.py:181 +#: ../content/prenotazione.py:181 msgid "description_booking_code" msgstr "Codice univoco della prenotazione" #. Default: "If you work for a company, please specify its name." -#: redturtle/prenotazioni/content/prenotazione.py:161 +#: ../content/prenotazione.py:161 msgid "description_company" msgstr "Se lavori per un'azienda, compila questo campo." #. Default: "The gate that will be unavailable" -#: redturtle/prenotazioni/browser/vacations.py:68 +#: ../browser/vacations.py:68 msgid "description_gate" msgstr "La postazione che non sarà disponibile." #. Default: "This text will appear in the calendar cells" -#: redturtle/prenotazioni/browser/vacations.py:61 +#: ../browser/vacations.py:61 msgid "description_title" msgstr "Questo testo apparirà nelle celle del calendario." #. Default: "Foreseen booking time: ${booking_time}" -#: redturtle/prenotazioni/browser/week.py:225 +#: ../browser/week.py:225 msgid "foreseen_booking_time" msgstr "Data prevista per la prenotazione: ${day}, alle ore ${booking_time}." #. Default: "${booking_time}, Orario non disponibile" -#: redturtle/prenotazioni/browser/week.py:244 +#: ../browser/week.py:244 msgid "foreseen_busy_time" msgstr "${booking_time}, Orario non disponibile." -msgid "from_label" -msgstr "Dal" - #. Default: "You should set a start range." -#: redturtle/prenotazioni/content/validators.py:160 +#: ../content/validators.py:160 msgid "from_month_error" msgstr "Devi impostare una data di inizio." #. Default: "Selected day is too big for that month for \"from\" field." -#: redturtle/prenotazioni/content/validators.py:167 +#: ../content/validators.py:167 msgid "from_month_too_days_error" msgstr "Il giorno selezionato non è corretto per il mese selezionato nel campo \"Al\"." #. Default: "Fullname" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:55 +#: ../browser/templates/prenotazione.pt:55 msgid "fullname" msgstr "Nome completo" #. Default: "Limit booking in the future to an amount of days in the future starting from the current day. \nKeep 0 to give no limits." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:410 +#: ../content/prenotazioni_folder.py:329 msgid "futureDays" msgstr "Limita la prenotazione ad un certo numero di giorni nel futuro partendo dal day corrente.Lascia 0 per non dare limiti." #. Default: "Put gates here (one per line)." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:432 +#: ../content/prenotazioni_folder.py:351 msgid "gates_help" msgstr "Inserisci le postazioni preposte (uno per riga)." #. Default: "Gates" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:431 +#: ../content/prenotazioni_folder.py:350 msgid "gates_label" msgstr "Postazioni preposte" -#: redturtle/prenotazioni/browser/prenotazione_add.py:156 +#: ../browser/prenotazione_add.py:156 msgid "help_prenotazione_add" msgstr "" #. Default: "User will not be able to add a booking unless those fields are filled. Remember that, whatever you selected in this list, users have to supply at least one of \"Email\", \"Mobile\", or \"Telephone\"" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:245 +#: ../content/prenotazioni_folder.py:164 msgid "help_required_booking_fields" msgstr "Gli utenti non saranno in grado di creare una prenotazione senza compilare i seguenti campi. Gli utenti saranno comunque sempre obbligati ad inserire un'email o un recapito telefonico." #. Default: "States if it is not allowed to reserve a booking during the current day" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:284 +#: ../content/prenotazioni_folder.py:203 msgid "help_same_day_booking_disallowed" msgstr "Se selezionato, impedisce agli utenti di prenotare per il giorno corrente." #. Default: "List of available reservation type for the current agenda" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:424 +#: ../browser/templates/prenotazione_macros.pt:424 msgid "help_tipologies" msgstr "Lista dei tipi di prenotazione disponibili per l'agenda corrente" #. Default: "User will not be able to add a booking unless those fields are filled. Remember that, whatever you selected in this list, users have to supply at least one of \"Email\" or \"Telephone\"" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:227 +#: ../content/prenotazioni_folder.py:146 msgid "help_visible_booking_fields" msgstr "Gli utenti vedranno solo i campi selezionati all'atto della creazione della prenotazione." #. Default: "Set holidays (one for line) in DD/MM/YYYY. you can write * for the year, if this event is yearly." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:385 +#: ../content/prenotazioni_folder.py:304 msgid "holidays_help" msgstr "Imposta eventuali festività (una per riga) nel formato GG/MM/AAAA. Se la data si ripete ogni anno, puoi scrivere * al posto dell'anno." #. Default: "Holidays" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:384 +#: ../content/prenotazioni_folder.py:303 msgid "holidays_label" msgstr "Festività" #. Default: "Booking for ${title}" -#: redturtle/prenotazioni/adapters/ical.py:84 +#: ../adapters/ical.py:84 msgid "ical_booking_label" msgstr "Prenotazione appuntamento per ${title}" #. Default: "Date should be in the format YYYY/mm/dd" -#: redturtle/prenotazioni/browser/vacations.py:32 +#: ../browser/vacations.py:32 msgid "invalid_date" msgstr "La data deve essere nel formato AAAA/MM/GG" #. Default: "Invalid email address" -#: redturtle/prenotazioni/content/prenotazione.py:32 +#: ../content/prenotazione.py:32 msgid "invalid_email_address" msgstr "Indirizzo email non valido" #. Default: "Invalid start or end date" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:40 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:26 +#: ../browser/prenotazioni_search.py:40 +#: ../browser/stats/booking_stats.py:26 msgid "invalid_end:search_date" msgstr "Data di ricerca non valilda" #. Default: "Invalid fiscal code" -#: redturtle/prenotazioni/content/prenotazione.py:40 +#: ../content/prenotazione.py:40 msgid "invalid_fiscalcode" msgstr "Codice fiscale non valido" #. Default: "Invalid phone number" -#: redturtle/prenotazioni/content/prenotazione.py:28 +#: ../content/prenotazione.py:28 msgid "invalid_phone_number" msgstr "Numero di telefono non valido" #. Default: "Date should be in the format HH:MM" -#: redturtle/prenotazioni/browser/vacations.py:36 +#: ../browser/vacations.py:36 msgid "invalid_time" msgstr "L'ora deve essere nel formato HH:MM" #. Default: "This date is past" -#: redturtle/prenotazioni/content/prenotazione.py:36 +#: ../content/prenotazione.py:36 msgid "is_not_future_date" msgstr "La data è nel passato." #. Default: "Booking code" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:106 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:123 -#: redturtle/prenotazioni/browser/templates/prenotazione_print.pt:110 +#: ../browser/templates/delete_reservation.pt:106 +#: ../browser/templates/prenotazione.pt:123 +#: ../browser/templates/prenotazione_print.pt:110 msgid "label_booking_code" msgstr "Codice prenotazione" #. Default: "Company" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:62 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:38 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:75 +#: ../browser/templates/delete_reservation.pt:62 +#: ../browser/templates/manager_notification_mail.pt:38 +#: ../browser/templates/prenotazione.pt:75 msgid "label_booking_company" msgstr "Azienda" #. Default: "Booking date" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:80 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:50 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:87 +#: ../browser/templates/delete_reservation.pt:80 +#: ../browser/templates/manager_notification_mail.pt:50 +#: ../browser/templates/prenotazione.pt:87 msgid "label_booking_date" msgstr "Data prenotazione" #. Default: "${from_date} at ${at}" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:92 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:54 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:98 +#: ../browser/templates/delete_reservation.pt:92 +#: ../browser/templates/manager_notification_mail.pt:54 +#: ../browser/templates/prenotazione.pt:98 msgid "label_booking_date_range" msgstr "${from_date} alle ore ${at}" #. Default: "Subject" -#: redturtle/prenotazioni/browser/prenotazione_add.py:41 -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:74 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:46 +#: ../browser/prenotazione_add.py:41 +#: ../browser/templates/delete_reservation.pt:74 +#: ../browser/templates/manager_notification_mail.pt:46 msgid "label_booking_description" msgstr "Note" #. Default: "Email" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:50 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:30 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:63 +#: ../browser/templates/delete_reservation.pt:50 +#: ../browser/templates/manager_notification_mail.pt:30 +#: ../browser/templates/prenotazione.pt:63 msgid "label_booking_email" msgstr "Email" #. Default: "Fiscal code" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:68 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:42 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:79 +#: ../browser/templates/delete_reservation.pt:68 +#: ../browser/templates/manager_notification_mail.pt:42 +#: ../browser/templates/prenotazione.pt:79 msgid "label_booking_fiscalcode" msgstr "Codice fiscale" #. Default: "Phone number" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:56 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:34 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:71 +#: ../browser/templates/delete_reservation.pt:56 +#: ../browser/templates/manager_notification_mail.pt:34 +#: ../browser/templates/prenotazione.pt:71 msgid "label_booking_phone" msgstr "Numero di telefono" #. Default: "Staff notes" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:113 -#: redturtle/prenotazioni/content/prenotazione.py:186 +#: ../browser/templates/prenotazione.pt:113 +#: ../content/prenotazione.py:186 msgid "label_booking_staff_notes" msgstr "Note del personale" #. Default: "Booking time" -#: redturtle/prenotazioni/browser/prenotazione_move.py:34 -#: redturtle/prenotazioni/content/prenotazione.py:126 +#: ../browser/prenotazione_move.py:31 +#: ../content/prenotazione.py:126 msgid "label_booking_time" msgstr "Data e ora" #. Default: "Fullname" -#: redturtle/prenotazioni/browser/prenotazione_add.py:38 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:22 -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:52 +#: ../browser/prenotazione_add.py:38 +#: ../browser/templates/manager_notification_mail.pt:22 +#: ../browser/templates/prenotazioni_search.pt:52 msgid "label_booking_title" msgstr "Nome completo" #. Default: "Booking type" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:44 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:26 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:59 +#: ../browser/templates/delete_reservation.pt:44 +#: ../browser/templates/manager_notification_mail.pt:26 +#: ../browser/templates/prenotazione.pt:59 msgid "label_booking_type" msgstr "Tipologia prenotazione" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:293 -#: redturtle/prenotazioni/vocabularies/requirable_booking_fields.py:24 +#: ../browser/prenotazioni_search.py:293 +#: ../vocabularies/requirable_booking_fields.py:24 msgid "label_booking_{}" msgstr "" #. Default: "End date" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:68 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:52 +#: ../browser/prenotazioni_search.py:68 +#: ../browser/stats/booking_stats.py:52 msgid "label_end" msgstr "Data fine" #. Default: "End time" -#: redturtle/prenotazioni/browser/vacations.py:84 +#: ../browser/vacations.py:84 msgid "label_end_time" msgstr "Ora fine" #. Default: "Gate" -#: redturtle/prenotazioni/browser/prenotazione_move.py:35 -#: redturtle/prenotazioni/browser/prenotazioni_search.py:56 -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:100 +#: ../browser/prenotazione_move.py:32 +#: ../browser/prenotazioni_search.py:56 +#: ../browser/templates/delete_reservation.pt:100 msgid "label_gate" msgstr "Postazione" #. Default: "Go to the booking to see more details and manage it: ${url}" -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:65 +#: ../browser/templates/manager_notification_mail.pt:65 msgid "label_new_booking_notify_link" msgstr "Vai alla prenotazione per gestirla e vedere maggiori dettagli" #. Default: "Required booking fields" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:244 +#: ../content/prenotazioni_folder.py:163 msgid "label_required_booking_fields" msgstr "Campi obbligatori" #. Default: "Disallow same day booking" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:280 +#: ../content/prenotazioni_folder.py:199 msgid "label_same_day_booking_disallowed" msgstr "Disabilita la prenotazione per lo stesso giorno" #. Default: "Selected date: ${date} — Time: ${slot}" -#: redturtle/prenotazioni/browser/prenotazione_add.py:141 +#: ../browser/prenotazione_add.py:141 msgid "label_selected_date" msgstr "Data selezionata: ${date} — Alle ore: ${slot}" #. Default: "Start date " -#: redturtle/prenotazioni/browser/prenotazioni_search.py:62 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:45 -#: redturtle/prenotazioni/browser/vacations.py:73 +#: ../browser/prenotazioni_search.py:62 +#: ../browser/stats/booking_stats.py:45 +#: ../browser/vacations.py:73 msgid "label_start" msgstr "Data inizio" #. Default: "Start time" -#: redturtle/prenotazioni/browser/vacations.py:78 +#: ../browser/vacations.py:78 msgid "label_start_time" msgstr "Ora inizio" #. Default: "Text to search" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:48 +#: ../browser/prenotazioni_search.py:48 msgid "label_text" msgstr "Testo da ricercare" #. Default: "Reservation types" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:423 +#: ../browser/templates/prenotazione_macros.pt:423 msgid "label_tipologies" msgstr "Tipi di prenotazione" #. Default: "Title" -#: redturtle/prenotazioni/browser/vacations.py:60 +#: ../browser/vacations.py:60 msgid "label_title" msgstr "Etichetta" #. Default: "User" -#: redturtle/prenotazioni/browser/stats/booking_stats.py:43 +#: ../browser/stats/booking_stats.py:43 msgid "label_user" msgstr "Utente" #. Default: "Visible booking fields" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:226 +#: ../content/prenotazioni_folder.py:145 msgid "label_visible_booking_fields" msgstr "Campi da visualizzare" #. Default: "Legend" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:447 +#: ../browser/templates/prenotazione_macros.pt:447 msgid "legend" msgstr "Legenda" #. Default: "Short description of available action for the booking board" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:448 +#: ../browser/templates/prenotazione_macros.pt:448 msgid "legend_description" msgstr "Breve descrizione delle azioni disponibili per l'agenda" #. Default: "The minimum value of a single slot is 5 minutes. You cannot book a reservation when the needed time exceeds the available time." -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:469 +#: ../browser/templates/prenotazione_macros.pt:469 msgid "legend_note" msgstr "L'unità di tempo minima è 5 minuti. La tua prenotazione non può eccedere il tempo disponibile." #. Default: "The number of simultaneous bookings allowed for the same user." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:602 +#: ../content/prenotazioni_folder.py:449 msgid "max_bookings_allowed_description" msgstr "Numero massimo delle prenotazioni contemporanee per una stessa tipologia, per lo stesso utente. Impostare '0' o lasciare vuoto per non porre limitazioni. Per attivare questo controllo è necessario richiedere obbligatoriamente all'utente il campo 'codice fiscale'" #. Default: "Maximum bookings number allowed" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:598 +#: ../content/prenotazioni_folder.py:445 msgid "max_bookings_allowed_label" msgstr "Numero massimo delle prenotazioni" -#. Default: "Type in here the message that you want to mail. Some defined content can be replaced: ${title} will be replaced with booking title (user fullname). ${date} will be replaced with booking new date. ${url} will be replaced by the booking url. ${portal} will be replaced by the title of the portal." -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:43 -msgid "message_help" -msgstr "Inserisci il messaggio che vuoi inviare per mail. E' possibile inserire alcuni marcatori che verranno sostituiti con dei valori presi dall'applicazione. \"${title}\" sarà sostituito con il titolo della prenotazione (il nome e cognome dell'utente). \"${date}\" sarà sostituito con la data della prenotazione. \"${url}\" sarà sostituito dall'url della prenotazione. ${portal} sarà sostituito con il titolo del portale. " - #. Default: "Unable to find a booking with the givend id: ${uid}." -#: redturtle/prenotazioni/browser/delete_reservation.py:44 +#: ../browser/delete_reservation.py:44 msgid "missing_booking" msgstr "Impossibile trovare la prenotazione con id: ${uid}." #. Default: "You need to provide a reservation id." -#: redturtle/prenotazioni/browser/delete_reservation.py:38 +#: ../browser/delete_reservation.py:38 msgid "missing_uid" msgstr "Devi fornite un'id prenotazione." -msgid "month_label" -msgstr "Mese" - #. Default: "End time in the morning" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:87 +#: ../content/prenotazioni_folder.py:84 msgid "morning_end_label" msgstr "Chiusura mattina" #. Default: "Start time in the morning" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:82 +#: ../content/prenotazioni_folder.py:79 msgid "morning_start_label" msgstr "Apertura mattina" #. Default: "Go back to the calendar" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:260 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:192 -#: redturtle/prenotazioni/browser/templates/prenotazione_add.pt:127 +#: ../browser/prenotazioni_search.py:260 +#: ../browser/templates/prenotazione.pt:192 +#: ../browser/templates/prenotazione_add.pt:127 msgid "move_back_message" msgstr "Ritorna al calendario" #. Default: "Move booking" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:163 +#: ../browser/templates/prenotazione.pt:163 msgid "move_booking" msgstr "Sposta la prenotazione" #. Default: "Please move this booking into a new available slot or" -#: redturtle/prenotazioni/browser/templates/prenotazione_move.pt:39 +#: ../browser/templates/prenotazione_move.pt:39 msgid "move_message" msgstr "Spostare l'appuntamento selezionato in un area libera oppure" #. Default: "next week" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:39 +#: ../browser/templates/prenotazione_macros.pt:39 msgid "next-week" msgstr "Settimana successiva" #. Default: "Booking is not allowed before the amount of days specified. \nKeep 0 to give no limits." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:422 +#: ../content/prenotazioni_folder.py:341 msgid "notBeforeDays" msgstr "La prenotazione non e' permessa prima del numero di giorni specificata. Impostare il valore 0 per non imporre limitazioni." +#. Default: "Enable AppIO notifications." +#: ../behaviors/booking_folder/appio/__init__.py:123 +msgid "notifications_appio_enabled_help" +msgstr "Abilita le notifiche via App IO. I campi del messaggio accettano il formato Markdown" + +#. Default: "AppIO notifications" +#: ../behaviors/booking_folder/appio/__init__.py:122 +msgid "notifications_appio_enabled_label" +msgstr "Notifiche AppIO" + +#. Default: "Enable Email notifications." +#: ../behaviors/booking_folder/email/__init__.py:123 +msgid "notifications_email_enabled_help" +msgstr "Abilita le notifiche via email" + +#. Default: "Email notifications" +#: ../behaviors/booking_folder/email/__init__.py:122 +msgid "notifications_email_enabled_label" +msgstr "Notifiche Email" + #. Default: "Notifications" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:642 +#: ../content/prenotazioni_folder.py:508 msgid "notifications_label" -msgstr "Notifiche email" +msgstr "Gestione delle Notifiche" + +#. Default: "Enable SMS notifications." +#: ../behaviors/booking_folder/sms/__init__.py:70 +msgid "notifications_sms_enabled_help" +msgstr "Abilita le notifiche via SMS. Queste notifiche partono solamente in caso le notifiche via AppIO o email non siano attive. Per poter ricevere un SMS, il campo 'Numero di telefono' della Prenotazione deve essere compilato." + +#. Default: "SMS notifications" +#: ../behaviors/booking_folder/sms/__init__.py:69 +msgid "notifications_sms_enabled_label" +msgstr "Notifiche SMS" + +#. Default: "This is an automatic reminder about your booking on ${date} for ${booking_type}.

You can see details and print a reminder following this [link](${booking_print_url})." +#: ../behaviors/booking_folder/appio/__init__.py:111 +msgid "notify_as_reminder_appio_message_default_value" +msgstr "Promemoria automatico per la prenotazione per ${booking_type} il ${booking_date} alle ${booking_time}.

Dal tuo [promemoria](${booking_print_url}) puoi controllare i dati, stampare ed eventualmente cancellare la prenotazione." + +#. Default: "[${prenotazioni_folder_title}] Booking reminder on ${booking_date}" +#: ../behaviors/booking_folder/appio/__init__.py:101 +msgid "notify_as_reminder_appio_subject_default_value" +msgstr "[${prenotazioni_folder_title}] Promemoria prenotazione del ${booking_date}" + +#. Default: "The message subject when a reminder will be sent." +#: ../behaviors/booking_folder/appio/__init__.py:231 +msgid "notify_as_reminder_appio_subject_help" +msgstr "L'oggetto del messaggio inviato come promemoria." + +#. Default: "[Reminder] message" +#: ../behaviors/booking_folder/appio/__init__.py:239 +#: ../behaviors/booking_folder/email/__init__.py:239 +#: ../behaviors/booking_folder/sms/__init__.py:126 +msgid "notify_as_reminder_message" +msgstr "[Promemoria] messaggio" + +#. Default: "This is an automatic reminder about your booking on ${date} for ${booking_type}.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:111 +msgid "notify_as_reminder_message_default_value" +msgstr "Promemoria automatico per la prenotazione per ${booking_type} il ${booking_date} alle ${booking_time}.

Dal tuo promemoria puoi controllare i dati, stampare ed eventualmente cancellare la prenotazione." + +#. Default: "The message text when a reminder will be sent." +#: ../behaviors/booking_folder/appio/__init__.py:243 +#: ../behaviors/booking_folder/email/__init__.py:243 +#: ../behaviors/booking_folder/sms/__init__.py:130 +msgid "notify_as_reminder_message_help" +msgstr "Il testo del messaggio inviato come promemoria." + +#. Default: "[${prenotazioni_folder_title}]: This is an automatic reminder about your booking on ${date} for ${booking_type}.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:58 +msgid "notify_as_reminder_sms_message_default_value" +msgstr "" +"[${prenotazioni_folder_title}]: Promemoria prenotazione per ${booking_type} il ${booking_date} alle ${booking_time}.\n" +"Per dettagli: ${booking_print_url}." + +#. Default: "[Reminder] subject" +#: ../behaviors/booking_folder/appio/__init__.py:227 +#: ../behaviors/booking_folder/email/__init__.py:227 +msgid "notify_as_reminder_subject" +msgstr "[Promemoria] oggetto" + +#. Default: "[${prenotazioni_folder_title}] Booking reminder on ${booking_date}" +#: ../behaviors/booking_folder/email/__init__.py:101 +msgid "notify_as_reminder_subject_default_value" +msgstr "[${prenotazioni_folder_title}] Promemoria prenotazione del ${booking_date}" + +#. Default: "The message subject when a reminder will be sent." +#: ../behaviors/booking_folder/email/__init__.py:231 +msgid "notify_as_reminder_subject_help" +msgstr "L'oggetto del messaggio inviato come promemoria." #. Default: "Notify when confirmed." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:498 +#: ../content/prenotazioni_folder.py:418 msgid "notify_on_confirm" msgstr "Notifica alla conferma" +#. Default: "The booking ${booking_type} for ${title} has been confirmed.

You can see details and print a reminder following this [link](${booking_print_url})." +#: ../behaviors/booking_folder/appio/__init__.py:48 +msgid "notify_on_confirm_appio_message_default_value" +msgstr "" +"La prenotazione ${booking_type} per ${title} è stata confermata. \n" +"Dal tuo [promemoria](${booking_print_url}) puoi controllare i dati, stampare ed eventualmente cancellare la prenotazione." + +#. Default: "[${prenotazioni_folder_title}] Booking of ${booking_date} at ${booking_time} was accepted" +#: ../behaviors/booking_folder/appio/__init__.py:38 +msgid "notify_on_confirm_appio_subject_default_value" +msgstr "[${prenotazioni_folder_title}] Prenotazione del ${booking_date} alle ${booking_time} accettata" + #. Default: "Notify via mail the user when his booking has been confirmed." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:499 +#: ../content/prenotazioni_folder.py:419 msgid "notify_on_confirm_help" -msgstr "Notifica l'utente via email quando la prenotazione viene confermata." +msgstr "Notifica l'utente quando la prenotazione viene confermata." -#. Default: "Prenotazione confirmed notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:552 +#. Default: "[Confirmed] message" +#: ../behaviors/booking_folder/appio/__init__.py:167 +#: ../behaviors/booking_folder/email/__init__.py:167 +#: ../behaviors/booking_folder/sms/__init__.py:90 msgid "notify_on_confirm_message" -msgstr "Testo notifica prenotazione confermata" +msgstr "[Conferma] messaggio" -#. Default: "The booking${booking_type} for ${title} was confirmed! Link" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:164 -#: redturtle/prenotazioni/upgrades.py:257 +#. Default: "The booking ${booking_type} for ${title} has been confirmed.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:48 msgid "notify_on_confirm_message_default_value" -msgstr "La prenotazione ${booking_type} per ${title} è stata confermata! Se non hai salvato o stampato il promemoria, puoi visualizzarlo su questo link Se desideri cancellare la prenotazione, accedi a questo link" +msgstr "La prenotazione ${booking_type} per ${title} è stata confermata.

Dal tuo promemoria puoi controllare i dati, stampare ed eventualmente cancellare la prenotazione." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:556 +#. Default: "The message text when a booking has been confirmed." +#: ../behaviors/booking_folder/appio/__init__.py:171 +#: ../behaviors/booking_folder/email/__init__.py:171 +#: ../behaviors/booking_folder/sms/__init__.py:94 msgid "notify_on_confirm_message_help" +msgstr "Il testo del messaggio quando una prenotazione è stata confermata." + +#. Default: "[${prenotazioni_folder_title}]: Booking of ${booking_date} at ${booking_time} has been accepted.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:28 +msgid "notify_on_confirm_sms_message_default_value" msgstr "" +"[${prenotazioni_folder_title}]: La prenotazione ${booking_type} per ${title} è stata confermata.\n" +"Per dettagli: ${booking_print_url}." -#. Default: "Prenotazione confirmed notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:543 +#. Default: "[Confirm] subject" +#: ../behaviors/booking_folder/appio/__init__.py:155 +#: ../behaviors/booking_folder/email/__init__.py:155 msgid "notify_on_confirm_subject" -msgstr "Oggetto notifica prenotazione confermata" +msgstr "[Conferma] oggetto" -#. Default: "Booking of ${booking_date} at ${booking_time} was accepted" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:154 -#: redturtle/prenotazioni/upgrades.py:250 +#. Default: "[${prenotazioni_folder_title}] Booking of ${booking_date} at ${booking_time} was accepted" +#: ../behaviors/booking_folder/email/__init__.py:38 msgid "notify_on_confirm_subject_default_value" -msgstr "Prenotazione del ${booking_date} alle ${booking_time} accettata" +msgstr "[${prenotazioni_folder_title}] Prenotazione del ${booking_date} alle ${booking_time} accettata" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:547 +#. Default: "The message subject when a booking has been confirmed." +#: ../behaviors/booking_folder/appio/__init__.py:159 +#: ../behaviors/booking_folder/email/__init__.py:159 msgid "notify_on_confirm_subject_help" -msgstr "" +msgstr "L'oggetto del messaggio quando una prenotazione è stata confermata." #. Default: "Notify when moved." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:507 +#: ../content/prenotazioni_folder.py:427 msgid "notify_on_move" -msgstr "Notifica se la prenotazione è stata spostata" +msgstr "Notifica allo spostamento" + +#. Default: "The booking scheduling for ${booking_type} was modified.

The new one is on ${booking_date} at ${booking_time}.

You can see details and print a reminder following this [link](${booking_print_url})." +#: ../behaviors/booking_folder/appio/__init__.py:69 +msgid "notify_on_move_appio_message_default_value" +msgstr "" +"L'orario della sua prenotazione ${booking_type} è stato modificato. \n" +"La nuova data è ${booking_date} alle ore ${booking_time}. \n" +"Dal tuo [promemoria](${booking_print_url}) puoi controllare i dati, stampare ed eventualmente cancellare la prenotazione." + +#. Default: "[${prenotazioni_folder_title}] Booking date modified for ${title}" +#: ../behaviors/booking_folder/appio/__init__.py:59 +msgid "notify_on_move_appio_subject_default_value" +msgstr "[${prenotazioni_folder_title}] Data di prenotazione modificata per ${title}" #. Default: "Notify via mail the user when his booking has been moved." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:508 +#: ../content/prenotazioni_folder.py:428 msgid "notify_on_move_help" -msgstr "Notifica l'utente via mail quando la prenotazione viene spostata." +msgstr "Notifica l'utente quando la prenotazione viene spostata di giorno/orario." -#. Default: "Prenotazione moved notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:570 +#. Default: "[Move] message" +#: ../behaviors/booking_folder/appio/__init__.py:191 +#: ../behaviors/booking_folder/email/__init__.py:191 +#: ../behaviors/booking_folder/sms/__init__.py:102 msgid "notify_on_move_message" -msgstr "Testo notifica prenotazione spostata" +msgstr "[Spostamento] messaggio" -#. Default: "The booking scheduling of ${booking_type} was modified.The new one is on ${booking_date} at ${booking_time}. Link." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:184 -#: redturtle/prenotazioni/upgrades.py:271 +#. Default: "The booking scheduling for ${booking_type} was modified.

The new one is on ${booking_date} at ${booking_time}.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:69 msgid "notify_on_move_message_default_value" -msgstr "L'orario della sua prenotazione ${booking_type} è stata modificata. La nuova data è ${booking_date} alle ore ${booking_time}. Controlla o stampa il nuovo promemoria su questo link." +msgstr "L'orario della sua prenotazione ${booking_type} è stato modificato.

La nuova data è ${booking_date} alle ore ${booking_time}.

Dal tuo promemoria puoi controllare i dati, stampare ed eventualmente cancellare la prenotazione." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:574 +#. Default: "The message text when a booking has been moved." +#: ../behaviors/booking_folder/appio/__init__.py:195 +#: ../behaviors/booking_folder/email/__init__.py:195 +#: ../behaviors/booking_folder/sms/__init__.py:106 msgid "notify_on_move_message_help" +msgstr "Il testo del messaggio quando una prenotazione è stata spostata." + +#. Default: "[${prenotazioni_folder_title}]: The booking scheduling for ${booking_type} was modified.\nThe new one is on ${booking_date} at ${booking_time}.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:38 +msgid "notify_on_move_sms_message_default_value" msgstr "" +"[${prenotazioni_folder_title}]: orario della prenotazione ${booking_type} modificato: ${booking_date} alle ${booking_time}.\n" +"Per dettagli: ${booking_print_url}." -#. Default: "Prenotazione moved notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:561 +#. Default: "[Move] subject" +#: ../behaviors/booking_folder/appio/__init__.py:179 +#: ../behaviors/booking_folder/email/__init__.py:179 msgid "notify_on_move_subject" -msgstr "Oggetto notifica prenotazione spostata" +msgstr "[Spostamento] oggetto" -#. Default: "Modified the boolking date for ${title}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:174 -#: redturtle/prenotazioni/upgrades.py:264 +#. Default: "[${prenotazioni_folder_title}] Booking date modified for ${title}" +#: ../behaviors/booking_folder/email/__init__.py:59 msgid "notify_on_move_subject_default_value" -msgstr "Modifica data di prenotazione per ${title}" +msgstr "[${prenotazioni_folder_title}] Data di prenotazione modificata per ${title} - ${booking_date}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:565 +#. Default: "The message subject when a booking has been moved." +#: ../behaviors/booking_folder/appio/__init__.py:183 +#: ../behaviors/booking_folder/email/__init__.py:183 msgid "notify_on_move_subject_help" -msgstr "" +msgstr "L'oggetto del messaggio quando una prenotazione è stata spostata." #. Default: "Notify when rejected." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:516 +#: ../content/prenotazioni_folder.py:436 msgid "notify_on_refuse" msgstr "Notifica se viene cancellata" +#. Default: "The booking ${booking_type} of ${booking_date} at ${booking_time} was refused." +#: ../behaviors/booking_folder/appio/__init__.py:91 +msgid "notify_on_refuse_appio_message_default_value" +msgstr "La prenotazione ${booking_type} del ${booking_date} delle ore ${booking_time} è stata rifiutata. Motivo del rifiuto: ${booking_refuse_message}" + +#. Default: "[${prenotazioni_folder_title}] Booking refused for ${title}" +#: ../behaviors/booking_folder/appio/__init__.py:81 +msgid "notify_on_refuse_appio_subject_default_value" +msgstr "[${prenotazioni_folder_title}] Prenotazione rifiutata per ${title}" + #. Default: "Notify via mail the user when his booking has been rejected." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:517 +#: ../content/prenotazioni_folder.py:437 msgid "notify_on_refuse_help" msgstr "Notifica l'utente via mail se la prenotazione viene cancellata" -#. Default: "Prenotazione created notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:588 +#. Default: "[Refuse] message" +#: ../behaviors/booking_folder/appio/__init__.py:215 +#: ../behaviors/booking_folder/email/__init__.py:215 +#: ../behaviors/booking_folder/sms/__init__.py:114 msgid "notify_on_refuse_message" msgstr "Testo notifica prenotazione rifiutata" #. Default: "The booking ${booking_type} of ${booking_date} at ${booking_time} was refused." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:205 -#: redturtle/prenotazioni/upgrades.py:286 +#: ../behaviors/booking_folder/email/__init__.py:91 msgid "notify_on_refuse_message_default_value" msgstr "La prenotazione ${booking_type} del ${booking_date} delle ore ${booking_time} è stata rifiutata. Motivo del rifiuto: ${booking_refuse_message}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:592 +#. Default: "The message text when a booking has been refused." +#: ../behaviors/booking_folder/appio/__init__.py:219 +#: ../behaviors/booking_folder/email/__init__.py:219 +#: ../behaviors/booking_folder/sms/__init__.py:118 msgid "notify_on_refuse_message_help" +msgstr "Il testo del messaggio quando una prenotazione è stata rifiutata." + +#. Default: "[${prenotazioni_folder_title}]: The booking ${booking_type} of ${booking_date} at ${booking_time} was refused." +#: ../behaviors/booking_folder/sms/__init__.py:48 +msgid "notify_on_refuse_sms_message_default_value" msgstr "" +"[${prenotazioni_folder_title}]: La prenotazione ${booking_type} del ${booking_date} alle ${booking_time} è stata rifiutata.\n" +"Motivo: ${booking_refuse_message}" -#. Default: "Prenotazione refused notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:579 +#. Default: "[Refuse] subject" +#: ../behaviors/booking_folder/appio/__init__.py:203 +#: ../behaviors/booking_folder/email/__init__.py:203 msgid "notify_on_refuse_subject" -msgstr "Oggetto notifica prenotazione rifiutata" +msgstr "[Rifiuto] oggetto" -#. Default: "Booking refused for ${title}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:195 -#: redturtle/prenotazioni/upgrades.py:279 +#. Default: "[${prenotazioni_folder_title}] Booking refused for ${title}" +#: ../behaviors/booking_folder/email/__init__.py:81 msgid "notify_on_refuse_subject_default_value" -msgstr "Prenotazione rifiutata per ${title}" +msgstr "[${prenotazioni_folder_title}] Prenotazione rifiutata per ${title}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:583 +#. Default: "The message subject when a booking has been refused." +#: ../behaviors/booking_folder/appio/__init__.py:207 +#: ../behaviors/booking_folder/email/__init__.py:207 msgid "notify_on_refuse_subject_help" -msgstr "" +msgstr "L'oggetto del messaggio quando una prenotazione è stata rifiutata." #. Default: "Notify when created." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:489 +#: ../content/prenotazioni_folder.py:409 msgid "notify_on_submit" -msgstr "Notifica alla prenotazione creata" +msgstr "Notifica alla creazione" + +#. Default: "Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.

You can see details and print a reminder following this [${booking_print_url}](link)." +#: ../behaviors/booking_folder/appio/__init__.py:28 +msgid "notify_on_submit_appio_message_default_value" +msgstr "" +"La prenotazione ${booking_type} per il ${booking_date} alle ${booking_time} è stata creata. \n" +"Dal tuo [${booking_print_url}](promemoria) puoi controllare i dati, stampare ed eventualmente cancellare la prenotazione." + +#. Default: "[${prenotazioni_folder_title}] Booking created" +#: ../behaviors/booking_folder/appio/__init__.py:18 +msgid "notify_on_submit_appio_subject_default_value" +msgstr "[${prenotazioni_folder_title}] Prenotazione creata" #. Default: "Notify via mail the user when his booking has been created. If auto-confirm flag is selected and confirm notify is selected, this one will be ignored." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:490 +#: ../content/prenotazioni_folder.py:410 msgid "notify_on_submit_help" -msgstr "Notifica l'utente via email quando la prenotazione viene creata. Se il flag di conferma automatica o di notifica alla conferma è stato selezionato, l'opzione corrente sarà ignorata" +msgstr "Notifica l'utente quando la prenotazione viene creata. Se il flag di conferma automatica e di notifica alla conferma sono selezionati, questa opzione verrà ignorata." -#. Default: "Prenotazione created notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:534 +#. Default: "[Created] message" +#: ../behaviors/booking_folder/appio/__init__.py:143 +#: ../behaviors/booking_folder/email/__init__.py:143 +#: ../behaviors/booking_folder/sms/__init__.py:78 msgid "notify_on_submit_message" -msgstr "Testo notifica prenotazione creata" +msgstr "[Creazione] messaggio" -#. Default: "Booking ${booking_type} for ${booking_date} at ${booking_time} was created.Link" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:144 -#: redturtle/prenotazioni/upgrades.py:243 +#. Default: "Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:28 msgid "notify_on_submit_message_default_value" -msgstr "La prenotazione ${booking_type} per il ${booking_date} alle ${booking_time} è stata creata. Riceverete una mail di conferma quando la prenotazione verrà confermata definitivamente. Se non hai salvato o stampato il promemoria, puoi visualizzarlo questo link" +msgstr "La prenotazione ${booking_type} per il ${booking_date} alle ${booking_time} è stata creata.

Dal tuo promemoria puoi controllare i dati, stampare ed eventualmente cancellare la prenotazione." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:538 +#. Default: "The message text when a booking has been created." +#: ../behaviors/booking_folder/appio/__init__.py:147 +#: ../behaviors/booking_folder/email/__init__.py:147 +#: ../behaviors/booking_folder/sms/__init__.py:82 msgid "notify_on_submit_message_help" -msgstr "" +msgstr "Il testo del messaggio quando una prenotazione è stata creata." -#. Default: "Prenotazione created notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:525 +#. Default: "[${prenotazioni_folder_title}]: Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:18 +msgid "notify_on_submit_sms_message_default_value" +msgstr "[${prenotazioni_folder_title}]: La prenotazione ${booking_type} per il ${booking_date} alle ${booking_time} è stata creata. Per dettagli: ${booking_print_url}." + +#. Default: "[Created] subject" +#: ../behaviors/booking_folder/appio/__init__.py:131 +#: ../behaviors/booking_folder/email/__init__.py:131 msgid "notify_on_submit_subject" -msgstr "Oggetto notifica prenotazione creata" +msgstr "[Creazione] oggetto" -#. Default: "Booking created ${title}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:137 -#: redturtle/prenotazioni/upgrades.py:239 +#. Default: "[${prenotazioni_folder_title}] Booking created" +#: ../behaviors/booking_folder/email/__init__.py:18 msgid "notify_on_submit_subject_default_value" -msgstr "Prenotazione creata correttamente per ${title}" +msgstr "[${prenotazioni_folder_title}] Prenotazione creata" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:529 +#. Default: "The message subject when a booking has been created." +#: ../behaviors/booking_folder/appio/__init__.py:135 +#: ../behaviors/booking_folder/email/__init__.py:135 msgid "notify_on_submit_subject_help" -msgstr "" +msgstr "L'oggetto del messaggio quando una prenotazione è stata creata." #. Default: "Pause end" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:128 +#: ../content/prenotazioni_folder.py:125 msgid "pause_end_label" msgstr "Termine pausa" #. Default: "Pause start" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:123 +#: ../content/prenotazioni_folder.py:120 msgid "pause_start_label" msgstr "Inizio pausa" #. Default: "Please select a time slot" -#: redturtle/prenotazioni/browser/prenotazione_add.py:280 +#: ../browser/prenotazione_add.py:280 msgid "please_pick_a_date" msgstr "Selezionare una data" #. Default: "${day}, ore ${booking_time}" -#: redturtle/prenotazioni/browser/week.py:256 +#: ../browser/week.py:256 msgid "prenotation_slot_message" msgstr "${day}, ore ${booking_time}" -#. Default: "Testo delle email di notifica" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:652 -msgid "prenotazioni_email_templates_label" -msgstr "Testo delle email di notifica" - #. Default: "prenotazioni_search" -#: redturtle/prenotazioni/profiles/default/actions.xml +#: ../profiles/default/actions.xml msgid "prenotazioni_search" msgstr "Ricerca" #. Default: "previous week" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:14 +#: ../browser/templates/prenotazione_macros.pt:14 msgid "previous-week" msgstr "Settimana precedente" -#: redturtle/prenotazioni/configure.zcml:32 +#: ../configure.zcml:31 msgid "redturtle.prenotazioni" msgstr "redturtle.prenotazioni" -#: redturtle/prenotazioni/configure.zcml:49 +#: ../configure.zcml:48 msgid "redturtle.prenotazioni (to_1500)" msgstr "redturtle.prenotazioni (to_1500)" -#: redturtle/prenotazioni/configure.zcml:41 +#: ../configure.zcml:40 +#: ../staging/configure.zcml:25 msgid "redturtle.prenotazioni (uninstall)" msgstr "redturtle.prenotazioni (disinstalla)" -#: redturtle/prenotazioni/configure.zcml:49 +#: ../configure.zcml:48 msgid "redturtle.prenotazioni to 1500." msgstr "redturtle.prenotazioni to 1500." +#: ../staging/configure.zcml:16 +msgid "redturtle.prenotazioni.staging" +msgstr "" + #. Default: "The booking state is \"refused\". If you change it, the booking time may conflict with another one." -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:30 +#: ../browser/templates/prenotazione.pt:30 msgid "refused-review-state-warning" msgstr "Lo stato della prenotazione è \"rifiutato\". Se lo cambi, questa prenotazione potrebbe entrare in conflitto con un'altra." #. Default: "Reject booking" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:176 +#: ../browser/templates/prenotazione.pt:176 msgid "reject_booking" msgstr "Rifiuta la prenotazione" -#. Default: "Reminders" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:700 -msgid "reminders_label" -msgstr "Promemoria" +#. Default: "Set how many days before of a booking date the user will be notified about it." +#: ../content/prenotazioni_folder.py:461 +msgid "reminder_notification_gap_description" +msgstr "Indicare quanti giorni prima della data di prenotazione, inviare un promemoria agli utenti." + +#. Default: "Booking reminder days" +#: ../content/prenotazioni_folder.py:457 +msgid "reminder_notification_gap_label" +msgstr "Promemoria prenotazione" #. Default: "Code" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:58 +#: ../browser/templates/prenotazioni_search.pt:58 msgid "reservation_code" msgstr "Codice prenotazione" #. Default: "Reservation date" -#: redturtle/prenotazioni/browser/templates/prenotazione_move.pt:33 -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:57 +#: ../browser/templates/prenotazione_move.pt:33 +#: ../browser/templates/prenotazioni_search.pt:57 msgid "reservation_date" msgstr "Data prenotazione" #. Default: "Booking request for: ${name}" -#: redturtle/prenotazioni/browser/prenotazione_print.py:44 +#: ../browser/prenotazione_print.py:44 msgid "reservation_request" msgstr "Richiesta prenotazione per: ${name}" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:30 +#: ../browser/templates/prenotazione_macros.pt:30 msgid "resize" msgstr "Ridimensiona" #. Default: "items matching your search terms." -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:30 +#: ../browser/templates/prenotazioni_search.pt:30 msgid "result_number" msgstr "elementi trovati" #. Default: "You need to provide a booking date to get the schema and available types." -#: redturtle/prenotazioni/restapi/services/booking_schema/get.py:71 +#: ../restapi/services/booking_schema/get.py:71 msgid "schema_missing_date" -msgstr "" +msgstr "Devi fornire una data di prenotazione, per avere lo schema e le tipologie disponibili." #. Default: "Search by gate" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:465 +#: ../browser/templates/prenotazione_macros.pt:465 msgid "search-by-gate" msgstr "Ricerca per postazione" #. Default: "Search result" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:12 +#: ../browser/templates/prenotazioni_search.pt:12 msgid "search_result_message" msgstr "Risultato della ricerca" #. Default: "seleziona l'opzione desiderata dal gruppo di radio button seguente" -#: redturtle/prenotazioni/browser/z3c_custom_widget.py:153 +#: ../browser/z3c_custom_widget.py:153 msgid "select-option" msgstr "seleziona l'opzione desiderata dal gruppo di campi seguente" +#. Default: "AppIO service code related to the current booking type" +#: ../behaviors/booking_folder/appio/__init__.py:293 +msgid "service_code_help" +msgstr "Matricola del servizio legato alla tipologia (serve per l'invio coretto delle notifiche)" + +#. Default: "AppIO service code." +#: ../behaviors/booking_folder/appio/__init__.py:289 +msgid "service_code_label" +msgstr "Matricola servizio App IO" + #. Default: "This gate has some booking schedule in this time period." -#: redturtle/prenotazioni/browser/vacations.py:217 +#: ../browser/vacations.py:217 msgid "slot_conflict_error" msgstr "Questa postazione ha già appuntamenti schedulati in questo periodo." -#. Default: "The email address that sends the email. If no email is provided here, it will use the address from portal." -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:33 -msgid "source_help" -msgstr "Il mittente della mail. Se nessun indirizzo viene inserito verrà utilizzato l'indirizzo configurato nel portale." - #. Default: "You cannot book any booking_type at this time" -#: redturtle/prenotazioni/browser/prenotazione_add.py:284 +#: ../browser/prenotazione_add.py:284 msgid "time_slot_to_short" msgstr "Tempo insufficiente per qualsiasi tipologia di prenotazione" -msgid "to_label" -msgstr "Al" - #. Default: "You should set an end range." -#: redturtle/prenotazioni/content/validators.py:175 +#: ../content/validators.py:175 msgid "to_month_error" msgstr "Devi impostare una data di inizio." #. Default: "Selected day is too big for that month for \"to\" field." -#: redturtle/prenotazioni/content/validators.py:182 +#: ../content/validators.py:182 msgid "to_month_too_days_error" msgstr "Il giorno selezionato non è compatibile col mese selezionato nel campo \"Al\"." #. Default: "You can't add a booking with type '${booking_type}'." -#: redturtle/prenotazioni/restapi/services/booking/add.py:84 +#: ../restapi/services/booking/add.py:89 msgid "unauthorized_add_vacation" -msgstr "" +msgstr "Impossibile creare una nuova prenotazione per la tipologia '${booking_type}'." #. Default: "Unbookable time" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:452 +#: ../browser/templates/prenotazione_macros.pt:452 msgid "unbookable_time" msgstr "Tempo non prenotabile " #. Default: "vacation_booking" -#: redturtle/prenotazioni/profiles/default/actions.xml +#: ../profiles/default/actions.xml msgid "vacation_booking" msgstr "Blocco risorsa" #. Default: "View booking" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:143 -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:463 +#: ../browser/templates/prenotazione.pt:143 +#: ../browser/templates/prenotazione_macros.pt:463 msgid "view_booking" msgstr "Vedi la prenotazione" #. Default: "Insert here week schema for some custom date intervals." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:362 +#: ../content/prenotazioni_folder.py:281 msgid "week_table_overrides_help" msgstr "Inserisci qui eventuali personalizzazioni nella schedulazione settimanale che andranno a vincere su quella standard per un determinato periodo di tempo." #. Default: "Week table overrides" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:361 +#: ../content/prenotazioni_folder.py:280 msgid "week_table_overrides_label" -msgstr "Personalizzazioni schedulazione settimanale" +msgstr "Personalizzazioni Schedulazione Settimanale" #. Default: "You tried to delete booking with a wrong action." -#: redturtle/prenotazioni/browser/delete_reservation.py:97 +#: ../browser/delete_reservation.py:97 msgid "wrong_authenticator" msgstr "Stai cercando di cancellare una prenotazione con un'azione sbagliata." diff --git a/src/redturtle/prenotazioni/locales/redturtle.prenotazioni.pot b/src/redturtle/prenotazioni/locales/redturtle.prenotazioni.pot index cb203fcf..bf864351 100644 --- a/src/redturtle/prenotazioni/locales/redturtle.prenotazioni.pot +++ b/src/redturtle/prenotazioni/locales/redturtle.prenotazioni.pot @@ -1,10 +1,10 @@ -# --- PLEASE EDIT THE LINES BELOW CORRECTLY --- -# SOME DESCRIPTIVE TITLE. -# FIRST AUTHOR , YEAR. +#--- PLEASE EDIT THE LINES BELOW CORRECTLY --- +#SOME DESCRIPTIVE TITLE. +#FIRST AUTHOR , YEAR. msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2023-12-14 13:19+0000\n" +"POT-Creation-Date: 2024-01-04 01:37+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,1445 +17,1614 @@ msgstr "" "Preferred-Encodings: utf-8 latin1\n" "Domain: redturtle.prenotazioni\n" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:63 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:46 -#: redturtle/prenotazioni/browser/vacations.py:74 +#: ../browser/prenotazioni_search.py:63 +#: ../browser/stats/booking_stats.py:46 +#: ../browser/vacations.py:74 msgid " format (YYYY-MM-DD)" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniFolder.xml +#: ../profiles/default/types/PrenotazioniFolder.xml msgid "A folder that will contain booking" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "A folder that will contain booking for this day" msgstr "" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:166 -msgid "A mail action that sends email notify when a booking is moved in an other slot." -msgstr "" - -msgid "Add" -msgstr "" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:165 -msgid "Add moved booking Mail Action" -msgstr "" - -#: redturtle/prenotazioni/content/prenotazioni_folder.py:478 -#: redturtle/prenotazioni/content/validators.py:213 +#: ../content/prenotazioni_folder.py:406 +#: ../content/validators.py:213 msgid "Afternoon start should not be greater than end." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:483 -msgid "App IO notification" -msgstr "" - -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:29 +#: ../browser/templates/prenotazione.pt:29 msgid "Attention" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:27 +#: ../adapters/stringinterp.py:27 msgid "Booking" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniFolder.xml +#: ../profiles/default/types/PrenotazioniFolder.xml msgid "Booking Folder" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioneType.xml +#: ../profiles/default/types/PrenotazioneType.xml msgid "Booking Type" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniWeek.xml +#: ../profiles/default/types/PrenotazioniWeek.xml msgid "Booking Week Folder" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniYear.xml +#: ../profiles/default/types/PrenotazioniYear.xml msgid "Booking Year Folder" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:44 +#: ../behaviors/booking_folder/appio/configure.zcml:17 +msgid "Booking folder notification appio" +msgstr "" + +#: ../behaviors/booking_folder/email/configure.zcml:17 +msgid "Booking folder notification email" +msgstr "" + +#: ../behaviors/booking_folder/sms/configure.zcml:17 +msgid "Booking folder notification sms" +msgstr "" + +#: ../browser/templates/prenotazione.pt:44 msgid "Booking for" msgstr "" -#: redturtle/prenotazioni/contentrules/configure.zcml:30 -msgid "Booking moved" +#: ../behaviors/booking_folder/appio/configure.zcml:27 +msgid "Booking type notification appio" msgstr "" #. Default: "Change date/time" -#: redturtle/prenotazioni/profiles/default/actions.xml +#: ../profiles/default/actions.xml msgid "Change date/time" msgstr "" #. Default: "Complete address" -#: redturtle/prenotazioni/behaviors/booking_folder.py:43 +#: ../behaviors/booking_folder/contacts.py:43 msgid "Complete address" msgstr "" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:170 -msgid "Configure element" -msgstr "" - -#: redturtle/prenotazioni/behaviors/booking_folder.py:36 +#: ../behaviors/booking_folder/contacts.py:36 msgid "Contact PEC" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:30 +#: ../behaviors/booking_folder/contacts.py:30 msgid "Contact fax" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:24 +#: ../behaviors/booking_folder/contacts.py:24 msgid "Contact phone" msgstr "" -#: redturtle/prenotazioni/behaviors/configure.zcml:19 +#: ../behaviors/booking_folder/configure.zcml:19 msgid "Contacts fields." msgstr "" -#: redturtle/prenotazioni/behaviors/configure.zcml:19 +#: ../behaviors/booking_folder/configure.zcml:19 msgid "Contatti cartella prenotazioni" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:46 +#: ../browser/templates/prenotazioni_search.pt:46 msgid "Content listing" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:262 +#: ../content/prenotazioni_folder.py:181 msgid "Data fine validità" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:259 +#: ../content/prenotazioni_folder.py:178 msgid "Data inizio validità" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:612 +#: ../content/prenotazioni_folder.py:471 msgid "Date validità" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:421 +#: ../content/prenotazioni_folder.py:340 msgid "Days booking is not allowed before" msgstr "" -msgid "Delete" -msgstr "" - #. Default: "Descrizione Agenda" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:218 +#: ../content/prenotazioni_folder.py:137 msgid "Descrizione Agenda" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioneType.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/PrenotazioneType.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "Edit" msgstr "" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:185 -msgid "Edit moved booking Mail Action" -msgstr "" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:72 -msgid "Email report to prenotazione owner" -msgstr "" - -#: redturtle/prenotazioni/content/prenotazione.py:175 +#: ../content/prenotazione.py:175 msgid "Expiration date booking" msgstr "" #. Default: "Campo" -#: redturtle/prenotazioni/browser/z3c_custom_widget.py:150 +#: ../browser/z3c_custom_widget.py:150 msgid "Field" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:116 +#: ../content/prenotazioni_folder.py:113 msgid "Friday" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:107 -#: redturtle/prenotazioni/content/prenotazione.py:170 +#: ../browser/templates/prenotazione.pt:107 +#: ../content/prenotazione.py:170 msgid "Gate" msgstr "" -msgid "Group" -msgstr "" - #. Default: "How to get here" -#: redturtle/prenotazioni/behaviors/booking_folder.py:19 +#: ../behaviors/booking_folder/contacts.py:19 msgid "How to get here" msgstr "" -#: redturtle/prenotazioni/content/validators.py:136 +#: ../content/validators.py:136 msgid "In the same day there are overlapping intervals" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/Prenotazione.xml msgid "Informations about a single booking" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:219 +#: ../content/prenotazioni_folder.py:138 msgid "Inserire il testo di presentazione dell'agenda corrente" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:450 +#: ../content/prenotazioni_folder.py:378 msgid "Insert a list of email addresses that will be notified when new bookings get created." msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:20 +#: ../behaviors/booking_folder/contacts.py:20 msgid "Insert here indications on how to reach the office" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:44 +#: ../behaviors/booking_folder/contacts.py:44 msgid "Insert here the complete office address" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:37 +#: ../behaviors/booking_folder/contacts.py:37 msgid "Insert here the contact PEC" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:31 +#: ../behaviors/booking_folder/contacts.py:31 msgid "Insert here the contact fax" msgstr "" -#: redturtle/prenotazioni/behaviors/booking_folder.py:25 +#: ../behaviors/booking_folder/contacts.py:25 msgid "Insert here the contact phone" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:372 +#: ../content/prenotazioni_folder.py:291 msgid "Insert pause table schema." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:295 +#: ../content/prenotazioni_folder.py:214 msgid "Insert week table schema." msgstr "" -#: redturtle/prenotazioni/configure.zcml:32 +#: ../configure.zcml:31 msgid "Installs the redturtle.prenotazioni add-on." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:409 -msgid "Max days in the future" +#: ../staging/configure.zcml:16 +msgid "Installs the redturtle.prenotazioni.staging add-on (demo site purpose only)." msgstr "" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:42 -msgid "Message" +#: ../content/prenotazioni_folder.py:328 +msgid "Max days in the future" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:112 +#: ../content/prenotazioni_folder.py:109 msgid "Monday" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:475 -#: redturtle/prenotazioni/content/validators.py:208 +#: ../content/prenotazioni_folder.py:403 +#: ../content/validators.py:208 msgid "Morning start should not be greater than end." msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:152 +#: ../browser/templates/prenotazione.pt:152 msgid "Move booking" msgstr "" -msgid "Move down" +#: ../restapi/services/booking/vacation.py:27 +msgid "Nessuno slot creato, verificare la corretteza dei dati inseriti" msgstr "" -msgid "Move up" +#: ../content/prenotazioni_folder.py:193 +msgid "No" msgstr "" -#: redturtle/prenotazioni/restapi/services/booking/vacation.py:27 -msgid "Nessuno slot creato, verificare la corretteza dei dati inseriti" +#: ../behaviors/booking_folder/appio/configure.zcml:17 +msgid "Notification APPIo" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:274 -msgid "No" +#: ../behaviors/booking_folder/appio/configure.zcml:27 +msgid "Notification APPIo for PrenotazioneType c.t." +msgstr "" + +#: ../behaviors/booking_folder/sms/configure.zcml:17 +msgid "Notification SMS" +msgstr "" + +#: ../behaviors/booking_folder/email/configure.zcml:17 +msgid "Notification email templates" msgstr "" -#: redturtle/prenotazioni/content/pause.py:43 +#: ../content/pause.py:43 msgid "Pause" msgstr "" -#: redturtle/prenotazioni/content/validators.py:100 +#: ../content/validators.py:100 msgid "Pause end should be greater than pause start" msgstr "" -#: redturtle/prenotazioni/content/validators.py:121 +#: ../content/validators.py:121 msgid "Pause should be included in morning slot or afternoon slot" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:371 +#: ../content/prenotazioni_folder.py:290 msgid "Pause table" msgstr "" -#: redturtle/prenotazioni/browser/prenotazione_add.py:221 +#: ../browser/prenotazione_add.py:221 msgid "Please provide a booking date" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/Prenotazione.xml msgid "Prenotazione" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "PrenotazioniDay" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniWeek.xml +#: ../profiles/default/types/PrenotazioniWeek.xml msgid "PrenotazioniWeek" msgstr "" -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniYear.xml +#: ../profiles/default/types/PrenotazioniYear.xml msgid "PrenotazioniYear" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazione_print.pt:129 +#: ../browser/templates/prenotazione_print.pt:129 msgid "Print" msgstr "" -#: redturtle/prenotazioni/configure.zcml:57 -msgid "Profile create to add the new default content rule: booking-confirm" -msgstr "" - -#: redturtle/prenotazioni/restapi/services/booking/add.py:72 +#: ../restapi/services/booking/add.py:77 msgid "Required input '${field}' is missing." msgstr "" -#: redturtle/prenotazioni/browser/prenotazione_add.py:217 +#: ../browser/prenotazione_add.py:217 msgid "Required input is missing." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:449 +#: ../content/prenotazioni_folder.py:377 msgid "Responsible email" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:117 +#: ../content/prenotazioni_folder.py:114 msgid "Saturday" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:16 +#: ../browser/templates/prenotazioni_search.pt:16 msgid "Search for" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:111 +#: ../content/prenotazioni_folder.py:108 msgid "Select a day" msgstr "" -#: redturtle/prenotazioni/contentrules/configure.zcml:57 -msgid "Send Email to booking owner when a booking is moved" -msgstr "" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:32 -msgid "Sender email" -msgstr "" - -#: redturtle/prenotazioni/adapters/booker.py:234 -#: redturtle/prenotazioni/restapi/services/booking/add.py:57 +#: ../adapters/booker.py:249 +#: ../restapi/services/booking/add.py:58 msgid "Sorry, this slot is not available anymore." msgstr "" -#: redturtle/prenotazioni/adapters/booker.py:273 +#: ../adapters/booker.py:292 msgid "Sorry, this slot is not available or does not fit your booking." msgstr "" -#: redturtle/prenotazioni/adapters/booker.py:239 +#: ../adapters/booker.py:143 msgid "Sorry, you can not book this slot for now." msgstr "" -#: redturtle/prenotazioni/content/prenotazione.py:171 +#: ../content/prenotazione.py:171 msgid "Sportello a cui presentarsi" msgstr "" -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:26 -msgid "Subject" -msgstr "" - -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:27 -msgid "Subject of the message" -msgstr "" - -#: redturtle/prenotazioni/content/prenotazioni_folder.py:118 +#: ../content/prenotazioni_folder.py:115 msgid "Sunday" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:37 +#: ../adapters/stringinterp.py:37 msgid "The booked date." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:50 +#: ../adapters/stringinterp.py:50 msgid "The booked end date." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:63 +#: ../adapters/stringinterp.py:63 msgid "The booked time." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:96 +#: ../adapters/stringinterp.py:96 msgid "The booking code." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:291 +#: ../adapters/stringinterp.py:291 msgid "The booking folder title" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:211 +#: ../adapters/stringinterp.py:211 msgid "The booking human readable date" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:177 +#: ../adapters/stringinterp.py:177 msgid "The booking office contact fax." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:167 +#: ../adapters/stringinterp.py:167 msgid "The booking office contact pec address." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:157 +#: ../adapters/stringinterp.py:157 msgid "The booking office contact phone." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:250 +#: ../adapters/stringinterp.py:250 msgid "The booking operator url" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:108 +#: ../adapters/stringinterp.py:108 msgid "The booking print url." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:259 +#: ../adapters/stringinterp.py:259 msgid "The booking refuse message" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:280 +#: ../adapters/stringinterp.py:280 msgid "The booking requirements url" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:75 +#: ../adapters/stringinterp.py:75 msgid "The booking time end." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:87 +#: ../adapters/stringinterp.py:87 msgid "The booking type." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:238 +#: ../adapters/stringinterp.py:238 msgid "The booking url with delete token" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:199 +#: ../adapters/stringinterp.py:199 msgid "The complete address information of the office whereuser book a reservation" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:139 +#: ../adapters/stringinterp.py:139 msgid "The email address of the user who made the reservation." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:28 +#: ../adapters/stringinterp.py:28 msgid "The gate booked." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:187 +#: ../adapters/stringinterp.py:187 msgid "The information to reach the office where user book a reservation" msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:130 +#: ../adapters/stringinterp.py:130 msgid "The phone number of the user who made the reservation." msgstr "" -#: redturtle/prenotazioni/adapters/booker.py:325 +#: ../adapters/booker.py:341 msgid "This day is not valid." msgstr "" -#: redturtle/prenotazioni/adapters/booker.py:320 +#: ../adapters/booker.py:336 msgid "This gate has some booking schedule in this time period." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:115 +#: ../content/prenotazioni_folder.py:112 msgid "Thursday" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:113 +#: ../content/prenotazioni_folder.py:110 msgid "Tuesday" msgstr "" -#: redturtle/prenotazioni/configure.zcml:41 +#: ../configure.zcml:40 msgid "Uninstalls the redturtle.prenotazioni add-on." msgstr "" -#: redturtle/prenotazioni/restapi/services/booking/add.py:108 -msgid "Unknown booking type '${booking_type}'." +#: ../staging/configure.zcml:25 +msgid "Uninstalls the redturtle.prenotazioni.staging add-on (demo site purpose only)." msgstr "" -#: redturtle/prenotazioni/configure.zcml:57 -msgid "Used to add new contentrules" +#: ../restapi/services/booking/add.py:113 +msgid "Unknown booking type '${booking_type}'." msgstr "" -#: redturtle/prenotazioni/profiles/default/types/Prenotazione.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioneType.xml -#: redturtle/prenotazioni/profiles/default/types/PrenotazioniDay.xml +#: ../profiles/default/types/Prenotazione.xml +#: ../profiles/default/types/PrenotazioneType.xml +#: ../profiles/default/types/PrenotazioniDay.xml msgid "View" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:114 +#: ../content/prenotazioni_folder.py:111 msgid "Wednesday" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:294 +#: ../content/prenotazioni_folder.py:213 msgid "Week table" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:273 +#: ../content/prenotazioni_folder.py:192 msgid "Yes" msgstr "" -#: redturtle/prenotazioni/restapi/services/booking/add.py:45 +#: ../restapi/services/booking/add.py:70 msgid "You are not allowed to force the gate." msgstr "" -#: redturtle/prenotazioni/content/validators.py:92 +#: ../content/validators.py:92 msgid "You must set both start and end" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:472 -#: redturtle/prenotazioni/content/validators.py:203 +#: ../content/prenotazioni_folder.py:400 +#: ../content/validators.py:203 msgid "You should set a start time for afternoon." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:468 -#: redturtle/prenotazioni/content/validators.py:195 +#: ../content/prenotazioni_folder.py:396 +#: ../content/validators.py:195 msgid "You should set a start time for morning." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:470 -#: redturtle/prenotazioni/content/validators.py:199 +#: ../content/prenotazioni_folder.py:398 +#: ../content/validators.py:199 msgid "You should set an end time for afternoon." msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:466 -#: redturtle/prenotazioni/content/validators.py:191 +#: ../content/prenotazioni_folder.py:394 +#: ../content/validators.py:191 msgid "You should set an end time for morning." msgstr "" -#: redturtle/prenotazioni/adapters/stringinterp.py:124 +#: ../adapters/stringinterp.py:124 msgid "[DEPRECATED] The booking print url with delete token." msgstr "" #. Default: "Leave empty, and this Booking Folder will never expire" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:263 +#: ../content/prenotazioni_folder.py:182 msgid "aData_help" msgstr "" #. Default: "Book" -#: redturtle/prenotazioni/browser/prenotazione_add.py:199 -#: redturtle/prenotazioni/browser/vacations.py:207 +#: ../browser/prenotazione_add.py:199 +#: ../browser/vacations.py:207 msgid "action_book" msgstr "" #. Default: "Cancel" -#: redturtle/prenotazioni/browser/prenotazione_add.py:252 -#: redturtle/prenotazioni/browser/prenotazione_move.py:150 -#: redturtle/prenotazioni/browser/vacations.py:232 +#: ../browser/prenotazione_add.py:252 +#: ../browser/prenotazione_move.py:147 +#: ../browser/vacations.py:232 msgid "action_cancel" msgstr "" #. Default: "Move" -#: redturtle/prenotazioni/browser/prenotazione_move.py:125 +#: ../browser/prenotazione_move.py:122 msgid "action_move" msgstr "" #. Default: "Search" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:250 +#: ../browser/prenotazioni_search.py:250 msgid "action_search" msgstr "" #. Default: "End time in the afternoon" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:99 +#: ../content/prenotazioni_folder.py:96 msgid "afternoon_end_label" msgstr "" #. Default: "Start time in the afternoon" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:93 +#: ../content/prenotazioni_folder.py:90 msgid "afternoon_start_label" msgstr "" #. Default: "All" -#: redturtle/prenotazioni/vocabularies/voc_booking_type_gates.py:22 +#: ../vocabularies/voc_booking_type_gates.py:16 msgid "all" msgstr "" #. Default: "Automatically confirm." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:439 +#: ../content/prenotazioni_folder.py:358 msgid "auto_confirm" msgstr "" #. Default: "All bookings will be automatically accepted." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:440 +#: ../content/prenotazioni_folder.py:359 msgid "auto_confirm_help" msgstr "" #. Default: "Automatically confirmfor managers." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:448 +#: ../content/prenotazioni_folder.py:367 msgid "auto_confirm_manager" msgstr "" #. Default: "All bookings created by Managers will be automatically accepted." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:449 +#: ../content/prenotazioni_folder.py:368 msgid "auto_confirm_manager_help" msgstr "" #. Default: "End date should be greater than start." -#: redturtle/prenotazioni/restapi/services/available_slots/get.py:44 +#: ../restapi/services/available_slots/get.py:44 msgid "available_slots_wrong_dates" msgstr "" #. Default: "Please select a booking slot." -#: redturtle/prenotazioni/browser/templates/week.pt:40 +#: ../browser/templates/week.pt:40 msgid "book_it" msgstr "" #. Default: "Bookable time" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:454 +#: ../browser/templates/prenotazione_macros.pt:454 msgid "bookable_time" msgstr "" #. Default: "${day}, ore ${booking_time}, prenotato da ${booked_by}, prenotazione: ${booking_type} durata: ${duration} minuti" -#: redturtle/prenotazioni/browser/week.py:276 +#: ../browser/week.py:276 msgid "booked_prenotation_message" msgstr "" #. Default: "Booking confirmed" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:456 +#: ../browser/templates/prenotazione_macros.pt:456 msgid "booking_confirmed" msgstr "" -#: redturtle/prenotazioni/browser/prenotazione_add.py:231 -#: redturtle/prenotazioni/browser/vacations.py:204 +#: ../browser/prenotazione_add.py:231 +#: ../browser/vacations.py:204 msgid "booking_created" msgstr "" #. Default: "Your booking has been deleted." -#: redturtle/prenotazioni/browser/delete_reservation.py:114 +#: ../browser/delete_reservation.py:114 msgid "booking_deleted_success" msgstr "" -#: redturtle/prenotazioni/browser/prenotazione_move.py:140 +#. Default: "Booking fields" +#: ../content/prenotazioni_folder.py:500 +msgid "booking_fields_label" +msgstr "" + +#: ../browser/prenotazione_move.py:137 msgid "booking_moved" msgstr "" #. Default: "Booking pending" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:458 +#: ../browser/templates/prenotazione_macros.pt:458 msgid "booking_pending" msgstr "" #. Default: "Booking refused" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:460 +#: ../browser/templates/prenotazione_macros.pt:460 msgid "booking_refused" msgstr "" #. Default: "Duration value" -#: redturtle/prenotazioni/content/prenotazione_type.py:15 +#: ../content/prenotazione_type.py:15 msgid "booking_type_duration_label" msgstr "" #. Default: "Name" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:427 +#: ../browser/templates/prenotazione_macros.pt:427 msgid "booking_type_name" msgstr "" #. Default: "List of requirements to recieve the service" -#: redturtle/prenotazioni/content/prenotazione_type.py:23 +#: ../content/prenotazione_type.py:23 msgid "booking_type_requirements_help" msgstr "" #. Default: "Requirements" -#: redturtle/prenotazioni/content/prenotazione_type.py:22 +#: ../content/prenotazione_type.py:22 msgid "booking_type_requirements_labled" msgstr "" #. Default: "Value" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:428 +#: ../browser/templates/prenotazione_macros.pt:428 msgid "booking_type_value" msgstr "" #. Default: "You may want to select another time slot to book one of these." -#: redturtle/prenotazioni/browser/templates/booking_type_radio_widget.pt:77 +#: ../browser/templates/booking_type_radio_widget.pt:77 msgid "booking_type_widget_suggest_reselect" msgstr "" #. Default: "The following tipologies will not fit the time you selected:" -#: redturtle/prenotazioni/browser/templates/booking_type_radio_widget.pt:65 +#: ../browser/templates/booking_type_radio_widget.pt:65 msgid "booking_type_widget_warn_unavailable" msgstr "" +#. Default: "Set message text for all available notification events." +#: ../behaviors/booking_folder/appio/__init__.py:257 +msgid "bookings_appio_templates_help" +msgstr "" + +#. Default: "AppIO Notifications" +#: ../behaviors/booking_folder/appio/__init__.py:253 +msgid "bookings_appio_templates_label" +msgstr "" + +#. Default: "Set message text for all available notification events." +#: ../behaviors/booking_folder/email/__init__.py:257 +msgid "bookings_email_templates_help" +msgstr "" + +#. Default: "Email Notifications" +#: ../behaviors/booking_folder/email/__init__.py:253 +msgid "bookings_email_templates_label" +msgstr "" + #. Default: "Booking limit({limit}) for the {booking_type} type is exceed for the current user" -#: redturtle/prenotazioni/exceptions/booker.py:15 +#: ../exceptions/booker.py:15 msgid "bookings_limit_exceeded_exception" msgstr "" #. Default: "Bookings not in agenda" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:111 +#: ../browser/templates/prenotazione_macros.pt:111 msgid "bookings_not_in_agenda" msgstr "" +#. Default: "Set message text for all available notification events. Remember that SMS has a 160 characters limit. Depending on your gateway service, it can split messages, if you exceed that limit." +#: ../behaviors/booking_folder/sms/__init__.py:144 +msgid "bookings_sms_templates_help" +msgstr "" + +#. Default: "SMS Notifications" +#: ../behaviors/booking_folder/sms/__init__.py:140 +msgid "bookings_sms_templates_label" +msgstr "" + #. Default: "Busy" -#: redturtle/prenotazioni/browser/prenotazioni_context_state.py:47 +#: ../browser/prenotazioni_context_state.py:45 msgid "busy" msgstr "" #. Default: "Your booking has been confirmed." -#: redturtle/prenotazioni/browser/prenotazione_print.py:28 +#: ../browser/prenotazione_print.py:28 msgid "confirm_booking_confirmed_message" msgstr "" #. Default: "Your booking has been refused." -#: redturtle/prenotazioni/browser/prenotazione_print.py:32 +#: ../browser/prenotazione_print.py:32 msgid "confirm_booking_refused_message" msgstr "" #. Default: "Your booking has to be confirmed by the administrators." -#: redturtle/prenotazioni/browser/prenotazione_print.py:24 +#: ../browser/prenotazione_print.py:24 msgid "confirm_booking_waiting_message" msgstr "" #. Default: "Show here contacts information that will be used by authomatic mail system" -#: redturtle/prenotazioni/behaviors/booking_folder.py:49 +#: ../behaviors/booking_folder/contacts.py:49 msgid "contacts_help" msgstr "" #. Default: "Contacts" -#: redturtle/prenotazioni/behaviors/booking_folder.py:48 +#: ../behaviors/booking_folder/contacts.py:48 msgid "contacts_label" msgstr "" #. Default: "This day is not valid." -#: redturtle/prenotazioni/browser/vacations.py:224 +#: ../browser/vacations.py:224 msgid "day_error" msgstr "" #. Default: "Day of week" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:73 +#: ../content/prenotazioni_folder.py:70 msgid "day_label" msgstr "" #. Default: "You can't delete your reservation; it's too late." -#: redturtle/prenotazioni/browser/delete_reservation.py:138 +#: ../browser/delete_reservation.py:138 msgid "delete_expired_booking" msgstr "" #. Default: "Delete reservation request for: ${name}" -#: redturtle/prenotazioni/browser/delete_reservation.py:61 +#: ../browser/delete_reservation.py:61 msgid "delete_reservation_request" msgstr "" #. Default: "Unique booking code" -#: redturtle/prenotazioni/content/prenotazione.py:181 +#: ../content/prenotazione.py:181 msgid "description_booking_code" msgstr "" #. Default: "If you work for a company, please specify its name." -#: redturtle/prenotazioni/content/prenotazione.py:161 +#: ../content/prenotazione.py:161 msgid "description_company" msgstr "" #. Default: "The gate that will be unavailable" -#: redturtle/prenotazioni/browser/vacations.py:68 +#: ../browser/vacations.py:68 msgid "description_gate" msgstr "" #. Default: "This text will appear in the calendar cells" -#: redturtle/prenotazioni/browser/vacations.py:61 +#: ../browser/vacations.py:61 msgid "description_title" msgstr "" #. Default: "Foreseen booking time: ${booking_time}" -#: redturtle/prenotazioni/browser/week.py:225 +#: ../browser/week.py:225 msgid "foreseen_booking_time" msgstr "" #. Default: "${booking_time}, Orario non disponibile" -#: redturtle/prenotazioni/browser/week.py:244 +#: ../browser/week.py:244 msgid "foreseen_busy_time" msgstr "" -msgid "from_label" -msgstr "" - #. Default: "You should set a start range." -#: redturtle/prenotazioni/content/validators.py:160 +#: ../content/validators.py:160 msgid "from_month_error" msgstr "" #. Default: "Selected day is too big for that month for \"from\" field." -#: redturtle/prenotazioni/content/validators.py:167 +#: ../content/validators.py:167 msgid "from_month_too_days_error" msgstr "" #. Default: "Fullname" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:55 +#: ../browser/templates/prenotazione.pt:55 msgid "fullname" msgstr "" #. Default: "Limit booking in the future to an amount of days in the future starting from the current day. \nKeep 0 to give no limits." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:410 +#: ../content/prenotazioni_folder.py:329 msgid "futureDays" msgstr "" #. Default: "Put gates here (one per line)." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:432 +#: ../content/prenotazioni_folder.py:351 msgid "gates_help" msgstr "" #. Default: "Gates" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:431 +#: ../content/prenotazioni_folder.py:350 msgid "gates_label" msgstr "" -#: redturtle/prenotazioni/browser/prenotazione_add.py:156 +#: ../browser/prenotazione_add.py:156 msgid "help_prenotazione_add" msgstr "" #. Default: "User will not be able to add a booking unless those fields are filled. Remember that, whatever you selected in this list, users have to supply at least one of \"Email\", \"Mobile\", or \"Telephone\"" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:245 +#: ../content/prenotazioni_folder.py:164 msgid "help_required_booking_fields" msgstr "" #. Default: "States if it is not allowed to reserve a booking during the current day" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:284 +#: ../content/prenotazioni_folder.py:203 msgid "help_same_day_booking_disallowed" msgstr "" #. Default: "List of available reservation type for the current agenda" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:424 +#: ../browser/templates/prenotazione_macros.pt:424 msgid "help_tipologies" msgstr "" #. Default: "User will not be able to add a booking unless those fields are filled. Remember that, whatever you selected in this list, users have to supply at least one of \"Email\" or \"Telephone\"" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:227 +#: ../content/prenotazioni_folder.py:146 msgid "help_visible_booking_fields" msgstr "" #. Default: "Set holidays (one for line) in DD/MM/YYYY. you can write * for the year, if this event is yearly." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:385 +#: ../content/prenotazioni_folder.py:304 msgid "holidays_help" msgstr "" #. Default: "Holidays" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:384 +#: ../content/prenotazioni_folder.py:303 msgid "holidays_label" msgstr "" #. Default: "Booking for ${title}" -#: redturtle/prenotazioni/adapters/ical.py:84 +#: ../adapters/ical.py:84 msgid "ical_booking_label" msgstr "" -#: redturtle/prenotazioni/browser/vacations.py:32 +#: ../browser/vacations.py:32 msgid "invalid_date" msgstr "" #. Default: "Invalid email address" -#: redturtle/prenotazioni/content/prenotazione.py:32 +#: ../content/prenotazione.py:32 msgid "invalid_email_address" msgstr "" #. Default: "Invalid start or end date" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:40 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:26 +#: ../browser/prenotazioni_search.py:40 +#: ../browser/stats/booking_stats.py:26 msgid "invalid_end:search_date" msgstr "" #. Default: "Invalid fiscal code" -#: redturtle/prenotazioni/content/prenotazione.py:40 +#: ../content/prenotazione.py:40 msgid "invalid_fiscalcode" msgstr "" #. Default: "Invalid phone number" -#: redturtle/prenotazioni/content/prenotazione.py:28 +#: ../content/prenotazione.py:28 msgid "invalid_phone_number" msgstr "" -#: redturtle/prenotazioni/browser/vacations.py:36 +#: ../browser/vacations.py:36 msgid "invalid_time" msgstr "" #. Default: "This date is past" -#: redturtle/prenotazioni/content/prenotazione.py:36 +#: ../content/prenotazione.py:36 msgid "is_not_future_date" msgstr "" #. Default: "Booking code" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:106 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:123 -#: redturtle/prenotazioni/browser/templates/prenotazione_print.pt:110 +#: ../browser/templates/delete_reservation.pt:106 +#: ../browser/templates/prenotazione.pt:123 +#: ../browser/templates/prenotazione_print.pt:110 msgid "label_booking_code" msgstr "" #. Default: "Company" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:62 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:38 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:75 +#: ../browser/templates/delete_reservation.pt:62 +#: ../browser/templates/manager_notification_mail.pt:38 +#: ../browser/templates/prenotazione.pt:75 msgid "label_booking_company" msgstr "" #. Default: "Booking date" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:80 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:50 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:87 +#: ../browser/templates/delete_reservation.pt:80 +#: ../browser/templates/manager_notification_mail.pt:50 +#: ../browser/templates/prenotazione.pt:87 msgid "label_booking_date" msgstr "" #. Default: "${from_date} at ${at}" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:92 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:54 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:98 +#: ../browser/templates/delete_reservation.pt:92 +#: ../browser/templates/manager_notification_mail.pt:54 +#: ../browser/templates/prenotazione.pt:98 msgid "label_booking_date_range" msgstr "" #. Default: "Subject" -#: redturtle/prenotazioni/browser/prenotazione_add.py:41 -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:74 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:46 +#: ../browser/prenotazione_add.py:41 +#: ../browser/templates/delete_reservation.pt:74 +#: ../browser/templates/manager_notification_mail.pt:46 msgid "label_booking_description" msgstr "" #. Default: "Email" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:50 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:30 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:63 +#: ../browser/templates/delete_reservation.pt:50 +#: ../browser/templates/manager_notification_mail.pt:30 +#: ../browser/templates/prenotazione.pt:63 msgid "label_booking_email" msgstr "" #. Default: "Fiscal code" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:68 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:42 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:79 +#: ../browser/templates/delete_reservation.pt:68 +#: ../browser/templates/manager_notification_mail.pt:42 +#: ../browser/templates/prenotazione.pt:79 msgid "label_booking_fiscalcode" msgstr "" #. Default: "Phone number" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:56 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:34 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:71 +#: ../browser/templates/delete_reservation.pt:56 +#: ../browser/templates/manager_notification_mail.pt:34 +#: ../browser/templates/prenotazione.pt:71 msgid "label_booking_phone" msgstr "" #. Default: "Staff notes" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:113 -#: redturtle/prenotazioni/content/prenotazione.py:186 +#: ../browser/templates/prenotazione.pt:113 +#: ../content/prenotazione.py:186 msgid "label_booking_staff_notes" msgstr "" #. Default: "Booking time" -#: redturtle/prenotazioni/browser/prenotazione_move.py:34 -#: redturtle/prenotazioni/content/prenotazione.py:126 +#: ../browser/prenotazione_move.py:31 +#: ../content/prenotazione.py:126 msgid "label_booking_time" msgstr "" #. Default: "Fullname" -#: redturtle/prenotazioni/browser/prenotazione_add.py:38 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:22 -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:52 +#: ../browser/prenotazione_add.py:38 +#: ../browser/templates/manager_notification_mail.pt:22 +#: ../browser/templates/prenotazioni_search.pt:52 msgid "label_booking_title" msgstr "" #. Default: "Booking type" -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:44 -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:26 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:59 +#: ../browser/templates/delete_reservation.pt:44 +#: ../browser/templates/manager_notification_mail.pt:26 +#: ../browser/templates/prenotazione.pt:59 msgid "label_booking_type" msgstr "" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:293 -#: redturtle/prenotazioni/vocabularies/requirable_booking_fields.py:24 +#: ../browser/prenotazioni_search.py:293 +#: ../vocabularies/requirable_booking_fields.py:24 msgid "label_booking_{}" msgstr "" #. Default: "End date" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:68 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:52 +#: ../browser/prenotazioni_search.py:68 +#: ../browser/stats/booking_stats.py:52 msgid "label_end" msgstr "" #. Default: "End time" -#: redturtle/prenotazioni/browser/vacations.py:84 +#: ../browser/vacations.py:84 msgid "label_end_time" msgstr "" #. Default: "Gate" -#: redturtle/prenotazioni/browser/prenotazione_move.py:35 -#: redturtle/prenotazioni/browser/prenotazioni_search.py:56 -#: redturtle/prenotazioni/browser/templates/delete_reservation.pt:100 +#: ../browser/prenotazione_move.py:32 +#: ../browser/prenotazioni_search.py:56 +#: ../browser/templates/delete_reservation.pt:100 msgid "label_gate" msgstr "" #. Default: "Go to the booking to see more details and manage it: ${url}" -#: redturtle/prenotazioni/browser/templates/manager_notification_mail.pt:65 +#: ../browser/templates/manager_notification_mail.pt:65 msgid "label_new_booking_notify_link" msgstr "" #. Default: "Required booking fields" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:244 +#: ../content/prenotazioni_folder.py:163 msgid "label_required_booking_fields" msgstr "" #. Default: "Disallow same day booking" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:280 +#: ../content/prenotazioni_folder.py:199 msgid "label_same_day_booking_disallowed" msgstr "" #. Default: "Selected date: ${date} — Time: ${slot}" -#: redturtle/prenotazioni/browser/prenotazione_add.py:141 +#: ../browser/prenotazione_add.py:141 msgid "label_selected_date" msgstr "" #. Default: "Start date " -#: redturtle/prenotazioni/browser/prenotazioni_search.py:62 -#: redturtle/prenotazioni/browser/stats/booking_stats.py:45 -#: redturtle/prenotazioni/browser/vacations.py:73 +#: ../browser/prenotazioni_search.py:62 +#: ../browser/stats/booking_stats.py:45 +#: ../browser/vacations.py:73 msgid "label_start" msgstr "" #. Default: "Start time" -#: redturtle/prenotazioni/browser/vacations.py:78 +#: ../browser/vacations.py:78 msgid "label_start_time" msgstr "" #. Default: "Text to search" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:48 +#: ../browser/prenotazioni_search.py:48 msgid "label_text" msgstr "" #. Default: "Reservation types" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:423 +#: ../browser/templates/prenotazione_macros.pt:423 msgid "label_tipologies" msgstr "" #. Default: "Title" -#: redturtle/prenotazioni/browser/vacations.py:60 +#: ../browser/vacations.py:60 msgid "label_title" msgstr "" #. Default: "User" -#: redturtle/prenotazioni/browser/stats/booking_stats.py:43 +#: ../browser/stats/booking_stats.py:43 msgid "label_user" msgstr "" #. Default: "Visible booking fields" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:226 +#: ../content/prenotazioni_folder.py:145 msgid "label_visible_booking_fields" msgstr "" #. Default: "Legend" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:447 +#: ../browser/templates/prenotazione_macros.pt:447 msgid "legend" msgstr "" #. Default: "Short description of available action for the booking board" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:448 +#: ../browser/templates/prenotazione_macros.pt:448 msgid "legend_description" msgstr "" #. Default: "The minimum value of a single slot is 5 minutes. You cannot book a reservation when the needed time exceeds the available time." -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:469 +#: ../browser/templates/prenotazione_macros.pt:469 msgid "legend_note" msgstr "" #. Default: "The number of simultaneous bookings allowed for the same user." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:602 +#: ../content/prenotazioni_folder.py:449 msgid "max_bookings_allowed_description" msgstr "" #. Default: "Maximum bookings number allowed" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:598 +#: ../content/prenotazioni_folder.py:445 msgid "max_bookings_allowed_label" msgstr "" -#. Default: "Type in here the message that you want to mail. Some defined content can be replaced: ${title} will be replaced with booking title (user fullname). ${date} will be replaced with booking new date. ${url} will be replaced by the booking url. ${portal} will be replaced by the title of the portal." -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:43 -msgid "message_help" -msgstr "" - #. Default: "Unable to find a booking with the givend id: ${uid}." -#: redturtle/prenotazioni/browser/delete_reservation.py:44 +#: ../browser/delete_reservation.py:44 msgid "missing_booking" msgstr "" #. Default: "You need to provide a reservation id." -#: redturtle/prenotazioni/browser/delete_reservation.py:38 +#: ../browser/delete_reservation.py:38 msgid "missing_uid" msgstr "" -msgid "month_label" -msgstr "" - #. Default: "End time in the morning" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:87 +#: ../content/prenotazioni_folder.py:84 msgid "morning_end_label" msgstr "" #. Default: "Start time in the morning" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:82 +#: ../content/prenotazioni_folder.py:79 msgid "morning_start_label" msgstr "" #. Default: "Go back to the calendar" -#: redturtle/prenotazioni/browser/prenotazioni_search.py:260 -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:192 -#: redturtle/prenotazioni/browser/templates/prenotazione_add.pt:127 +#: ../browser/prenotazioni_search.py:260 +#: ../browser/templates/prenotazione.pt:192 +#: ../browser/templates/prenotazione_add.pt:127 msgid "move_back_message" msgstr "" #. Default: "Move booking" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:163 +#: ../browser/templates/prenotazione.pt:163 msgid "move_booking" msgstr "" #. Default: "Please move this booking into a new available slot or" -#: redturtle/prenotazioni/browser/templates/prenotazione_move.pt:39 +#: ../browser/templates/prenotazione_move.pt:39 msgid "move_message" msgstr "" #. Default: "next week" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:39 +#: ../browser/templates/prenotazione_macros.pt:39 msgid "next-week" msgstr "" #. Default: "Booking is not allowed before the amount of days specified. \nKeep 0 to give no limits." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:422 +#: ../content/prenotazioni_folder.py:341 msgid "notBeforeDays" msgstr "" +#. Default: "Enable AppIO notifications." +#: ../behaviors/booking_folder/appio/__init__.py:123 +msgid "notifications_appio_enabled_help" +msgstr "" + +#. Default: "AppIO notifications" +#: ../behaviors/booking_folder/appio/__init__.py:122 +msgid "notifications_appio_enabled_label" +msgstr "" + +#. Default: "Enable Email notifications." +#: ../behaviors/booking_folder/email/__init__.py:123 +msgid "notifications_email_enabled_help" +msgstr "" + +#. Default: "Email notifications" +#: ../behaviors/booking_folder/email/__init__.py:122 +msgid "notifications_email_enabled_label" +msgstr "" + #. Default: "Notifications" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:642 +#: ../content/prenotazioni_folder.py:508 msgid "notifications_label" msgstr "" +#. Default: "Enable SMS notifications." +#: ../behaviors/booking_folder/sms/__init__.py:70 +msgid "notifications_sms_enabled_help" +msgstr "" + +#. Default: "SMS notifications" +#: ../behaviors/booking_folder/sms/__init__.py:69 +msgid "notifications_sms_enabled_label" +msgstr "" + +#. Default: "This is an automatic reminder about your booking on ${date} for ${booking_type}.

You can see details and print a reminder following this [link](${booking_print_url})." +#: ../behaviors/booking_folder/appio/__init__.py:111 +msgid "notify_as_reminder_appio_message_default_value" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking reminder on ${booking_date}" +#: ../behaviors/booking_folder/appio/__init__.py:101 +msgid "notify_as_reminder_appio_subject_default_value" +msgstr "" + +#. Default: "The message subject when a reminder will be sent." +#: ../behaviors/booking_folder/appio/__init__.py:231 +msgid "notify_as_reminder_appio_subject_help" +msgstr "" + +#. Default: "[Reminder] message" +#: ../behaviors/booking_folder/appio/__init__.py:239 +#: ../behaviors/booking_folder/email/__init__.py:239 +#: ../behaviors/booking_folder/sms/__init__.py:126 +msgid "notify_as_reminder_message" +msgstr "" + +#. Default: "This is an automatic reminder about your booking on ${date} for ${booking_type}.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:111 +msgid "notify_as_reminder_message_default_value" +msgstr "" + +#. Default: "The message text when a reminder will be sent." +#: ../behaviors/booking_folder/appio/__init__.py:243 +#: ../behaviors/booking_folder/email/__init__.py:243 +#: ../behaviors/booking_folder/sms/__init__.py:130 +msgid "notify_as_reminder_message_help" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}]: This is an automatic reminder about your booking on ${date} for ${booking_type}.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:58 +msgid "notify_as_reminder_sms_message_default_value" +msgstr "" + +#. Default: "[Reminder] subject" +#: ../behaviors/booking_folder/appio/__init__.py:227 +#: ../behaviors/booking_folder/email/__init__.py:227 +msgid "notify_as_reminder_subject" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking reminder on ${booking_date}" +#: ../behaviors/booking_folder/email/__init__.py:101 +msgid "notify_as_reminder_subject_default_value" +msgstr "" + +#. Default: "The message subject when a reminder will be sent." +#: ../behaviors/booking_folder/email/__init__.py:231 +msgid "notify_as_reminder_subject_help" +msgstr "" + #. Default: "Notify when confirmed." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:498 +#: ../content/prenotazioni_folder.py:418 msgid "notify_on_confirm" msgstr "" +#. Default: "The booking ${booking_type} for ${title} has been confirmed.

You can see details and print a reminder following this [link](${booking_print_url})." +#: ../behaviors/booking_folder/appio/__init__.py:48 +msgid "notify_on_confirm_appio_message_default_value" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking of ${booking_date} at ${booking_time} was accepted" +#: ../behaviors/booking_folder/appio/__init__.py:38 +msgid "notify_on_confirm_appio_subject_default_value" +msgstr "" + #. Default: "Notify via mail the user when his booking has been confirmed." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:499 +#: ../content/prenotazioni_folder.py:419 msgid "notify_on_confirm_help" msgstr "" -#. Default: "Prenotazione confirmed notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:552 +#. Default: "[Confirmed] message" +#: ../behaviors/booking_folder/appio/__init__.py:167 +#: ../behaviors/booking_folder/email/__init__.py:167 +#: ../behaviors/booking_folder/sms/__init__.py:90 msgid "notify_on_confirm_message" msgstr "" -#. Default: "The booking${booking_type} for ${title} was confirmed! Link" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:164 -#: redturtle/prenotazioni/upgrades.py:257 +#. Default: "The booking ${booking_type} for ${title} has been confirmed.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:48 msgid "notify_on_confirm_message_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:556 +#. Default: "The message text when a booking has been confirmed." +#: ../behaviors/booking_folder/appio/__init__.py:171 +#: ../behaviors/booking_folder/email/__init__.py:171 +#: ../behaviors/booking_folder/sms/__init__.py:94 msgid "notify_on_confirm_message_help" msgstr "" -#. Default: "Prenotazione confirmed notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:543 +#. Default: "[${prenotazioni_folder_title}]: Booking of ${booking_date} at ${booking_time} has been accepted.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:28 +msgid "notify_on_confirm_sms_message_default_value" +msgstr "" + +#. Default: "[Confirm] subject" +#: ../behaviors/booking_folder/appio/__init__.py:155 +#: ../behaviors/booking_folder/email/__init__.py:155 msgid "notify_on_confirm_subject" msgstr "" -#. Default: "Booking of ${booking_date} at ${booking_time} was accepted" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:154 -#: redturtle/prenotazioni/upgrades.py:250 +#. Default: "[${prenotazioni_folder_title}] Booking of ${booking_date} at ${booking_time} was accepted" +#: ../behaviors/booking_folder/email/__init__.py:38 msgid "notify_on_confirm_subject_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:547 +#. Default: "The message subject when a booking has been confirmed." +#: ../behaviors/booking_folder/appio/__init__.py:159 +#: ../behaviors/booking_folder/email/__init__.py:159 msgid "notify_on_confirm_subject_help" msgstr "" #. Default: "Notify when moved." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:507 +#: ../content/prenotazioni_folder.py:427 msgid "notify_on_move" msgstr "" +#. Default: "The booking scheduling for ${booking_type} was modified.

The new one is on ${booking_date} at ${booking_time}.

You can see details and print a reminder following this [link](${booking_print_url})." +#: ../behaviors/booking_folder/appio/__init__.py:69 +msgid "notify_on_move_appio_message_default_value" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking date modified for ${title}" +#: ../behaviors/booking_folder/appio/__init__.py:59 +msgid "notify_on_move_appio_subject_default_value" +msgstr "" + #. Default: "Notify via mail the user when his booking has been moved." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:508 +#: ../content/prenotazioni_folder.py:428 msgid "notify_on_move_help" msgstr "" -#. Default: "Prenotazione moved notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:570 +#. Default: "[Move] message" +#: ../behaviors/booking_folder/appio/__init__.py:191 +#: ../behaviors/booking_folder/email/__init__.py:191 +#: ../behaviors/booking_folder/sms/__init__.py:102 msgid "notify_on_move_message" msgstr "" -#. Default: "The booking scheduling of ${booking_type} was modified.The new one is on ${booking_date} at ${booking_time}. Link." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:184 -#: redturtle/prenotazioni/upgrades.py:271 +#. Default: "The booking scheduling for ${booking_type} was modified.

The new one is on ${booking_date} at ${booking_time}.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:69 msgid "notify_on_move_message_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:574 +#. Default: "The message text when a booking has been moved." +#: ../behaviors/booking_folder/appio/__init__.py:195 +#: ../behaviors/booking_folder/email/__init__.py:195 +#: ../behaviors/booking_folder/sms/__init__.py:106 msgid "notify_on_move_message_help" msgstr "" -#. Default: "Prenotazione moved notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:561 +#. Default: "[${prenotazioni_folder_title}]: The booking scheduling for ${booking_type} was modified.\nThe new one is on ${booking_date} at ${booking_time}.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:38 +msgid "notify_on_move_sms_message_default_value" +msgstr "" + +#. Default: "[Move] subject" +#: ../behaviors/booking_folder/appio/__init__.py:179 +#: ../behaviors/booking_folder/email/__init__.py:179 msgid "notify_on_move_subject" msgstr "" -#. Default: "Modified the boolking date for ${title}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:174 -#: redturtle/prenotazioni/upgrades.py:264 +#. Default: "[${prenotazioni_folder_title}] Booking date modified for ${title}" +#: ../behaviors/booking_folder/email/__init__.py:59 msgid "notify_on_move_subject_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:565 +#. Default: "The message subject when a booking has been moved." +#: ../behaviors/booking_folder/appio/__init__.py:183 +#: ../behaviors/booking_folder/email/__init__.py:183 msgid "notify_on_move_subject_help" msgstr "" #. Default: "Notify when rejected." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:516 +#: ../content/prenotazioni_folder.py:436 msgid "notify_on_refuse" msgstr "" +#. Default: "The booking ${booking_type} of ${booking_date} at ${booking_time} was refused." +#: ../behaviors/booking_folder/appio/__init__.py:91 +msgid "notify_on_refuse_appio_message_default_value" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking refused for ${title}" +#: ../behaviors/booking_folder/appio/__init__.py:81 +msgid "notify_on_refuse_appio_subject_default_value" +msgstr "" + #. Default: "Notify via mail the user when his booking has been rejected." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:517 +#: ../content/prenotazioni_folder.py:437 msgid "notify_on_refuse_help" msgstr "" -#. Default: "Prenotazione created notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:588 +#. Default: "[Refuse] message" +#: ../behaviors/booking_folder/appio/__init__.py:215 +#: ../behaviors/booking_folder/email/__init__.py:215 +#: ../behaviors/booking_folder/sms/__init__.py:114 msgid "notify_on_refuse_message" msgstr "" #. Default: "The booking ${booking_type} of ${booking_date} at ${booking_time} was refused." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:205 -#: redturtle/prenotazioni/upgrades.py:286 +#: ../behaviors/booking_folder/email/__init__.py:91 msgid "notify_on_refuse_message_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:592 +#. Default: "The message text when a booking has been refused." +#: ../behaviors/booking_folder/appio/__init__.py:219 +#: ../behaviors/booking_folder/email/__init__.py:219 +#: ../behaviors/booking_folder/sms/__init__.py:118 msgid "notify_on_refuse_message_help" msgstr "" -#. Default: "Prenotazione refused notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:579 +#. Default: "[${prenotazioni_folder_title}]: The booking ${booking_type} of ${booking_date} at ${booking_time} was refused." +#: ../behaviors/booking_folder/sms/__init__.py:48 +msgid "notify_on_refuse_sms_message_default_value" +msgstr "" + +#. Default: "[Refuse] subject" +#: ../behaviors/booking_folder/appio/__init__.py:203 +#: ../behaviors/booking_folder/email/__init__.py:203 msgid "notify_on_refuse_subject" msgstr "" -#. Default: "Booking refused for ${title}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:195 -#: redturtle/prenotazioni/upgrades.py:279 +#. Default: "[${prenotazioni_folder_title}] Booking refused for ${title}" +#: ../behaviors/booking_folder/email/__init__.py:81 msgid "notify_on_refuse_subject_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:583 +#. Default: "The message subject when a booking has been refused." +#: ../behaviors/booking_folder/appio/__init__.py:207 +#: ../behaviors/booking_folder/email/__init__.py:207 msgid "notify_on_refuse_subject_help" msgstr "" #. Default: "Notify when created." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:489 +#: ../content/prenotazioni_folder.py:409 msgid "notify_on_submit" msgstr "" +#. Default: "Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.

You can see details and print a reminder following this [${booking_print_url}](link)." +#: ../behaviors/booking_folder/appio/__init__.py:28 +msgid "notify_on_submit_appio_message_default_value" +msgstr "" + +#. Default: "[${prenotazioni_folder_title}] Booking created" +#: ../behaviors/booking_folder/appio/__init__.py:18 +msgid "notify_on_submit_appio_subject_default_value" +msgstr "" + #. Default: "Notify via mail the user when his booking has been created. If auto-confirm flag is selected and confirm notify is selected, this one will be ignored." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:490 +#: ../content/prenotazioni_folder.py:410 msgid "notify_on_submit_help" msgstr "" -#. Default: "Prenotazione created notification message." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:534 +#. Default: "[Created] message" +#: ../behaviors/booking_folder/appio/__init__.py:143 +#: ../behaviors/booking_folder/email/__init__.py:143 +#: ../behaviors/booking_folder/sms/__init__.py:78 msgid "notify_on_submit_message" msgstr "" -#. Default: "Booking ${booking_type} for ${booking_date} at ${booking_time} was created.Link" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:144 -#: redturtle/prenotazioni/upgrades.py:243 +#. Default: "Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.

You can see details and print a reminder following this link." +#: ../behaviors/booking_folder/email/__init__.py:28 msgid "notify_on_submit_message_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:538 +#. Default: "The message text when a booking has been created." +#: ../behaviors/booking_folder/appio/__init__.py:147 +#: ../behaviors/booking_folder/email/__init__.py:147 +#: ../behaviors/booking_folder/sms/__init__.py:82 msgid "notify_on_submit_message_help" msgstr "" -#. Default: "Prenotazione created notification subject." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:525 +#. Default: "[${prenotazioni_folder_title}]: Booking ${booking_type} for ${booking_date} at ${booking_time} has been created.\nSee details or delete it: ${booking_print_url}." +#: ../behaviors/booking_folder/sms/__init__.py:18 +msgid "notify_on_submit_sms_message_default_value" +msgstr "" + +#. Default: "[Created] subject" +#: ../behaviors/booking_folder/appio/__init__.py:131 +#: ../behaviors/booking_folder/email/__init__.py:131 msgid "notify_on_submit_subject" msgstr "" -#. Default: "Booking created ${title}" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:137 -#: redturtle/prenotazioni/upgrades.py:239 +#. Default: "[${prenotazioni_folder_title}] Booking created" +#: ../behaviors/booking_folder/email/__init__.py:18 msgid "notify_on_submit_subject_default_value" msgstr "" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:529 +#. Default: "The message subject when a booking has been created." +#: ../behaviors/booking_folder/appio/__init__.py:135 +#: ../behaviors/booking_folder/email/__init__.py:135 msgid "notify_on_submit_subject_help" msgstr "" #. Default: "Pause end" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:128 +#: ../content/prenotazioni_folder.py:125 msgid "pause_end_label" msgstr "" #. Default: "Pause start" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:123 +#: ../content/prenotazioni_folder.py:120 msgid "pause_start_label" msgstr "" #. Default: "Please select a time slot" -#: redturtle/prenotazioni/browser/prenotazione_add.py:280 +#: ../browser/prenotazione_add.py:280 msgid "please_pick_a_date" msgstr "" #. Default: "${day}, ore ${booking_time}" -#: redturtle/prenotazioni/browser/week.py:256 +#: ../browser/week.py:256 msgid "prenotation_slot_message" msgstr "" -#. Default: "Testo delle email di notifica" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:652 -msgid "prenotazioni_email_templates_label" -msgstr "" - #. Default: "prenotazioni_search" -#: redturtle/prenotazioni/profiles/default/actions.xml +#: ../profiles/default/actions.xml msgid "prenotazioni_search" msgstr "" #. Default: "previous week" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:14 +#: ../browser/templates/prenotazione_macros.pt:14 msgid "previous-week" msgstr "" -#: redturtle/prenotazioni/configure.zcml:32 +#: ../configure.zcml:31 msgid "redturtle.prenotazioni" msgstr "" -#: redturtle/prenotazioni/configure.zcml:49 +#: ../configure.zcml:48 msgid "redturtle.prenotazioni (to_1500)" msgstr "" -#: redturtle/prenotazioni/configure.zcml:41 +#: ../configure.zcml:40 +#: ../staging/configure.zcml:25 msgid "redturtle.prenotazioni (uninstall)" msgstr "" -#: redturtle/prenotazioni/configure.zcml:49 +#: ../configure.zcml:48 msgid "redturtle.prenotazioni to 1500." msgstr "" +#: ../staging/configure.zcml:16 +msgid "redturtle.prenotazioni.staging" +msgstr "" + #. Default: "The booking state is \"refused\". If you change it, the booking time may conflict with another one." -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:30 +#: ../browser/templates/prenotazione.pt:30 msgid "refused-review-state-warning" msgstr "" #. Default: "Reject booking" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:176 +#: ../browser/templates/prenotazione.pt:176 msgid "reject_booking" msgstr "" -#. Default: "Reminders" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:700 -msgid "reminders_label" +#. Default: "Set how many days before of a booking date the user will be notified about it." +#: ../content/prenotazioni_folder.py:461 +msgid "reminder_notification_gap_description" +msgstr "" + +#. Default: "Booking reminder days" +#: ../content/prenotazioni_folder.py:457 +msgid "reminder_notification_gap_label" msgstr "" #. Default: "Code" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:58 +#: ../browser/templates/prenotazioni_search.pt:58 msgid "reservation_code" msgstr "" #. Default: "Reservation date" -#: redturtle/prenotazioni/browser/templates/prenotazione_move.pt:33 -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:57 +#: ../browser/templates/prenotazione_move.pt:33 +#: ../browser/templates/prenotazioni_search.pt:57 msgid "reservation_date" msgstr "" #. Default: "Booking request for: ${name}" -#: redturtle/prenotazioni/browser/prenotazione_print.py:44 +#: ../browser/prenotazione_print.py:44 msgid "reservation_request" msgstr "" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:30 +#: ../browser/templates/prenotazione_macros.pt:30 msgid "resize" msgstr "" #. Default: "items matching your search terms." -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:30 +#: ../browser/templates/prenotazioni_search.pt:30 msgid "result_number" msgstr "" #. Default: "You need to provide a booking date to get the schema and available types." -#: redturtle/prenotazioni/restapi/services/booking_schema/get.py:71 +#: ../restapi/services/booking_schema/get.py:71 msgid "schema_missing_date" msgstr "" #. Default: "Search by gate" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:465 +#: ../browser/templates/prenotazione_macros.pt:465 msgid "search-by-gate" msgstr "" #. Default: "Search result" -#: redturtle/prenotazioni/browser/templates/prenotazioni_search.pt:12 +#: ../browser/templates/prenotazioni_search.pt:12 msgid "search_result_message" msgstr "" #. Default: "seleziona l'opzione desiderata dal gruppo di radio button seguente" -#: redturtle/prenotazioni/browser/z3c_custom_widget.py:153 +#: ../browser/z3c_custom_widget.py:153 msgid "select-option" msgstr "" -#. Default: "This gate has some booking schedule in this time period." -#: redturtle/prenotazioni/browser/vacations.py:217 -msgid "slot_conflict_error" +#. Default: "AppIO service code related to the current booking type" +#: ../behaviors/booking_folder/appio/__init__.py:293 +msgid "service_code_help" msgstr "" -#. Default: "The email address that sends the email. If no email is provided here, it will use the address from portal." -#: redturtle/prenotazioni/contentrules/sendMovedPrenotazione.py:33 -msgid "source_help" +#. Default: "AppIO service code." +#: ../behaviors/booking_folder/appio/__init__.py:289 +msgid "service_code_label" msgstr "" -#. Default: "You cannot book any booking_type at this time" -#: redturtle/prenotazioni/browser/prenotazione_add.py:284 -msgid "time_slot_to_short" +#. Default: "This gate has some booking schedule in this time period." +#: ../browser/vacations.py:217 +msgid "slot_conflict_error" msgstr "" -msgid "to_label" +#. Default: "You cannot book any booking_type at this time" +#: ../browser/prenotazione_add.py:284 +msgid "time_slot_to_short" msgstr "" #. Default: "You should set an end range." -#: redturtle/prenotazioni/content/validators.py:175 +#: ../content/validators.py:175 msgid "to_month_error" msgstr "" #. Default: "Selected day is too big for that month for \"to\" field." -#: redturtle/prenotazioni/content/validators.py:182 +#: ../content/validators.py:182 msgid "to_month_too_days_error" msgstr "" #. Default: "You can't add a booking with type '${booking_type}'." -#: redturtle/prenotazioni/restapi/services/booking/add.py:84 +#: ../restapi/services/booking/add.py:89 msgid "unauthorized_add_vacation" msgstr "" #. Default: "Unbookable time" -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:452 +#: ../browser/templates/prenotazione_macros.pt:452 msgid "unbookable_time" msgstr "" #. Default: "vacation_booking" -#: redturtle/prenotazioni/profiles/default/actions.xml +#: ../profiles/default/actions.xml msgid "vacation_booking" msgstr "" #. Default: "View booking" -#: redturtle/prenotazioni/browser/templates/prenotazione.pt:143 -#: redturtle/prenotazioni/browser/templates/prenotazione_macros.pt:463 +#: ../browser/templates/prenotazione.pt:143 +#: ../browser/templates/prenotazione_macros.pt:463 msgid "view_booking" msgstr "" #. Default: "Insert here week schema for some custom date intervals." -#: redturtle/prenotazioni/content/prenotazioni_folder.py:362 +#: ../content/prenotazioni_folder.py:281 msgid "week_table_overrides_help" msgstr "" #. Default: "Week table overrides" -#: redturtle/prenotazioni/content/prenotazioni_folder.py:361 +#: ../content/prenotazioni_folder.py:280 msgid "week_table_overrides_label" msgstr "" #. Default: "You tried to delete booking with a wrong action." -#: redturtle/prenotazioni/browser/delete_reservation.py:97 +#: ../browser/delete_reservation.py:97 msgid "wrong_authenticator" msgstr "" diff --git a/src/redturtle/prenotazioni/locales/update.sh b/src/redturtle/prenotazioni/locales/update.sh index 2b6b81d2..557fe3d3 100755 --- a/src/redturtle/prenotazioni/locales/update.sh +++ b/src/redturtle/prenotazioni/locales/update.sh @@ -8,5 +8,5 @@ domain=redturtle.prenotazioni -i18ndude rebuild-pot --pot $domain.pot --create $domain ../ -i18ndude sync --pot $domain.pot */LC_MESSAGES/$domain.po +pipx run i18ndude rebuild-pot --pot $domain.pot --create $domain ../ +pipx run i18ndude sync --pot $domain.pot */LC_MESSAGES/$domain.po diff --git a/src/redturtle/prenotazioni/profiles/default/metadata.xml b/src/redturtle/prenotazioni/profiles/default/metadata.xml index 35a3b743..38cd0d30 100644 --- a/src/redturtle/prenotazioni/profiles/default/metadata.xml +++ b/src/redturtle/prenotazioni/profiles/default/metadata.xml @@ -1,6 +1,6 @@ - 2002 + 2003 profile-plone.app.dexterity:default profile-collective.z3cform.datagridfield:default diff --git a/src/redturtle/prenotazioni/profiles/default/types/PrenotazioniFolder.xml b/src/redturtle/prenotazioni/profiles/default/types/PrenotazioniFolder.xml index 19bc838e..0ee16981 100644 --- a/src/redturtle/prenotazioni/profiles/default/types/PrenotazioniFolder.xml +++ b/src/redturtle/prenotazioni/profiles/default/types/PrenotazioniFolder.xml @@ -46,6 +46,7 @@ + diff --git a/src/redturtle/prenotazioni/restapi/services/booking/notify_about_confirm.py b/src/redturtle/prenotazioni/restapi/services/booking/notify_about_confirm.py index 65ece567..b3938084 100644 --- a/src/redturtle/prenotazioni/restapi/services/booking/notify_about_confirm.py +++ b/src/redturtle/prenotazioni/restapi/services/booking/notify_about_confirm.py @@ -3,11 +3,10 @@ from plone.restapi.services import Service from Products.DCWorkflow.events import AfterTransitionEvent from zExceptions import BadRequest +from zope.event import notify from zope.interface import implementer from zope.publisher.interfaces import IPublishTraverse -from redturtle.prenotazioni.events.prenotazione import notify_on_after_transition_event - @implementer(IPublishTraverse) class NotifyUserAboutBookingConfirm(Service): @@ -28,10 +27,8 @@ def reply(self): "TranstionBillet", (object,), {"__name__": "confirm"} )() - # Simulate the confirm transition - notify_on_after_transition_event( - context=booking, - event=AfterTransitionEvent( + notify( + AfterTransitionEvent( workflow=None, obj=booking, old_state=None, @@ -39,7 +36,7 @@ def reply(self): status=None, kwargs=None, transition=transition_billet, - ), + ) ) return "" diff --git a/src/redturtle/prenotazioni/scripts/app_io.py b/src/redturtle/prenotazioni/scripts/app_io.py deleted file mode 100644 index feb6cacb..00000000 --- a/src/redturtle/prenotazioni/scripts/app_io.py +++ /dev/null @@ -1,223 +0,0 @@ -# -*- encoding: utf-8 -*- -import locale -import logging -import sys -from datetime import datetime -from datetime import timedelta - -import click -import transaction -from plone import api -from zope.annotation.interfaces import IAnnotations - -from redturtle.prenotazioni.config import NOTIFICATIONS_LOGS -from redturtle.prenotazioni.config import VERIFIED_BOOKING - -from .io_tools.api import Api -from .io_tools.storage import logstorage - -logger = logging.getLogger("redturtle.prenotazioni.app_io") -locale.setlocale(locale.LC_ALL, "it_IT.UTF-8") - - -def days_before(obj, days=1, as_date=True): - if as_date: - if ( - timedelta() - < obj.booking_date.date() - datetime.now().date() - <= timedelta(days=days) - ): - return True - else: - if timedelta() < obj.booking_date - datetime.now() <= timedelta(days=days): - return True - return False - - -MSGS = { - "1day": """ -Il Comune le ricorda il suo appuntamento di domani {day} -alle ore {time} presso {how_to_get_here}{sportello}. -{booking_code}""" -} - - -def notifica_app_io(obj, api_io, msg_type, commit=False, verbose=False): - annotations = IAnnotations(obj) - fiscal_code = obj.fiscalcode - if not annotations.get(VERIFIED_BOOKING): - logger.info( - "Prenotazione %s non verificata per invio notifiche App IO", - obj.absolute_url(), - ) - return False - if fiscal_code: - # TODO: spostare i template di messaggi in una configurazione esterna - # allo script - # TODO: esistono definite delle stringiterp plone, valutare se usare quelle - subject = "Promemoria appuntamento" - folder = obj.getPrenotazioniFolder() - how_to_get_here = getattr(folder, "how_to_get_here", None) or "" - # how_to_get_here = getattr(folder, "how_to_get_here", "") - # BODY: markdown, 'maxLength': 10000, 'minLength': 80 - body = (MSGS[msg_type]).format( - day=obj.booking_date.strftime("%d %B %Y"), - time=obj.booking_date.strftime("%H:%M"), - how_to_get_here=how_to_get_here, - # sportello=u" sportello %s" % obj.gate if obj.gate else "", - sportello=" - %s" % obj.gate if obj.gate else "", - booking_code="\n\nIl codice della prenotazione è %s" % obj.getBookingCode() - if obj.getBookingCode() - else "", - ) - key = "%s_%s" % (obj.UID(), msg_type) - msg = api_io.storage.get_message(key=key) - if msg and msg.msgid: - logger.info("Notifica precedentemente inviata %s", msg) - return api_io.update_message_status(key=key) - elif commit: - msgid = api_io.send_message( - fiscal_code=fiscal_code, - subject=subject, - body=body, - key=key, - ) - logger.info("Notifica %s per %s - %s", msgid, fiscal_code, subject) - return bool(msgid) - else: - logger.warning( - " TO:%s SUBJECT:%s BODY:%s, KEY:%s", - fiscal_code, - subject, - body, - key, - ) - return True - else: - logger.info( - "prenotazione %s fiscal_code=%s non presente", - obj.absolute_url(), - fiscal_code, - ) - return False - - -class ObjectView(object): - def __init__(self, d): - self.__dict__ = d - - def __repr__(self): - return self.__dict__.__repr__() - - -class Storage(object): - def __init__(self, context): - self.context = IAnnotations(context) - - def get_message(self, key): - d = self.context.get("%s.%s" % (NOTIFICATIONS_LOGS, key)) - return ObjectView(d) if d else None - - def create_message(self, key, fiscal_code, subject, body, payment_data, due_date): - msg = { - "key": key, - "fiscal_code": fiscal_code, - "subject": subject, - "body": body, - # "payment_data": payment_data, - # "due_data": due_data, - } - self.context["%s.%s" % (NOTIFICATIONS_LOGS, key)] = msg - return ObjectView(msg) - - def update_message(self, key, **kwargs): - msg = self.context.get("%s.%s" % (NOTIFICATIONS_LOGS, key)) or {} - # update o sostituzione completa ? - msg.update(kwargs) - self.context["%s.%s" % (NOTIFICATIONS_LOGS, key)] = msg - - def cleanup(self): - ids = [k for k in self.context if k.startswith(NOTIFICATIONS_LOGS)] - for id in ids: - del self.context[id] - - -@click.command() -@click.option("--commit/--dry-run", is_flag=True, default=False) -@click.option("--verbose", is_flag=True, help="Will print verbose messages.") -@click.option("--io-secret") -@click.option("--test-message", is_flag=True, default=False) -@click.option("--test-message-cf") -def _main(commit, verbose, io_secret, test_message, test_message_cf): - if verbose: - logging.getLogger().setLevel(logging.INFO) - - if commit and not io_secret: - print("Missing --io-secret") # NOQA - return -1 - - api_io = Api(secret=io_secret) - - if test_message and test_message_cf: - if not io_secret: - print("Missing --io-secret") # NOQA - return -1 - api_io.storage = logstorage - msgid = api_io.send_message( - fiscal_code=test_message_cf, - subject="Messaggio di prova", - body="0123456789 " * 9, - ) - return bool(msgid) - - catalog = api.portal.get_tool("portal_catalog") - - # TODO: spostare la configurazione in un file fuori dallo script - actions = ( - ( - days_before, - {"days": 1, "as_date": True}, - notifica_app_io, - { - "api_io": api_io, - "msg_type": "1day", - "commit": commit, - "verbose": verbose, - }, - ), - ) - - # XXX: valutare un filtro più preciso sulle ricerche e degli indici/metadati sul catalogo - for brain in catalog.unrestrictedSearchResults( - portal_type="Prenotazione", review_state="confirmed" - ): - obj = brain.getObject() - if not obj.app_io_enabled: - logger.info("App IO reminder disabled for %s", brain.getPath()) - continue - api_io.storage = Storage(obj) - # api_io.storage.cleanup() - for action in actions: - if action[0](obj, **action[1]): - if action[2](obj, **action[3]): - if commit: - logger.info("COMMIT") - transaction.commit() - - # if commit: - # transaction.commit() - # logger.warning('Changes Saved') - # else: - # transaction.abort() - # logger.warning('Dry Run mode - nothing changed') - - -def main(): - if "-c" in sys.argv: - _main(sys.argv[3:]) - else: - _main() - - -if __name__ == "__main__": - main() diff --git a/src/redturtle/prenotazioni/scripts/notify_upcoming_bookings.py b/src/redturtle/prenotazioni/scripts/notify_upcoming_bookings.py new file mode 100644 index 00000000..fe2b3f96 --- /dev/null +++ b/src/redturtle/prenotazioni/scripts/notify_upcoming_bookings.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +"""Send reminders script""" + +from AccessControl.SecurityManagement import newSecurityManager +from plone import api +from Testing.makerequest import makerequest +from transaction import commit +from zope.component.hooks import setHooks +from zope.component.hooks import setSite +from zope.globalrequest import getRequest + +from redturtle.prenotazioni import logger + + +def main(app): + app = makerequest(app) + portal = app.Plone + admin = app.acl_users.getUserById("admin") + + newSecurityManager(None, admin) + setHooks() + setSite(portal) + + with api.env.adopt_roles(roles=["Manager"]): + logger.info("Call the send reminders view") + api.content.get_view( + context=api.portal.get(), + request=getRequest(), + name="send-booking-reminders", + )() + + commit() + + +if __name__ == "__main__": + main(app) # noqa diff --git a/src/redturtle/prenotazioni/staging/__init__.py b/src/redturtle/prenotazioni/staging/__init__.py new file mode 100644 index 00000000..437a9bdc --- /dev/null +++ b/src/redturtle/prenotazioni/staging/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +import logging + +logger = logging.getLogger(__name__) diff --git a/src/redturtle/prenotazioni/staging/configure.zcml b/src/redturtle/prenotazioni/staging/configure.zcml new file mode 100644 index 00000000..bc133c39 --- /dev/null +++ b/src/redturtle/prenotazioni/staging/configure.zcml @@ -0,0 +1,32 @@ + + + + + + + + + diff --git a/src/redturtle/prenotazioni/staging/interfaces.py b/src/redturtle/prenotazioni/staging/interfaces.py new file mode 100644 index 00000000..46af4e2d --- /dev/null +++ b/src/redturtle/prenotazioni/staging/interfaces.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from redturtle.prenotazioni.interfaces import IRedturtlePrenotazioniLayer + + +class IRedturtlePrenotazioniStagingLayer(IRedturtlePrenotazioniLayer): + """Marker interface that defines a browser layer""" diff --git a/src/redturtle/prenotazioni/staging/profiles/default/browserlayer.xml b/src/redturtle/prenotazioni/staging/profiles/default/browserlayer.xml new file mode 100644 index 00000000..a3c8d570 --- /dev/null +++ b/src/redturtle/prenotazioni/staging/profiles/default/browserlayer.xml @@ -0,0 +1,6 @@ + + + + diff --git a/src/redturtle/prenotazioni/staging/profiles/default/metadata.xml b/src/redturtle/prenotazioni/staging/profiles/default/metadata.xml new file mode 100644 index 00000000..f768b5a7 --- /dev/null +++ b/src/redturtle/prenotazioni/staging/profiles/default/metadata.xml @@ -0,0 +1,4 @@ + + + 1000 + diff --git a/src/redturtle/prenotazioni/staging/profiles/uninstall/browserlayer.xml b/src/redturtle/prenotazioni/staging/profiles/uninstall/browserlayer.xml new file mode 100644 index 00000000..d3a358be --- /dev/null +++ b/src/redturtle/prenotazioni/staging/profiles/uninstall/browserlayer.xml @@ -0,0 +1,6 @@ + + + + diff --git a/src/redturtle/prenotazioni/staging/setuphandlers.py b/src/redturtle/prenotazioni/staging/setuphandlers.py new file mode 100644 index 00000000..864cee78 --- /dev/null +++ b/src/redturtle/prenotazioni/staging/setuphandlers.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from Products.CMFPlone.interfaces import INonInstallable +from zope.interface import implementer + + +@implementer(INonInstallable) +class HiddenProfiles(object): + def getNonInstallableProfiles(self): + """Hide uninstall profile from site-creation and quickinstaller.""" + return [ + "redturtle.prenotazioni.stagong:uninstall", + ] + + +def post_install(context): + """Post install script""" + # Do something at the end of the installation of this package. + + +def uninstall(context): + """Uninstall script""" + # Do something at the end of the uninstallation of this package. diff --git a/src/redturtle/prenotazioni/staging/smsdemo.py b/src/redturtle/prenotazioni/staging/smsdemo.py new file mode 100644 index 00000000..86793d0d --- /dev/null +++ b/src/redturtle/prenotazioni/staging/smsdemo.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +from plone import api +from zope.component import adapter +from zope.interface import implementer + +from redturtle.prenotazioni.behaviors.booking_folder.sms.adapters import ( + BookingNotificationSender, +) +from redturtle.prenotazioni.content.prenotazione import IPrenotazione +from redturtle.prenotazioni.interfaces import IBookingNotificationSender +from redturtle.prenotazioni.interfaces import IBookingSMSMessage +from redturtle.prenotazioni.staging import logger +from redturtle.prenotazioni.staging.interfaces import IRedturtlePrenotazioniStagingLayer + + +@implementer(IBookingNotificationSender) +@adapter(IBookingSMSMessage, IPrenotazione, IRedturtlePrenotazioniStagingLayer) +class DemoSMSSenderAdapter(BookingNotificationSender): + def send(self): + logger.info( + "Sending (%s) the notification <%s>(`%s`) via SMS gateway to %s", + self.is_notification_allowed(), + self.booking.UID(), + self.message_adapter.message, + self.booking.phone, + ) + if self.is_notification_allowed(): + message = self.message_adapter.message + phone = self.booking.phone + api.portal.send_email( + recipient=f"{phone}@redturtle.it", + subject=f"SMS to {phone}", + body=message, + ) diff --git a/src/redturtle/prenotazioni/tests/test_available_slots.py b/src/redturtle/prenotazioni/tests/test_available_slots.py index b523408f..aa80fa01 100644 --- a/src/redturtle/prenotazioni/tests/test_available_slots.py +++ b/src/redturtle/prenotazioni/tests/test_available_slots.py @@ -100,7 +100,7 @@ def setUp(self): def tearDown(self): self.api_session.close() - @unittest.skip("issue testing in the last days of a month") + @freeze_time(date(date.today().year, date.today().month, 2)) def test_month_slots_called_without_params_return_all_available_slots_of_current_month( self, ): @@ -116,10 +116,17 @@ def test_month_slots_called_without_params_return_all_available_slots_of_current for week in calendar.monthcalendar(current_year, current_month): # week[0] is monday and should be greater than today if week[0] > current_day: - for hour in [7, 8, 9]: + for hour in [6, 7, 8]: expected.append( json_compatible( - datetime(current_year, current_month, week[0], hour, 0) + datetime( + current_year, + current_month, + week[0], + hour, + 0, + tzinfo=pytz.UTC, + ) ) ) self.assertEqual(expected, response.json()["items"]) diff --git a/src/redturtle/prenotazioni/tests/test_booking_notify_on_confirm_by_endoint.py b/src/redturtle/prenotazioni/tests/test_booking_notify.py similarity index 50% rename from src/redturtle/prenotazioni/tests/test_booking_notify_on_confirm_by_endoint.py rename to src/redturtle/prenotazioni/tests/test_booking_notify.py index 26ac296b..3e18f344 100644 --- a/src/redturtle/prenotazioni/tests/test_booking_notify_on_confirm_by_endoint.py +++ b/src/redturtle/prenotazioni/tests/test_booking_notify.py @@ -9,11 +9,19 @@ from plone import api from plone.app.testing import TEST_USER_ID from plone.app.testing import setRoles +from zope.component import getGlobalSiteManager from zope.globalrequest import getRequest from zope.interface import implementer from zope.interface.interfaces import IObjectEvent from redturtle.prenotazioni.adapters.booker import IBooker +from redturtle.prenotazioni.behaviors.booking_folder.sms.adapters import ( + BookingNotificationSender, +) +from redturtle.prenotazioni.content.prenotazione import IPrenotazione +from redturtle.prenotazioni.interfaces import IBookingNotificationSender +from redturtle.prenotazioni.interfaces import IBookingSMSMessage +from redturtle.prenotazioni.interfaces import IRedturtlePrenotazioniLayer from redturtle.prenotazioni.testing import ( REDTURTLE_PRENOTAZIONI_API_INTEGRATION_TESTING, ) @@ -25,7 +33,7 @@ def __init__(self, object): self.object = object -class TestSPrenotazioneEvents(unittest.TestCase): +class TestBookingNotify(unittest.TestCase): layer = REDTURTLE_PRENOTAZIONI_API_INTEGRATION_TESTING maxDiff = None timezone = "Europe/Rome" @@ -42,6 +50,13 @@ def setUp(self): setRoles(self.portal, TEST_USER_ID, ["Manager"]) + # Add SMS and AppIO behaviors to the PrenotazioniFolder + portal_types = api.portal.get_tool("portal_types") + content_type = portal_types["PrenotazioniFolder"] + behaviors = list(content_type.behaviors) + behaviors.append("redturtle.prenotazioni.behavior.notification_sms") + content_type.behaviors = tuple(behaviors) + self.folder_prenotazioni = api.content.create( container=self.portal, type="PrenotazioniFolder", @@ -74,18 +89,26 @@ def setUp(self): self.timezone, ) - self.booking = self.create_booking() - self.view = api.content.get_view( - context=self.booking.getPrenotazioniFolder(), - request=getRequest(), - name="GET_application_json_@booking-notify", + self.sms = sms = [] + + class CustomSMSSenderAdapter(BookingNotificationSender): + def send(self): + if self.is_notification_allowed(): + # the message is automatically generated basing on the event type + message = self.message_adapter.message + phone = self.booking.phone + sms.append((phone, message)) + + gsm = getGlobalSiteManager() + gsm.registerAdapter( + CustomSMSSenderAdapter, + (IBookingSMSMessage, IPrenotazione, IRedturtlePrenotazioniLayer), + IBookingNotificationSender, + "booking_transition_sms_sender", ) - self.view.booking_uid = self.booking.UID() def create_booking(self, booking_date=None): booker = IBooker(self.folder_prenotazioni) - if booking_date is None: - booking_date = self.tomorrow_8_0 return booker.book( { "booking_date": booking_date, @@ -95,7 +118,55 @@ def create_booking(self, booking_date=None): } ) - def test_email_send_on_enpoint_call(self): + def test_sms_notification_on_create(self): + self.folder_prenotazioni.notifications_sms_enabled = True + self.folder_prenotazioni.notify_on_submit = True + + booker = IBooker(self.folder_prenotazioni) + booking = booker.book( + { + "booking_date": self.tomorrow_8_0, + "booking_type": "Type A", + "title": "foo", + "phone": "123456789", + } + ) + self.assertEqual(len(self.sms), 1) + self.assertEqual(self.sms[0][0], "123456789") + self.assertIn("[Prenota foo]: Booking Type A for ", self.sms[0][1]) + # default confirmation is not setted, so the sms is for creation + self.assertIn(" at 08:00 has been created.", self.sms[0][1]) + + # reject booking does not send sms + api.content.transition(obj=booking, transition="refuse") + self.assertEqual(len(self.sms), 1) + + self.folder_prenotazioni.notify_on_confirm = True + api.content.transition(obj=booking, transition="restore") + api.content.transition(obj=booking, transition="confirm") + self.assertEqual(len(self.sms), 2) + self.assertEqual(self.sms[-1][0], "123456789") + self.assertIn("[Prenota foo]: Booking of ", self.sms[-1][1]) + self.assertIn(" at 08:00 has been accepted.", self.sms[-1][1]) + + # now notify also refuse + self.folder_prenotazioni.notify_on_refuse = True + api.content.transition(obj=booking, transition="refuse") + self.assertEqual(len(self.sms), 3) + self.assertEqual(self.sms[-1][0], "123456789") + self.assertIn("[Prenota foo]: The booking Type A of ", self.sms[-1][1]) + self.assertIn(" at 08:00 was refused.", self.sms[-1][1]) + + def test_email_send_on_endpoint_call(self): + self.booking = self.create_booking(booking_date=self.tomorrow_8_0) + + self.view = api.content.get_view( + context=self.booking.getPrenotazioniFolder(), + request=getRequest(), + name="GET_application_json_@booking-notify", + ) + self.view.booking_uid = self.booking.UID() + self.folder_prenotazioni.notify_on_confirm = True self.folder_prenotazioni.notify_on_confirm_subject = self.email_subject self.folder_prenotazioni.notify_on_confirm_message = self.email_message diff --git a/src/redturtle/prenotazioni/tests/test_browser_utilities_notify_upcoming_bookings.py b/src/redturtle/prenotazioni/tests/test_browser_utilities_notify_upcoming_bookings.py new file mode 100644 index 00000000..ba28e5e9 --- /dev/null +++ b/src/redturtle/prenotazioni/tests/test_browser_utilities_notify_upcoming_bookings.py @@ -0,0 +1,193 @@ +# -*- coding: UTF-8 -*- +import unittest +from datetime import date +from datetime import datetime +from datetime import timedelta + +import pytz +from freezegun import freeze_time +from plone import api +from plone.app.testing import TEST_USER_ID +from plone.app.testing import setRoles +from zope.component import adapter +from zope.component import provideHandler +from zope.globalrequest import getRequest + +from redturtle.prenotazioni.adapters.booker import IBooker +from redturtle.prenotazioni.interfaces import IBookingReminderEvent +from redturtle.prenotazioni.testing import REDTURTLE_PRENOTAZIONI_FUNCTIONAL_TESTING + +from .helpers import WEEK_TABLE_SCHEMA + +TESTING_TIME = datetime(year=2023, month=11, day=23, hour=10, minute=0) +NOTIFICAION_GAP = 3 + + +class TestNotifyAboutUpcommingBookings(unittest.TestCase): + layer = REDTURTLE_PRENOTAZIONI_FUNCTIONAL_TESTING + timezone = "Europe/Rome" + + def dt_local_to_utc(self, value): + return pytz.timezone(self.timezone).localize(value).astimezone(pytz.utc) + + @freeze_time(TESTING_TIME) + def setUp(self): + self.app = self.layer["app"] + self.portal = self.layer["portal"] + self.mailhost = self.portal.MailHost + + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + + self.folder_prenotazioni = api.content.create( + container=self.portal, + type="PrenotazioniFolder", + title="Prenota foo", + description="", + daData=date.today(), + gates=["Gate A"], + reminder_notification_gap=NOTIFICAION_GAP, + week_table=WEEK_TABLE_SCHEMA, + ) + + api.content.create( + type="PrenotazioneType", + title="Type A", + duration=30, + container=self.folder_prenotazioni, + gates=["all"], + ) + api.content.create( + type="PrenotazioneType", + title="Type B", + duration=90, + container=self.folder_prenotazioni, + gates=["all"], + ) + + self.today_8_0 = self.dt_local_to_utc( + datetime.now().replace(hour=8, minute=0, second=0, microsecond=0) + ) + self.tomorrow_8_0 = self.today_8_0 + timedelta(1) + self.folder_prenotazioni.email_responsabile = ["admin@test.com"] + api.portal.set_registry_record( + "plone.portal_timezone", + self.timezone, + ) + + def create_booking(self, data: dict): + booker = IBooker(self.folder_prenotazioni) + return booker.book(data) + + @freeze_time(TESTING_TIME - timedelta(days=NOTIFICAION_GAP)) + def test_notification_event_is_raised_when_in_gap(self): + events = [] + + # XXX: booking created by a manager is automatically confirmed + self.create_booking( + data={ + "booking_date": TESTING_TIME, + "booking_type": "Type A", + "title": "foo", + "email": "jdoe@redturtle.it", + } + ) + + @adapter(IBookingReminderEvent) + def _handleReminder(_event): + events.append(_event) + + provideHandler(_handleReminder) + + api.content.get_view( + context=api.portal.get(), + request=getRequest(), + name="send-booking-reminders", + )() + + self.assertTrue(IBookingReminderEvent.providedBy(events[0])) + + @freeze_time(TESTING_TIME - timedelta(days=NOTIFICAION_GAP)) + def test_notification_event_is_not_raised_when_not_confirmed(self): + events = [] + + booking = self.create_booking( + data={ + "booking_date": TESTING_TIME, + "booking_type": "Type A", + "title": "foo", + "email": "jdoe@redturtle.it", + } + ) + # XXX: booking created by a manager is automatically confirmed + api.content.transition(obj=booking, transition="refuse") + + @adapter(IBookingReminderEvent) + def _handleReminder(_event): + events.append(_event) + + provideHandler(_handleReminder) + + api.content.get_view( + context=api.portal.get(), + request=getRequest(), + name="send-booking-reminders", + )() + + self.assertFalse(events) + + @freeze_time(TESTING_TIME - timedelta(days=NOTIFICAION_GAP - 1)) + def test_notification_event_is_not_raised_when_out_of_gap(self): + events = [] + + # XXX: booking created by a manager is automatically confirmed + self.create_booking( + data={ + "booking_date": TESTING_TIME, + "booking_type": "Type A", + "title": "foo", + "email": "jdoe@redturtle.it", + } + ) + + @adapter(IBookingReminderEvent) + def _handleReminder(_event): + events.append(_event) + + provideHandler(_handleReminder) + + api.content.get_view( + context=api.portal.get(), + request=getRequest(), + name="send-booking-reminders", + )() + + self.assertEqual(len(events), 0) + + @freeze_time(TESTING_TIME - timedelta(days=NOTIFICAION_GAP)) + def test_notification_event_is_not_raised_when_gap_is_none(self): + self.folder_prenotazioni.reminder_notification_gap = None + events = [] + + # XXX: booking created by a manager is automatically confirmed + self.create_booking( + data={ + "booking_date": TESTING_TIME, + "booking_type": "Type A", + "title": "foo", + "email": "jdoe@redturtle.it", + } + ) + + @adapter(IBookingReminderEvent) + def _handleReminder(_event): + events.append(_event) + + provideHandler(_handleReminder) + + api.content.get_view( + context=api.portal.get(), + request=getRequest(), + name="send-booking-reminders", + )() + + self.assertEqual(len(events), 0) diff --git a/src/redturtle/prenotazioni/tests/test_delete_booking_api.py b/src/redturtle/prenotazioni/tests/test_delete_booking_api.py index 07364035..bfdde078 100644 --- a/src/redturtle/prenotazioni/tests/test_delete_booking_api.py +++ b/src/redturtle/prenotazioni/tests/test_delete_booking_api.py @@ -102,9 +102,6 @@ def get_response(self, session, uid=None): response = session.delete("{}/@booking".format(self.portal_url)) else: response = session.delete("{}/@booking/{}".format(self.portal_url, uid)) - # per le restapi il commit qui non ha senso, senza i test si rompono, - # ma è un caso, va spostato dove serve veramente, questo non è il suo posto - transaction.commit() return response def test_endpoint_raise_404_without_uid(self): @@ -172,6 +169,8 @@ def test_anon_can_delete_anon_booking(self): response = self.get_response(session=self.api_session_anon, uid=uid) + transaction.commit() + self.assertEqual(response.status_code, 204) self.assertEqual( len(self.portal.portal_catalog.unrestrictedSearchResults(UID=uid)), @@ -197,6 +196,8 @@ def test_user_can_delete_his_booking(self): response = self.get_response(session=self.api_session_user, uid=uid) + transaction.commit() + self.assertEqual(response.status_code, 204) self.assertEqual( len(self.portal.portal_catalog.unrestrictedSearchResults(UID=uid)), @@ -214,7 +215,6 @@ def test_user_cant_delete_other_user_booking(self): } ) uid = booking.UID() - transaction.commit() self.assertEqual( len(self.portal.portal_catalog.unrestrictedSearchResults(UID=uid)), @@ -222,6 +222,7 @@ def test_user_cant_delete_other_user_booking(self): ) response = self.get_response(session=self.api_session_user2, uid=uid) + transaction.commit() self.assertEqual(response.status_code, 401) self.assertEqual( diff --git a/src/redturtle/prenotazioni/tests/test_notification_supervisor_utility.py b/src/redturtle/prenotazioni/tests/test_notification_supervisor_utility.py new file mode 100644 index 00000000..c9253bdb --- /dev/null +++ b/src/redturtle/prenotazioni/tests/test_notification_supervisor_utility.py @@ -0,0 +1,160 @@ +# -*- coding: UTF-8 -*- +import unittest +from datetime import date +from datetime import datetime +from datetime import timedelta + +import pytz +from plone import api +from plone.app.testing import TEST_USER_ID +from plone.app.testing import setRoles + +from redturtle.prenotazioni.adapters.booker import IBooker +from redturtle.prenotazioni.behaviors.booking_folder import ( + BookingNotificationSupervisorUtility, +) +from redturtle.prenotazioni.testing import ( + REDTURTLE_PRENOTAZIONI_API_INTEGRATION_TESTING, +) + + +class TestBookingNotificationSupervisorUtility(unittest.TestCase): + layer = REDTURTLE_PRENOTAZIONI_API_INTEGRATION_TESTING + timezone = "Europe/Rome" + + def setUp(self): + self.app = self.layer["app"] + self.portal = self.layer["portal"] + self.mailhost = self.portal.MailHost + self.email_subject = "Testing subject" + self.email_message = "Testing message" + self.supervisor = BookingNotificationSupervisorUtility() + + setRoles(self.portal, TEST_USER_ID, ["Manager"]) + + self.folder_prenotazioni = api.content.create( + container=self.portal, + type="PrenotazioniFolder", + title="Prenota foo", + description="", + daData=date.today(), + gates=["Gate A"], + ) + + api.content.create( + type="PrenotazioneType", + title="Type A", + duration=30, + container=self.folder_prenotazioni, + gates=["all"], + ) + + self.today_8_0 = self.dt_local_to_utc( + datetime.now().replace(hour=8, minute=0, second=0, microsecond=0) + ) + self.tomorrow_8_0 = self.today_8_0 + timedelta(1) + week_table = self.folder_prenotazioni.week_table + for data in week_table: + data["morning_start"] = "0700" + data["morning_end"] = "1000" + self.folder_prenotazioni.week_table = week_table + + api.portal.set_registry_record( + "plone.portal_timezone", + self.timezone, + ) + + self.booking = self.create_booking() + + def dt_local_to_utc(self, value): + return pytz.timezone(self.timezone).localize(value).astimezone(pytz.utc) + + def create_booking(self, booking_date=None): + booker = IBooker(self.folder_prenotazioni) + if booking_date is None: + booking_date = self.tomorrow_8_0 + return booker.book( + { + "booking_date": booking_date, + "booking_type": "Type A", + "title": "foo", + "email": "jdoe@redturtle.it", + "fiscalcode": "FISCALCODE", + "phone": "1111111111", + } + ) + + def test_is_email_message_allowed_positive(self): + self.folder_prenotazioni.notifications_email_enabled = True + + self.assertTrue(self.supervisor.is_email_message_allowed(self.booking)) + + def test_is_email_message_allowed_positive_negative(self): + self.folder_prenotazioni.notifications_email_enabled = False + + self.assertFalse(self.supervisor.is_email_message_allowed(self.booking)) + + # No email provided + + self.folder_prenotazioni.notifications_email_enabled = True + self.booking.email = None + + self.assertFalse(self.supervisor.is_appio_message_allowed(self.booking)) + + def test_is_appio_message_allowed_positive(self): + self.folder_prenotazioni.notifications_appio_enabled = True + self.assertTrue(self.supervisor.is_appio_message_allowed(self.booking)) + + def test_is_appio_message_allowed_negative(self): + # Mock the AppIO subscription check + self.supervisor._check_user_appio_subscription_to_booking_type = ( + lambda booking: True + ) + + self.folder_prenotazioni.notifications_appio_enabled = False + + self.assertFalse(self.supervisor.is_appio_message_allowed(self.booking)) + + # No fiscalcode provided + self.folder_prenotazioni.notifications_appio_enabled = True + self.booking.fiscalcode = None + + self.assertFalse(self.supervisor.is_appio_message_allowed(self.booking)) + + def test_is_sms_message_allowed_positive(self): + self.supervisor.is_email_message_allowed = lambda booking: False + self.supervisor.is_appio_message_allowed = lambda booking: False + self.folder_prenotazioni.notifications_sms_enabled = True + + self.assertTrue(self.supervisor.is_sms_message_allowed(self.booking)) + + def test_is_sms_message_allowed_negative(self): + # Flag is False + self.supervisor.is_email_message_allowed = lambda booking: True + self.supervisor.is_appio_message_allowed = lambda booking: True + self.folder_prenotazioni.notifications_sms_enabled = False + + self.assertFalse(self.supervisor.is_sms_message_allowed(self.booking)) + + # Email notification is allowed + self.supervisor.is_email_message_allowed = lambda booking: True + self.supervisor.is_appio_message_allowed = lambda booking: False + self.folder_prenotazioni.notifications_sms_enabled = True + + self.assertFalse(self.supervisor.is_sms_message_allowed(self.booking)) + + # AppIO notification is allowed + self.supervisor.is_email_message_allowed = lambda booking: False + self.supervisor.is_appio_message_allowed = lambda booking: True + self.supervisor.app_io_allowed_for = lambda *_: True + self.folder_prenotazioni.notifications_sms_enabled = True + self.assertFalse(self.supervisor.is_sms_message_allowed(self.booking)) + + # No phone number was provided + self.supervisor.is_email_message_allowed = lambda booking: True + self.supervisor.is_appio_message_allowed = lambda booking: True + self.folder_prenotazioni.notifications_sms_enabled = True + + self.booking.phone = None + + self.assertFalse(self.supervisor.is_sms_message_allowed(self.booking)) diff --git a/src/redturtle/prenotazioni/tests/test_prenotazione_events.py b/src/redturtle/prenotazioni/tests/test_prenotazione_events.py index 9afce007..e6f63594 100644 --- a/src/redturtle/prenotazioni/tests/test_prenotazione_events.py +++ b/src/redturtle/prenotazioni/tests/test_prenotazione_events.py @@ -10,20 +10,13 @@ from plone.app.testing import TEST_USER_ID from plone.app.testing import setRoles from zope.event import notify -from zope.interface import implementer -from zope.interface.interfaces import IObjectEvent from redturtle.prenotazioni.adapters.booker import IBooker +from redturtle.prenotazioni.events import BookingReminderEvent from redturtle.prenotazioni.prenotazione_event import MovedPrenotazione from redturtle.prenotazioni.testing import REDTURTLE_PRENOTAZIONI_FUNCTIONAL_TESTING -@implementer(IObjectEvent) -class DummyEvent(object): - def __init__(self, object): - self.object = object - - class TestSPrenotazioneEvents(unittest.TestCase): layer = REDTURTLE_PRENOTAZIONI_FUNCTIONAL_TESTING maxDiff = None @@ -399,3 +392,15 @@ def test_email_send_on_refuse_does_not_have_ical(self): message = email.message_from_bytes(mail_sent) self.assertTrue(len(message.get_payload()), 1) + + def test_email_is_sent_on_booking_reminder_event(self): + self.assertFalse(self.mailhost.messages) + + notify(BookingReminderEvent(self.create_booking())) + + self.assertEqual(len(self.mailhost.messages), 1) + + mail_sent = self.mailhost.messages[0] + message = email.message_from_bytes(mail_sent) + + self.assertTrue(len(message.get_payload()), 1) diff --git a/src/redturtle/prenotazioni/upgrades.py b/src/redturtle/prenotazioni/upgrades.py index f4c74a7f..c55d5687 100644 --- a/src/redturtle/prenotazioni/upgrades.py +++ b/src/redturtle/prenotazioni/upgrades.py @@ -2,19 +2,45 @@ import logging import pytz +from dateutil.tz.tz import tzutc from plone import api from plone.app.contentrules.actions.workflow import WorkflowAction from plone.app.contentrules.conditions.portaltype import PortalTypeCondition from plone.app.contentrules.conditions.wfstate import WorkflowStateCondition from plone.app.contentrules.conditions.wftransition import WorkflowTransitionCondition from plone.app.event.base import default_timezone +from plone.app.textfield.value import RichTextValue from plone.app.upgrade.utils import loadMigrationProfile from plone.app.workflow.remap import remap_workflow +from plone.contentrules.engine.interfaces import IRuleAssignmentManager from plone.contentrules.engine.interfaces import IRuleStorage from zope.component import getUtility from zope.component import queryUtility -from redturtle.prenotazioni import _ +from redturtle.prenotazioni.behaviors.booking_folder.email import ( + notify_on_confirm_message_default_factory, +) +from redturtle.prenotazioni.behaviors.booking_folder.email import ( + notify_on_confirm_subject_default_factory, +) +from redturtle.prenotazioni.behaviors.booking_folder.email import ( + notify_on_move_message_default_factory, +) +from redturtle.prenotazioni.behaviors.booking_folder.email import ( + notify_on_move_subject_default_factory, +) +from redturtle.prenotazioni.behaviors.booking_folder.email import ( + notify_on_refuse_message_default_factory, +) +from redturtle.prenotazioni.behaviors.booking_folder.email import ( + notify_on_refuse_subject_default_factory, +) +from redturtle.prenotazioni.behaviors.booking_folder.email import ( + notify_on_submit_message_default_factory, +) +from redturtle.prenotazioni.behaviors.booking_folder.email import ( + notify_on_submit_subject_default_factory, +) from redturtle.prenotazioni.events.prenotazione import set_booking_code logger = logging.getLogger(__name__) @@ -235,78 +261,21 @@ def to_1502(context): def to_1600_popolate_templates(context): - notify_on_submit_subject = context.translate( - _("notify_on_submit_subject_default_value", "Booking created ${title}") - ) - - notify_on_submit_message = context.translate( - _( - "notify_on_submit_message_default_value", - "Booking ${booking_type} for ${booking_date} at ${booking_time} was created.Link", - ) - ) - - notify_on_confirm_subject = context.translate( - _( - "notify_on_confirm_subject_default_value", - "Booking of ${booking_date} at ${booking_time} was accepted", - ) - ) - - notify_on_confirm_message = context.translate( - _( - "notify_on_confirm_message_default_value", - "The booking${booking_type} for ${title} was confirmed! Link", - ) - ) - - notify_on_move_subject = context.translate( - _( - "notify_on_move_subject_default_value", - "Modified the boolking date for ${title}", - ) - ) - - notify_on_move_message = context.translate( - _( - "notify_on_move_message_default_value", - "The booking scheduling of ${booking_type} was modified." - "The new one is on ${booking_date} at ${booking_time}. Link.", - ) - ) - - notify_on_refuse_subject = context.translate( - _( - "notify_on_refuse_subject_default_value", - "Booking refused for ${title}", - ) - ) - - notify_on_refuse_message = context.translate( - _( - "notify_on_refuse_message_default_value", - "The booking ${booking_type} of ${booking_date} at ${booking_time} was refused.", - ) - ) - for brain in api.portal.get_tool("portal_catalog")( portal_type="PrenotazioniFolder" ): obj = brain.getObject() - obj.notify_on_submit_subject = notify_on_submit_subject - obj.notify_on_submit_message = notify_on_submit_message - obj.notify_on_confirm_subject = notify_on_confirm_subject - obj.notify_on_confirm_message = notify_on_confirm_message - obj.notify_on_move_subject = notify_on_move_subject - obj.notify_on_move_message = notify_on_move_message - obj.notify_on_refuse_subject = notify_on_refuse_subject - obj.notify_on_refuse_message = notify_on_refuse_message + obj.notify_on_submit_subject = notify_on_submit_subject_default_factory(obj) + obj.notify_on_submit_message = notify_on_submit_message_default_factory(obj) + obj.notify_on_confirm_subject = notify_on_confirm_subject_default_factory(obj) + obj.notify_on_confirm_message = notify_on_confirm_message_default_factory(obj) + obj.notify_on_move_subject = notify_on_move_subject_default_factory(obj) + obj.notify_on_move_message = notify_on_move_message_default_factory(obj) + obj.notify_on_refuse_subject = notify_on_refuse_subject_default_factory(obj) + obj.notify_on_refuse_message = notify_on_refuse_message_default_factory(obj) def to_1600_upgrade_contentrules(context): - from plone.contentrules.engine.interfaces import IRuleAssignmentManager - from plone.contentrules.engine.interfaces import IRuleStorage - rules_to_delete = [ "booking-accepted", "booking-moved", @@ -359,8 +328,6 @@ def to_1700(context): """ Fix timezones in bookings """ - from dateutil.tz.tz import tzutc - brains = api.content.find(portal_type="Prenotazione") tot = len(brains) i = 0 @@ -412,8 +379,6 @@ def to_1804(context): def to_1805(context): - from plone.app.textfield.value import RichTextValue - for brain in api.portal.get_tool("portal_catalog")( portal_type="PrenotazioniFolder" ): diff --git a/src/redturtle/prenotazioni/upgrades.zcml b/src/redturtle/prenotazioni/upgrades.zcml index cc6c6e62..530bf21e 100644 --- a/src/redturtle/prenotazioni/upgrades.zcml +++ b/src/redturtle/prenotazioni/upgrades.zcml @@ -282,4 +282,14 @@ handler=".upgrades.update_rolemap" /> + + + diff --git a/src/redturtle/prenotazioni/utilities/__init__.py b/src/redturtle/prenotazioni/utilities/__init__.py index e69de29b..c730f467 100644 --- a/src/redturtle/prenotazioni/utilities/__init__.py +++ b/src/redturtle/prenotazioni/utilities/__init__.py @@ -0,0 +1,2 @@ +from .email import send_email # noqa +from .log_errors import handle_exception_by_log # noqa diff --git a/src/redturtle/prenotazioni/utilities/email.py b/src/redturtle/prenotazioni/utilities/email.py new file mode 100644 index 00000000..46d1d1d2 --- /dev/null +++ b/src/redturtle/prenotazioni/utilities/email.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from plone import api +from plone.registry.interfaces import IRegistry +from zope.component import getUtility + +from redturtle.prenotazioni import logger + + +def send_email(msg): + if not msg: + logger.error("Could not send email due to no message was provided") + return + + host = api.portal.get_tool(name="MailHost") + registry = getUtility(IRegistry) + encoding = registry.get("plone.email_charset", "utf-8") + + host.send(msg, charset=encoding) diff --git a/src/redturtle/prenotazioni/utilities/log_errors.py b/src/redturtle/prenotazioni/utilities/log_errors.py new file mode 100644 index 00000000..0f631679 --- /dev/null +++ b/src/redturtle/prenotazioni/utilities/log_errors.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +import inspect +from logging import getLogger + + +def handle_exception_by_log(func): + """Handles all the `func` exceptions by an error log""" + func_module_name = inspect.getmodule(func).__name__ + + def inner(*args, **kwargs): + try: + func(*args, **kwargs) + except Exception: + getLogger(func_module_name).exception( + f"An error occured during the {func_module_name}.{func.__name__} execution:" + ) + + return inner diff --git a/src/redturtle/prenotazioni/viewlets/app_io.py b/src/redturtle/prenotazioni/viewlets/app_io.py deleted file mode 100644 index 7f67345e..00000000 --- a/src/redturtle/prenotazioni/viewlets/app_io.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- encoding: utf-8 -*- -from plone.app.layout.viewlets.common import ViewletBase -from zope.annotation.interfaces import IAnnotations - -from redturtle.prenotazioni.config import NOTIFICATIONS_LOGS - - -class Viewlet(ViewletBase): - def available(self): - return getattr(self.context, "app_io_enabled", False) - - def logs(self): - annotations = IAnnotations(self.context) - return [v for (k, v) in annotations.items() if k.startswith(NOTIFICATIONS_LOGS)] diff --git a/src/redturtle/prenotazioni/viewlets/templates/app_io.pt b/src/redturtle/prenotazioni/viewlets/templates/app_io.pt deleted file mode 100644 index 14400b55..00000000 --- a/src/redturtle/prenotazioni/viewlets/templates/app_io.pt +++ /dev/null @@ -1,33 +0,0 @@ -
-

- - - - - - - - - - - - - - - - - - - - - - - - - -
Codice FiscaleTitoloMessaggioID MessaggioData invioStatoNotificheInfo
-
diff --git a/src/redturtle/prenotazioni/vocabularies/tipologies.py b/src/redturtle/prenotazioni/vocabularies/tipologies.py index 5b986f39..54ecee64 100644 --- a/src/redturtle/prenotazioni/vocabularies/tipologies.py +++ b/src/redturtle/prenotazioni/vocabularies/tipologies.py @@ -27,13 +27,12 @@ def get_terms(self, context): """The vocabulary terms""" prenotazioni_folder = getPrenotazioniFolder(context) - res = [ + return [ self.booking_type2term(booking_type) for booking_type in prenotazioni_folder and prenotazioni_folder.get_booking_types() or [] ] - return res def __call__(self, context): """ diff --git a/test-5.2.x-py27.cfg b/test-5.2.x-py27.cfg deleted file mode 100644 index c63353ef..00000000 --- a/test-5.2.x-py27.cfg +++ /dev/null @@ -1,10 +0,0 @@ -[buildout] -extends = test-5.2.x.cfg - -[versions] -# python 2 -bravado = 11.0.3 -bravado-core = 5.17.0 -typing-extensions = 3.10.0.2 -jsonref = 0.2 -webcolors = 1.10