Subversion Repositories SmartDukaan

Rev

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