Subversion Repositories SmartDukaan

Rev

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