Skip to content

Commit 632ebb3

Browse files
committed
* 'master' of https://github.com/mikeckennedy/mongodb-quickstart-course: final code. guest can book a snake into a cage Register and list cages Create account implemented. Model classes converted to MongoEngine entities Code from "register connections". Added plain python classes for modeling. misspelling.
2 parents 63d1c8c + 4b57cf4 commit 632ebb3

File tree

12 files changed

+446
-50
lines changed

12 files changed

+446
-50
lines changed
File renamed without changes.

src/snake_bnb/src/data/bookings.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import mongoengine
2+
3+
4+
class Booking(mongoengine.EmbeddedDocument):
5+
guest_owner_id = mongoengine.ObjectIdField()
6+
guest_snake_id = mongoengine.ObjectIdField()
7+
8+
booked_date = mongoengine.DateTimeField()
9+
check_in_date = mongoengine.DateTimeField(required=True)
10+
check_out_date = mongoengine.DateTimeField(required=True)
11+
12+
review = mongoengine.StringField()
13+
rating = mongoengine.IntField(default=0)
14+
15+
@property
16+
def duration_in_days(self):
17+
dt = self.check_out_date - self.check_in_date
18+
return dt.days

src/snake_bnb/src/data/cages.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import datetime
2+
import mongoengine
3+
4+
from data.bookings import Booking
5+
6+
7+
class Cage(mongoengine.Document):
8+
registered_date = mongoengine.DateTimeField(default=datetime.datetime.now)
9+
10+
name = mongoengine.StringField(required=True)
11+
price = mongoengine.FloatField(required=True)
12+
square_meters = mongoengine.FloatField(required=True)
13+
is_carpeted = mongoengine.BooleanField(required=True)
14+
has_toys = mongoengine.BooleanField(required=True)
15+
allow_dangerous_snakes = mongoengine.BooleanField(default=False)
16+
17+
bookings = mongoengine.EmbeddedDocumentListField(Booking)
18+
19+
meta = {
20+
'db_alias': 'core',
21+
'collection': 'cages'
22+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import mongoengine
2+
3+
4+
def global_init():
5+
mongoengine.register_connection(alias='core', name='snake_bnb')

src/snake_bnb/src/data/owners.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import datetime
2+
import mongoengine
3+
4+
5+
class Owner(mongoengine.Document):
6+
registered_date = mongoengine.DateTimeField(default=datetime.datetime.now)
7+
name = mongoengine.StringField(required=True)
8+
email = mongoengine.StringField(required=True)
9+
10+
snake_ids = mongoengine.ListField()
11+
cage_ids = mongoengine.ListField()
12+
13+
meta = {
14+
'db_alias': 'core',
15+
'collection': 'owners'
16+
}

src/snake_bnb/src/data/snakes.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import datetime
2+
import mongoengine
3+
4+
5+
class Snake(mongoengine.Document):
6+
registered_date = mongoengine.DateTimeField(default=datetime.datetime.now)
7+
species = mongoengine.StringField(required=True)
8+
9+
length = mongoengine.FloatField(required=True)
10+
name = mongoengine.StringField(required=True)
11+
is_venomous = mongoengine.BooleanField(required=True)
12+
13+
meta = {
14+
'db_alias': 'core',
15+
'collection': 'snakes'
16+
}
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
active_account = None
1+
from data.owners import Owner
2+
import servies.data_service as svc
3+
4+
active_account: Owner = None
25

36

47
def reload_account():
58
global active_account
69
if not active_account:
710
return
811

9-
# TODO: pull owner account from the database.
10-
pass
12+
active_account = svc.find_account_by_email(active_account.email)

src/snake_bnb/src/program.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from colorama import Fore
22
import program_guests
33
import program_hosts
4+
import data.mongo_setup as mongo_setup
45

56

67
def main():
7-
# TODO: Setup mongoengine global values
8+
mongo_setup.global_init()
89

910
print_header()
1011

src/snake_bnb/src/program_guests.py

Lines changed: 100 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import datetime
2+
from dateutil import parser
3+
14
from infrastructure.switchlang import switch
25
import program_hosts as hosts
6+
import servies.data_service as svc
37
from program_hosts import success_msg, error_msg
48
import infrastructure.state as state
59

@@ -54,36 +58,114 @@ def show_commands():
5458

5559
def add_a_snake():
5660
print(' ****************** Add a snake **************** ')
57-
# TODO: Require an account
58-
# TODO: Get snake info from user
59-
# TODO: Create the snake in the DB.
61+
if not state.active_account:
62+
error_msg("You must log in first to add a snake")
63+
return
64+
65+
name = input("What is your snake's name? ")
66+
if not name:
67+
error_msg('cancelled')
68+
return
69+
70+
length = float(input('How long is your snake (in meters)? '))
71+
species = input("Species? ")
72+
is_venomous = input("Is your snake venomous [y]es, [n]o? ").lower().startswith('y')
6073

61-
print(" -------- NOT IMPLEMENTED -------- ")
74+
snake = svc.add_snake(state.active_account, name, length, species, is_venomous)
75+
state.reload_account()
76+
success_msg('Created {} with id {}'.format(snake.name, snake.id))
6277

6378

6479
def view_your_snakes():
6580
print(' ****************** Your snakes **************** ')
81+
if not state.active_account:
82+
error_msg("You must log in first to view your snakes")
83+
return
6684

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

7295

7396
def book_a_cage():
7497
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.
98+
if not state.active_account:
99+
error_msg("You must log in first to book a cage")
100+
return
101+
102+
snakes = svc.get_snakes_for_user(state.active_account.id)
103+
if not snakes:
104+
error_msg('You must first [a]dd a snake before you can book a cage.')
105+
return
106+
107+
print("Let's start by finding available cages.")
108+
start_text = input("Check-in date [yyyy-mm-dd]: ")
109+
if not start_text:
110+
error_msg('cancelled')
111+
return
112+
113+
checkin = parser.parse(
114+
start_text
115+
)
116+
checkout = parser.parse(
117+
input("Check-out date [yyyy-mm-dd]: ")
118+
)
119+
if checkin >= checkout:
120+
error_msg('Check in must be before check out')
121+
return
122+
123+
print()
124+
for idx, s in enumerate(snakes):
125+
print('{}. {} (length: {}, venomous: {})'.format(
126+
idx + 1,
127+
s.name,
128+
s.length,
129+
'yes' if s.is_venomous else 'no'
130+
))
80131

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

83154

84155
def view_bookings():
85156
print(' ****************** Your bookings **************** ')
86-
# TODO: Require an account
87-
# TODO: List booking info along with snake info
88-
89-
print(" -------- NOT IMPLEMENTED -------- ")
157+
if not state.active_account:
158+
error_msg("You must log in first to register a cage")
159+
return
160+
161+
snakes = {s.id: s for s in svc.get_snakes_for_user(state.active_account.id)}
162+
bookings = svc.get_bookings_for_user(state.active_account.email)
163+
164+
print("You have {} bookings.".format(len(bookings)))
165+
for b in bookings:
166+
print(' * Snake: {} is booked at {} from {} for {} days.'.format(
167+
snakes.get(b.guest_snake_id).name,
168+
b.cage.name,
169+
datetime.date(b.check_in_date.year, b.check_in_date.month, b.check_in_date.day),
170+
(b.check_out_date - b.check_in_date).days
171+
))

0 commit comments

Comments
 (0)