Subversion Repositories SmartDukaan

Rev

Rev 4508 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4506 phani.kuma 1
#!/usr/bin/python
2
'''
3
It processes the following orders:
4
 1. Orders in DOA_PICKUP_CONFIRMED status : get details of orders that 
5
     were in DOA_PICKUP_CONFIRMED status from database and 
6
     calls aramex api to know whether they are picked up by armaex
7
     and changes the status to DOA_RETURN_IN_TRANSIT if it is done.
8
 2. Orders in SHIPPED_FROM_WH status: get details of orders that
9
     were in SHIPPED_FROM_WH status from database and 
10
     calls aramex api to know whether they are picked up by armaex
11
     and changes the status to SHIPPED_TO_LOGST if it is done.
12
 3. Orders in SHIPPED_TO_LOGST status: get details of orders that
13
     were in SHIPPED_TO_LOGST status from database and 
14
     calls aramex api to know their status and changes the status accordingly.
15
 
16
It sends out a Pickup mismatch report, a Doa Pickup mismatch and Returned Orders Report
17
report to cnc.center@shop2020.in
18
 
19
http://www.aramex.com/track_xml.asp?ShipperRef={variable1}&OrgCntry=In&FromDate={variable2}&ToDate={variable3} is hard coded
20
to track DOA orders and for other orders ConfigClient is called to get aramex_update_url
21
 
22
@author: Phani Kumar
23
'''
24
import time
25
import datetime
26
import optparse
27
import sys
28
import csv
29
import traceback
30
import urllib2
31
from xml.etree.ElementTree import parse
32
 
33
if __name__ == '__main__' and __package__ is None:
34
    import os
35
    sys.path.insert(0, os.getcwd())
36
 
37
from shop2020.clients.LogisticsClient import LogisticsClient
38
from shop2020.clients.TransactionClient import TransactionClient
39
from shop2020.config.client.ConfigClient import ConfigClient
40
from shop2020.thriftpy.config.ttypes import ConfigException
41
from shop2020.thriftpy.model.v1.order.ttypes import TransactionServiceException, OrderStatus
42
from shop2020.utils.EmailAttachmentSender import get_attachment_part, mail
43
from shop2020.utils.Utils import to_py_date
44
 
45
from_user = 'cnc.center@shop2020.in'
46
from_pwd = '5h0p2o2o'
47
to = ['cnc.center@shop2020.in', "suraj.sharma@shop2020.in", "sandeep.sachdeva@shop2020.in", "parmod.kumar@shop2020.in"]
48
#to = ['phani.kumar@shop2020.in']
49
 
50
def process_dao_pickup_orders(provider):
51
    doas_tobe_picked_up = fetch_data(provider.id, OrderStatus.DOA_PICKUP_CONFIRMED)
52
    doa_pickup_details = read_dao_pickup_orders(doas_tobe_picked_up)
53
    doas_not_picked_up = update_picked_doas(provider.id, doa_pickup_details)
54
    try:
55
        if doas_not_picked_up:
56
            print "DOAs not Picked up:"
57
            print doas_not_picked_up
58
            mismatch_file = "/tmp/DoaPickupMismatch.csv"
59
            print "Some of our DOA orders were not picked up. Printing report to:" + mismatch_file
60
            print_pickup_mismatch_report(mismatch_file, doas_not_picked_up)
61
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
62
            mail(from_user, from_pwd, to,\
63
                 "DOA Pickup Mismatch for " + provider.name,\
64
                 "This is a system generated email.Please don't reply to it.",\
65
                 pickup_mismatch_part)
66
    except Exception:
67
        print "Some issue sending the DOA mismatch report"
68
        traceback.print_exc()
69
 
70
def process_pickup_records(provider):
71
    orders_tobe_picked_up = fetch_data(provider.id, OrderStatus.SHIPPED_FROM_WH)
72
    pickup_details = read_pickup_orders(orders_tobe_picked_up)
73
    orders_not_picked_up = update_picked_orders(provider.id, pickup_details)
74
    try:
75
        if orders_not_picked_up:
76
            print "Orders not Picked up:"
77
            print orders_not_picked_up
78
            mismatch_file = "/tmp/PickupMismatch.csv"
79
            print "Some of our orders were not picked up. Printing report to:" + mismatch_file
80
            print_pickup_mismatch_report(mismatch_file, orders_not_picked_up)
81
            pickup_mismatch_part = [get_attachment_part(mismatch_file)]
82
            mail(from_user, from_pwd, to,\
83
                 "Order Pickup Mismatch for " + provider.name,\
84
                 "This is a system generated email.Please don't reply to it.",\
85
                 pickup_mismatch_part)
86
    except Exception:
87
        print "Some issue sending the pickup mismatch report"
88
        traceback.print_exc()
89
 
90
def process_delivery_report(provider):
91
    try:
92
        orders_tobe_delivered = fetch_data(provider.id, OrderStatus.SHIPPED_TO_LOGST)
93
        delivered_orders, returned_orders, undelivered_orders = read_delivery_orders(orders_tobe_delivered)
94
        if undelivered_orders:
95
            update_reason_of_undelivered_orders(provider.id, undelivered_orders)
96
        if delivered_orders:
97
            update_delivered_orders(provider.id, delivered_orders)
98
        if returned_orders:
99
            update_returned_orders(provider.id, returned_orders)
100
            try:
101
                returned_orders_file = "/tmp/ReturnedOrders.csv"
102
                print_rto_orders_report(returned_orders_file, returned_orders)
103
                returned_orders_report = [get_attachment_part(returned_orders_file)]
104
                mail(from_user, from_pwd, to,\
105
                     "Returned Orders Report for " + provider.name,\
106
                     "This is a system generated email.Please don't reply to it.",\
107
                     returned_orders_report)
108
            except:
109
                print "Some issue sending the returned orders report"
110
                traceback.print_exc()
111
    except:
112
        print "Some issue while processing the returned orders"
113
        traceback.print_exc()
114
 
115
def get_provider_by_name(provider_name):
116
    logistics_client = LogisticsClient().get_client()
117
    #TODO: Write a thrift call to get a provider by name
118
    provider = None
119
    providers = logistics_client.getAllProviders()
120
    for p in providers:
121
        if p.name == provider_name:
122
            provider=p
123
            break
124
    if provider == None:
125
        sys.exit("Can't continue execution: No such provider")
126
    return provider
127
 
128
def fetch_data(provider_id, order_status):
129
    txnClient = TransactionClient().get_client()
130
    try:
131
        doas_tobe_picked_up = txnClient.getOrdersForProviderForStatus(provider_id, order_status)
132
        return doas_tobe_picked_up
133
    except TransactionServiceException as tex:
134
        print tex.message
135
 
136
def read_dao_pickup_orders(doas_tobe_picked_up):
137
    #uri=http://www.aramex.com/track_xml.asp?ShipperRef=61582&OrgCntry=In&FromDate=2-6-2012&ToDate=2-6-2012
138
    picked_up_doas = {}
139
    for order in doas_tobe_picked_up:
140
        uri = 'http://www.aramex.com/track_xml.asp?ShipperRef=' + str(order.pickupRequestNo) + '&OrgCntry=In&FromDate=' + to_py_date(order.doa_auth_timestamp).strftime("%m-%d-%Y") +'&ToDate=' + datetime.date.today().strftime("%m-%d-%Y")
141
        root = parse(urllib2.urlopen(uri)).getroot()
142
        try:
143
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
144
            if len(nodes):
145
                element = nodes[len(nodes)-1]
146
                if element.findtext('TrackingCodeDescription', '') == 'Shipment Origin Received':
147
                    delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
148
                    picked_up_doas[order.pickupRequestNo] = str(delivery_date)
149
        except:
150
            pass
151
 
152
    print "Picked up DOAs:"
153
    print picked_up_doas
154
    return picked_up_doas
155
 
156
def read_pickup_orders(orders_tobe_picked_up):
157
    try:
158
        config_client = ConfigClient()
159
        ARAMEX_URL = config_client.get_property("aramex_update_url")
160
    except ConfigException as cex:
161
        print cex.message
162
        traceback.print_exc()
163
 
164
    picked_up_orders = {}
165
    for order in orders_tobe_picked_up:
166
        uri = ARAMEX_URL + order.airwaybill_no
167
        root = parse(urllib2.urlopen(uri)).getroot()
168
        try:
169
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
170
            if len(nodes):
171
                element = nodes[len(nodes)-1]
172
                if element.findtext('TrackingCodeDescription', '') == 'Shipment Origin Received':
173
                    delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
174
                    picked_up_orders[order.airwaybill_no] = str(delivery_date)
175
        except:
176
            pass
177
 
178
    print "Picked up Orders:"
179
    print picked_up_orders
180
    return picked_up_orders
181
 
182
def read_delivery_orders(orders_tobe_delivered):
183
    try:
184
        config_client = ConfigClient()
185
        ARAMEX_URL = config_client.get_property("aramex_update_url")
186
    except ConfigException as cex:
187
        print cex.message
188
        traceback.print_exc()
189
 
190
    delivered_orders = {}
191
    returned_orders = {}
192
    undelivered_orders = {}
193
    for order in orders_tobe_delivered:
194
        uri = ARAMEX_URL + order.airwaybill_no
195
        root = parse(urllib2.urlopen(uri)).getroot()
196
        try:
197
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
198
            if len(nodes):
199
                i = len(nodes)-1
200
                while i>=0:
201
                    element = nodes[i]
202
                    if element.findtext('TrackingCodeDescription', '') == 'Shipment Delivered':
203
                        delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
204
                        receiver = root.findtext('HAWBDetails/DeliveredTo', '')
205
                        delivered_orders[order.airwaybill_no] = str(delivery_date) + "|" +  receiver
206
                        break
207
                    elif element.findtext('TrackingCodeDescription', '') == 'Shipment Release Hold':
208
                        delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
209
                        if i < len(nodes)-1:
210
                            reason_for_return = nodes[i+1].findtext('CustomerDescription', '')
211
                        else:
212
                            reason_for_return = element.findtext('CustomerDescription', '')
213
                        returned_orders[order.airwaybill_no] = str(delivery_date) + "|" + reason_for_return
214
                        break
215
                    elif i == 0:
216
                        reason = element.findtext('TrackingCodeDescription', '')
217
                        undelivered_orders[order.airwaybill_no] = reason
218
                        break
219
                    i = i-1
220
        except:
221
            pass
222
 
223
    print "Delivered Orders:"
224
    print delivered_orders
225
 
226
    print "Returned Orders:"
227
    print returned_orders
228
 
229
    print "Undelivered Orders"
230
    print undelivered_orders
231
 
232
    return delivered_orders, returned_orders, undelivered_orders
233
 
234
def update_picked_orders(provider_id, pickup_details):
235
    txnClient = TransactionClient().get_client()
236
    try:
237
        orders_not_picked_up = txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
238
        return orders_not_picked_up
239
    except TransactionServiceException as tex:
240
        print tex.message
241
 
242
def update_picked_doas(provider_id, doa_pickup_details):
243
    txnClient = TransactionClient().get_client()
244
    try:
245
        doas_not_picked_up = txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
246
        return doas_not_picked_up
247
    except TransactionServiceException as tex:
248
        print tex.message
249
 
250
def update_delivered_orders(provider_id, delivered_orders):
251
    txnClient = TransactionClient().get_client()
252
    try:
253
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
254
    except TransactionServiceException as tex:
255
        print tex.message
256
 
257
def update_returned_orders(provider_id, returned_orders):
258
    txnClient = TransactionClient().get_client()
259
    try:
260
        txnClient.markOrdersAsFailed(provider_id, returned_orders)
261
    except TransactionServiceException as tex:
262
        print tex.message
263
 
264
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
265
    txnClient = TransactionClient().get_client()
266
    try:
267
        txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
268
    except TransactionServiceException as tex:
269
        print tex.message
270
 
271
def print_pickup_mismatch_report(filename, orders):
272
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
273
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
274
    for order in orders:
275
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
276
 
277
def print_rto_orders_report(filename, returned_orders):
278
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
279
    writer.writerow(['AWB No', 'Return date', 'Reason'])
280
    for awb, date_reason in returned_orders.iteritems():
281
        date, reason = date_reason.split('|')
282
        writer.writerow([awb, date, reason])
283
 
284
def get_py_datetime(time_string):
285
    # This should be a command line argument.
286
    # Refer http://docs.python.org/library/time.html#time.strftime to
287
    # get a complete list of format specifiers available for date time.
288
    time_format = "%m/%d/%Y %I:%M:%S %p"
289
    if time_string == '':
290
        return None
291
    mytime = time.strptime(time_string, time_format)
292
    return datetime.datetime(*mytime[:6])
293
 
294
def main():
295
    parser = optparse.OptionParser()
296
    parser.add_option("-e", "--doa", dest="doa_report",
297
                   action="store_true",
298
                   help="Run the DOA pickup reconciliation")
299
    parser.add_option("-p", "--pickup", dest="pickup_report",
300
                   action="store_true",
301
                   help="Run the pickup reconciliation")
302
    parser.add_option("-d", "--delivery", dest="delivery_report",
303
                   action="store_true",
304
                   help="Run the delivery reconciliation")
305
    parser.add_option("-a", "--all", dest="all_reports",
306
                   action="store_true",
307
                   help="Run all reconciliations")
308
    parser.add_option("-P", "--provider", dest="provider",
309
                   default="BlueDart", type="string",
310
                   help="The PROVIDER this report is for",
311
                   metavar="PROVIDER")
312
    parser.set_defaults(doa_report=False, pickup_report=False, delivery_report=False, all_reports=False)
313
    (options, args) = parser.parse_args()
314
    if len(args) != 0:
315
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
316
 
317
    if options.all_reports:
318
        options.doa_report = True
319
        options.pickup_report = True
320
        options.delivery_report = True
321
 
322
    provider = get_provider_by_name(options.provider)
323
 
324
    if options.doa_report:
325
        process_dao_pickup_orders(provider)
326
    if options.pickup_report:
327
        process_pickup_records(provider)
328
    if options.delivery_report:
329
        process_delivery_report(provider)
330
 
331
if __name__ == '__main__':
332
    main()