- {% for daycare in daycares %}
-
-
-
-
-
{{ daycare.name }}
+
+
+
+
+
Found {{ day_care_queryset.count }} results for your dog!
+
+ {% for daycare in day_care_queryset %}
+
+
+
+
+
{{ daycare.name }}
+
+
{{ daycare.area | truncatechars:20 }}
+
{{ daycare.city | truncatechars:20 }}
+
{{ daycare.price_per_day | truncatechars:20 }}
+
{{ daycare.description | truncatechars:35}}
+
Daycare Profile
+
+
+ {% endfor %}
+
-
{{ daycare.description | truncatechars:250 }}
-
Daycare Profile
-
- {% endfor %}
-
-
-
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/dogowner/views.py b/dogowner/views.py
index 53333ed..7fc3285 100644
--- a/dogowner/views.py
+++ b/dogowner/views.py
@@ -1,11 +1,27 @@
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from daycare.models import DayCare
+from daycare.forms import DayCareSearchForm
+from orders.models import Order
@login_required()
def dog_owner_home(request):
+ form = DayCareSearchForm(request.POST or None)
+ day_care_queryset = DayCare.objects.all()
+ if request.method == 'POST':
+ if form.is_valid():
+ filter_day_cares = DayCare.objects.filter(area__startswith=form['area'].value(),
+ city__icontains=form['city'].value(),
+ name__icontains=form['name'].value(),
+ price_per_day__lte=form['price_per_day'].value())
+
+ available_day_cares = Order.get_all_day_cares_available_on_dates(form['start_date'].value(),
+ form['end_date'].value())
+ day_care_queryset = filter_day_cares.intersection(available_day_cares)
+
context = {
- 'daycares': DayCare.objects.all(),
+ 'day_care_queryset': day_care_queryset,
+ 'form': form
}
return render(request, 'dogowner/dog_owner_homepage.html', context)
diff --git a/main/templates/main/base_template.html b/main/templates/main/base_template.html
index b045033..87360af 100644
--- a/main/templates/main/base_template.html
+++ b/main/templates/main/base_template.html
@@ -26,7 +26,6 @@
{% if request.user.is_authenticated %}
Profile
Orders
-
Search
Chats
{% endif %}
About
diff --git a/main/tests.py b/main/tests.py
index 3d3107c..8a2547a 100644
--- a/main/tests.py
+++ b/main/tests.py
@@ -1,5 +1,7 @@
import pytest
+from dogowner.models import DogOwner
from daycare.models import DayCare
+from orders.models import Order
@pytest.mark.django_db
@@ -72,8 +74,66 @@ def test_unlogged_user_access_to_homepage(self, client):
assert response.status_code == 302
assert response['Location'] == '/login/?next=/homepage/'
- def test_dog_owner_homepage_is_visible_for_dog_owner(self, client, create_dog_owner_user):
+
+@pytest.mark.django_db
+class TestDogOwnerHomePageView:
+ def test_dog_owner_homepage_present_all_daycares(self, client, create_dog_owner_user):
client.force_login(user=create_dog_owner_user.user)
response = client.get("/homepage/")
assert response.status_code == 200
- assert list(response.context['daycares']) == list(DayCare.objects.all())
+ assert set(response.context['day_care_queryset']) == set(DayCare.objects.all())
+
+ def test_daycare_not_appears_in_search_after_reduce_capacity_on_dates_to_0(self, client,
+ create_dog_owner_user,
+ create_daycare_user):
+ search_form = {'area': "",
+ 'city': "",
+ 'price_per_day': 100,
+ 'name': "",
+ 'start_date': "2022-05-03",
+ 'end_date': "2022-05-08",
+ }
+ daycare_user = create_daycare_user
+ client.force_login(user=create_dog_owner_user.user)
+ response = client.post('/homepage/', search_form, follow=True)
+ day_care_queryset = response.context['day_care_queryset']
+ assert daycare_user in day_care_queryset
+
+ for _ in range(daycare_user.capacity):
+ Order.create(dog_owner_id=DogOwner.objects.get(id=1), daycare_id=daycare_user,
+ start_date="2022-05-02", end_date="2022-08-02", price_per_day=100).approve_order()
+ response = client.post('/homepage/', search_form, follow=True)
+ assert daycare_user not in response.context['day_care_queryset']
+
+ def test_successful_dog_owner_search_for_day_care(self, client, create_dog_owner_user):
+ client.force_login(user=create_dog_owner_user.user)
+ search_form = {'area': "C",
+ 'city': "tel aviv",
+ 'price_per_day': 800,
+ 'name': "",
+ 'start_date': "2022-05-03",
+ 'end_date': "2022-05-08",
+ }
+ response = client.post('/homepage/', search_form, follow=True)
+ day_care_queryset = response.context['day_care_queryset']
+ available_day_cares = Order.get_all_day_cares_available_on_dates("2022-05-03", "2022-05-08")
+ filter_day_cares = DayCare.objects.filter(area__startswith='C',
+ city__icontains="tel aviv",
+ price_per_day__lte=800)
+ expected_queryset = available_day_cares.intersection(filter_day_cares)
+ assert set(day_care_queryset) == set(expected_queryset)
+
+ def test_search_for_day_care_with_start_date_greater_than_end_date_show_error_and_present_all_daycares(
+ self, client, create_dog_owner_user):
+ client.force_login(user=create_dog_owner_user.user)
+ search_form = {'area': "C",
+ 'city': "tel aviv",
+ 'price_per_day': 800,
+ 'name': "",
+ 'start_date': "2022-05-03",
+ 'end_date': "2022-05-01",
+ }
+ response = client.post('/homepage/', search_form, follow=True)
+ day_care_queryset = response.context['day_care_queryset']
+ assert set(day_care_queryset) == set(DayCare.objects.all())
+ assert response.context['form']._errors['end_date']
diff --git a/orders/models.py b/orders/models.py
index 105e1f3..9c7ccb4 100644
--- a/orders/models.py
+++ b/orders/models.py
@@ -1,7 +1,9 @@
from django.db import models
+from django.db.models import QuerySet
from django.utils import timezone
from daycare.models import DayCare
from dogowner.models import DogOwner
+import datetime
class StatusOptions(models.TextChoices):
@@ -71,3 +73,38 @@ def cancel_order(self):
def get_order_total_price(self):
return self.price_per_day * (self.end_date - self.start_date).days
+
+ @staticmethod
+ def get_capacity_of_daycare_in_dates_range(daycare_id, start_date, end_date):
+ relevant_orders = Order.objects.filter(daycare_id=daycare_id, status__in=['A', 'O'])
+ start_date = datetime.date(year=start_date.year, month=start_date.month, day=start_date.day)
+ end_date = datetime.date(year=end_date.year, month=end_date.month, day=end_date.day)
+ capacity_per_day_list = [0] * ((end_date - start_date).days + 2)
+
+ for order in relevant_orders:
+ if end_date < order.start_date or order.end_date < start_date:
+ continue
+
+ number_of_days = (order.end_date - order.start_date).days
+
+ for day in range(number_of_days):
+ current_date = order.start_date + datetime.timedelta(days=day)
+ if current_date < start_date:
+ continue
+ elif current_date > end_date:
+ break
+ else:
+ capacity_per_day_list[day] = capacity_per_day_list[day] + 1
+
+ return capacity_per_day_list
+
+ @staticmethod
+ def get_all_day_cares_available_on_dates(start_date: str, end_date: str) -> QuerySet:
+ start_date = datetime.date.fromisoformat(start_date)
+ end_date = datetime.date.fromisoformat(end_date)
+ id_list = []
+ for day_care in DayCare.objects.all():
+ capacity_per_day_list = Order.get_capacity_of_daycare_in_dates_range(day_care.id, start_date, end_date)
+ if all(current_capacity < day_care.capacity for current_capacity in capacity_per_day_list):
+ id_list.append(day_care.id)
+ return DayCare.objects.filter(id__in=id_list)
diff --git a/orders/tests.py b/orders/tests.py
index e9259ab..ac72c9c 100644
--- a/orders/tests.py
+++ b/orders/tests.py
@@ -52,3 +52,24 @@ def test_dog_owner_id_is_deleted_when_dog_owner_is_deleted(self, create_order):
def test_daycare_id_is_deleted_when_daycare_is_deleted(self, create_order):
DayCare.objects.get(id=1).delete()
assert Order.objects.get(id=create_order.id).daycare_id is None
+
+ @pytest.mark.parametrize('start_date, end_date',
+ [
+ ("2022-05-02", "2022-08-02"),
+ ])
+ def test_day_care_available_on_dates_appears_in_available_day_cares_queryset(self, create_daycare_user,
+ start_date, end_date):
+ day_care_user = create_daycare_user
+ assert day_care_user in Order.get_all_day_cares_available_on_dates(start_date, end_date)
+
+ @pytest.mark.parametrize('start_date, end_date',
+ [
+ ("2022-05-02", "2022-08-02"),
+ ])
+ def test_day_care_not_available_on_dates_not_appears_in_available_day_cares_queryset(self, create_daycare_user,
+ start_date, end_date):
+ day_care_user = create_daycare_user
+ for _ in range(day_care_user.capacity):
+ Order.create(dog_owner_id=DogOwner.objects.get(id=1), daycare_id=day_care_user,
+ start_date=start_date, end_date=end_date, price_per_day=500).approve_order()
+ assert day_care_user not in Order.get_all_day_cares_available_on_dates(start_date, end_date)
diff --git a/static/CSS/dog_owner_homepage.css b/static/CSS/dog_owner_homepage.css
index 7c77f17..092071b 100644
--- a/static/CSS/dog_owner_homepage.css
+++ b/static/CSS/dog_owner_homepage.css
@@ -1,32 +1,24 @@
.cards
{
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- margin-left: 50px;
- justify-content: center;
- align-items: center;
+ float:left;
+ margin: 0 0 0 5em;
+ position:relative;
+ width:100%;
}
-.row
-{
- height: 30rem;
- width: 120rem;
- margin-left: 200px;
+#searchResult {
+ font-weight:bold;
+ position: relative;
+ left: 6.3em;
+ top:30px;
}
.card
{
- width: 18.5%;
+ width: 330px;
height: 30rem;
- margin: 60px 60px 0 60px;
- max-width: 100%;
-}
-
-.card-body
-{
- display: flex;
- flex-direction: column;
+ float:left;
+ margin: 60px 20px 0 20px;
}
.card-body .btn
@@ -38,4 +30,31 @@
.card-img-top
{
height: 200px;
-}
\ No newline at end of file
+}
+
+#searchBoxArea {
+ background-color:#dcdcdc;
+ left:5em;
+ top: 5.2em;
+ max-width:100%;
+ padding: 2em 2em 2em 2em;
+}
+
+#searchBoxArea span {
+ font-weight:bold;
+ font-size:18px;
+ color:#3e3e3e;
+ padding: 5px 0 1em 0;
+ float:left;
+}
+
+#searchBoxArea input[type="submit"] {
+ background-color:#3e3e3e;
+ border: 0;
+ border-radius:12px;
+ color:#FFF;
+}
+
+#searchBoxArea input[type="submit"]:hover {
+ background-color:#1e1e1e;
+}