Subversion Repositories SmartDukaan

Rev

Rev 4540 | Rev 4581 | Go to most recent revision | Details | Compare with Previous | 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
 
49
def process_dao_pickup_orders(provider):
50
    try:
4559 phani.kuma 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
    except:
70
        print "Some issue while processing the orders in DOA_PICKUP_CONFIRMED status"
4506 phani.kuma 71
        traceback.print_exc()
72
 
73
def process_pickup_records(provider):
74
    try:
4559 phani.kuma 75
        orders_tobe_picked_up = fetch_data(provider.id, OrderStatus.SHIPPED_FROM_WH)
76
        pickup_details = read_pickup_orders(orders_tobe_picked_up)
77
        orders_not_picked_up = update_picked_orders(provider.id, pickup_details)
78
        try:
79
            if orders_not_picked_up:
80
                print "Orders not Picked up:"
81
                print orders_not_picked_up
82
                mismatch_file = "/tmp/PickupMismatch.csv"
83
                print "Some of our orders were not picked up. Printing report to:" + mismatch_file
84
                print_pickup_mismatch_report(mismatch_file, orders_not_picked_up)
85
                pickup_mismatch_part = [get_attachment_part(mismatch_file)]
86
                mail(from_user, from_pwd, to,\
87
                     "Order Pickup Mismatch for " + provider.name,\
88
                     "This is a system generated email.Please don't reply to it.",\
89
                     pickup_mismatch_part)
90
        except Exception:
91
            print "Some issue sending the pickup mismatch report"
92
            traceback.print_exc()
93
    except:
94
        print "Some issue while processing the orders in SHIPPED_FROM_WH status"
4506 phani.kuma 95
        traceback.print_exc()
96
 
97
def process_delivery_report(provider):
98
    try:
99
        orders_tobe_delivered = fetch_data(provider.id, OrderStatus.SHIPPED_TO_LOGST)
4540 phani.kuma 100
        delivered_orders, delivered_orders_but_wrong_code_mentioned, returned_orders, undelivered_orders = read_delivery_orders(orders_tobe_delivered)
4506 phani.kuma 101
        if undelivered_orders:
102
            update_reason_of_undelivered_orders(provider.id, undelivered_orders)
103
        if delivered_orders:
104
            update_delivered_orders(provider.id, delivered_orders)
105
        if returned_orders:
106
            update_returned_orders(provider.id, returned_orders)
107
            try:
108
                returned_orders_file = "/tmp/ReturnedOrders.csv"
109
                print_rto_orders_report(returned_orders_file, returned_orders)
110
                returned_orders_report = [get_attachment_part(returned_orders_file)]
111
                mail(from_user, from_pwd, to,\
112
                     "Returned Orders Report for " + provider.name,\
113
                     "This is a system generated email.Please don't reply to it.",\
114
                     returned_orders_report)
115
            except:
116
                print "Some issue sending the returned orders report"
117
                traceback.print_exc()
4540 phani.kuma 118
        if delivered_orders_but_wrong_code_mentioned:
119
            try:
120
                delivered_orders_but_wrong_code_mentioned_file = "/tmp/delivered_orders_but_wrong_code.csv"
121
                print_delivered_orders_but_wrong_code_mentioned_report(delivered_orders_but_wrong_code_mentioned_file, delivered_orders_but_wrong_code_mentioned)
122
                delivered_orders_but_wrong_code_mentioned_report = [get_attachment_part(delivered_orders_but_wrong_code_mentioned_file)]
123
                mail(from_user, from_pwd, to,\
124
                     "Delivered Orders but Wrong Code Mentioned Report for " + provider.name,\
125
                     "This is a system generated email.Please don't reply to it.",\
126
                     delivered_orders_but_wrong_code_mentioned_report)
127
            except:
128
                print "Some issue sending the delivered orders but wrong code mentioned report"
129
                traceback.print_exc()            
4506 phani.kuma 130
    except:
4540 phani.kuma 131
        print "Some issue while processing the orders in SHIPPED_TO_LOGST status"
4506 phani.kuma 132
        traceback.print_exc()
133
 
134
def get_provider_by_name(provider_name):
135
    logistics_client = LogisticsClient().get_client()
136
    provider = None
137
    providers = logistics_client.getAllProviders()
138
    for p in providers:
139
        if p.name == provider_name:
140
            provider=p
141
            break
142
    if provider == None:
143
        sys.exit("Can't continue execution: No such provider")
144
    return provider
145
 
146
def fetch_data(provider_id, order_status):
147
    txnClient = TransactionClient().get_client()
148
    try:
149
        doas_tobe_picked_up = txnClient.getOrdersForProviderForStatus(provider_id, order_status)
150
        return doas_tobe_picked_up
151
    except TransactionServiceException as tex:
152
        print tex.message
153
 
154
def read_dao_pickup_orders(doas_tobe_picked_up):
155
    #uri=http://www.aramex.com/track_xml.asp?ShipperRef=61582&OrgCntry=In&FromDate=2-6-2012&ToDate=2-6-2012
156
    picked_up_doas = {}
157
    for order in doas_tobe_picked_up:
158
        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")
159
        root = parse(urllib2.urlopen(uri)).getroot()
160
        try:
161
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
162
            if len(nodes):
163
                element = nodes[len(nodes)-1]
4540 phani.kuma 164
                if element.findtext('Status', '') == 'SHOR' and element.findtext('Condition', '') == 'PKUP':
4506 phani.kuma 165
                    delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
166
                    picked_up_doas[order.pickupRequestNo] = str(delivery_date)
167
        except:
168
            pass
169
 
170
    print "Picked up DOAs:"
171
    print picked_up_doas
172
    return picked_up_doas
173
 
174
def read_pickup_orders(orders_tobe_picked_up):
175
    try:
176
        config_client = ConfigClient()
177
        ARAMEX_URL = config_client.get_property("aramex_update_url")
178
    except ConfigException as cex:
179
        print cex.message
180
        traceback.print_exc()
181
 
182
    picked_up_orders = {}
183
    for order in orders_tobe_picked_up:
184
        uri = ARAMEX_URL + order.airwaybill_no
185
        root = parse(urllib2.urlopen(uri)).getroot()
186
        try:
187
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
188
            if len(nodes):
189
                element = nodes[len(nodes)-1]
4540 phani.kuma 190
                if element.findtext('Status', '') == 'SHOR' and element.findtext('Condition', '') == 'PKUP':
4506 phani.kuma 191
                    delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
192
                    picked_up_orders[order.airwaybill_no] = str(delivery_date)
193
        except:
194
            pass
195
 
196
    print "Picked up Orders:"
197
    print picked_up_orders
198
    return picked_up_orders
199
 
200
def read_delivery_orders(orders_tobe_delivered):
201
    try:
202
        config_client = ConfigClient()
203
        ARAMEX_URL = config_client.get_property("aramex_update_url")
204
    except ConfigException as cex:
205
        print cex.message
206
        traceback.print_exc()
207
 
208
    delivered_orders = {}
4540 phani.kuma 209
    delivered_orders_but_wrong_code_mentioned = {}
4506 phani.kuma 210
    returned_orders = {}
211
    undelivered_orders = {}
212
    for order in orders_tobe_delivered:
213
        uri = ARAMEX_URL + order.airwaybill_no
214
        root = parse(urllib2.urlopen(uri)).getroot()
215
        try:
216
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
217
            if len(nodes):
218
                i = len(nodes)-1
219
                while i>=0:
220
                    element = nodes[i]
4540 phani.kuma 221
                    if element.findtext('Status', '') == 'SHDL' and (element.findtext('Condition', '') == 'DLVD' or element.findtext('Condition', '') == 'DPTT' or element.findtext('Condition', '') == 'DLPT' or element.findtext('Condition', '') == 'LTRB'):
4506 phani.kuma 222
                        delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
223
                        receiver = root.findtext('HAWBDetails/DeliveredTo', '')
224
                        delivered_orders[order.airwaybill_no] = str(delivery_date) + "|" +  receiver
4540 phani.kuma 225
                        if element.findtext('Condition', '') != 'DLVD':
226
                            delivered_orders_but_wrong_code_mentioned[order.airwaybill_no] = element.findtext('Condition', '')
4506 phani.kuma 227
                        break
4540 phani.kuma 228
                    elif element.findtext('Condition', '') == 'RTRN' and (element.findtext('Status', '') == 'SHRH' or element.findtext('Status', '') == 'SHUP'):
4506 phani.kuma 229
                        delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
230
                        if i < len(nodes)-1:
231
                            reason_for_return = nodes[i+1].findtext('CustomerDescription', '')
232
                        else:
233
                            reason_for_return = element.findtext('CustomerDescription', '')
234
                        returned_orders[order.airwaybill_no] = str(delivery_date) + "|" + reason_for_return
235
                        break
236
                    elif i == 0:
4540 phani.kuma 237
                        reason = root.findtext('CurrentStatus', '')
4506 phani.kuma 238
                        undelivered_orders[order.airwaybill_no] = reason
239
                        break
240
                    i = i-1
241
        except:
242
            pass
243
 
244
    print "Delivered Orders:"
245
    print delivered_orders
246
 
4540 phani.kuma 247
    print "Delivered Orders but wrong code mentioned:"
248
    print delivered_orders_but_wrong_code_mentioned
249
 
4506 phani.kuma 250
    print "Returned Orders:"
251
    print returned_orders
252
 
253
    print "Undelivered Orders"
254
    print undelivered_orders
255
 
4540 phani.kuma 256
    return delivered_orders, delivered_orders_but_wrong_code_mentioned, returned_orders, undelivered_orders
4506 phani.kuma 257
 
258
def update_picked_orders(provider_id, pickup_details):
259
    txnClient = TransactionClient().get_client()
260
    try:
261
        orders_not_picked_up = txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
262
        return orders_not_picked_up
263
    except TransactionServiceException as tex:
264
        print tex.message
265
 
266
def update_picked_doas(provider_id, doa_pickup_details):
267
    txnClient = TransactionClient().get_client()
268
    try:
269
        doas_not_picked_up = txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
270
        return doas_not_picked_up
271
    except TransactionServiceException as tex:
272
        print tex.message
273
 
274
def update_delivered_orders(provider_id, delivered_orders):
275
    txnClient = TransactionClient().get_client()
276
    try:
277
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
278
    except TransactionServiceException as tex:
279
        print tex.message
280
 
281
def update_returned_orders(provider_id, returned_orders):
282
    txnClient = TransactionClient().get_client()
283
    try:
284
        txnClient.markOrdersAsFailed(provider_id, returned_orders)
285
    except TransactionServiceException as tex:
286
        print tex.message
287
 
288
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
289
    txnClient = TransactionClient().get_client()
290
    try:
291
        txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
292
    except TransactionServiceException as tex:
293
        print tex.message
294
 
295
def print_pickup_mismatch_report(filename, orders):
296
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
297
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
298
    for order in orders:
299
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
300
 
301
def print_rto_orders_report(filename, returned_orders):
302
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
303
    writer.writerow(['AWB No', 'Return date', 'Reason'])
304
    for awb, date_reason in returned_orders.iteritems():
305
        date, reason = date_reason.split('|')
306
        writer.writerow([awb, date, reason])
307
 
4540 phani.kuma 308
def print_delivered_orders_but_wrong_code_mentioned_report(filename, delivered_orders_but_wrong_code_mentioned):
309
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
310
    writer.writerow(['AWB No', 'Code Used'])
311
    for awb, code_used in delivered_orders_but_wrong_code_mentioned.iteritems():
312
        writer.writerow([awb, code_used])
313
 
4506 phani.kuma 314
def get_py_datetime(time_string):
315
    # This should be a command line argument.
316
    # Refer http://docs.python.org/library/time.html#time.strftime to
317
    # get a complete list of format specifiers available for date time.
318
    time_format = "%m/%d/%Y %I:%M:%S %p"
319
    if time_string == '':
320
        return None
321
    mytime = time.strptime(time_string, time_format)
322
    return datetime.datetime(*mytime[:6])
323
 
324
def main():
325
    parser = optparse.OptionParser()
326
    parser.add_option("-e", "--doa", dest="doa_report",
327
                   action="store_true",
328
                   help="Run the DOA pickup reconciliation")
329
    parser.add_option("-p", "--pickup", dest="pickup_report",
330
                   action="store_true",
331
                   help="Run the pickup reconciliation")
332
    parser.add_option("-d", "--delivery", dest="delivery_report",
333
                   action="store_true",
334
                   help="Run the delivery reconciliation")
335
    parser.add_option("-a", "--all", dest="all_reports",
336
                   action="store_true",
337
                   help="Run all reconciliations")
338
    parser.add_option("-P", "--provider", dest="provider",
4508 phani.kuma 339
                   default="Aramex", type="string",
4506 phani.kuma 340
                   help="The PROVIDER this report is for",
341
                   metavar="PROVIDER")
342
    parser.set_defaults(doa_report=False, pickup_report=False, delivery_report=False, all_reports=False)
343
    (options, args) = parser.parse_args()
344
    if len(args) != 0:
345
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
346
 
347
    if options.all_reports:
348
        options.doa_report = True
349
        options.pickup_report = True
350
        options.delivery_report = True
351
 
352
    provider = get_provider_by_name(options.provider)
353
 
354
    if options.doa_report:
355
        process_dao_pickup_orders(provider)
356
    if options.pickup_report:
357
        process_pickup_records(provider)
358
    if options.delivery_report:
359
        process_delivery_report(provider)
360
 
361
if __name__ == '__main__':
362
    main()