예제 #1
0
def notify_pickup_delay():
    date = datetime.today()
    day_start = ist_day_start(date)
    day_end = ist_day_end(date)

    delivery_status_queryset = OrderDeliveryStatus.objects.filter(date__gte=day_start, date__lte=day_end)
    delivery_status_queryset = delivery_status_queryset.filter(
        Q(order_status=constants.ORDER_STATUS_PLACED) |
        Q(order_status=constants.ORDER_STATUS_QUEUED) )
    
    current_datetime = datetime.now()
    delivery_status_queryset = delivery_status_queryset.filter(order__pickup_datetime__lte=current_datetime)

    pickup_guys = delivery_status_queryset.values_list('pickup_guy', flat = True).exclude(pickup_guy=None).distinct()
    for pickup_guy_id in pickup_guys:
        try:
            pickup_guy = get_object_or_404(DeliveryGuy, id = pickup_guy_id)
            pickupguy_wise_delivery_ids = delivery_status_queryset.filter(pickup_guy= pickup_guy).values_list('id', flat = True)
            delivery_ids = delivery_ids_string(pickupguy_wise_delivery_ids)
            delivery_ids_msg_string = delivery_ids_message_string(pickupguy_wise_delivery_ids)
            ops_managers = ops_executive_for_dg(pickup_guy)
            if len(ops_managers)  > 0:
                notification_type = notification_type_for_code(constants.NOTIFICATION_CODE_LATE_PICKUP)
                for ops_manager in ops_managers:
                    if check_if_notification_already_exists(notification_type, ops_manager, delivery_ids) is False:
                        notification_message = constants.NOTIFICATION_MESSAGE_PICKUP_DELAY%(ops_manager.user.first_name, pickup_guy.user.first_name, delivery_ids_msg_string, pickup_guy.user.first_name, pickup_guy.user.username)
                        new_notification = Notification.objects.create(notification_type = notification_type, 
                            delivery_id = delivery_ids, message = notification_message)
                        ops_manager.notifications.add(new_notification)
                        ops_manager.save()
            else:
                create_notif_for_no_ops_exec_for_delivery_guy(pickup_guy)
        except Exception, e:
            pass
예제 #2
0
def notify_unassigned_deliveries():
    date = datetime.today()
    day_start = ist_day_start(date)
    day_end = ist_day_end(date)

    delivery_status_queryset = OrderDeliveryStatus.objects.filter(date__gte=day_start, date__lte=day_end)
    delivery_status_queryset = delivery_status_queryset.filter(Q(delivery_guy=None))
    delivery_status_queryset = delivery_status_queryset.filter(
        Q(order_status=constants.ORDER_STATUS_PLACED) |
        Q(order_status=constants.ORDER_STATUS_QUEUED) |
        Q(order_status=constants.ORDER_STATUS_INTRANSIT))

    notif_datetime = datetime.now() + timedelta(hours=2, minutes=0)
    delivery_status_queryset = delivery_status_queryset.filter(order__delivery_datetime__lte=notif_datetime)

    pincodes = delivery_status_queryset.values_list('order__delivery_address__pin_code', flat = True).distinct()
    for pincode in pincodes:
        pincode_wise_delivery_ids = delivery_status_queryset.filter(order__delivery_address__pin_code= pincode).values_list('id', flat = True)
        delivery_ids = delivery_ids_string(pincode_wise_delivery_ids)
        delivery_ids_msg_string = delivery_ids_message_string(pincode_wise_delivery_ids)
        ops_managers = ops_executive_for_pincode(pincode)
        if len(ops_managers)  > 0:
            notification_type = notification_type_for_code(constants.NOTIFICATION_CODE_UNASSIGNED_DELIVERY)            
            for ops_manager in ops_managers:
                if check_if_notification_already_exists(notification_type, ops_manager, delivery_ids) is False:
                    notification_message = constants.NOTIFICATION_MESSAGE_UNASSIGNED_DELIVERY%(ops_manager.user.first_name, delivery_ids_msg_string, pincode)
                    new_notification = Notification.objects.create(notification_type = notification_type, 
                        delivery_id = delivery_ids, message = notification_message)
                    ops_manager.notifications.add(new_notification)
                    ops_manager.save()
        else:
            create_notif_for_no_ops_exec_for_pincode(pincode)
def excel_download(request):
    try:
        start_date_string = request.QUERY_PARAMS.get('start_date', None)
        end_date_string = request.QUERY_PARAMS.get('end_date', None)

        start_date = parse_datetime(start_date_string)
        start_date = ist_day_start(start_date)

        end_date = parse_datetime(end_date_string)
        end_date = ist_day_end(end_date)
    except Exception as e:
        params = ['start_date', 'end_date']
        return response_incomplete_parameters(params)

    # VENDOR FILTERING -----------------------------------------------------------
    vendor = None
    role = user_role(request.user)
    if role == constants.VENDOR:
        vendor_agent = get_object_or_404(VendorAgent, user=request.user)
        vendor = vendor_agent.vendor
    else:
        vendor_id = request.QUERY_PARAMS.get('vendor_id', None)
        if vendor_id is not None:
            vendor = get_object_or_404(Vendor, pk=vendor_id)
        else:
            pass

    if vendor is not None:
        delivery_status_queryset = OrderDeliveryStatus.objects.filter(
            order__vendor=vendor).select_related('delivery_guy__user')
    else:
        delivery_status_queryset = OrderDeliveryStatus.objects.all(
        ).select_related('delivery_guy__user')

    # DATE FILTERING ---------------------------------------------------------------
    delivery_status_queryset = delivery_status_queryset.filter(
        date__gte=start_date, date__lte=end_date).select_related('order')
    # ------------------------------------------------------------------------------

    if len(delivery_status_queryset) > 5000:
        error_message = 'Too many records. Max of 5000 deliveries can be downloaded at a time.'
        return response_error_with_message(error_message)

    # CONSTRUCTING RESPONSE ---------------------------------------------------------------
    ist_timedelta = timedelta(hours=5, minutes=30)
    excel_order_details = []
    for delivery_status in delivery_status_queryset:
        try:
            date = delivery_status.date + ist_timedelta
            order = delivery_status.order
            excel_order = {
                'date': date.strftime('%d-%m-%Y'),
                'order_id': delivery_status.id,
                'customer_name': order.consumer.full_name,
                'customer_phone_number': order.consumer.phone_number,
                'cod_amount': order.cod_amount,
                'cod_collected': delivery_status.cod_collected_amount,
                'cod_reason': delivery_status.cod_remarks,
                'status': delivery_status.order_status,
                'vendor_notes': order.notes,
                'vendor_order_id': order.vendor_order_id
            }
            if role == constants.OPERATIONS:
                excel_order['vendor_name'] = order.vendor.store_name
                if delivery_status.delivery_guy is not None:
                    excel_order[
                        'delivery_guy'] = delivery_status.delivery_guy.user.first_name
                else:
                    excel_order['delivery_guy'] = None

            excel_order_details.append(excel_order)
        except Exception as e:
            pass
    return response_with_payload(excel_order_details, None)
예제 #4
0
def vendor_report():
    date = datetime.today()
    day_start = ist_day_start(date)
    day_end = ist_day_end(date)

    # TOTAL ORDERS ----------------------------------------------------------------------
    # filter on today
    # filter on all orders statues
    # then group by vendor name to get sum_of_cod_collected and sum_of_cod_amount
    # iterate over this list and for each vendor check length of orders

    delivery_statuses_today = OrderDeliveryStatus.objects.filter(date__gte=day_start, date__lte=day_end)
    delivery_statuses_today = delivery_statuses_today.filter(
        Q(order_status=constants.ORDER_STATUS_QUEUED) |
        Q(order_status=constants.ORDER_STATUS_INTRANSIT) |
        Q(order_status=constants.ORDER_STATUS_PICKUP_ATTEMPTED) |
        Q(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED) |
        Q(order_status=constants.ORDER_STATUS_DELIVERED) |
        Q(order_status=constants.ORDER_STATUS_OUTFORDELIVERY) |
        Q(order_status=constants.ORDER_STATUS_CANCELLED)
    )
    delivery_statuses_cancelled_today = delivery_statuses_today.filter(order_status=constants.ORDER_STATUS_CANCELLED)

    # Executed orders are delivery attempted and delivered orders since we charge the vendors under both these cases
    delivery_statuses_executed_today = delivery_statuses_today.filter(Q(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED) |
                                                                      Q(order_status=constants.ORDER_STATUS_DELIVERED))

    vendors_tracked = delivery_statuses_today.values('order__vendor__store_name'). \
        annotate(sum_of_cod_collected=Sum('cod_collected_amount'), sum_of_cod_amount=Sum('order__cod_amount'),
                 total_orders=Count('order'))

    # Adding COD exclusions for cancelled, pickup attempted and delivery attempted amount
    delivery_statuses_without_attempted = delivery_statuses_today.exclude(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED)
    delivery_statuses_without_attempted = delivery_statuses_without_attempted.exclude(order_status=constants.ORDER_STATUS_PICKUP_ATTEMPTED)
    delivery_statuses_without_attempted = delivery_statuses_without_attempted.exclude(order_status=constants.ORDER_STATUS_CANCELLED)
    vendors_tracked_2 = delivery_statuses_without_attempted.values('order__vendor__store_name'). \
        annotate(sum_of_cod_collected_without_attempted=Sum('cod_collected_amount'),
                 sum_of_cod_amount_without_attempted=Sum('order__cod_amount'), total_orders=Count('order'))

    # This is for handling delivery and pickup attempted case in COD
    # In both these cases, COD is not considered, but the order is still considered to be executed order
    for vendor in vendors_tracked:
        vendor_store_name = vendor['order__vendor__store_name']
        filtered_vendors = vendors_tracked_2.filter(order__vendor__store_name=vendor_store_name)
        if len(filtered_vendors) ==1:
            single = filtered_vendors[0]
            # for single in filtered_dgs:
            vendor['sum_of_cod_collected'] = single['sum_of_cod_collected_without_attempted']
            vendor['sum_of_cod_amount'] = single['sum_of_cod_amount_without_attempted']
        else:
            vendor['sum_of_cod_collected'] = 0
            vendor['sum_of_cod_amount'] = 0
    #=================================================================

    for item in vendors_tracked:
        vendor_name = item['order__vendor__store_name']
        sum_of_cod_collected = item['sum_of_cod_collected']
        sum_of_cod_amount = item['sum_of_cod_amount']
        orders_total_count = item['total_orders']

        vendors = Vendor.objects.get(store_name=vendor_name)
        vendor_mail_id = [vendors.email]

        # -----------------------------------------------------------------------------------

        if orders_total_count == 0:
            today_string = datetime.now().strftime("%Y %b %d")
            email_subject = 'YourGuy Vendor Report for %s: %s' % (vendor_name, today_string)

            email_body = "Good Evening,"
            email_body = email_body + "\n\n You have no orders today."
            email_body = email_body + "\n\n- YourGuy BOT"

            send_email(vendor_mail_id, email_subject, email_body)
            return Response(status=status.HTTP_200_OK)
        else:
            orders_for_this_vendor = OrderDeliveryStatus.objects.filter(date__gte=day_start, date__lte=day_end,
                                                                        order__vendor=vendors)
            list_of_orders = []
            for single_order in orders_for_this_vendor:
                order_ids = single_order.id
                list_of_orders.append(order_ids)

            cancelled_orders = delivery_statuses_cancelled_today.filter(order__vendor__store_name=vendor_name)
            count_cancelled_orders = len(cancelled_orders)

            executed_orders = delivery_statuses_executed_today.filter(order__vendor__store_name=vendor_name)
            count_executed_orders = len(executed_orders)

            today_string = datetime.now().strftime("%Y %b %d")
            email_subject = 'YourGuy Vendor Report for %s: %s' % (vendor_name, today_string)

            email_body = "Good Evening Guys, \n\nPlease find the report of the day."
            email_body = email_body + "\nTotal orders = %s" % (orders_total_count)
            email_body = email_body + "\nCanceled orders = %s" % (count_cancelled_orders)
            email_body = email_body + "\nExecuted orders = %s" % (count_executed_orders)
            email_body = email_body + "\nCOD supposed to be collected: %s" % (sum_of_cod_amount)
            email_body = email_body + "\nCOD collected: %s" % (sum_of_cod_collected)
            email_body = email_body + "\nAll order numbers: %s" % (list_of_orders)

            email_body = email_body + "\n-----------------------------------"
            email_body = email_body + "\n\n- YourGuy BOT"

            send_email(vendor_mail_id, email_subject, email_body)
    #return Response(status=status.HTTP_200_OK)
예제 #5
0
def dg_report():
    date = datetime.today()
    day_start = ist_day_start(date)
    day_end = ist_day_end(date)

    # Number of dgs working today ----------------------------------------------------------------------
    dg_working_today_count = DGAttendance.objects.filter(login_time__gte=day_start, login_time__lte=day_end).count()

    # --------------------------------------------
    delivery_statuses_today = OrderDeliveryStatus.objects.filter(date__gte=day_start, date__lte=day_end)
    delivery_statuses_today = delivery_statuses_today.filter(
        Q(order_status=constants.ORDER_STATUS_QUEUED) |
        Q(order_status=constants.ORDER_STATUS_INTRANSIT) |
        Q(order_status=constants.ORDER_STATUS_PICKUP_ATTEMPTED) |
        Q(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED) |
        Q(order_status=constants.ORDER_STATUS_OUTFORDELIVERY) |
        Q(order_status=constants.ORDER_STATUS_DELIVERED)
    )
    delivery_statuses_today = delivery_statuses_today.exclude(order_status=constants.ORDER_STATUS_PICKUP_ATTEMPTED)
    all_dgs = delivery_statuses_today.values('delivery_guy__user__username'). \
        annotate(sum_of_cod_collected=Sum('cod_collected_amount'), sum_of_cod_amount=Sum('order__cod_amount'))

    delivery_statuses_without_attempted = delivery_statuses_today.exclude(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED)
    all_dgs_2 = delivery_statuses_without_attempted.values('delivery_guy__user__username'). \
        annotate(sum_of_cod_collected_without_attempted=Sum('cod_collected_amount'),
                 sum_of_cod_amount_without_attempted=Sum('order__cod_amount'))

    # This is for handling delivery attempted and pickup attempted case in COD
    # In both these cases, COD is not considered, but the order is still considered to be executed order
    for dg in all_dgs:
        dg_phone_number = dg['delivery_guy__user__username']
        filtered_dgs = all_dgs_2.filter(delivery_guy__user__username=dg_phone_number)
        if len(filtered_dgs) ==1:
            single = filtered_dgs[0]
            # for single in filtered_dgs:
            dg['sum_of_cod_collected'] = single['sum_of_cod_collected_without_attempted']
            dg['sum_of_cod_amount'] = single['sum_of_cod_amount_without_attempted']
        else:
            dg['sum_of_cod_collected'] = 0
            dg['sum_of_cod_amount'] = 0

    all_pgs = delivery_statuses_today.values('pickup_guy__user__username').annotate(
        sum_of_cod_amount=Sum('order__cod_amount'))

    all_ops_execs = Employee.objects.filter(department=constants.OPERATIONS)

    # -----------------------------------------------------------------------------------

    if dg_working_today_count == 0:
        today_string = datetime.now().strftime("%Y %b %d")
        email_subject = 'DG Report : %s' % (today_string)

        email_body = "Good Evening Guys,"
        email_body = email_body + "\n\n No DG working today."
        email_body = email_body + "\n\n- YourGuy BOT"

        send_email(constants.EMAIL_DG_REPORT, email_subject, email_body)
    else:
        # DG details for today
        today_string = datetime.now().strftime("%Y %b %d")
        email_subject = 'DG Report : %s' % (today_string)

        email_body = "Good Evening Guys, \nPlease find the dg report of the day."
        email_body = email_body + "\nTotal dgs working today = %s" % (dg_working_today_count)

        orders_executed_dg = delivery_statuses_today.filter(Q(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED) |
                                                            Q(order_status=constants.ORDER_STATUS_DELIVERED))

        orders_executed_pg = delivery_statuses_today.filter(Q(order_status=constants.ORDER_STATUS_PICKUP_ATTEMPTED) |
                                                            Q(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED) |
                                                            Q(order_status=constants.ORDER_STATUS_DELIVERED) |
                                                            Q(order_status=constants.ORDER_STATUS_OUTFORDELIVERY))

        for single_ops_exec in all_ops_execs:
            associated_guys = single_ops_exec.associate_delivery_guys.all()
            orders_count = 0
            executed_orders_count = 0
            assigned_orders_count = 0
            ops_cod_to_be_collected = 0
            ops_cod_collected = 0
            pgs_data = []
            dgs_data = []

            for single_pg in all_pgs:
                pg_ph_number = single_pg['pickup_guy__user__username']
                if pg_ph_number is not None:
                    pickup_guy = DeliveryGuy.objects.get(user__username=pg_ph_number)
                    if pickup_guy in associated_guys:
                        pickup_guy_full_name = pickup_guy.user.first_name + pickup_guy.user.last_name

                        no_of_assigned_orders = delivery_statuses_today.filter(pickup_guy__user__username=pg_ph_number).count()
                        assigned_orders_count = assigned_orders_count + no_of_assigned_orders

                        no_of_executed_orders = orders_executed_pg.filter(pickup_guy__user__username=pg_ph_number).count()
                        executed_orders_count = executed_orders_count + no_of_executed_orders
                        pgs_data.append("%s - Orders: %s/%s" % (pickup_guy_full_name, no_of_executed_orders,
                                                                              no_of_assigned_orders))
                else:
                    # Handle case when pg is not assigned to an order but dg is assigned to the same order
                    pass

            for single_dg in all_dgs:
                dg_ph_number = single_dg['delivery_guy__user__username']
                if dg_ph_number is not None:
                    dg = DeliveryGuy.objects.get(user__username=dg_ph_number)
                    if dg in associated_guys:
                        cod_collected = single_dg['sum_of_cod_collected']
                        if cod_collected is None:
                            cod_collected = 0

                        cod_to_be_collected = single_dg['sum_of_cod_amount']
                        if cod_to_be_collected is None:
                            cod_to_be_collected = 0

                        dg_full_name = dg.user.first_name + dg.user.last_name

                        no_of_assigned_orders = delivery_statuses_today.filter(delivery_guy__user__username=dg_ph_number).count()
                        assigned_orders_count = assigned_orders_count + no_of_assigned_orders

                        no_of_executed_orders = orders_executed_dg.filter(delivery_guy__user__username=dg_ph_number).count()
                        executed_orders_count = executed_orders_count + no_of_executed_orders
                        dgs_data.append("%s - Orders: %s/%s, COD: %s/%s" % (dg_full_name, no_of_executed_orders,
                                                                                          no_of_assigned_orders, cod_collected,
                                                                                          cod_to_be_collected))
                        ops_cod_to_be_collected = ops_cod_to_be_collected + cod_to_be_collected
                        ops_cod_collected = ops_cod_collected + cod_collected

                        orders_count = "%s/%s" %(executed_orders_count, assigned_orders_count)
                else:
                    # Handle Case when dg is not assigned to an order but pg is assigned to same order
                    pass

            email_body = email_body + "\n\nOPS EXECUTIVE %s - Orders: %s, COD: %s/%s"%(single_ops_exec.user.first_name,
                                                                                       orders_count, ops_cod_collected,
                                                                                       ops_cod_to_be_collected)
            email_body = email_body + "\nPickup boys:\n"
            for single in pgs_data:
                email_body = email_body + single +"\n"
            email_body = email_body + "Delivery Boys:\n"
            for single in dgs_data:
                email_body = email_body + single + "\n"
        # ---------------------------------------------------
        # For unassociated pgs and dgs
        all_associated_guys = []
        all_unassociated_pgs = []
        all_unassociated_dgs = []

        orders_count = 0
        assigned_orders_count = 0
        executed_orders_count = 0
        ops_cod_to_be_collected = 0
        ops_cod_collected = 0

        for single_ops_exec in all_ops_execs:
            all_associated_guys.extend(single_ops_exec.associate_delivery_guys.all())

        for single_pg in all_pgs:
            pg_ph_number = single_pg['pickup_guy__user__username']
            if pg_ph_number is not None:
                pickup_guy = DeliveryGuy.objects.get(user__username=pg_ph_number)
                if not (pickup_guy in all_associated_guys):
                    pickup_guy_full_name = pickup_guy.user.first_name + pickup_guy.user.last_name

                    no_of_assigned_orders = delivery_statuses_today.filter(pickup_guy__user__username=pg_ph_number).count()
                    assigned_orders_count = assigned_orders_count + no_of_assigned_orders

                    no_of_executed_orders = orders_executed_pg.filter(pickup_guy__user__username=pg_ph_number).count()
                    executed_orders_count = executed_orders_count + no_of_executed_orders
                    all_unassociated_pgs.append("%s - Orders: %s/%s" % (pickup_guy_full_name, no_of_executed_orders,
                                                                            no_of_assigned_orders))
        for single_dg in all_dgs:
            dg_ph_number = single_dg['delivery_guy__user__username']
            if dg_ph_number is not None:
                dg = DeliveryGuy.objects.get(user__username=dg_ph_number)
                if dg not in all_associated_guys:
                    cod_collected = single_dg['sum_of_cod_collected']
                    if cod_collected is None:
                        cod_collected = 0

                    cod_to_be_collected = single_dg['sum_of_cod_amount']
                    if cod_to_be_collected is None:
                        cod_to_be_collected = 0

                    dg_full_name = dg.user.first_name + dg.user.last_name

                    no_of_assigned_orders = delivery_statuses_today.filter(delivery_guy__user__username=dg_ph_number).count()
                    assigned_orders_count = assigned_orders_count + no_of_assigned_orders

                    no_of_executed_orders = orders_executed_dg.filter(delivery_guy__user__username=dg_ph_number).count()
                    executed_orders_count = executed_orders_count + no_of_executed_orders
                    all_unassociated_dgs.append("%s - Orders: %s/%s, COD: %s/%s" % (dg_full_name, no_of_executed_orders,
                                                                                        no_of_assigned_orders, cod_collected,
                                                                                        cod_to_be_collected))
                    ops_cod_to_be_collected = ops_cod_to_be_collected + cod_to_be_collected
                    ops_cod_collected = ops_cod_collected + cod_collected

                    orders_count = "%s/%s" %(executed_orders_count, assigned_orders_count)

        email_body = email_body + "\n\nUNASSOCIATED PICKP/DELIVERY BOYS - Orders: %s, COD: %s/%s"%(orders_count, ops_cod_collected,
                                                                                       ops_cod_to_be_collected)

        email_body = email_body + "\nPickup Boys:\n"
        for single in all_unassociated_pgs:
            email_body = email_body + single +"\n"
        email_body = email_body + "Delivery Boys:\n"
        for single in all_unassociated_dgs:
            email_body = email_body + single + "\n"

        email_body = email_body + "\n"
        email_body = email_body + "\n\n- YourGuy BOT"
        send_email(constants.EMAIL_DG_REPORT, email_subject, email_body)
예제 #6
0
def cod_report():
    date = datetime.today()
    day_start = ist_day_start(date)
    day_end = ist_day_end(date)

    # TOTAL ORDERS ----------------------------------------------------------------------
    delivery_statuses_today = OrderDeliveryStatus.objects.filter(date__gte=day_start, date__lte=day_end,
                                                                 order__cod_amount__gt=0)
    orders_total_count = len(delivery_statuses_today)
    # -----------------------------------------------------------------------------------

    if orders_total_count == 0:
        today_string = datetime.now().strftime("%Y %b %d")
        email_subject = 'COD Report : %s' % (today_string)

        email_body = "Good Evening Guys,"
        email_body = email_body + "\n\n No COD today on the app."
        email_body = email_body + "\n\n- YourGuy BOT"

        send_email(constants.EMAIL_COD_REPORT, email_subject, email_body)
        return Response(status=status.HTTP_200_OK)
    else:
        # COD as per ORDER_STATUS --------------------------------------------------------
        orders_pending_queryset = delivery_statuses_today.filter(Q(order_status=constants.ORDER_STATUS_QUEUED) |
                                                                 Q(order_status=constants.ORDER_STATUS_OUTFORDELIVERY) |
                                                                 Q(order_status=constants.ORDER_STATUS_INTRANSIT))
        orders_pending = orders_pending_queryset.aggregate(sum_of_cod_amount=Sum('order__cod_amount'))
        pending_cod_amount = orders_pending['sum_of_cod_amount']
        if pending_cod_amount is None:
            pending_cod_amount = 0

        orders_attempted_queryset = delivery_statuses_today.filter(
            Q(order_status=constants.ORDER_STATUS_PICKUP_ATTEMPTED) |
            Q(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED))
        orders_attempted = orders_attempted_queryset.aggregate(sum_of_cod_amount=Sum('order__cod_amount'))
        attempted_cod_amount = orders_attempted['sum_of_cod_amount']
        if attempted_cod_amount is None:
            attempted_cod_amount = 0

        orders_cancelled_queryset = delivery_statuses_today.filter(order_status=constants.ORDER_STATUS_CANCELLED)
        orders_cancelled = orders_cancelled_queryset.aggregate(sum_of_cod_amount=Sum('order__cod_amount'))
        cancelled_cod_amount = orders_cancelled['sum_of_cod_amount']
        if cancelled_cod_amount is None:
            cancelled_cod_amount = 0

        orders_executed_queryset = delivery_statuses_today.filter(Q(order_status=constants.ORDER_STATUS_DELIVERED) &
                                                                  Q(cod_collected_amount__lt=F('order__cod_amount')))
        orders_executed = orders_executed_queryset.aggregate(sum_of_cod_collected=Sum('cod_collected_amount'),
                                                             sum_of_cod_amount=Sum('order__cod_amount'))
        delivered_cod_collected = orders_executed['sum_of_cod_collected']
        if delivered_cod_collected is None:
            delivered_cod_collected = 0

        delivered_cod_amount = orders_executed['sum_of_cod_amount']
        if delivered_cod_amount is None:
            delivered_cod_amount = 0

        pending_cod = delivered_cod_amount - delivered_cod_collected
        pending_cod_amount = pending_cod_amount + pending_cod
        if pending_cod_amount is None:
            pending_cod_amount = 0

        delivery_statuses_tracked_queryset = delivery_statuses_today.filter(
            Q(order_status=constants.ORDER_STATUS_QUEUED) |
            Q(order_status=constants.ORDER_STATUS_INTRANSIT) |
            Q(order_status=constants.ORDER_STATUS_DELIVERED) |
            Q(order_status=constants.ORDER_STATUS_OUTFORDELIVERY) |
            Q(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED)
        )

        collected = delivery_statuses_today.aggregate(Sum('cod_collected_amount'))
        total_cod_collected = collected['cod_collected_amount__sum']

        total_cod = delivery_statuses_tracked_queryset.aggregate(total_cod=Sum('order__cod_amount'))
        total_cod_amount = total_cod['total_cod']

        # -------------------------------------------------------------------------------

        today_string = datetime.now().strftime("%Y %b %d")
        email_subject = "COD Report : %s" % (today_string)

        email_body = "Good Evening Guys, \nPlease find the COD report of the day."
        email_body = email_body + "\n-----------------------\n"

        email_body = email_body + "\nDELIVERY STATUS wise COD"
        email_body = email_body + "\n-----------------------"
        email_body = email_body + "\nPENDING Orders amount: %0.0f" % (pending_cod_amount)

        email_body = email_body + "\nATTEMPTED Orders amount: %0.0f" % (attempted_cod_amount)

        email_body = email_body + "\nCANCELLED Orders amount: %0.0f" % (cancelled_cod_amount)

        email_body = email_body + "\nTOTAL COD amount: %0.0f" % (total_cod_amount)

        email_body = email_body + "\nCOLLECTED COD amount: %0.0f" % (total_cod_collected)
        email_body = email_body + "\n-----------------------\n"

        # COD as per VENDOR --------------------------------------------------------
        # all tracked orders
        delivery_statuses_tracked_queryset = delivery_statuses_today.filter(
            Q(order_status=constants.ORDER_STATUS_QUEUED) |
            Q(order_status=constants.ORDER_STATUS_INTRANSIT) |
            Q(order_status=constants.ORDER_STATUS_OUTFORDELIVERY) |
            Q(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED) |
            Q(order_status=constants.ORDER_STATUS_DELIVERED))
        delivery_statuses_tracked_queryset = delivery_statuses_tracked_queryset.filter(order__cod_amount__gt=0)
        vendors_tracked = delivery_statuses_tracked_queryset.values('order__vendor__store_name'). \
            annotate(sum_of_cod_collected=Sum('cod_collected_amount'), sum_of_cod_amount=Sum('order__cod_amount'))

        cod_with_vendor = ''
        for item in vendors_tracked:
            vendor = item['order__vendor__store_name']
            sum_of_cod_collected = item['sum_of_cod_collected']
            if sum_of_cod_collected is None:
                sum_of_cod_collected = 0

            sum_of_cod_amount = item['sum_of_cod_amount']
            if sum_of_cod_amount is None:
                sum_of_cod_amount = 0

            cod_with_vendor = cod_with_vendor + \
                              "\n%s - COD: %s/%s" % \
                              (vendor, sum_of_cod_collected, sum_of_cod_amount)
        # -----------------------------------------------------------------------------------
        email_body = email_body + "\n-----------------------\n"
        email_body = email_body + "\nVENDOR wise COD: \n* COD of pending and attempted orders are not considered."
        email_body = email_body + "\n\n" + cod_with_vendor

        # COD as per DG
        # dict of all DGs for tracked orders
        email_body = email_body + "\n-----------------------"
        email_body = email_body + "\nDG wise COD: \n* COD of pending and attempted orders are not considered."

        dg_tracked = delivery_statuses_tracked_queryset.values('delivery_guy__user__username'). \
            annotate(sum_of_cod_collected=Sum('cod_collected_amount'), sum_of_cod_amount=Sum('order__cod_amount'))
        cod_with_dg = ''
        # for each DG, display his total collection and amount supposed to be collected
        for single_dg in dg_tracked:
            dg_ph_number = single_dg['delivery_guy__user__username']
            sum_of_cod_collected = single_dg['sum_of_cod_collected']
            if sum_of_cod_collected is None:
                sum_of_cod_collected = 0

            sum_of_cod_amount = single_dg['sum_of_cod_amount']
            if sum_of_cod_amount is None:
                sum_of_cod_amount = 0

            if dg_ph_number is not None:
                dg = DeliveryGuy.objects.get(user__username=dg_ph_number)
                dg_full_name = dg.user.first_name + dg.user.last_name
            else:
                dg_full_name = 'Unassigned'

            cod_with_dg = "%s - COD: %s/%s" % \
                          (dg_full_name, sum_of_cod_collected, sum_of_cod_amount)
            email_body = email_body + "\n\n" + cod_with_dg
            # ===============================================================
            # For the same DG, specify vendor wise collection bifurcation,
            # For doing this, vendor and dg is being associated using order & filter by dg name and then by vendor name
            orders_tracked = OrderDeliveryStatus.objects.filter(
                delivery_guy__user__username=single_dg['delivery_guy__user__username'], date__gte=day_start,
                date__lte=day_end)
            orders_tracked = orders_tracked.filter(Q(order_status=constants.ORDER_STATUS_QUEUED) |
                                                   Q(order_status=constants.ORDER_STATUS_INTRANSIT) |
                                                   Q(order_status=constants.ORDER_STATUS_OUTFORDELIVERY) |
                                                   Q(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED) |
                                                   Q(order_status=constants.ORDER_STATUS_DELIVERED))
            orders_tracked = orders_tracked.filter(order__cod_amount__gt=0)
            vendor_tracked_per_order = orders_tracked.values('order__vendor__store_name').annotate(
                sum_of_cod_collected=Sum('cod_collected_amount'), sum_of_cod_amount=Sum('order__cod_amount'))
            for item in vendor_tracked_per_order:
                vendor_name = item['order__vendor__store_name']
                sum_of_cod_collected = item['sum_of_cod_collected']
                if sum_of_cod_collected is None:
                    sum_of_cod_collected = 0

                sum_of_cod_amount = item['sum_of_cod_amount']
                if sum_of_cod_amount is None:
                    sum_of_cod_amount = 0

                cod_with_vendor = ''
                cod_with_vendor = "  %s- COD: %s/%s" % (vendor_name, sum_of_cod_collected, sum_of_cod_amount)
                email_body = email_body + "\n" + cod_with_vendor

        # ---------------------------------------------------------------------------
        email_body = email_body + "\n----------------------------"
        email_body = email_body + "\n\n- YourGuy BOT"

        send_email(constants.EMAIL_COD_REPORT, email_subject, email_body)
예제 #7
0
def daily_report():
    date = datetime.today()
    day_start = ist_day_start(date)
    day_end = ist_day_end(date)

    # TOTAL ORDERS ----------------------------------------------------------------------
    delivery_statuses_today = OrderDeliveryStatus.objects.filter(date__gte=day_start, date__lte=day_end)
    orders_total_count = len(delivery_statuses_today)
    # -----------------------------------------------------------------------------------

    if orders_total_count == 0:
        today_string = datetime.now().strftime("%Y %b %d")
        email_subject = 'Daily Report : %s' % (today_string)

        email_body = "Good Evening Guys,"
        email_body = email_body + "\n\n No orders on the app."
        email_body = email_body + "\n\n Chill out!"
        email_body = email_body + "\n\n- YourGuy BOT"

        send_email(constants.EMAIL_IDS_EVERYBODY, email_subject, email_body)
        return Response(status=status.HTTP_200_OK)
    else:
        # TOTAL ORDERS ASSIGNED vs UNASSIGNED ORDERS ----------------------------------------
        orders_unassigned_count = delivery_statuses_today.filter(delivery_guy=None).count()
        orders_assigned_count = orders_total_count - orders_unassigned_count

        orders_unassigned_percentage = "{0:.0f}%".format(
            float(orders_unassigned_count) / float(orders_total_count) * 100)
        orders_assigned_percentage = "{0:.0f}%".format(float(orders_assigned_count) / float(orders_total_count) * 100)
        # -----------------------------------------------------------------------------------

        # ORDERS ACC TO ORDER_STATUS --------------------------------------------------------
        orders_placed_count = delivery_statuses_today.filter(order_status=constants.ORDER_STATUS_PLACED).count()

        orders_queued_count = delivery_statuses_today.filter(order_status=constants.ORDER_STATUS_QUEUED).count()
        orders_queued_percentage = "{0:.0f}%".format(float(orders_queued_count) / float(orders_total_count) * 100)

        orders_intransit_count = delivery_statuses_today.filter(order_status=constants.ORDER_STATUS_INTRANSIT).count()
        orders_intransit_percentage = "{0:.0f}%".format(float(orders_intransit_count) / float(orders_total_count) * 100)

        orders_out_for_delivery_count = delivery_statuses_today.filter(order_status=constants.ORDER_STATUS_OUTFORDELIVERY).count()
        orders_out_for_delivery_percentage = "{0:.0f}%".format(float(orders_out_for_delivery_count) / float(orders_total_count) * 100)

        orders_delivered_count = delivery_statuses_today.filter(order_status=constants.ORDER_STATUS_DELIVERED).count()
        orders_delivered_percentage = "{0:.0f}%".format(float(orders_delivered_count) / float(orders_total_count) * 100)

        orders_pickup_attempted_count = delivery_statuses_today.filter(
            order_status=constants.ORDER_STATUS_PICKUP_ATTEMPTED).count()
        orders_pickup_attempted_percentage = "{0:.0f}%".format(
            float(orders_pickup_attempted_count) / float(orders_total_count) * 100)

        orders_delivery_attempted_count = delivery_statuses_today.filter(
            order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED).count()
        orders_delivery_attempted_percentage = "{0:.0f}%".format(
            float(orders_delivery_attempted_count) / float(orders_total_count) * 100)

        orders_rejected_count = delivery_statuses_today.filter(order_status=constants.ORDER_STATUS_REJECTED).count()
        orders_rejected_percentage = "{0:.0f}%".format(float(orders_rejected_count) / float(orders_total_count) * 100)

        orders_canceled_count = delivery_statuses_today.filter(order_status=constants.ORDER_STATUS_CANCELLED).count()
        orders_canceled_percentage = "{0:.0f}%".format(float(orders_canceled_count) / float(orders_total_count) * 100)

        pending_orders_count = orders_queued_count + orders_placed_count + orders_intransit_count + orders_out_for_delivery_count
        pending_orders_percentage = "{0:.0f}%".format(float(pending_orders_count) / float(orders_total_count) * 100)

        completed_orders_count = orders_delivered_count + orders_pickup_attempted_count + \
                                 orders_delivery_attempted_count + orders_rejected_count + orders_canceled_count
        completed_orders_percentage = "{0:.0f}%".format(float(completed_orders_count) / float(orders_total_count) * 100)
        # -----------------------------------------------------------------------------------

        # DG ATTENDANCE DETAILS -------------------------------------------------------------
        total_dg_count = DeliveryGuy.objects.all().count()
        total_dg_checked_in_count = DGAttendance.objects.filter(date__year=date.year, date__month=date.month,
                                                                date__day=date.day).count()
        dg_checkin_percentage = "{0:.0f}%".format(float(total_dg_checked_in_count) / float(total_dg_count) * 100)
        # -----------------------------------------------------------------------------------

        # TOTAL COD COLLECTED Vs SUPPOSSED TO BE COLLECTED ----------------------------------
        total_cod_collected = delivery_statuses_today.aggregate(Sum('cod_collected_amount'))
        total_cod_collected = total_cod_collected['cod_collected_amount__sum']
        if total_cod_collected is None:
            total_cod_collected = 0

        executable_deliveries = delivery_statuses_today.filter(
            Q(order_status=constants.ORDER_STATUS_QUEUED) |
            Q(order_status=constants.ORDER_STATUS_INTRANSIT) |
            Q(order_status=constants.ORDER_STATUS_DELIVERED) |
            Q(order_status=constants.ORDER_STATUS_DELIVERY_ATTEMPTED) |
            Q(order_status=constants.ORDER_STATUS_OUTFORDELIVERY) |
            Q(order_status=constants.ORDER_STATUS_PICKUP_ATTEMPTED))
        total_cod_dict = executable_deliveries.aggregate(total_cod=Sum('order__cod_amount'))
        total_cod_to_be_collected = total_cod_dict['total_cod']
        if total_cod_to_be_collected is None:
            total_cod_to_be_collected = 0

        if total_cod_to_be_collected > 0:
            cod_collected_percentage = "{0:.0f}%".format(
                float(total_cod_collected) / float(total_cod_to_be_collected) * 100)
        else:
            cod_collected_percentage = "100%"
        # -----------------------------------------------------------------------------------

        # DELIVERY BOY WHO HAVE COD --------------------------------------------------------
        cod_deliveries = delivery_statuses_today.filter(cod_collected_amount__gt=0)
        cod_with_delivery_boys = cod_deliveries.values('delivery_guy__user__first_name').annotate(
            total=Sum('cod_collected_amount'))

        cod_with_dg_string = ''
        for item in cod_with_delivery_boys:
            delivery_guy = item['delivery_guy__user__first_name']
            total = item['total']
            if total is None:
                total = 0
            cod_with_dg_string = cod_with_dg_string + "\n%s = %s" % (delivery_guy, total)
        # -----------------------------------------------------------------------------------
        today_string = datetime.now().strftime("%Y %b %d")
        email_subject = 'Daily Report : %s' % (today_string)

        email_body = "Good Evening Guys, \n\nPlease find the report of the day."
        email_body = email_body + "\n\nTotal orders = %s" % (orders_total_count)

        email_body = email_body + "\nPending orders     = %s [%s percent]" % (
            pending_orders_count, pending_orders_percentage)
        email_body = email_body + "\nExecuted orders    = %s [%s percent]" % (
            completed_orders_count, completed_orders_percentage)

        email_body = email_body + "\n\nSTATUS WISE BIFURGATION ------------"
        email_body = email_body + "\nOrders assigned    = %s [%s percent]" % (
            orders_assigned_count, orders_assigned_percentage)
        email_body = email_body + "\nOrders unassigned  = %s [%s percent]" % (
            orders_unassigned_count, orders_unassigned_percentage)
        email_body = email_body + "\nQueued         = %s [%s percent]" % (orders_queued_count, orders_queued_percentage)
        email_body = email_body + "\nInTransit      = %s [%s percent]" % (
            orders_intransit_count, orders_intransit_percentage)
        email_body = email_body + "\nOutForDelivery      = %s [%s percent]" % (
            orders_out_for_delivery_count, orders_out_for_delivery_percentage)
        email_body = email_body + "\nDelivered      = %s [%s percent]" % (
            orders_delivered_count, orders_delivered_percentage)
        email_body = email_body + "\nPickup Attempted   = %s [%s percent]" % (
            orders_pickup_attempted_count, orders_pickup_attempted_percentage)
        email_body = email_body + "\nDelivery Attempted = %s [%s percent]" % (
            orders_delivery_attempted_count, orders_delivery_attempted_percentage)
        email_body = email_body + "\nRejected       = %s [%s percent]" % (
            orders_rejected_count, orders_rejected_percentage)
        email_body = email_body + "\nCanceled       = %s [%s percent]" % (
            orders_canceled_count, orders_canceled_percentage)
        email_body = email_body + "\n------------------------------------"

        email_body = email_body + "\n\nDELIVERY BOY ATTENDANCE -------"
        email_body = email_body + "\nTotal DGs on app   = %s" % total_dg_count
        email_body = email_body + "\nTotal DGs CheckIn  = %s [%s percent]" % (
            total_dg_checked_in_count, dg_checkin_percentage)
        email_body = email_body + "\n-----------------------------------"

        email_body = email_body + "\n\nCOD DETAILS ------------------"
        email_body = email_body + "\nTotal COD to be collected  = %s" % total_cod_to_be_collected
        email_body = email_body + "\nTotal COD collected        = %s [%s percent]" % (
            total_cod_collected, cod_collected_percentage)

        email_body = email_body + "\n-----------------------------------"

        email_body = email_body + "\n\nCOD WITH EACH DG ------------------"
        email_body = email_body + cod_with_dg_string
        email_body = email_body + "\n-----------------------------------"
        email_body = email_body + "\n\n- YourGuy BOT"

        send_email(constants.EMAIL_DAILY_REPORT, email_subject, email_body)
예제 #8
0
def assign_dg():
    # FETCH ALL TODAY ORDERS --------------------------------------------

    date = datetime.today()
    day_start = ist_day_start(date)
    day_end = ist_day_end(date)

    # FILTER TO BE ASSIGNED ORDERS -------------------------------------------------------------------------
    delivery_status_queryset = OrderDeliveryStatus.objects.filter(date__gte=day_start, date__lte=day_end)
    delivery_status_queryset = delivery_status_queryset.filter(Q(delivery_guy=None) | Q(pickup_guy=None))
    delivery_status_queryset = delivery_status_queryset.filter(
        Q(order_status=constants.ORDER_STATUS_PLACED) |
        Q(order_status=constants.ORDER_STATUS_QUEUED) |
        Q(order_status=constants.ORDER_STATUS_INTRANSIT))
    # --------------------------------------------------------------------------------------------------------

    # --------------------------------------------------------------------
    for delivery_status in delivery_status_queryset.all():
        try:
            order = delivery_status.order

            # CUSTOMER AND VENDOR FILTERING -----------------------------------------------------------------
            vendor = order.vendor
            consumer = order.consumer

            previous_delivery_statuses = OrderDeliveryStatus.objects.filter(
                delivery_guy__isnull=False, order__consumer=consumer, order__vendor=vendor)
            # ------------------------------------------------------------------------------------------------

            # FILTER LAST 1 MONTHS ORDERS --------------------------------------------------------------------
            two_months_previous_date = day_start - dateutil.relativedelta.relativedelta(months=1)
            previous_delivery_statuses = previous_delivery_statuses.filter(
                date__gte=two_months_previous_date, date__lte=day_start)
            # ------------------------------------------------------------------------------------------------

            # FILTERING BY PICKUP TIME RANGE -----------------------------------------------------------------
            pickup_hour = int(order.pickup_datetime.hour)
            previous_delivery_statuses = previous_delivery_statuses.filter(
                Q(order__pickup_datetime__hour=pickup_hour - 1) |
                Q(order__pickup_datetime__hour=pickup_hour) |
                Q(order__pickup_datetime__hour=pickup_hour + 1))
            # ------------------------------------------------------------------------------------------------

            # PICK LATEST PICKUP ASSIGNED PREVIOUSLY AND ASSIGN FOR TODAY ---------------------------------------
            try:
                if delivery_status.pickup_guy is None:
                    latest_assigned_pickup = previous_delivery_statuses.exclude(pickup_guy=None).latest('date')
                    if latest_assigned_pickup is not None:
                        delivery_status.pickup_guy = latest_assigned_pickup.pickup_guy
                        delivery_status.save()
            except Exception as e:
                pass
            # ------------------------------------------------------------------------------------------------
            
            # PICK LATEST DELIVERY ASSIGNED AND ASSIGN FOR TODAY ------------------------------------------------
            try:
                if delivery_status.delivery_guy is None:
                    latest_assigned_delivery = previous_delivery_statuses.exclude(delivery_guy=None).latest('date')
                    if latest_assigned_delivery is not None:
                        delivery_status.delivery_guy = latest_assigned_delivery.delivery_guy
                        delivery_status.save()
            except Exception as e:
                pass
                # ------------------------------------------------------------------------------------------------
        except Exception as e:
            pass
    
    delivery_status_queryset = OrderDeliveryStatus.objects.filter(date__gte=day_start, date__lte=day_end)
    delivery_status_queryset = delivery_status_queryset.filter(
        Q(order_status=constants.ORDER_STATUS_PLACED) |
        Q(order_status=constants.ORDER_STATUS_QUEUED) |
        Q(order_status=constants.ORDER_STATUS_INTRANSIT))

    unassigned_pickups_queryset = delivery_status_queryset.filter(Q(pickup_guy=None)).values('order__vendor__store_name').annotate(the_count=Count('order__vendor__store_name'))
    unassigned_pickups_string = ''
    for unassigned_pickups in unassigned_pickups_queryset:
        unassigned_pickups_string = unassigned_pickups_string + '%s - %s\n'%(unassigned_pickups['order__vendor__store_name'],unassigned_pickups['the_count'])

    unassigned_deliveries_queryset = delivery_status_queryset.filter(Q(delivery_guy=None)).values('order__vendor__store_name').annotate(the_count=Count('order__vendor__store_name'))
    unassigned_deliveries_string = ''    
    for unassigned_deliveries in unassigned_deliveries_queryset:
        unassigned_deliveries_string = unassigned_deliveries_string + '%s - %s\n'%(unassigned_deliveries['order__vendor__store_name'],unassigned_deliveries['the_count'])

    # SEND AN EMAIL SAYING CANT FIND APPROPRAITE DELIVERY GUY FOR THIS ORDER. PLEASE ASSIGN MANUALLY
    today_string = datetime.now().strftime("%Y %b %d")
    email_subject = 'Unassigned orders for %s' % (today_string)

    email_body = "Hello, \nPlease find the unassigned orders for the day. " \
                 "\nUnassigned pickups: \n%s \n\nUnassigned deliveries: \n%s \n\nPlease assign manually. \n\n- Team YourGuy" \
                 % (unassigned_pickups_string, unassigned_deliveries_string)
    send_email(constants.EMAIL_UNASSIGNED_ORDERS, email_subject, email_body)