Subversion Repositories SmartDukaan

Rev

Rev 9173 | Rev 13085 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6952 rajveer 1
#!/usr/bin/python
2
'''
3
It processes the following orders:
4
 1. Orders in DOA_PICKUP_CONFIRMED status : get details of orders that 
5
     were in DOA_PICKUP_CONFIRMED status from database and 
6
     calls BlueDart api to know whether they are picked up by BlueDart
7
     and changes the status to DOA_RETURN_IN_TRANSIT if it is done.
8
 2. Orders in RET_PICKUP_CONFIRMED status : get details of orders that 
9
     were in RET_PICKUP_CONFIRMED status from database and 
10
     calls BlueDart api to know whether they are picked up by BlueDart
11
     and changes the status to RET_RETURN_IN_TRANSIT if it is done.
12
 3. Orders in SHIPPED_FROM_WH status: get details of orders that
13
     were in SHIPPED_FROM_WH status from database and 
14
     calls BlueDart api to know whether they are picked up by BlueDart
15
     and changes the status to SHIPPED_TO_LOGST if it is done.
16
 4. Orders in SHIPPED_TO_LOGST status: get details of orders that
17
     were in SHIPPED_TO_LOGST status from database and 
18
     calls BlueDart api to know their status and changes the status accordingly.
19
 
20
It sends out a Pickup mismatch report, Return orders Pickup Mismatch report, Doa Pickup mismatch report,
21
Undelivered orders report and Returned Orders report to cnc.center@shop2020.in
22
 
23
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
24
to track DOA orders and for other orders ConfigClient is called to get bluedart_update_url
25
 
26
@author: Phani Kumar
27
'''
28
from shop2020.clients.CRMClient import CRMClient
29
from shop2020.clients.LogisticsClient import LogisticsClient
30
from shop2020.clients.TransactionClient import TransactionClient
31
from shop2020.clients.UserClient import UserClient
32
from LogisticUtils import enqueueMailForFDA
33
from shop2020.thriftpy.crm.ttypes import *
34
from shop2020.thriftpy.model.v1.order.ttypes import TransactionServiceException, \
35
    OrderStatus
36
from shop2020.utils.EmailAttachmentSender import get_attachment_part, mail
37
from shop2020.utils.Utils import to_py_date
38
from xml.etree.ElementTree import parse, XML, fromstring
8714 manish.sha 39
from datetime import datetime
6952 rajveer 40
import csv
41
import datetime
42
import optparse
43
import sys
44
import time
45
import traceback
46
import urllib2
47
from suds.client import Client
8714 manish.sha 48
import json
49
import StringIO
50
import zlib
51
import gzip
52
import xmltodict
53
import ast
6952 rajveer 54
if __name__ == '__main__' and __package__ is None:
55
    import os
56
    sys.path.insert(0, os.getcwd())
57
 
58
 
59
RED_EXPRESS_URL = "http://tracking.getsetred.net/TrackingService.svc?wsdl"
60
username = 'C00086721141'
9893 manish.sha 61
password = '87e95$'
8714 manish.sha 62
tracking_Id_Type = 'REFERENCENO'
63
tracking_Level = 'ALL_DETAILS'
6952 rajveer 64
 
8714 manish.sha 65
RED_EXPRESS_TRACKING_URL = 'http://webservices.getsetred.net/Services/BulkTracking.svc/'
66
headers = {
67
               "User-Agent" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.218 Safari/535.1",
68
               "Accept" : "    text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8",
69
               "Accept-Language" : "en-us,en;q=0.5",
70
               "Accept-Encoding" : "gzip, deflate",
71
               "Connection" : "keep-alive",
72
               "Accept-Charset" : "ISO-8859-1",
73
               "Content-type": "application/json; charset=UTF-8"
74
               }
75
 
6952 rajveer 76
client = None
77
def getClient():
78
    global client
79
    if client is None:
80
        client = Client(RED_EXPRESS_URL, timeout=70)
81
    return client
82
 
8292 manish.sha 83
defaultUndeliveredAsssigneeId = 47
6952 rajveer 84
from_user = 'cnc.center@shop2020.in'
85
from_pwd = '5h0p2o2o'
9173 manish.sha 86
to = ['cnc.center@shop2020.in', "amit.sirohi@shop2020.in", "sandeep.sachdeva@shop2020.in", "sunil.kumar@shop2020.in", "rajveer.singh@shop2020.in"]
6952 rajveer 87
 
88
 
89
def get_updates(awb_number): 
90
    str = getClient().service.ProcessTrackingRequest('<TrackingRequest><Request><UserID>' + username + '</UserID><Password>' + password + '</Password><TrackingID>' + awb_number + '</TrackingID><TrackingLevel>ALL_DETAILS</TrackingLevel></Request></TrackingRequest>')
91
    print str
92
    return str
93
 
7026 rajveer 94
def get_updates_for_user(awb_number):
95
    root =  fromstring(str(get_updates(awb_number)))
96
    children = root.getchildren()
97
    results = []
98
    for child in children:
99
        nodes = child.findall('ShipmentInfo/ShipmentEvent')
100
        for element in reversed(nodes):
101
            datestring = element.findtext('Date', '')
102
            timestring = element.findtext('Time', '')
103
            description = element.findtext('ServiceEvent', '')
104
            results.append(datestring+"~!~"+timestring+"~!~"+description)
105
    return results
6952 rajveer 106
 
8714 manish.sha 107
def get_track_updates(awb_numbers):
8838 manish.sha 108
    track_data_list=[]
109
    if len(awb_numbers)>0:
110
        req_args = json.dumps({'password':password,
111
                               'trackingIdType':'REFERENCENO',
112
                               'trackingLevel':'ALL_DETAILS',
113
                               'userId':username,
114
                               'waybillNo': awb_numbers 
115
                               })
116
        request = urllib2.Request(RED_EXPRESS_TRACKING_URL, req_args, headers)
117
        response = urllib2.urlopen(request)
8714 manish.sha 118
 
8838 manish.sha 119
        encoding = response.info().get("Content-Encoding")    
120
        if encoding in ('gzip', 'x-gzip', 'deflate'):
121
            content = response.read()
122
            if encoding == 'deflate':
123
                track_data_decoded = StringIO.StringIO(zlib.decompress(content))
124
            else:
125
                track_data_decoded = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(content))
126
        track_data_readable = track_data_decoded.read()
127
 
128
        conv_dict = xmltodict.parse(track_data_readable)
129
        track_data_json= json.dumps(conv_dict)
130
        if track_data_json.find('null') > 0:
131
            track_data_json = track_data_json.replace('null','\"No Description Available\"');
8714 manish.sha 132
        track_data_dict = ast.literal_eval(track_data_json)
133
 
8838 manish.sha 134
        if len(awb_numbers)==1:
135
            track_data_list=[]
136
            track_data_list.append(track_data_dict['BulkTrackingResponse']['BulkResponse']['TrackingResponse'])
137
            track_data_list.append('DUMMY')
138
        else:
139
            track_data_list = track_data_dict['BulkTrackingResponse']['BulkResponse']['TrackingResponse']    
140
 
8714 manish.sha 141
    return track_data_list
142
 
143
 
6952 rajveer 144
def process_dao_pickup_orders(provider):
145
    try:
146
        doas_tobe_picked_up = fetch_data(provider.id, [OrderStatus.DOA_PICKUP_CONFIRMED])
147
        doa_pickup_details = read_dao_return_pickup_orders(doas_tobe_picked_up)
148
        if doa_pickup_details:
149
            update_picked_doas(provider.id, doa_pickup_details)
150
    except:
151
        print "Some issue while processing the orders in DOA_PICKUP_CONFIRMED status"
152
        traceback.print_exc()
153
 
154
def process_return_pickup_orders(provider):
155
    try:
156
        returns_tobe_picked_up = fetch_data(provider.id, [OrderStatus.RET_PICKUP_CONFIRMED])
157
        returns_pickup_details = read_dao_return_pickup_orders(returns_tobe_picked_up)
158
        if returns_pickup_details:
159
            update_picked_returns(provider.id, returns_pickup_details)
160
    except:
161
        print "Some issue while processing the orders in RET_PICKUP_CONFIRMED status"
162
        traceback.print_exc()
163
 
164
def process_pickup_records(provider):
165
    try:
166
        orders_tobe_picked_up = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH])
167
        pickup_details = read_pickup_orders(orders_tobe_picked_up)
168
        if pickup_details:
169
            update_picked_orders(provider.id, pickup_details)
170
    except:
171
        print "Some issue while processing the orders in SHIPPED_FROM_WH status"
172
        traceback.print_exc()
173
 
174
def process_local_connection_orders(provider):
175
    try:
176
        orders_tobe_local_connected = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST])
177
        local_connected_orders = read_local_connection_orders(orders_tobe_local_connected)
178
        if local_connected_orders:
179
            update_local_connected_orders(provider.id, local_connected_orders)
180
    except:
181
        print "Some issue while processing the orders for local connection status"
182
        traceback.print_exc()
183
 
7025 rajveer 184
def process_first_delivery_attempt_orders(provider):
185
    try:
186
        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])
187
        first_atdl_orders = read_first_delivery_attempt_orders(orders_tobe_first_delivery_attempted)
188
        if first_atdl_orders:
189
            update_first_atdl_orders(provider.id, first_atdl_orders)
190
    except:
191
        print "Some issue while processing the orders for First delivery attempt status"
192
        traceback.print_exc()
193
 
6952 rajveer 194
def process_reached_destination_city_orders(provider):
195
    try:
196
        orders_tobe_reached_destination_city = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY])
197
        destination_city_reached_orders = read_reached_destination_orders(orders_tobe_reached_destination_city)
198
        if destination_city_reached_orders:
199
            update_destination_city_reached_orders(provider.id, destination_city_reached_orders)
200
    except:
201
        print "Some issue while processing the orders for Reached Destination City status"
202
        traceback.print_exc()
203
 
204
def process_delivery_report(provider):
205
    try:
206
        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])
207
        delivered_orders, returned_orders, undelivered_orders = read_delivery_orders(orders_tobe_delivered)
208
        if delivered_orders:
209
            update_delivered_orders(provider.id, delivered_orders)
210
        if returned_orders:
211
            update_returned_orders(provider.id, returned_orders)
212
        if undelivered_orders:
213
            update_reason_of_undelivered_orders(provider.id, undelivered_orders)
214
    except:
215
        print "Some issue while processing the orders for delivery status"
216
        traceback.print_exc()
217
 
218
def generate_reports(provider):
219
    get_doas_not_picked_up(provider)
220
    get_returns_not_picked_up(provider)
221
    get_orders_not_picked_up(provider)
222
    get_orders_pending_local_connection(provider)
223
    get_returned_orders(provider)
224
    get_orders_not_delivered(provider)
225
 
226
def get_doas_not_picked_up(provider):
227
    txnClient = TransactionClient().get_client()
228
    try:
229
        doas_not_picked_up = txnClient.getDoasNotPickedUp(provider.id)
230
    except TransactionServiceException as tex:
231
        print tex.message
232
 
233
    try:
234
        if doas_not_picked_up:
235
            print "DOAs not Picked up:"
236
            print doas_not_picked_up
237
            mismatch_file = "/tmp/BlueDart_DoaPickupMismatch.csv"
238
            print "Some of our DOA orders were not picked up. Printing report to:" + mismatch_file
239
            print_dao_return_pickup_mismatch_report(mismatch_file, doas_not_picked_up)
240
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
241
            mail(from_user, from_pwd, to,\
242
                 "DOA Pickup Mismatch for " + provider.name,\
243
                 "This is a system generated email.Please don't reply to it.",\
244
                 pickup_mismatch_part)
245
    except Exception:
246
        print "Some issue sending the DOA mismatch report"
247
        traceback.print_exc()
248
 
249
def get_returns_not_picked_up(provider):
250
    txnClient = TransactionClient().get_client()
251
    try:
252
        returns_not_picked_up = txnClient.getReturnOrdersNotPickedUp(provider.id)
253
    except TransactionServiceException as tex:
254
        print tex.message
255
 
256
    try:
257
        if returns_not_picked_up:
258
            print "Return Orders not Picked up:"
259
            print returns_not_picked_up
260
            mismatch_file = "/tmp/BlueDart_ReturnsPickupMismatch.csv"
261
            print "Some of our Return orders were not picked up. Printing report to:" + mismatch_file
262
            print_dao_return_pickup_mismatch_report(mismatch_file, returns_not_picked_up)
263
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
264
            mail(from_user, from_pwd, to,\
265
                 "Return orders Pickup Mismatch for " + provider.name,\
266
                 "This is a system generated email.Please don't reply to it.",\
267
                 pickup_mismatch_part)
268
    except Exception:
269
        print "Some issue sending the Return orders mismatch report"
270
        traceback.print_exc()
271
 
272
def get_orders_not_picked_up(provider):
273
    txnClient = TransactionClient().get_client()
274
    try:
275
        orders_not_picked_up = txnClient.getOrdersNotPickedUp(provider.id)
276
    except TransactionServiceException as tex:
277
        print tex.message
278
 
279
    try:
280
        if orders_not_picked_up:
281
            print "Orders not Picked up:"
282
            print orders_not_picked_up
8883 manish.sha 283
            mismatch_file = "/tmp/RedExpress_PickupMismatch.csv"
6952 rajveer 284
            print "Some of our orders were not picked up. Printing report to:" + mismatch_file
285
            print_pickup_mismatch_report(mismatch_file, orders_not_picked_up)
286
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
287
            mail(from_user, from_pwd, to,\
288
                 "Order Pickup Mismatch for " + provider.name,\
289
                 "This is a system generated email.Please don't reply to it.",\
290
                 pickup_mismatch_part)
291
    except Exception:
292
        print "Some issue sending the pickup mismatch report"
293
        traceback.print_exc()
294
 
295
def get_orders_pending_local_connection(provider):
296
    txnClient = TransactionClient().get_client()
297
    try:
298
        orders_pending_local_connection = txnClient.getOrdersNotLocalConnected(provider.id)
299
    except TransactionServiceException as tex:
300
        print tex.message
301
 
302
    try:
303
        if orders_pending_local_connection:
304
            print "Local Connection Pending Orders:"
305
            print orders_pending_local_connection
8883 manish.sha 306
            mismatch_file = "/tmp/RedExpress_LocalConnectionPendingOrders.csv"
6952 rajveer 307
            print "Some of our Orders were not Shipped to Destination yet. Printing report to:" + mismatch_file
308
            print_undelivered_orders_report(mismatch_file, orders_pending_local_connection)
309
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
310
            mail(from_user, from_pwd, to,\
311
                 "Orders that are not Shipped to Destination yet for " + provider.name,\
312
                 "This is a system generated email.Please don't reply to it.",\
313
                 pickup_mismatch_part)
314
    except Exception:
315
        print "Some issue updating and sending the Local Connection orders report"
316
        traceback.print_exc()
317
 
318
def get_returned_orders(provider):
319
    txnClient = TransactionClient().get_client()
320
    try:
321
        returned_orders = txnClient.getRTOrders(provider.id)
322
    except TransactionServiceException as tex:
323
        print tex.message
324
 
325
    try:
326
        if returned_orders:
327
            print "Returned Orders:"
328
            print returned_orders
8883 manish.sha 329
            returned_orders_file = "/tmp/RedExpress_ReturnedOrders.csv"
6952 rajveer 330
            print "Some of our Orders were returned by logistics provider. Printing report to:" + returned_orders_file
331
            print_rto_orders_report(returned_orders_file, returned_orders)
332
            returned_orders_report = [get_attachment_part(returned_orders_file)]
333
            mail(from_user, from_pwd, to,\
334
                 "Returned Orders Report for " + provider.name,\
335
                 "This is a system generated email.Please don't reply to it.",\
336
                 returned_orders_report)
337
    except:
338
        print "Some issue sending the returned orders report"
339
        traceback.print_exc()
340
 
341
def get_orders_not_delivered(provider):
342
    txnClient = TransactionClient().get_client()
343
    try:
344
        orders_not_delivered = txnClient.getNonDeliveredOrdersbyCourier(provider.id)
345
    except TransactionServiceException as tex:
346
        print tex.message
347
 
348
    try:
349
        if orders_not_delivered:
350
            print "Undelivered Orders:"
351
            print orders_not_delivered
8883 manish.sha 352
            mismatch_file = "/tmp/RedExpress_UndeliveredOrders.csv"
6952 rajveer 353
            print "Some of our Orders were not delivered. Printing report to:" + mismatch_file
354
            print_undelivered_orders_report(mismatch_file, orders_not_delivered)
355
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
356
            mail(from_user, from_pwd, to,\
357
                 "Orders that are undelivered but picked up or shipped four days ago for " + provider.name,\
358
                 "This is a system generated email.Please don't reply to it.",\
359
                 pickup_mismatch_part)
360
    except Exception:
361
        print "Some issue updating and sending the undelivered orders report"
362
        traceback.print_exc()
363
 
364
def get_provider_by_name(provider_name):
365
    logistics_client = LogisticsClient().get_client()
366
    provider = None
367
    providers = logistics_client.getAllProviders()
368
    for p in providers:
369
        if p.name == provider_name:
370
            provider=p
371
            break
372
    if provider == None:
373
        sys.exit("Can't continue execution: No such provider")
374
    return provider
375
 
376
def fetch_data(provider_id, order_status_list):
377
    txnClient = TransactionClient().get_client()
378
    try:
379
        doas_tobe_picked_up = txnClient.getOrdersForProviderForStatus(provider_id, order_status_list)
380
        return doas_tobe_picked_up
381
    except TransactionServiceException as tex:
382
        print tex.message
383
 
384
def read_dao_return_pickup_orders(orders_tobe_picked_up):
385
    #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
386
    picked_up_orders = {}
387
    for order in orders_tobe_picked_up:
388
        try:
389
            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)
390
            root = parse(urllib2.urlopen(uri)).getroot()
391
            children = root.getchildren()
392
            for child in children:
393
                nodes = child.findall('Scans/ScanDetail')
394
                for element in reversed(nodes):
395
                    datestring = element.findtext('ScanDate', '')
396
                    timestring = element.findtext('ScanTime', '')
397
                    delivery_date = get_py_datetime(datestring, timestring)
398
                    picked_up_orders[order.pickupRequestNo] = str(delivery_date)
399
                    break
400
                break
401
        except:
402
            pass
403
 
404
    print "Picked up Orders:"
405
    print picked_up_orders
406
    return picked_up_orders
407
 
408
def read_pickup_orders(orders_tobe_picked_up):
409
    picked_up_orders = {}
8714 manish.sha 410
    awb_number_list =[]
6952 rajveer 411
    for order in orders_tobe_picked_up:
8714 manish.sha 412
        awb_number_list.append(order.airwaybill_no)
413
 
414
    track_update_list = get_track_updates(awb_number_list)
415
 
416
    for update in track_update_list:
417
        if update == 'DUMMY':
418
            continue
419
        else:
420
            try:
421
                airwaybill_no = update['ReferenceNo'] 
422
                track_list = update['TrackingList']['TrackingList']
8836 manish.sha 423
                #track_list.reverse()
8714 manish.sha 424
                for track_update in track_list:
425
                    if track_update['TrackingCode'] == 'BKD' :
8771 manish.sha 426
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
8714 manish.sha 427
                        datestring  = date_obj.strftime("%Y-%m-%d")
428
                        timestring = track_update['ExecutionTime']+':00'
8772 manish.sha 429
                        delivery_date = datestring +' '+ timestring
8714 manish.sha 430
                        picked_up_orders[airwaybill_no] = delivery_date
431
                        break
432
            except:
433
                pass
434
 
6952 rajveer 435
    print "Picked up Orders:"
436
    print picked_up_orders
437
    return picked_up_orders
438
 
439
def read_local_connection_orders(orders_tobe_local_connected):
440
    local_connected_orders = {}
8714 manish.sha 441
 
442
    awb_number_list =[]
6952 rajveer 443
    for order in orders_tobe_local_connected:
8714 manish.sha 444
        awb_number_list.append(order.airwaybill_no)
445
 
446
    track_update_list = get_track_updates(awb_number_list)
447
 
448
    for update in track_update_list:
449
        if update == 'DUMMY':
450
            continue
451
        else:
452
            try:
453
                airwaybill_no = update['ReferenceNo'] 
454
                track_list = update['TrackingList']['TrackingList']
8836 manish.sha 455
                #track_list.reverse()
8714 manish.sha 456
                for track_update in track_list:
457
                    if track_update['TrackingCode'] == 'PRO' :
8771 manish.sha 458
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
8714 manish.sha 459
                        datestring  = date_obj.strftime("%Y-%m-%d")
460
                        timestring = track_update['ExecutionTime']+':00'
8772 manish.sha 461
                        delivery_date = datestring +' '+ timestring
8714 manish.sha 462
                        local_connected_orders[airwaybill_no] = delivery_date
6952 rajveer 463
                        break
8714 manish.sha 464
            except:
465
                pass
7025 rajveer 466
 
6952 rajveer 467
    print "Local Connected Orders"
468
    print local_connected_orders
469
 
470
    return local_connected_orders
471
 
472
def read_reached_destination_orders(orders_tobe_reached_destination_city):
473
    destination_city_reached_orders = {}
8714 manish.sha 474
 
475
    awb_number_list =[]
6952 rajveer 476
    for order in orders_tobe_reached_destination_city:
8714 manish.sha 477
        awb_number_list.append(order.airwaybill_no)
478
 
479
    track_update_list = get_track_updates(awb_number_list)
480
 
481
    for update in track_update_list:
482
        if update == 'DUMMY':
483
            continue
484
        else:
485
            try:
486
                airwaybill_no = update['ReferenceNo'] 
487
                track_list = update['TrackingList']['TrackingList']
8836 manish.sha 488
                #track_list.reverse()
8714 manish.sha 489
                for track_update in track_list:
490
                    if track_update['TrackingCode'] == 'RDB' :
8771 manish.sha 491
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
8714 manish.sha 492
                        datestring  = date_obj.strftime("%Y-%m-%d")
493
                        timestring = track_update['ExecutionTime']+':00'
8772 manish.sha 494
                        delivery_date = datestring +' '+ timestring
8714 manish.sha 495
                        destination_city_reached_orders[airwaybill_no] = delivery_date
6952 rajveer 496
                        break
8714 manish.sha 497
            except:
498
                pass
6952 rajveer 499
 
500
    print "Destination City Reached Orders"
501
    print destination_city_reached_orders
502
 
503
    return destination_city_reached_orders
504
 
505
def read_first_delivery_attempt_orders(orders_tobe_first_delivery_attempted):
506
    first_atdl_orders = {}
8714 manish.sha 507
 
508
    awb_number_list =[]
6952 rajveer 509
    for order in orders_tobe_first_delivery_attempted:
8714 manish.sha 510
        awb_number_list.append(order.airwaybill_no)
511
 
512
    track_update_list = get_track_updates(awb_number_list)
513
 
514
    for update in track_update_list:
515
        if update == 'DUMMY':
516
            continue
517
        else:
518
            try:
519
                airwaybill_no = update['ReferenceNo'] 
520
                track_list = update['TrackingList']['TrackingList']
8836 manish.sha 521
                #track_list.reverse()
8714 manish.sha 522
                for track_update in track_list:
523
                    if track_update['TrackingCode'] == 'OFD' :
8771 manish.sha 524
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
8714 manish.sha 525
                        datestring  = date_obj.strftime("%Y-%m-%d")
526
                        timestring = track_update['ExecutionTime']+':00'
8772 manish.sha 527
                        delivery_date = datestring +' '+ timestring
8776 manish.sha 528
                        first_atdl_orders[airwaybill_no] = delivery_date +'|'+ track_update['ServiceEvent']
6952 rajveer 529
                        break
8714 manish.sha 530
            except:
531
                pass
532
 
6952 rajveer 533
 
534
    print "FIRST DELIVERY ATTEMPT MADE Orders"
535
    print first_atdl_orders
536
 
537
    return first_atdl_orders
538
 
539
def read_delivery_orders(orders_tobe_delivered):
540
    delivered_orders = {}
541
    returned_orders = {}
542
    undelivered_orders = {}
8714 manish.sha 543
    awb_order_map = {}
544
 
6952 rajveer 545
    for order in orders_tobe_delivered:
8714 manish.sha 546
        awb_order_list =[]
547
        awb_order_list.append(order.id)
548
        awb_order_list.append(order.shipping_timestamp)
549
        awb_order_map[order.airwaybill_no]= awb_order_list
6952 rajveer 550
 
8714 manish.sha 551
    track_update_list = get_track_updates(awb_order_map.keys())
552
 
553
    for update in track_update_list:
554
        if update == 'DUMMY':
555
            continue
556
        else:
557
            try:
558
                airwaybill_no = update['ReferenceNo'] 
559
                track_list = update['TrackingList']['TrackingList']
8836 manish.sha 560
                #track_list.reverse()
8714 manish.sha 561
                reason_for_return = None
562
                for record in track_list:
563
                    if record['TrackingCode'] == 'UDLD' :
564
                        reason_for_return = record['ServiceEvent'].split(" -")[1]
565
                        break
566
 
567
                for track_update in track_list:
568
                    if track_update['TrackingCode'] == 'DLVD' :
8771 manish.sha 569
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
8714 manish.sha 570
                        datestring  = date_obj.strftime("%Y-%m-%d")
571
                        timestring = track_update['ExecutionTime']+':00'
8772 manish.sha 572
                        del_date = datestring +' '+ timestring
8771 manish.sha 573
                        delivery_date = datetime.datetime.strptime(del_date,"%Y-%m-%d %H:%M:%S")
8714 manish.sha 574
                        receiver = track_update['ServiceEvent'].split("[ ")[1].split(" ]")[0]
575
                        if to_py_date(awb_order_map.get(airwaybill_no)[1]) > delivery_date:
576
                            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))
577
                        else:
578
                            delivered_orders[airwaybill_no] = str(delivery_date) + "|" +  receiver
579
                        break
580
                    elif track_update['TrackingCode'] == 'RTO' :
8771 manish.sha 581
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
8714 manish.sha 582
                        datestring  = date_obj.strftime("%Y-%m-%d")
583
                        timestring = track_update['ExecutionTime']+':00'
8772 manish.sha 584
                        del_date = datestring +' '+ timestring
8771 manish.sha 585
                        delivery_date = datetime.datetime.strptime(del_date,"%Y-%m-%d %H:%M:%S")
8714 manish.sha 586
                        if reason_for_return == None:
587
                            returned_orders[airwaybill_no] = str(delivery_date) + "|"  + " Order Booked for Return"
588
                        else:
589
                            returned_orders[airwaybill_no] = str(delivery_date) + "|"  + reason_for_return
590
                        break
591
                    elif track_update['TrackingCode'] == 'UDLD' :
8771 manish.sha 592
                        date_obj = datetime.datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
8714 manish.sha 593
                        datestring  = date_obj.strftime("%Y-%m-%d")
594
                        timestring = track_update['ExecutionTime']+':00'
8772 manish.sha 595
                        del_date = datestring +' '+ timestring
8771 manish.sha 596
                        delivery_date = datetime.datetime.strptime(del_date,"%Y-%m-%d %H:%M:%S")
8714 manish.sha 597
                        if reason_for_return == None:
598
                            undelivered_orders[airwaybill_no] = str(delivery_date) + "|" + track_update['ServiceEvent'].split(" -")[1]
599
                        else:
600
                            undelivered_orders[airwaybill_no] = str(delivery_date) + "|" + reason_for_return
601
                        break
602
            except:
603
                pass
604
 
6952 rajveer 605
    print "Delivered Orders:"
606
    print delivered_orders
607
 
608
    print "Returned Orders:"
609
    print returned_orders
610
 
611
    print "Undelivered Orders"
612
    print undelivered_orders
613
 
614
    return delivered_orders, returned_orders, undelivered_orders
615
 
616
def update_picked_orders(provider_id, pickup_details):
617
    txnClient = TransactionClient().get_client()
618
    try:
619
        txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
620
    except TransactionServiceException as tex:
621
        print tex.message
622
 
623
def update_picked_doas(provider_id, doa_pickup_details):
624
    txnClient = TransactionClient().get_client()
625
    try:
626
        txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
627
    except TransactionServiceException as tex:
628
        print tex.message
629
 
630
def update_picked_returns(provider_id, returns_pickup_details):
631
    txnClient = TransactionClient().get_client()
632
    try:
633
        txnClient.markReturnOrdersAsPickedUp(provider_id, returns_pickup_details)
634
    except TransactionServiceException as tex:
635
        print tex.message
636
 
637
def update_delivered_orders(provider_id, delivered_orders):
638
    txnClient = TransactionClient().get_client()
639
    try:
640
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
641
    except TransactionServiceException as tex:
642
        print tex.message
643
 
644
def update_returned_orders(provider_id, returned_orders):
645
    txnClient = TransactionClient().get_client()
646
    try:
647
        txnClient.markAsRTOrders(provider_id, returned_orders)
648
    except TransactionServiceException as tex:
649
        print tex.message
650
 
651
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
652
    txnClient = TransactionClient().get_client()
653
    try:
654
        txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
655
    except TransactionServiceException as tex:
656
        print tex.message
657
 
658
def update_local_connected_orders(provider_id, local_connected_orders):
659
    txnClient = TransactionClient().get_client()
660
    try:
661
        txnClient.markOrdersAsLocalConnected(provider_id, local_connected_orders)
662
    except TransactionServiceException as tex:
663
        print tex.message
664
 
665
def update_destination_city_reached_orders(provider_id, destination_city_reached_orders):
666
    txnClient = TransactionClient().get_client()
667
    try:
668
        txnClient.markOrdersAsDestinationCityReached(provider_id, destination_city_reached_orders)
669
    except TransactionServiceException as tex:
670
        print tex.message
671
 
672
def update_first_atdl_orders(provider_id, first_atdl_orders):
673
    txnClient = TransactionClient().get_client()
674
    try:
675
        txnClient.markOrdersAsFirstDeliveryAttempted(provider_id, first_atdl_orders)
676
    except TransactionServiceException as tex:
677
        print tex.message
678
 
679
def print_pickup_mismatch_report(filename, orders):
680
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
681
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
682
    for order in orders:
683
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
684
 
685
def print_dao_return_pickup_mismatch_report(filename, orders):
686
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
687
    writer.writerow(['Order Id', 'Pickup Request No', 'Authorization timestamp'])
688
    for order in orders:
689
        writer.writerow([order.id, order.pickupRequestNo, to_py_date(order.doa_auth_timestamp)])
690
 
691
def print_rto_orders_report(filename, orders):
692
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
693
    writer.writerow(['Order Id', 'AWB No', 'Return date', 'Reason'])
694
    for order in orders:
695
        statusDescription = ''
696
        if order.statusDescription is not None:
697
            statusDescription = order.statusDescription.replace(","," ")
698
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.delivery_timestamp), statusDescription])
699
 
700
def print_undelivered_orders_report(filename, orders):
701
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
702
    writer.writerow(['Order Id', 'AWB No', 'Status', 'Status Description', 'Shipping timestamp', 'Pickup timestamp', 'Promised delivery date', 'Expected delivery date', 'OTG'])
703
    for order in orders:
704
        statusDescription = ''
705
        if order.statusDescription is not None:
706
            statusDescription = order.statusDescription.replace(","," ")
707
        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'])
708
 
709
def create_crm_tickets_for_delivey_attempted_orders(provider):
710
    try:
711
        tickets_tobe_created = fetch_data(provider.id, [OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE])
712
        userClient = UserClient().get_client()
713
        crmServiceClient = CRMClient().get_client()
714
        for order in tickets_tobe_created:
715
            ticket_created = False
716
            searchFilter = SearchFilter()
717
            user = userClient.getUserByEmail(order.customer_email)
718
            if user is None or user.userId == -1:
719
                searchFilter.customerEmailId = order.customer_email
720
                searchFilter.customerMobileNumber = order.customer_mobilenumber
721
            else:
722
                searchFilter.customerId = user.userId
723
            searchFilter.ticketCategory = TicketCategory.UNDELIVERED
724
            tickets = crmServiceClient.getTickets(searchFilter)
725
            print tickets
726
            for old_ticket in tickets:
727
                if old_ticket.orderId == order.id:
728
                    ticket_created = True
729
                    break
730
            if not ticket_created:
731
                print "creating ticket for orderId:"+str(order.id)
732
                ticket = Ticket()
733
                activity = Activity()
734
                description = order.statusDescription + "\n\nOrder not delivered by courier due to problems at customer end."
735
                ticket.creatorId = 1
736
                ticket.assigneeId = defaultUndeliveredAsssigneeId
737
                ticket.category = TicketCategory.UNDELIVERED
738
                ticket.priority = TicketPriority.HIGH
739
                ticket.status = TicketStatus.OPEN
740
                ticket.description = description
741
                ticket.orderId = order.id
742
                ticket.airwayBillNo = order.airwaybill_no
743
 
744
                activity.creatorId = 1
745
                activity.ticketAssigneeId = ticket.assigneeId
746
                activity.type = ActivityType.OTHER
747
                activity.description = description
748
                activity.ticketCategory = ticket.category
749
                activity.ticketDescription = ticket.description
750
                activity.ticketPriority = ticket.priority
751
                activity.ticketStatus = ticket.status
752
 
753
                if user is None or user.userId == -1:
754
                    ticket.customerEmailId = order.customer_email
755
                    ticket.customerMobileNumber = order.customer_mobilenumber
756
                    ticket.customerName = order.customer_name
757
                    activity.customerEmailId = order.customer_email
758
                    activity.customerMobileNumber = order.customer_mobilenumber
759
                    activity.customerName = order.customer_name
760
                else:
761
                    ticket.customerId = user.userId
762
                    activity.customerId = user.userId
763
 
764
                crmServiceClient.insertTicket(ticket, activity)
765
                '''
766
                Inform user about first delivery attempt
767
                '''
768
                enqueueMailForFDA(order)
769
    except:
770
        print "Some issue while creating crm tickets for orders in FIRST_DELIVERY_ATTEMPT_MADE status"
771
        traceback.print_exc()
772
 
773
def auto_close_crm_tickets_created():
774
    try:
775
        ticket_created_orders = []
776
        tickets_map = {}
777
        crmServiceClient = CRMClient().get_client()
778
        searchFilter = SearchFilter()
779
        searchFilter.ticketCategory = TicketCategory.UNDELIVERED
780
        searchFilter.ticketAssigneeIds = [defaultUndeliveredAsssigneeId]
781
        searchFilter.ticketPriority = TicketPriority.HIGH
782
        searchFilter.ticketStatuses = [TicketStatus.OPEN]
783
        tickets = crmServiceClient.getTickets(searchFilter)
784
        print tickets
785
        for old_ticket in tickets:
786
            ticket_created_orders.append(old_ticket.orderId)
787
            tickets_map[old_ticket.orderId] = old_ticket
788
        print ticket_created_orders
789
        txnClient = TransactionClient().get_client()
790
        orders = txnClient.getOrderList(ticket_created_orders)
791
        for order in orders:
792
            if order.status not in [OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE]:
793
                old_ticket = tickets_map.get(order.id)
794
                old_ticket.status = TicketStatus.CLOSED
795
                activity = Activity()
796
                activity.creatorId = 1
797
                activity.ticketAssigneeId = old_ticket.assigneeId
798
                activity.type = ActivityType.OTHER
799
                activity.description = "Ticket Closed bcoz order status changed to:" + order.statusDescription
800
                activity.ticketCategory = old_ticket.category
801
                activity.ticketDescription = old_ticket.description
802
                activity.ticketPriority = old_ticket.priority
803
                activity.ticketStatus = old_ticket.status
804
 
805
                if old_ticket.customerId is None or old_ticket.customerId == -1:
806
                    activity.customerEmailId = old_ticket.customerEmailId
807
                    activity.customerMobileNumber = old_ticket.customerMobileNumber
808
                    activity.customerName = old_ticket.customerName
809
                else:
810
                    activity.customerId = old_ticket.customerId
811
 
812
                crmServiceClient.updateTicket(old_ticket, activity)
813
    except:
814
        print "Some issue while closing crm tickets for orders in DELIVERY_SUCCESS status"
815
        traceback.print_exc()
816
 
817
def get_py_datetime(datestring, timestring):
818
    # This should be a command line argument.
819
    # Refer http://docs.python.org/library/time.html#time.strftime to
820
    # get a complete list of format specifiers available for date time.
821
    if datestring == '':
822
        return None
823
    if datestring.find('-') == -1:
824
        time_format = "%A,%d %B, %Y %H:%M:%S"
825
    else:
826
        time_format = "%d-%b-%Y %H:%M:%S"
827
    if timestring == '':
828
        timestring = '00:00:00'
829
    time_array = timestring.split(':')
830
    if len(time_array) < 3:
831
        timestring = timestring + ':00'
832
    time_string = datestring + ' ' + timestring[0:8]
833
    mytime = time.strptime(time_string, time_format)
834
    return datetime.datetime(*mytime[:6])
835
 
836
 
837
def getTrimedString(text):
838
    if text is None or text == '':
839
        return ''
840
    else:
841
        text = text.strip().lower()
842
        text_list = list(text)
843
        new_text = ''
844
        for letter in text_list:
845
            if letter.isalnum():
846
                new_text = new_text + str(letter)
847
        return new_text
848
 
849
def main():
850
    parser = optparse.OptionParser()
851
    parser.add_option("-p", "--pickup", dest="pickup_report",
852
                   action="store_true",
853
                   help="Run the pickup reconciliation")
854
    parser.add_option("-d", "--delivery", dest="delivery_report",
855
                   action="store_true",
856
                   help="Run the delivery reconciliation")
857
    parser.add_option("-r", "--reports", dest="gen_reports",
858
                   action="store_true",
859
                   help="Generate logistic reconciliation reports")
860
    parser.add_option("-a", "--all", dest="all_reports",
861
                   action="store_true",
862
                   help="Run all reconciliations")
863
    parser.add_option("-P", "--provider", dest="provider",
6966 rajveer 864
                   default="RedExpress", type="string",
6952 rajveer 865
                   help="The PROVIDER this report is for",
866
                   metavar="PROVIDER")
867
    parser.set_defaults(pickup_report=False, delivery_report=False, gen_reports=False, all_reports=False)
868
    (options, args) = parser.parse_args()
869
    if len(args) != 0:
870
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
871
 
872
    if options.all_reports:
873
        options.pickup_report = True
874
        options.delivery_report = True
875
 
876
    provider = get_provider_by_name(options.provider)
877
 
878
    if options.pickup_report:
879
        process_pickup_records(provider)
880
        #process_dao_pickup_orders(provider)
881
        #process_return_pickup_orders(provider)
882
    if options.delivery_report:
883
        process_local_connection_orders(provider)
7025 rajveer 884
        process_reached_destination_city_orders(provider)
885
        process_first_delivery_attempt_orders(provider)
6952 rajveer 886
        process_delivery_report(provider)
7025 rajveer 887
        create_crm_tickets_for_delivey_attempted_orders(provider)
888
        auto_close_crm_tickets_created()
6952 rajveer 889
    if options.gen_reports:
890
        generate_reports(provider)
891
 
892
if __name__ == '__main__':
893
    main()