Subversion Repositories SmartDukaan

Rev

Rev 4910 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3476 chandransh 1
#!/usr/bin/python
4090 chandransh 2
'''
3
It processes the following reports received from Couriers
4
through email:
5
 1. Pickup Report : contains details of orders that were 
4741 phani.kuma 6
     picked up from our warehouse, Return orders and DOA orders that were
4090 chandransh 7
     picked up from our customers.
8
 2. Delivery & RTO Report: contains details of orders that
9
     were either successfully delivered to our customers or
10
     which are being returned to us.
11
 3. Non-delivery Report: contains details of orders whose
12
     delivery date has passed but which have not been 
13
     delivered yet.
1132 chandransh 14
 
4741 phani.kuma 15
It sends out a Pickup mismatch report, Return orders Pickup Mismatch report, Doa Pickup mismatch report,
16
Undelivered orders report and Returned Orders report to cnc.center@shop2020.in
4090 chandransh 17
 
18
@author: Chandranshu
19
'''
1246 chandransh 20
import time
1132 chandransh 21
import datetime
22
import optparse
23
import sys
24
import csv
25
import xlrd
3476 chandransh 26
import traceback
1132 chandransh 27
 
28
if __name__ == '__main__' and __package__ is None:
29
    import os
30
    sys.path.insert(0, os.getcwd())
31
 
32
from shop2020.clients.LogisticsClient import LogisticsClient
33
from shop2020.clients.TransactionClient import TransactionClient
34
from shop2020.thriftpy.model.v1.order.ttypes import TransactionServiceException
35
from shop2020.utils.EmailAttachmentDownloader import download_attachment
1246 chandransh 36
from shop2020.utils.EmailAttachmentSender import get_attachment_part, mail
1132 chandransh 37
from shop2020.utils.Utils import to_py_date
38
 
1246 chandransh 39
from_user = 'cnc.center@shop2020.in'
40
from_pwd = '5h0p2o2o'
6643 rajveer 41
to = ['cnc.center@shop2020.in', "amit.sirohi@shop2020.in", "sandeep.sachdeva@shop2020.in", "manoj.kumar@shop2020.in"]
1246 chandransh 42
 
1132 chandransh 43
def process_pickup_records(provider):
2001 chandransh 44
    try:
45
        filename = fetch_report(provider.name.upper() + ' PICKUP REPORT')
4741 phani.kuma 46
        pickup_details, doa_pickup_details, returns_pickup_details = read_pickup_report(filename)
2001 chandransh 47
        orders_not_picked_up = update_picked_orders(provider.id, pickup_details)
2764 chandransh 48
        try:
49
            if orders_not_picked_up:
3476 chandransh 50
                mismatch_file = "/tmp/PickupMismatch.csv"
2764 chandransh 51
                print "Some of our orders were not picked up. Printing report to:" + mismatch_file
52
                print_pickup_mismatch_report(mismatch_file, orders_not_picked_up)
3476 chandransh 53
                pickup_mismatch_part = [get_attachment_part(mismatch_file)]
2764 chandransh 54
                mail(from_user, from_pwd, to,\
55
                     "Order Pickup Mismatch for " + provider.name,\
56
                     "This is a system generated email.Please don't reply to it.",\
57
                     pickup_mismatch_part)
58
        except Exception:
3477 chandransh 59
            print "Some issue sending the pickup mismatch report"
3476 chandransh 60
            traceback.print_exc()
2764 chandransh 61
 
62
        doas_not_picked_up = update_picked_doas(provider.id, doa_pickup_details)
63
        try:
64
            if doas_not_picked_up:
3476 chandransh 65
                mismatch_file = "/tmp/DoaPickupMismatch.csv"
2764 chandransh 66
                print "Some of our DOA orders were not picked up. Printing report to:" + mismatch_file
4783 phani.kuma 67
                print_dao_return_pickup_mismatch_report(mismatch_file, doas_not_picked_up)
3475 chandransh 68
                pickup_mismatch_part = [get_attachment_part(mismatch_file)]
2764 chandransh 69
                mail(from_user, from_pwd, to,\
70
                     "DOA Pickup Mismatch for " + provider.name,\
71
                     "This is a system generated email.Please don't reply to it.",\
72
                     pickup_mismatch_part)
73
        except Exception:
3477 chandransh 74
            print "Some issue sending the DOA mismatch report"
3476 chandransh 75
            traceback.print_exc()
4741 phani.kuma 76
 
77
        returns_not_picked_up = update_picked_returns(provider.id, returns_pickup_details)
78
        try:
79
            if returns_not_picked_up:
80
                mismatch_file = "/tmp/ReturnsPickupMismatch.csv"
81
                print "Some of our Return orders were not picked up. Printing report to:" + mismatch_file
4783 phani.kuma 82
                print_dao_return_pickup_mismatch_report(mismatch_file, returns_not_picked_up)
4741 phani.kuma 83
                pickup_mismatch_part = [get_attachment_part(mismatch_file)]
84
                mail(from_user, from_pwd, to,\
85
                     "Return orders Pickup Mismatch for " + provider.name,\
86
                     "This is a system generated email.Please don't reply to it.",\
87
                     pickup_mismatch_part)
88
        except Exception:
89
            print "Some issue sending the Return orders mismatch report"
90
            traceback.print_exc()
4572 phani.kuma 91
    except:
92
        print "Some issue while processing the Pickup Report"
93
        traceback.print_exc()
2001 chandransh 94
    finally:
95
        os.remove(filename)
1132 chandransh 96
 
97
def process_delivery_report(provider):
2001 chandransh 98
    try:
99
        filename = fetch_report(provider.name.upper() + ' DELIVERED AND RTO REPORT')
100
        #filename = 'delivery_report.xls'
101
        delivered_orders, returned_orders = read_delivery_report(filename)
102
        if delivered_orders:
103
            update_delivered_orders(provider.id, delivered_orders)
104
        if returned_orders:
105
            update_returned_orders(provider.id, returned_orders)
4101 chandransh 106
            try:
107
                returned_orders_file = "/tmp/ReturnedOrders.csv"
108
                print_rto_orders_report(returned_orders_file, returned_orders)
109
                returned_orders_report = [get_attachment_part(returned_orders_file)]
110
                mail(from_user, from_pwd, to,\
111
                     "Returned Orders Report for " + provider.name,\
112
                     "This is a system generated email.Please don't reply to it.",\
4121 chandransh 113
                     returned_orders_report)
4101 chandransh 114
            except:
115
                print "Some issue sending the returned orders report"
116
                traceback.print_exc()
3476 chandransh 117
    except:
4572 phani.kuma 118
        print "Some issue while processing the Delivery & RTO Report"
3476 chandransh 119
        traceback.print_exc()
2001 chandransh 120
    finally:
121
        os.remove(filename)
1132 chandransh 122
 
123
def process_non_delivery_report(provider):
2001 chandransh 124
    try:
125
        filename = fetch_report(provider.name.upper() + ' UNDELIVERED REPORT')
126
        undelivered_orders = read_undelivered_report(filename)
4615 phani.kuma 127
        orders_not_delivered = update_reason_of_undelivered_orders(provider.id, undelivered_orders)
128
        try:
129
            if orders_not_delivered:
130
                print "Undelivered Orders:"
131
                print orders_not_delivered
132
                mismatch_file = "/tmp/UndeliveredOrders.csv"
133
                print "Some of our Orders were not delivered. Printing report to:" + mismatch_file
134
                print_undelivered_orders_report(mismatch_file, orders_not_delivered)
135
                pickup_mismatch_part = [get_attachment_part(mismatch_file)]
136
                mail(from_user, from_pwd, to,\
137
                     "Orders that are undelivered but picked up or shipped four days ago for " + provider.name,\
138
                     "This is a system generated email.Please don't reply to it.",\
139
                     pickup_mismatch_part)
140
        except:
141
                print "Some issue sending the undelivered orders report"
142
                traceback.print_exc()
4572 phani.kuma 143
    except:
144
        print "Some issue while processing the Non-delivery Report"
145
        traceback.print_exc()
2001 chandransh 146
    finally:
147
        os.remove(filename)
1246 chandransh 148
 
149
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
150
    txnClient = TransactionClient().get_client()
151
    try:
4615 phani.kuma 152
        orders_not_delivered = txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
153
        return orders_not_delivered
1246 chandransh 154
    except TransactionServiceException as tex:
155
        print tex.message
156
 
1132 chandransh 157
def get_provider_by_name(provider_name):
158
    logistics_client = LogisticsClient().get_client()
1246 chandransh 159
    #TODO: Write a thrift call to get a provider by name
1132 chandransh 160
    provider = None
161
    providers = logistics_client.getAllProviders()
162
    for p in providers:
163
        if p.name == provider_name:
164
            provider=p
165
            break
166
    if provider == None:
167
        sys.exit("Can't continue execution: No such provider")
168
    return provider
169
 
170
def fetch_report(type):
171
    filename = download_attachment(type, todays_date_string())
172
    if filename is None:
173
        sys.exit("The " + type + " report is not yet available.")
174
    return filename
175
 
176
def read_pickup_report(filename):
177
    print "Reading pickup report from:" + filename
178
    workbook = xlrd.open_workbook(filename)
179
    sheet = workbook.sheet_by_index(0)
180
    num_rows = sheet.nrows
181
    picked_up_orders = {}
2764 chandransh 182
    picked_up_doas = {}
4741 phani.kuma 183
    picked_up_returns = {}
1132 chandransh 184
    for rownum in range(1, num_rows):
2764 chandransh 185
        unused_customer_code, awb, ref_no, timeval, date = sheet.row_values(rownum)[0:5]
1263 chandransh 186
        picked_up_orders[awb] = str(get_py_datetime(date, timeval))
2764 chandransh 187
        picked_up_doas[ref_no] = str(get_py_datetime(date, timeval))
4741 phani.kuma 188
        picked_up_returns[ref_no] = str(get_py_datetime(date, timeval))
1135 chandransh 189
 
190
    print "Picked up Orders:"
191
    print picked_up_orders
4741 phani.kuma 192
    print "Picked up DOAs:"
2764 chandransh 193
    print picked_up_doas
4741 phani.kuma 194
    print "Picked up RETURNS:"
195
    print picked_up_returns
196
    return picked_up_orders, picked_up_doas, picked_up_returns
1132 chandransh 197
 
198
def read_delivery_report(filename):
199
    print "Reading delivery details from:" + filename
200
    workbook = xlrd.open_workbook(filename)
201
    sheet = workbook.sheet_by_index(0)
202
    num_rows = sheet.nrows
203
    delivered_orders = {}
204
    returned_orders = {}
205
    for rownum in range(1, num_rows):
4077 chandransh 206
        unused_customer_code, awb, unused_ref_no, timeval, date, status, receiver, reason_for_return = sheet.row_values(rownum)[0:8]
1265 chandransh 207
        delivery_date = str(get_py_datetime(date, timeval))
4077 chandransh 208
        if 'Rto' in status:
209
            returned_orders[awb] = delivery_date + "|" + reason_for_return
210
        else:
1246 chandransh 211
            delivered_orders[awb] = delivery_date + "|" +  receiver
1135 chandransh 212
 
1132 chandransh 213
    print "Delivered Orders:"
214
    print delivered_orders
215
 
216
    print "Returned Orders:"
217
    print returned_orders
218
    return delivered_orders, returned_orders
219
 
1246 chandransh 220
def read_undelivered_report(filename):
221
    print "Reading undelivered details from:" + filename
222
    workbook = xlrd.open_workbook(filename)
223
    sheet = workbook.sheet_by_index(0)
224
    num_rows = sheet.nrows
225
    undelivered_orders = {}
226
    for rownum in range(1, num_rows):
2625 chandransh 227
        unused_cusotmer_code, awb, unused_ref_no, reason, timeval, date = sheet.row_values(rownum)[0:6]
2001 chandransh 228
        try:
229
            unused_status_date = str(get_py_datetime(date, timeval))
230
        except ValueError:
231
            #ValueError can be expected if the date or time are not in the expected format
232
            #Harmless error for now since we are not storing the status date
233
            print sys.exc_info()[0]
1246 chandransh 234
        undelivered_orders[awb] = reason
235
 
236
    print "Undelivered Orders"
237
    print undelivered_orders
238
 
239
    return undelivered_orders
240
 
1132 chandransh 241
def update_picked_orders(provider_id, pickup_details):
242
    txnClient = TransactionClient().get_client()
243
    try:
244
        orders_not_picked_up = txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
245
        return orders_not_picked_up
246
    except TransactionServiceException as tex:
247
        print tex.message
248
 
2764 chandransh 249
def update_picked_doas(provider_id, doa_pickup_details):
250
    txnClient = TransactionClient().get_client()
251
    try:
252
        doas_not_picked_up = txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
253
        return doas_not_picked_up
254
    except TransactionServiceException as tex:
255
        print tex.message
256
 
4741 phani.kuma 257
def update_picked_returns(provider_id, returns_pickup_details):
258
    txnClient = TransactionClient().get_client()
259
    try:
260
        returns_not_picked_up = txnClient.markReturnOrdersAsPickedUp(provider_id, returns_pickup_details)
261
        return returns_not_picked_up
262
    except TransactionServiceException as tex:
263
        print tex.message
264
 
1135 chandransh 265
def update_delivered_orders(provider_id, delivered_orders):
1132 chandransh 266
    txnClient = TransactionClient().get_client()
267
    try:
1135 chandransh 268
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
1132 chandransh 269
    except TransactionServiceException as tex:
270
        print tex.message
271
 
1135 chandransh 272
def update_returned_orders(provider_id, returned_orders):
273
    txnClient = TransactionClient().get_client()
274
    try:
4910 phani.kuma 275
        txnClient.markAsRTOrders(provider_id, returned_orders)
1135 chandransh 276
    except TransactionServiceException as tex:
277
        print tex.message
1132 chandransh 278
 
1246 chandransh 279
def print_pickup_mismatch_report(filename, orders):
1132 chandransh 280
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
281
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
282
    for order in orders:
283
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
284
 
4783 phani.kuma 285
def print_dao_return_pickup_mismatch_report(filename, orders):
286
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
287
    writer.writerow(['Order Id', 'Pickup Request No', 'Authorization timestamp'])
288
    for order in orders:
289
        writer.writerow([order.id, order.pickupRequestNo, to_py_date(order.doa_auth_timestamp)])
290
 
4101 chandransh 291
def print_rto_orders_report(filename, returned_orders):
292
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
293
    writer.writerow(['AWB No', 'Return date', 'Reason'])
294
    for awb, date_reason in returned_orders.iteritems():
295
        date, reason = date_reason.split('|')
4792 phani.kuma 296
        if reason is not None:
297
            reason = reason.replace(","," ")
4120 chandransh 298
        writer.writerow([awb, date, reason])
4101 chandransh 299
 
4615 phani.kuma 300
def print_undelivered_orders_report(filename, orders):
301
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
302
    writer.writerow(['Order Id', 'AWB No', 'Status', 'Status Description', 'Shipping timestamp', 'Pickup timestamp'])
303
    for order in orders:
4792 phani.kuma 304
        statusDescription = ''
305
        if order.statusDescription is not None:
306
            statusDescription = order.statusDescription.replace(","," ")
307
        writer.writerow([order.id, order.airwaybill_no, order.status, statusDescription, to_py_date(order.shipping_timestamp), to_py_date(order.pickup_timestamp)])
4615 phani.kuma 308
 
1132 chandransh 309
def todays_date_string():
1246 chandransh 310
    today_date = time.strftime("%d-%b-%Y")
311
    return '"' + today_date + '"'
1132 chandransh 312
 
1263 chandransh 313
def get_py_datetime(date, timeval):
1246 chandransh 314
    # This should be a command line argument.
315
    # Refer http://docs.python.org/library/time.html#time.strftime to
316
    # get a complete list of format specifiers available for date time.
317
    time_format = "%d-%b-%y %H%M"
2693 chandransh 318
    if timeval is None or timeval == '--':
319
        timeval='0000'
1263 chandransh 320
    time_string = date + " " + timeval
1246 chandransh 321
    mytime = time.strptime(time_string, time_format)
322
    return datetime.datetime(*mytime[:6])
323
 
1132 chandransh 324
def main():
325
    parser = optparse.OptionParser()
326
    parser.add_option("-p", "--pickup", dest="pickup_report",
327
                   action="store_true",
328
                   help="Run the pickup reconciliation")
329
    parser.add_option("-d", "--delivery", dest="delivery_report",
330
                   action="store_true",
331
                   help="Run the delivery reconciliation")
332
    parser.add_option("-n", "--non-delivery", dest="non_delivery_report",
333
                   action="store_true",
334
                   help="Run the non delivery reconciliation")
335
    parser.add_option("-a", "--all", dest="all_reports",
336
                   action="store_true",
337
                   help="Run all reconciliations")
338
    parser.add_option("-P", "--provider", dest="provider",
339
                   default="BlueDart", type="string",
340
                   help="The PROVIDER this report is for",
341
                   metavar="PROVIDER")
342
    parser.set_defaults(pickup_report=False, delivery_report=False, non_delivery_report=False, all_reports=False)
343
    (options, args) = parser.parse_args()
344
    if len(args) != 0:
345
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
346
 
347
    if options.all_reports:
348
        options.pickup_report = True
349
        options.delivery_report = True
350
        options.non_delivery_report = True
351
 
352
    provider = get_provider_by_name(options.provider)
353
 
354
    if options.pickup_report:
355
        process_pickup_records(provider)
356
    if options.delivery_report:
357
        process_delivery_report(provider)
358
    if options.non_delivery_report:
359
        process_non_delivery_report(provider)
360
 
361
if __name__ == '__main__':
1718 chandransh 362
    main()