def __init__(self, request):
     BaseController.__init__(self, request)
     self.vendor_rating_repo = VendorRatingRepo()
     self.vendor_repo = VendorRepo()
     self.vendor_engagement_repo = VendorEngagementRepo()
     self.menu_repo = MenuRepo()
     self.meal_repo = MealItemRepo()
     self.order_repo = OrderRepo()
Ejemplo n.º 2
0
 def __init__(self, request):
     BaseController.__init__(self, request)
     self.rating_repo = VendorRatingRepo()
     self.order_repo = OrderRepo()
     self.engagement_repo = VendorEngagementRepo()
     self.vendor_repo = VendorRepo()
     self.user_repo = UserRepo()
     self.session_repo = MealSessionRepo()
Ejemplo n.º 3
0
 def __init__(self, request):
     BaseController.__init__(self, request)
     self.slackhelper = SlackHelper()
     self.menu_repo = MenuRepo()
     self.meal_repo = MealItemRepo()
     self.engagement_repo = VendorEngagementRepo()
     self.andela_service = AndelaService()
     self.vendor_rating_repo = VendorRatingRepo()
Ejemplo n.º 4
0
class TestVendorRepo(BaseTestCase):
    def setUp(self):
        self.BaseSetUp()
        self.repo = VendorRepo()
        self.rating_repo = VendorRatingRepo()
        self.location = LocationFactory()

    def tearDown(self):
        self.BaseTearDown()

    def test_new_vendor_method_returns_new_vendor_object(self):
        vendor = VendorFactory.build(location_id=self.location.id)
        new_vendor = self.repo.new_vendor(vendor.name, vendor.address,
                                          vendor.tel, vendor.is_active,
                                          vendor.contact_person,
                                          vendor.location_id)

        self.assertIsInstance(new_vendor, Vendor)
        self.assertEqual(vendor.name, new_vendor.name)
        self.assertEqual(vendor.tel, new_vendor.tel)
        self.assertEqual(vendor.address, new_vendor.address)
        self.assertEqual(vendor.contact_person, new_vendor.contact_person)
        self.assertIsNot(new_vendor.id, 0)

    def test_update_vendor_rating(self):
        vendor = VendorFactory.build(location_id=self.location.id)
        new_vendor = self.repo.new_vendor(vendor.name, vendor.address,
                                          vendor.tel, vendor.is_active,
                                          vendor.contact_person,
                                          vendor.location_id)

        engagement = VendorEngagementFactory(location_id=self.location.id,
                                             vendor_id=vendor.id,
                                             vendor=vendor)

        vendor_rating = VendorRatingFactory.build()
        main_meal_id = MealItemFactory.create().id
        vendor_rating = VendorRatingFactory.build(vendor_id=vendor.id,
                                                  engagement_id=engagement.id)
        self.rating_repo.new_rating(
            new_vendor.id, vendor_rating.user_id, 4,
            vendor_rating.service_date, vendor_rating.rating_type,
            vendor_rating.type_id, vendor_rating.engagement_id, main_meal_id,
            vendor_rating.channel, vendor_rating.comment)

        self.repo.update_vendor_average_rating(new_vendor.id)

        self.assertEqual(new_vendor.average_rating, 4)
Ejemplo n.º 5
0
 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 VendorRatingController(BaseController):
    def __init__(self, request):
        BaseController.__init__(self, request)
        self.vendor_rating_repo = VendorRatingRepo()
        self.vendor_repo = VendorRepo()
        self.vendor_engagement_repo = VendorEngagementRepo()
        self.menu_repo = MenuRepo()
        self.meal_repo = MealItemRepo()
        self.order_repo = OrderRepo()

    def list_ratings(self, date):
        """retrieves a list of all ratings"""
        query_kwargs = self.get_params_dict()
        date = datetime.strptime(date, '%Y-%m-%d')

        ratings = self.vendor_rating_repo.filter_by(service_date=date,
                                                    **query_kwargs)
        if ratings.items:
            result = []
            vendor_name = self.vendor_repo.get(ratings.items[0].vendor_id).name

            for rating in ratings.items:
                if not rating.main_meal_id:
                    continue

                meal_name = self.meal_repo.get(rating.main_meal_id).name

                if meal_name not in [item.get('mainMeal') for item in result]:
                    meal_rating = {
                        'mainMeal':
                        meal_name,
                        'overallRating':
                        self.vendor_rating_repo.meal_average(
                            rating.main_meal_id, date),
                        'items': [
                            rtng.serialize() for rtng in ratings.items
                            if rtng.main_meal_id == rating.main_meal_id
                        ]
                    }
                    result.append(meal_rating)

            return self.handle_response('OK',
                                        payload={
                                            'date': date,
                                            'vendor': vendor_name,
                                            'result': result
                                        })
        return self.handle_response('No ratings for this date',
                                    status_code=404)

    def get_vendor_rating(self, rating_id):
        """retrieves the details of a specific rating, giving the rating id"""
        rating = self.vendor_rating_repo.get(rating_id)
        if rating:
            rtng = rating.serialize()

            return self.handle_response('OK', payload={'rating': rtng})
        else:
            return self.handle_response('Bad Request', status_code=400)

    def create_vendor_rating(self):
        '''Adds a vendor rating during a specific engagement'''
        (comment, rating, service_date, channel,
         engagement_id) = self.request_params('comment', 'rating',
                                              'serviceDate', 'channel',
                                              'engagementId')
        main_meal_id = None
        user_id = Auth.user('id')
        vendor_id = self.vendor_engagement_repo.get(engagement_id).vendor_id

        if self.vendor_repo.get(vendor_id):

            service_date = datetime.strptime(service_date, '%Y-%m-%d')

            rating = self.vendor_rating_repo.new_rating(
                vendor_id, user_id, rating, service_date,
                RatingType.engagement, engagement_id, engagement_id,
                main_meal_id, channel, comment)
            self.vendor_repo.update_vendor_average_rating(vendor_id)
            rtng = rating.serialize()

            return self.handle_response('Rating created',
                                        payload={'rating': rtng},
                                        status_code=201)

        return self.handle_response('Invalid vendor_id provided',
                                    status_code=400)

    def create_order_rating(self):
        """Adds a order or meal rating during a specific engagement """

        (order_id, main_meal_id, engagement_id, comment, rating, service_date,
         channel) = self.request_params('orderId', 'mainMealId',
                                        'engagementId', 'comment', 'rating',
                                        'serviceDate', 'channel')
        if not (1 <= rating <= 5):
            return self.handle_response(
                'Rating must be between 1 and 5, inclusive.', status_code=400)

        user_id = Auth.user('id')
        if not self.meal_repo.get(main_meal_id):
            return self.handle_response('Meal item with this id not found',
                                        status_code=400)
        engagement = self.vendor_engagement_repo.get(engagement_id)
        if not engagement:
            return self.handle_response('Engagement with this id is not found',
                                        status_code=400)
        vendor_id = engagement.vendor_id
        if order_id:
            rating_type = RatingType.order
            type_id = order_id
            order = self.order_repo.get(order_id)
            if not order:
                return self.handle_response('Order with this id is not found',
                                            status_code=400)
            if order.has_rated:
                return self.handle_response('This order has been rated',
                                            status_code=400)

        else:
            if (datetime.now() -
                    datetime.strptime(service_date, '%Y-%m-%d')).days < 1:
                return self.handle_response(
                    'You can only rate meals of past days.', status_code=400)
            rating_type = RatingType.meal
            type_id = main_meal_id
            user_meal_rating = self.vendor_rating_repo.get_unpaginated(
                user_id=user_id, type_id=type_id, rating_type='meal')
            if user_meal_rating:
                return self.handle_response('You have already rated this meal',
                                            status_code=400)

        rating = self.vendor_rating_repo.new_rating(
            vendor_id, user_id, rating,
            datetime.strptime(service_date, '%Y-%m-%d'), rating_type, type_id,
            engagement_id, main_meal_id, channel, comment)

        self.vendor_repo.update_vendor_average_rating(vendor_id)
        if rating.id and rating_type == RatingType.order:
            updates = {'has_rated': True}
            self.order_repo.update(order, **updates)

        rating_obj = rating.serialize()
        return self.handle_response('Rating successful',
                                    payload={'rating': rating_obj},
                                    status_code=201)

    def update_vendor_rating(self, rating_id):
        """edits an existing rating"""

        rtng = self.vendor_rating_repo.get(rating_id)
        comment = self.get_json()['comment']
        if rtng:
            if Auth.user(
                    'id'
            ) == rtng.user_id:  #You cannot update someone else's rating

                updates = {}
                if comment:
                    updates['comment'] = comment
                self.vendor_rating_repo.update(rtng, **updates)
                return self.handle_response(
                    'OK', payload={'rating': rtng.serialize()})
            return self.handle_response(
                'You are not allowed to update a rating that is not yours',
                status_code=403)
        return self.handle_response('Invalid or incorrect rating_id provided',
                                    status_code=404)
Ejemplo n.º 7
0
class BotController(BaseController):
    def __init__(self, request):
        BaseController.__init__(self, request)
        self.slackhelper = SlackHelper()
        self.menu_repo = MenuRepo()
        self.meal_repo = MealItemRepo()
        self.engagement_repo = VendorEngagementRepo()
        self.andela_service = AndelaService()
        self.vendor_rating_repo = VendorRatingRepo()

    def bot(self):
        locations = LocationRepo().fetch_all()
        location_buttons = [{
            'name': 'location',
            'text': f'{location.name}',
            'type': "button",
            'value': location.id
        } for location in locations.items]

        request_buttons = [{
            "text": "",
            "callback_id": "center_selector",
            "color": "#3AA3E3",
            "attachment_type": "default",
            "actions": location_buttons
        }]

        return self.handle_response(slack_response={
            'text': f'Welcome To Andela Eats',
            'attachments': request_buttons
        })

    def interactions(self):
        request_payload, trigger_id = self.post_params('payload', 'trigger_id')
        payload = json.loads(request_payload)

        webhook_url = payload["response_url"]
        slack_id = payload['user']['id']

        if payload['type'] == 'dialog_submission':
            slack_user_info = self.slackhelper.user_info(slack_id)
            slack_user_email = slack_user_info['user']['profile']['email']

            if payload['callback_id'] == 'final_selection':

                state = payload['state'].split('_')
                menu_id = state[0]
                meal_period = state[1]
                date_booked_for = state[2]
                location_id = state[4]
                submitted_values = payload['submission']
                meal_items = [int(v) for k, v in submitted_values.items()]
                meal_items.append(MenuRepo().get(menu_id).main_meal_id)
                meal_items = [
                    meal for meal in MealItemRepo().get_meal_items_by_ids(
                        meal_items)
                ]
                channel = 'slack'

                # Retrieve User Object
                user = self.andela_service.get_user_by_email_or_id(
                    slack_user_email)
                user_id = user['id']

                order = OrderRepo().create_order(
                    user_id=user_id,
                    date_booked_for=date_booked_for,
                    meal_items=meal_items,
                    location_id=location_id,
                    menu_id=menu_id,
                    channel=channel,
                    meal_period=meal_period)

                if order:
                    slack_data = {'text': 'Booking Confirmed!'}
                    requests.post(webhook_url,
                                  data=json.dumps(slack_data),
                                  headers={'Content-Type': 'application/json'})
                else:
                    slack_data = {'text': 'Booking Failed. Please Retry'}
                    requests.post(webhook_url,
                                  data=json.dumps(slack_data),
                                  headers={'Content-Type': 'application/json'})

            if payload['callback_id'] == 'submit_rating':

                state = payload['state'].split('_')
                menu_id = state[0]
                menu = self.menu_repo.get(menu_id)
                service_date = menu.date
                rating_type = RatingType.meal
                type_id = menu.main_meal_id
                engagement_id = menu.vendor_engagement_id
                vendor_id = self.engagement_repo.get(engagement_id).vendor_id
                rating_value = payload['submission']['rating value']
                channel = 'slack'
                comment = payload['submission']['comment']

                # Retrieve User Object
                user = self.andela_service.get_user_by_email_or_id(
                    slack_user_email)
                user_id = user['id']

                rating = self.vendor_rating_repo.new_rating(
                    vendor_id, user_id, rating_value, service_date,
                    rating_type, type_id, engagement_id, channel, comment,
                    type_id)

                if rating:
                    slack_data = {'text': 'Rating Successful!'}
                    requests.post(webhook_url,
                                  data=json.dumps(slack_data),
                                  headers={'Content-Type': 'application/json'})
                else:
                    slack_data = {'text': 'Rating Failed. Please Retry'}
                    requests.post(webhook_url,
                                  data=json.dumps(slack_data),
                                  headers={'Content-Type': 'application/json'})

            return make_response('', 200)

        if payload['type'] == 'interactive_message' and payload[
                'callback_id'] == 'center_selector':
            location_id = payload['actions'][0]['value']

            location = LocationRepo().get(location_id)
            menu_start_end_on = BotController.get_menu_start_end_on(location)
            start_on = menu_start_end_on[0]
            end_on = menu_start_end_on[1]

            date_buttons = [{
                'name':
                'selected_date',
                'type':
                'button',
                'text':
                '{}, {}'.format(day.strftime('%a'), day.strftime('%b %-d')),
                'value':
                '{}_{}'.format(day.strftime('%Y-%m-%d'), location.id)
            } for day in daterange(start_on, end_on)]

            request_buttons = [{
                "text": "",
                "callback_id": "day_selector",
                "color": "#3AA3E3",
                "attachment_type": "default",
                "actions": date_buttons
            }]

            return self.handle_response(slack_response={
                'text': f'Select Date',
                'attachments': request_buttons
            })

        if payload['type'] == 'interactive_message' and payload[
                'callback_id'] == 'day_selector':
            payload_action_value = payload['actions'][0]['value']
            selected_date = payload_action_value.split('_')[0]
            location_id = payload_action_value.split('_')[1]

            period_buttons = [
                # {'name': 'meal_period', 'type': 'button', 'text': 'Breakfast',
                #  'value': 'breakfast_{}'.format(payload_action_value)},
                {
                    'name': 'meal_period',
                    'type': 'button',
                    'text': 'Lunch',
                    'value': 'lunch_{}'.format(payload_action_value)
                }
            ]

            request_buttons = [{
                "text": "",
                "callback_id": "period_selector",
                "color": "#3AA3E3",
                "attachment_type": "default",
                "actions": period_buttons
            }]

            return self.handle_response(slack_response={
                'text': f'Select Meal Period',
                'attachments': request_buttons
            })

        if payload['type'] == 'interactive_message' and payload[
                'callback_id'] == 'period_selector':
            period = payload['actions'][0]['value'].split('_')[0]
            date = payload['actions'][0]['value'].split('_')[1]
            location_id = payload['actions'][0]['value'].split('_')[2]
            actions = {
                "attachments": [{
                    "text":
                    'What do you want to do?',
                    "callback_id":
                    "action_selector",
                    "color":
                    "#3AA3E3",
                    "attachment_type":
                    "default",
                    "actions": [{
                        "name": "main meal",
                        "text": "View Menu List",
                        "type": "button",
                        "value": f'{period}_{date}_menu_{location_id}'
                    }, {
                        "name": "main meal",
                        "text": "Place order",
                        "type": "button",
                        "value": f'{period}_{date}_order_{location_id}'
                    }]
                }]
            }
            return self.handle_response(slack_response=actions)

        if payload['type'] == 'interactive_message' and payload[
                'callback_id'] == 'action_selector':
            payload_action_value = payload['actions'][0]['value']
            if payload_action_value.split('_')[2] == 'menu':
                date = payload_action_value.split('_')[1]
                period = payload_action_value.split('_')[0]
                location_id = payload_action_value.split('_')[3]
                menus = self.menu_repo.get_unpaginated(date=date,
                                                       meal_period=period,
                                                       is_deleted=False)
                if not menus:
                    #   No Menu for provided date
                    back_buttons = [{
                        'name': 'back',
                        'text': 'Back',
                        'type': "button",
                        'value': location_id
                    }]
                    request_buttons = [{
                        "text": "",
                        "callback_id": "center_selector",
                        "color": "#3AA3E3",
                        "attachment_type": "default",
                        "actions": back_buttons
                    }]
                    return self.handle_response(
                        slack_response={
                            'text':
                            f'Sorry No Menu found for Date: {date}, Meal Period: {period}',
                            'attachments': request_buttons
                        })
                text = ''

                for menu in menus:
                    side_items_list = menu.side_items.split(',')
                    protein_items_list = menu.protein_items.split(',')

                    main = self.meal_repo.get(menu.main_meal_id).name
                    sides = [
                        side.name for side in
                        self.meal_repo.get_meal_items_by_ids(side_items_list)
                    ]
                    proteins = [
                        protein.name
                        for protein in self.meal_repo.get_meal_items_by_ids(
                            protein_items_list)
                    ]
                    menu_info = f'Main meal: *{main}*\n Side items: {", ".join(sides)}\nProtein items: {", ".join(proteins)}\n\n\n'
                    text += menu_info

                meals = {
                    "text":
                    f'{period.upper()}',
                    "attachments": [{
                        "text":
                        text,
                        "callback_id":
                        "after_menu_list",
                        "color":
                        "#3AA3E3",
                        "attachment_type":
                        "default",
                        "actions": [{
                            "name":
                            "main meal",
                            "text":
                            "Rate meal",
                            "type":
                            "button",
                            "value":
                            f'{period}_{date}_rate_{location_id}_{location_id}'
                        }, {
                            "name":
                            "main meal",
                            "text":
                            "Place an order",
                            "type":
                            "button",
                            "value":
                            f'{period}_{date}_order_{location_id}_{location_id}'
                        }]
                    }]
                }
                return self.handle_response(slack_response=meals)

        if (payload['type'] == 'interactive_message'
                and payload['callback_id'] == 'action_selector'
                and payload['actions'][0]['value'].split('_')[2] == 'order'
            ) or (payload['callback_id'] == 'after_menu_list'
                  and payload['actions'][0]['value'].split('_')[2] == 'order'):
            payload_action_value = payload['actions'][0]['value']
            meal_period = payload_action_value.split('_')[0]
            selected_date = payload_action_value.split('_')[1]
            location_id = payload_action_value.split('_')[3]
            menus = self.menu_repo.get_unpaginated(date=selected_date,
                                                   meal_period=meal_period,
                                                   is_deleted=False)
            if not menus:
                #   No Menu for provided date
                back_buttons = [{
                    'name': 'back',
                    'text': 'Back',
                    'type': "button",
                    'value': location_id
                }]

                request_buttons = [{
                    "text": "",
                    "callback_id": "center_selector",
                    "color": "#3AA3E3",
                    "attachment_type": "default",
                    "actions": back_buttons
                }]
                return self.handle_response(
                    slack_response={
                        'text':
                        f'Sorry No Menu found for Date: {selected_date}, Meal Period: {meal_period}',
                        'attachments': request_buttons
                    })

            meal_buttons = [{
                'name': 'main_meal',
                'type': 'button',
                'text': f'{menu.main_meal.name}',
                'value': f'{menu.id}_{payload_action_value}'
            } for menu in menus]

            request_buttons = [{
                "text": "",
                "callback_id": "meal_action_selector",
                "color": "#3AA3E3",
                "attachment_type": "default",
                "actions": meal_buttons
            }]

            return self.handle_response(slack_response={
                'text': 'Select Main Meal',
                'attachments': request_buttons
            })

        if payload['type'] == 'interactive_message' and payload[
                'callback_id'] == 'meal_action_selector':
            payload_action_value = payload['actions'][0]['value']
            if payload_action_value.find('order') > -1:
                menu_id = payload_action_value.split('_')[0]
                menu = self.menu_repo.get(menu_id)
                slack_id = payload['user']['id']
                slack_user_info = self.slackhelper.user_info(slack_id)
                slack_user_email = slack_user_info['user']['profile']['email']
                user = self.andela_service.get_user_by_email_or_id(
                    slack_user_email)

                # check if user already has an order
                if OrderRepo().user_has_order(user['id'],
                                              menu.date.strftime('%Y-%m-%d'),
                                              menu.meal_period):
                    slack_data = {
                        'text':
                        'You already have an order for this meal period.'
                    }
                    requests.post(webhook_url,
                                  data=json.dumps(slack_data),
                                  headers={'Content-Type': 'application/json'})
                    return self.handle_response(status_code=400)
                trigger_id = payload['trigger_id']

                side_items_list = menu.side_items.split(',')
                protein_items_list = menu.protein_items.split(',')

                side_items = self.meal_repo.get_meal_items_by_ids(
                    side_items_list)
                protein_items = self.meal_repo.get_meal_items_by_ids(
                    protein_items_list)

                request_dialog_element = []

                for i in range(1, menu.allowed_side + 1):
                    request_dialog_element.append({
                        'label':
                        f'Select Side {i}',
                        'type':
                        'select',
                        'name':
                        f'side_{i}',
                        'options': [{
                            'label': f'{side.name}',
                            'value': f'{side.id}'
                        } for side in side_items]
                    })

                for i in range(1, menu.allowed_protein + 1):
                    request_dialog_element.append({
                        'label':
                        f'Select Protein {i}',
                        'type':
                        'select',
                        'name':
                        f'protein_{i}',
                        'options': [{
                            'label': f'{protein.name}',
                            'value': f'{protein.id}'
                        } for protein in protein_items]
                    })

                state = f'{payload_action_value}'
                self.create_dialog(dialog_elem=request_dialog_element,
                                   trigger_id=trigger_id,
                                   title='Select Protein & Sides',
                                   callback_id='final_selection',
                                   state=state)

                return self.handle_response(
                    slack_response={'text': 'Select Meal Protein and Sides'})

        if payload['callback_id'] == 'after_menu_list' and payload['actions'][
                0]['value'].split('_')[2] == 'rate':

            payload_action_value = payload['actions'][0]['value']
            meal_period = payload_action_value.split('_')[0]
            selected_date = payload_action_value.split('_')[1]
            location_id = payload_action_value.split('_')[2]
            menus = self.menu_repo.get_unpaginated(date=selected_date,
                                                   meal_period=meal_period,
                                                   is_deleted=False)
            if not menus:
                #   No Menu for provided date
                back_buttons = [{
                    'name': 'back',
                    'text': 'Back',
                    'type': "button",
                    'value': location_id
                }]

                request_buttons = [{
                    "text": "",
                    "callback_id": "center_selector",
                    "color": "#3AA3E3",
                    "attachment_type": "default",
                    "actions": back_buttons
                }]
                return self.handle_response(
                    slack_response={
                        'text':
                        f'Sorry No Menu found forr Date: {selected_date}, Meal Period: {meal_period}',
                        'attachments': request_buttons
                    })

            meal_buttons = [{
                'name': 'main_meal',
                'type': 'button',
                'text': f'{menu.main_meal.name}',
                'value': f'{menu.id}_{payload_action_value}'
            } for menu in menus]

            request_buttons = [{
                "text": "",
                "callback_id": "rating_selector",
                "color": "#3AA3E3",
                "attachment_type": "default",
                "actions": meal_buttons
            }]

            return self.handle_response(slack_response={
                'text': 'Select Main Meal',
                'attachments': request_buttons
            })

        if payload['callback_id'] == 'rating_selector':

            menu_id = payload['actions'][0]['value'].split('_')[0]
            menu = self.menu_repo.get(menu_id)
            trigger_id = payload['trigger_id']
            main_meal = menu.main_meal_id

            request_dialog_element = [{
                'label':
                f'Rate meal: {self.meal_repo.get(main_meal).name}',
                'type':
                'select',
                'name':
                'rating value',
                'options': [{
                    'label': f'{value}',
                    'value': f'{value}'
                } for value in range(1, 6)]
            }, {
                'label': 'Add a short comment',
                'type': 'text',
                'name': 'comment'
            }]

            state = f'{payload["actions"][0]["value"]}'
            self.create_dialog(dialog_elem=request_dialog_element,
                               trigger_id=trigger_id,
                               title='Rate a meal',
                               callback_id='submit_rating',
                               state=state)

            return self.handle_response(slack_response={'text': 'Meal rating'})

    def create_dialog(self,
                      dialog_elem,
                      trigger_id,
                      title,
                      callback_id,
                      state=None):
        dialog = {
            "title": title,
            "submit_label": "Submit",
            "callback_id": callback_id,
            "notify_on_cancel": True,
            "state": state,
            "elements": dialog_elem
        }
        return self.slackhelper.dialog(dialog=dialog, trigger_id=trigger_id)

    @staticmethod
    def get_menu_start_end_on(location):
        """This method takes a location id, and attempts to return a start date and an end date based on the conditions
        the application expects.

        Conditions:
            If current datetime is over 3PM , skip a day and return next days.
            If day is thursday and not yet 3PM, return only friday
            If current datetime is friday, saturday or sunday, return next week from monday till friday.
            If No conditions matches, return None for both dates.

        """
        start_on = end_on = None

        current_date = current_time_by_zone(location.zone)

        if current_date.strftime('%a') == 'Mon' and int(
                current_date.strftime('%H')) >= 15:
            start_on = current_date + timedelta(days=2)
            end_on = start_on + timedelta(days=2)

        elif current_date.strftime('%a') == 'Tue' and int(
                current_date.strftime('%H')) >= 15:
            start_on = current_date + timedelta(days=2)
            end_on = start_on + timedelta(days=1)

        elif current_date.strftime('%a') == 'Wed' and int(
                current_date.strftime('%H')) >= 15:
            start_on = end_on = current_date + timedelta(days=2)

        elif current_date.strftime('%a') == 'Thu' and int(
                current_date.strftime('%H')) >= 15:
            start_on = end_on = current_date + timedelta(days=4)

        else:

            start_on = current_date + timedelta(days=1)
            if current_date.strftime('%a') == 'Mon':
                end_on = start_on + timedelta(3)
            if current_date.strftime('%a') == 'Tue':
                end_on = start_on + timedelta(2)
            if current_date.strftime('%a') == 'Wed':
                end_on = start_on + timedelta(1)
            if current_date.strftime('%a') == 'Thu':
                end_on = start_on

            else:
                if current_date.strftime('%a') == 'Fri':
                    start_on = current_date + timedelta(days=3)
                    end_on = current_date + timedelta(days=7)

                if current_date.strftime('%a') == 'Sat':
                    start_on = current_date + timedelta(days=2)
                    end_on = current_date + timedelta(days=6)

                if current_date.strftime('%a') == 'Sun':
                    next_day = 1 if int(
                        current_date.strftime('%H')) < 15 else 2
                    start_on = current_date + timedelta(days=next_day)
                    end_on = current_date + timedelta(days=5)

        return tuple((start_on, end_on))
class VendorRatingController(BaseController):
    def __init__(self, request):
        BaseController.__init__(self, request)
        self.vendor_rating_repo = VendorRatingRepo()
        self.vendor_repo = VendorRepo()
        self.menu_repo = MenuRepo()
        self.order_repo = OrderRepo()

    def list_ratings(self, vendor_id):
        '''retrieves a list of ratings for a specific vendor'''

        ratings = self.vendor_rating_repo.get_unpaginated(vendor_id=vendor_id)

        if ratings:
            ratings_list = [rating.serialize() for rating in ratings]
            return self.handle_response('OK',
                                        payload={'ratings': ratings_list})

        return self.handle_response('Expected vendor in request')

    def get_vendor_rating(self, rating_id):
        '''retrieves the details of a specific rating, giving the rating id'''
        rating = self.vendor_rating_repo.get(rating_id)
        if rating:
            rtng = rating.serialize()

            return self.handle_response('OK', payload={'rating': rtng})
        else:
            return self.handle_response('Bad Request', status_code=400)

    def create_vendor_rating(self):
        '''Adds a vendor rating during a specific engagement'''
        (vendor_id, comment, rating, channel,
         engagement_id) = self.request_params('vendorId', 'comment', 'rating',
                                              'channel', 'engagementId')
        user_id = Auth.user('id')

        if self.vendor_repo.get(vendor_id):

            rating = self.vendor_rating_repo.new_rating(
                vendor_id, user_id, rating, RatingType.engagement, 0,
                engagement_id, channel, comment)
            rtng = rating.serialize()

            return self.handle_response('Rating created',
                                        payload={'rating': rtng},
                                        status_code=201)

        return self.handle_response('Invalid vendor_id provided',
                                    status_code=400)

    def create_order_rating(self):
        '''Adds a order rating during a specific engagement '''

        (order_id, comment, rating,
         channel) = self.request_params('orderId', 'comment', 'rating',
                                        'channel')
        user_id = Auth.user('id')
        order = self.order_repo.get(order_id)
        if order:
            menu = self.menu_repo.get(order.menu_id)
            if menu:
                vendor_id = menu.vendor_engagement.vendor_id
                engagement_id = menu.vendor_engagement.id
                rating = self.vendor_rating_repo.new_rating(
                    vendor_id, user_id, rating, RatingType.order, order_id,
                    engagement_id, channel, comment)
                rating_obj = rating.serialize()
                if rating:
                    updates = {}
                    updates['has_rated'] = True
                    updated_order = self.order_repo.update(
                        order, **updates).serialize()
                return self.handle_response('Rating created',
                                            payload={'rating': rating_obj},
                                            status_code=201)

        return self.handle_response('Invalid vendor_id provided',
                                    status_code=400)

    def update_vendor_rating(self, rating_id):
        '''edits an existing rating'''

        rtng = self.vendor_rating_repo.get(rating_id)
        comment = self.get_json()['comment']

        if Auth.user(
                'id'
        ) == rtng.user_id:  #You cannot update someone else's rating
            if rtng:
                updates = {}
                if comment:
                    updates['comment'] = comment
                self.vendor_rating_repo.update(rtng, **updates)
                return self.handle_response(
                    'OK', payload={'rating': rtng.serialize()})
            return self.handle_response(
                'Invalid or incorrect rating_id provided', status_code=400)
        return self.handle_response(
            'You are not allowed to update a rating that is not yours',
            status_code=403)
 def __init__(self, request):
     BaseController.__init__(self, request)
     self.vendor_rating_repo = VendorRatingRepo()
     self.vendor_repo = VendorRepo()
     self.menu_repo = MenuRepo()
     self.order_repo = OrderRepo()
Ejemplo n.º 10
0
 def setUp(self):
     self.BaseSetUp()
     self.repo = VendorRepo()
     self.rating_repo = VendorRatingRepo()
Ejemplo n.º 11
0
 def setUp(self):
     self.BaseSetUp()
     self.repo = VendorRepo()
     self.rating_repo = VendorRatingRepo()
     self.location = LocationFactory()
Ejemplo n.º 12
0
class ReportsController(BaseController):
    def __init__(self, request):
        BaseController.__init__(self, request)
        self.rating_repo = VendorRatingRepo()
        self.order_repo = OrderRepo()
        self.engagement_repo = VendorEngagementRepo()
        self.vendor_repo = VendorRepo()
        self.user_repo = UserRepo()
        self.session_repo = MealSessionRepo()

    def dashboard_summary(self):
        params = self.get_params_dict()
        location = Auth.get_location()
        vendors = self.vendor_repo.get_unpaginated(is_deleted=False)
        engagements = self.engagement_repo.get_unpaginated(
            is_deleted=False, location_id=location)

        if 'all_vendor_comparison' in params:
            orders = self.order_repo.fetch_all()
            vendor_orders = []
            for vendor in vendors:
                vendor_info = {}
                vendor_info['id'] = vendor.id
                vendor_info['name'] = vendor.name
                vendor_info['collectedOrders'] = len([
                    order for order in orders.items
                    if order.order_status == 'collected' and Menu.query.get(
                        order.menu_id).vendor_engagement.vendor_id == vendor.id
                ])
                vendor_info['uncollectedOrders'] = len([
                    order for order in orders.items
                    if order.order_status == 'booked' and Menu.query.get(
                        order.menu_id).vendor_engagement.vendor_id == vendor.id
                ])
                vendor_info['cancelledOrders'] = len([
                    order for order in orders.items
                    if order.order_status == 'cancelled' and Menu.query.get(
                        order.menu_id).vendor_engagement.vendor_id == vendor.id
                ])
                vendor_orders.append(vendor_info)

            return self.handle_response('ok', payload=vendor_orders)

        str_start_date = params.get('start_date', None)
        start_date = datetime.now().date(
        ) if str_start_date is None else datetime.strptime(
            str_start_date, '%Y-%m-%d').date()

        str_end_date = params.get('end_date', None)
        end_date = (
            datetime.now().date() -
            timedelta(14)) if str_end_date is None else datetime.strptime(
                str_end_date, '%Y-%m-%d').date()

        if start_date < end_date:
            return self.handle_response(
                'Start date must not be less than end date', status_code=400)

        result = []
        orders = Order.query.filter(
            and_(Order.date_booked_for >= end_date,
                 Order.date_booked_for <= start_date))

        if orders and vendors and engagements:
            orders_collected = [
                order for order in orders if order.order_status == 'collected'
            ]
            orders_cancelled = [
                order for order in orders if order.order_status == 'cancelled'
            ]
            orders_uncollected = [
                order for order in orders if order.order_status == 'booked'
            ]

            dates = [
                date.date() for date in pd.bdate_range(end_date, start_date)
            ]
            for date in dates:
                date_info = {
                    'date':
                    date,
                    'collectedOrders':
                    len([
                        order for order in orders_collected
                        if order.date_booked_for == date
                    ]),
                    'uncollectedOrders':
                    len([
                        order for order in orders_uncollected
                        if order.date_booked_for == date
                    ]),
                    'cancelledOrders':
                    len([
                        order for order in orders_cancelled
                        if order.date_booked_for == date
                    ]),
                    'averageRating':
                    self.rating_repo.daily_average_rating(date),
                    'vendor':
                    self.engagement_repo.vendor_of_the_day(date)
                }
                result.append(date_info)

        return self.handle_response('OK', payload=result)

    def daily_taps(self):
        date_range = self.get_params_dict().get('date_range')

        if date_range is not None:
            date_range_list = date_range.split(':')
            start_date = datetime.strptime(date_range_list[0], '%Y-%m-%d')
            end_date = datetime.strptime(date_range_list[1], '%Y-%m-%d')

            if start_date < end_date:
                return self.handle_response(
                    'Start date must not be less than end date',
                    status_code=400)
        else:
            start_date = datetime.today().date()
            end_date = start_date - timedelta(days=7)
        services = MealService.query.filter(
            and_(MealService.date >= end_date, MealService.date <= start_date))
        result = []
        dates = [date.date() for date in pd.bdate_range(end_date, start_date)]
        for date in dates:
            srv_list = []
            current_services = [
                service for service in services if service.date.date() == date
            ]
            for service in current_services:
                user = self.user_repo.get(service.user_id)
                session = self.session_repo.get(service.session_id).name
                service_user = {
                    'id': user.id,
                    'name': f'{user.first_name} {user.last_name}',
                    'userId': user.user_id,
                    'slackId': user.slack_id,
                    'session': session
                }
                srv_list.append(service_user)

            date_info = {'date': str(date), 'count': len(srv_list)}

            result.append(date_info)

        return self.handle_response('OK', payload=result)