Skip to content

Commit b871ae0

Browse files
committed
guest can book a snake into a cage
1 parent cee8493 commit b871ae0

File tree

3 files changed

+203
-21
lines changed

3 files changed

+203
-21
lines changed

src/snake_bnb/src/program_guests.py

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
from dateutil import parser
2+
13
from infrastructure.switchlang import switch
24
import program_hosts as hosts
5+
import servies.data_service as svc
36
from program_hosts import success_msg, error_msg
47
import infrastructure.state as state
58

@@ -54,31 +57,98 @@ def show_commands():
5457

5558
def add_a_snake():
5659
print(' ****************** Add a snake **************** ')
57-
# TODO: Require an account
58-
# TODO: Get snake info from user
59-
# TODO: Create the snake in the DB.
60+
if not state.active_account:
61+
error_msg("You must log in first to add a snake")
62+
return
6063

61-
print(" -------- NOT IMPLEMENTED -------- ")
64+
name = input("What is your snake's name? ")
65+
if not name:
66+
error_msg('cancelled')
67+
return
68+
69+
length = float(input('How long is your snake (in meters)? '))
70+
species = input("Species? ")
71+
is_venomous = input("Is your snake venomous [y]es, [n]o? ").lower().startswith('y')
72+
73+
snake = svc.add_snake(state.active_account, name, length, species, is_venomous)
74+
state.reload_account()
75+
success_msg('Created {} with id {}'.format(snake.name, snake.id))
6276

6377

6478
def view_your_snakes():
6579
print(' ****************** Your snakes **************** ')
80+
if not state.active_account:
81+
error_msg("You must log in first to view your snakes")
82+
return
6683

67-
# TODO: Require an account
68-
# TODO: Get snakes from DB, show details list
69-
70-
print(" -------- NOT IMPLEMENTED -------- ")
84+
snakes = svc.get_snakes_for_user(state.active_account.id)
85+
print("You have {} snakes.".format(len(snakes)))
86+
for s in snakes:
87+
print(" * {} is a {} that is {}m long and is {}venomous.".format(
88+
s.name,
89+
s.species,
90+
s.length,
91+
'' if s.is_venomous else 'not '
92+
))
7193

7294

7395
def book_a_cage():
7496
print(' ****************** Book a cage **************** ')
75-
# TODO: Require an account
76-
# TODO: Verify they have a snake
77-
# TODO: Get dates and select snake
78-
# TODO: Find cages available across date range
79-
# TODO: Let user select cage to book.
97+
if not state.active_account:
98+
error_msg("You must log in first to book a cage")
99+
return
100+
101+
snakes = svc.get_snakes_for_user(state.active_account.id)
102+
if not snakes:
103+
error_msg('You must first [a]dd a snake before you can book a cage.')
104+
return
105+
106+
print("Let's start by finding available cages.")
107+
start_text = input("Check-in date [yyyy-mm-dd]: ")
108+
if not start_text:
109+
error_msg('cancelled')
110+
return
111+
112+
checkin = parser.parse(
113+
start_text
114+
)
115+
checkout = parser.parse(
116+
input("Check-out date [yyyy-mm-dd]: ")
117+
)
118+
if checkin >= checkout:
119+
error_msg('Check in must be before check out')
120+
return
80121

81-
print(" -------- NOT IMPLEMENTED -------- ")
122+
print()
123+
for idx, s in enumerate(snakes):
124+
print('{}. {} (length: {}, venomous: {})'.format(
125+
idx + 1,
126+
s.name,
127+
s.length,
128+
'yes' if s.is_venomous else 'no'
129+
))
130+
131+
snake = snakes[int(input('Which snake do you want to book (number)')) - 1]
132+
133+
cages = svc.get_available_cages(checkin, checkout, snake)
134+
135+
print("There are {} cages available in that time.".format(len(cages)))
136+
for idx, c in enumerate(cages):
137+
print(" {}. {} with {}m carpeted: {}, has toys: {}.".format(
138+
idx + 1,
139+
c.name,
140+
c.square_meters,
141+
'yes' if c.is_carpeted else 'no',
142+
'yes' if c.has_toys else 'no'))
143+
144+
if not cages:
145+
error_msg("Sorry, no cages are available for that date.")
146+
return
147+
148+
cage = cages[int(input('Which cage do you want to book (number)')) - 1]
149+
svc.book_cage(state.active_account, snake, cage, checkin, checkout)
150+
151+
success_msg('Successfully booked {} for {} at ${}/night.'.format(cage.name, snake.name, cage.price))
82152

83153

84154
def view_bookings():

src/snake_bnb/src/program_hosts.py

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from colorama import Fore
2+
from dateutil import parser
3+
24
from infrastructure.switchlang import switch
35
import infrastructure.state as state
46
import servies.data_service as svc
@@ -115,19 +117,50 @@ def list_cages(suppress_header=False):
115117

116118
cages = svc.find_cages_for_user(state.active_account)
117119
print(f"You have {len(cages)} cages.")
118-
for c in cages:
119-
print(f' * {c.name} is {c.square_meters} meters.')
120+
for idx, c in enumerate(cages):
121+
print(f' {idx+1}. {c.name} is {c.square_meters} meters.')
122+
for b in c.bookings:
123+
print(' * Booking: {}, {} days, booked? {}'.format(
124+
b.check_in_date,
125+
(b.check_out_date - b.check_in_date).days,
126+
'YES' if b.booked_date is not None else 'no'
127+
))
120128

121129

122130
def update_availability():
123131
print(' ****************** Add available date **************** ')
124132

125-
# TODO: Require an account
126-
# TODO: list cages
127-
# TODO: Choose cage
128-
# TODO: Set dates, save to DB.
133+
if not state.active_account:
134+
error_msg("You must log in first to register a cage")
135+
return
129136

130-
print(" -------- NOT IMPLEMENTED -------- ")
137+
list_cages(suppress_header=True)
138+
139+
cage_number = input("Enter cage number: ")
140+
if not cage_number.strip():
141+
error_msg('Cancelled')
142+
print()
143+
return
144+
145+
cage_number = int(cage_number)
146+
147+
cages = svc.find_cages_for_user(state.active_account)
148+
selected_cage = cages[cage_number - 1]
149+
150+
success_msg("Selected cage {}".format(selected_cage.name))
151+
152+
start_date = parser.parse(
153+
input("Enter available date [yyyy-mm-dd]: ")
154+
)
155+
days = int(input("How many days is this block of time? "))
156+
157+
svc.add_available_date(
158+
selected_cage,
159+
start_date,
160+
days
161+
)
162+
163+
success_msg(f'Date added to cage {selected_cage.name}.')
131164

132165

133166
def view_bookings():

src/snake_bnb/src/servies/data_service.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
from typing import List
22

3+
import datetime
4+
5+
import bson
6+
7+
from data.bookings import Booking
38
from data.cages import Cage
49
from data.owners import Owner
10+
from data.snakes import Snake
511

612

713
def create_account(name: str, email: str) -> Owner:
@@ -45,3 +51,76 @@ def find_cages_for_user(account: Owner) -> List[Cage]:
4551
cages = list(query)
4652

4753
return cages
54+
55+
56+
def add_available_date(cage: Cage,
57+
start_date: datetime.datetime, days: int) -> Cage:
58+
booking = Booking()
59+
booking.check_in_date = start_date
60+
booking.check_out_date = start_date + datetime.timedelta(days=days)
61+
62+
cage = Cage.objects(id=cage.id).first()
63+
cage.bookings.append(booking)
64+
cage.save()
65+
66+
return cage
67+
68+
69+
def add_snake(account, name, length, species, is_venomous) -> Snake:
70+
snake = Snake()
71+
snake.name = name
72+
snake.length = length
73+
snake.species = species
74+
snake.is_venomous = is_venomous
75+
snake.save()
76+
77+
owner = find_account_by_email(account.email)
78+
owner.snake_ids.append(snake.id)
79+
owner.save()
80+
81+
return snake
82+
83+
84+
def get_snakes_for_user(user_id: bson.ObjectId) -> List[Snake]:
85+
owner = Owner.objects(id=user_id).first()
86+
snakes = Snake.objects(id__in=owner.snake_ids).all()
87+
88+
return list(snakes)
89+
90+
91+
def get_available_cages(checkin: datetime.datetime,
92+
checkout: datetime.datetime, snake: Snake) -> List[Cage]:
93+
min_size = snake.length / 4
94+
95+
query = Cage.objects() \
96+
.filter(square_meters__gte=min_size) \
97+
.filter(bookings__check_in_date__lte=checkin) \
98+
.filter(bookings__check_out_date__gte=checkout)
99+
100+
if snake.is_venomous:
101+
query = query.filter(allow_dangerous_snakes=True)
102+
103+
cages = query.order_by('price', '-square_meters')
104+
105+
final_cages = []
106+
for c in cages:
107+
for b in c.bookings:
108+
if b.check_in_date <= checkin and b.check_out_date >= checkout and b.guest_snake_id is None:
109+
final_cages.append(c)
110+
111+
return final_cages
112+
113+
114+
def book_cage(account, snake, cage, checkin, checkout):
115+
booking: Booking = None
116+
117+
for b in cage.bookings:
118+
if b.check_in_date <= checkin and b.check_out_date >= checkout and b.guest_snake_id is None:
119+
booking = b
120+
break
121+
122+
booking.guest_owner_id = account.id
123+
booking.guest_snake_id = snake.id
124+
booking.booked_date = datetime.datetime.now()
125+
126+
cage.save()

0 commit comments

Comments
 (0)