Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Us orario invernale estivo #66

Merged
merged 19 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Changelog
2.0.0 (unreleased)
------------------

- Add logic to override pauses and gates.
[daniele]

- permit to force gate / duration to operator (restapi add booking)
[mamico]

Expand Down
81 changes: 67 additions & 14 deletions src/redturtle/prenotazioni/browser/prenotazioni_context_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ def get_week_table(self, day):
week_table_overrides = json.loads(
getattr(self.context, "week_table_overrides", "[]") or "[]"
)

if not week_table_overrides:
return week_table

Expand Down Expand Up @@ -383,18 +384,47 @@ def get_anonymous_booking_url(self, day, slot, slot_min_size=0):
return self.unavailable_slot_booking_url

@memoize
def get_gates(self, day=None):
def get_gates(self, booking_date=None):
"""
Get's the gates, available and unavailable
"""
# TODO: gestire le gates in base al giorno
gates = self.context.getGates() or [""]

week_table_overrides = json.loads(
getattr(self.context, "week_table_overrides", "[]") or "[]"
)
if week_table_overrides:
gates_override = week_table_overrides[0].get("gates", [])
if gates_override:
for override in week_table_overrides:
from_month = int(override.get("from_month", ""))
from_day = int(override.get("from_day", ""))
to_month = int(override.get("to_month", ""))
to_day = int(override.get("to_day", ""))

if not booking_date:
toYear = datetime.today().year
else:
toYear = booking_date.year

if from_month > to_month:
# next year
toYear += 1

fromDate = date(booking_date.year, from_month, from_day)
toDate = date(toYear, to_month, to_day)

if fromDate <= booking_date <= toDate:
gates = gates_override
break

unavailable = self.context.getUnavailable_gates() or []
return [
{
"name": gate,
"available": gate not in unavailable,
}
for gate in self.context.getGates() or [""]
for gate in gates or [""]
]

@memoize
Expand All @@ -405,17 +435,13 @@ def get_unavailable_gates(self):
return self.context.getUnavailable_gates()

@memoize
def get_available_gates(self):
def get_available_gates(self, booking_date=None):
"""
Get's the gates declared available
"""
# total = set(self.get_gates())
# if self.get_unavailable_gates():
# unavailable = set(self.get_unavailable_gates())
# else:
# unavailable = set()
# return total - unavailable
return [gate["name"] for gate in self.get_gates() if gate["available"]]
return [
gate["name"] for gate in self.get_gates(booking_date) if gate["available"]
]

def get_busy_gates_in_slot(self, booking_date, booking_end_date=None):
"""
Expand Down Expand Up @@ -473,7 +499,7 @@ def get_free_gates_in_slot(self, booking_date, booking_end_date=None):

:param booking_date: a DateTime object
"""
available = set(self.get_available_gates())
available = set(self.get_available_gates(booking_date))
busy = set(self.get_busy_gates_in_slot(booking_date, booking_end_date))
return available - busy

Expand Down Expand Up @@ -605,7 +631,34 @@ def get_pauses_in_day_folder(self, booking_date):
:param booking_date: a date as a datetime or a string
"""
weekday = booking_date.weekday()

week_table_overrides = json.loads(
getattr(self.context, "week_table_overrides", "[]") or "[]"
)

pause_override = []
if week_table_overrides:
pause_override = week_table_overrides[0].get("pauses", [])
pause_table = self.context.pause_table or []

if pause_override:
for override in week_table_overrides:
from_month = int(override.get("from_month", ""))
from_day = int(override.get("from_day", ""))
to_month = int(override.get("to_month", ""))
to_day = int(override.get("to_day", ""))
toYear = booking_date.year

if from_month > to_month:
# next year
toYear += 1

fromDate = date(booking_date.year, from_month, from_day)
toDate = date(toYear, to_month, to_day)

if fromDate <= booking_date <= toDate:
pause_table = pause_override

today_pauses = [row for row in pause_table if row["day"] == str(weekday)]
pauses = []
for pause in today_pauses:
Expand Down Expand Up @@ -687,7 +740,7 @@ def get_busy_slots(self, booking_date, period="day"):
slots = self.get_busy_slots_in_period(booking_date, period)
for slot in slots:
if slot.context.portal_type == PAUSE_PORTAL_TYPE:
for gate in self.get_gates():
for gate in self.get_gates(booking_date):
slots_by_gate.setdefault(gate["name"], []).append(slot)
else:
slots_by_gate.setdefault(slot.gate, []).append(slot)
Expand All @@ -710,7 +763,7 @@ def get_free_slots(self, booking_date, period="day"):
else:
intervals = [day_intervals[period]]
slots_by_gate = self.get_busy_slots(booking_date, period)
gates = [gate["name"] for gate in self.get_gates()]
gates = [gate["name"] for gate in self.get_gates(booking_date)]
availability = {}
for gate in gates:
# unavailable gates doesn't have free slots
Expand Down
212 changes: 212 additions & 0 deletions src/redturtle/prenotazioni/tests/test_pauses_overrides.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
# -*- coding: utf-8 -*-
from datetime import date
import transaction

from plone.app.testing import (
SITE_OWNER_NAME,
SITE_OWNER_PASSWORD,
TEST_USER_ID,
setRoles,
)
from plone.restapi.testing import RelativeSession
from redturtle.prenotazioni.testing import (
REDTURTLE_PRENOTAZIONI_API_FUNCTIONAL_TESTING,
)
from redturtle.prenotazioni.testing import (
REDTURTLE_PRENOTAZIONI_FUNCTIONAL_TESTING,
)
from plone import api

import unittest
import json


class TestContextState(unittest.TestCase):
layer = REDTURTLE_PRENOTAZIONI_FUNCTIONAL_TESTING

def setUp(self):
self.app = self.layer["app"]
self.portal = self.layer["portal"]
self.request = self.layer["request"]
self.portal_url = self.portal.absolute_url()
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(),
booking_types=[
{"name": "Type A", "duration": "30"},
],
gates=["Gate A"],
pause_table=[
{"day": "0", "pause_start": "0900", "pause_end": "0915"},
{"day": "1", "pause_start": "0900", "pause_end": "0915"},
{"day": "2", "pause_start": "0900", "pause_end": "0915"},
{"day": "3", "pause_start": "0900", "pause_end": "0915"},
{"day": "4", "pause_start": "0900", "pause_end": "0915"},
{"day": "5", "pause_start": "0900", "pause_end": "0915"},
],
week_table=[
{
"day": "Lunedì",
"morning_start": "0700",
"morning_end": "1000",
"afternoon_start": None,
"afternoon_end": None,
},
],
week_table_overrides=json.dumps(
[
{
"from_day": "1",
"from_month": "1",
"to_month": "2",
"pauses": [
{"day": "0", "pause_end": "1200", "pause_start": "1000"},
{"day": "1", "pause_end": "1200", "pause_start": "1000"},
{"day": "2", "pause_end": "1200", "pause_start": "1000"},
{"day": "3", "pause_end": "1200", "pause_start": "1000"},
{"day": "4", "pause_end": "1200", "pause_start": "1000"},
{"day": "5", "pause_end": "1200", "pause_start": "1000"},
],
"to_day": "18",
"week_table": [
{
"day": "Lunedì",
"morning_start": "1100",
"morning_end": "1200",
"afternoon_start": None,
"afternoon_end": None,
},
],
}
]
),
)
api.content.transition(obj=self.folder_prenotazioni, transition="publish")
transaction.commit()

self.view = api.content.get_view(
name="prenotazioni_context_state",
context=self.folder_prenotazioni,
request=self.request,
)

def test_day_in_override_pause_table(self):
now = date.today()
res = self.view.get_pauses_in_day_folder(date(now.year, 1, 10))
pause = res[0]
self.assertEqual(pause.start, "10:00") and self.assertEqual(pause.stop, "12:00")

def test_day_not_in_override_pause_table(self):
now = date.today()
res = self.view.get_pauses_in_day_folder(date(now.year, 6, 10))
pause = res[0]
self.assertNotEqual(pause.start, "10:00") and self.assertNotEqual(
pause.stop, "12:00"
)


class TestAPIPost(unittest.TestCase):
layer = REDTURTLE_PRENOTAZIONI_API_FUNCTIONAL_TESTING

def setUp(self):
self.app = self.layer["app"]
self.portal = self.layer["portal"]
self.request = self.layer["request"]
self.portal_url = self.portal.absolute_url()
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(),
booking_types=[
{"name": "Type A", "duration": "30"},
],
gates=["Gate A"],
pause_table=[
{"day": "0", "pause_start": "0900", "pause_end": "0915"},
{"day": "1", "pause_start": "0900", "pause_end": "0915"},
{"day": "2", "pause_start": "0900", "pause_end": "0915"},
{"day": "3", "pause_start": "0900", "pause_end": "0915"},
{"day": "4", "pause_start": "0900", "pause_end": "0915"},
{"day": "5", "pause_start": "0900", "pause_end": "0915"},
],
week_table=[
{
"day": "Lunedì",
"morning_start": "0700",
"morning_end": "1000",
"afternoon_start": None,
"afternoon_end": None,
},
],
week_table_overrides=json.dumps(
[
{
"from_day": "1",
"from_month": "1",
"to_month": "2",
"pauses": [
{"day": "0", "pause_end": "1200", "pause_start": "1000"},
{"day": "1", "pause_end": "1200", "pause_start": "1000"},
{"day": "2", "pause_end": "1200", "pause_start": "1000"},
{"day": "3", "pause_end": "1200", "pause_start": "1000"},
{"day": "4", "pause_end": "1200", "pause_start": "1000"},
{"day": "5", "pause_end": "1200", "pause_start": "1000"},
],
"to_day": "18",
"week_table": [
{
"day": "Lunedì",
"morning_start": "1100",
"morning_end": "1200",
"afternoon_start": None,
"afternoon_end": None,
},
],
}
]
),
)
api.content.transition(obj=self.folder_prenotazioni, transition="publish")
transaction.commit()

self.api_session = RelativeSession(self.portal_url)
self.api_session.headers.update({"Accept": "application/json"})
self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD)

self.view = api.content.get_view(
name="prenotazioni_context_state",
context=self.folder_prenotazioni,
request=self.request,
)

def tearDown(self):
self.api_session.close()

def test_add_booking_in_overrided_pause(self):
self.api_session.auth = None
booking_date = "{}T11:00:00+00:00".format(
(date(date.today().year, 1, 10)).strftime("%Y-%m-%d")
)

res = self.api_session.post(
self.folder_prenotazioni.absolute_url() + "/@booking",
json={
"booking_date": booking_date,
"booking_type": "Type A",
"fields": [
{"name": "fullname", "value": "Mario Rossi"},
{"name": "email", "value": "mario.rossi@example"},
],
},
)

self.assertNotEqual(res.status_code, 200)
Loading