Skip to content

Commit

Permalink
Bookings export view (#210)
Browse files Browse the repository at this point in the history
* Bookings export script

* Formatting

* Add sort order by date

* Fix translation

* Update script

* Add name surname to export

* Translations

* Update README.rst
  • Loading branch information
folix-01 authored Jun 24, 2024
1 parent d9d71ae commit 3f86de8
Show file tree
Hide file tree
Showing 7 changed files with 464 additions and 95 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ Changelog
2.7.4 (unreleased)
------------------

- Nothing changed yet.
- @@bookings-export view.
[folix-01]


2.7.3 (2024-06-14)
Expand Down
12 changes: 11 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ Response::

If a user is authenticated and, he is not a site operator, returns all own bookings.

With an experimental envionment `SEE_OWN_ANONYMOUS_BOOKINGS` set to `True`, the endpoint will return
With an experimental envionment `SEE_OWN_ANONYMOUS_BOOKINGS` set to `True`, the endpoint will return
also the bookings created by anonymous users with the same fiscalcode of the authenticated user.

@booking-notify
Expand Down Expand Up @@ -734,6 +734,16 @@ have the Reminder Notification Gap field populated. If you intend to set up a cr
The script is located at src/redturtle/prenotazioni/scripts/notify_upcoming_bookings.py.


@@bookings-export
-----------------

Export bookings by passed **date** in ISO format or today by default.

Example::
curl -i http://localhost:8080/Plone/@@bookings-export?date=2024-06-21

Response::
Binary csv file

Scripts
=======
Expand Down
159 changes: 159 additions & 0 deletions src/redturtle/prenotazioni/browser/bookings_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
import csv
import datetime

from plone import api
from Products.Five import BrowserView
from six import StringIO
from zExceptions import BadRequest

from redturtle.prenotazioni import _
from redturtle.prenotazioni.restapi.serializers.adapters.prenotazione import (
get_booking_wf_state_title,
)
from redturtle.prenotazioni.utilities.dateutils import get_default_timezone


class BookingsExport(BrowserView):
filename = "Bookings_export"
date = None

@property
def csv_fields(self):
return [
api.portal.translate(_("csv_export_uid", default="UID")),
api.portal.translate(_("csv_export_code", default="CODE")),
api.portal.translate(_("csv_export_type", default="TYPE")),
api.portal.translate(_("csv_export_phone", default="PHONE")),
api.portal.translate(_("csv_export_email", default="EMAIL")),
api.portal.translate(_("csv_export_name", default="NAME SURNAME")),
api.portal.translate(_("csv_export_fiscalcode", default="FISCALCODE")),
api.portal.translate(_("csv_export_start_time", default="BOOKING START")),
api.portal.translate(
_("csv_export_end_time", default="BOOKING EXPIRATION")
),
api.portal.translate(_("csv_export_state", default="STATE")),
api.portal.translate(_("csv_export_gate", default="GATE")),
api.portal.translate(_("csv_export_notes", default="NOTES")),
api.portal.translate(
_("csv_export_booking_folder", default="BOOKING FOLDER")
),
api.portal.translate(_("csv_export_company", default="COMPANY")),
]

@property
def csv_filename(self):
"""Return a filename for this csv"""

return "%s-%s.csv" % (self.filename, self.date.date().isoformat())

@property
def brains(self):

return api.portal.get_tool("portal_catalog").unrestrictedSearchResults(
portal_type="Prenotazione",
Date={
"query": (
get_default_timezone(True).localize(self.date),
get_default_timezone(True).localize(
self.date.replace(hour=23, minute=59)
),
),
"range": "min:max",
},
review_state="confirmed",
sort_on="Date",
)

def setHeader(self, *args):
"""
Shorcut for setting headers in the request
"""
return self.context.REQUEST.RESPONSE.setHeader(*args)

def brain2row(self, brain):
"""
returns a generator with the booking data
"""
booking = brain.getObject()

return {
api.portal.translate(_("csv_export_uid", default="UID")): booking.UID(),
api.portal.translate(
_("csv_export_code", default="CODE")
): booking.getBookingCode(),
api.portal.translate(
_("csv_export_type", default="TYPE")
): booking.booking_type,
api.portal.translate(_("csv_export_phone", default="PHONE")): booking.phone,
api.portal.translate(_("csv_export_email", default="EMAIL")): booking.email,
api.portal.translate(
_("csv_export_fiscalcode", default="FISCALCODE")
): getattr(booking, "fiscalcode", "").upper(),
api.portal.translate(
_("csv_export_start_time", default="BOOKING START")
): booking.booking_date.strftime("%Y-%m-%d %H:%M"),
api.portal.translate(
_("csv_export_end_time", default="BOOKING EXPIRATION")
): booking.booking_expiration_date.strftime("%Y-%m-%d %H:%M"),
api.portal.translate(
_("csv_export_notes", default="NOTES")
): booking.description,
api.portal.translate(
_("csv_export_state", default="STATE")
): get_booking_wf_state_title(booking),
api.portal.translate(_("csv_export_gate", default="GATE")): booking.gate,
api.portal.translate(
_("csv_export_booking_folder", default="BOOKING FOLDER")
): booking.getPrenotazioniFolder().Title(),
api.portal.translate(
_("csv_export_company", default="COMPANY")
): booking.company,
api.portal.translate(
_("csv_export_name", default="NAME SURNAME")
): booking.title,
}

def get_csv_rows(self):
"""Return the csv rows as a dictionary"""
for brain in self.brains:
yield self.brain2row(brain)

def get_csv(self):
"""Get a csv out of the view brains"""

buffer = StringIO()
csv_writer = csv.DictWriter(buffer, fieldnames=self.csv_fields)

csv_writer.writeheader()

for row in self.get_csv_rows():
csv_writer.writerow(row)

buffer.seek(0)

return buffer.getvalue().encode("utf-8")

def __call__(self):
date = self.request.get("date")

if not date:
self.date = datetime.datetime.combine(
datetime.date.today(), datetime.datetime.min.time()
)
else:
try:
self.date = datetime.datetime.combine(
datetime.date.fromisoformat(date), datetime.datetime.min.time()
)
except ValueError:
raise BadRequest(_("Bad date format passed"))
self.setHeader(
"Content-Disposition", "attachment;filename=%s" % self.csv_filename
)
self.request.response.setHeader(
"Content-Type",
"application/csv",
)

return self.get_csv()
7 changes: 7 additions & 0 deletions src/redturtle/prenotazioni/browser/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,13 @@
permission="redturtle.prenotazioni.SearchPrenotazioni"
/>

<browser:page
name="bookings-export"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
class=".bookings_export.BookingsExport"
permission="cmf.ModifyPortalContent"
/>

<!-- define new widget -->
<class class=".widget.WeekTableOverridesWidget">
<require
Expand Down
Loading

0 comments on commit 3f86de8

Please sign in to comment.