def test_update_order_method_updates_order_object(self): meal = MealItemFactory.build() new_meal = MealItemRepo().new_meal_item(meal.name, meal.image, meal.meal_type, meal.location_id) order = OrderFactory.build() new_order = self.repo.create_order( order.user_id, order.date_booked_for.strftime('%Y-%m-%d'), order.meal_item_orders, order.location_id, order.menu_id, order.channel, order.meal_period) update_meal_list = [new_meal] update_order = self.repo.update_order( order.user_id, order.date_booked_for.strftime('%Y-%m-%d'), new_order.date_booked.strftime('%Y-%m-%d'), update_meal_list) self.assertIsInstance(update_order, Order) self.assertEqual(new_order.user_id, order.user_id) self.assertEqual(update_order.meal_item_orders, update_meal_list)
class MenuRepo(BaseRepo): def __init__(self): BaseRepo.__init__(self, Menu) self.meal_repo = MealItemRepo() def new_menu(self, date, meal_period, main_meal_id, allowed_side, allowed_protein, side_items, protein_items, vendor_engagement_id, location_id): date = datetime.strptime(date, '%Y-%m-%d') meal_period = meal_period.lower() menu = Menu(date=date, meal_period=meal_period, main_meal_id=main_meal_id, allowed_side=allowed_side, allowed_protein=allowed_protein, side_items=','.join(str(item) for item in side_items), protein_items=','.join( str(item) for item in protein_items), vendor_engagement_id=vendor_engagement_id, location_id=location_id) menu.save() return menu def get_meal_items(self, meal_ids): meal_items = [] for id in meal_ids: item = self.meal_repo.get(id).serialize() meal_items.append(item) return meal_items def get_range_paginated_options(self, start_date, end_date, meal_period, location_id): return Menu.query.filter(Menu.date >= start_date, Menu.date <= end_date, Menu.meal_period == meal_period, Menu.is_deleted.is_(False), Menu.location_id == location_id).order_by( Menu.date.asc()).paginate(error_out=False)
def __init__(self, request): BaseController.__init__(self, request) self.order_repo = OrderRepo() self.meal_item_repo = MealItemRepo() self.andela_service = AndelaService() self.rating_repo = VendorRatingRepo()
class OrderController(BaseController): default_meal_item_return_fields = ['name', 'image', 'id', 'meal_type'] def __init__(self, request): BaseController.__init__(self, request) self.order_repo = OrderRepo() self.meal_item_repo = MealItemRepo() self.andela_service = AndelaService() self.rating_repo = VendorRatingRepo() def list_orders(self): """ List all orders in the application: should rarely be should :return: """ location_id = Auth.get_location() yesterday = date.today() - timedelta(days=1) tomorrow = date.today() + timedelta(days=1) orders = self.order_repo.get_range_paginated_options_all( start_date=yesterday, end_date=tomorrow, location_id=location_id) order_list = [] if len(orders.items) > 0: for order in orders.items: meal_items = self.order_repo.get(order.id).meal_item_orders try: user = self.andela_service.get_user_by_email_or_id( order.user_id) except Exception as e: return str(e) order_item = order.serialize() order_item['mealItems'] = [ item.to_dict( only=OrderController.default_meal_item_return_fields) for item in meal_items ] order_item['user'] = '******'.format( user['first_name'], user['last_name']) if user else None rating = self.order_repo.get_rating(user['id'], 'order', order.id) if user else None order_item['user_rating'] = rating order_list.append(order_item) return self.handle_response('OK', payload={ 'orders': order_list, 'meta': self.pagination_meta(orders) }) def list_orders_date(self, start_date): """ List all orders for a particular date :param start_date: :return: """ location_id = Auth.get_location() orders = self.order_repo.get_unpaginated(is_deleted=False, date_booked_for=start_date, location_id=location_id) order_list = [] if len(orders) > 0: for order in orders: meal_items = self.order_repo.get(order.id).meal_item_orders try: user = self.andela_service.get_user_by_email_or_id( order.user_id) except Exception as e: return str(e) order_item = order.serialize() order_item['mealItems'] = [ item.to_dict( only=OrderController.default_meal_item_return_fields) for item in meal_items ] order_item['user'] = '******'.format( user['first_name'], user['last_name']) if user else None rating = self.order_repo.get_rating(user['id'], 'order', order.id) if user else None order_item['user_rating'] = rating order_list.append(order_item) return self.handle_response('OK', payload={'orders': order_list}) def list_orders_date_range(self, start_date, end_date): """ List all orders for a particular date :param start_date: :param end_date: :return: """ location_id = Auth.get_location() orders = self.order_repo.get_range_paginated_options_all( start_date=start_date, end_date=end_date, location_id=location_id) order_list = [] if len(orders.items) > 0: for order in orders.items: meal_items = self.order_repo.get(order.id).meal_item_orders try: user = self.andela_service.get_user_by_email_or_id( order.user_id) except Exception as e: return str(e) order_item = order.serialize() order_item['mealItems'] = [ item.to_dict( only=OrderController.default_meal_item_return_fields) for item in meal_items ] order_item['user'] = '******'.format( user['first_name'], user['last_name']) if user else None rating = self.order_repo.get_rating(user['id'], 'order', order.id) if user else None order_item['user_rating'] = rating order_list.append(order_item) return self.handle_response('OK', payload={'orders': order_list}) def get_order(self, order_id): """ Gets all orders for an order_id :param order_id: :return: """ order = self.order_repo.get(order_id) if order: order_serialized = order.serialize() order_serialized['mealItems'] = [ item.to_dict( only=OrderController.default_meal_item_return_fields) for item in order.meal_item_orders ] try: user = self.andela_service.get_user_by_email_or_id( order.user_id) except Exception as e: return str(e) order_serialized['user'] = '******'.format( user['first_name'], user['last_name']) if user else None rating = self.order_repo.get_rating(user['id'], 'order', order.id) if user else None order_serialized['user_rating'] = rating return self.handle_response('OK', payload={'order': order_serialized}) return self.handle_response('Order not found', status_code=400) def get_order_by_user_id(self, user_id): """ Gets all orders for a user by the user id :param user_id: :return: list of orders in json model """ orders = self.order_repo.filter_by(user_id=user_id, is_deleted=False) orders_list = [] if len(orders.items) > 0: for order in orders.items: meal_items = self.order_repo.get(order.id).meal_item_orders try: user = self.andela_service.get_user_by_email_or_id( order.user_id) except Exception as e: return str(e) order_item = order.serialize() order_item['mealItems'] = [ item.to_dict( only=OrderController.default_meal_item_return_fields) for item in meal_items ] order_item['user'] = '******'.format( user['first_name'], user['last_name']) if user else None rating = self.order_repo.get_rating(user['id'], 'order', order.id) if user else None order_item['user_rating'] = rating orders_list.append(order_item) return self.handle_response('OK', payload={'orders': orders_list}) def get_order_by_user_id_date_range(self, user_id, start_date, end_date): """ :param user_id: :param start_date: :param end_date: :return: """ orders = self.order_repo.get_range_paginated_options( user_id=user_id, start_date=start_date, end_date=end_date) order_list = [] if len(orders.items) > 0: for order in orders.items: meal_items = self.order_repo.get(order.id).meal_item_orders user = self.andela_service.get_user_by_email_or_id( order.user_id) order_item = order.serialize() order_item['mealItems'] = [ item.to_dict( only=OrderController.default_meal_item_return_fields) for item in meal_items ] order_item['user'] = '******'.format( user['first_name'], user['last_name']) if user else None rating = self.order_repo.get_rating(user['id'], 'order', order.id) if user else None order_item['user_rating'] = rating order_list.append(order_item) return self.handle_response('OK', payload={'orders': order_list}) def create_order(self): """ creates an order :return: order object """ user_id = Auth.user('id') location_id = Auth.get_location() date_booked_for, channel, meal_period, meal_items, menu_id = self.request_params( 'dateBookedFor', 'channel', 'mealPeriod', 'mealItems', 'menuId') if self.order_repo.user_has_order(user_id, date_booked_for, meal_period): return self.handle_response( 'You have already booked for this meal period.', status_code=400) location = LocationRepo().get(location_id) current_time = current_time_by_zone(location.zone) if datetime.strptime(date_booked_for, "%Y-%m-%d") < datetime.now(): return self.handle_response( 'You are not allowed to book for a date in the past', status_code=400) if int(current_time_by_zone(location.zone).strftime('%H')) > 15: if check_date_current_vs_date_for( current_time, datetime.strptime(date_booked_for, "%Y-%m-%d")): return self.handle_response( 'It is too late to book a meal for the selected date ', status_code=400) meal_object_items = self.meal_item_repo.get_meal_items_by_ids( meal_items) new_order = self.order_repo.create_order(user_id, date_booked_for, meal_object_items, location_id, menu_id, channel, meal_period).serialize() new_order['mealItems'] = [ item.to_dict(only=OrderController.default_meal_item_return_fields) for item in meal_object_items ] return self.handle_response('OK', payload={'order': new_order}, status_code=201) def update_order(self, order_id): """ updates an order based on the order Id :param order_id: :return: """ date_booked_for, channel, meal_items, menu_id = self.request_params( 'dateBookedFor', 'channel', 'mealItems', 'menuId') meal_object_items = [] for meal_item_id in meal_items: meal_item = self.meal_item_repo.get(meal_item_id) meal_object_items.append(meal_item) order = self.order_repo.get(order_id) if order: if order.is_deleted: return self.handle_response('Order has already been deleted', status_code=400) updates = {} if date_booked_for: order_date_midnight = datetime.strptime( date_booked_for, '%Y-%m-%d').replace(hour=00).replace( minute=00).replace(second=00) current_time = datetime.now() if order_date_midnight - current_time < timedelta( 'hours' == 7): return self.handle_response( 'It is too late to book meal for the selected date ', status_code=400) updates['date_booked_for'] = datetime.strptime( date_booked_for, '%Y-%m-%d') if menu_id: updates['menu_id'] = menu_id if channel: updates['channel'] = channel if meal_items: updates['meal_item_orders'] = meal_object_items updated_order = self.order_repo.update(order, **updates).serialize() updated_order['mealItems'] = [ item.to_dict( only=OrderController.default_meal_item_return_fields) for item in order.meal_item_orders ] return self.handle_response('OK', payload={'order': updated_order}) return self.handle_response('Invalid or incorrect order_id provided', status_code=400) def collect_order(self): """ Collects order and mark as collected for a user Id :param user_id: :param order_type: :param order_date: :return: """ user_id, order_type, order_date = self.request_params( 'userId', 'orderType', 'orderDate') order = self.order_repo.find_first(user_id=user_id, meal_period=order_type, date_booked_for=order_date, is_deleted=False) if not order: return self.handle_response( f'User has no {order_type} order for the date.', status_code=400) if order.order_status == OrderStatus.collected: return self.handle_response('Order already collected', status_code=400) updates = {} updates['order_status'] = OrderStatus.collected self.order_repo.update(order, **updates) return self.handle_response('Order successfully collected', payload={'order': order.serialize()}) def check_order(self): """ Checks if a user has an order for a particular date and period :return: """ user_id, order_type, order_date = self.request_params( 'userId', 'orderType', 'orderDate') # get user_id from another method and reform to db's user id order = self.order_repo.find_first(user_id=user_id, meal_period=order_type, date_booked_for=order_date, is_deleted=False) if not order: return self.handle_response( f'User has no {order_type} order for this date') return self.handle_response('OK', payload={'order': order.serialize()}) def delete_order(self, order_id): order = self.order_repo.get(order_id) if order: if order.is_deleted: return self.handle_response('Order has already been deleted', status_code=400) if Auth.user('id') != order.user_id: return self.handle_response( 'You cannot delete an order that is not yours', status_code=403) updates = {} updates['is_deleted'] = True self.order_repo.update(order, **updates) return self.handle_response('Order deleted', payload={"status": "success"}) return self.handle_response('Invalid or incorrect order_id provided', status_code=400)
def __init__(self, request): BaseController.__init__(self, request) self.menu_repo = MenuRepo() self.meal_repo = MealItemRepo()
class MenuController(BaseController): '''Menu controller class''' def __init__(self, request): BaseController.__init__(self, request) self.menu_repo = MenuRepo() self.meal_repo = MealItemRepo() def create_menu(self): ''' params are gotten from request object :return: json object with status of menu created with menu ''' location_id = Auth.get_location() date, meal_period, main_meal_id, allowed_side,\ allowed_protein, side_items, protein_items,\ vendor_engagement_id = self.request_params( 'date', 'mealPeriod', 'mainMealId', 'allowedSide', 'allowedProtein', 'sideItems', 'proteinItems', 'vendorEngagementId' ) if self.menu_repo.get_unpaginated(date=date, main_meal_id=main_meal_id, location_id=location_id): return self.handle_response( 'You can\'t create multiple menus with same main item on the same day', status_code=400) menu = self.menu_repo.new_menu(date, meal_period, main_meal_id, allowed_side, allowed_protein, side_items, protein_items, vendor_engagement_id, location_id).serialize() menu['mainMeal'] = self.meal_repo.get(main_meal_id).serialize() menu['proteinItems'] = self.menu_repo.get_meal_items(protein_items) menu['sideItems'] = self.menu_repo.get_meal_items(side_items) return self.handle_response('OK', payload={'menu': menu}, status_code=201) def delete_menu(self, menu_id): ''' :param menu_id: id of the menu :return: json object ''' menu = self.menu_repo.get(menu_id) updates = {} if menu: if menu.is_deleted: return self.handle_response('Menu has already been deleted', status_code=400) updates['is_deleted'] = True self.meal_repo.update(menu, **updates) return self.handle_response('Menu deleted', payload={"status": "success"}) return self.handle_response('Invalid or incorrect menu_id provided', status_code=400) def list_menus(self, menu_period, menu_date): '''retrieves a list of menus for a specific date for a specific meal period. date fornat: "YYYY-MM-DD" meal period: breakfast or lunch menu_date: date of request ''' location_id = Auth.get_location() if MealPeriods.has_value(menu_period): menus = self.menu_repo.get_unpaginated(date=menu_date, meal_period=menu_period, is_deleted=False, location_id=location_id) menu_list = defaultdict(list) for menu in menus: serialised_menu = menu.serialize() arr_protein = menu.protein_items.split(",") arr_side = menu.side_items.split(",") serialised_menu['mainMeal'] = self.meal_repo.get( menu.main_meal_id).serialize() serialised_menu[ 'proteinItems'] = self.menu_repo.get_meal_items( arr_protein) serialised_menu['sideItems'] = self.menu_repo.get_meal_items( arr_side) menu_list[serialised_menu['date'].strftime('%Y-%m-%d')].append( serialised_menu) grouped = [{ 'date': date, 'menus': menus } for date, menus in menu_list.items()] return self.handle_response('OK', payload={ 'dateOfMeal': menu_date, 'mealPeriod': menu_period, 'menuList': grouped }) return self.handle_response('Provide valid meal period and date', status_code=404) def list_menus_range_admin(self, menu_period, menu_start_date, menu_end_date): """retrieves a list of menus for a specific date range for a specific meal period. date fornat: "YYYY-MM-DD" meal period: breakfast or lunch menu_start_date: start date of search menu_end_date: end date of search """ location_id = Auth.get_location() if MealPeriods.has_value(menu_period): menu_start_date = datetime.strptime(menu_start_date, '%Y-%m-%d') menu_end_date = datetime.strptime(menu_end_date, '%Y-%m-%d') if menu_start_date >= menu_end_date: return self.handle_response( 'Provide valid date range. start_date cannot be greater than end_date', status_code=400) menus = self.menu_repo.get_range_paginated_options( start_date=menu_start_date, end_date=menu_end_date, meal_period=menu_period, location_id=location_id) menu_list = [] for menu in menus.items: serialised_menu = menu.serialize() arr_protein = [ int(prot_id) for prot_id in menu.protein_items.split(',') ] arr_side = [ int(side_id) for side_id in menu.side_items.split(',') ] serialised_menu['mainMeal'] = self.meal_repo.get( menu.main_meal_id).serialize() serialised_menu[ 'proteinItems'] = self.menu_repo.get_meal_items( arr_protein) serialised_menu['sideItems'] = self.menu_repo.get_meal_items( arr_side) menu_list.append(serialised_menu) return self.handle_response('OK', payload={ 'startDateOfSearch': menu_start_date, 'endDateOfSearch': menu_end_date, 'mealPeriod': menu_period, 'meta': self.pagination_meta(menus), 'menuList': menu_list }) return self.handle_response('Provide valid meal period and date range', status_code=400) def list_menus_range(self, menu_period, menu_start_date, menu_end_date): """retrieves a list of menus for a specific date range for a specific meal period. date fornat: "YYYY-MM-DD" meal period: breakfast or lunch menu_start_date: start date of search menu_end_date: end date of search """ location_id = Auth.get_location() if MealPeriods.has_value(menu_period): menu_start_date = datetime.strptime(menu_start_date, '%Y-%m-%d') menu_end_date = datetime.strptime(menu_end_date, '%Y-%m-%d') if menu_start_date >= menu_end_date: return self.handle_response( 'Provide valid date range. start_date cannot be greater than end_date', status_code=400) menus = self.menu_repo.get_range_paginated_options( start_date=menu_start_date, end_date=menu_end_date, meal_period=menu_period, location_id=location_id) menu_list = defaultdict(list) for menu in menus.items: serialised_menu = menu.serialize() arr_protein = [ int(prot_id) for prot_id in menu.protein_items.split(',') ] arr_side = [ int(side_id) for side_id in menu.side_items.split(',') ] serialised_menu['mainMeal'] = self.meal_repo.get( menu.main_meal_id).serialize() serialised_menu[ 'proteinItems'] = self.menu_repo.get_meal_items( arr_protein) serialised_menu['sideItems'] = self.menu_repo.get_meal_items( arr_side) menu_list[serialised_menu['date'].strftime('%Y-%m-%d')].append( serialised_menu) grouped = [{ 'date': date, 'menus': menus } for date, menus in menu_list.items()] return self.handle_response('OK', payload={ 'startDateOfSearch': menu_start_date, 'endDateOfSearch': menu_end_date, 'mealPeriod': menu_period, 'meta': self.pagination_meta(menus), 'menuList': grouped }) return self.handle_response('Provide valid meal period and date range', status_code=400) def update_menu(self, menu_id): ''' :param menu_id: id of menu record :params other params sent via request_param :return: ''' date, meal_period, main_meal_id, allowed_side,\ allowed_protein, side_items, protein_items,\ vendor_engagement_id = self.request_params( 'date', 'mealPeriod', 'mainMealId', 'allowedSide', 'allowedProtein', 'sideItems', 'proteinItems', 'vendorEngagementId' ) menu = self.menu_repo.get(menu_id) if menu: if menu.is_deleted: return self.handle_response('This menu is already deleted', status_code=400) updates = {} if date: updates['date'] = datetime.strptime(date, '%Y-%m-%d') if meal_period: updates['meal_period'] = meal_period if main_meal_id: updates['main_meal_id'] = main_meal_id if allowed_side: updates['allowed_side'] = allowed_side if allowed_protein: updates['allowed_protein'] = allowed_protein if side_items: updates['side_items'] = ','.join( str(item) for item in side_items) if protein_items: updates['protein_items'] = ','.join( str(item) for item in protein_items) if vendor_engagement_id: updates['vendor_engagement_id'] = vendor_engagement_id updated_menu = self.menu_repo.update(menu, **updates) prot_items = [ int(prot_id) for prot_id in updated_menu.protein_items.split(',') ] sid_items = [ int(side_id) for side_id in updated_menu.side_items.split(',') ] menu = updated_menu.serialize() menu['mainMeal'] = self.meal_repo.get( updated_menu.main_meal_id).serialize() menu['proteinItems'] = self.menu_repo.get_meal_items(prot_items) menu['sideItems'] = self.menu_repo.get_meal_items(sid_items) return self.handle_response('OK', payload={'menu': menu}, status_code=200) return self.handle_response('This menu_id does not exist', status_code=404)
class MealItemController(BaseController): def __init__(self, request): BaseController.__init__(self, request) self.meal_repo = MealItemRepo() def list_meals(self): query_kwargs = self.get_params_dict() location_id = Auth.get_location() meals = self.meal_repo.get_unpaginated_asc(self.meal_repo._model.name, is_deleted=False, location_id=location_id, **query_kwargs) meals_list = [meal.serialize() for meal in meals] return self.handle_response('OK', payload={'mealItems': meals_list}) def list_meals_page(self, page_id, meals_per_page): location_id = Auth.get_location() meals = self.meal_repo.filter_by(page=page_id, per_page=meals_per_page, location_id=location_id) meals_list = [meal.serialize() for meal in meals.items] return self.handle_response('OK', payload={ 'mealItems': meals_list, 'meta': self.pagination_meta(meals) }) def get_meal(self, meal_id): meal = self.meal_repo.get(meal_id) if meal: if meal.is_deleted: return self.handle_response( 'Bad Request. This meal item is deleted', status_code=400) meal = meal.serialize() return self.handle_response('OK', payload={'mealItem': meal}) else: return self.handle_response( 'Bad Request. This meal id does not exist', status_code=400) def create_meal(self): """ Creates a new meal item """ location_id = Auth.get_location() name, image_url, meal_type = self.request_params( 'mealName', 'image', 'mealType') if self.meal_repo.get_unpaginated(name=name, location_id=location_id): return self.handle_response( 'Meal item with this name already exists', status_code=400) if MealTypes.has_value(meal_type): new_meal_item = self.meal_repo.new_meal_item( name, image_url, meal_type, location_id).serialize() return self.handle_response('OK', payload={'mealItem': new_meal_item}, status_code=201) return self.handle_response( 'Invalid meal type. Must be main, protein or side', status_code=400) def update_meal(self, meal_id): name, image_url, meal_type = self.request_params( 'mealName', 'image', 'mealType') meal = self.meal_repo.get(meal_id) if meal: if meal.is_deleted: return self.handle_response( 'Bad Request. This meal item is deleted', status_code=400) updates = {} if name: if self.meal_repo.get_unpaginated(name=name): return self.handle_response( 'Meal item with this name already exists', status_code=400) updates['name'] = name if image_url: updates['image'] = image_url if meal_type and MealTypes.has_value(meal_type): updates['meal_type'] = meal_type self.meal_repo.update(meal, **updates) return self.handle_response('OK', payload={'mealItem': meal.serialize()}) return self.handle_response('Invalid or incorrect meal_id provided', status_code=400) def delete_meal(self, meal_id): meal = self.meal_repo.get(meal_id) updates = {} if meal: if meal.is_deleted: return self.handle_response( 'Bad Request. This meal item is deleted', status_code=400) updates['is_deleted'] = True self.meal_repo.update(meal, **updates) return self.handle_response('OK', payload={"status": "success"}) return self.handle_response('Invalid or incorrect meal_id provided', status_code=400)
def __init__(self): BaseRepo.__init__(self, Order) self.meal_item_repo = MealItemRepo()
def __init__(self): BaseRepo.__init__(self, Menu) self.meal_repo = MealItemRepo()