Subversion Repositories SmartDukaan

Rev

Rev 4506 | Rev 4540 | 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)
92
        delivered_orders, returned_orders, undelivered_orders = read_delivery_orders(orders_tobe_delivered)
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()
110
    except:
111
        print "Some issue while processing the returned orders"
112
        traceback.print_exc()
113
 
114
def get_provider_by_name(provider_name):
115
    logistics_client = LogisticsClient().get_client()
116
    provider = None
117
    providers = logistics_client.getAllProviders()
118
    for p in providers:
119
        if p.name == provider_name:
120
            provider=p
121
            break
122
    if provider == None:
123
        sys.exit("Can't continue execution: No such provider")
124
    return provider
125
 
126
def fetch_data(provider_id, order_status):
127
    txnClient = TransactionClient().get_client()
128
    try:
129
        doas_tobe_picked_up = txnClient.getOrdersForProviderForStatus(provider_id, order_status)
130
        return doas_tobe_picked_up
131
    except TransactionServiceException as tex:
132
        print tex.message
133
 
134
def read_dao_pickup_orders(doas_tobe_picked_up):
135
    #uri=http://www.aramex.com/track_xml.asp?ShipperRef=61582&OrgCntry=In&FromDate=2-6-2012&ToDate=2-6-2012
136
    picked_up_doas = {}
137
    for order in doas_tobe_picked_up:
138
        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")
139
        root = parse(urllib2.urlopen(uri)).getroot()
140
        try:
141
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
142
            if len(nodes):
143
                element = nodes[len(nodes)-1]
144
                if element.findtext('TrackingCodeDescription', '') == 'Shipment Origin Received':
145
                    delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
146
                    picked_up_doas[order.pickupRequestNo] = str(delivery_date)
147
        except:
148
            pass
149
 
150
    print "Picked up DOAs:"
151
    print picked_up_doas
152
    return picked_up_doas
153
 
154
def read_pickup_orders(orders_tobe_picked_up):
155
    try:
156
        config_client = ConfigClient()
157
        ARAMEX_URL = config_client.get_property("aramex_update_url")
158
    except ConfigException as cex:
159
        print cex.message
160
        traceback.print_exc()
161
 
162
    picked_up_orders = {}
163
    for order in orders_tobe_picked_up:
164
        uri = ARAMEX_URL + order.airwaybill_no
165
        root = parse(urllib2.urlopen(uri)).getroot()
166
        try:
167
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
168
            if len(nodes):
169
                element = nodes[len(nodes)-1]
170
                if element.findtext('TrackingCodeDescription', '') == 'Shipment Origin Received':
171
                    delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
172
                    picked_up_orders[order.airwaybill_no] = str(delivery_date)
173
        except:
174
            pass
175
 
176
    print "Picked up Orders:"
177
    print picked_up_orders
178
    return picked_up_orders
179
 
180
def read_delivery_orders(orders_tobe_delivered):
181
    try:
182
        config_client = ConfigClient()
183
        ARAMEX_URL = config_client.get_property("aramex_update_url")
184
    except ConfigException as cex:
185
        print cex.message
186
        traceback.print_exc()
187
 
188
    delivered_orders = {}
189
    returned_orders = {}
190
    undelivered_orders = {}
191
    for order in orders_tobe_delivered:
192
        uri = ARAMEX_URL + order.airwaybill_no
193
        root = parse(urllib2.urlopen(uri)).getroot()
194
        try:
195
            nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')
196
            if len(nodes):
197
                i = len(nodes)-1
198
                while i>=0:
199
                    element = nodes[i]
200
                    if element.findtext('TrackingCodeDescription', '') == 'Shipment Delivered':
201
                        delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
202
                        receiver = root.findtext('HAWBDetails/DeliveredTo', '')
203
                        delivered_orders[order.airwaybill_no] = str(delivery_date) + "|" +  receiver
204
                        break
205
                    elif element.findtext('TrackingCodeDescription', '') == 'Shipment Release Hold':
206
                        delivery_date = get_py_datetime(element.findtext('ActionDate', ''))
207
                        if i < len(nodes)-1:
208
                            reason_for_return = nodes[i+1].findtext('CustomerDescription', '')
209
                        else:
210
                            reason_for_return = element.findtext('CustomerDescription', '')
211
                        returned_orders[order.airwaybill_no] = str(delivery_date) + "|" + reason_for_return
212
                        break
213
                    elif i == 0:
214
                        reason = element.findtext('TrackingCodeDescription', '')
215
                        undelivered_orders[order.airwaybill_no] = reason
216
                        break
217
                    i = i-1
218
        except:
219
            pass
220
 
221
    print "Delivered Orders:"
222
    print delivered_orders
223
 
224
    print "Returned Orders:"
225
    print returned_orders
226
 
227
    print "Undelivered Orders"
228
    print undelivered_orders
229
 
230
    return delivered_orders, returned_orders, undelivered_orders
231
 
232
def update_picked_orders(provider_id, pickup_details):
233
    txnClient = TransactionClient().get_client()
234
    try:
235
        orders_not_picked_up = txnClient.markOrdersAsPickedUp(provider_id, pickup_details)
236
        return orders_not_picked_up
237
    except TransactionServiceException as tex:
238
        print tex.message
239
 
240
def update_picked_doas(provider_id, doa_pickup_details):
241
    txnClient = TransactionClient().get_client()
242
    try:
243
        doas_not_picked_up = txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)
244
        return doas_not_picked_up
245
    except TransactionServiceException as tex:
246
        print tex.message
247
 
248
def update_delivered_orders(provider_id, delivered_orders):
249
    txnClient = TransactionClient().get_client()
250
    try:
251
        txnClient.markOrdersAsDelivered(provider_id, delivered_orders)
252
    except TransactionServiceException as tex:
253
        print tex.message
254
 
255
def update_returned_orders(provider_id, returned_orders):
256
    txnClient = TransactionClient().get_client()
257
    try:
258
        txnClient.markOrdersAsFailed(provider_id, returned_orders)
259
    except TransactionServiceException as tex:
260
        print tex.message
261
 
262
def update_reason_of_undelivered_orders(provider_id, undelivered_orders):
263
    txnClient = TransactionClient().get_client()
264
    try:
265
        txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)
266
    except TransactionServiceException as tex:
267
        print tex.message
268
 
269
def print_pickup_mismatch_report(filename, orders):
270
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
271
    writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])
272
    for order in orders:
273
        writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])
274
 
275
def print_rto_orders_report(filename, returned_orders):
276
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)
277
    writer.writerow(['AWB No', 'Return date', 'Reason'])
278
    for awb, date_reason in returned_orders.iteritems():
279
        date, reason = date_reason.split('|')
280
        writer.writerow([awb, date, reason])
281
 
282
def get_py_datetime(time_string):
283
    # This should be a command line argument.
284
    # Refer http://docs.python.org/library/time.html#time.strftime to
285
    # get a complete list of format specifiers available for date time.
286
    time_format = "%m/%d/%Y %I:%M:%S %p"
287
    if time_string == '':
288
        return None
289
    mytime = time.strptime(time_string, time_format)
290
    return datetime.datetime(*mytime[:6])
291
 
292
def main():
293
    parser = optparse.OptionParser()
294
    parser.add_option("-e", "--doa", dest="doa_report",
295
                   action="store_true",
296
                   help="Run the DOA pickup reconciliation")
297
    parser.add_option("-p", "--pickup", dest="pickup_report",
298
                   action="store_true",
299
                   help="Run the pickup reconciliation")
300
    parser.add_option("-d", "--delivery", dest="delivery_report",
301
                   action="store_true",
302
                   help="Run the delivery reconciliation")
303
    parser.add_option("-a", "--all", dest="all_reports",
304
                   action="store_true",
305
                   help="Run all reconciliations")
306
    parser.add_option("-P", "--provider", dest="provider",
4508 phani.kuma 307
                   default="Aramex", type="string",
4506 phani.kuma 308
                   help="The PROVIDER this report is for",
309
                   metavar="PROVIDER")
310
    parser.set_defaults(doa_report=False, pickup_report=False, delivery_report=False, all_reports=False)
311
    (options, args) = parser.parse_args()
312
    if len(args) != 0:
313
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
314
 
315
    if options.all_reports:
316
        options.doa_report = True
317
        options.pickup_report = True
318
        options.delivery_report = True
319
 
320
    provider = get_provider_by_name(options.provider)
321
 
322
    if options.doa_report:
323
        process_dao_pickup_orders(provider)
324
    if options.pickup_report:
325
        process_pickup_records(provider)
326
    if options.delivery_report:
327
        process_delivery_report(provider)
328
 
329
if __name__ == '__main__':
330
    main()