Skip to content

Commit 312fb13

Browse files
Feat: Added delete functionality (delete itinerary, itinerary flight, or itinerary attraction) to main.py and manage_itineraries.py + code cleanup.
1 parent aa82bf9 commit 312fb13

2 files changed

Lines changed: 140 additions & 44 deletions

File tree

Travel Itinerary Planner/main.py

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from src.file_handler import load_itineraries
2-
from src.manage_itineraries import add_itinerary, edit_itinerary, add_new_flight, add_new_attraction, view_itineraries, delete_itinerary, print_table
2+
from src.manage_itineraries import add_itinerary, edit_itinerary, add_new_flight, add_new_attraction, view_itineraries, delete_itinerary, delete_itinerary_item, print_table
33
from pick import pick
44

55

@@ -226,13 +226,98 @@ def run_app():
226226

227227
# View itinerary
228228
elif user_choice == "4":
229-
view_itineraries(itineraries)
229+
if not itineraries:
230+
print("No itineraries available to view!")
231+
else:
232+
view_itineraries(itineraries)
230233

231234
# Delete itinerary
232235
elif user_choice == "5":
233-
chosen_itinerary = input("")
234-
delete_itinerary(chosen_itinerary)
235-
pass
236+
# Use pick to choose delete options
237+
delete_prompt = 'Would you like to delete a full itinerary, or a flight/attraction? \n(Note: You can only delete a flight or attraction if there is MORE THAN ONE available in the itinerary. \nIf there is only one, please select return.)'
238+
delete_options = ['Entire itinerary', 'Itinerary flight', 'Itinerary attraction', 'Return']
239+
delete_option, delete_index = pick(delete_options, delete_prompt)
240+
print_table(itineraries)
241+
242+
if delete_option == 'Entire itinerary':
243+
itinerary_prompt = 'Which itinerary would you like to delete? '
244+
itinerary_options = []
245+
for itinerary in itineraries:
246+
itinerary_options.append(itinerary["name"])
247+
itinerary_option, itinerary_index = pick(itinerary_options, itinerary_prompt)
248+
if delete_itinerary(itineraries, itinerary_option):
249+
print("Itinerary has been deleted.")
250+
else:
251+
print("Itinerary could not be found.")
252+
253+
elif delete_option == 'Itinerary flight':
254+
while True:
255+
multiple_flights = True
256+
selected_type = "flights"
257+
# Choose itinerary
258+
itinerary_prompt = 'Which itinerary would you like to change? '
259+
itinerary_options = []
260+
for itinerary in itineraries:
261+
itinerary_options.append(itinerary["name"])
262+
itinerary_option, itinerary_index = pick(itinerary_options, itinerary_prompt)
263+
# Choose flight
264+
flight_prompt = 'Which flight would you like to delete? '
265+
flight_options = []
266+
for itinerary in itineraries:
267+
if itinerary["name"] == itinerary_option:
268+
if len(itinerary["flights"]) <= 1:
269+
print("There is only one flight available, therefore you cannot delete it.")
270+
multiple_flights = False
271+
break
272+
else:
273+
for flight in itinerary["flights"]:
274+
flight_options.append(flight["flight name"])
275+
# Checks if 'while True' statement should be broken
276+
if not multiple_flights:
277+
print("Returning to main menu...")
278+
break
279+
flight_id, itinerary_index = pick(flight_options, flight_prompt)
280+
if delete_itinerary_item(itineraries, selected_type, itinerary_option, flight_id):
281+
print(f"Flight '{flight_id}' has been deleted.")
282+
else:
283+
print("Flight could not be found.")
284+
break
285+
286+
elif delete_option == 'Itinerary attraction':
287+
while True:
288+
multiple_attractions = True
289+
selected_type = "attractions"
290+
# Choose itinerary
291+
itinerary_prompt = 'Which itinerary would you like to change? '
292+
itinerary_options = []
293+
for itinerary in itineraries:
294+
itinerary_options.append(itinerary["name"])
295+
itinerary_option, itinerary_index = pick(itinerary_options, itinerary_prompt)
296+
# Choose attraction
297+
attraction_prompt = 'Which attraction would you like to delete? '
298+
attraction_options = []
299+
for itinerary in itineraries:
300+
if itinerary["name"] == itinerary_option:
301+
if len(itinerary["attractions"]) <= 1:
302+
print("There is only one attraction available, therefore you cannot delete it.")
303+
multiple_attractions = False
304+
break
305+
else:
306+
for attraction in itinerary["attractions"]:
307+
attraction_options.append(attraction["attraction name"])
308+
# Checks if 'while True' statement should be broken
309+
if not multiple_attractions:
310+
print("Returning to main menu...")
311+
break
312+
attraction_id, itinerary_index = pick(attraction_options, attraction_prompt)
313+
if delete_itinerary_item(itineraries, selected_type, itinerary_option, attraction_id):
314+
print(f"Attraction '{attraction_id}' has been deleted.")
315+
else:
316+
print("Attraction could not be found.")
317+
break
318+
319+
elif delete_option == 'Return':
320+
print("Returning to previous menu...\n")
236321

237322
# Log out
238323
elif user_choice == "6":

Travel Itinerary Planner/src/manage_itineraries.py

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
from src.file_handler import load_itineraries, save_itineraries
22
from datetime import datetime
33
from pick import pick
4-
from anytree import Node, RenderTree
5-
from pickpack import pickpack, PickPacker, AnyNode
64
from rich.console import Console
75
from rich.table import Table
86
from rich import print
@@ -22,14 +20,15 @@ def add_itinerary(itinerary_list, name, location, description, start_date, end_d
2220
Side Effects:
2321
- Saves the updated itinerary list to a file using `save_itineraries`.
2422
"""
25-
# TEST: check that all items have been transferred correctly
26-
print(name)
27-
print(location)
28-
print(description)
29-
print(start_date)
30-
print(end_date)
31-
print(flights)
32-
print(attractions)
23+
# Print TEST: Uncomment to check that all items have been transferred correctly
24+
# print(name)
25+
# print(location)
26+
# print(description)
27+
# print(start_date)
28+
# print(end_date)
29+
# print(flights)
30+
# print(attractions)
31+
# print("TEST ENDS HERE")
3332

3433
if validate_dates(start_date, end_date, flights):
3534
# Add the new itinerary after validation checks
@@ -42,10 +41,12 @@ def add_itinerary(itinerary_list, name, location, description, start_date, end_d
4241
"flights": flights,
4342
"attractions": attractions
4443
}
45-
print(new_itinerary)
44+
# Uncomment to print for itinerary validation:
45+
# print(new_itinerary)
4646

4747
itinerary_list.append(new_itinerary)
48-
print(itinerary_list)
48+
# Uncomment to print for itinerary_list validation:
49+
# print(itinerary_list)
4950

5051
save_itineraries(itinerary_list)
5152
return True
@@ -145,7 +146,8 @@ def edit_itinerary(itinerary_list, itinerary_option, edit_option, flight_choice,
145146
attraction.update({"tag(s)": attraction_tags})
146147
break
147148
save_itineraries(itinerary_list)
148-
print(itinerary_list)
149+
# Uncomment to print for itinerary_list validation:
150+
# print(itinerary_list)
149151
return True
150152

151153

@@ -159,7 +161,8 @@ def add_new_flight(itinerary_list, itinerary_name, new_flights):
159161
print(f"Duplicate flight detected: {flight["flight name"]}!")
160162
print("This flight will not be added.")
161163
save_itineraries(itinerary_list)
162-
print(itinerary_list)
164+
# Uncomment to print for itinerary_list validation:
165+
# print(itinerary_list)
163166
return True
164167

165168

@@ -173,7 +176,8 @@ def add_new_attraction(itinerary_list, itinerary_name, new_attractions):
173176
print(f"Duplicate attraction detected: {attraction["attraction name"]}!")
174177
print("This attraction will not be added.")
175178
save_itineraries(itinerary_list)
176-
print(itinerary_list)
179+
# Uncomment to print for itinerary_list validation:
180+
# print(itinerary_list)
177181
return True
178182

179183

@@ -208,15 +212,36 @@ def view_itineraries(itinerary_list):
208212
return True
209213

210214

211-
def delete_itinerary(chosen_itinerary):
212-
itinerary_list = load_itineraries()
213-
214-
print("What would you like to delete?")
215-
# Use pickpack module (https://github.com/anafvana/pickpack#map-function-for-nested-lists)
216-
pass
215+
def delete_itinerary(itinerary_list, itinerary_to_delete):
216+
for itinerary in itinerary_list:
217+
if itinerary["name"] == itinerary_to_delete:
218+
itinerary_list.remove(itinerary)
219+
save_itineraries(itinerary_list)
220+
# Uncomment to print for itinerary_list validation:
221+
# print(itinerary_list)
222+
return True
223+
return False
217224

218225

219-
# Print functions
226+
def delete_itinerary_item(itinerary_list, flights_or_attractions_type, itinerary_name, item_to_delete):
227+
for itinerary in itinerary_list:
228+
if itinerary["name"] == itinerary_name:
229+
if flights_or_attractions_type == "flights":
230+
for item in itinerary["flights"]:
231+
if item["flight name"] == item_to_delete:
232+
itinerary["flights"].remove(item)
233+
save_itineraries(itinerary_list)
234+
return True
235+
elif flights_or_attractions_type == "attractions":
236+
for item in itinerary["attractions"]:
237+
if item["attraction name"] == item_to_delete:
238+
itinerary["attractions"].remove(item)
239+
save_itineraries(itinerary_list)
240+
return True
241+
return False
242+
243+
244+
# Print rich table function
220245
def print_table(trips):
221246
trip_console = Console()
222247
trip_table = Table(title="Itineraries", show_lines=True)
@@ -233,14 +258,14 @@ def print_table(trips):
233258
flight_list = ''
234259
attraction_list = ''
235260
if len(trip["flights"]) == 1:
236-
flight_list = f'[bold red]{flight["flight name"]}[/bold red] \nDepart: {flight["departure date"]}\nArrive: {flight["arrival date"]} \n'
261+
flight_list = f'[bold red]{trip["flights"][0]["flight name"]}[/bold red] \nDepart: {trip["flights"][0]["departure date"]}\nArrive: {trip["flights"][0]["arrival date"]} \n'
237262
else:
238263
for flight in trip["flights"]:
239264
flight_item = f'[bold red]{flight["flight name"]}[/bold red] \nDepart: {flight["departure date"]}\nArrive: {flight["arrival date"]} \n'
240265
flight_list = flight_list + f'{flight_item}'
241266

242267
if len(trip["attractions"]) == 1:
243-
attraction_list = f'[bold red]{attraction["attraction name"]}[/bold red] \nAddress: {attraction["address"]} \nSummary: {attraction["summary"]} \nTag(s): {attraction["tag(s)"]}\n'
268+
attraction_list = f'[bold red]{trip["attractions"][0]["attraction name"]}[/bold red] \nAddress: {trip["attractions"][0]["address"]} \nSummary: {trip["attractions"][0]["summary"]} \nTag(s): {trip["attractions"][0]["tag(s)"]}\n'
244269
else:
245270
for attraction in trip["attractions"]:
246271
# Printing python text with colour using ANSI codes: https://vascosim.medium.com/how-to-print-colored-text-in-python-52f6244e2e30
@@ -252,7 +277,7 @@ def print_table(trips):
252277
return
253278

254279

255-
# Validation functions
280+
# Validate dates function
256281
def validate_dates(start_date, end_date, flights):
257282
"""
258283
Validate dates given for start date, end date and flight datetime
@@ -291,17 +316,3 @@ def validate_dates(start_date, end_date, flights):
291316
print("Error: Invalid date/time for flight arrival. Use 'DD-MM-YYYY HH:MM' format.")
292317
return False
293318
return True
294-
295-
296-
def find_itinerary(itinerary_list, trip_name):
297-
"""
298-
299-
Args:
300-
itinerary_list: List of all itineraries saved to itinerary.bin file.
301-
trip_name: Name of the trip user wants to view.
302-
303-
Returns:
304-
itinerary: The itinerary the user wants to view.
305-
"""
306-
trip = [itinerary for itinerary in itinerary_list if itinerary["name"] == trip_name]
307-
return trip

0 commit comments

Comments
 (0)