Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
23236 amit.gupta 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 aramex api to know whether they are picked up by aramex
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 aramex api to know whether they are picked up by aramex
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 aramex api to know whether they are picked up by aramex
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 aramex 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.aramex.com/track_xml.asp?ShipperRef={variable1}&OrgCntry=In&FromDate={variable2}&ToDate={variable3} is hard coded
24
to track DOA orders and for other orders ConfigClient is called to get aramex_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 shop2020.config.client.ConfigClient import ConfigClient
33
from shop2020.model.v1.order.script.LogisticUtils import enqueueMailForFDA, \
34
    create_crm_tickets_for_delivey_attempted_orders
35
from shop2020.thriftpy.config.ttypes import ConfigException
36
from shop2020.thriftpy.crm.ttypes import *
37
from shop2020.thriftpy.model.v1.order.ttypes import TransactionServiceException, \
38
    OrderStatus
39
from shop2020.utils.EmailAttachmentSender import get_attachment_part, mail
40
from shop2020.utils.Utils import to_py_date
23250 amit.gupta 41
from xml.etree.ElementTree import parse, fromstring
23236 amit.gupta 42
import csv
43
import datetime
44
import json
45
import optparse
46
import re
47
import sys
48
import time
49
import traceback
50
import urllib
51
import urllib2
52
 
53
if __name__ == '__main__' and __package__ is None:
54
    import os
55
    sys.path.insert(0, os.getcwd())
56
 
23250 amit.gupta 57
REASON_CODES_PICKUP_REGISTERED = ['013']
58
REASON_CODES_SHIPMENT_ARRIVED = ['127', '0002'] 
59
REASON_CODES_UNDELIVERED_MAP = { '005':'Reached Destination City', '006':'Out for Delivery', '303': 'Shipment In Transit'}
60
REASON_CODES_NDR = ['200', '201', '202', '206', '207', '208', '209', '210', '212', '213', '214', '215', '216', 
61
                    '217', '221', '222', '223', '224', '225', '226', '227', '228','229', '231', '232', '233',
62
                    '331','331','332','333','331','666','888','218', '219', '220', '1225'
63
                    ]
64
REASON_CODES_DELIVERED=['999', '204']
65
REASON_CODES_RTO = ['777', '77', '80', '82', '83']
23236 amit.gupta 66
 
67
finalUpdateUrl = ""
68
live = "false"
69
try:
70
    config_client = ConfigClient()
71
    live = config_client.get_property("live")
72
except:
73
    live = "true"
74
 
75
if live=="true":
76
    UPDATE_URL = "http://plapi.ecomexpress.in/track_me/api/mawbd/?order=&"
23250 amit.gupta 77
    ECOM_API_USERNAME = "newspice671445"
78
    ECOM_API_PASSWORD = "npcs67unsd44debm"
23236 amit.gupta 79
else:
80
    UPDATE_URL = "http://staging.ecomexpress.in/track_me/api/mawbd/?order=&"
81
    ECOM_API_USERNAME = "ecomexpress"
82
    ECOM_API_PASSWORD = "Ke$3c@4oT5m6h%23$"
83
 
23250 amit.gupta 84
finalUpdateUrl = UPDATE_URL + "username=" + ECOM_API_USERNAME + "&password="+ECOM_API_PASSWORD
85
 
23236 amit.gupta 86
 
87
 
88
defaultUndeliveredAsssigneeId = 65
89
dtrUndeliveredAsssigneeId = 33
90
from_user = 'cnc.center@shop2020.in'
91
from_pwd = '5h0p2o2o'
92
to = ["ritesh.chauhan@shop2020.in", "deena.nath@profitmandi.com"]
93
 
94
def process_dao_pickup_orders(provider):
95
    try:
96
        doas_tobe_picked_up = fetch_data(provider.id, [OrderStatus.DOA_PICKUP_CONFIRMED])
97
        doa_pickup_details = read_dao_return_pickup_orders(doas_tobe_picked_up)
98
        if doa_pickup_details:
99
            update_picked_doas(provider.id, doa_pickup_details)
100
    except:
101
        print "Some issue while processing the orders in DOA_PICKUP_CONFIRMED status"
102
        traceback.print_exc()
103
 
104
def process_return_pickup_orders(provider):
105
    try:
106
        returns_tobe_picked_up = fetch_data(provider.id, [OrderStatus.RET_PICKUP_CONFIRMED])
107
        returns_pickup_details = read_dao_return_pickup_orders(returns_tobe_picked_up)
108
        if returns_pickup_details:
109
            update_picked_returns(provider.id, returns_pickup_details)
110
    except:
111
        print "Some issue while processing the orders in RET_PICKUP_CONFIRMED status"
112
        traceback.print_exc()
113
 
114
def process_pickup_records(provider):
115
    try:
116
        orders_tobe_picked_up = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH])
117
        pickup_details = read_pickup_orders(orders_tobe_picked_up)
23250 amit.gupta 118
        print "pickup_details", pickup_details
23236 amit.gupta 119
        if pickup_details:
120
            update_picked_orders(provider.id, pickup_details)
121
    except:
122
        print "Some issue while processing the orders in SHIPPED_FROM_WH status"
123
        traceback.print_exc()
124
 
125
def process_local_connection_orders(provider):
126
    try:
127
        orders_tobe_local_connected = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST])
128
        local_connected_orders = read_local_connection_orders(orders_tobe_local_connected)
129
        if local_connected_orders:
130
            update_local_connected_orders(provider.id, local_connected_orders)
131
    except:
132
        print "Some issue while processing the orders for local connection status"
133
        traceback.print_exc()
134
 
135
def process_reached_destination_city_orders(provider):
136
    try:
137
        orders_tobe_reached_destination_city = fetch_data(provider.id, [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY])
138
        destination_city_reached_orders = read_reached_destination_orders(orders_tobe_reached_destination_city)
139
        if destination_city_reached_orders:
140
            update_destination_city_reached_orders(provider.id, destination_city_reached_orders)
141
    except:
142
        print "Some issue while processing the orders for Reached Destination City status"
143
        traceback.print_exc()
144
 
145
def process_first_delivery_attempt_orders(provider):
146
    try:
147
        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])
148
        first_atdl_orders = read_first_delivery_attempt_orders(orders_tobe_first_delivery_attempted)
149
        if first_atdl_orders:
150
            update_first_atdl_orders(provider.id, first_atdl_orders)
151
    except:
152
        print "Some issue while processing the orders for First delivery attempt status"
153
        traceback.print_exc()
154
 
155
def process_delivery_report(provider):
156
    try:
157
        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])
158
        delivered_orders, returned_orders, undelivered_orders = read_delivery_orders(orders_tobe_delivered)
23250 amit.gupta 159
        print "delivey_orders", delivered_orders
23236 amit.gupta 160
        if delivered_orders:
161
            update_delivered_orders(provider.id, delivered_orders)
23250 amit.gupta 162
        print "returned_orders", returned_orders
23236 amit.gupta 163
        if returned_orders:
164
            update_returned_orders(provider.id, returned_orders)
23250 amit.gupta 165
        print "undelivered_orders", undelivered_orders
23236 amit.gupta 166
        if undelivered_orders:
167
            update_reason_of_undelivered_orders(provider.id, undelivered_orders)
168
    except:
169
        print "Some issue while processing the orders for delivery status"
170
        traceback.print_exc()
171
 
172
def generate_reports(provider):
173
    #get_doas_not_picked_up(provider)
174
    #get_returns_not_picked_up(provider)
175
    get_orders_not_picked_up(provider)
176
    #get_orders_pending_local_connection(provider)
177
    #get_returned_orders(provider)
178
    get_orders_not_delivered(provider)
179
 
180
def get_doas_not_picked_up(provider):
181
    txnClient = TransactionClient().get_client()
182
    try:
183
        doas_not_picked_up = txnClient.getDoasNotPickedUp(provider.id)
184
    except TransactionServiceException as tex:
185
        print tex.message
186
 
187
    try:
188
        if doas_not_picked_up:
189
            print "DOAs not Picked up:"
190
            print doas_not_picked_up
191
            mismatch_file = "/tmp/Aramex_DoaPickupMismatch.csv"
192
            print "Some of our DOA orders were not picked up. Printing report to:" + mismatch_file
193
            print_dao_return_pickup_mismatch_report(mismatch_file, doas_not_picked_up)
194
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
195
            mail(from_user, from_pwd, to,\
196
                 "DOA Pickup Mismatch for " + provider.name,\
197
                 "This is a system generated email.Please don't reply to it.",\
198
                 pickup_mismatch_part)
199
    except Exception:
200
        print "Some issue sending the DOA mismatch report"
201
        traceback.print_exc()
202
 
203
def get_returns_not_picked_up(provider):
204
    txnClient = TransactionClient().get_client()
205
    try:
206
        returns_not_picked_up = txnClient.getReturnOrdersNotPickedUp(provider.id)
207
    except TransactionServiceException as tex:
208
        print tex.message
209
 
210
    try:
211
        if returns_not_picked_up:
212
            print "Return Orders not Picked up:"
213
            print returns_not_picked_up
214
            mismatch_file = "/tmp/Aramex_ReturnsPickupMismatch.csv"
215
            print "Some of our Return orders were not picked up. Printing report to:" + mismatch_file
216
            print_dao_return_pickup_mismatch_report(mismatch_file, returns_not_picked_up)
217
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
218
            mail(from_user, from_pwd, to,\
219
                 "Return orders Pickup Mismatch for " + provider.name,\
220
                 "This is a system generated email.Please don't reply to it.",\
221
                 pickup_mismatch_part)
222
    except Exception:
223
        print "Some issue sending the Return orders mismatch report"
224
        traceback.print_exc()
225
 
226
def get_orders_not_picked_up(provider):
227
    txnClient = TransactionClient().get_client()
228
    try:
229
        orders_not_picked_up = txnClient.getOrdersNotPickedUp(provider.id)
230
    except TransactionServiceException as tex:
231
        print tex.message
232
 
233
    try:
234
        if orders_not_picked_up:
235
            print "Orders not Picked up:"
236
            print orders_not_picked_up
237
            mismatch_file = "/tmp/Aramex_PickupMismatch.csv"
238
            print "Some of our orders were not picked up. Printing report to:" + mismatch_file
239
            print_pickup_mismatch_report(mismatch_file, orders_not_picked_up)
240
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
241
            mail(from_user, from_pwd, to,\
242
                 "Order Pickup Mismatch for " + provider.name,\
243
                 "This is a system generated email.Please don't reply to it.",\
244
                 pickup_mismatch_part)
245
    except Exception:
246
        print "Some issue sending the pickup mismatch report"
247
        traceback.print_exc()
248
 
249
def get_orders_pending_local_connection(provider):
250
    txnClient = TransactionClient().get_client()
251
    try:
252
        orders_pending_local_connection = txnClient.getOrdersNotLocalConnected(provider.id)
253
    except TransactionServiceException as tex:
254
        print tex.message
255
 
256
    try:
257
        if orders_pending_local_connection:
258
            print "Local Connection Pending Orders:"
259
            print orders_pending_local_connection
260
            mismatch_file = "/tmp/Aramex_LocalConnectionPendingOrders.csv"
261
            print "Some of our Orders were not Shipped to Destination yet. Printing report to:" + mismatch_file
262
            print_undelivered_orders_report(mismatch_file, orders_pending_local_connection)
263
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
264
            mail(from_user, from_pwd, to,\
265
                 "Orders that are not Shipped to Destination yet for " + provider.name,\
266
                 "This is a system generated email.Please don't reply to it.",\
267
                 pickup_mismatch_part)
268
    except Exception:
269
        print "Some issue updating and sending the Local Connection orders report"
270
        traceback.print_exc()
271
 
272
def get_returned_orders(provider):
273
    txnClient = TransactionClient().get_client()
274
    try:
275
        returned_orders = txnClient.getRTOrders(provider.id)
276
    except TransactionServiceException as tex:
277
        print tex.message
278
 
279
    try:
280
        if returned_orders:
281
            print "Returned Orders:"
282
            print returned_orders
283
            returned_orders_file = "/tmp/Aramex_ReturnedOrders.csv"
284
            print "Some of our Orders were returned by logistics provider. Printing report to:" + returned_orders_file
285
            print_rto_orders_report(returned_orders_file, returned_orders)
286
            returned_orders_report = [get_attachment_part(returned_orders_file)]
287
            mail(from_user, from_pwd, to,\
288
                 "Returned Orders Report for " + provider.name,\
289
                 "This is a system generated email.Please don't reply to it.",\
290
                 returned_orders_report)
291
    except:
292
        print "Some issue sending the returned orders report"
293
        traceback.print_exc()
294
 
295
def get_orders_not_delivered(provider):
296
    txnClient = TransactionClient().get_client()
297
    try:
298
        orders_not_delivered = txnClient.getNonDeliveredOrdersbyCourier(provider.id)
299
    except TransactionServiceException as tex:
300
        print tex.message
301
 
302
    try:
303
        if orders_not_delivered:
304
            print "Undelivered Orders:"
305
            print orders_not_delivered
306
            mismatch_file = "/tmp/Aramex_UndeliveredOrders.csv"
307
            print "Some of our Orders were not delivered. Printing report to:" + mismatch_file
308
            print_undelivered_orders_report(mismatch_file, orders_not_delivered)
309
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
310
            mail(from_user, from_pwd, to,\
311
                 "Orders that are undelivered but picked up or shipped four days ago for " + provider.name,\
312
                 "This is a system generated email.Please don't reply to it.",\
313
                 pickup_mismatch_part)
314
    except Exception:
315
        print "Some issue updating and sending the undelivered orders report"
316
        traceback.print_exc()
317
 
318
def get_provider_by_name(provider_name):
319
    logistics_client = LogisticsClient().get_client()
320
    provider = None
321
    providers = logistics_client.getAllProviders()
322
    for p in providers:
323
        if p.name == provider_name:
324
            provider=p
325
            break
326
    if provider == None:
327
        sys.exit("Can't continue execution: No such provider")
328
    return provider
329
 
330
def fetch_data(provider_id, order_status_list):
331
    txnClient = TransactionClient().get_client()
332
    try:
333
        doas_tobe_picked_up = txnClient.getOrdersForProviderForStatus(provider_id, order_status_list)
334
        return doas_tobe_picked_up
335
    except TransactionServiceException as tex:
336
        print tex.message
337
 
338
def read_dao_return_pickup_orders(orders_tobe_picked_up):
339
    #uri=http://www.aramex.com/track_xml.asp?ShipperRef=61582&OrgCntry=In&FromDate=2-6-2012&ToDate=2-6-2012
340
    picked_up_orders = {}
341
    for order in orders_tobe_picked_up:
342
        try:
343
            uri = 'http://www.aramex.com/track_xml.asp?ShipperRef=' + str(order.pickupRequestNo) + '&OrgCntry=In&FromDate=' + to_py_date(order.doa_auth_timestamp).strftime("%m-%d-%Y") +'&ToDate=' + datetime.date.today().strftime("%m-%d-%Y")
344
            root = parse(urllib2.urlopen(uri)).getroot()
345
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
346
            for element in reversed(nodes):
347
                delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
348
                picked_up_orders[order.pickupRequestNo] = str(delivery_date)
349
                break
350
        except:
351
            pass
352
 
353
    print "Picked up Orders:"
354
    print picked_up_orders
355
    return picked_up_orders
356
 
357
def get_awb_status(awbs):
358
    awbs = list(set(awbs))
359
    awbStatuses = {}
360
    if not awbs:
361
        return awbStatuses
362
    else:
363
        doneAwbs = 0
364
        batchSize = 15
365
        while len(awbs) > doneAwbs: 
366
            currentBatch = awbs[doneAwbs:doneAwbs+batchSize]
367
            print "currentBatch", currentBatch
368
            url = finalUpdateUrl + "&awb=" + ",".join(currentBatch)
369
            print url 
370
            response = urllib2.urlopen(url)
23250 amit.gupta 371
            responseString = response.read()
372
            print responseString 
373
            root = fromstring(responseString)
374
            print root.tag
375
            awbs = []
376
            for awbEle in root:
377
                awbNumber = awbEle.findall("field/[@name='awb_number']")[0].text
378
                reasonCode = awbEle.findall("field/[@name='reason_code_number']")[0].text
379
                deliveryDate = awbEle.findall("field/[@name='delivery_date']")[0].text
380
                lastUpdateDate = awbEle.findall("field/[@name='last_update_date']")[0].text
381
                xmlScans = awbEle.findall("field/object/[@model='scan_stages']")
382
                awbStatuses[awbNumber] = {'awbNumber': awbNumber, 'reasonCode': reasonCode, 'deliveryDate':deliveryDate, 'lastUpdateDate':lastUpdateDate, 'scans': xmlScans}
23236 amit.gupta 383
 
23250 amit.gupta 384
        doneAwbs += batchSize
385
        print awbStatuses
23236 amit.gupta 386
 
387
        return awbStatuses       
388
 
389
 
390
 
391
class __AWBStatusObj:
23250 amit.gupta 392
    def __init__(self, awb, statusCode, statusDescription, statusDate):
23236 amit.gupta 393
        self.awb = awb
23250 amit.gupta 394
        self.statusCode = statusCode
395
        self.statusDescription = statusDescription
23236 amit.gupta 396
        self.statusDate = statusDate
23250 amit.gupta 397
 
398
def __get_scan_by_code(xmlScans, codes):
399
    awbStatusObj = None
400
    for xmlScan in xmlScans:
401
        reasonCodeNumber = xmlScan.findall("[@name='reason_code_number']")[0].text
402
        if reasonCodeNumber in codes:
403
            statusDescription = xmlScan.findall("[@name='status']")[0].text
404
            statusDate = get_py_datetime(xmlScan.findall("[@name='updated_on']")[0].text)
405
            awbStatusObj = __AWBStatusObj(None, reasonCodeNumber, statusDescription, statusDate)
23236 amit.gupta 406
 
23250 amit.gupta 407
    return awbStatusObj
23236 amit.gupta 408
 
409
def read_pickup_orders(orders_tobe_picked_up):
410
    picked_up_orders = {}
411
    awbs = [order.airwaybill_no for order in orders_tobe_picked_up]
412
 
413
    for awb, awbDetails in get_awb_status(awbs).iteritems():
23250 amit.gupta 414
 
415
        xmlScans = awbDetails['xmlScans']
416
        awbStatusObj = __get_scan_by_code(xmlScans, ['0011'])
417
 
418
        if awbStatusObj is None:
419
            continue
420
 
421
        bookedTime = awbStatusObj.statusDate
23236 amit.gupta 422
        picked_up_orders[awb] = str(bookedTime)
23250 amit.gupta 423
 
23236 amit.gupta 424
    print "Picked up Orders:"
425
    print picked_up_orders
426
    return picked_up_orders
427
 
428
def read_local_connection_orders(orders_tobe_local_connected):
429
 
430
    local_connected_orders = {}
431
    awbs = [order.airwaybill_no for order in orders_tobe_local_connected]
432
 
433
    for awb, awbDetails in get_awb_status(awbs).iteritems():
434
        #status = awbDetails['Status']
435
        #statusDate = get_pawbDetails['StatusDateTime']
436
        tracking = awbDetails['Tracking']
437
        bookedTime = get_py_datetime(tracking[-1]['StatusDateTime'])
438
        local_connected_orders[awb] = str(bookedTime)
439
 
440
    print "Local Connected Orders"
441
    print local_connected_orders
442
 
443
    return local_connected_orders
444
 
445
def read_reached_destination_orders(orders_tobe_reached_destination_city):
446
    destination_city_reached_orders = {}
447
 
448
    print "Destination City Reached Orders"
449
    print destination_city_reached_orders
450
 
451
    return destination_city_reached_orders
452
 
453
def read_first_delivery_attempt_orders(orders_tobe_first_delivery_attempted):
454
    first_atdl_orders = {}
455
    awbs = [order.airwaybill_no for order in orders_tobe_first_delivery_attempted]
456
    for awb, awbDetails in get_awb_status(awbs).iteritems():
457
        status = awbDetails['Status']
458
        print "STATUS -----", status
459
        if status.startswith("Undelivered"):
460
            statusTime = get_py_datetime(awbDetails['StatusDateTime'])
461
            first_atdl_orders[awb] = str(statusTime) + "|" + awbDetails['Status']
462
    print "FIRST DELIVERY ATTEMPT MADE Orders", first_atdl_orders
463
    print first_atdl_orders
464
 
465
    return first_atdl_orders
466
 
467
def read_delivery_orders(orders_tobe_delivered):
468
    delivered_orders = {}
469
    returned_orders = {}
470
    undelivered_orders = {}
471
 
472
    awbs = [order.airwaybill_no for order in orders_tobe_delivered]
473
 
474
    for awb, awbDetails in get_awb_status(awbs).iteritems():
23250 amit.gupta 475
        xmlScans = awbDetails['xmlScans']
23236 amit.gupta 476
 
23250 amit.gupta 477
        deliveredAwbStatusObj = __get_scan_by_code(xmlScans, REASON_CODES_DELIVERED)
478
        if deliveredAwbStatusObj is not None:
479
            bookedTime = get_py_date(awbDetails['deliveryDate'])
480
            delivered_orders[awb] = str(bookedTime) + "|" +  "Not Available"
481
            continue
23236 amit.gupta 482
 
23250 amit.gupta 483
        rtoAwbStatusObj = __get_scan_by_code(xmlScans, REASON_CODES_RTO)
484
        if rtoAwbStatusObj is not None:
485
            bookedTime = rtoAwbStatusObj.statusDate
486
            delivered_orders[awb] = str(bookedTime) + "|" +  "Not Available"
487
            continue
23236 amit.gupta 488
 
23250 amit.gupta 489
 
490
        undeliveredAwbStatusObj = __get_scan_by_code(xmlScans, REASON_CODES_UNDELIVERED_MAP.keys())
491
        if undeliveredAwbStatusObj is not None:
492
            delivered_orders[awb] = REASON_CODES_UNDELIVERED_MAP.get(undeliveredAwbStatusObj.reasonCodeNumber)
493
 
494
 
495
 
496
        #undelivered_orders[awb] = awbDetails.statusDescription
497
 
23236 amit.gupta 498
    print "Delivered Orders:"
499
    print delivered_orders
500
 
501
    print "Returned Orders:"
502
    print returned_orders
503
 
504
    print "Undelivered Orders"
505
    print undelivered_orders
506
 
507
    return delivered_orders, returned_orders, undelivered_orders
508
 
509
def update_picked_orders(provider_id, pickup_details):
510
    txnClient = TransactionClient().get_client()
511
    try:
512
        txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
513
    except TransactionServiceException as tex:
514
        print tex.message
515
 
516
def update_picked_doas(provider_id, doa_pickup_details):
517
    txnClient = TransactionClient().get_client()
518
    try:
519
        txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
520
    except TransactionServiceException as tex:
521
        print tex.message
522
 
523
def update_picked_returns(provider_id, returns_pickup_details):
524
    txnClient = TransactionClient().get_client()
525
    try:
526
        txnClient.markReturnOrdersAsPickedUp(provider_id, returns_pickup_details)
527
    except TransactionServiceException as tex:
528
        print tex.message
529
 
530
def update_delivered_orders(provider_id, delivered_orders):
531
    txnClient = TransactionClient().get_client()
532
    try:
533
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
534
    except TransactionServiceException as tex:
535
        print tex.message
536
 
537
def update_returned_orders(provider_id, returned_orders):
538
    txnClient = TransactionClient().get_client()
539
    try:
540
        txnClient.markAsRTOrders(provider_id, returned_orders)
541
    except TransactionServiceException as tex:
542
        print tex.message
543
 
544
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
545
    txnClient = TransactionClient().get_client()
546
    try:
547
        txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
548
    except TransactionServiceException as tex:
549
        print tex.message
550
 
551
def update_local_connected_orders(provider_id, local_connected_orders):
552
    txnClient = TransactionClient().get_client()
553
    try:
554
        txnClient.markOrdersAsLocalConnected(provider_id, local_connected_orders)
555
    except TransactionServiceException as tex:
556
        print tex.message
557
 
558
def update_destination_city_reached_orders(provider_id, destination_city_reached_orders):
559
    txnClient = TransactionClient().get_client()
560
    try:
561
        txnClient.markOrdersAsDestinationCityReached(provider_id, destination_city_reached_orders)
562
    except TransactionServiceException as tex:
563
        print tex.message
564
 
565
def update_first_atdl_orders(provider_id, first_atdl_orders):
566
    txnClient = TransactionClient().get_client()
567
    try:
568
        txnClient.markOrdersAsFirstDeliveryAttempted(provider_id, first_atdl_orders)
569
    except TransactionServiceException as tex:
570
        print tex.message
571
 
572
def print_pickup_mismatch_report(filename, orders):
573
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
574
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
575
    for order in orders:
576
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
577
 
578
def print_dao_return_pickup_mismatch_report(filename, orders):
579
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
580
    writer.writerow(['Order Id', 'Pickup Request No', 'Authorization timestamp'])
581
    for order in orders:
582
        writer.writerow([order.id, order.pickupRequestNo, to_py_date(order.doa_auth_timestamp)])
583
 
584
def print_rto_orders_report(filename, orders):
585
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
586
    writer.writerow(['Order Id', 'AWB No', 'Return date', 'Reason'])
587
    for order in orders:
588
        statusDescription = ''
589
        if order.statusDescription is not None:
590
            statusDescription = order.statusDescription.replace(","," ")
591
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.delivery_timestamp), statusDescription])
592
 
593
def print_undelivered_orders_report(filename, orders):
594
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
595
    writer.writerow(['Order Id', 'AWB No', 'Status', 'Status Description', 'Shipping timestamp', 'Pickup timestamp', 'Promised delivery date', 'Expected delivery date'])
596
    for order in orders:
597
        statusDescription = ''
598
        if order.statusDescription is not None:
599
            statusDescription = order.statusDescription.replace(","," ")
600
        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)])
601
 
602
def auto_close_crm_tickets_created():
603
    try:
604
        ticket_created_orders = []
605
        tickets_map = {}
606
        crmServiceClient = CRMClient().get_client()
607
        searchFilter = SearchFilter()
608
        searchFilter.ticketCategory = TicketCategory.UNDELIVERED
609
        searchFilter.ticketAssigneeIds = [defaultUndeliveredAsssigneeId]
610
        searchFilter.ticketPriority = TicketPriority.HIGH
611
        searchFilter.ticketStatuses = [TicketStatus.OPEN]
612
        tickets = crmServiceClient.getTickets(searchFilter)
613
        print tickets
614
        for old_ticket in tickets:
615
            ticket_created_orders.append(old_ticket.orderId)
616
            tickets_map[old_ticket.orderId] = old_ticket
617
        print ticket_created_orders
618
        txnClient = TransactionClient().get_client()
619
        orders = txnClient.getOrderList(ticket_created_orders)
620
        for order in orders:
621
            if order.status not in [OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.RTO_IN_TRANSIT]:
622
                old_ticket = tickets_map.get(order.id)
623
                old_ticket.status = TicketStatus.CLOSED
624
                activity = Activity()
625
                activity.creatorId = 1
626
                activity.ticketAssigneeId = old_ticket.assigneeId
627
                activity.type = ActivityType.OTHER
628
                activity.description = "Ticket Closed bcoz order status changed to:" + order.statusDescription
629
                activity.ticketCategory = old_ticket.category
630
                activity.ticketDescription = old_ticket.description
631
                activity.ticketPriority = old_ticket.priority
632
                activity.ticketStatus = old_ticket.status
633
 
634
                if old_ticket.customerId is None or old_ticket.customerId == -1:
635
                    activity.customerEmailId = old_ticket.customerEmailId
636
                    activity.customerMobileNumber = old_ticket.customerMobileNumber
637
                    activity.customerName = old_ticket.customerName
638
                else:
639
                    activity.customerId = old_ticket.customerId
640
 
641
                crmServiceClient.updateTicket(old_ticket, activity)
642
    except:
643
        print "Some issue while closing crm tickets for orders in DELIVERY_SUCCESS status"
644
        traceback.print_exc()
645
 
646
def get_py_datetime(time_string):
647
    # This should be a command line argument.
648
    # Refer http://docs.python.org/library/time.html#time.strftime to
649
    # get a complete list of format specifiers available for date time.
23250 amit.gupta 650
    time_format = "%d %b, %Y, %H:%M"
23236 amit.gupta 651
    if time_string == '':
652
        return None
653
    return datetime.datetime.strptime(time_string, time_format)
654
 
23250 amit.gupta 655
def get_py_date(time_string):
656
    # This should be a command line argument.
657
    # Refer http://docs.python.org/library/time.html#time.strftime to
658
    # get a complete list of format specifiers available for date time.
659
    time_format = "%d-%b-%Y"
660
    if time_string == '':
661
        return None
662
    return datetime.datetime.strptime(time_string, time_format)
663
 
23236 amit.gupta 664
def getOriginCityBranchID(originCity):
665
    branchId_OriginCitymap = {'DEL':'7933'}
666
    if originCity is None or originCity == '':
667
        return ''
668
    else:
669
        return branchId_OriginCitymap.get(originCity)
670
 
671
def sanitizeUnicode(unicodeText):
672
    #remove unicode characters
673
    unicodeText = re.sub(r'[^\x00-\x7F]+','', unicodeText)
674
    #remove whitespaces and strip
675
    unicodeText = re.sub(r'[^\S]+',' ', unicodeText)
676
    return unicodeText.strip().encode('utf-8', 'ignore')
677
 
678
def main():
679
    parser = optparse.OptionParser()
680
    parser.add_option("-p", "--pickup", dest="pickup_report",
681
                   action="store_true",
682
                   help="Run the pickup reconciliation")
683
    parser.add_option("-d", "--delivery", dest="delivery_report",
684
                   action="store_true",
685
                   help="Run the delivery reconciliation")
686
    parser.add_option("-r", "--reports", dest="gen_reports",
687
                   action="store_true",
688
                   help="Generate logistic reconciliation reports")
689
    parser.add_option("-a", "--all", dest="all_reports",
690
                   action="store_true",
691
                   help="Run all reconciliations")
692
    parser.add_option("-P", "--provider", dest="provider",
693
                   default="RQuick-Express", type="string",
694
                   help="The PROVIDER this report is for",
695
                   metavar="PROVIDER")
696
    parser.set_defaults(pickup_report=False, delivery_report=False, gen_reports=False, all_reports=False)
697
    (options, args) = parser.parse_args()
698
    if len(args) != 0:
699
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
700
 
701
    if options.all_reports:
702
        options.pickup_report = True
703
        options.delivery_report = True
704
 
705
    provider = get_provider_by_name(options.provider)
706
 
707
    if options.pickup_report:
708
        process_pickup_records(provider)
709
        #process_dao_pickup_orders(provider)
710
        #process_return_pickup_orders(provider)
711
    if options.delivery_report:
712
        #process_local_connection_orders(provider)
713
        #process_reached_destination_city_orders(provider)
23250 amit.gupta 714
        #process_first_delivery_attempt_orders(provider)
23236 amit.gupta 715
        process_delivery_report(provider)
716
        #create_crm_tickets_for_delivey_attempted_orders(provider)
717
        #auto_close_crm_tickets_created()
718
    if options.gen_reports:
719
        pass
720
        #generate_reports(provider)
721
 
722
if __name__ == '__main__':
23250 amit.gupta 723
    main()
724
    #awbs =["897986473","225839621", "225839622", "225839623", "22583962"]
725
    #for awb, awbDetails in get_awb_status(awbs).iteritems():
726
        #print awb, awbDetails