Skip to content

Commit

Permalink
Notifications heavy refactoring + booking reminder from #130 pr (#135)
Browse files Browse the repository at this point in the history
* 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 cb95522.

* 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 <[email protected]>
Co-authored-by: Mauro Amico <[email protected]>
  • Loading branch information
3 people authored Jan 4, 2024
1 parent af35c5d commit adcde26
Show file tree
Hide file tree
Showing 82 changed files with 4,631 additions and 2,465 deletions.
17 changes: 13 additions & 4 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -83,6 +90,7 @@ Changelog

- Set PrenotazioniFolder and PrenotazioneType as not searchable (types_not_searched).
[cekk]

- Send ical also for manager notifications.
[cekk]

Expand Down Expand Up @@ -120,7 +128,7 @@ Changelog

- Add booking_refuse_message to Prenotazione stringinterp variables.
[folix-01]

- Extended PrenotaizoniFolder email templates var list.
[folix-01]

Expand Down Expand Up @@ -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)
-----------------------
Expand Down
111 changes: 98 additions & 13 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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::

<adapter
factory = ".my_adapter.CustomSMSSenderAdapter"
name="booking_transition_sms_sender"
/>

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
---------
Expand Down Expand Up @@ -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_<AppIO Sevice code here>=<AppIO Sevice key here>**

Content-transfer-encoding
=========================

Expand Down
4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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": [
Expand All @@ -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
""",
)
22 changes: 0 additions & 22 deletions src/redturtle/prenotazioni/adapters/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -190,27 +190,5 @@
for="redturtle.prenotazioni.content.prenotazione.IPrenotazione"
/>

<!-- Prenotazione email message adapters -->


<adapter
factory=".prenotazione_email_message.PrenotazioneAfterTransitionEmailMessage"
name="refuse"
/>
<adapter
factory=".prenotazione_email_message.PrenotazioneAfterTransitionEmailMessage"
name="submit"
/>
<adapter
factory=".prenotazione_email_message.PrenotazioneAfterTransitionEmailICalMessage"
name="confirm"
/>

<adapter
factory=".prenotazione_email_message.PrenotazioneManagerEmailMessage"
name="notify_manager"
/>
<!-- Prenotazione moved event message adapter -->
<adapter factory=".prenotazione_email_message.PrenotazioneMovedICalEmailMessage" />

</configure>
65 changes: 65 additions & 0 deletions src/redturtle/prenotazioni/behaviors/booking_folder/__init__.py
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit adcde26

Please sign in to comment.