Subversion Repositories SmartDukaan

Rev

Rev 4572 | Rev 4741 | Go to most recent revision | 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 
6
     picked up from our warehouse and DOA orders that were
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
 
4090 chandransh 15
It sends out a Pickup mismatch report and a Doa Pickup mismatch
16
report to cnc.center@shop2020.in
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'
4255 rajveer 41
to = ['cnc.center@shop2020.in', "suraj.sharma@shop2020.in", "sandeep.sachdeva@shop2020.in", "parmod.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')
2764 chandransh 46
        pickup_details, doa_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
67
                print_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()
4572 phani.kuma 76
    except:
77
        print "Some issue while processing the Pickup Report"
78
        traceback.print_exc()
2001 chandransh 79
    finally:
80
        os.remove(filename)
1132 chandransh 81
 
82
def process_delivery_report(provider):
2001 chandransh 83
    try:
84
        filename = fetch_report(provider.name.upper() + ' DELIVERED AND RTO REPORT')
85
        #filename = 'delivery_report.xls'
86
        delivered_orders, returned_orders = read_delivery_report(filename)
87
        if delivered_orders:
88
            update_delivered_orders(provider.id, delivered_orders)
89
        if returned_orders:
90
            update_returned_orders(provider.id, returned_orders)
4101 chandransh 91
            try:
92
                returned_orders_file = "/tmp/ReturnedOrders.csv"
93
                print_rto_orders_report(returned_orders_file, returned_orders)
94
                returned_orders_report = [get_attachment_part(returned_orders_file)]
95
                mail(from_user, from_pwd, to,\
96
                     "Returned Orders Report for " + provider.name,\
97
                     "This is a system generated email.Please don't reply to it.",\
4121 chandransh 98
                     returned_orders_report)
4101 chandransh 99
            except:
100
                print "Some issue sending the returned orders report"
101
                traceback.print_exc()
3476 chandransh 102
    except:
4572 phani.kuma 103
        print "Some issue while processing the Delivery & RTO Report"
3476 chandransh 104
        traceback.print_exc()
2001 chandransh 105
    finally:
106
        os.remove(filename)
1132 chandransh 107
 
108
def process_non_delivery_report(provider):
2001 chandransh 109
    try:
110
        filename = fetch_report(provider.name.upper() + ' UNDELIVERED REPORT')
111
        undelivered_orders = read_undelivered_report(filename)
4615 phani.kuma 112
        orders_not_delivered = update_reason_of_undelivered_orders(provider.id, undelivered_orders)
113
        try:
114
            if orders_not_delivered:
115
                print "Undelivered Orders:"
116
                print orders_not_delivered
117
                mismatch_file = "/tmp/UndeliveredOrders.csv"
118
                print "Some of our Orders were not delivered. Printing report to:" + mismatch_file
119
                print_undelivered_orders_report(mismatch_file, orders_not_delivered)
120
                pickup_mismatch_part = [get_attachment_part(mismatch_file)]
121
                mail(from_user, from_pwd, to,\
122
                     "Orders that are undelivered but picked up or shipped four days ago for " + provider.name,\
123
                     "This is a system generated email.Please don't reply to it.",\
124
                     pickup_mismatch_part)
125
        except:
126
                print "Some issue sending the undelivered orders report"
127
                traceback.print_exc()
4572 phani.kuma 128
    except:
129
        print "Some issue while processing the Non-delivery Report"
130
        traceback.print_exc()
2001 chandransh 131
    finally:
132
        os.remove(filename)
1246 chandransh 133
 
134
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
135
    txnClient = TransactionClient().get_client()
136
    try:
4615 phani.kuma 137
        orders_not_delivered = txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
138
        return orders_not_delivered
1246 chandransh 139
    except TransactionServiceException as tex:
140
        print tex.message
141
 
1132 chandransh 142
def get_provider_by_name(provider_name):
143
    logistics_client = LogisticsClient().get_client()
1246 chandransh 144
    #TODO: Write a thrift call to get a provider by name
1132 chandransh 145
    provider = None
146
    providers = logistics_client.getAllProviders()
147
    for p in providers:
148
        if p.name == provider_name:
149
            provider=p
150
            break
151
    if provider == None:
152
        sys.exit("Can't continue execution: No such provider")
153
    return provider
154
 
155
def fetch_report(type):
156
    filename = download_attachment(type, todays_date_string())
157
    if filename is None:
158
        sys.exit("The " + type + " report is not yet available.")
159
    return filename
160
 
161
def read_pickup_report(filename):
162
    print "Reading pickup report from:" + filename
163
    workbook = xlrd.open_workbook(filename)
164
    sheet = workbook.sheet_by_index(0)
165
    num_rows = sheet.nrows
166
    picked_up_orders = {}
2764 chandransh 167
    picked_up_doas = {}
1132 chandransh 168
    for rownum in range(1, num_rows):
2764 chandransh 169
        unused_customer_code, awb, ref_no, timeval, date = sheet.row_values(rownum)[0:5]
1263 chandransh 170
        picked_up_orders[awb] = str(get_py_datetime(date, timeval))
2764 chandransh 171
        picked_up_doas[ref_no] = str(get_py_datetime(date, timeval))
1135 chandransh 172
 
173
    print "Picked up Orders:"
174
    print picked_up_orders
2764 chandransh 175
    print picked_up_doas
176
    return picked_up_orders, picked_up_doas
1132 chandransh 177
 
178
def read_delivery_report(filename):
179
    print "Reading delivery details from:" + filename
180
    workbook = xlrd.open_workbook(filename)
181
    sheet = workbook.sheet_by_index(0)
182
    num_rows = sheet.nrows
183
    delivered_orders = {}
184
    returned_orders = {}
185
    for rownum in range(1, num_rows):
4077 chandransh 186
        unused_customer_code, awb, unused_ref_no, timeval, date, status, receiver, reason_for_return = sheet.row_values(rownum)[0:8]
1265 chandransh 187
        delivery_date = str(get_py_datetime(date, timeval))
4077 chandransh 188
        if 'Rto' in status:
189
            returned_orders[awb] = delivery_date + "|" + reason_for_return
190
        else:
1246 chandransh 191
            delivered_orders[awb] = delivery_date + "|" +  receiver
1135 chandransh 192
 
1132 chandransh 193
    print "Delivered Orders:"
194
    print delivered_orders
195
 
196
    print "Returned Orders:"
197
    print returned_orders
198
    return delivered_orders, returned_orders
199
 
1246 chandransh 200
def read_undelivered_report(filename):
201
    print "Reading undelivered details from:" + filename
202
    workbook = xlrd.open_workbook(filename)
203
    sheet = workbook.sheet_by_index(0)
204
    num_rows = sheet.nrows
205
    undelivered_orders = {}
206
    for rownum in range(1, num_rows):
2625 chandransh 207
        unused_cusotmer_code, awb, unused_ref_no, reason, timeval, date = sheet.row_values(rownum)[0:6]
2001 chandransh 208
        try:
209
            unused_status_date = str(get_py_datetime(date, timeval))
210
        except ValueError:
211
            #ValueError can be expected if the date or time are not in the expected format
212
            #Harmless error for now since we are not storing the status date
213
            print sys.exc_info()[0]
1246 chandransh 214
        undelivered_orders[awb] = reason
215
 
216
    print "Undelivered Orders"
217
    print undelivered_orders
218
 
219
    return undelivered_orders
220
 
1132 chandransh 221
def update_picked_orders(provider_id, pickup_details):
222
    txnClient = TransactionClient().get_client()
223
    try:
224
        orders_not_picked_up = txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
225
        return orders_not_picked_up
226
    except TransactionServiceException as tex:
227
        print tex.message
228
 
2764 chandransh 229
def update_picked_doas(provider_id, doa_pickup_details):
230
    txnClient = TransactionClient().get_client()
231
    try:
232
        doas_not_picked_up = txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
233
        return doas_not_picked_up
234
    except TransactionServiceException as tex:
235
        print tex.message
236
 
1135 chandransh 237
def update_delivered_orders(provider_id, delivered_orders):
1132 chandransh 238
    txnClient = TransactionClient().get_client()
239
    try:
1135 chandransh 240
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
1132 chandransh 241
    except TransactionServiceException as tex:
242
        print tex.message
243
 
1135 chandransh 244
def update_returned_orders(provider_id, returned_orders):
245
    txnClient = TransactionClient().get_client()
246
    try:
247
        txnClient.markOrdersAsFailed(provider_id, returned_orders)
248
    except TransactionServiceException as tex:
249
        print tex.message
1132 chandransh 250
 
1246 chandransh 251
def print_pickup_mismatch_report(filename, orders):
1132 chandransh 252
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
253
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
254
    for order in orders:
255
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
256
 
4101 chandransh 257
def print_rto_orders_report(filename, returned_orders):
258
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
259
    writer.writerow(['AWB No', 'Return date', 'Reason'])
260
    for awb, date_reason in returned_orders.iteritems():
261
        date, reason = date_reason.split('|')
4120 chandransh 262
        writer.writerow([awb, date, reason])
4101 chandransh 263
 
4615 phani.kuma 264
def print_undelivered_orders_report(filename, orders):
265
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
266
    writer.writerow(['Order Id', 'AWB No', 'Status', 'Status Description', 'Shipping timestamp', 'Pickup timestamp'])
267
    for order in orders:
268
        writer.writerow([order.id, order.airwaybill_no, order.status, order.statusDescription, to_py_date(order.shipping_timestamp), to_py_date(order.pickup_timestamp)])
269
 
1132 chandransh 270
def todays_date_string():
1246 chandransh 271
    today_date = time.strftime("%d-%b-%Y")
272
    return '"' + today_date + '"'
1132 chandransh 273
 
1263 chandransh 274
def get_py_datetime(date, timeval):
1246 chandransh 275
    # This should be a command line argument.
276
    # Refer http://docs.python.org/library/time.html#time.strftime to
277
    # get a complete list of format specifiers available for date time.
278
    time_format = "%d-%b-%y %H%M"
2693 chandransh 279
    if timeval is None or timeval == '--':
280
        timeval='0000'
1263 chandransh 281
    time_string = date + " " + timeval
1246 chandransh 282
    mytime = time.strptime(time_string, time_format)
283
    return datetime.datetime(*mytime[:6])
284
 
1132 chandransh 285
def main():
286
    parser = optparse.OptionParser()
287
    parser.add_option("-p", "--pickup", dest="pickup_report",
288
                   action="store_true",
289
                   help="Run the pickup reconciliation")
290
    parser.add_option("-d", "--delivery", dest="delivery_report",
291
                   action="store_true",
292
                   help="Run the delivery reconciliation")
293
    parser.add_option("-n", "--non-delivery", dest="non_delivery_report",
294
                   action="store_true",
295
                   help="Run the non delivery reconciliation")
296
    parser.add_option("-a", "--all", dest="all_reports",
297
                   action="store_true",
298
                   help="Run all reconciliations")
299
    parser.add_option("-P", "--provider", dest="provider",
300
                   default="BlueDart", type="string",
301
                   help="The PROVIDER this report is for",
302
                   metavar="PROVIDER")
303
    parser.set_defaults(pickup_report=False, delivery_report=False, non_delivery_report=False, all_reports=False)
304
    (options, args) = parser.parse_args()
305
    if len(args) != 0:
306
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
307
 
308
    if options.all_reports:
309
        options.pickup_report = True
310
        options.delivery_report = True
311
        options.non_delivery_report = True
312
 
313
    provider = get_provider_by_name(options.provider)
314
 
315
    if options.pickup_report:
316
        process_pickup_records(provider)
317
    if options.delivery_report:
318
        process_delivery_report(provider)
319
    if options.non_delivery_report:
320
        process_non_delivery_report(provider)
321
 
322
if __name__ == '__main__':
1718 chandransh 323
    main()