Subversion Repositories SmartDukaan

Rev

Rev 23335 | 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'
23839 amit.gupta 92
to = ["ritesh.chauhan@shop2020.in", "deena.nath@smartdukaan.com"]
23236 amit.gupta 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()
23251 amit.gupta 322
    print "Providers", providers
23236 amit.gupta 323
    for p in providers:
324
        if p.name == provider_name:
325
            provider=p
326
            break
327
    if provider == None:
328
        sys.exit("Can't continue execution: No such provider")
329
    return provider
330
 
331
def fetch_data(provider_id, order_status_list):
332
    txnClient = TransactionClient().get_client()
333
    try:
334
        doas_tobe_picked_up = txnClient.getOrdersForProviderForStatus(provider_id, order_status_list)
335
        return doas_tobe_picked_up
336
    except TransactionServiceException as tex:
337
        print tex.message
338
 
339
def read_dao_return_pickup_orders(orders_tobe_picked_up):
340
    #uri=http://www.aramex.com/track_xml.asp?ShipperRef=61582&OrgCntry=In&FromDate=2-6-2012&ToDate=2-6-2012
341
    picked_up_orders = {}
342
    for order in orders_tobe_picked_up:
343
        try:
344
            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")
345
            root = parse(urllib2.urlopen(uri)).getroot()
346
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
347
            for element in reversed(nodes):
348
                delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
349
                picked_up_orders[order.pickupRequestNo] = str(delivery_date)
350
                break
351
        except:
352
            pass
353
 
354
    print "Picked up Orders:"
355
    print picked_up_orders
356
    return picked_up_orders
357
 
358
def get_awb_status(awbs):
359
    awbs = list(set(awbs))
360
    awbStatuses = {}
361
    if not awbs:
362
        return awbStatuses
363
    else:
364
        doneAwbs = 0
365
        batchSize = 15
366
        while len(awbs) > doneAwbs: 
367
            currentBatch = awbs[doneAwbs:doneAwbs+batchSize]
368
            print "currentBatch", currentBatch
369
            url = finalUpdateUrl + "&awb=" + ",".join(currentBatch)
370
            print url 
371
            response = urllib2.urlopen(url)
23250 amit.gupta 372
            responseString = response.read()
373
            print responseString 
374
            root = fromstring(responseString)
375
            print root.tag
376
            awbs = []
377
            for awbEle in root:
23251 amit.gupta 378
 
23266 amit.gupta 379
                awbNumber = __findElementByAttr(awbEle, 'name', 'awb_number').text  
380
                reasonCode = __findElementByAttr(awbEle, 'name', 'reason_code_number').text
23265 amit.gupta 381
                deliveryDate =  __findElementByAttr(awbEle, 'name', 'delivery_date').text
23266 amit.gupta 382
                lastUpdateDate = __findElementByAttr(awbEle, 'name', 'last_update_date').text
23256 amit.gupta 383
                xmlScans = __findElementByAttr(awbEle, 'name', 'scans')
23253 amit.gupta 384
                awbStatuses[awbNumber] = {'awbNumber': awbNumber, 'reasonCode': reasonCode, 'deliveryDate':deliveryDate, 'lastUpdateDate':lastUpdateDate, 'xmlScans': xmlScans}
23236 amit.gupta 385
 
23250 amit.gupta 386
        doneAwbs += batchSize
387
        print awbStatuses
23236 amit.gupta 388
 
389
        return awbStatuses       
390
 
391
 
392
 
393
class __AWBStatusObj:
23250 amit.gupta 394
    def __init__(self, awb, statusCode, statusDescription, statusDate):
23236 amit.gupta 395
        self.awb = awb
23250 amit.gupta 396
        self.statusCode = statusCode
397
        self.statusDescription = statusDescription
23236 amit.gupta 398
        self.statusDate = statusDate
23250 amit.gupta 399
 
400
def __get_scan_by_code(xmlScans, codes):
23258 amit.gupta 401
    print "xmlScansText", xmlScans.text
23259 amit.gupta 402
    print "xmlScansTag", xmlScans.text
23250 amit.gupta 403
    awbStatusObj = None
404
    for xmlScan in xmlScans:
23257 amit.gupta 405
        print "xmlScanText", xmlScan.text
23259 amit.gupta 406
        print "xmlScanTag", xmlScan.tag
23266 amit.gupta 407
        reasonCodeNumber = __findElementByAttr(xmlScan, 'name', 'reason_code_number').text
23250 amit.gupta 408
        if reasonCodeNumber in codes:
23266 amit.gupta 409
            statusDescription = __findElementByAttr(xmlScan, 'name', 'status').text
410
            statusDate = get_py_datetime(__findElementByAttr(xmlScan, 'name', 'updated_on').text)
23250 amit.gupta 411
            awbStatusObj = __AWBStatusObj(None, reasonCodeNumber, statusDescription, statusDate)
23251 amit.gupta 412
            print awbStatusObj
413
    return awbStatusObj
414
 
415
def __findElementByAttr(xmlElement, name, value=None):
23252 amit.gupta 416
        print "Name", name
417
        print "Value", value
23260 amit.gupta 418
        i = 1
23251 amit.gupta 419
        for innerElement in xmlElement:
23260 amit.gupta 420
            print "inner index ", i
23261 amit.gupta 421
            print "inner attrib ", innerElement.attrib
23260 amit.gupta 422
            i += 1
23251 amit.gupta 423
            if innerElement.attrib.has_key(name):
424
                if value and innerElement.attrib[name]==value:
425
                    return innerElement
23262 amit.gupta 426
                elif value == None:
23252 amit.gupta 427
                    return innerElement
23236 amit.gupta 428
 
23251 amit.gupta 429
        return None
430
 
23236 amit.gupta 431
 
432
def read_pickup_orders(orders_tobe_picked_up):
433
    picked_up_orders = {}
434
    awbs = [order.airwaybill_no for order in orders_tobe_picked_up]
435
 
436
    for awb, awbDetails in get_awb_status(awbs).iteritems():
23250 amit.gupta 437
 
438
        xmlScans = awbDetails['xmlScans']
439
        awbStatusObj = __get_scan_by_code(xmlScans, ['0011'])
440
 
441
        if awbStatusObj is None:
442
            continue
443
 
444
        bookedTime = awbStatusObj.statusDate
23236 amit.gupta 445
        picked_up_orders[awb] = str(bookedTime)
23250 amit.gupta 446
 
23236 amit.gupta 447
    print "Picked up Orders:"
448
    print picked_up_orders
449
    return picked_up_orders
450
 
451
def read_local_connection_orders(orders_tobe_local_connected):
452
 
453
    local_connected_orders = {}
454
    awbs = [order.airwaybill_no for order in orders_tobe_local_connected]
455
 
456
    for awb, awbDetails in get_awb_status(awbs).iteritems():
457
        #status = awbDetails['Status']
458
        #statusDate = get_pawbDetails['StatusDateTime']
459
        tracking = awbDetails['Tracking']
460
        bookedTime = get_py_datetime(tracking[-1]['StatusDateTime'])
461
        local_connected_orders[awb] = str(bookedTime)
462
 
463
    print "Local Connected Orders"
464
    print local_connected_orders
465
 
466
    return local_connected_orders
467
 
468
def read_reached_destination_orders(orders_tobe_reached_destination_city):
469
    destination_city_reached_orders = {}
470
 
471
    print "Destination City Reached Orders"
472
    print destination_city_reached_orders
473
 
474
    return destination_city_reached_orders
475
 
476
def read_first_delivery_attempt_orders(orders_tobe_first_delivery_attempted):
477
    first_atdl_orders = {}
478
    awbs = [order.airwaybill_no for order in orders_tobe_first_delivery_attempted]
479
    for awb, awbDetails in get_awb_status(awbs).iteritems():
480
        status = awbDetails['Status']
481
        print "STATUS -----", status
482
        if status.startswith("Undelivered"):
483
            statusTime = get_py_datetime(awbDetails['StatusDateTime'])
484
            first_atdl_orders[awb] = str(statusTime) + "|" + awbDetails['Status']
485
    print "FIRST DELIVERY ATTEMPT MADE Orders", first_atdl_orders
486
    print first_atdl_orders
487
 
488
    return first_atdl_orders
489
 
490
def read_delivery_orders(orders_tobe_delivered):
491
    delivered_orders = {}
492
    returned_orders = {}
493
    undelivered_orders = {}
494
 
495
    awbs = [order.airwaybill_no for order in orders_tobe_delivered]
496
 
497
    for awb, awbDetails in get_awb_status(awbs).iteritems():
23250 amit.gupta 498
        xmlScans = awbDetails['xmlScans']
23236 amit.gupta 499
 
23250 amit.gupta 500
        deliveredAwbStatusObj = __get_scan_by_code(xmlScans, REASON_CODES_DELIVERED)
501
        if deliveredAwbStatusObj is not None:
23334 amit.gupta 502
            bookedTime = deliveredAwbStatusObj.statusDate
23250 amit.gupta 503
            delivered_orders[awb] = str(bookedTime) + "|" +  "Not Available"
504
            continue
23236 amit.gupta 505
 
23250 amit.gupta 506
        rtoAwbStatusObj = __get_scan_by_code(xmlScans, REASON_CODES_RTO)
507
        if rtoAwbStatusObj is not None:
23335 amit.gupta 508
            bookedTime = rtoAwbStatusObj.statusDate
23250 amit.gupta 509
            delivered_orders[awb] = str(bookedTime) + "|" +  "Not Available"
510
            continue
23236 amit.gupta 511
 
23250 amit.gupta 512
 
513
        undeliveredAwbStatusObj = __get_scan_by_code(xmlScans, REASON_CODES_UNDELIVERED_MAP.keys())
514
        if undeliveredAwbStatusObj is not None:
23268 amit.gupta 515
            undelivered_orders[awb] = REASON_CODES_UNDELIVERED_MAP.get(undeliveredAwbStatusObj.statusCode)
23250 amit.gupta 516
 
517
 
518
 
519
        #undelivered_orders[awb] = awbDetails.statusDescription
520
 
23236 amit.gupta 521
    print "Delivered Orders:"
522
    print delivered_orders
523
 
524
    print "Returned Orders:"
525
    print returned_orders
526
 
527
    print "Undelivered Orders"
528
    print undelivered_orders
529
 
530
    return delivered_orders, returned_orders, undelivered_orders
531
 
532
def update_picked_orders(provider_id, pickup_details):
533
    txnClient = TransactionClient().get_client()
534
    try:
535
        txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
536
    except TransactionServiceException as tex:
537
        print tex.message
538
 
539
def update_picked_doas(provider_id, doa_pickup_details):
540
    txnClient = TransactionClient().get_client()
541
    try:
542
        txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
543
    except TransactionServiceException as tex:
544
        print tex.message
545
 
546
def update_picked_returns(provider_id, returns_pickup_details):
547
    txnClient = TransactionClient().get_client()
548
    try:
549
        txnClient.markReturnOrdersAsPickedUp(provider_id, returns_pickup_details)
550
    except TransactionServiceException as tex:
551
        print tex.message
552
 
553
def update_delivered_orders(provider_id, delivered_orders):
554
    txnClient = TransactionClient().get_client()
555
    try:
556
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
557
    except TransactionServiceException as tex:
558
        print tex.message
559
 
560
def update_returned_orders(provider_id, returned_orders):
561
    txnClient = TransactionClient().get_client()
562
    try:
563
        txnClient.markAsRTOrders(provider_id, returned_orders)
564
    except TransactionServiceException as tex:
565
        print tex.message
566
 
567
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
568
    txnClient = TransactionClient().get_client()
569
    try:
570
        txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
571
    except TransactionServiceException as tex:
572
        print tex.message
573
 
574
def update_local_connected_orders(provider_id, local_connected_orders):
575
    txnClient = TransactionClient().get_client()
576
    try:
577
        txnClient.markOrdersAsLocalConnected(provider_id, local_connected_orders)
578
    except TransactionServiceException as tex:
579
        print tex.message
580
 
581
def update_destination_city_reached_orders(provider_id, destination_city_reached_orders):
582
    txnClient = TransactionClient().get_client()
583
    try:
584
        txnClient.markOrdersAsDestinationCityReached(provider_id, destination_city_reached_orders)
585
    except TransactionServiceException as tex:
586
        print tex.message
587
 
588
def update_first_atdl_orders(provider_id, first_atdl_orders):
589
    txnClient = TransactionClient().get_client()
590
    try:
591
        txnClient.markOrdersAsFirstDeliveryAttempted(provider_id, first_atdl_orders)
592
    except TransactionServiceException as tex:
593
        print tex.message
594
 
595
def print_pickup_mismatch_report(filename, orders):
596
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
597
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
598
    for order in orders:
599
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
600
 
601
def print_dao_return_pickup_mismatch_report(filename, orders):
602
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
603
    writer.writerow(['Order Id', 'Pickup Request No', 'Authorization timestamp'])
604
    for order in orders:
605
        writer.writerow([order.id, order.pickupRequestNo, to_py_date(order.doa_auth_timestamp)])
606
 
607
def print_rto_orders_report(filename, orders):
608
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
609
    writer.writerow(['Order Id', 'AWB No', 'Return date', 'Reason'])
610
    for order in orders:
611
        statusDescription = ''
612
        if order.statusDescription is not None:
613
            statusDescription = order.statusDescription.replace(","," ")
614
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.delivery_timestamp), statusDescription])
615
 
616
def print_undelivered_orders_report(filename, orders):
617
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
618
    writer.writerow(['Order Id', 'AWB No', 'Status', 'Status Description', 'Shipping timestamp', 'Pickup timestamp', 'Promised delivery date', 'Expected delivery date'])
619
    for order in orders:
620
        statusDescription = ''
621
        if order.statusDescription is not None:
622
            statusDescription = order.statusDescription.replace(","," ")
623
        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)])
624
 
625
def auto_close_crm_tickets_created():
626
    try:
627
        ticket_created_orders = []
628
        tickets_map = {}
629
        crmServiceClient = CRMClient().get_client()
630
        searchFilter = SearchFilter()
631
        searchFilter.ticketCategory = TicketCategory.UNDELIVERED
632
        searchFilter.ticketAssigneeIds = [defaultUndeliveredAsssigneeId]
633
        searchFilter.ticketPriority = TicketPriority.HIGH
634
        searchFilter.ticketStatuses = [TicketStatus.OPEN]
635
        tickets = crmServiceClient.getTickets(searchFilter)
636
        print tickets
637
        for old_ticket in tickets:
638
            ticket_created_orders.append(old_ticket.orderId)
639
            tickets_map[old_ticket.orderId] = old_ticket
640
        print ticket_created_orders
641
        txnClient = TransactionClient().get_client()
642
        orders = txnClient.getOrderList(ticket_created_orders)
643
        for order in orders:
644
            if order.status not in [OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.RTO_IN_TRANSIT]:
645
                old_ticket = tickets_map.get(order.id)
646
                old_ticket.status = TicketStatus.CLOSED
647
                activity = Activity()
648
                activity.creatorId = 1
649
                activity.ticketAssigneeId = old_ticket.assigneeId
650
                activity.type = ActivityType.OTHER
651
                activity.description = "Ticket Closed bcoz order status changed to:" + order.statusDescription
652
                activity.ticketCategory = old_ticket.category
653
                activity.ticketDescription = old_ticket.description
654
                activity.ticketPriority = old_ticket.priority
655
                activity.ticketStatus = old_ticket.status
656
 
657
                if old_ticket.customerId is None or old_ticket.customerId == -1:
658
                    activity.customerEmailId = old_ticket.customerEmailId
659
                    activity.customerMobileNumber = old_ticket.customerMobileNumber
660
                    activity.customerName = old_ticket.customerName
661
                else:
662
                    activity.customerId = old_ticket.customerId
663
 
664
                crmServiceClient.updateTicket(old_ticket, activity)
665
    except:
666
        print "Some issue while closing crm tickets for orders in DELIVERY_SUCCESS status"
667
        traceback.print_exc()
668
 
669
def get_py_datetime(time_string):
23266 amit.gupta 670
    if time_string is None:
671
        return None
672
    time_string = time_string.strip()
23236 amit.gupta 673
    # This should be a command line argument.
674
    # Refer http://docs.python.org/library/time.html#time.strftime to
675
    # get a complete list of format specifiers available for date time.
23250 amit.gupta 676
    time_format = "%d %b, %Y, %H:%M"
23236 amit.gupta 677
    if time_string == '':
678
        return None
679
    return datetime.datetime.strptime(time_string, time_format)
680
 
23250 amit.gupta 681
def get_py_date(time_string):
23266 amit.gupta 682
    if time_string is None:
683
        return None
684
    time_string = time_string.strip()
23250 amit.gupta 685
    # This should be a command line argument.
686
    # Refer http://docs.python.org/library/time.html#time.strftime to
687
    # get a complete list of format specifiers available for date time.
688
    time_format = "%d-%b-%Y"
689
    if time_string == '':
690
        return None
691
    return datetime.datetime.strptime(time_string, time_format)
692
 
23236 amit.gupta 693
def getOriginCityBranchID(originCity):
694
    branchId_OriginCitymap = {'DEL':'7933'}
695
    if originCity is None or originCity == '':
696
        return ''
697
    else:
698
        return branchId_OriginCitymap.get(originCity)
699
 
700
def sanitizeUnicode(unicodeText):
701
    #remove unicode characters
702
    unicodeText = re.sub(r'[^\x00-\x7F]+','', unicodeText)
703
    #remove whitespaces and strip
704
    unicodeText = re.sub(r'[^\S]+',' ', unicodeText)
705
    return unicodeText.strip().encode('utf-8', 'ignore')
706
 
707
def main():
708
    parser = optparse.OptionParser()
709
    parser.add_option("-p", "--pickup", dest="pickup_report",
710
                   action="store_true",
711
                   help="Run the pickup reconciliation")
712
    parser.add_option("-d", "--delivery", dest="delivery_report",
713
                   action="store_true",
714
                   help="Run the delivery reconciliation")
715
    parser.add_option("-r", "--reports", dest="gen_reports",
716
                   action="store_true",
717
                   help="Generate logistic reconciliation reports")
718
    parser.add_option("-a", "--all", dest="all_reports",
719
                   action="store_true",
720
                   help="Run all reconciliations")
721
    parser.add_option("-P", "--provider", dest="provider",
722
                   default="RQuick-Express", type="string",
723
                   help="The PROVIDER this report is for",
724
                   metavar="PROVIDER")
725
    parser.set_defaults(pickup_report=False, delivery_report=False, gen_reports=False, all_reports=False)
726
    (options, args) = parser.parse_args()
727
    if len(args) != 0:
728
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
729
 
730
    if options.all_reports:
731
        options.pickup_report = True
732
        options.delivery_report = True
733
 
734
    provider = get_provider_by_name(options.provider)
735
 
736
    if options.pickup_report:
737
        process_pickup_records(provider)
738
        #process_dao_pickup_orders(provider)
739
        #process_return_pickup_orders(provider)
740
    if options.delivery_report:
741
        #process_local_connection_orders(provider)
742
        #process_reached_destination_city_orders(provider)
23250 amit.gupta 743
        #process_first_delivery_attempt_orders(provider)
23236 amit.gupta 744
        process_delivery_report(provider)
745
        #create_crm_tickets_for_delivey_attempted_orders(provider)
746
        #auto_close_crm_tickets_created()
747
    if options.gen_reports:
748
        pass
749
        #generate_reports(provider)
750
 
751
if __name__ == '__main__':
23250 amit.gupta 752
    main()
753
    #awbs =["897986473","225839621", "225839622", "225839623", "22583962"]
754
    #for awb, awbDetails in get_awb_status(awbs).iteritems():
755
        #print awb, awbDetails