Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
4741 phani.kuma 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
import time
29
import datetime
30
import optparse
31
import sys
32
import csv
33
import traceback
34
import urllib2
35
from xml.etree.ElementTree import parse
36
 
37
if __name__ == '__main__' and __package__ is None:
38
    import os
39
    sys.path.insert(0, os.getcwd())
40
 
41
from shop2020.clients.LogisticsClient import LogisticsClient
42
from shop2020.clients.TransactionClient import TransactionClient
43
from shop2020.config.client.ConfigClient import ConfigClient
44
from shop2020.thriftpy.config.ttypes import ConfigException
45
from shop2020.thriftpy.model.v1.order.ttypes import TransactionServiceException, OrderStatus
46
from shop2020.utils.EmailAttachmentSender import get_attachment_part, mail
47
from shop2020.utils.Utils import to_py_date
48
 
49
from_user = 'cnc.center@shop2020.in'
50
from_pwd = '5h0p2o2o'
4760 phani.kuma 51
to = ['cnc.center@shop2020.in', "suraj.sharma@shop2020.in", "sandeep.sachdeva@shop2020.in", "manoj.kumar@shop2020.in"]
4741 phani.kuma 52
 
53
def process_dao_pickup_orders(provider):
54
    try:
55
        doas_tobe_picked_up = fetch_data(provider.id, OrderStatus.DOA_PICKUP_CONFIRMED)
56
        doa_pickup_details = read_dao_return_pickup_orders(doas_tobe_picked_up)
57
        doas_not_picked_up = update_picked_doas(provider.id, doa_pickup_details)
58
        try:
59
            if doas_not_picked_up:
60
                print "DOAs not Picked up:"
61
                print doas_not_picked_up
62
                mismatch_file = "/tmp/DoaPickupMismatch.csv"
63
                print "Some of our DOA orders were not picked up. Printing report to:" + mismatch_file
64
                print_pickup_mismatch_report(mismatch_file, doas_not_picked_up)
65
                pickup_mismatch_part = [get_attachment_part(mismatch_file)]
66
                mail(from_user, from_pwd, to,\
67
                     "DOA Pickup Mismatch for " + provider.name,\
68
                     "This is a system generated email.Please don't reply to it.",\
69
                     pickup_mismatch_part)
70
        except Exception:
71
            print "Some issue sending the DOA mismatch report"
72
            traceback.print_exc()
73
    except:
74
        print "Some issue while processing the orders in DOA_PICKUP_CONFIRMED status"
75
        traceback.print_exc()
76
 
77
def process_return_pickup_orders(provider):
78
    try:
79
        returns_tobe_picked_up = fetch_data(provider.id, OrderStatus.RET_PICKUP_CONFIRMED)
80
        returns_pickup_details = read_dao_return_pickup_orders(returns_tobe_picked_up)
81
        returns_not_picked_up = update_picked_returns(provider.id, returns_pickup_details)
82
        try:
83
            if returns_not_picked_up:
84
                print "Return Orders not Picked up:"
85
                print returns_not_picked_up
86
                mismatch_file = "/tmp/ReturnsPickupMismatch.csv"
87
                print "Some of our Return orders were not picked up. Printing report to:" + mismatch_file
88
                print_pickup_mismatch_report(mismatch_file, returns_not_picked_up)
89
                pickup_mismatch_part = [get_attachment_part(mismatch_file)]
90
                mail(from_user, from_pwd, to,\
91
                     "Return orders Pickup Mismatch for " + provider.name,\
92
                     "This is a system generated email.Please don't reply to it.",\
93
                     pickup_mismatch_part)
94
        except Exception:
95
            print "Some issue sending the Return orders mismatch report"
96
            traceback.print_exc()
97
    except:
98
        print "Some issue while processing the orders in RET_PICKUP_CONFIRMED status"
99
        traceback.print_exc()
100
 
101
def process_pickup_records(provider):
102
    try:
103
        orders_tobe_picked_up = fetch_data(provider.id, OrderStatus.SHIPPED_FROM_WH)
104
        pickup_details = read_pickup_orders(orders_tobe_picked_up)
105
        orders_not_picked_up = update_picked_orders(provider.id, pickup_details)
106
        try:
107
            if orders_not_picked_up:
108
                print "Orders not Picked up:"
109
                print orders_not_picked_up
110
                mismatch_file = "/tmp/PickupMismatch.csv"
111
                print "Some of our orders were not picked up. Printing report to:" + mismatch_file
112
                print_pickup_mismatch_report(mismatch_file, orders_not_picked_up)
113
                pickup_mismatch_part = [get_attachment_part(mismatch_file)]
114
                mail(from_user, from_pwd, to,\
115
                     "Order Pickup Mismatch for " + provider.name,\
116
                     "This is a system generated email.Please don't reply to it.",\
117
                     pickup_mismatch_part)
118
        except Exception:
119
            print "Some issue sending the pickup mismatch report"
120
            traceback.print_exc()
121
    except:
122
        print "Some issue while processing the orders in SHIPPED_FROM_WH status"
123
        traceback.print_exc()
124
 
125
def process_delivery_report(provider):
126
    try:
127
        orders_tobe_delivered = fetch_data(provider.id, OrderStatus.SHIPPED_TO_LOGST)
128
        delivered_orders, returned_orders, undelivered_orders = read_delivery_orders(orders_tobe_delivered)
129
        if delivered_orders:
130
            update_delivered_orders(provider.id, delivered_orders)
131
        if returned_orders:
132
            update_returned_orders(provider.id, returned_orders)
133
            try:
134
                returned_orders_file = "/tmp/ReturnedOrders.csv"
135
                print_rto_orders_report(returned_orders_file, returned_orders)
136
                returned_orders_report = [get_attachment_part(returned_orders_file)]
137
                mail(from_user, from_pwd, to,\
138
                     "Returned Orders Report for " + provider.name,\
139
                     "This is a system generated email.Please don't reply to it.",\
140
                     returned_orders_report)
141
            except:
142
                print "Some issue sending the returned orders report"
143
                traceback.print_exc()
144
        try:
145
            orders_not_delivered = update_reason_of_undelivered_orders(provider.id, undelivered_orders)
146
            if orders_not_delivered:
147
                print "Undelivered Orders:"
148
                print orders_not_delivered
149
                mismatch_file = "/tmp/UndeliveredOrders.csv"
150
                print "Some of our Orders were not delivered. Printing report to:" + mismatch_file
151
                print_undelivered_orders_report(mismatch_file, orders_not_delivered)
152
                pickup_mismatch_part = [get_attachment_part(mismatch_file)]
153
                mail(from_user, from_pwd, to,\
154
                     "Orders that are undelivered but picked up or shipped four days ago for " + provider.name,\
155
                     "This is a system generated email.Please don't reply to it.",\
156
                     pickup_mismatch_part)
157
        except Exception:
158
            print "Some issue updating and sending the undelivered orders report"
159
            traceback.print_exc()
160
    except:
161
        print "Some issue while processing the orders in SHIPPED_TO_LOGST status"
162
        traceback.print_exc()
163
 
164
def get_provider_by_name(provider_name):
165
    logistics_client = LogisticsClient().get_client()
166
    provider = None
167
    providers = logistics_client.getAllProviders()
168
    for p in providers:
169
        if p.name == provider_name:
170
            provider=p
171
            break
172
    if provider == None:
173
        sys.exit("Can't continue execution: No such provider")
174
    return provider
175
 
176
def fetch_data(provider_id, order_status):
177
    txnClient = TransactionClient().get_client()
178
    try:
179
        doas_tobe_picked_up = txnClient.getOrdersForProviderForStatus(provider_id, order_status)
180
        return doas_tobe_picked_up
181
    except TransactionServiceException as tex:
182
        print tex.message
183
 
184
def read_dao_return_pickup_orders(orders_tobe_picked_up):
185
    #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
186
    picked_up_orders = {}
187
    for order in orders_tobe_picked_up:
188
        try:
189
            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)
190
            root = parse(urllib2.urlopen(uri)).getroot()
191
            children = root.getchildren()
192
            if len(children):
193
                firstchild = children[0]
194
                nodes = firstchild.findall('Scans/ScanDetail')
195
                if len(nodes):
196
                    element = nodes[len(nodes)-1]
197
                    if element.findtext('ScanType', '') == 'UD' and element.findtext('Scan', '').strip().lower() == 'Shipment Inscan'.lower():
198
                        datestring = element.findtext('ScanDate', '')
199
                        timestring = element.findtext('ScanTime', '')
200
                        delivery_date = get_py_datetime(datestring, timestring)
201
                        picked_up_orders[order.pickupRequestNo] = str(delivery_date)
202
        except:
203
            pass
204
 
205
    print "Picked up Orders:"
206
    print picked_up_orders
207
    return picked_up_orders
208
 
209
def read_pickup_orders(orders_tobe_picked_up):
210
    try:
211
        config_client = ConfigClient()
212
        BLUEDART_URL = config_client.get_property("bluedart_update_url")
213
    except ConfigException as cex:
214
        print cex.message
215
        traceback.print_exc()
216
 
217
    picked_up_orders = {}
218
    for order in orders_tobe_picked_up:
219
        try:
220
            uri = BLUEDART_URL + order.airwaybill_no
221
            root = parse(urllib2.urlopen(uri)).getroot()
222
            children = root.getchildren()
223
            if len(children):
224
                firstchild = children[0]
225
                nodes = firstchild.findall('Scans/ScanDetail')
226
                if len(nodes):
227
                    element = nodes[len(nodes)-1]
228
                    if element.findtext('ScanType', '') == 'UD' and element.findtext('Scan', '').strip().lower() == 'Shipment Inscan'.lower():
229
                        datestring = element.findtext('ScanDate', '')
230
                        timestring = element.findtext('ScanTime', '')
231
                        delivery_date = get_py_datetime(datestring, timestring)
232
                        picked_up_orders[order.airwaybill_no] = str(delivery_date)
233
        except:
234
            pass
235
 
236
    print "Picked up Orders:"
237
    print picked_up_orders
238
    return picked_up_orders
239
 
240
def read_delivery_orders(orders_tobe_delivered):
241
    try:
242
        config_client = ConfigClient()
243
        BLUEDART_URL = config_client.get_property("bluedart_update_url")
244
    except ConfigException as cex:
245
        print cex.message
246
        traceback.print_exc()
247
 
248
    delivered_orders = {}
249
    returned_orders = {}
250
    undelivered_orders = {}
251
    for order in orders_tobe_delivered:
252
        try:
253
            uri = BLUEDART_URL + order.airwaybill_no
254
            root = parse(urllib2.urlopen(uri)).getroot()
255
            children = root.getchildren()
256
            child_number = 0
257
            for child in children:
258
                child_number = child_number + 1
259
                nodes = child.findall('Scans/ScanDetail')
260
                orderstatus = None
261
                if len(nodes):
262
                    i = len(nodes)-1
263
                    while i>=0:
264
                        element = nodes[i]
265
                        if element.findtext('ScanType', '') == 'DL':
266
                            orderstatus = 'DL'
267
                            datestring = element.findtext('ScanDate', '')
268
                            timestring = element.findtext('ScanTime', '')
269
                            delivery_date = get_py_datetime(datestring, timestring)
270
                            receiver = child.findtext('ReceivedBy', '')
271
                            delivered_orders[order.airwaybill_no] = str(delivery_date) + "|" +  receiver
272
                            break
273
                        elif element.findtext('ScanType', '') == 'RT':
274
                            orderstatus = 'RT'
275
                            datestring = element.findtext('ScanDate', '')
276
                            timestring = element.findtext('ScanTime', '')
277
                            delivery_date = get_py_datetime(datestring, timestring)
278
                            if i < len(nodes)-1:
279
                                reason_for_return = nodes[i+1].findtext('Scan', '')
280
                            else:
281
                                reason_for_return = element.findtext('Scan', '')
282
                            returned_orders[order.airwaybill_no] = str(delivery_date) + "|" + reason_for_return
283
                            break
284
                        elif element.findtext('ScanType', '') == 'RD':
285
                            orderstatus = 'RD'
286
                            break
287
                        elif i == 0:
288
                            orderstatus = 'UD'
289
                            reason = child.findtext('Status', '')
290
                            undelivered_orders[order.airwaybill_no] = reason
291
                            break
292
                        i = i-1
293
                else:
294
                    if child_number > 1:
295
                        reason = children[child_number-1].findtext('Status', '')
296
                        undelivered_orders[order.airwaybill_no] = reason
297
                if orderstatus != 'RD':
298
                    break
299
        except:
300
            pass
301
 
302
    print "Delivered Orders:"
303
    print delivered_orders
304
 
305
    print "Returned Orders:"
306
    print returned_orders
307
 
308
    print "Undelivered Orders"
309
    print undelivered_orders
310
 
311
    return delivered_orders, returned_orders, undelivered_orders
312
 
313
def update_picked_orders(provider_id, pickup_details):
314
    txnClient = TransactionClient().get_client()
315
    try:
316
        orders_not_picked_up = txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
317
        return orders_not_picked_up
318
    except TransactionServiceException as tex:
319
        print tex.message
320
 
321
def update_picked_doas(provider_id, doa_pickup_details):
322
    txnClient = TransactionClient().get_client()
323
    try:
324
        doas_not_picked_up = txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
325
        return doas_not_picked_up
326
    except TransactionServiceException as tex:
327
        print tex.message
328
 
329
def update_picked_returns(provider_id, returns_pickup_details):
330
    txnClient = TransactionClient().get_client()
331
    try:
332
        returns_not_picked_up = txnClient.markReturnOrdersAsPickedUp(provider_id, returns_pickup_details)
333
        return returns_not_picked_up
334
    except TransactionServiceException as tex:
335
        print tex.message
336
 
337
def update_delivered_orders(provider_id, delivered_orders):
338
    txnClient = TransactionClient().get_client()
339
    try:
340
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
341
    except TransactionServiceException as tex:
342
        print tex.message
343
 
344
def update_returned_orders(provider_id, returned_orders):
345
    txnClient = TransactionClient().get_client()
346
    try:
347
        txnClient.markOrdersAsFailed(provider_id, returned_orders)
348
    except TransactionServiceException as tex:
349
        print tex.message
350
 
351
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
352
    txnClient = TransactionClient().get_client()
353
    try:
354
        orders_not_delivered = txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
355
        return orders_not_delivered
356
    except TransactionServiceException as tex:
357
        print tex.message
358
 
359
def print_pickup_mismatch_report(filename, orders):
360
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
361
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
362
    for order in orders:
363
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
364
 
365
def print_rto_orders_report(filename, returned_orders):
366
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
367
    writer.writerow(['AWB No', 'Return date', 'Reason'])
368
    for awb, date_reason in returned_orders.iteritems():
369
        date, reason = date_reason.split('|')
370
        writer.writerow([awb, date, reason])
371
 
372
def print_undelivered_orders_report(filename, orders):
373
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
374
    writer.writerow(['Order Id', 'AWB No', 'Status', 'Status Description', 'Shipping timestamp', 'Pickup timestamp'])
375
    for order in orders:
376
        writer.writerow([order.id, order.airwaybill_no, order.status, order.statusDescription, to_py_date(order.shipping_timestamp), to_py_date(order.pickup_timestamp)])
377
 
378
def get_py_datetime(datestring, timestring):
379
    # This should be a command line argument.
380
    # Refer http://docs.python.org/library/time.html#time.strftime to
381
    # get a complete list of format specifiers available for date time.
382
    time_format = "%d-%b-%Y %H:%M:%S"
383
    if datestring == '':
384
        return None
385
    if timestring == '':
386
        timestring = '00:00:00'
387
    time_array = timestring.split(':')
388
    if len(time_array) < 3:
389
        timestring = timestring + ':00'
390
    time_string = datestring + ' ' + timestring
391
    mytime = time.strptime(time_string, time_format)
392
    return datetime.datetime(*mytime[:6])
393
 
394
def main():
395
    parser = optparse.OptionParser()
396
    parser.add_option("-p", "--pickup", dest="pickup_report",
397
                   action="store_true",
398
                   help="Run the pickup reconciliation")
399
    parser.add_option("-d", "--delivery", dest="delivery_report",
400
                   action="store_true",
401
                   help="Run the delivery reconciliation")
402
    parser.add_option("-a", "--all", dest="all_reports",
403
                   action="store_true",
404
                   help="Run all reconciliations")
405
    parser.add_option("-P", "--provider", dest="provider",
406
                   default="BlueDart", type="string",
407
                   help="The PROVIDER this report is for",
408
                   metavar="PROVIDER")
409
    parser.set_defaults(pickup_report=False, delivery_report=False, all_reports=False)
410
    (options, args) = parser.parse_args()
411
    if len(args) != 0:
412
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
413
 
414
    if options.all_reports:
415
        options.pickup_report = True
416
        options.delivery_report = True
417
 
418
    provider = get_provider_by_name(options.provider)
419
 
420
    if options.pickup_report:
421
        process_pickup_records(provider)
422
        process_dao_pickup_orders(provider)
423
        process_return_pickup_orders(provider)
424
    if options.delivery_report:
425
        process_delivery_report(provider)
426
 
427
if __name__ == '__main__':
428
    main()