Subversion Repositories SmartDukaan

Rev

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