Rev 2684 | Rev 2697 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
'''Created on 29-Mar-2010@author: Chandranshu'''import sysimport osimport datetimeimport timefrom datetime import datefrom textwrap import dedentfrom string import Templatefrom sqlalchemy.sql.expression import and_, or_, descfrom sqlalchemy.sql import funcfrom elixir import *from reportlab.pdfgen.canvas import Canvasfrom reportlab.rl_config import defaultPageSizefrom reportlab.lib.units import inchPAGE_HEIGHT=defaultPageSize[1]PAGE_WIDTH=defaultPageSize[0]from shop2020.model.v1.order.impl.model.ReturnOrder import ReturnOrderfrom shop2020.model.v1.order.impl.DataService import Transaction, LineItem,\Alerts, Order, BatchNoGeneratorfrom shop2020.thriftpy.model.v1.order.ttypes import Transaction as T_Transaction,\TransactionServiceException, TransactionStatus, OrderStatusfrom shop2020.utils.Utils import to_py_date, to_java_datefrom shop2020.model.v1 import orderfrom shop2020.clients.LogisticsClient import LogisticsClientfrom shop2020.clients.InventoryClient import InventoryClientfrom shop2020.clients.UserClient import UserClientfrom shop2020.clients.HelperClient import HelperClientfrom shop2020.utils.EmailAttachmentSender import mail, get_attachment_partdef get_new_transaction():transaction = Transaction()transaction.createdOn = datetime.datetime.now()transaction.status = TransactionStatus.INITtransaction.status_message = "New transaction"return transactiondef create_order(t_order):order = Order()if t_order.warehouse_id:order.warehouse_id = t_order.warehouse_idif t_order.logistics_provider_id:order.logistics_provider_id = t_order.logistics_provider_idorder.airwaybill_no = t_order.airwaybill_noorder.tracking_id = t_order.tracking_idif t_order.expected_delivery_time:order.expected_delivery_time = to_py_date(t_order.expected_delivery_time)if t_order.customer_id:order.customer_id = t_order.customer_idorder.customer_name = t_order.customer_nameorder.customer_city = t_order.customer_cityorder.customer_state = t_order.customer_stateorder.customer_mobilenumber = t_order.customer_mobilenumberorder.customer_pincode = t_order.customer_pincodeorder.customer_address1 = t_order.customer_address1order.customer_address2 = t_order.customer_address2order.customer_email = t_order.customer_email#new status and status description to be addedorder.status = t_order.statusorder.statusDescription = t_order.statusDescriptionorder.total_amount = t_order.total_amountorder.total_weight = t_order.total_weightif t_order.created_timestamp:order.created_timestamp = to_py_date(t_order.created_timestamp)else:order.created_timestamp = datetime.datetime.now()return orderdef create_transaction(t_transaction):t_orders = t_transaction.ordersif not t_orders:raise TransactionServiceException(101, "Orders missing from the transaction")transaction = get_new_transaction()transaction.customer_id = t_transaction.customer_idtransaction.shopping_cart_id = t_transaction.shoppingCartidtransaction.coupon_code = t_transaction.coupon_codefor t_order in t_orders:order = create_order(t_order)order.transaction = transactionfor line_item in t_order.lineitems:litem = LineItem()litem.item_id = line_item.item_idlitem.productGroup = line_item.productGrouplitem.brand = line_item.brandif line_item.model_number:litem.model_number = line_item.model_numberif line_item.model_name:litem.model_name = line_item.model_nameif line_item.color:litem.color = line_item.colorif line_item.extra_info:litem.extra_info = line_item.extra_infolitem.quantity = line_item.quantitylitem.unit_price = line_item.unit_pricelitem.unit_weight = line_item.unit_weightlitem.total_price = line_item.total_pricelitem.total_weight = line_item.total_weightlitem.transfer_price = line_item.transfer_price"""if line_item.addedOn:litem.added_on = to_py_date(line_item.addedOn)else:litem.added_on = datetime.datetime.now()"""litem.order = ordersession.commit()return transaction.iddef get_transaction(transaction_id):transaction = Transaction.get_by(id=transaction_id)if not transaction:raise TransactionServiceException(108, "no such transaction")return transactiondef get_transactions_for_customer(customer_id, from_date, to_date, status):if not customer_id:raise TransactionServiceException(101, "bad customer id")query = Transaction.query.filter(Transaction.customer_id == customer_id)if status is not None:query = query.filter(Transaction.status == status)if from_date:query = query.filter(Transaction.createdOn >from_date)if to_date:query = query.filter(Transaction.createdOn < to_date)return query.all()def get_transactions_for_shopping_cart_id(shopping_cart_id):transactions = Transaction.query.filter_by(shopping_cart_id=shopping_cart_id).all()return transactionsdef get_transaction_status(transaction_id):if not transaction_id:raise TransactionServiceException(101, "bad transaction id")transaction = get_transaction(transaction_id)return transaction.statusdef change_transaction_status(transaction_id, new_status, description):transaction = get_transaction(transaction_id)transaction.status = new_statustransaction.status_message = descriptionif new_status == TransactionStatus.FAILED:for order in transaction.orders:order.status = OrderStatus.PAYMENT_FAILEDorder.statusDescription = "Payment Failed"elif new_status == TransactionStatus.IN_PROCESS:for order in transaction.orders:order.status = OrderStatus.SUBMITTED_FOR_PROCESSINGorder.statusDescription = "Submitted to warehouse"#After we got payment success, we will set logistics info alsologistics_client = LogisticsClient().get_client()#FIXME line item is only one now. If multiple will come, need to fix.item_id = order.lineitems[0].item_idlogistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id)current_time = datetime.datetime.now()logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)order.warehouse_id = logistics_info.warehouseIdorder.logistics_provider_id = logistics_info.providerIdorder.airwaybill_no = logistics_info.airway_billnoorder.tracking_id = order.airwaybill_noorder.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)catalog_client = InventoryClient().get_client()catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, order.lineitems[0].quantity)item_pricing = catalog_client.getItemPricing(item_id, order.warehouse_id)order.lineitems[0].transfer_price = item_pricing.transferPricesession.commit()return Truedef adjust_delivery_time(order_time, delivery_days):order_date = order_time.date()delivery_date = order_date + datetime.timedelta(days = delivery_days)final_delivery_date = delivery_datetime_format = "%Y-%m-%d %H:%M:%S.%f"t = time.strptime(str(order_time), time_format)midnightTime = datetime.datetime(*t[:3])fromDate = to_java_date(midnightTime)toDate = -1Llogistics_client = LogisticsClient().get_client()holiday_dates = logistics_client.getHolidays(fromDate, toDate)holiday_dates = [(to_py_date(h_date)).date() for h_date in holiday_dates]while order_date <= final_delivery_date:if order_date.weekday() == 6 or is_holiday(holiday_dates, order_date):delivery_days = delivery_days + 1final_delivery_date = final_delivery_date + datetime.timedelta(days = 1)order_date = order_date + datetime.timedelta(days = 1)return delivery_daysdef is_holiday(holidays, date):try:holidays.index(date)return 1except:return 0def enqueue_transaction_info_email(transaction_id):transaction = get_transaction(transaction_id)html_header = """<html><body><div><p>Hello,<br /><br />Thanks for placing order with us. Following are the details of your order:</p><div>Order Date: $order_date</div><div><table><tr><td colspan="5"><hr /></td></tr><tr><td colspan="5" align="left"><b>Order Details</b></td></tr><tr><td colspan="5"><hr /></td></tr><tr><th width="100">Order No.</th><th>Product</th><th width="100">Quantity</th><th width="100">Unit Price</th><th width="100">Amount</th></tr>"""user_email = ""total_amount = 0.0html_table = ""order_date = datetime.datetime.now()for order in transaction.orders:order_date = order.created_timestampuser_email = order.customer_emailhtml_tr = "<tr><td align='center'>" + str(order.id) + "</td>"for lineitem in order.lineitems:lineitem_total_price = round(lineitem.total_price, 2)html_tr += "<td>" + str(lineitem) + "</td>"html_tr += "<td align='center'>" + ("%.0f" % lineitem.quantity) + "</td>"html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem.unit_price) + "</td>"html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem_total_price) + "</td></tr>"total_amount += lineitem_total_pricehtml_table += html_trhtml_footer = """<tr><td colspan=5> </td></tr><tr><td colspan=5><hr /></td></tr><tr><td colspan=4>Total Amount</td><td> Rs. $total_amount</td></tr><tr><td colspan=5><hr /></td></tr></table></div><p>Best Wishes,<br />Saholic Team</p></div></body></html>"""dt = datetime.datetime.strptime(str(order_date), "%Y-%m-%d %H:%M:%S")formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")email_header = Template(html_header).substitute(dict(order_date = formated_order_date))email_footer = Template(html_footer).substitute(dict(total_amount = "%.2f" % total_amount))try:helper_client = HelperClient().get_client()helper_client.saveUserEmailForSending(user_email, "", "Saholic - Order Details", email_header + html_table + email_footer, str(transaction_id), "TransactionInfo")return Trueexcept Exception as e:print ereturn Falsedef get_order(order_id):order = Order.get_by(id=order_id)if not order:raise TransactionServiceException(108, "no such order")return orderdef get_orders_for_customer(customer_id, from_date, to_date, status):if not customer_id:raise TransactionServiceException(101, "bad customer id")query = Order.query.filter(Order.customer_id == customer_id)if status:query = query.filter(Order.status == status)if from_date:query = query.filter(Order.created_timestamp >from_date)if to_date:query = query.filter(Order.created_timestamp < to_date)return query.all()def get_order_for_customer(order_id, customer_id):if not customer_id:raise TransactionServiceException(101, "bad customer id")order = get_order(order_id)if order.customer_id != customer_id:raise TransactionServiceException(108, "order: " + str(order_id) + " does not belong to customer: " + str(customer_id))return orderdef get_all_orders(status, from_date, to_date, warehouse_id):if not warehouse_id:raise TransactionServiceException(101, "bad warehouse id")query = Order.query.filter(Order.warehouse_id == warehouse_id)if status:query = query.filter(Order.status == status)if from_date:query = query.filter(Order.created_timestamp >from_date)if to_date:query = query.filter(Order.created_timestamp < to_date)return query.all()def get_returnable_orders_for_customer(customer_id, limit = None):if not customer_id:raise TransactionServiceException(101, "bad customer id")query = Order.query.filter(Order.customer_id == customer_id)query = query.filter(Order.status != OrderStatus.PAYMENT_FAILED)query = query.filter(Order.status != OrderStatus.REJECTED)query = query.filter(Order.status > OrderStatus.SHIPPED_FROM_WH)query = query.filter(or_(Order.status < OrderStatus.DELIVERY_SUCCESS, Order.delivery_timestamp < datetime.datetime.now() + datetime.timedelta(hours = 48)))orders = query.all()order_ids = [order.id for order in orders]return order_idsdef get_cancellable_orders_for_customer(customer_id, limit = None):if not customer_id:raise TransactionServiceException(101, "bad customer id")query = Order.query.filter(Order.customer_id == customer_id)query = query.filter(Order.status != OrderStatus.REJECTED)query = query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING)query = query.filter(Order.status < OrderStatus.BILLED)orders = query.all()return [order.id for order in orders]def get_orders_by_billing_date(status, start_billing_date, end_billing_date, warehouse_id):if not warehouse_id:raise TransactionServiceException(101, "bad warehouse id")query = Order.query.filter(Order.warehouse_id == warehouse_id)if status:query = query.filter(Order.status == status)if start_billing_date:query = query.filter(Order.billing_timestamp >= start_billing_date)if end_billing_date:query = query.filter(Order.billing_timestamp <= end_billing_date)return query.all()def get_orders_for_transaction(transaction_id, customer_id):orders = Order.query.filter_by(transaction_id=transaction_id, customer_id=customer_id).all()if not orders:raise TransactionServiceException(101, "No order for the transaction")return ordersdef get_undelivered_orders(provider_id, warehouse_id):query = Order.queryif provider_id != -1:query = query.filter_by(Order.logistics_provider_id == provider_id)if warehouse_id != -1:query = query.filter(Order.warehouse_id == warehouse_id)query = query.filter(and_(Order.status != OrderStatus.DELIVERY_SUCCESS, Order.status != OrderStatus.FAILED, \Order.status > OrderStatus.SHIPPED_FROM_WH))#Get last midnight time instead of current time as courier company would have sent the#delivery records updated at least till midnight and not by the current time.time_format = "%Y-%m-%d %H:%M:%S.%f"t = time.strptime(str(datetime.datetime.now()), time_format)midnightTime = datetime.datetime(*t[:3])query = query.filter(Order.expected_delivery_time < midnightTime)orders = query.all()return ordersdef get_line_items_for_order(order_id):query = LineItem.query.filter(LineItem.order_id == order_id)return query.all()def change_order_status(self, orderId, status, description):order = get_order(orderId)order.status = statusorder.statusDescription = descriptionsession.commit()return Truedef accept_order(self, orderId):order = get_order(orderId)order.status = OrderStatus.ACCEPTEDorder.statusDescription = "Order Accepted"order.accepted_timestamp = datetime.datetime.now()session.commit()return Truedef bill_order(self, orderId):order = get_order(orderId)order.status = OrderStatus.BILLEDorder.statusDescription = "Order Billed"order.billing_timestamp = datetime.datetime.now()session.commit()return Truedef add_billing_details(orderId, invoice_number, billed_by):order = Order.get_by(id=orderId)if not order:raise TransactionServiceException(101, "No order found for the givem orderid")order.invoice_number = invoice_numberorder.billed_by = billed_bysession.commit()return Truedef add_jacket_number(orderId, jacket_number):order = Order.get_by(id=orderId)if not order:raise TransactionServiceException(101, "No order found for the givem orderid")order.jacket_number = jacket_numbersession.commit()return Truedef batch_orders(warehouseId):if not warehouseId:raise TransactionServiceException(101, "bad warehouse id")batchno_generator = BatchNoGenerator()session.commit()query = Order.query.filter_by(warehouse_id=warehouseId)query = query.filter_by(status=OrderStatus.SUBMITTED_FOR_PROCESSING)query = query.order_by(Order.created_timestamp)pending_orders = query.all()serial_no = 1for order in pending_orders:order.batchNo = batchno_generator.idorder.serialNo = serial_noserial_no += 1session.commit()pending_orders = query.all()return pending_ordersdef order_outofstock(orderId):'''Mark order as out of stock'''order = get_order(orderId)order.status = OrderStatus.INVENTORY_LOWorder.statusDescription = "Low Inventory"order.outofstock_timestamp = datetime.datetime.now()session.commit()return Truedef mark_orders_as_manifested(warehouse_id, provider_id):try:current_timestamp = datetime.datetime.now()orders = Order.query.filter_by(warehouse_id = warehouse_id, logistics_provider_id = provider_id, status = OrderStatus.BILLED).all()for order in orders:order.status = OrderStatus.SHIPPED_FROM_WHorder.statusDescription = "Order shipped from warehouse"order.shipping_timestamp = current_timestampsession.commit()return Trueexcept:return Falsedef mark_orders_as_picked_up(provider_id, pickup_details):for awb, pickup_timestamp in pickup_details.iteritems():order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()if order == None or order.status != OrderStatus.SHIPPED_FROM_WH:#raise TransactionServiceException(102, "No order found for the awb: " + awb)continueorder.status = OrderStatus.SHIPPED_TO_LOGSTorder.statusDescription = "Order picked up by Courier Company"order.pickup_timestamp = pickup_timestampsession.commit()current_time = datetime.datetime.now()to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)from_datetime = to_datetime - datetime.timedelta(2)orders_not_picked_up = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.SHIPPED_FROM_WH).filter(Order.shipping_timestamp >= from_datetime).filter(Order.shipping_timestamp <= to_datetime).all()return orders_not_picked_updef mark_orders_as_delivered(provider_id, delivered_orders):for awb, detail in delivered_orders.iteritems():order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:continue#raise TransactionServiceException(103, "No order found for the awb:" + awb)order.status = OrderStatus.DELIVERY_SUCCESSorder.statusDescription = "Order delivered"order.delivery_timestamp, order.receiver = detail.split('|')session.commit()def mark_orders_as_failed(provider_id, returned_orders):for awb, detail in returned_orders.iteritems():order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:continue#raise TransactionServiceException(103, "No order found for the awb:" + awb)order.status = OrderStatus.SALES_RETURN_IN_TRANSITorder.delivery_timestamp, reason = detail.split('|')order.statusDescription = "Order Returned to Origin:" + reasonsession.commit()def update_non_delivery_reason(provider_id, undelivered_orders):for awb, reason in undelivered_orders.iteritems():order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()if order == None:continue#raise TransactionServiceException(103, "No order found for the awb:" + awb)order.statusDescription = reasonsession.commit()def get_alerts(order_id, all):query = Alerts.query.filter_by(order_id=order_id)if not all:query = query.filter_by(valid=True)return query.all()def set_alert(order_id, unset, type, comment):#get existing alertif unset:query = Alerts.query.filter_by(order_id=order_id)query = query.filter_by(type=type)alerts = query.all()for alert in alerts:if alert.valid:alert.valid = Falsealert.comment = commentalert.time_unset = datetime.datetime.now()else:alert = Alerts()alert.order_id = order_idalert.valid = Truealert.type = typealert.comment = commentalert.time_set = datetime.datetime.now()session.commit()def get_valid_order_count():return Order.query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).count()def get_cust_count_with_successful_txn():return session.query(Order.customer_id).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).distinct().count()def get_valid_orders_amount_range():orders = Order.query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).all()order_amounts = [o.total_amount for o in orders]return [min(order_amounts), max(order_amounts)]def get_valid_orders(limit):query = Order.query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING)query = query.order_by(desc(Order.created_timestamp))if limit > 0:query = query.limit(limit)elif limit < 0:raise TransactionServiceException(101, "Invalid argument limit " + limit)return query.all()def toggle_doa_flag(order_id):order = get_order(order_id)if(order.doaFlag):order.doaFlag = Falseelse:order.doaFlag = Truesession.commit()return order.doaFlagdef request_pickup_number(order_id):order = get_order(order_id)if order.status != OrderStatus.DELIVERY_SUCCESS and order.status != OrderStatus.DOA_PICKUP_REQUESTED:return Falsefrom_user = 'cnc.center@shop2020.in'from_pwd = '5h0p2o2o'subject = "Pickup request"try:catalog_client = InventoryClient().get_client()warehouse = catalog_client.getWarehouse(order.warehouse_id)logistics_client = LogisticsClient().get_client()provider = logistics_client.getProvider(order.logistics_provider_id)to_addr = provider.emailraw_message = '''Dear Sir/Madam,Kindly arrange a pickup today from %(customer_city)s. Pickup and delivery addresses are mentioned below.Pickup CODE: %(provider_code)sTotal Weight: %(order_weight)s kgPickup Address:%(customer_address)sDelivery Address:%(warehouse_executive)s%(warehouse_address)sPIN %(warehouse_pin)sPhone: %(warehouse_phone)sThanks and RegardsAnand Sinha'''message = dedent(raw_message) % { 'customer_city' : order.customer_city,'provider_code' : provider.accountNo,'order_weight' : str(order.total_weight),'customer_address' : __get_order_address(order),'warehouse_executive' : 'Parmod Kumar','warehouse_address' : warehouse.location,'warehouse_pin' : warehouse.pincode,'warehouse_phone': '9971573026'}mail(from_user, from_pwd, to_addr, subject, message)order.status = OrderStatus.DOA_PICKUP_REQUESTEDorder.statusDescription = "Pick up requested for DOA"session.commit()return Trueexcept Exception as e:print sys.exc_info()[0]return Falsedef authorize_pickup(order_id, pickup_number):order = get_order(order_id)if order.status != OrderStatus.DOA_PICKUP_REQUESTED:return Falsefrom_user = 'help@shop2020.in'from_pwd = '5h0p2o2o'subject = 'Pickup details'filename = "/tmp/" + str(order.id) +".pdf"try:catalog_client = InventoryClient().get_client()warehouse = catalog_client.getWarehouse(order.warehouse_id)logistics_client = LogisticsClient().get_client()provider = logistics_client.getProvider(order.logistics_provider_id)provider_name = provider.nameto_addr = order.customer_emailtoday = date.today().strftime("%d-%B-%Y (%A)")raw_message = '''Dear Mr. %(customer_name)s,In reference to the return of order ID %(order_id)d. We request you to kindly pack the box properly with bubble wrap, and send it along with the original "DOA" certificate and the invoice.Take a printout of the attachment in this mail which contains the delivery address and paste it on the packed parcel.We have instructed %(provider_name)s to pick up the material from the below mentioned address on %(date)s. %(provider_name)s pickup request number is %(pickup_request_no)s. Kindly keep the parcel ready.Pickup will happen from the below mentioned address:-%(customer_address)sDo let us know in case of any concernsThanks & RegardsSaholic Team'''message = dedent(raw_message) % {'customer_name' : order.customer_name,'order_id' : order_id,'provider_name' : provider_name,'date': today,'pickup_request_no' : pickup_number,'customer_address' : __get_order_address(order)}print message__generate_return_advice(order, warehouse, provider, filename)mail(from_user, from_pwd, to_addr, subject, message, get_attachment_part(filename))order.pickupRequestNo = pickup_numberorder.status = OrderStatus.DOA_RETURN_AUTHORIZEDorder.statusDescription = "DOA pick up authorized"session.commit()return Trueexcept Exception as e:print sys.exc_info()[0]return Falsefinally:if os.path.exists(filename):os.remove(filename)def receive_return(order_id):order = get_order(order_id)if order.status in [OrderStatus.DOA_RETURN_AUTHORIZED, OrderStatus.DOA_RETURN_IN_TRANSIT]:order.status = OrderStatus.DOA_RECEIVEDorder.statusDescription = "DOA package received"session.commit()elif order.status == OrderStatus.SALES_RETURN_IN_TRANSIT :order.status = OrderStatus.SALES_RET_RECEIVEDorder.statusDescription = "Sales return received"session.commit()else:return Falsereturn Truedef validate_doa(order_id, is_valid):order = get_order(order_id)if order.status != OrderStatus.DOA_RECEIVED:return Falseif is_valid:order.status = OrderStatus.DOA_CERT_VALIDorder.statusDescription = "DOA Certificate Valid"else:order.status = OrderStatus.DOA_CERT_INVALIDorder.statusDescription = "DOA Certificate Invalid"session.commit()return Truedef reship_order(order_id):"""If the order is in SALES_RET_RECEIVED or DOA_CERT_INVALID state, it does the following:1. Creates a new order for processing in the BILLED state. All billing information is saved.2. Marks the current order as one of the final states SALES_RET_RESHIPPED and DOA_INVALID_RESHIPPED depending on what state the order started in.If the order is in DOA_CERT_VALID state, it does the following:1. Creates a new order for processing in the SUBMITTED_FOR_PROCESSING state.2. Creates a return order for the warehouse executive to return the DOA material.3. Marks the current order as the final DOA_RESHIPPED state.Returns the id of the newly created order.Throws an exception if the order with the given id couldn't be found.Parameters:- orderId"""order = get_order(order_id)if order.status == OrderStatus.SALES_RET_RECEIVED:new_order = __clone_order(order, True)order.status = OrderStatus.SALES_RET_RESHIPPEDorder.statusDescription = "Order Reshipped"session.commit()elif order.status == OrderStatus.DOA_CERT_INVALID:new_order = __clone_order(order, True)order.status = OrderStatus.DOA_INVALID_RESHIPPEDorder.statusDescription = "Order Reshipped"session.commit()elif order.status == OrderStatus.DOA_CERT_VALID:new_order = __clone_order(order, False)ret_order = __create_return_order(order)order.status = OrderStatus.DOA_RESHIPPEDorder.statusDescription = "Order Reshipped"session.commit()else:raise TransactionServiceException(112, "This order can't be reshipped")order.new_order_id = new_order.idsession.commit()return new_order.iddef refund_order(order_id):"""If the order is in SALES_RET_RECEIVED, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:1. Creates a refund request for batch processing.2. Creates a return order for the warehouse executive to return the shipped material.3. Marks the current order as SALES_RET_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:1. Creates a refund request for batch processing.2. Marks the current order as the REFUNDED final state.Returns True if it is successful.Throws an exception if the order with the given id couldn't be found.Parameters:- orderId"""status_transition = {OrderStatus.SALES_RET_RECEIVED : OrderStatus.SALES_RET_REFUNDED,OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.REFUNDED,OrderStatus.INVENTORY_LOW : OrderStatus.REFUNDED}order = get_order(order_id)if order.status in [OrderStatus.SALES_RET_RECEIVED, OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID] :__create_return_order(order)__create_refund(order)order.status = status_transition[order.status]order.statusDescription = "Refunded"elif order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW]:__create_refund(order)try:#Reduce the reservation count for all lineitems.catalog_client = InventoryClient().get_client()for lineitem in order.lineitems:catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity);except:print "Unable to reduce reservation count"order.status = status_transition[order.status]order.statusDescription = "Refunded"else:raise TransactionServiceException(114, "This order can't be refunded")session.commit()return Truedef __clone_order(order, should_copy_billing_info):current_time = datetime.datetime.now()new_order = Order()new_order.customer_id = order.customer_idnew_order.customer_name = order.customer_namenew_order.customer_city = order.customer_citynew_order.customer_state = order.customer_statenew_order.customer_mobilenumber = order.customer_mobilenumbernew_order.customer_pincode = order.customer_pincodenew_order.customer_address1 = order.customer_address1new_order.customer_address2 = order.customer_address2new_order.customer_email = order.customer_emailnew_order.total_amount = order.total_amountnew_order.total_weight = order.total_weightnew_order.status = OrderStatus.SUBMITTED_FOR_PROCESSINGnew_order.statusDescription = 'Submitted for Processing'new_order.created_timestamp = current_timenew_order.transaction = order.transactionfor line_item in order.lineitems:litem = LineItem()litem.item_id = line_item.item_idlitem.productGroup = line_item.productGrouplitem.brand = line_item.brandif line_item.model_number:litem.model_number = line_item.model_numberif line_item.model_name:litem.model_name = line_item.model_nameif line_item.color:litem.color = line_item.colorif line_item.extra_info:litem.extra_info = line_item.extra_infolitem.quantity = line_item.quantitylitem.unit_price = line_item.unit_pricelitem.unit_weight = line_item.unit_weightlitem.total_price = line_item.total_pricelitem.total_weight = line_item.total_weightlitem.transfer_price = line_item.transfer_pricelitem.order = new_orderlogistics_client = LogisticsClient().get_client()item_id = new_order.lineitems[0].item_idlogistics_info = logistics_client.getLogisticsInfo(new_order.customer_pincode, item_id) #TODO: We should be able to pass another flag to suggest ignoring the inventory situation.logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)new_order.warehouse_id = logistics_info.warehouseIdnew_order.logistics_provider_id = logistics_info.providerIdnew_order.airwaybill_no = logistics_info.airway_billnonew_order.tracking_id = new_order.airwaybill_nonew_order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)if should_copy_billing_info:new_order.invoice_number = order.invoice_numbernew_order.billed_by = order.billed_bynew_order.warehouse_id = order.warehouse_idnew_order.accepted_timestamp = current_timenew_order.billing_timestamp = current_timenew_order.status = OrderStatus.BILLEDnew_order.statusDescription = 'Order Billed'else:catalog_client = InventoryClient().get_client()catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, new_order.lineitems[0].quantity)item_pricing = catalog_client.getItemPricing(item_id, order.warehouse_id)new_order.lineitems[0].transfer_price = item_pricing.transferPricereturn new_orderdef __create_return_order(order):ret_order = ReturnOrder(order)return ret_orderdef __create_refund(order):passdef __get_order_address(order):address = order.customer_name + "\n" + order.customer_address1 + "\n"if order.customer_address2:address = address + order.customer_address2 + "\n"address = address + order.customer_city + "\n"address = address + order.customer_state + "\n"address = address + "PIN " + order.customer_pincode + "\n"address = address + "Phone: " + order.customer_mobilenumberreturn addressdef __generate_return_advice(order, warehouse, provider, filename):pdf = Canvas(filename)pdf.setFont('Times-Bold',16)address_text = pdf.beginText(inch, PAGE_HEIGHT - inch)address_text.textLine("To")address_text.textLine("Parmod Kumar")for line in warehouse.location.split("\n"):address_text.textLine(line)address_text.textLine("PIN " + warehouse.pincode)address_text.textLine("")address_text.textLine("Phone: 9971573026")pdf.drawText(address_text)pdf.setFont('Times-Roman',12)order_text = pdf.beginText(inch, PAGE_HEIGHT - 4 * inch)order_text.textLine("Pickup CODE: " + provider.accountNo)lineitem = order.lineitems[0]order_text.textLine("Content : " + lineitem.brand + " " + lineitem.model_number + " " + lineitem.color)order_text.textLine("Declared Value: Rs. " + str(order.total_amount))order_text.textLine("Order ID : " + str(order.id))pdf.drawText(order_text)pdf.showPage()pdf.save()return filenamedef close_session():if session.is_active:print "session is active. closing it."session.close()