Rev 17248 | Blame | Compare with Previous | Last modification | View Log | RSS feed
'''Created on Jan 15, 2015@author: Manish'''from bs4 import BeautifulSoupfrom bson.binary import Binaryfrom datetime import datetime, date, timedeltafrom dtr import mainfrom dtr.dao import AffiliateInfo, Order, SubOrder, HomeShopAffiliateInfofrom dtr.main import getBrowserObject, ScrapeException, getStore, ParseException, \Store as MStore, ungzipResponse, tprintfrom dtr.storage import Mongofrom dtr.storage.Mongo import getImgSrcfrom dtr.utils.utils import fetchResponseUsingProxy, PROXY_MESH_GENERALfrom pprint import pprintfrom pymongo import MongoClientimport jsonimport pymongoimport reimport timeimport tracebackimport urllibimport urllib2from urlparse import urlparse, parse_qsimport xml.etree.ElementTree as ETfrom dtr.storage import MemCachefrom dtr.storage.Mongo import getDealRankAFFLIATE_TRASACTIONS_URL = "https://admin.optimisemedia.com/v2/reports/affiliate/leads/leadsummaryexport.aspx?Contact=796881&Country=26&Agency=95&Merchant=331902&Status=-1&Year=%d&Month=%d&Day=%d&EndYear=%d&EndMonth=%d&EndDay=%d&DateType=0&Sort=CompletionDate&Login=1347562DA5E3EFF6FB1561765C47C782&Format=XML&RestrictURL=0"ORDER_TRACK_URL='https://m.homeshop18.com/order/orderDetail.mobi?orderId=%d'HS_ORDER_TRACK_URL='http://www.homeshop18.com/track-your-order.html'BASE_URL= 'http://www.shopclues.com'BASE_MURL= 'http://m.shopclues.com'BASE_PRODUCT_URL= 'http://m.homeshop18.com/product.mobi?productId=%d'BASE_IMG_URL='http://stat.homeshop18.com/homeshop18'#http://m.homeshop18.com/checkout/paySuccess.mobi?orderComplete=trueclass Store(MStore):'''This is to map order statuses of our system to order statuses of snapdeal.And our statuses will change accordingly.'''OrderStatusMap = {MStore.ORDER_PLACED : ['payment successful', 'new order - cod confirmation pending', 'processing', 'quality check','on schedule', 'processing - pickup initiated', 'processing - ready to dispatch','processing - procurement delay from merchant','processing - slight procurment delay from merchant','cod order confirmed by customer'],MStore.ORDER_DELIVERED : ['delivered', 'complete'],MStore.ORDER_SHIPPED : ['in transit', 'dispatched','shipped','order handed to courier','order handed over to courier'],MStore.ORDER_CANCELLED : ['payment failed', 'canceled', 'payment declined', 'order on hold - cancellation requested by customer', 'courier returned', 'canceled on customer request', 'canceled by customer','order canceled by customer','canceled - address not shippable','return complete','undelivered - returning to origin']}OrderStatusConfirmationMap= {"P" : "Payment Successful","D" : "Order Declined","O" : "New Order - COD confirmation Pending"}OrderStatusStringMap = {MStore.ORDER_PLACED : ['expect the order to reach', 'received your payment'],MStore.ORDER_DELIVERED : ['has been delivered'],MStore.ORDER_SHIPPED : ['has been shipped', 'has been dispatched'],MStore.ORDER_CANCELLED : ['has been cancelled', 'has been rejected','is returned back to us','payment failed']}OrderStatusShownMap = {"Under Process" : ['expect the order to reach', 'received your payment'],"Order Delivered" : ['has been delivered'],"Order Shipped" : ['has been shipped', 'has been dispatched'],"Order Cancelled" : ['has been cancelled', 'has been rejected','is returned back to us','payment failed']}CONF_CB_AMOUNT = MStore.CONF_CB_DISCOUNTED_PRICEdef __init__(self,store_id):super(Store, self).__init__(store_id)def convertToObj(self,offer):orderRef = offer['MerchantRef']if len(orderRef)>15:orderRef = orderRef[0:len(orderRef)-10]offer1 = HomeShopAffiliateInfo(offer['UID'], offer['TransactionTime'], offer['TransactionID'], orderRef, orderRef, offer['Merchant'], offer['PID'], offer['Product'], float(str(offer['SR'])), float(str(offer['TransactionValue'])), offer['UKey'], offer['ClickTime'], offer['Status'])return offer1def _saveToAffiliate(self, offers):collection = self.db.homeshopOrderAffiliateInfomcollection = self.db.merchantOrderfor offerObj in offers:offer = self.convertToObj(offerObj)collection.update({"transactionId":offer.transactionId, "subTagId":offer.subTagId, "payOut":offer.payOut},{"$set":todict(offer)}, upsert=True)mcollection.update({"subTagId":offer.subTagId, "storeId":self.store_id, "subOrders.missingAff":True}, {"$set":{"subOrders.$.missingAff":False}})def scrapeAffiliate(self, startDate=datetime.today() - timedelta(days=10), endDate=datetime.today()):uri = AFFLIATE_TRASACTIONS_URL%(startDate.year,startDate.month,startDate.day,endDate.year,endDate.month,endDate.day)root = ET.parse(urllib2.urlopen(uri)).getroot()if len(root)> 0 and len(root[0])> 0:offers = []for child in root[0][0]:offers.append(child.attrib)self._saveToAffiliate(offers)def _setLastSaleDate(self, saleDate):self.db.lastSaleDtate.update({'storeId':self.store_id}, {'$set':{'saleDate':saleDate}})def getName(self):return "homeshop18"def _getLastSaleDate(self,):lastDaySaleObj = self.db.lastDaySale.find_one({"storeId":self.store_id})if lastDaySaleObj is None:return datetime.mindef _getStatusFromDetailedStatus(self, detailedStatus):for key, statusList in Store.OrderStatusStringMap.iteritems():for value in statusList:if value in detailedStatus.lower():return keyprint "Detailed Status need to be mapped", detailedStatus, self.store_idreturn Nonedef _getDisplayStatusFromDetailedStatus(self, detailedStatus):for key, statusList in Store.OrderStatusShownMap.iteritems():for value in statusList:if value in detailedStatus.lower():return keyprint "Display Status need to be mapped", detailedStatus, self.store_idreturn Nonedef updateCashbackInSubOrders(self, subOrders):for subOrder in subOrders:cashbackStatus = Store.CB_NAcashbackAmount = 0percentage = 0amount = subOrder.amountPaidif amount > 0:(cashbackAmount, percentage) = self.getCashbackAmount(subOrder.productCode, amount)if cashbackAmount > 0:cashbackStatus = Store.CB_PENDINGsubOrder.cashBackStatus = cashbackStatussubOrder.cashBackAmount = cashbackAmountsubOrder.cashBackPercentage = percentagereturn subOrdersdef _parseUsingOrderJson(self, orderId, subTagId, userId, rawHtmlSoup, orderSuccessUrl):orderObj = Nonescripts = rawHtmlSoup.find_all('script')for script in scripts:if 'var order =' in script.text:requiredObjList = script.text.strip().split('\n')for val in requiredObjList:if "$.parseJSON('" in val:val = val.encode("ascii","ignore")print 'Val......',valprint val.split("$.parseJSON('")[1].split("');")[0]orderObj = json.loads(val.split("$.parseJSON('")[1].split("');")[0])print orderObjbreakbreakif orderObj is not None:merchantOrder = Order(orderId, userId, subTagId, self.store_id, orderSuccessUrl)merchantOrder.placedOn = orderObj['orderDate']merchantOrder.merchantOrderId = str(long(orderObj['orderId']))merchantOrder.paidAmount = long(orderObj['pricing']['orderNetPrice'])merchantOrder.totalAmount = long(orderObj['pricing']['orderGrossPrice'])merchantOrder.discountApplied = long(orderObj['pricing']['discountCouponRedemptionAmount'])+long(orderObj['pricing']['giftCouponRedemptionAmount'])merchantOrder.deliveryCharges = long(orderObj['totalShipmentCharges'])subOrders= []for subOrderObj in orderObj['subOrders']:subOrder = SubOrder(subOrderObj['cartItem']['cartItemTitle'], BASE_PRODUCT_URL%(long(subOrderObj['cartItem']['productId'])), orderObj['orderDate'], long(subOrderObj['pricing']['payablePrice']))subOrder.estimatedDeliveryDate = subOrderObj['shipment']['expectedDeliveryDate']subOrder.merchantSubOrderId = str(subOrderObj['subOrderId'])if rawHtmlSoup.body.find("div", {'class':'sub-order-status'}) is not None:subOrder.detailedStatus = rawHtmlSoup.body.find("div", {'class':'sub-order-status'}).textelse:subOrder.detailedStatus = 'Order Placed'subOrder.imgUrl = BASE_IMG_URL+subOrderObj['cartItem']['lineItemImageUrl']subOrder.offerDiscount = (long(subOrderObj['cartItem']['price'])+long(subOrderObj['shipment']['shipmentCharge']))*long(subOrderObj['cartItem']['itemQuantity'])-long(subOrderObj['pricing']['payablePrice'])subOrder.unitPrice = long(subOrderObj['cartItem']['price'])subOrder.productCode = str(long(subOrderObj['cartItem']['productId']))subOrder.amountPaid = long(subOrderObj['pricing']['payablePrice'])subOrder.quantity = long(subOrderObj['cartItem']['itemQuantity'])subOrder.tracingkUrl = ORDER_TRACK_URL%(long(orderObj['orderId']))dealRank = getDealRank(subOrder.productCode, self.store_id, merchantOrder.userId)subOrder.dealRank = dealRank.get('rank')subOrder.rankDesc = dealRank.get('description')subOrder.maxNlc = dealRank.get('maxNlc')subOrder.minNlc = dealRank.get('minNlc')subOrder.db = dealRank.get('dp')subOrder.itemStatus = dealRank.get('status')subOrders.append(subOrder)merchantOrder.subOrders = self.updateCashbackInSubOrders(subOrders)return merchantOrderdef parseOrderRawHtml(self, orderId, subTagId, userId, rawHtml, orderSuccessUrl):resp = {}try:rawHtmlSoup = BeautifulSoup(rawHtml)merchantOrder = self._parseUsingOrderJson(orderId, subTagId, userId, rawHtmlSoup, orderSuccessUrl)merchantOrder.orderTrackingUrl = ORDER_TRACK_URL%(long(merchantOrder.merchantOrderId))if self._saveToOrder(todict(merchantOrder)):resp['result'] = 'ORDER_CREATED'else:resp['result'] = 'ORDER_ALREADY_CREATED_IGNORED'return respexcept:print "Error occurred"traceback.print_exc()resp['result'] = 'ORDER_NOT_CREATED'return respdef scrapeStoreOrders(self,):#collectionMap = {'palcedOn':1}searchMap = {}collectionMap = {"orderTrackingUrl":1,"merchantOrderId":1}orders = self._getActiveOrders(searchMap,collectionMap)for order in orders:bulk = self.db.merchantOrder.initialize_ordered_bulk_op()try:print "Order", self.store_name, order['orderId'], order['orderTrackingUrl'], order['merchantOrderId']br1 = track(HS_ORDER_TRACK_URL, order['merchantOrderId'])ungzipResponseBr(br1.response(), br1)trackPageSoup = BeautifulSoup(br1.response())subOrderTable = trackPageSoup.body.find("table", {'class':'lower-table'})subOrders = subOrderTable.find_all('tr')firstRow = subOrders.pop(0)closed = Truefor row in subOrders:cols = row.find_all('td')subOrderId = cols[0].text.strip()subOrderStatus = cols[1].text.strip()subbulk = self.db.merchantOrder.initialize_ordered_bulk_op()print 'Sub Order Id', str(subOrderId)subOrder = self._isSubOrderActive(order, str(subOrderId))if subOrder is None:print 'No HS Sub Order Found for SubOrder Id:- '+ str(subOrderId)elif subOrder['closed']:continueelse:findMap = {"orderId": order['orderId'], "subOrders.merchantSubOrderId": str(subOrderId)}updateMap = {}displayStatus = self._getDisplayStatusFromDetailedStatus(subOrderStatus)status = self._getStatusFromDetailedStatus(subOrderStatus)if displayStatus is not None:updateMap["subOrders.$.detailedStatus"] = displayStatusclosedStatus = status in [Store.ORDER_DELIVERED, Store.ORDER_CANCELLED]if status is not None:updateMap["subOrders.$.status"] = statusif closedStatus:#if status is closed then change the paybackStatus accordinglyprint 'Order Closed'updateMap["subOrders.$.closed"] = Trueif status == Store.ORDER_DELIVERED:if subOrder.get("cashBackStatus") == Store.CB_PENDING:updateMap["subOrders.$.cashBackStatus"] = Store.CB_APPROVEDelif status == Store.ORDER_CANCELLED:if subOrder.get("cashBackStatus") == Store.CB_PENDING:updateMap["subOrders.$.cashBackStatus"] = Store.CB_CANCELLEDelse:closed = Falseprint 'Order not Closed'subbulk.find(findMap).update({'$set' : updateMap})subresult = subbulk.execute()tprint(subresult)bulk.find({'orderId': order['orderId']}).update({'$set':{'closed': closed,"parseError":False}})result = bulk.execute()tprint(result)except:print "Error occurred for tracking order... "+str(order['merchantOrderId'])traceback.print_exc()continuedef track(url, orderId):br = getBrowserObject()br.set_proxies({"http": PROXY_MESH_GENERAL})response = br.open(url)ungzipResponseBr(response, br)soup = BeautifulSoup(br.response())csrf = soup.find('input', {'name': '_csrf'}).get('value')print csrf#html = response.read()#print htmlbr.select_form(name='trackForm')br.form['orderId'] = str(orderId)response = br.submit()print "********************"print "Attempting to Login"print "********************"#ungzipResponse(response, br)return brdef ungzipResponseBr(r,b):headers = r.info()if headers['Content-Encoding']=='gzip':import gzipprint "********************"print "Deflating gzip response"print "********************"gz = gzip.GzipFile(fileobj=r, mode='rb')html = gz.read()gz.close()headers["Content-type"] = "text/html; charset=utf-8"r.set_data( html )b.set_response(r)def to_py_date(java_timestamp):date = datetime.fromtimestamp(java_timestamp)return datedef todict(obj, classkey=None):if isinstance(obj, dict):data = {}for (k, v) in obj.items():data[k] = todict(v, classkey)return dataelif hasattr(obj, "_ast"):return todict(obj._ast())elif hasattr(obj, "__iter__"):return [todict(v, classkey) for v in obj]elif hasattr(obj, "__dict__"):data = dict([(key, todict(value, classkey))for key, value in obj.__dict__.iteritems()if not callable(value) and not key.startswith('_')])if classkey is not None and hasattr(obj, "__class__"):data[classkey] = obj.__class__.__name__return dataelse:return obj