Subversion Repositories SmartDukaan

Rev

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