Ejemplo n.º 1
0
class WorkshopResourcesSerializer(serializers.ModelSerializer):
    on_date = serializers.DateField(required=False,
                                    default=_convert_to_given_timezone(
                                        timezone.now(),
                                        settings.TIME_ZONE).date())
    updated_by = serializers.PrimaryKeyRelatedField(
        default=serializers.CurrentUserDefault(),
        queryset=get_user_model().objects.all())

    class Meta:
        model = WorkshopResources
        fields = ('__all__')

    def save(self, **kwargs):
        request = self.context.get('request')
        kwargs['updated_by'] = request.user
        super(WorkshopResourcesSerializer, self).save(**kwargs)
Ejemplo n.º 2
0
    def handle(self, *args, **options):
        current_time = timezone.now()
        logger.info(
            "Script:: OPS_ALERTS_DAILY_SUMMARY:: Script started - current_time: %s"
            % current_time)

        current_context_time = _convert_to_given_timezone(
            timezone.now(), settings.TIME_ZONE)
        start_time = make_datetime_timezone_aware_convert_to_utc(
            str(current_context_time.date()) + " 00:00:00", "+0530")
        end_time = make_datetime_timezone_aware_convert_to_utc(
            str(current_context_time.date()) + " 23:59:59", "+0530")
        logger.info(
            "Script:: OPS_ALERTS_DAILY_SUMMARY:: start_time: %s - end_Time: %s"
            % (start_time, end_time))

        try:
            ops_alerts_raised = BookingAlertTriggerStatus.objects.select_related('alert_type')\
                .filter(created_at__range =[start_time, end_time]).exclude(alert_type_id__in=[1, 2])

            logger.debug(
                'Script:: OPS_ALERTS_DAILY_SUMMARY:: Bookings sent in notification: %s'
                % ops_alerts_raised)

            notification = Notifications.objects.get(
                name='OPS_ALERTS_DAILY_SUMMARY')
            cc_address_list = notification.get_cc_list()
            to_address_list = notification.get_to_list()

            email_service = NewEmailService(
                to_address_list,
                cc_address_list,
                context={'ops_alerts_raised': ops_alerts_raised},
                analytic_info={'notification_id': notification.id})

            email_service.send(
                template_folder_name=notification.template_folder_name)

        except:
            logger.exception(
                "Script:: OPS_ALERTS_DAILY_SUMMARY:: Failed to get bookings to process"
            )
Ejemplo n.º 3
0
def build_resource_datewise(days_to_plan_for, num_of_working_hrs):
    today = _convert_to_given_timezone(timezone.now(), settings.TIME_ZONE)
    for item in BUMPER_WORKSHOP_RESOURCES:
        daily_avilable_hrs = {}
        for num in range(0, days_to_plan_for, 1):
            logger.info(
                'SCHEDULING_EOD_WORKSHOP:: Building res for date ->%s' % str(
                    (today + timezone.timedelta(days=num)).date()))
            daily_avilable_hrs[str(
                (today + timezone.timedelta(days=num)).date())] = {
                    'total_minutes_available':
                    num_of_working_hrs[str(
                        (today + timezone.timedelta(days=num)).date())] *
                    item['count'] * 60,
                    'minutes_remaining':
                    num_of_working_hrs[str(
                        (today + timezone.timedelta(days=num)).date())] *
                    item['count'] * 60,
                }
        item['hrs_mapping'] = daily_avilable_hrs
Ejemplo n.º 4
0
    def handle(self, *args, **options):
        current_time = timezone.now()
        logger.info(
            "Script:: SCHEDULING_WORKSHOP:: Script started - current_time: %s"
            % current_time)

        # pickup time in next day
        current_context_time = _convert_to_given_timezone(
            timezone.now(), settings.TIME_ZONE)
        date_for_tomorrow_in_current_context = current_context_time + timezone.timedelta(
            days=1)
        start_time = make_datetime_timezone_aware_convert_to_utc(
            str(date_for_tomorrow_in_current_context.date()) + " 00:00:00",
            "+0530")
        end_time = start_time + timezone.timedelta(hours=24)

        logger.info(
            "Script:: SCHEDULING_WORKSHOP:: Tomorrow's start_time: %s - end_Time: %s"
            % (start_time, end_time))

        try:
            # Get all panels in all bookings for which work needs to be done,
            # and that are in workshop in ready to work status.
            all_bookings_in_workshop = Booking.objects.filter(
                status__in=[12, 13])
            all_booking_all_tasks = []

            for booking in all_bookings_in_workshop:
                groups_of_work = get_groups_of_work_from_booking(booking)

                # all_panels_in_booking = BookingPackagePanel.objects.select_related('panel') \
                #     .filter(booking_package__booking_id=booking.id)

                booking_tasks_remaining = []
                groups = []
                for type_of_group in groups_of_work:
                    work_list = get_steps_by_type_of_work(type_of_group)
                    for group in groups_of_work[type_of_group]:
                        if group["name"] not in groups:
                            groups.append(group["name"])

                        for work in work_list:
                            booking_tasks_remaining.append({
                                'task_name':
                                "Task(%s:%s)::%s::seq-%s" %
                                (booking.id, group['name'],
                                 work['step']['name'], work['step']['seq']
                                 ),  # (12435:fender_right)::denting::seq-1
                                'group_name':
                                group['name'],
                                'type_of_work':
                                work['step']['name'],
                                'resource':
                                work['step']['resource_type_req'],
                                'processing_time':
                                (work['processing_time'] * group['units']),
                                'seq':
                                work['step']['seq'],
                            })

                checkpoint_tasks = []
                checkpoints = get_checkpoint_steps(booking)
                for checkpoint_num, checkpoint in enumerate(checkpoints):
                    if "Full_Car" not in groups:
                        groups.append("Full_Car")

                    t = {
                        'task_name':
                        "Task(%s:Full_Car)::%s::seq-%s" %
                        (booking.id, checkpoint['step']['name'],
                         checkpoint['step']['seq']),
                        'group_name':
                        "full_car",
                        'type_of_work':
                        checkpoint['step']['name'],
                        'resource':
                        checkpoint['step']['resource_type_req'],
                        'processing_time':
                        checkpoint['processing_time'],
                        'seq':
                        checkpoint['step']['seq'],
                    }
                    booking_tasks_remaining.append(t)
                    checkpoint_tasks.append(t)

                all_booking_all_tasks.append({
                    'id': booking.id,
                    'groups': groups,
                    'tasks': booking_tasks_remaining,
                    'checkpoints': checkpoint_tasks,
                })

            logger.info(
                "Script:: SCHEDULING_WORKSHOP:: Bookings & their tasks To Process: %s"
                % all_booking_all_tasks)

            bumper_horizon = 0
            for booking in all_booking_all_tasks:
                for task in booking['tasks']:
                    bumper_horizon += task['processing_time']

            logger.info("Script:: SCHEDULING_WORKSHOP::%s" % bumper_horizon)

            task_to_interval = collections.OrderedDict()
            resource_to_intervals = {}
            all_resource_list = []

            for r in bumper_resources:
                i = 1
                while i <= r['count']:
                    resource_name = "%s%i" % (r['name'], i)
                    all_resource_list.append(resource_name)
                    resource_to_intervals[resource_name] = list()
                    i += 1

            # Create the solver.
            solver = pywrapcp.Solver('bumper workshop')

            # Create all interval based tasks for all bookings.
            for booking in all_booking_all_tasks:
                for task in booking['tasks']:
                    solver_task = solver.FixedDurationIntervalVar(
                        0, bumper_horizon - task['processing_time'],
                        task['processing_time'], False, task["task_name"])

                    task_to_interval[task['task_name']] = solver_task

                    # process multiple resource on same task
                    task_resources_required_both = str(
                        task['resource']).split('&')

                    for req_resource_type in task_resources_required_both:
                        # process optional resources on same task
                        task_resources_required = str(req_resource_type).split(
                            '|')
                        RA_tasks_optional = list()
                        for resource_type in task_resources_required:
                            for resource_name in get_resource_seq_by_type(
                                    resource_type):
                                # Adding optional tasks
                                I_ = solver.FixedDurationIntervalVar(
                                    0,
                                    bumper_horizon - task['processing_time'],
                                    task['processing_time'], True, '%s_%s' %
                                    (task['task_name'], resource_name))

                                resource_to_intervals[resource_name].append(I_)
                                RA_tasks_optional.append(I_)
                                solver.Add(solver_task.StaysInSync(I_))

                        # one resource needs to get selected
                        solver.Add(
                            solver.Sum([
                                I_.PerformedExpr() for I_ in RA_tasks_optional
                            ]) == 1)

            # resources
            sequences = collections.OrderedDict()
            for R in all_resource_list:
                disj = solver.DisjunctiveConstraint(resource_to_intervals[R],
                                                    R)
                sequences[R] = disj.SequenceVar()
                solver.Add(disj)

            # Precedences inside a job.
            # for booking in all_bookings_in_workshop:
            #     groups_of_work = get_groups_of_work_from_booking(booking)
            #     for type_of_group in groups_of_work:
            #         work_list = get_steps_by_type_of_work(type_of_group)
            #         for idx, group in enumerate(groups_of_work[type_of_group]):
            #             for task_num, work in enumerate( work_list):
            #                 # Do this using SEQ num rather than list index.
            #                 if task_num == len(work_list) - 1:
            #                     continue
            #                 solver.Add(task_to_interval["%s-%s-%s" % (booking.id, idx, task_num + 1)].StartsAfterEnd(
            #                     task_to_interval["%s-%s-%s" % (booking.id, idx, task_num)]))

            for booking in all_booking_all_tasks:
                # set precedence within booking tasks
                for group in booking['groups']:
                    # set precedence within group of works
                    all_task_within_group = [
                        item for item in booking["tasks"]
                        if str(item["task_name"]).split("::")[0] ==
                        'Task(%s:%s)' % (booking["id"], group)
                    ]
                    # is there a task with greater seq num than this task in this group
                    foo = sorted(all_task_within_group, key=lambda x: x['seq'])
                    max_task_to_process = len(foo) - 1
                    for idx, task in enumerate(foo):
                        if idx == max_task_to_process:
                            continue
                        solver.Add(task_to_interval[foo[
                            idx + 1]["task_name"]].StartsAfterEnd(
                                task_to_interval[task["task_name"]]))

                    if len(all_task_within_group) > 0 and group != "Full_Car":
                        # set precedence for checkpoints
                        for checkpoint_task in booking["checkpoints"]:
                            seq_num = checkpoint_task["seq"]
                            all_tasks_below_checkpoint = [
                                item for item in all_task_within_group
                                if item["seq"] < seq_num
                            ]
                            if len(all_tasks_below_checkpoint) > 0:
                                # going through all group to get last task before seq
                                last_task = all_tasks_below_checkpoint[-1]
                                solver.Add(task_to_interval[checkpoint_task[
                                    "task_name"]].StartsAfterEnd(
                                        task_to_interval[
                                            last_task["task_name"]]))

            # Objective
            # obj_var = solver.Max([((task_to_interval["%s-%s-%s" % (booking['id'], task['group_num'], task['task_num'])].EndExpr()
            #                                )for task in booking["tasks"]) for booking in all_booking_all_tasks])

            # obj_var = solver.Max([task_to_interval[booking['tasks'][-1]['task_name']].EndExpr()
            #                       for booking in all_booking_all_tasks if len(booking['tasks']) > 0])

            #  Last item as per seq to be done as soon as possible.
            obj_var = solver.Max([
                task_to_interval[sorted(
                    booking["tasks"],
                    key=lambda x: x['seq'])[-1]['task_name']].EndExpr()
                for booking in all_booking_all_tasks
                if len(booking['tasks']) > 0
            ])

            objective_monitor = solver.Minimize(obj_var, 1)

            # Creates search phases.
            vars_phase = solver.Phase([obj_var], solver.CHOOSE_FIRST_UNBOUND,
                                      solver.ASSIGN_MIN_VALUE)

            sequence_phase = solver.Phase(sequences.values(),
                                          solver.SEQUENCE_DEFAULT)

            main_phase = solver.Compose([sequence_phase, vars_phase])

            # Create the solution collector.
            collector = solver.LastSolutionCollector()

            # Add the interesting variables to the SolutionCollector.
            collector.Add(sequences.values())
            collector.AddObjective(obj_var)

            for R in all_resource_list:
                sequence = sequences[R]
                sequence_count = sequence.Size()
                for j in range(0, sequence_count):
                    t = sequence.Interval(j)
                    collector.Add(t.StartExpr().Var())
                    collector.Add(t.EndExpr().Var())
            # Solve the problem.
            disp_col_width = 10

            if solver.Solve(main_phase, [objective_monitor, collector]):
                print("\nOptimal Schedule Length:",
                      collector.ObjectiveValue(0), "\n")
                sol_line = ""
                sol_line_tasks = ""
                print("Optimal Schedule", "\n")

                for R in all_resource_list:
                    seq = sequences[R]
                    sol_line += R + ": "
                    sol_line_tasks += R + ": "
                    sequence = collector.ForwardSequence(0, seq)
                    seq_size = len(sequence)

                    for j in range(0, seq_size):
                        t = seq.Interval(sequence[j])
                        # Add spaces to output to align columns.
                        sol_line_tasks += t.Name() + " " * disp_col_width

                    for j in range(0, seq_size):
                        t = seq.Interval(sequence[j])
                        sol_tmp = "[" + str(
                            collector.Value(0,
                                            t.StartExpr().Var())) + ","
                        sol_tmp += str(collector.Value(
                            0,
                            t.EndExpr().Var())) + "] "
                        # Add spaces to output to align columns.
                        sol_line += sol_tmp + " " * disp_col_width

                    sol_line += "\n"
                    sol_line_tasks += "\n"

                print(sol_line_tasks)
                print("Time Intervals for Tasks\n")
                print(sol_line)
        except:
            logger.exception(
                "Script:: SCHEDULING_WORKSHOP:: Failed to process to bookings")
Ejemplo n.º 5
0
    def handle(self, *args, **options):
        current_time = timezone.now()
        logger.info(
            "Script:: PICKUP_REMINDER_TODAY:: Script started - current_time: %s"
            % current_time)

        subject = None

        # pickup time in next day
        current_context_time = _convert_to_given_timezone(
            timezone.now(), settings.TIME_ZONE)
        start_time = make_datetime_timezone_aware_convert_to_utc(
            str(current_context_time.date()) + " 00:00:00", "+0530")
        end_time = make_datetime_timezone_aware_convert_to_utc(
            str(current_context_time.date()) + " 23:59:59", "+0530")

        logger.info(
            "Script:: PICKUP_REMINDER_TODAY:: start_time: %s - end_Time: %s" %
            (start_time, end_time))
        try:
            pickup_in_next_day_bookings = Booking.objects.select_related('user')\
                .filter(status_id=3, pickup_time__range =[start_time, end_time])\
                .exclude(Q(ops_status_id=8) | Q(pickup_driver_id__isnull=True))

            if not pickup_in_next_day_bookings:
                logger.exception(
                    "Script:: PICKUP_REMINDER_TODAY:: No Bookings to send notifications to."
                )

            for booking in pickup_in_next_day_bookings:
                try:
                    pickup_time = format_datetime_for_grid(booking.pickup_time)
                    if pickup_time and format_datetime_for_grid(
                            booking.pickup_slot_end_time):
                        pickup_time = pickup_time + ' - ' + format_datetime_for_msg(
                            booking.pickup_slot_end_time)

                    booking_packages = BookingPackage.objects.filter(
                        booking=booking)
                    package_taken = []
                    for item in booking_packages:
                        package_taken.append(item.package.package.name)

                    logger.info(
                        "Script:: PICKUP_REMINDER_TODAY:: Booking Id: %s" %
                        booking.id)
                    template_vars = {
                        'bookingId':
                        booking.id,
                        'customer_name':
                        booking.user.name,
                        'phone':
                        booking.user.phone,
                        'email':
                        booking.user.email,
                        'pickup_driver_name':
                        booking.pickup_driver.name
                        if booking.pickup_driver else '',
                        'pickup_driver_phone':
                        booking.pickup_driver.ops_phone
                        if booking.pickup_driver else '',
                        'pickup_time_details':
                        pickup_time if pickup_time else '',
                        'package_details':
                        ', '.join(package_taken),
                        'app_redirect_url':
                        settings.BUMPER_APP_URL_THROUGH_APP_REDIRECT_URL %
                        str(booking.id)
                    }

                    messages = Messages.objects.filter(booking_id=booking.id)

                    if booking.is_doorstep:
                        sms_notification = Notifications.objects.get(
                            name='USER_SMS_PICKUP_REMINDER_ATDOOR')
                        push_notification = Notifications.objects.get(
                            name='USER_PUSH_PICKUP_REMINDER_ATDOOR')
                    else:
                        sms_notification = Notifications.objects.get(
                            name='USER_SMS_PICKUP_REMINDER')
                        push_notification = Notifications.objects.get(
                            name='USER_EMAIL_PICKUP_REMINDER')

                    logger.info("Script:: PICKUP_REMINDER_TODAY:: Sending SMS")
                    send_custom_notification(
                        sms_notification.name,
                        template_vars,
                        params_dict={'booking_id': booking.id},
                        user=booking.user)

                    logger.info(
                        "Script:: PICKUP_REMINDER_TODAY:: Sending PUSH")
                    send_custom_notification(
                        push_notification.name,
                        template_vars,
                        params_dict={'booking_id': booking.id},
                        user=booking.user)

                    logger.info("Script:: PICKUP_REMINDER_TODAY:: Processed")
                except:
                    logger.exception("Script:: PICKUP_REMINDER_TODAY:: Failed")
        except:
            logger.exception(
                "Script:: PICKUP_REMINDER_TODAY:: Failed to process to bookings"
            )
Ejemplo n.º 6
0
def generate_workshop_schedule(days_to_plan_for,
                               avail_resources,
                               remove_list,
                               workshop_id,
                               use_current_status=True,
                               working_hrs_available=9):
    # TODO: Find delay from expected status.
    # TODO: when considering next day then priortize untouched.
    logger.info("SCHEDULING_EOD_WORKSHOP:: Script started - current_time: %s" %
                timezone.now())
    today = _convert_to_given_timezone(timezone.now(), settings.TIME_ZONE)
    try:
        for item in BUMPER_WORKSHOP_RESOURCES:
            if item["name"] in avail_resources:
                item["count"] = int(avail_resources[item["name"]])

        datewise_booking_allocation = {}
        datewise_available_working_hrs = {}
        for num in range(0, days_to_plan_for, 1):
            dt_to_consider = today + timezone.timedelta(days=num)
            datewise_booking_allocation[str(dt_to_consider.date())] = []
            datewise_available_working_hrs[str(
                dt_to_consider.date())] = working_hrs_available
            if use_current_status and num == 0:
                if dt_to_consider.hour >= 19:
                    datewise_available_working_hrs[str(
                        dt_to_consider.date())] = 0
                elif dt_to_consider.hour < 10:
                    datewise_available_working_hrs[str(
                        dt_to_consider.date())] = working_hrs_available
                else:
                    datewise_available_working_hrs[str(
                        dt_to_consider.date())] = 19 - dt_to_consider.hour

        build_resource_datewise(days_to_plan_for,
                                datewise_available_working_hrs)

        # Get all panels in all bookings for which work needs to be done,
        # and that are in workshop in ready to work status.
        workshop_ids_to_consider = [workshop_id]
        if workshop_id == 17:
            workshop_ids_to_consider = [16, 17, 18]
        all_bookings_in_workshop = Booking.objects.filter(
            status__in=[12, 13],
            estimate_complete_time__isnull=False,
            rework_booking_id__isnull=True,
            workshop_id__in=workshop_ids_to_consider).order_by('workshop_eta')
        if remove_list:
            all_bookings_in_workshop.exclude(id__in=remove_list)

        all_bookings_with_eod = []
        projected_delayed_bookings = set()

        for booking in all_bookings_in_workshop:
            has_dent_or_fbb = BookingPackage.objects.filter(
                booking_id=booking.id,
                package__package__category__in=[2, 3]).exists()
            if has_dent_or_fbb:
                workshop_reached_time = _convert_to_given_timezone(
                    booking.workshop_reached_time, settings.TIME_ZONE)
                customer_eta = _convert_to_given_timezone(
                    booking.estimate_complete_time, settings.TIME_ZONE)
                workshop_eta = _convert_to_given_timezone(
                    booking.workshop_eta, settings.TIME_ZONE)
                panels_breakup = get_panels_breakup(booking)
                workshop_vendor = booking.workshop.name

                work_to_done_in_day_datewise = {}
                date_to_process = today
                for num in range(0, days_to_plan_for, 1):
                    date_to_process = today + timezone.timedelta(days=num)

                    if date_to_process.isoweekday() == 7:
                        # to remove sunday from scheduling
                        continue

                    if date_to_process == today:
                        # taking status at start of day as, output need resource allocation for complete day.
                        # if current status is taken then full resource time will be available but that is not the
                        # case in realty.
                        if not use_current_status:
                            status_at_start_of_day = get_status_at_start_of_day(
                                booking, today.date())
                        else:
                            booking_expected_eod = BookingExpectedEOD.objects\
                                .filter(booking=booking,for_date=today.date())\
                                .order_by('-created_at').first()

                            if booking_expected_eod:
                                status_at_start_of_day = {
                                    'last_status':
                                    booking_expected_eod.status.flow_order_num,
                                    'last_ops_status':
                                    booking_expected_eod.ops_status.
                                    flow_order_num if
                                    booking_expected_eod.ops_status else None,
                                }
                            else:
                                status_at_start_of_day = {
                                    'last_status':
                                    booking.status.flow_order_num,
                                    'last_ops_status':
                                    booking.ops_status.flow_order_num
                                    if booking.ops_status else None,
                                }
                    else:
                        if date_to_process.isoweekday() == 1:
                            if str(
                                (date_to_process - timezone.timedelta(days=2)
                                 ).date()) not in work_to_done_in_day_datewise:
                                status_at_start_of_day = get_status_at_start_of_day(
                                    booking, date_to_process.date())
                            else:
                                status_at_start_of_day = \
                                work_to_done_in_day_datewise[str((date_to_process - timezone.timedelta(days=2)).date())][
                                    'status_at_end_of_day']
                        else:
                            if str(
                                (date_to_process - timezone.timedelta(days=1)
                                 ).date()) not in work_to_done_in_day_datewise:
                                status_at_start_of_day = get_status_at_start_of_day(
                                    booking, date_to_process.date())
                            else:
                                status_at_start_of_day = \
                                work_to_done_in_day_datewise[str((date_to_process - timezone.timedelta(days=1)).date())][
                                    'status_at_end_of_day']

                    expected_end_of_day = get_expected_end_of_day(
                        booking.id, workshop_reached_time, date_to_process,
                        panels_breakup, status_at_start_of_day,
                        working_hrs_available)
                    if expected_end_of_day['delay']:
                        projected_delayed_bookings.add(
                            "%s_%s" % (booking.id, workshop_vendor))

                    data = {
                        'expected_status_as_per_sla':
                        get_ops_desc_from_seq(
                            expected_end_of_day['eod_task_seq']),
                        'status_at_start_of_day':
                        status_at_start_of_day,
                        'status_at_end_of_day':
                        expected_end_of_day['status_at_end_of_day'],
                        'total_time_used_for_date':
                        expected_end_of_day['total_time_used_for_date'],
                        'delay':
                        expected_end_of_day['delay'],
                        'days_in_workshop':
                        expected_end_of_day['days_in_workshop'],
                        'tasks_done_for_date':
                        expected_end_of_day['tasks_done_for_date'],
                    }
                    total_hrs_used = 0
                    if expected_end_of_day['total_time_used_for_date']:
                        for work_data in expected_end_of_day[
                                'total_time_used_for_date'].iteritems():
                            total_hrs_used += work_data[1]

                        if total_hrs_used > 0:
                            formatted_data = data
                            formatted_data["booking_id"] = booking.id
                            formatted_data[
                                "car_model"] = booking.usercar.car_model.name
                            formatted_data[
                                "car_reg_num"] = booking.usercar.registration_number
                            formatted_data["workshop"] = booking.workshop.name
                            formatted_data["panels_breakup"] = panels_breakup
                            formatted_data["workshop_eta"] = workshop_eta
                            formatted_data["customer_eta"] = customer_eta
                            formatted_data[
                                "current_status"] = booking.ops_status.ops_status_desc if booking.ops_status else ""
                            formatted_data[
                                "status_at_start_of_day_desc"] = get_ops_desc_from_seq(
                                    data['status_at_start_of_day']
                                    ['last_ops_status']
                                ) if data['status_at_start_of_day'][
                                    'last_ops_status'] else "Not Started"
                            formatted_data[
                                "status_at_end_of_day_desc"] = get_ops_desc_from_seq(
                                    data['status_at_end_of_day']
                                    ['last_ops_status'])
                            datewise_booking_allocation[str(
                                date_to_process.date())].append(formatted_data)

                    work_to_done_in_day_datewise[str(
                        date_to_process.date())] = data

                ordered_work_to_done_in_day_datewise = OrderedDict(
                    sorted(work_to_done_in_day_datewise.items(),
                           key=lambda t: t[0]))

                cannot_meet_workshop_eta = False
                if len(ordered_work_to_done_in_day_datewise.values()) > 0:
                    last_data = ordered_work_to_done_in_day_datewise.values(
                    )[-1]
                    if workshop_eta.date() > date_to_process.date(
                    ) and last_data['status_at_end_of_day'][
                            'last_ops_status'] < 327:
                        cannot_meet_workshop_eta = True

                booking_detail = {
                    'booking_id': booking.id,
                    'workshop_vendor': workshop_vendor,
                    'workshop_id': booking.workshop.id,
                    'workshop_reached_time': workshop_reached_time,
                    'workshop_eta': workshop_eta,
                    'customer_eta': customer_eta,
                    'work_to_done_in_day_datewise':
                    ordered_work_to_done_in_day_datewise,
                    'panels_breakup': panels_breakup,
                    'cannot_meet_workshop_eta': cannot_meet_workshop_eta
                    # 'is_untouched': is_untouched,
                }
                all_bookings_with_eod.append(booking_detail)

        for item in BUMPER_WORKSHOP_RESOURCES:
            ordered_datewise = OrderedDict(
                sorted(item['hrs_mapping'].items(), key=lambda t: t[0]))
            item['hrs_mapping'] = ordered_datewise

        return all_bookings_with_eod, projected_delayed_bookings, BUMPER_WORKSHOP_RESOURCES, datewise_booking_allocation
    except:
        logger.exception('Failed to create EOD list')
Ejemplo n.º 7
0
    def handle(self, *args, **options):
        current_time = timezone.now()
        logger.info(
            "Script:: CREW_SCHEDULING:: Script started - current_time: %s" %
            current_time)
        gmaps = googlemaps.Client(key=GOOGLE_MAP_API_KEY)

        only_pickup = options['only_pickup']

        # pickup time in next day
        current_context_time = _convert_to_given_timezone(
            timezone.now(), settings.TIME_ZONE)
        date_for_tomorrow_in_current_context = current_context_time + timezone.timedelta(
            days=1)
        start_time = make_datetime_timezone_aware_convert_to_utc(
            str(date_for_tomorrow_in_current_context.date()) + " 00:00:00",
            "+0530")
        end_time = start_time + timezone.timedelta(hours=24)

        logger.info(
            "Script:: CREW_SCHEDULING:: start_time: %s - end_Time: %s" %
            (start_time, end_time))

        try:
            pickup_in_next_day_bookings = Booking.objects.select_related('user')\
                .filter(status_id__lt=9, pickup_time__range =[start_time, end_time])\
                .exclude(ops_status_id=8)

            pickup_data = []
            for booking in pickup_in_next_day_bookings:
                address = booking.booking_address.filter(
                    type=BookingAddress.ADDRESS_TYPE_PICKUP).first()
                directions_result = None
                try:
                    origins = [
                        (DRIVER_1_LOC_LAT, DRIVER_1_LOC_LONG),
                        (DRIVER_2_LOC_LAT, DRIVER_2_LOC_LONG),
                    ]
                    directions_result = gmaps.distance_matrix(
                        origins,
                        (address.address.latitude, address.address.longitude),
                        mode="transit",
                        units="metric",
                        arrival_time=booking.pickup_time)
                except:
                    logger.exception(
                        "Script:: CREW_SCHEDULING:: Failed To get ETA based on Google map APIS."
                    )

                pickup_data.append({
                    'bookingId': booking.id,
                    'name': booking.user.name,
                    'phone': booking.user.phone,
                    'time': booking.pickup_time,
                    'address_lat': address.address.latitude,
                    'address_long': address.address.longitude,
                    'driver': booking.pickup_driver,
                    'directions_result': directions_result
                })

            logger.info("Script:: CREW_SCHEDULING:: pickup data: %s" %
                        (pickup_data))

        except:
            logger.exception(
                "Script:: CREW_SCHEDULING:: Failed to process to bookings")
Ejemplo n.º 8
0
    def handle(self, *args, **options):
        current_time = timezone.now()
        logger.info("Script:: PICKUP_SUMMARY:: Script started - current_time: %s" % current_time)

        override_subject = None
        if options['reminder']:
            override_subject = "Reminder to set Tomorrow's Pickup"

        # pickup time in next day
        current_context_time = _convert_to_given_timezone(timezone.now(), settings.TIME_ZONE)
        date_for_tomorrow_in_current_context = current_context_time + timezone.timedelta(days=1)
        start_time = make_datetime_timezone_aware_convert_to_utc(str(date_for_tomorrow_in_current_context.date())+" 00:00:00", "+0530")
        end_time = start_time + timezone.timedelta(hours=24)

        logger.info("Script:: PICKUP_SUMMARY:: start_time: %s - end_Time: %s" % (start_time, end_time))
        try:
            pickup_in_next_day_bookings = Booking.objects.select_related('user', 'usercar', 'usercar__car_model')\
                .filter(status_id__lt=9, pickup_time__range =[start_time, end_time])\
                .exclude(ops_status_id=8)

            pickup_data = []
            for booking in pickup_in_next_day_bookings:
                booking_packages = BookingPackage.objects.filter(booking=booking)
                package_taken = []
                panels = 0
                for item in booking_packages:
                    package_taken.append(item.package.package.name)
                    if item.package.package.category == Package.CATEGORY_DENT:
                        for panel_item in BookingPackagePanel.objects.filter(booking_package=item):
                            # Not using count here as full body will be counted as 14 panels.
                            panels += 1
                    if item.package.package.category == Package.CATEGORY_FULL_BODY:
                        panels += 14

                pickup_address = booking.booking_address.filter(type=BookingAddress.ADDRESS_TYPE_PICKUP).first()
                pickup_data.append({
                    'bookingId': booking.id,
                    'name': booking.user.name,
                    'phone': booking.user.phone,
                    'time': format_datetime_for_grid(booking.pickup_time),
                    'address': "%s, %s" % (pickup_address.address.address1, pickup_address.address.address2),
                    'packages': ', '.join(package_taken),
                    'panels': panels,
                    'car': str(booking.usercar.car_model),
                    'driver': booking.pickup_driver.name if booking.pickup_driver else '',
                })
            try:
                logger.info("Script:: PICKUP_SUMMARY:: pickup data: %s" % (pickup_data))
                notification = Notifications.objects.get(name='OPS_ALERT_PICKUP_FOR_TOMORROW')
                cc_address_list = notification.get_cc_list()
                to_address_list = notification.get_to_list()

                email_service = NewEmailService(to_address_list, cc_address_list, context={'pickup_data': pickup_data},
                                                analytic_info={'notification_id': notification.id})
                email_service.send(template_folder_name=notification.template_folder_name, subject=override_subject)

                logger.info("Script:: PICKUP_SUMMARY:: Sent")
            except:
                logger.exception("Script:: PICKUP_SUMMARY:: Failed")
        except:
            logger.exception("Script:: PICKUP_SUMMARY:: Failed to process to bookings")