Subversion Repositories SmartDukaan

Rev

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