Subversion Repositories SmartDukaan

Rev

Rev 13144 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#!/usr/bin/python
'''
It processes the following orders:
 1. Orders in DOA_PICKUP_CONFIRMED status : get details of orders that 
     were in DOA_PICKUP_CONFIRMED status from database and 
     calls BlueDart api to know whether they are picked up by BlueDart
     and changes the status to DOA_RETURN_IN_TRANSIT if it is done.
 2. Orders in RET_PICKUP_CONFIRMED status : get details of orders that 
     were in RET_PICKUP_CONFIRMED status from database and 
     calls BlueDart api to know whether they are picked up by BlueDart
     and changes the status to RET_RETURN_IN_TRANSIT if it is done.
 3. Orders in SHIPPED_FROM_WH status: get details of orders that
     were in SHIPPED_FROM_WH status from database and 
     calls BlueDart api to know whether they are picked up by BlueDart
     and changes the status to SHIPPED_TO_LOGST if it is done.
 4. Orders in SHIPPED_TO_LOGST status: get details of orders that
     were in SHIPPED_TO_LOGST status from database and 
     calls BlueDart api to know their status and changes the status accordingly.

It sends out a Pickup mismatch report, Return orders Pickup Mismatch report, Doa Pickup mismatch report,
Undelivered orders report and Returned Orders report to cnc.center@shop2020.in

http://www.bluedart.com/servlet/RoutingServlet?handler=tnt&action=custawbquery&loginid=DEL24119&awb=ref&format=XML&lickey=6265d61bafa6292c5ddfdb1ee335ca80&verno=1.3&scan=1&numbers={variable1} is hard coded
to track DOA orders and for other orders ConfigClient is called to get bluedart_update_url

@author: Phani Kumar
'''
from datetime import datetime
from shop2020.clients.CRMClient import CRMClient
from shop2020.clients.LogisticsClient import LogisticsClient
from shop2020.clients.TransactionClient import TransactionClient
from shop2020.model.v1.order.script.LogisticUtils import \
    create_crm_tickets_for_delivey_attempted_orders
from shop2020.thriftpy.crm.ttypes import TicketCategory, TicketPriority, \
    TicketStatus, Activity, ActivityType, SearchFilter
from shop2020.thriftpy.model.v1.order.ttypes import TransactionServiceException, \
    OrderStatus
from shop2020.utils.EmailAttachmentSender import get_attachment_part, mail
from shop2020.utils.Utils import to_py_date
from suds.client import Client
from xml.etree.ElementTree import parse, fromstring
import StringIO
import ast
import csv
import gzip
import json
import optparse
import sys
import time
import traceback
import urllib2
import xmltodict
import zlib
import datetime

if __name__ == '__main__' and __package__ is None:
    import os
    sys.path.insert(0, os.getcwd())


RED_EXPRESS_URL = "http://tracking.getsetred.net/TrackingService.svc?wsdl"
username = 'C00086721141'
password = '87e95$'
tracking_Id_Type = 'REFERENCENO'
tracking_Level = 'ALL_DETAILS'

RED_EXPRESS_TRACKING_URL = 'http://webservices.getsetred.net/Services/BulkTracking.svc/'
headers = {
               "User-Agent" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.218 Safari/535.1",
               "Accept" : "    text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8",
               "Accept-Language" : "en-us,en;q=0.5",
               "Accept-Encoding" : "gzip, deflate",
               "Connection" : "keep-alive",
               "Accept-Charset" : "ISO-8859-1",
               "Content-type": "application/json; charset=UTF-8"
               }

client = None
def getClient():
    global client
    if client is None:
        client = Client(RED_EXPRESS_URL, timeout=70)
    return client

defaultUndeliveredAsssigneeId = 65
dtrUndeliveredAsssigneeId = 33

from_user = 'cnc.center@shop2020.in'
from_pwd = '5h0p2o2o'
to = ['cnc.center@shop2020.in', "amit.sirohi@shop2020.in", "sandeep.sachdeva@shop2020.in", "sunil.kumar@shop2020.in", "rajveer.singh@shop2020.in"]


def get_updates(awb_number): 
    str1 = getClient().service.ProcessTrackingRequest('<TrackingRequest><Request><UserID>' + username + '</UserID><Password>' + password + '</Password><TrackingID>' + awb_number + '</TrackingID><TrackingLevel>ALL_DETAILS</TrackingLevel></Request></TrackingRequest>')
    return str1

def get_updates_for_user(awb_number):
    root =  fromstring(str(get_updates(awb_number)))
    children = root.getchildren()
    results = []
    for child in children:
        nodes = child.findall('ShipmentInfo/ShipmentEvent')
        for element in reversed(nodes):
            datestring = element.findtext('Date', '')
            timestring = element.findtext('Time', '')
            description = element.findtext('ServiceEvent', '')
            results.append(datestring+"~!~"+timestring+"~!~"+description)
    return results

def get_track_updates(awb_numbers):
    track_data_list=[]
    if len(awb_numbers)>0:
        req_args = json.dumps({'password':password,
                               'trackingIdType':'REFERENCENO',
                               'trackingLevel':'ALL_DETAILS',
                               'userId':username,
                               'waybillNo': awb_numbers 
                               })
        request = urllib2.Request(RED_EXPRESS_TRACKING_URL, req_args, headers)
        response = urllib2.urlopen(request)
    
        encoding = response.info().get("Content-Encoding")    
        if encoding in ('gzip', 'x-gzip', 'deflate'):
            content = response.read()
            if encoding == 'deflate':
                track_data_decoded = StringIO.StringIO(zlib.decompress(content))
            else:
                track_data_decoded = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(content))
        track_data_readable = track_data_decoded.read()
        
        conv_dict = xmltodict.parse(track_data_readable)
        track_data_json= json.dumps(conv_dict)
        if track_data_json.find('null') > 0:
            track_data_json = track_data_json.replace('null','\"No Description Available\"');
        track_data_dict = ast.literal_eval(track_data_json)
    
        if len(awb_numbers)==1:
            track_data_list=[]
            track_data_list.append(track_data_dict['BulkTrackingResponse']['BulkResponse']['TrackingResponse'])
            track_data_list.append('DUMMY')
        else:
            track_data_list = track_data_dict['BulkTrackingResponse']['BulkResponse']['TrackingResponse']    
    
    return track_data_list
    
    
def process_dao_pickup_orders(provider):
    try:
        doas_tobe_picked_up = fetch_data(provider.id, [OrderStatus.DOA_PICKUP_CONFIRMED])
        doa_pickup_details = read_dao_return_pickup_orders(doas_tobe_picked_up)
        if doa_pickup_details:
            update_picked_doas(provider.id, doa_pickup_details)
    except:
        print "Some issue while processing the orders in DOA_PICKUP_CONFIRMED status"
        traceback.print_exc()

def process_return_pickup_orders(provider):
    try:
        returns_tobe_picked_up = fetch_data(provider.id, [OrderStatus.RET_PICKUP_CONFIRMED])
        returns_pickup_details = read_dao_return_pickup_orders(returns_tobe_picked_up)
        if returns_pickup_details:
            update_picked_returns(provider.id, returns_pickup_details)
    except:
        print "Some issue while processing the orders in RET_PICKUP_CONFIRMED status"
        traceback.print_exc()

def process_pickup_records(provider):
    try:
        orders_tobe_picked_up = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH])
        pickup_details = read_pickup_orders(orders_tobe_picked_up)
        if pickup_details:
            update_picked_orders(provider.id, pickup_details)
    except:
        print "Some issue while processing the orders in SHIPPED_FROM_WH status"
        traceback.print_exc()

def process_local_connection_orders(provider):
    try:
        orders_tobe_local_connected = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST])
        local_connected_orders = read_local_connection_orders(orders_tobe_local_connected)
        if local_connected_orders:
            update_local_connected_orders(provider.id, local_connected_orders)
    except:
        print "Some issue while processing the orders for local connection status"
        traceback.print_exc()

def process_first_delivery_attempt_orders(provider):
    try:
        orders_tobe_first_delivery_attempted = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY])
        first_atdl_orders = read_first_delivery_attempt_orders(orders_tobe_first_delivery_attempted)
        if first_atdl_orders:
            update_first_atdl_orders(provider.id, first_atdl_orders)
    except:
        print "Some issue while processing the orders for First delivery attempt status"
        traceback.print_exc()

def process_reached_destination_city_orders(provider):
    try:
        orders_tobe_reached_destination_city = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY])
        destination_city_reached_orders = read_reached_destination_orders(orders_tobe_reached_destination_city)
        if destination_city_reached_orders:
            update_destination_city_reached_orders(provider.id, destination_city_reached_orders)
    except:
        print "Some issue while processing the orders for Reached Destination City status"
        traceback.print_exc()

def process_delivery_report(provider):
    try:
        orders_tobe_delivered = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE])
        delivered_orders, returned_orders, undelivered_orders = read_delivery_orders(orders_tobe_delivered)
        if delivered_orders:
            update_delivered_orders(provider.id, delivered_orders)
        if returned_orders:
            update_returned_orders(provider.id, returned_orders)
        if undelivered_orders:
            update_reason_of_undelivered_orders(provider.id, undelivered_orders)
    except:
        print "Some issue while processing the orders for delivery status"
        traceback.print_exc()

def generate_reports(provider):
    get_doas_not_picked_up(provider)
    get_returns_not_picked_up(provider)
    get_orders_not_picked_up(provider)
    get_orders_pending_local_connection(provider)
    get_returned_orders(provider)
    get_orders_not_delivered(provider)

def get_doas_not_picked_up(provider):
    txnClient = TransactionClient().get_client()
    try:
        doas_not_picked_up = txnClient.getDoasNotPickedUp(provider.id)
    except TransactionServiceException as tex:
        print tex.message
    
    try:
        if doas_not_picked_up:
            print "DOAs not Picked up:"
            print doas_not_picked_up
            mismatch_file = "/tmp/BlueDart_DoaPickupMismatch.csv"
            print "Some of our DOA orders were not picked up. Printing report to:" + mismatch_file
            print_dao_return_pickup_mismatch_report(mismatch_file, doas_not_picked_up)
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
            mail(from_user, from_pwd, to,\
                 "DOA Pickup Mismatch for " + provider.name,\
                 "This is a system generated email.Please don't reply to it.",\
                 pickup_mismatch_part)
    except Exception:
        print "Some issue sending the DOA mismatch report"
        traceback.print_exc()

def get_returns_not_picked_up(provider):
    txnClient = TransactionClient().get_client()
    try:
        returns_not_picked_up = txnClient.getReturnOrdersNotPickedUp(provider.id)
    except TransactionServiceException as tex:
        print tex.message
    
    try:
        if returns_not_picked_up:
            print "Return Orders not Picked up:"
            print returns_not_picked_up
            mismatch_file = "/tmp/BlueDart_ReturnsPickupMismatch.csv"
            print "Some of our Return orders were not picked up. Printing report to:" + mismatch_file
            print_dao_return_pickup_mismatch_report(mismatch_file, returns_not_picked_up)
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
            mail(from_user, from_pwd, to,\
                 "Return orders Pickup Mismatch for " + provider.name,\
                 "This is a system generated email.Please don't reply to it.",\
                 pickup_mismatch_part)
    except Exception:
        print "Some issue sending the Return orders mismatch report"
        traceback.print_exc()

def get_orders_not_picked_up(provider):
    txnClient = TransactionClient().get_client()
    try:
        orders_not_picked_up = txnClient.getOrdersNotPickedUp(provider.id)
    except TransactionServiceException as tex:
        print tex.message
    
    try:
        if orders_not_picked_up:
            print "Orders not Picked up:"
            print orders_not_picked_up
            mismatch_file = "/tmp/RedExpress_PickupMismatch.csv"
            print "Some of our orders were not picked up. Printing report to:" + mismatch_file
            print_pickup_mismatch_report(mismatch_file, orders_not_picked_up)
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
            mail(from_user, from_pwd, to,\
                 "Order Pickup Mismatch for " + provider.name,\
                 "This is a system generated email.Please don't reply to it.",\
                 pickup_mismatch_part)
    except Exception:
        print "Some issue sending the pickup mismatch report"
        traceback.print_exc()

def get_orders_pending_local_connection(provider):
    txnClient = TransactionClient().get_client()
    try:
        orders_pending_local_connection = txnClient.getOrdersNotLocalConnected(provider.id)
    except TransactionServiceException as tex:
        print tex.message
    
    try:
        if orders_pending_local_connection:
            print "Local Connection Pending Orders:"
            print orders_pending_local_connection
            mismatch_file = "/tmp/RedExpress_LocalConnectionPendingOrders.csv"
            print "Some of our Orders were not Shipped to Destination yet. Printing report to:" + mismatch_file
            print_undelivered_orders_report(mismatch_file, orders_pending_local_connection)
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
            mail(from_user, from_pwd, to,\
                 "Orders that are not Shipped to Destination yet for " + provider.name,\
                 "This is a system generated email.Please don't reply to it.",\
                 pickup_mismatch_part)
    except Exception:
        print "Some issue updating and sending the Local Connection orders report"
        traceback.print_exc()

def get_returned_orders(provider):
    txnClient = TransactionClient().get_client()
    try:
        returned_orders = txnClient.getRTOrders(provider.id)
    except TransactionServiceException as tex:
        print tex.message
    
    try:
        if returned_orders:
            print "Returned Orders:"
            print returned_orders
            returned_orders_file = "/tmp/RedExpress_ReturnedOrders.csv"
            print "Some of our Orders were returned by logistics provider. Printing report to:" + returned_orders_file
            print_rto_orders_report(returned_orders_file, returned_orders)
            returned_orders_report = [get_attachment_part(returned_orders_file)]
            mail(from_user, from_pwd, to,\
                 "Returned Orders Report for " + provider.name,\
                 "This is a system generated email.Please don't reply to it.",\
                 returned_orders_report)
    except:
        print "Some issue sending the returned orders report"
        traceback.print_exc()

def get_orders_not_delivered(provider):
    txnClient = TransactionClient().get_client()
    try:
        orders_not_delivered = txnClient.getNonDeliveredOrdersbyCourier(provider.id)
    except TransactionServiceException as tex:
        print tex.message
    
    try:
        if orders_not_delivered:
            print "Undelivered Orders:"
            print orders_not_delivered
            mismatch_file = "/tmp/RedExpress_UndeliveredOrders.csv"
            print "Some of our Orders were not delivered. Printing report to:" + mismatch_file
            print_undelivered_orders_report(mismatch_file, orders_not_delivered)
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
            mail(from_user, from_pwd, to,\
                 "Orders that are undelivered but picked up or shipped four days ago for " + provider.name,\
                 "This is a system generated email.Please don't reply to it.",\
                 pickup_mismatch_part)
    except Exception:
        print "Some issue updating and sending the undelivered orders report"
        traceback.print_exc()

def get_provider_by_name(provider_name):
    logistics_client = LogisticsClient().get_client()
    provider = None
    providers = logistics_client.getAllProviders()
    for p in providers:
        if p.name == provider_name:
            provider=p
            break
    if provider == None:
        sys.exit("Can't continue execution: No such provider")
    return provider

def fetch_data(provider_id, order_status_list):
    txnClient = TransactionClient().get_client()
    try:
        doas_tobe_picked_up = txnClient.getOrdersForProviderForStatus(provider_id, order_status_list)
        return doas_tobe_picked_up
    except TransactionServiceException as tex:
        print tex.message

def read_dao_return_pickup_orders(orders_tobe_picked_up):
    #uri=http://www.bluedart.com/servlet/RoutingServlet?handler=tnt&action=custawbquery&loginid=DEL24119&awb=ref&format=XML&lickey=6265d61bafa6292c5ddfdb1ee335ca80&verno=1.3&scan=1&numbers=82390
    picked_up_orders = {}
    for order in orders_tobe_picked_up:
        try:
            uri = 'http://www.bluedart.com/servlet/RoutingServlet?handler=tnt&action=custawbquery&loginid=DEL24119&awb=ref&format=XML&lickey=6265d61bafa6292c5ddfdb1ee335ca80&verno=1.3&scan=1&numbers=' + str(order.pickupRequestNo)
            root = parse(urllib2.urlopen(uri)).getroot()
            children = root.getchildren()
            for child in children:
                nodes = child.findall('Scans/ScanDetail')
                for element in reversed(nodes):
                    datestring = element.findtext('ScanDate', '')
                    timestring = element.findtext('ScanTime', '')
                    delivery_date = get_py_datetime(datestring, timestring)
                    picked_up_orders[order.pickupRequestNo] = str(delivery_date)
                    break
                break
        except:
            pass
    
    print "Picked up Orders:"
    print picked_up_orders
    return picked_up_orders

def read_pickup_orders(orders_tobe_picked_up):
    picked_up_orders = {}
    awb_number_list =[]
    for order in orders_tobe_picked_up:
        awb_number_list.append(order.airwaybill_no)
    
    track_update_list = get_track_updates(awb_number_list)
    
    for update in track_update_list:
        if update == 'DUMMY':
            continue
        else:
            try:
                airwaybill_no = update['ReferenceNo'] 
                track_list = update['TrackingList']['TrackingList']
                #track_list.reverse()
                for track_update in track_list:
                    if track_update['TrackingCode'] == 'BKD' :
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
                        datestring  = date_obj.strftime("%Y-%m-%d")
                        timestring = track_update['ExecutionTime']+':00'
                        delivery_date = datestring +' '+ timestring
                        picked_up_orders[airwaybill_no] = delivery_date
                        break
            except:
                pass
        
    print "Picked up Orders:"
    print picked_up_orders
    return picked_up_orders

def read_local_connection_orders(orders_tobe_local_connected):
    local_connected_orders = {}
    
    awb_number_list =[]
    for order in orders_tobe_local_connected:
        awb_number_list.append(order.airwaybill_no)
    
    track_update_list = get_track_updates(awb_number_list)
    
    for update in track_update_list:
        if update == 'DUMMY':
            continue
        else:
            try:
                airwaybill_no = update['ReferenceNo'] 
                track_list = update['TrackingList']['TrackingList']
                #track_list.reverse()
                for track_update in track_list:
                    if track_update['TrackingCode'] == 'PRO' :
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
                        datestring  = date_obj.strftime("%Y-%m-%d")
                        timestring = track_update['ExecutionTime']+':00'
                        delivery_date = datestring +' '+ timestring
                        local_connected_orders[airwaybill_no] = delivery_date
                        break
            except:
                pass
            
    print "Local Connected Orders"
    print local_connected_orders
    
    return local_connected_orders

def read_reached_destination_orders(orders_tobe_reached_destination_city):
    destination_city_reached_orders = {}
    
    awb_number_list =[]
    for order in orders_tobe_reached_destination_city:
        awb_number_list.append(order.airwaybill_no)
    
    track_update_list = get_track_updates(awb_number_list)
    
    for update in track_update_list:
        if update == 'DUMMY':
            continue
        else:
            try:
                airwaybill_no = update['ReferenceNo'] 
                track_list = update['TrackingList']['TrackingList']
                #track_list.reverse()
                for track_update in track_list:
                    if track_update['TrackingCode'] == 'RDB' :
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
                        datestring  = date_obj.strftime("%Y-%m-%d")
                        timestring = track_update['ExecutionTime']+':00'
                        delivery_date = datestring +' '+ timestring
                        destination_city_reached_orders[airwaybill_no] = delivery_date
                        break
            except:
                pass
    
    print "Destination City Reached Orders"
    print destination_city_reached_orders
    
    return destination_city_reached_orders

def read_first_delivery_attempt_orders(orders_tobe_first_delivery_attempted):
    first_atdl_orders = {}
    
    awb_number_list =[]
    for order in orders_tobe_first_delivery_attempted:
        awb_number_list.append(order.airwaybill_no)
    
    track_update_list = get_track_updates(awb_number_list)
    
    for update in track_update_list:
        if update == 'DUMMY':
            continue
        else:
            try:
                airwaybill_no = update['ReferenceNo'] 
                track_list = update['TrackingList']['TrackingList']
                #track_list.reverse()
                for track_update in track_list:
                    if track_update['TrackingCode'] == 'OFD' :
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
                        datestring  = date_obj.strftime("%Y-%m-%d")
                        timestring = track_update['ExecutionTime']+':00'
                        delivery_date = datestring +' '+ timestring
                        first_atdl_orders[airwaybill_no] = delivery_date +'|'+ track_update['ServiceEvent']
                        break
            except:
                pass
        
    
    print "FIRST DELIVERY ATTEMPT MADE Orders"
    print first_atdl_orders
    
    return first_atdl_orders

def read_delivery_orders(orders_tobe_delivered):
    delivered_orders = {}
    returned_orders = {}
    undelivered_orders = {}
    awb_order_map = {}
    
    for order in orders_tobe_delivered:
        awb_order_list =[]
        awb_order_list.append(order.id)
        awb_order_list.append(order.shipping_timestamp)
        awb_order_map[order.airwaybill_no]= awb_order_list
    
    track_update_list = get_track_updates(awb_order_map.keys())
    
    for update in track_update_list:
        if update == 'DUMMY':
            continue
        else:
            try:
                airwaybill_no = update['ReferenceNo'] 
                track_list = update['TrackingList']['TrackingList']
                #track_list.reverse()
                reason_for_return = None
                for record in track_list:
                    if record['TrackingCode'] == 'UDLD' :
                        reason_for_return = record['ServiceEvent'].split(" -")[1]
                        break
                    
                for track_update in track_list:
                    if track_update['TrackingCode'] == 'DLVD' :
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
                        datestring  = date_obj.strftime("%Y-%m-%d")
                        timestring = track_update['ExecutionTime']+':00'
                        del_date = datestring +' '+ timestring
                        delivery_date = datetime.datetime.strptime(del_date,"%Y-%m-%d %H:%M:%S")
                        receiver = track_update['ServiceEvent'].split("[ ")[1].split(" ]")[0]
                        if to_py_date(awb_order_map.get(airwaybill_no)[1]) > delivery_date:
                            mail(from_user, from_pwd, to, "Delivery Problem for Red Express", "Order id " + str(awb_order_map.get(airwaybill_no)[0]) + " has shipping date " + str(awb_order_map.get(airwaybill_no)[1]) + " larger than delivery date " + str(delivery_date))
                        else:
                            delivered_orders[airwaybill_no] = str(delivery_date) + "|" +  receiver
                        break
                    elif track_update['TrackingCode'] == 'RTO' :
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
                        datestring  = date_obj.strftime("%Y-%m-%d")
                        timestring = track_update['ExecutionTime']+':00'
                        del_date = datestring +' '+ timestring
                        delivery_date = datetime.datetime.strptime(del_date,"%Y-%m-%d %H:%M:%S")
                        if reason_for_return == None:
                            returned_orders[airwaybill_no] = str(delivery_date) + "|"  + " Order Booked for Return"
                        else:
                            returned_orders[airwaybill_no] = str(delivery_date) + "|"  + reason_for_return
                        break
                    elif track_update['TrackingCode'] == 'UDLD' :
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
                        datestring  = date_obj.strftime("%Y-%m-%d")
                        timestring = track_update['ExecutionTime']+':00'
                        del_date = datestring +' '+ timestring
                        delivery_date = datetime.datetime.strptime(del_date,"%Y-%m-%d %H:%M:%S")
                        if reason_for_return == None:
                            undelivered_orders[airwaybill_no] = str(delivery_date) + "|" + track_update['ServiceEvent'].split(" -")[1]
                        else:
                            undelivered_orders[airwaybill_no] = str(delivery_date) + "|" + reason_for_return
                        break
            except:
                pass
    
    print "Delivered Orders:"
    print delivered_orders
    
    print "Returned Orders:"
    print returned_orders
    
    print "Undelivered Orders"
    print undelivered_orders
    
    return delivered_orders, returned_orders, undelivered_orders

def update_picked_orders(provider_id, pickup_details):
    txnClient = TransactionClient().get_client()
    try:
        txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
    except TransactionServiceException as tex:
        print tex.message

def update_picked_doas(provider_id, doa_pickup_details):
    txnClient = TransactionClient().get_client()
    try:
        txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
    except TransactionServiceException as tex:
        print tex.message

def update_picked_returns(provider_id, returns_pickup_details):
    txnClient = TransactionClient().get_client()
    try:
        txnClient.markReturnOrdersAsPickedUp(provider_id, returns_pickup_details)
    except TransactionServiceException as tex:
        print tex.message

def update_delivered_orders(provider_id, delivered_orders):
    txnClient = TransactionClient().get_client()
    try:
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
    except TransactionServiceException as tex:
        print tex.message

def update_returned_orders(provider_id, returned_orders):
    txnClient = TransactionClient().get_client()
    try:
        txnClient.markAsRTOrders(provider_id, returned_orders)
    except TransactionServiceException as tex:
        print tex.message

def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
    txnClient = TransactionClient().get_client()
    try:
        txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
    except TransactionServiceException as tex:
        print tex.message

def update_local_connected_orders(provider_id, local_connected_orders):
    txnClient = TransactionClient().get_client()
    try:
        txnClient.markOrdersAsLocalConnected(provider_id, local_connected_orders)
    except TransactionServiceException as tex:
        print tex.message

def update_destination_city_reached_orders(provider_id, destination_city_reached_orders):
    txnClient = TransactionClient().get_client()
    try:
        txnClient.markOrdersAsDestinationCityReached(provider_id, destination_city_reached_orders)
    except TransactionServiceException as tex:
        print tex.message

def update_first_atdl_orders(provider_id, first_atdl_orders):
    txnClient = TransactionClient().get_client()
    try:
        txnClient.markOrdersAsFirstDeliveryAttempted(provider_id, first_atdl_orders)
    except TransactionServiceException as tex:
        print tex.message

def print_pickup_mismatch_report(filename, orders):
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
    for order in orders:
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])

def print_dao_return_pickup_mismatch_report(filename, orders):
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
    writer.writerow(['Order Id', 'Pickup Request No', 'Authorization timestamp'])
    for order in orders:
        writer.writerow([order.id, order.pickupRequestNo, to_py_date(order.doa_auth_timestamp)])

def print_rto_orders_report(filename, orders):
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
    writer.writerow(['Order Id', 'AWB No', 'Return date', 'Reason'])
    for order in orders:
        statusDescription = ''
        if order.statusDescription is not None:
            statusDescription = order.statusDescription.replace(","," ")
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.delivery_timestamp), statusDescription])

def print_undelivered_orders_report(filename, orders):
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
    writer.writerow(['Order Id', 'AWB No', 'Status', 'Status Description', 'Shipping timestamp', 'Pickup timestamp', 'Promised delivery date', 'Expected delivery date', 'OTG'])
    for order in orders:
        statusDescription = ''
        if order.statusDescription is not None:
            statusDescription = order.statusDescription.replace(","," ")
        writer.writerow([order.id, order.airwaybill_no, order.status, statusDescription, to_py_date(order.shipping_timestamp), to_py_date(order.pickup_timestamp), to_py_date(order.promised_delivery_time), to_py_date(order.expected_delivery_time), 'True'  if order.otg else 'False'])

def auto_close_crm_tickets_created():
    try:
        ticket_created_orders = []
        tickets_map = {}
        crmServiceClient = CRMClient().get_client()
        searchFilter = SearchFilter()
        searchFilter.ticketCategory = TicketCategory.UNDELIVERED
        searchFilter.ticketAssigneeIds = [defaultUndeliveredAsssigneeId]
        searchFilter.ticketPriority = TicketPriority.HIGH
        searchFilter.ticketStatuses = [TicketStatus.OPEN]
        tickets = crmServiceClient.getTickets(searchFilter)
        print tickets
        for old_ticket in tickets:
            ticket_created_orders.append(old_ticket.orderId)
            tickets_map[old_ticket.orderId] = old_ticket
        print ticket_created_orders
        txnClient = TransactionClient().get_client()
        orders = txnClient.getOrderList(ticket_created_orders)
        for order in orders:
            if order.status not in [OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.RTO_IN_TRANSIT]:
                old_ticket = tickets_map.get(order.id)
                old_ticket.status = TicketStatus.CLOSED
                activity = Activity()
                activity.creatorId = 1
                activity.ticketAssigneeId = old_ticket.assigneeId
                activity.type = ActivityType.OTHER
                activity.description = "Ticket Closed bcoz order status changed to:" + order.statusDescription
                activity.ticketCategory = old_ticket.category
                activity.ticketDescription = old_ticket.description
                activity.ticketPriority = old_ticket.priority
                activity.ticketStatus = old_ticket.status
                
                if old_ticket.customerId is None or old_ticket.customerId == -1:
                    activity.customerEmailId = old_ticket.customerEmailId
                    activity.customerMobileNumber = old_ticket.customerMobileNumber
                    activity.customerName = old_ticket.customerName
                else:
                    activity.customerId = old_ticket.customerId
                
                crmServiceClient.updateTicket(old_ticket, activity)
    except:
        print "Some issue while closing crm tickets for orders in DELIVERY_SUCCESS status"
        traceback.print_exc()

def get_py_datetime(datestring, timestring):
    # This should be a command line argument.
    # Refer http://docs.python.org/library/time.html#time.strftime to
    # get a complete list of format specifiers available for date time.
    if datestring == '':
        return None
    if datestring.find('-') == -1:
        time_format = "%A,%d %B, %Y %H:%M:%S"
    else:
        time_format = "%d-%b-%Y %H:%M:%S"
    if timestring == '':
        timestring = '00:00:00'
    time_array = timestring.split(':')
    if len(time_array) < 3:
        timestring = timestring + ':00'
    time_string = datestring + ' ' + timestring[0:8]
    mytime = time.strptime(time_string, time_format)
    return datetime.datetime(*mytime[:6])


def getTrimedString(text):
    if text is None or text == '':
        return ''
    else:
        text = text.strip().lower()
        text_list = list(text)
        new_text = ''
        for letter in text_list:
            if letter.isalnum():
                new_text = new_text + str(letter)
        return new_text

def main():
    parser = optparse.OptionParser()
    parser.add_option("-p", "--pickup", dest="pickup_report",
                   action="store_true",
                   help="Run the pickup reconciliation")
    parser.add_option("-d", "--delivery", dest="delivery_report",
                   action="store_true",
                   help="Run the delivery reconciliation")
    parser.add_option("-r", "--reports", dest="gen_reports",
                   action="store_true",
                   help="Generate logistic reconciliation reports")
    parser.add_option("-a", "--all", dest="all_reports",
                   action="store_true",
                   help="Run all reconciliations")
    parser.add_option("-P", "--provider", dest="provider",
                   default="RedExpress", type="string",
                   help="The PROVIDER this report is for",
                   metavar="PROVIDER")
    parser.set_defaults(pickup_report=False, delivery_report=False, gen_reports=False, all_reports=False)
    (options, args) = parser.parse_args()
    if len(args) != 0:
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
    
    if options.all_reports:
        options.pickup_report = True
        options.delivery_report = True
    
    provider = get_provider_by_name(options.provider)
    
    if options.pickup_report:
        process_pickup_records(provider)
        #process_dao_pickup_orders(provider)
        #process_return_pickup_orders(provider)
    if options.delivery_report:
        process_local_connection_orders(provider)
        process_reached_destination_city_orders(provider)
        process_first_delivery_attempt_orders(provider)
        process_delivery_report(provider)
        create_crm_tickets_for_delivey_attempted_orders(provider)
        auto_close_crm_tickets_created()
    if options.gen_reports:
        generate_reports(provider)

if __name__ == '__main__':
    main()