Esempio n. 1
0
def upsale_search(order_items, order_date):
    """
    Returns masters and services that they can do on `order_date`
    with respect to the `order_items`

    :param order_items:
    :param order_date:
    :return:
    """
    logger.info(f'Using an upsale search filter on items {order_items} '
                f'with params: date={order_date}')

    # taking the maximum duration of all services of the master and
    # checking if there exists a required number of adjacent empty slots
    result = []
    for item in order_items:
        master = Master.objects.get(pk=item['master_id'])

        logger.info(f'Checking master {master.first_name}')
        schedule = master.get_schedule(order_date)
        logger.info(f'Checking schedule on {schedule.date}')

        for service in master.services.exclude(pk__in=item['service_ids']):
            # ignoring certain services
            time = item['time']
            if time_slot_utils.service_fits_into_slots(
                    service, schedule.time_slots.all(), time_from=time):
                logger.info(f'Master can do service {service.name} '
                            f'on {schedule.date} at {time}')
                result.append({
                    'master_id': master.id,
                    'service_id': service.id
                })
    return result
Esempio n. 2
0
    def _create_order_item(self, item, order):
        master_id = item['master_id']
        logger.info(f'Creating order_item for order={order.id}, '
                    f'master_id={master_id}')

        master = Master.objects.prefetch_related('schedule').get(
            pk=master_id)

        services = Service.objects.filter(pk__in=item['service_ids'])
        if not services:
            raise ValidationError(
                f'Services with provided ids:{item["service_ids"]} '
                f'are not found')

        schedule = master.get_schedule(order.date)
        order_item = None
        start_time = None

        for service in services:
            start_time = start_time or order.time
            next_slot_time = add_time(start_time, minutes=service.max_duration)

            # master's schedule could have changed after the search
            if not time_slot_utils.service_fits_into_slots(
                    service, schedule.time_slots.all(),
                    start_time, next_slot_time):
                raise ApplicationError(
                    'Unable to create order. '
                    'Master\'s schedule has changed ',
                    error_type=ApplicationError.ErrorTypes.
                        ORDER_CREATION_ERROR)

            order_item = OrderItem.objects.create(order=order,
                                                  master=master,
                                                  service=service,
                                                  locked=item['locked'])

            master.create_order_payment(order, order_item)
            logger.info(f'Filling time_slots for '
                        f'master={master.first_name}, '
                        f'service={service.name}, '
                        f'duration={service.max_duration}, '
                        f'schedule_date={schedule.date}')

            start_time = schedule.assign_time(
                start_time, next_slot_time, order_item)

        # add +1 if it's not end of the day
        if start_time:
            next_slot_time = add_time(start_time, minutes=TimeSlot.DURATION)
            schedule.assign_time(start_time,
                                 next_slot_time,
                                 order_item=order_item)
 def test_fits_same_time(self):
     time_slots = [
         TimeSlot(time=_make_time(10, 30), taken=True),
         TimeSlot(time=_make_time(11, 00), taken=False),
         TimeSlot(time=_make_time(11, 30), taken=False),
         TimeSlot(time=_make_time(12, 00), taken=False),
         TimeSlot(time=_make_time(12, 30), taken=False),
     ]
     # max - 60 - 2+1 slots
     result = time_slot_utils.service_fits_into_slots(
         self.service, time_slots, datetime.time(hour=11, minute=30))
     self.assertTrue(result)