Rev 4760 | Rev 4792 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#!/usr/bin/python'''It processes the following orders:1. Orders in DOA_PICKUP_CONFIRMED status : get details of orders thatwere in DOA_PICKUP_CONFIRMED status from database andcalls aramex api to know whether they are picked up by armaexand changes the status to DOA_RETURN_IN_TRANSIT if it is done.2. Orders in RET_PICKUP_CONFIRMED status : get details of orders thatwere in RET_PICKUP_CONFIRMED status from database andcalls aramex api to know whether they are picked up by armaexand changes the status to RET_RETURN_IN_TRANSIT if it is done.3. Orders in SHIPPED_FROM_WH status: get details of orders thatwere in SHIPPED_FROM_WH status from database andcalls aramex api to know whether they are picked up by armaexand changes the status to SHIPPED_TO_LOGST if it is done.4. Orders in SHIPPED_TO_LOGST status: get details of orders thatwere in SHIPPED_TO_LOGST status from database andcalls aramex api to know their status and changes the status accordingly.It sends out a Pickup mismatch report, Return orders Pickup Mismatch report, Doa Pickup mismatch report,Undelivered orders report and Returned Orders report to cnc.center@shop2020.inhttp://www.aramex.com/track_xml.asp?ShipperRef={variable1}&OrgCntry=In&FromDate={variable2}&ToDate={variable3} is hard codedto track DOA orders and for other orders ConfigClient is called to get aramex_update_url@author: Phani Kumar'''import timeimport datetimeimport optparseimport sysimport csvimport tracebackimport urllib2from xml.etree.ElementTree import parseif __name__ == '__main__' and __package__ is None:import ossys.path.insert(0, os.getcwd())from shop2020.clients.LogisticsClient import LogisticsClientfrom shop2020.clients.TransactionClient import TransactionClientfrom shop2020.config.client.ConfigClient import ConfigClientfrom shop2020.thriftpy.config.ttypes import ConfigExceptionfrom shop2020.thriftpy.model.v1.order.ttypes import TransactionServiceException, OrderStatusfrom shop2020.utils.EmailAttachmentSender import get_attachment_part, mailfrom shop2020.utils.Utils import to_py_datefrom_user = 'cnc.center@shop2020.in'from_pwd = '5h0p2o2o'to = ['cnc.center@shop2020.in', "suraj.sharma@shop2020.in", "sandeep.sachdeva@shop2020.in", "manoj.kumar@shop2020.in"]def process_dao_pickup_orders(provider):try:doas_tobe_picked_up = fetch_data(provider.id, OrderStatus.DOA_PICKUP_CONFIRMED)doa_pickup_details = read_dao_return_pickup_orders(doas_tobe_picked_up)doas_not_picked_up = update_picked_doas(provider.id, doa_pickup_details)try:if doas_not_picked_up:print "DOAs not Picked up:"print doas_not_picked_upmismatch_file = "/tmp/DoaPickupMismatch.csv"print "Some of our DOA orders were not picked up. Printing report to:" + mismatch_fileprint_dao_return_pickup_mismatch_report(mismatch_file, doas_not_picked_up)pickup_mismatch_part = [get_attachment_part(mismatch_file)]mail(from_user, from_pwd, to,\"DOA Pickup Mismatch for " + provider.name,\"This is a system generated email.Please don't reply to it.",\pickup_mismatch_part)except Exception:print "Some issue sending the DOA mismatch report"traceback.print_exc()except:print "Some issue while processing the orders in DOA_PICKUP_CONFIRMED status"traceback.print_exc()def process_return_pickup_orders(provider):try:returns_tobe_picked_up = fetch_data(provider.id, OrderStatus.RET_PICKUP_CONFIRMED)returns_pickup_details = read_dao_return_pickup_orders(returns_tobe_picked_up)returns_not_picked_up = update_picked_returns(provider.id, returns_pickup_details)try:if returns_not_picked_up:print "Return Orders not Picked up:"print returns_not_picked_upmismatch_file = "/tmp/ReturnsPickupMismatch.csv"print "Some of our Return orders were not picked up. Printing report to:" + mismatch_fileprint_dao_return_pickup_mismatch_report(mismatch_file, returns_not_picked_up)pickup_mismatch_part = [get_attachment_part(mismatch_file)]mail(from_user, from_pwd, to,\"Return orders Pickup Mismatch for " + provider.name,\"This is a system generated email.Please don't reply to it.",\pickup_mismatch_part)except Exception:print "Some issue sending the Return orders mismatch report"traceback.print_exc()except:print "Some issue while processing the orders in RET_PICKUP_CONFIRMED status"traceback.print_exc()def process_pickup_records(provider):try:orders_tobe_picked_up = fetch_data(provider.id, OrderStatus.SHIPPED_FROM_WH)pickup_details = read_pickup_orders(orders_tobe_picked_up)orders_not_picked_up = update_picked_orders(provider.id, pickup_details)try:if orders_not_picked_up:print "Orders not Picked up:"print orders_not_picked_upmismatch_file = "/tmp/PickupMismatch.csv"print "Some of our orders were not picked up. Printing report to:" + mismatch_fileprint_pickup_mismatch_report(mismatch_file, orders_not_picked_up)pickup_mismatch_part = [get_attachment_part(mismatch_file)]mail(from_user, from_pwd, to,\"Order Pickup Mismatch for " + provider.name,\"This is a system generated email.Please don't reply to it.",\pickup_mismatch_part)except Exception:print "Some issue sending the pickup mismatch report"traceback.print_exc()except:print "Some issue while processing the orders in SHIPPED_FROM_WH status"traceback.print_exc()def process_delivery_report(provider):try:orders_tobe_delivered = fetch_data(provider.id, OrderStatus.SHIPPED_TO_LOGST)delivered_orders, delivered_orders_but_wrong_code_mentioned, returned_orders, undelivered_orders = read_delivery_orders(orders_tobe_delivered)if delivered_orders:update_delivered_orders(provider.id, delivered_orders)if returned_orders:update_returned_orders(provider.id, returned_orders)try:returned_orders_file = "/tmp/ReturnedOrders.csv"print_rto_orders_report(returned_orders_file, returned_orders)returned_orders_report = [get_attachment_part(returned_orders_file)]mail(from_user, from_pwd, to,\"Returned Orders Report for " + provider.name,\"This is a system generated email.Please don't reply to it.",\returned_orders_report)except:print "Some issue sending the returned orders report"traceback.print_exc()if delivered_orders_but_wrong_code_mentioned:try:delivered_orders_but_wrong_code_mentioned_file = "/tmp/delivered_orders_but_wrong_code.csv"print_delivered_orders_but_wrong_code_mentioned_report(delivered_orders_but_wrong_code_mentioned_file, delivered_orders_but_wrong_code_mentioned)delivered_orders_but_wrong_code_mentioned_report = [get_attachment_part(delivered_orders_but_wrong_code_mentioned_file)]mail(from_user, from_pwd, to,\"Delivered Orders but Wrong Code Mentioned Report for " + provider.name,\"This is a system generated email.Please don't reply to it.",\delivered_orders_but_wrong_code_mentioned_report)except:print "Some issue sending the delivered orders but wrong code mentioned report"traceback.print_exc()try:orders_not_delivered = update_reason_of_undelivered_orders(provider.id, undelivered_orders)if orders_not_delivered:print "Undelivered Orders:"print orders_not_deliveredmismatch_file = "/tmp/UndeliveredOrders.csv"print "Some of our Orders were not delivered. Printing report to:" + mismatch_fileprint_undelivered_orders_report(mismatch_file, orders_not_delivered)pickup_mismatch_part = [get_attachment_part(mismatch_file)]mail(from_user, from_pwd, to,\"Orders that are undelivered but picked up or shipped four days ago for " + provider.name,\"This is a system generated email.Please don't reply to it.",\pickup_mismatch_part)except Exception:print "Some issue updating and sending the undelivered orders report"traceback.print_exc()except:print "Some issue while processing the orders in SHIPPED_TO_LOGST status"traceback.print_exc()def get_provider_by_name(provider_name):logistics_client = LogisticsClient().get_client()provider = Noneproviders = logistics_client.getAllProviders()for p in providers:if p.name == provider_name:provider=pbreakif provider == None:sys.exit("Can't continue execution: No such provider")return providerdef fetch_data(provider_id, order_status):txnClient = TransactionClient().get_client()try:doas_tobe_picked_up = txnClient.getOrdersForProviderForStatus(provider_id, order_status)return doas_tobe_picked_upexcept TransactionServiceException as tex:print tex.messagedef read_dao_return_pickup_orders(orders_tobe_picked_up):#uri=http://www.aramex.com/track_xml.asp?ShipperRef=61582&OrgCntry=In&FromDate=2-6-2012&ToDate=2-6-2012picked_up_orders = {}for order in orders_tobe_picked_up:try: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")root = parse(urllib2.urlopen(uri)).getroot()nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')if len(nodes):element = nodes[len(nodes)-1]if element.findtext('Status', '') == 'SHOR' and element.findtext('Condition', '') == 'PKUP':delivery_date = get_py_datetime(element.findtext('ActionDate', ''))picked_up_orders[order.pickupRequestNo] = str(delivery_date)except:passprint "Picked up Orders:"print picked_up_ordersreturn picked_up_ordersdef read_pickup_orders(orders_tobe_picked_up):try:config_client = ConfigClient()ARAMEX_URL = config_client.get_property("aramex_update_url")except ConfigException as cex:print cex.messagetraceback.print_exc()picked_up_orders = {}for order in orders_tobe_picked_up:try:uri = ARAMEX_URL + order.airwaybill_noroot = parse(urllib2.urlopen(uri)).getroot()nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')if len(nodes):element = nodes[len(nodes)-1]if element.findtext('Status', '') == 'SHOR' and element.findtext('Condition', '') == 'PKUP':delivery_date = get_py_datetime(element.findtext('ActionDate', ''))picked_up_orders[order.airwaybill_no] = str(delivery_date)except:passprint "Picked up Orders:"print picked_up_ordersreturn picked_up_ordersdef read_delivery_orders(orders_tobe_delivered):try:config_client = ConfigClient()ARAMEX_URL = config_client.get_property("aramex_update_url")except ConfigException as cex:print cex.messagetraceback.print_exc()delivered_orders = {}delivered_orders_but_wrong_code_mentioned = {}returned_orders = {}undelivered_orders = {}for order in orders_tobe_delivered:try:uri = ARAMEX_URL + order.airwaybill_noroot = parse(urllib2.urlopen(uri)).getroot()nodes = root.findall('HAWBDetails/HAWBHistory/HAWBUpdate')if len(nodes):i = len(nodes)-1while i>=0:element = nodes[i]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'):delivery_date = get_py_datetime(element.findtext('ActionDate', ''))receiver = root.findtext('HAWBDetails/DeliveredTo', '')delivered_orders[order.airwaybill_no] = str(delivery_date) + "|" + receiverif element.findtext('Condition', '') != 'DLVD':delivered_orders_but_wrong_code_mentioned[order.airwaybill_no] = element.findtext('Condition', '')breakelif element.findtext('Condition', '') == 'RTRN' and (element.findtext('Status', '') == 'SHRH' or element.findtext('Status', '') == 'SHUP'):delivery_date = get_py_datetime(element.findtext('ActionDate', ''))if i < len(nodes)-1:reason_for_return = nodes[i+1].findtext('CustomerDescription', '')else:reason_for_return = element.findtext('CustomerDescription', '')returned_orders[order.airwaybill_no] = str(delivery_date) + "|" + reason_for_returnbreakelif i == 0:reason = root.findtext('HAWBDetails/CurrentStatus', '')undelivered_orders[order.airwaybill_no] = reasonbreaki = i-1except:passprint "Delivered Orders:"print delivered_ordersprint "Delivered Orders but wrong code mentioned:"print delivered_orders_but_wrong_code_mentionedprint "Returned Orders:"print returned_ordersprint "Undelivered Orders"print undelivered_ordersreturn delivered_orders, delivered_orders_but_wrong_code_mentioned, returned_orders, undelivered_ordersdef update_picked_orders(provider_id, pickup_details):txnClient = TransactionClient().get_client()try:orders_not_picked_up = txnClient.markOrdersAsPickedUp(provider_id, pickup_details)return orders_not_picked_upexcept TransactionServiceException as tex:print tex.messagedef update_picked_doas(provider_id, doa_pickup_details):txnClient = TransactionClient().get_client()try:doas_not_picked_up = txnClient.markDoasAsPickedUp(provider_id, doa_pickup_details)return doas_not_picked_upexcept TransactionServiceException as tex:print tex.messagedef update_picked_returns(provider_id, returns_pickup_details):txnClient = TransactionClient().get_client()try:returns_not_picked_up = txnClient.markReturnOrdersAsPickedUp(provider_id, returns_pickup_details)return returns_not_picked_upexcept TransactionServiceException as tex:print tex.messagedef update_delivered_orders(provider_id, delivered_orders):txnClient = TransactionClient().get_client()try:txnClient.markOrdersAsDelivered(provider_id, delivered_orders)except TransactionServiceException as tex:print tex.messagedef update_returned_orders(provider_id, returned_orders):txnClient = TransactionClient().get_client()try:txnClient.markOrdersAsFailed(provider_id, returned_orders)except TransactionServiceException as tex:print tex.messagedef update_reason_of_undelivered_orders(provider_id, undelivered_orders):txnClient = TransactionClient().get_client()try:orders_not_delivered = txnClient.updateNonDeliveryReason(provider_id, undelivered_orders)return orders_not_deliveredexcept TransactionServiceException as tex:print tex.messagedef print_pickup_mismatch_report(filename, orders):writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)writer.writerow(['Order Id', 'AWB No', 'Shipping timestamp'])for order in orders:writer.writerow([order.id, order.airwaybill_no, to_py_date(order.shipping_timestamp)])def print_dao_return_pickup_mismatch_report(filename, orders):writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)writer.writerow(['Order Id', 'Pickup Request No', 'Authorization timestamp'])for order in orders:writer.writerow([order.id, order.pickupRequestNo, to_py_date(order.doa_auth_timestamp)])def print_rto_orders_report(filename, returned_orders):writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)writer.writerow(['AWB No', 'Return date', 'Reason'])for awb, date_reason in returned_orders.iteritems():date, reason = date_reason.split('|')writer.writerow([awb, date, reason])def print_delivered_orders_but_wrong_code_mentioned_report(filename, delivered_orders_but_wrong_code_mentioned):writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)writer.writerow(['AWB No', 'Code Used'])for awb, code_used in delivered_orders_but_wrong_code_mentioned.iteritems():writer.writerow([awb, code_used])def print_undelivered_orders_report(filename, orders):writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_NONE)writer.writerow(['Order Id', 'AWB No', 'Status', 'Status Description', 'Shipping timestamp', 'Pickup timestamp'])for order in orders:writer.writerow([order.id, order.airwaybill_no, order.status, order.statusDescription, to_py_date(order.shipping_timestamp), to_py_date(order.pickup_timestamp)])def get_py_datetime(time_string):# This should be a command line argument.# Refer http://docs.python.org/library/time.html#time.strftime to# get a complete list of format specifiers available for date time.time_format = "%m/%d/%Y %I:%M:%S %p"if time_string == '':return Nonemytime = time.strptime(time_string, time_format)return datetime.datetime(*mytime[:6])def main():parser = optparse.OptionParser()parser.add_option("-p", "--pickup", dest="pickup_report",action="store_true",help="Run the pickup reconciliation")parser.add_option("-d", "--delivery", dest="delivery_report",action="store_true",help="Run the delivery reconciliation")parser.add_option("-a", "--all", dest="all_reports",action="store_true",help="Run all reconciliations")parser.add_option("-P", "--provider", dest="provider",default="Aramex", type="string",help="The PROVIDER this report is for",metavar="PROVIDER")parser.set_defaults(pickup_report=False, delivery_report=False, all_reports=False)(options, args) = parser.parse_args()if len(args) != 0:parser.error("You've supplied extra arguments. Are you sure you want to run this program?")if options.all_reports:options.pickup_report = Trueoptions.delivery_report = Trueprovider = get_provider_by_name(options.provider)if options.pickup_report:process_pickup_records(provider)process_dao_pickup_orders(provider)process_return_pickup_orders(provider)if options.delivery_report:process_delivery_report(provider)if __name__ == '__main__':main()