Subversion Repositories SmartDukaan

Rev

Rev 8702 | Rev 8771 | 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' :
427
                        date_obj = datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
428
                        datestring  = date_obj.strftime("%Y-%m-%d")
429
                        timestring = track_update['ExecutionTime']+':00'
430
                        delivery_date = datestring + timestring
431
                        picked_up_orders[airwaybill_no] = delivery_date
432
                        break
8702 manish.sha 433
                break
8714 manish.sha 434
            except:
435
                pass
436
 
6952 rajveer 437
    print "Picked up Orders:"
438
    print picked_up_orders
439
    return picked_up_orders
440
 
441
def read_local_connection_orders(orders_tobe_local_connected):
442
    local_connected_orders = {}
8714 manish.sha 443
 
444
    awb_number_list =[]
6952 rajveer 445
    for order in orders_tobe_local_connected:
8714 manish.sha 446
        awb_number_list.append(order.airwaybill_no)
447
 
448
    track_update_list = get_track_updates(awb_number_list)
449
 
450
    for update in track_update_list:
451
        if update == 'DUMMY':
452
            continue
453
        else:
454
            try:
455
                airwaybill_no = update['ReferenceNo'] 
456
                track_list = update['TrackingList']['TrackingList']
457
                track_list.reverse()
458
                for track_update in track_list:
459
                    if track_update['TrackingCode'] == 'PRO' :
460
                        date_obj = datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
461
                        datestring  = date_obj.strftime("%Y-%m-%d")
462
                        timestring = track_update['ExecutionTime']+':00'
463
                        delivery_date = datestring + timestring
464
                        local_connected_orders[airwaybill_no] = delivery_date
6952 rajveer 465
                        break
466
                break
8714 manish.sha 467
            except:
468
                pass
7025 rajveer 469
 
6952 rajveer 470
    print "Local Connected Orders"
471
    print local_connected_orders
472
 
473
    return local_connected_orders
474
 
475
def read_reached_destination_orders(orders_tobe_reached_destination_city):
476
    destination_city_reached_orders = {}
8714 manish.sha 477
 
478
    awb_number_list =[]
6952 rajveer 479
    for order in orders_tobe_reached_destination_city:
8714 manish.sha 480
        awb_number_list.append(order.airwaybill_no)
481
 
482
    track_update_list = get_track_updates(awb_number_list)
483
 
484
    for update in track_update_list:
485
        if update == 'DUMMY':
486
            continue
487
        else:
488
            try:
489
                airwaybill_no = update['ReferenceNo'] 
490
                track_list = update['TrackingList']['TrackingList']
491
                track_list.reverse()
492
                for track_update in track_list:
493
                    if track_update['TrackingCode'] == 'RDB' :
494
                        date_obj = datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
495
                        datestring  = date_obj.strftime("%Y-%m-%d")
496
                        timestring = track_update['ExecutionTime']+':00'
497
                        delivery_date = datestring + timestring
498
                        destination_city_reached_orders[airwaybill_no] = delivery_date
6952 rajveer 499
                        break
8714 manish.sha 500
                break
501
            except:
502
                pass
6952 rajveer 503
 
504
    print "Destination City Reached Orders"
505
    print destination_city_reached_orders
506
 
507
    return destination_city_reached_orders
508
 
509
def read_first_delivery_attempt_orders(orders_tobe_first_delivery_attempted):
510
    first_atdl_orders = {}
8714 manish.sha 511
 
512
    awb_number_list =[]
6952 rajveer 513
    for order in orders_tobe_first_delivery_attempted:
8714 manish.sha 514
        awb_number_list.append(order.airwaybill_no)
515
 
516
    track_update_list = get_track_updates(awb_number_list)
517
 
518
    for update in track_update_list:
519
        if update == 'DUMMY':
520
            continue
521
        else:
522
            try:
523
                airwaybill_no = update['ReferenceNo'] 
524
                track_list = update['TrackingList']['TrackingList']
525
                track_list.reverse()
526
                for track_update in track_list:
527
                    if track_update['TrackingCode'] == 'OFD' :
528
                        date_obj = datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
529
                        datestring  = date_obj.strftime("%Y-%m-%d")
530
                        timestring = track_update['ExecutionTime']+':00'
531
                        delivery_date = datestring + timestring
532
                        first_atdl_orders[airwaybill_no] = delivery_date
6952 rajveer 533
                        break
7025 rajveer 534
                break
8714 manish.sha 535
            except:
536
                pass
537
 
6952 rajveer 538
 
539
    print "FIRST DELIVERY ATTEMPT MADE Orders"
540
    print first_atdl_orders
541
 
542
    return first_atdl_orders
543
 
544
def read_delivery_orders(orders_tobe_delivered):
545
    delivered_orders = {}
546
    returned_orders = {}
547
    undelivered_orders = {}
8714 manish.sha 548
    awb_order_map = {}
549
 
6952 rajveer 550
    for order in orders_tobe_delivered:
8714 manish.sha 551
        awb_order_list =[]
552
        awb_order_list.append(order.id)
553
        awb_order_list.append(order.shipping_timestamp)
554
        awb_order_map[order.airwaybill_no]= awb_order_list
6952 rajveer 555
 
8714 manish.sha 556
    track_update_list = get_track_updates(awb_order_map.keys())
557
 
558
    for update in track_update_list:
559
        if update == 'DUMMY':
560
            continue
561
        else:
562
            try:
563
                airwaybill_no = update['ReferenceNo'] 
564
                track_list = update['TrackingList']['TrackingList']
565
                track_list.reverse()
566
                reason_for_return = None
567
                for record in track_list:
568
                    if record['TrackingCode'] == 'UDLD' :
569
                        reason_for_return = record['ServiceEvent'].split(" -")[1]
570
                        break
571
 
572
                for track_update in track_list:
573
                    if track_update['TrackingCode'] == 'DLVD' :
574
                        date_obj = datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
575
                        datestring  = date_obj.strftime("%Y-%m-%d")
576
                        timestring = track_update['ExecutionTime']+':00'
577
                        del_date = datestring + timestring
578
                        delivery_date = datetime.strptime(del_date,"%Y-%m-%d %H:%M:%S")
579
                        receiver = track_update['ServiceEvent'].split("[ ")[1].split(" ]")[0]
580
                        if to_py_date(awb_order_map.get(airwaybill_no)[1]) > delivery_date:
581
                            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))
582
                        else:
583
                            delivered_orders[airwaybill_no] = str(delivery_date) + "|" +  receiver
584
                        break
585
                    elif track_update['TrackingCode'] == 'RTO' :
586
                        date_obj = datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
587
                        datestring  = date_obj.strftime("%Y-%m-%d")
588
                        timestring = track_update['ExecutionTime']+':00'
589
                        del_date = datestring + timestring
590
                        delivery_date = datetime.strptime(del_date,"%Y-%m-%d %H:%M:%S")
591
                        if reason_for_return == None:
592
                            returned_orders[airwaybill_no] = str(delivery_date) + "|"  + " Order Booked for Return"
593
                        else:
594
                            returned_orders[airwaybill_no] = str(delivery_date) + "|"  + reason_for_return
595
                        break
596
                    elif track_update['TrackingCode'] == 'UDLD' :
597
                        date_obj = datetime.strptime(track_update['ExecutionDate'].split(' ')[0],"%m/%d/%Y")
598
                        datestring  = date_obj.strftime("%Y-%m-%d")
599
                        timestring = track_update['ExecutionTime']+':00'
600
                        del_date = datestring + timestring
601
                        delivery_date = datetime.strptime(del_date,"%Y-%m-%d %H:%M:%S")
602
                        if reason_for_return == None:
603
                            undelivered_orders[airwaybill_no] = str(delivery_date) + "|" + track_update['ServiceEvent'].split(" -")[1]
604
                        else:
605
                            undelivered_orders[airwaybill_no] = str(delivery_date) + "|" + reason_for_return
606
                        break
607
                break
608
            except:
609
                pass
610
 
6952 rajveer 611
    print "Delivered Orders:"
612
    print delivered_orders
613
 
614
    print "Returned Orders:"
615
    print returned_orders
616
 
617
    print "Undelivered Orders"
618
    print undelivered_orders
619
 
620
    return delivered_orders, returned_orders, undelivered_orders
621
 
622
def update_picked_orders(provider_id, pickup_details):
623
    txnClient = TransactionClient().get_client()
624
    try:
625
        txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
626
    except TransactionServiceException as tex:
627
        print tex.message
628
 
629
def update_picked_doas(provider_id, doa_pickup_details):
630
    txnClient = TransactionClient().get_client()
631
    try:
632
        txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
633
    except TransactionServiceException as tex:
634
        print tex.message
635
 
636
def update_picked_returns(provider_id, returns_pickup_details):
637
    txnClient = TransactionClient().get_client()
638
    try:
639
        txnClient.markReturnOrdersAsPickedUp(provider_id, returns_pickup_details)
640
    except TransactionServiceException as tex:
641
        print tex.message
642
 
643
def update_delivered_orders(provider_id, delivered_orders):
644
    txnClient = TransactionClient().get_client()
645
    try:
646
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
647
    except TransactionServiceException as tex:
648
        print tex.message
649
 
650
def update_returned_orders(provider_id, returned_orders):
651
    txnClient = TransactionClient().get_client()
652
    try:
653
        txnClient.markAsRTOrders(provider_id, returned_orders)
654
    except TransactionServiceException as tex:
655
        print tex.message
656
 
657
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
658
    txnClient = TransactionClient().get_client()
659
    try:
660
        txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
661
    except TransactionServiceException as tex:
662
        print tex.message
663
 
664
def update_local_connected_orders(provider_id, local_connected_orders):
665
    txnClient = TransactionClient().get_client()
666
    try:
667
        txnClient.markOrdersAsLocalConnected(provider_id, local_connected_orders)
668
    except TransactionServiceException as tex:
669
        print tex.message
670
 
671
def update_destination_city_reached_orders(provider_id, destination_city_reached_orders):
672
    txnClient = TransactionClient().get_client()
673
    try:
674
        txnClient.markOrdersAsDestinationCityReached(provider_id, destination_city_reached_orders)
675
    except TransactionServiceException as tex:
676
        print tex.message
677
 
678
def update_first_atdl_orders(provider_id, first_atdl_orders):
679
    txnClient = TransactionClient().get_client()
680
    try:
681
        txnClient.markOrdersAsFirstDeliveryAttempted(provider_id, first_atdl_orders)
682
    except TransactionServiceException as tex:
683
        print tex.message
684
 
685
def print_pickup_mismatch_report(filename, orders):
686
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
687
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
688
    for order in orders:
689
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
690
 
691
def print_dao_return_pickup_mismatch_report(filename, orders):
692
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
693
    writer.writerow(['Order Id', 'Pickup Request No', 'Authorization timestamp'])
694
    for order in orders:
695
        writer.writerow([order.id, order.pickupRequestNo, to_py_date(order.doa_auth_timestamp)])
696
 
697
def print_rto_orders_report(filename, orders):
698
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
699
    writer.writerow(['Order Id', 'AWB No', 'Return date', 'Reason'])
700
    for order in orders:
701
        statusDescription = ''
702
        if order.statusDescription is not None:
703
            statusDescription = order.statusDescription.replace(","," ")
704
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.delivery_timestamp), statusDescription])
705
 
706
def print_undelivered_orders_report(filename, orders):
707
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
708
    writer.writerow(['Order Id', 'AWB No', 'Status', 'Status Description', 'Shipping timestamp', 'Pickup timestamp', 'Promised delivery date', 'Expected delivery date', 'OTG'])
709
    for order in orders:
710
        statusDescription = ''
711
        if order.statusDescription is not None:
712
            statusDescription = order.statusDescription.replace(","," ")
713
        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'])
714
 
715
def create_crm_tickets_for_delivey_attempted_orders(provider):
716
    try:
717
        tickets_tobe_created = fetch_data(provider.id, [OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE])
718
        userClient = UserClient().get_client()
719
        crmServiceClient = CRMClient().get_client()
720
        for order in tickets_tobe_created:
721
            ticket_created = False
722
            searchFilter = SearchFilter()
723
            user = userClient.getUserByEmail(order.customer_email)
724
            if user is None or user.userId == -1:
725
                searchFilter.customerEmailId = order.customer_email
726
                searchFilter.customerMobileNumber = order.customer_mobilenumber
727
            else:
728
                searchFilter.customerId = user.userId
729
            searchFilter.ticketCategory = TicketCategory.UNDELIVERED
730
            tickets = crmServiceClient.getTickets(searchFilter)
731
            print tickets
732
            for old_ticket in tickets:
733
                if old_ticket.orderId == order.id:
734
                    ticket_created = True
735
                    break
736
            if not ticket_created:
737
                print "creating ticket for orderId:"+str(order.id)
738
                ticket = Ticket()
739
                activity = Activity()
740
                description = order.statusDescription + "\n\nOrder not delivered by courier due to problems at customer end."
741
                ticket.creatorId = 1
742
                ticket.assigneeId = defaultUndeliveredAsssigneeId
743
                ticket.category = TicketCategory.UNDELIVERED
744
                ticket.priority = TicketPriority.HIGH
745
                ticket.status = TicketStatus.OPEN
746
                ticket.description = description
747
                ticket.orderId = order.id
748
                ticket.airwayBillNo = order.airwaybill_no
749
 
750
                activity.creatorId = 1
751
                activity.ticketAssigneeId = ticket.assigneeId
752
                activity.type = ActivityType.OTHER
753
                activity.description = description
754
                activity.ticketCategory = ticket.category
755
                activity.ticketDescription = ticket.description
756
                activity.ticketPriority = ticket.priority
757
                activity.ticketStatus = ticket.status
758
 
759
                if user is None or user.userId == -1:
760
                    ticket.customerEmailId = order.customer_email
761
                    ticket.customerMobileNumber = order.customer_mobilenumber
762
                    ticket.customerName = order.customer_name
763
                    activity.customerEmailId = order.customer_email
764
                    activity.customerMobileNumber = order.customer_mobilenumber
765
                    activity.customerName = order.customer_name
766
                else:
767
                    ticket.customerId = user.userId
768
                    activity.customerId = user.userId
769
 
770
                crmServiceClient.insertTicket(ticket, activity)
771
                '''
772
                Inform user about first delivery attempt
773
                '''
774
                enqueueMailForFDA(order)
775
    except:
776
        print "Some issue while creating crm tickets for orders in FIRST_DELIVERY_ATTEMPT_MADE status"
777
        traceback.print_exc()
778
 
779
def auto_close_crm_tickets_created():
780
    try:
781
        ticket_created_orders = []
782
        tickets_map = {}
783
        crmServiceClient = CRMClient().get_client()
784
        searchFilter = SearchFilter()
785
        searchFilter.ticketCategory = TicketCategory.UNDELIVERED
786
        searchFilter.ticketAssigneeIds = [defaultUndeliveredAsssigneeId]
787
        searchFilter.ticketPriority = TicketPriority.HIGH
788
        searchFilter.ticketStatuses = [TicketStatus.OPEN]
789
        tickets = crmServiceClient.getTickets(searchFilter)
790
        print tickets
791
        for old_ticket in tickets:
792
            ticket_created_orders.append(old_ticket.orderId)
793
            tickets_map[old_ticket.orderId] = old_ticket
794
        print ticket_created_orders
795
        txnClient = TransactionClient().get_client()
796
        orders = txnClient.getOrderList(ticket_created_orders)
797
        for order in orders:
798
            if order.status not in [OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE]:
799
                old_ticket = tickets_map.get(order.id)
800
                old_ticket.status = TicketStatus.CLOSED
801
                activity = Activity()
802
                activity.creatorId = 1
803
                activity.ticketAssigneeId = old_ticket.assigneeId
804
                activity.type = ActivityType.OTHER
805
                activity.description = "Ticket Closed bcoz order status changed to:" + order.statusDescription
806
                activity.ticketCategory = old_ticket.category
807
                activity.ticketDescription = old_ticket.description
808
                activity.ticketPriority = old_ticket.priority
809
                activity.ticketStatus = old_ticket.status
810
 
811
                if old_ticket.customerId is None or old_ticket.customerId == -1:
812
                    activity.customerEmailId = old_ticket.customerEmailId
813
                    activity.customerMobileNumber = old_ticket.customerMobileNumber
814
                    activity.customerName = old_ticket.customerName
815
                else:
816
                    activity.customerId = old_ticket.customerId
817
 
818
                crmServiceClient.updateTicket(old_ticket, activity)
819
    except:
820
        print "Some issue while closing crm tickets for orders in DELIVERY_SUCCESS status"
821
        traceback.print_exc()
822
 
823
def get_py_datetime(datestring, timestring):
824
    # This should be a command line argument.
825
    # Refer http://docs.python.org/library/time.html#time.strftime to
826
    # get a complete list of format specifiers available for date time.
827
    if datestring == '':
828
        return None
829
    if datestring.find('-') == -1:
830
        time_format = "%A,%d %B, %Y %H:%M:%S"
831
    else:
832
        time_format = "%d-%b-%Y %H:%M:%S"
833
    if timestring == '':
834
        timestring = '00:00:00'
835
    time_array = timestring.split(':')
836
    if len(time_array) < 3:
837
        timestring = timestring + ':00'
838
    time_string = datestring + ' ' + timestring[0:8]
839
    mytime = time.strptime(time_string, time_format)
840
    return datetime.datetime(*mytime[:6])
841
 
842
 
843
def getTrimedString(text):
844
    if text is None or text == '':
845
        return ''
846
    else:
847
        text = text.strip().lower()
848
        text_list = list(text)
849
        new_text = ''
850
        for letter in text_list:
851
            if letter.isalnum():
852
                new_text = new_text + str(letter)
853
        return new_text
854
 
855
def main():
856
    parser = optparse.OptionParser()
857
    parser.add_option("-p", "--pickup", dest="pickup_report",
858
                   action="store_true",
859
                   help="Run the pickup reconciliation")
860
    parser.add_option("-d", "--delivery", dest="delivery_report",
861
                   action="store_true",
862
                   help="Run the delivery reconciliation")
863
    parser.add_option("-r", "--reports", dest="gen_reports",
864
                   action="store_true",
865
                   help="Generate logistic reconciliation reports")
866
    parser.add_option("-a", "--all", dest="all_reports",
867
                   action="store_true",
868
                   help="Run all reconciliations")
869
    parser.add_option("-P", "--provider", dest="provider",
6966 rajveer 870
                   default="RedExpress", type="string",
6952 rajveer 871
                   help="The PROVIDER this report is for",
872
                   metavar="PROVIDER")
873
    parser.set_defaults(pickup_report=False, delivery_report=False, gen_reports=False, all_reports=False)
874
    (options, args) = parser.parse_args()
875
    if len(args) != 0:
876
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
877
 
878
    if options.all_reports:
879
        options.pickup_report = True
880
        options.delivery_report = True
881
 
882
    provider = get_provider_by_name(options.provider)
883
 
884
    if options.pickup_report:
885
        process_pickup_records(provider)
886
        #process_dao_pickup_orders(provider)
887
        #process_return_pickup_orders(provider)
888
    if options.delivery_report:
889
        process_local_connection_orders(provider)
7025 rajveer 890
        process_reached_destination_city_orders(provider)
891
        process_first_delivery_attempt_orders(provider)
6952 rajveer 892
        process_delivery_report(provider)
7025 rajveer 893
        create_crm_tickets_for_delivey_attempted_orders(provider)
894
        auto_close_crm_tickets_created()
6952 rajveer 895
    if options.gen_reports:
896
        generate_reports(provider)
897
 
898
if __name__ == '__main__':
899
    main()