Subversion Repositories SmartDukaan

Rev

Rev 4255 | Rev 4615 | 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)
112
        update_reason_of_undelivered_orders(provider.id, undelivered_orders)
4572 phani.kuma 113
    except:
114
        print "Some issue while processing the Non-delivery Report"
115
        traceback.print_exc()
2001 chandransh 116
    finally:
117
        os.remove(filename)
1246 chandransh 118
 
119
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
120
    txnClient = TransactionClient().get_client()
121
    try:
122
        txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
123
    except TransactionServiceException as tex:
124
        print tex.message
125
 
1132 chandransh 126
def get_provider_by_name(provider_name):
127
    logistics_client = LogisticsClient().get_client()
1246 chandransh 128
    #TODO: Write a thrift call to get a provider by name
1132 chandransh 129
    provider = None
130
    providers = logistics_client.getAllProviders()
131
    for p in providers:
132
        if p.name == provider_name:
133
            provider=p
134
            break
135
    if provider == None:
136
        sys.exit("Can't continue execution: No such provider")
137
    return provider
138
 
139
def fetch_report(type):
140
    filename = download_attachment(type, todays_date_string())
141
    if filename is None:
142
        sys.exit("The " + type + " report is not yet available.")
143
    return filename
144
 
145
def read_pickup_report(filename):
146
    print "Reading pickup report from:" + filename
147
    workbook = xlrd.open_workbook(filename)
148
    sheet = workbook.sheet_by_index(0)
149
    num_rows = sheet.nrows
150
    picked_up_orders = {}
2764 chandransh 151
    picked_up_doas = {}
1132 chandransh 152
    for rownum in range(1, num_rows):
2764 chandransh 153
        unused_customer_code, awb, ref_no, timeval, date = sheet.row_values(rownum)[0:5]
1263 chandransh 154
        picked_up_orders[awb] = str(get_py_datetime(date, timeval))
2764 chandransh 155
        picked_up_doas[ref_no] = str(get_py_datetime(date, timeval))
1135 chandransh 156
 
157
    print "Picked up Orders:"
158
    print picked_up_orders
2764 chandransh 159
    print picked_up_doas
160
    return picked_up_orders, picked_up_doas
1132 chandransh 161
 
162
def read_delivery_report(filename):
163
    print "Reading delivery details from:" + filename
164
    workbook = xlrd.open_workbook(filename)
165
    sheet = workbook.sheet_by_index(0)
166
    num_rows = sheet.nrows
167
    delivered_orders = {}
168
    returned_orders = {}
169
    for rownum in range(1, num_rows):
4077 chandransh 170
        unused_customer_code, awb, unused_ref_no, timeval, date, status, receiver, reason_for_return = sheet.row_values(rownum)[0:8]
1265 chandransh 171
        delivery_date = str(get_py_datetime(date, timeval))
4077 chandransh 172
        if 'Rto' in status:
173
            returned_orders[awb] = delivery_date + "|" + reason_for_return
174
        else:
1246 chandransh 175
            delivered_orders[awb] = delivery_date + "|" +  receiver
1135 chandransh 176
 
1132 chandransh 177
    print "Delivered Orders:"
178
    print delivered_orders
179
 
180
    print "Returned Orders:"
181
    print returned_orders
182
    return delivered_orders, returned_orders
183
 
1246 chandransh 184
def read_undelivered_report(filename):
185
    print "Reading undelivered details from:" + filename
186
    workbook = xlrd.open_workbook(filename)
187
    sheet = workbook.sheet_by_index(0)
188
    num_rows = sheet.nrows
189
    undelivered_orders = {}
190
    for rownum in range(1, num_rows):
2625 chandransh 191
        unused_cusotmer_code, awb, unused_ref_no, reason, timeval, date = sheet.row_values(rownum)[0:6]
2001 chandransh 192
        try:
193
            unused_status_date = str(get_py_datetime(date, timeval))
194
        except ValueError:
195
            #ValueError can be expected if the date or time are not in the expected format
196
            #Harmless error for now since we are not storing the status date
197
            print sys.exc_info()[0]
1246 chandransh 198
        undelivered_orders[awb] = reason
199
 
200
    print "Undelivered Orders"
201
    print undelivered_orders
202
 
203
    return undelivered_orders
204
 
1132 chandransh 205
def update_picked_orders(provider_id, pickup_details):
206
    txnClient = TransactionClient().get_client()
207
    try:
208
        orders_not_picked_up = txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
209
        return orders_not_picked_up
210
    except TransactionServiceException as tex:
211
        print tex.message
212
 
2764 chandransh 213
def update_picked_doas(provider_id, doa_pickup_details):
214
    txnClient = TransactionClient().get_client()
215
    try:
216
        doas_not_picked_up = txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
217
        return doas_not_picked_up
218
    except TransactionServiceException as tex:
219
        print tex.message
220
 
1135 chandransh 221
def update_delivered_orders(provider_id, delivered_orders):
1132 chandransh 222
    txnClient = TransactionClient().get_client()
223
    try:
1135 chandransh 224
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
1132 chandransh 225
    except TransactionServiceException as tex:
226
        print tex.message
227
 
1135 chandransh 228
def update_returned_orders(provider_id, returned_orders):
229
    txnClient = TransactionClient().get_client()
230
    try:
231
        txnClient.markOrdersAsFailed(provider_id, returned_orders)
232
    except TransactionServiceException as tex:
233
        print tex.message
1132 chandransh 234
 
1246 chandransh 235
def print_pickup_mismatch_report(filename, orders):
1132 chandransh 236
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
237
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
238
    for order in orders:
239
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
240
 
4101 chandransh 241
def print_rto_orders_report(filename, returned_orders):
242
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
243
    writer.writerow(['AWB No', 'Return date', 'Reason'])
244
    for awb, date_reason in returned_orders.iteritems():
245
        date, reason = date_reason.split('|')
4120 chandransh 246
        writer.writerow([awb, date, reason])
4101 chandransh 247
 
1132 chandransh 248
def todays_date_string():
1246 chandransh 249
    today_date = time.strftime("%d-%b-%Y")
250
    return '"' + today_date + '"'
1132 chandransh 251
 
1263 chandransh 252
def get_py_datetime(date, timeval):
1246 chandransh 253
    # This should be a command line argument.
254
    # Refer http://docs.python.org/library/time.html#time.strftime to
255
    # get a complete list of format specifiers available for date time.
256
    time_format = "%d-%b-%y %H%M"
2693 chandransh 257
    if timeval is None or timeval == '--':
258
        timeval='0000'
1263 chandransh 259
    time_string = date + " " + timeval
1246 chandransh 260
    mytime = time.strptime(time_string, time_format)
261
    return datetime.datetime(*mytime[:6])
262
 
1132 chandransh 263
def main():
264
    parser = optparse.OptionParser()
265
    parser.add_option("-p", "--pickup", dest="pickup_report",
266
                   action="store_true",
267
                   help="Run the pickup reconciliation")
268
    parser.add_option("-d", "--delivery", dest="delivery_report",
269
                   action="store_true",
270
                   help="Run the delivery reconciliation")
271
    parser.add_option("-n", "--non-delivery", dest="non_delivery_report",
272
                   action="store_true",
273
                   help="Run the non delivery reconciliation")
274
    parser.add_option("-a", "--all", dest="all_reports",
275
                   action="store_true",
276
                   help="Run all reconciliations")
277
    parser.add_option("-P", "--provider", dest="provider",
278
                   default="BlueDart", type="string",
279
                   help="The PROVIDER this report is for",
280
                   metavar="PROVIDER")
281
    parser.set_defaults(pickup_report=False, delivery_report=False, non_delivery_report=False, all_reports=False)
282
    (options, args) = parser.parse_args()
283
    if len(args) != 0:
284
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
285
 
286
    if options.all_reports:
287
        options.pickup_report = True
288
        options.delivery_report = True
289
        options.non_delivery_report = True
290
 
291
    provider = get_provider_by_name(options.provider)
292
 
293
    if options.pickup_report:
294
        process_pickup_records(provider)
295
    if options.delivery_report:
296
        process_delivery_report(provider)
297
    if options.non_delivery_report:
298
        process_non_delivery_report(provider)
299
 
300
if __name__ == '__main__':
1718 chandransh 301
    main()