Subversion Repositories SmartDukaan

Rev

Rev 6952 | Rev 7025 | 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
39
import csv
40
import datetime
41
import optparse
42
import sys
43
import time
44
import traceback
45
import urllib2
46
from suds.client import Client
47
if __name__ == '__main__' and __package__ is None:
48
    import os
49
    sys.path.insert(0, os.getcwd())
50
 
51
 
52
RED_EXPRESS_URL = "http://tracking.getsetred.net/TrackingService.svc?wsdl"
53
username = 'C00086721141'
54
password = 'SANDEEP.SACHDEVA@SHOP2020.IN'
55
 
56
client = None
57
def getClient():
58
    global client
59
    if client is None:
60
        client = Client(RED_EXPRESS_URL, timeout=70)
61
    return client
62
 
63
defaultUndeliveredAsssigneeId = 19
64
from_user = 'cnc.center@shop2020.in'
65
from_pwd = '5h0p2o2o'
66
to = ['cnc.center@shop2020.in', "amit.sirohi@shop2020.in", "sandeep.sachdeva@shop2020.in", "manoj.kumar@shop2020.in", "rajveer.singh@shop2020.in"]
67
 
68
 
69
def get_updates(awb_number): 
70
    str = getClient().service.ProcessTrackingRequest('<TrackingRequest><Request><UserID>' + username + '</UserID><Password>' + password + '</Password><TrackingID>' + awb_number + '</TrackingID><TrackingLevel>ALL_DETAILS</TrackingLevel></Request></TrackingRequest>')
71
    print str
72
    return str
73
 
74
 
75
 
76
def process_dao_pickup_orders(provider):
77
    try:
78
        doas_tobe_picked_up = fetch_data(provider.id, [OrderStatus.DOA_PICKUP_CONFIRMED])
79
        doa_pickup_details = read_dao_return_pickup_orders(doas_tobe_picked_up)
80
        if doa_pickup_details:
81
            update_picked_doas(provider.id, doa_pickup_details)
82
    except:
83
        print "Some issue while processing the orders in DOA_PICKUP_CONFIRMED status"
84
        traceback.print_exc()
85
 
86
def process_return_pickup_orders(provider):
87
    try:
88
        returns_tobe_picked_up = fetch_data(provider.id, [OrderStatus.RET_PICKUP_CONFIRMED])
89
        returns_pickup_details = read_dao_return_pickup_orders(returns_tobe_picked_up)
90
        if returns_pickup_details:
91
            update_picked_returns(provider.id, returns_pickup_details)
92
    except:
93
        print "Some issue while processing the orders in RET_PICKUP_CONFIRMED status"
94
        traceback.print_exc()
95
 
96
def process_pickup_records(provider):
97
    try:
98
        orders_tobe_picked_up = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH])
99
        pickup_details = read_pickup_orders(orders_tobe_picked_up)
100
        if pickup_details:
101
            update_picked_orders(provider.id, pickup_details)
102
    except:
103
        print "Some issue while processing the orders in SHIPPED_FROM_WH status"
104
        traceback.print_exc()
105
 
106
def process_local_connection_orders(provider):
107
    try:
108
        orders_tobe_local_connected = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST])
109
        local_connected_orders = read_local_connection_orders(orders_tobe_local_connected)
110
        if local_connected_orders:
111
            update_local_connected_orders(provider.id, local_connected_orders)
112
    except:
113
        print "Some issue while processing the orders for local connection status"
114
        traceback.print_exc()
115
 
116
def process_reached_destination_city_orders(provider):
117
    try:
118
        orders_tobe_reached_destination_city = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY])
119
        destination_city_reached_orders = read_reached_destination_orders(orders_tobe_reached_destination_city)
120
        if destination_city_reached_orders:
121
            update_destination_city_reached_orders(provider.id, destination_city_reached_orders)
122
    except:
123
        print "Some issue while processing the orders for Reached Destination City status"
124
        traceback.print_exc()
125
 
126
def process_first_delivery_attempt_orders(provider):
127
    try:
128
        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])
129
        first_atdl_orders = read_first_delivery_attempt_orders(orders_tobe_first_delivery_attempted)
130
        if first_atdl_orders:
131
            update_first_atdl_orders(provider.id, first_atdl_orders)
132
    except:
133
        print "Some issue while processing the orders for First delivery attempt status"
134
        traceback.print_exc()
135
 
136
def process_delivery_report(provider):
137
    try:
138
        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])
139
        delivered_orders, returned_orders, undelivered_orders = read_delivery_orders(orders_tobe_delivered)
140
        if delivered_orders:
141
            update_delivered_orders(provider.id, delivered_orders)
142
        if returned_orders:
143
            update_returned_orders(provider.id, returned_orders)
144
        if undelivered_orders:
145
            update_reason_of_undelivered_orders(provider.id, undelivered_orders)
146
    except:
147
        print "Some issue while processing the orders for delivery status"
148
        traceback.print_exc()
149
 
150
def generate_reports(provider):
151
    get_doas_not_picked_up(provider)
152
    get_returns_not_picked_up(provider)
153
    get_orders_not_picked_up(provider)
154
    get_orders_pending_local_connection(provider)
155
    get_returned_orders(provider)
156
    get_orders_not_delivered(provider)
157
 
158
def get_doas_not_picked_up(provider):
159
    txnClient = TransactionClient().get_client()
160
    try:
161
        doas_not_picked_up = txnClient.getDoasNotPickedUp(provider.id)
162
    except TransactionServiceException as tex:
163
        print tex.message
164
 
165
    try:
166
        if doas_not_picked_up:
167
            print "DOAs not Picked up:"
168
            print doas_not_picked_up
169
            mismatch_file = "/tmp/BlueDart_DoaPickupMismatch.csv"
170
            print "Some of our DOA orders were not picked up. Printing report to:" + mismatch_file
171
            print_dao_return_pickup_mismatch_report(mismatch_file, doas_not_picked_up)
172
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
173
            mail(from_user, from_pwd, to,\
174
                 "DOA Pickup Mismatch for " + provider.name,\
175
                 "This is a system generated email.Please don't reply to it.",\
176
                 pickup_mismatch_part)
177
    except Exception:
178
        print "Some issue sending the DOA mismatch report"
179
        traceback.print_exc()
180
 
181
def get_returns_not_picked_up(provider):
182
    txnClient = TransactionClient().get_client()
183
    try:
184
        returns_not_picked_up = txnClient.getReturnOrdersNotPickedUp(provider.id)
185
    except TransactionServiceException as tex:
186
        print tex.message
187
 
188
    try:
189
        if returns_not_picked_up:
190
            print "Return Orders not Picked up:"
191
            print returns_not_picked_up
192
            mismatch_file = "/tmp/BlueDart_ReturnsPickupMismatch.csv"
193
            print "Some of our Return orders were not picked up. Printing report to:" + mismatch_file
194
            print_dao_return_pickup_mismatch_report(mismatch_file, returns_not_picked_up)
195
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
196
            mail(from_user, from_pwd, to,\
197
                 "Return orders Pickup Mismatch for " + provider.name,\
198
                 "This is a system generated email.Please don't reply to it.",\
199
                 pickup_mismatch_part)
200
    except Exception:
201
        print "Some issue sending the Return orders mismatch report"
202
        traceback.print_exc()
203
 
204
def get_orders_not_picked_up(provider):
205
    txnClient = TransactionClient().get_client()
206
    try:
207
        orders_not_picked_up = txnClient.getOrdersNotPickedUp(provider.id)
208
    except TransactionServiceException as tex:
209
        print tex.message
210
 
211
    try:
212
        if orders_not_picked_up:
213
            print "Orders not Picked up:"
214
            print orders_not_picked_up
215
            mismatch_file = "/tmp/BlueDart_PickupMismatch.csv"
216
            print "Some of our orders were not picked up. Printing report to:" + mismatch_file
217
            print_pickup_mismatch_report(mismatch_file, orders_not_picked_up)
218
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
219
            mail(from_user, from_pwd, to,\
220
                 "Order Pickup Mismatch for " + provider.name,\
221
                 "This is a system generated email.Please don't reply to it.",\
222
                 pickup_mismatch_part)
223
    except Exception:
224
        print "Some issue sending the pickup mismatch report"
225
        traceback.print_exc()
226
 
227
def get_orders_pending_local_connection(provider):
228
    txnClient = TransactionClient().get_client()
229
    try:
230
        orders_pending_local_connection = txnClient.getOrdersNotLocalConnected(provider.id)
231
    except TransactionServiceException as tex:
232
        print tex.message
233
 
234
    try:
235
        if orders_pending_local_connection:
236
            print "Local Connection Pending Orders:"
237
            print orders_pending_local_connection
238
            mismatch_file = "/tmp/BlueDart_LocalConnectionPendingOrders.csv"
239
            print "Some of our Orders were not Shipped to Destination yet. Printing report to:" + mismatch_file
240
            print_undelivered_orders_report(mismatch_file, orders_pending_local_connection)
241
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
242
            mail(from_user, from_pwd, to,\
243
                 "Orders that are not Shipped to Destination yet 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 updating and sending the Local Connection orders report"
248
        traceback.print_exc()
249
 
250
def get_returned_orders(provider):
251
    txnClient = TransactionClient().get_client()
252
    try:
253
        returned_orders = txnClient.getRTOrders(provider.id)
254
    except TransactionServiceException as tex:
255
        print tex.message
256
 
257
    try:
258
        if returned_orders:
259
            print "Returned Orders:"
260
            print returned_orders
261
            returned_orders_file = "/tmp/BlueDart_ReturnedOrders.csv"
262
            print "Some of our Orders were returned by logistics provider. Printing report to:" + returned_orders_file
263
            print_rto_orders_report(returned_orders_file, returned_orders)
264
            returned_orders_report = [get_attachment_part(returned_orders_file)]
265
            mail(from_user, from_pwd, to,\
266
                 "Returned Orders Report for " + provider.name,\
267
                 "This is a system generated email.Please don't reply to it.",\
268
                 returned_orders_report)
269
    except:
270
        print "Some issue sending the returned orders report"
271
        traceback.print_exc()
272
 
273
def get_orders_not_delivered(provider):
274
    txnClient = TransactionClient().get_client()
275
    try:
276
        orders_not_delivered = txnClient.getNonDeliveredOrdersbyCourier(provider.id)
277
    except TransactionServiceException as tex:
278
        print tex.message
279
 
280
    try:
281
        if orders_not_delivered:
282
            print "Undelivered Orders:"
283
            print orders_not_delivered
284
            mismatch_file = "/tmp/BlueDart_UndeliveredOrders.csv"
285
            print "Some of our Orders were not delivered. Printing report to:" + mismatch_file
286
            print_undelivered_orders_report(mismatch_file, orders_not_delivered)
287
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
288
            mail(from_user, from_pwd, to,\
289
                 "Orders that are undelivered but picked up or shipped four days ago 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 updating and sending the undelivered orders report"
294
        traceback.print_exc()
295
 
296
def get_provider_by_name(provider_name):
297
    logistics_client = LogisticsClient().get_client()
298
    provider = None
299
    providers = logistics_client.getAllProviders()
300
    for p in providers:
301
        if p.name == provider_name:
302
            provider=p
303
            break
304
    if provider == None:
305
        sys.exit("Can't continue execution: No such provider")
306
    return provider
307
 
308
def fetch_data(provider_id, order_status_list):
309
    txnClient = TransactionClient().get_client()
310
    try:
311
        doas_tobe_picked_up = txnClient.getOrdersForProviderForStatus(provider_id, order_status_list)
312
        return doas_tobe_picked_up
313
    except TransactionServiceException as tex:
314
        print tex.message
315
 
316
def read_dao_return_pickup_orders(orders_tobe_picked_up):
317
    #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
318
    picked_up_orders = {}
319
    for order in orders_tobe_picked_up:
320
        try:
321
            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)
322
            root = parse(urllib2.urlopen(uri)).getroot()
323
            children = root.getchildren()
324
            for child in children:
325
                nodes = child.findall('Scans/ScanDetail')
326
                for element in reversed(nodes):
327
                    datestring = element.findtext('ScanDate', '')
328
                    timestring = element.findtext('ScanTime', '')
329
                    delivery_date = get_py_datetime(datestring, timestring)
330
                    picked_up_orders[order.pickupRequestNo] = str(delivery_date)
331
                    break
332
                break
333
        except:
334
            pass
335
 
336
    print "Picked up Orders:"
337
    print picked_up_orders
338
    return picked_up_orders
339
 
340
def read_pickup_orders(orders_tobe_picked_up):
341
    picked_up_orders = {}
342
    for order in orders_tobe_picked_up:
343
        try:
344
            root =  fromstring(str(get_updates(order.airwaybill_no)))
345
            children = root.getchildren()
346
            for child in children:
347
                nodes = child.findall('ShipmentInfo/ShipmentEvent')
348
                for element in reversed(nodes):
349
                    datestring = element.findtext('Date', '')
350
                    timestring = element.findtext('Time', '')
351
                    delivery_date = get_py_datetime(datestring, timestring)
352
                    picked_up_orders[order.airwaybill_no] = str(delivery_date)
353
                    break
354
                break
355
        except:
356
            pass
357
 
358
    print "Picked up Orders:"
359
    print picked_up_orders
360
    return picked_up_orders
361
 
362
def read_local_connection_orders(orders_tobe_local_connected):
363
    local_connected_orders = {}
364
    for order in orders_tobe_local_connected:
365
        try:
366
            root =  fromstring(str(get_updates(order.airwaybill_no)))
367
            children = root.getchildren()
368
            for child in children:
369
                nodes = child.findall('ShipmentInfo/ShipmentEvent')
370
                for element in reversed(nodes):
371
                    if (getTrimedString(element.findtext('ServiceEvent', '')).find(getTrimedString('Reached at OKHLA SDC')) != -1):
372
                        datestring = element.findtext('Date', '')
373
                        timestring = element.findtext('Time', '')
374
                        delivery_date = get_py_datetime(datestring, timestring)
375
                        local_connected_orders[order.airwaybill_no] = str(delivery_date)
376
                        break
377
                break
378
        except:
379
            pass
380
 
381
    print "Local Connected Orders"
382
    print local_connected_orders
383
 
384
    return local_connected_orders
385
 
386
def read_reached_destination_orders(orders_tobe_reached_destination_city):
387
    destination_city_reached_orders = {}
388
    for order in orders_tobe_reached_destination_city:
389
        try:
390
            root =  fromstring(str(get_updates(order.airwaybill_no)))
391
            children = root.getchildren()
392
            child_number = 0
393
            for child in children:
394
                child_number = child_number + 1
395
                nodes = child.findall('ShipmentInfo/ShipmentEvent')
396
                orderstatus = None
397
                for element in nodes:
398
                    if element.findtext('ScanType', '') == 'UD' and (getTrimedString(element.findtext('Scan', '')) == getTrimedString('Shipment Inscan') or getTrimedString(element.findtext('Scan', '')) == getTrimedString('Shipment-Autoscan')) and element.findtext('ScannedLocation', '') == child.findtext('Destination', ''):
399
                        datestring = element.findtext('Date', '')
400
                        timestring = element.findtext('Time', '')
401
                        delivery_date = get_py_datetime(datestring, timestring)
402
                        destination_city_reached_orders[order.airwaybill_no] = str(delivery_date)
403
                        orderstatus = 'UD'
404
                        break
405
                    elif element.findtext('ScanType', '') == 'RD':
406
                        if child_number < len(children):
407
                            orderstatus = 'RD'
408
                            break
409
                if orderstatus != 'RD':
410
                    break
411
        except:
412
            pass
413
 
414
    print "Destination City Reached Orders"
415
    print destination_city_reached_orders
416
 
417
    return destination_city_reached_orders
418
 
419
def read_first_delivery_attempt_orders(orders_tobe_first_delivery_attempted):
420
    first_atdl_orders = {}
421
    for order in orders_tobe_first_delivery_attempted:
422
        try:
423
            root =  fromstring(str(get_updates(order.airwaybill_no)))
424
            children = root.getchildren()
425
            children = root.getchildren()
426
            child_number = 0
427
            for child in children:
428
                child_number = child_number + 1
429
                nodes = child.findall('ShipmentInfo/ShipmentEvent')
430
                orderstatus = None
431
                node_number = len(nodes)-1
432
                for element in reversed(nodes):
433
                    if element.findtext('ScanType', '') == 'UD' and getTrimedString(element.findtext('Scan', '')) == getTrimedString('Shipment Outscan'):
434
                        if node_number != 0 and nodes[node_number-1].findtext('ScanType', '') == 'UD':
435
                            element = nodes[node_number-1]
436
                            datestring = element.findtext('ScanDate', '')
437
                            timestring = element.findtext('ScanTime', '')
438
                            delivery_date = get_py_datetime(datestring, timestring)
439
                            reason_for_nondelivery = element.findtext('Scan', '')
440
                            first_atdl_orders[order.airwaybill_no] = str(delivery_date) + "|" + reason_for_nondelivery
441
                        orderstatus = 'UD'
442
                        break
443
                    elif element.findtext('ScanType', '') == 'UD' and getTrimedString(element.findtext('Scan', '')) == getTrimedString("Shpt Held At Destination As Per Shipper's Request"):
444
                        datestring = element.findtext('ScanDate', '')
445
                        timestring = element.findtext('ScanTime', '')
446
                        delivery_date = get_py_datetime(datestring, timestring)
447
                        reason_for_nondelivery = element.findtext('Scan', '')
448
                        first_atdl_orders[order.airwaybill_no] = str(delivery_date) + "|" + reason_for_nondelivery
449
                        orderstatus = 'UD'
450
                        break
451
                    elif element.findtext('ScanType', '') == 'RD':
452
                        if child_number < len(children):
453
                            orderstatus = 'RD'
454
                            break
455
                    node_number = node_number - 1
456
                if orderstatus != 'RD':
457
                    break
458
        except:
459
            pass
460
 
461
    print "FIRST DELIVERY ATTEMPT MADE Orders"
462
    print first_atdl_orders
463
 
464
    return first_atdl_orders
465
 
466
def read_delivery_orders(orders_tobe_delivered):
467
    delivered_orders = {}
468
    returned_orders = {}
469
    undelivered_orders = {}
470
    for order in orders_tobe_delivered:
471
        try:
472
            root =  fromstring(str(get_updates(order.airwaybill_no)))
473
            children = root.getchildren()
474
            child_number = 0
475
            for child in children:
476
                child_number = child_number + 1
477
                nodes = child.findall('ShipmentInfo/ShipmentEvent')
478
                if len(nodes):
479
                    node_number = len(nodes)-1
480
                    for element in reversed(nodes):
481
                        if element.findtext('StatusCode', '') == 'Delivered':
482
                            datestring = element.findtext('Date', '')
483
                            timestring = element.findtext('Time', '')
484
                            delivery_date = get_py_datetime(datestring, timestring)
485
                            receiver = 'Receiver'
486
                            delivered_orders[order.airwaybill_no] = str(delivery_date) + "|" +  receiver
487
                            break
488
                        elif element.findtext('StatusCode', '') == 'RTO':
489
                            datestring = element.findtext('Date', '')
490
                            timestring = element.findtext('Time', '')
491
                            delivery_date = get_py_datetime(datestring, timestring)
492
                            if node_number < len(nodes)-1:
493
                                reason_for_return = nodes[node_number+1].findtext('ServiceEvent', '')
494
                            else:
495
                                reason_for_return = element.findtext('ServiceEvent', '')
496
                            returned_orders[order.airwaybill_no] = str(delivery_date) + "|" + reason_for_return
497
                            break       
498
                        node_number = node_number - 1
499
        except:
500
            pass
501
 
502
    print "Delivered Orders:"
503
    print delivered_orders
504
 
505
    print "Returned Orders:"
506
    print returned_orders
507
 
508
    print "Undelivered Orders"
509
    print undelivered_orders
510
 
511
    return delivered_orders, returned_orders, undelivered_orders
512
 
513
def update_picked_orders(provider_id, pickup_details):
514
    txnClient = TransactionClient().get_client()
515
    try:
516
        txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
517
    except TransactionServiceException as tex:
518
        print tex.message
519
 
520
def update_picked_doas(provider_id, doa_pickup_details):
521
    txnClient = TransactionClient().get_client()
522
    try:
523
        txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
524
    except TransactionServiceException as tex:
525
        print tex.message
526
 
527
def update_picked_returns(provider_id, returns_pickup_details):
528
    txnClient = TransactionClient().get_client()
529
    try:
530
        txnClient.markReturnOrdersAsPickedUp(provider_id, returns_pickup_details)
531
    except TransactionServiceException as tex:
532
        print tex.message
533
 
534
def update_delivered_orders(provider_id, delivered_orders):
535
    txnClient = TransactionClient().get_client()
536
    try:
537
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
538
    except TransactionServiceException as tex:
539
        print tex.message
540
 
541
def update_returned_orders(provider_id, returned_orders):
542
    txnClient = TransactionClient().get_client()
543
    try:
544
        txnClient.markAsRTOrders(provider_id, returned_orders)
545
    except TransactionServiceException as tex:
546
        print tex.message
547
 
548
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
549
    txnClient = TransactionClient().get_client()
550
    try:
551
        txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
552
    except TransactionServiceException as tex:
553
        print tex.message
554
 
555
def update_local_connected_orders(provider_id, local_connected_orders):
556
    txnClient = TransactionClient().get_client()
557
    try:
558
        txnClient.markOrdersAsLocalConnected(provider_id, local_connected_orders)
559
    except TransactionServiceException as tex:
560
        print tex.message
561
 
562
def update_destination_city_reached_orders(provider_id, destination_city_reached_orders):
563
    txnClient = TransactionClient().get_client()
564
    try:
565
        txnClient.markOrdersAsDestinationCityReached(provider_id, destination_city_reached_orders)
566
    except TransactionServiceException as tex:
567
        print tex.message
568
 
569
def update_first_atdl_orders(provider_id, first_atdl_orders):
570
    txnClient = TransactionClient().get_client()
571
    try:
572
        txnClient.markOrdersAsFirstDeliveryAttempted(provider_id, first_atdl_orders)
573
    except TransactionServiceException as tex:
574
        print tex.message
575
 
576
def print_pickup_mismatch_report(filename, orders):
577
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
578
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
579
    for order in orders:
580
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
581
 
582
def print_dao_return_pickup_mismatch_report(filename, orders):
583
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
584
    writer.writerow(['Order Id', 'Pickup Request No', 'Authorization timestamp'])
585
    for order in orders:
586
        writer.writerow([order.id, order.pickupRequestNo, to_py_date(order.doa_auth_timestamp)])
587
 
588
def print_rto_orders_report(filename, orders):
589
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
590
    writer.writerow(['Order Id', 'AWB No', 'Return date', 'Reason'])
591
    for order in orders:
592
        statusDescription = ''
593
        if order.statusDescription is not None:
594
            statusDescription = order.statusDescription.replace(","," ")
595
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.delivery_timestamp), statusDescription])
596
 
597
def print_undelivered_orders_report(filename, orders):
598
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
599
    writer.writerow(['Order Id', 'AWB No', 'Status', 'Status Description', 'Shipping timestamp', 'Pickup timestamp', 'Promised delivery date', 'Expected delivery date', 'OTG'])
600
    for order in orders:
601
        statusDescription = ''
602
        if order.statusDescription is not None:
603
            statusDescription = order.statusDescription.replace(","," ")
604
        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'])
605
 
606
def create_crm_tickets_for_delivey_attempted_orders(provider):
607
    try:
608
        tickets_tobe_created = fetch_data(provider.id, [OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE])
609
        userClient = UserClient().get_client()
610
        crmServiceClient = CRMClient().get_client()
611
        for order in tickets_tobe_created:
612
            ticket_created = False
613
            searchFilter = SearchFilter()
614
            user = userClient.getUserByEmail(order.customer_email)
615
            if user is None or user.userId == -1:
616
                searchFilter.customerEmailId = order.customer_email
617
                searchFilter.customerMobileNumber = order.customer_mobilenumber
618
            else:
619
                searchFilter.customerId = user.userId
620
            searchFilter.ticketCategory = TicketCategory.UNDELIVERED
621
            tickets = crmServiceClient.getTickets(searchFilter)
622
            print tickets
623
            for old_ticket in tickets:
624
                if old_ticket.orderId == order.id:
625
                    ticket_created = True
626
                    break
627
            if not ticket_created:
628
                print "creating ticket for orderId:"+str(order.id)
629
                ticket = Ticket()
630
                activity = Activity()
631
                description = order.statusDescription + "\n\nOrder not delivered by courier due to problems at customer end."
632
                ticket.creatorId = 1
633
                ticket.assigneeId = defaultUndeliveredAsssigneeId
634
                ticket.category = TicketCategory.UNDELIVERED
635
                ticket.priority = TicketPriority.HIGH
636
                ticket.status = TicketStatus.OPEN
637
                ticket.description = description
638
                ticket.orderId = order.id
639
                ticket.airwayBillNo = order.airwaybill_no
640
 
641
                activity.creatorId = 1
642
                activity.ticketAssigneeId = ticket.assigneeId
643
                activity.type = ActivityType.OTHER
644
                activity.description = description
645
                activity.ticketCategory = ticket.category
646
                activity.ticketDescription = ticket.description
647
                activity.ticketPriority = ticket.priority
648
                activity.ticketStatus = ticket.status
649
 
650
                if user is None or user.userId == -1:
651
                    ticket.customerEmailId = order.customer_email
652
                    ticket.customerMobileNumber = order.customer_mobilenumber
653
                    ticket.customerName = order.customer_name
654
                    activity.customerEmailId = order.customer_email
655
                    activity.customerMobileNumber = order.customer_mobilenumber
656
                    activity.customerName = order.customer_name
657
                else:
658
                    ticket.customerId = user.userId
659
                    activity.customerId = user.userId
660
 
661
                crmServiceClient.insertTicket(ticket, activity)
662
                '''
663
                Inform user about first delivery attempt
664
                '''
665
                enqueueMailForFDA(order)
666
    except:
667
        print "Some issue while creating crm tickets for orders in FIRST_DELIVERY_ATTEMPT_MADE status"
668
        traceback.print_exc()
669
 
670
def auto_close_crm_tickets_created():
671
    try:
672
        ticket_created_orders = []
673
        tickets_map = {}
674
        crmServiceClient = CRMClient().get_client()
675
        searchFilter = SearchFilter()
676
        searchFilter.ticketCategory = TicketCategory.UNDELIVERED
677
        searchFilter.ticketAssigneeIds = [defaultUndeliveredAsssigneeId]
678
        searchFilter.ticketPriority = TicketPriority.HIGH
679
        searchFilter.ticketStatuses = [TicketStatus.OPEN]
680
        tickets = crmServiceClient.getTickets(searchFilter)
681
        print tickets
682
        for old_ticket in tickets:
683
            ticket_created_orders.append(old_ticket.orderId)
684
            tickets_map[old_ticket.orderId] = old_ticket
685
        print ticket_created_orders
686
        txnClient = TransactionClient().get_client()
687
        orders = txnClient.getOrderList(ticket_created_orders)
688
        for order in orders:
689
            if order.status not in [OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE]:
690
                old_ticket = tickets_map.get(order.id)
691
                old_ticket.status = TicketStatus.CLOSED
692
                activity = Activity()
693
                activity.creatorId = 1
694
                activity.ticketAssigneeId = old_ticket.assigneeId
695
                activity.type = ActivityType.OTHER
696
                activity.description = "Ticket Closed bcoz order status changed to:" + order.statusDescription
697
                activity.ticketCategory = old_ticket.category
698
                activity.ticketDescription = old_ticket.description
699
                activity.ticketPriority = old_ticket.priority
700
                activity.ticketStatus = old_ticket.status
701
 
702
                if old_ticket.customerId is None or old_ticket.customerId == -1:
703
                    activity.customerEmailId = old_ticket.customerEmailId
704
                    activity.customerMobileNumber = old_ticket.customerMobileNumber
705
                    activity.customerName = old_ticket.customerName
706
                else:
707
                    activity.customerId = old_ticket.customerId
708
 
709
                crmServiceClient.updateTicket(old_ticket, activity)
710
    except:
711
        print "Some issue while closing crm tickets for orders in DELIVERY_SUCCESS status"
712
        traceback.print_exc()
713
 
714
def get_py_datetime(datestring, timestring):
715
    # This should be a command line argument.
716
    # Refer http://docs.python.org/library/time.html#time.strftime to
717
    # get a complete list of format specifiers available for date time.
718
    if datestring == '':
719
        return None
720
    if datestring.find('-') == -1:
721
        time_format = "%A,%d %B, %Y %H:%M:%S"
722
    else:
723
        time_format = "%d-%b-%Y %H:%M:%S"
724
    if timestring == '':
725
        timestring = '00:00:00'
726
    time_array = timestring.split(':')
727
    if len(time_array) < 3:
728
        timestring = timestring + ':00'
729
    time_string = datestring + ' ' + timestring[0:8]
730
    mytime = time.strptime(time_string, time_format)
731
    return datetime.datetime(*mytime[:6])
732
 
733
 
734
def getTrimedString(text):
735
    if text is None or text == '':
736
        return ''
737
    else:
738
        text = text.strip().lower()
739
        text_list = list(text)
740
        new_text = ''
741
        for letter in text_list:
742
            if letter.isalnum():
743
                new_text = new_text + str(letter)
744
        return new_text
745
 
746
def main():
747
    parser = optparse.OptionParser()
748
    parser.add_option("-p", "--pickup", dest="pickup_report",
749
                   action="store_true",
750
                   help="Run the pickup reconciliation")
751
    parser.add_option("-d", "--delivery", dest="delivery_report",
752
                   action="store_true",
753
                   help="Run the delivery reconciliation")
754
    parser.add_option("-r", "--reports", dest="gen_reports",
755
                   action="store_true",
756
                   help="Generate logistic reconciliation reports")
757
    parser.add_option("-a", "--all", dest="all_reports",
758
                   action="store_true",
759
                   help="Run all reconciliations")
760
    parser.add_option("-P", "--provider", dest="provider",
6966 rajveer 761
                   default="RedExpress", type="string",
6952 rajveer 762
                   help="The PROVIDER this report is for",
763
                   metavar="PROVIDER")
764
    parser.set_defaults(pickup_report=False, delivery_report=False, gen_reports=False, all_reports=False)
765
    (options, args) = parser.parse_args()
766
    if len(args) != 0:
767
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
768
 
769
    if options.all_reports:
770
        options.pickup_report = True
771
        options.delivery_report = True
772
 
773
    provider = get_provider_by_name(options.provider)
774
 
775
    if options.pickup_report:
776
        process_pickup_records(provider)
777
        #process_dao_pickup_orders(provider)
778
        #process_return_pickup_orders(provider)
779
    if options.delivery_report:
780
        process_local_connection_orders(provider)
781
        #process_reached_destination_city_orders(provider)
782
        #process_first_delivery_attempt_orders(provider)
783
        process_delivery_report(provider)
6966 rajveer 784
        #create_crm_tickets_for_delivey_attempted_orders(provider)
785
        #auto_close_crm_tickets_created()
6952 rajveer 786
    if options.gen_reports:
787
        generate_reports(provider)
788
 
789
if __name__ == '__main__':
790
    main()