Subversion Repositories SmartDukaan

Rev

Rev 17802 | Rev 17811 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

    '''
    Created on 10-May-2010
    
    @author: ashish
    '''
    from elixir import *
    from shop2020.clients.CatalogClient import CatalogClient
    from shop2020.clients.InventoryClient import InventoryClient
    from shop2020.clients.LogisticsClient import LogisticsClient
    from shop2020.clients.PromotionClient import PromotionClient
    from shop2020.clients.TransactionClient import TransactionClient
    from shop2020.model.v1 import user
    from shop2020.model.v1.user.impl.Converters import to_t_cart, to_t_line
    from shop2020.model.v1.user.impl.Dataservice import Cart, Line, Address, User, \
        Discount, InsuranceDetails, PrivateDealUser
    from shop2020.thriftpy.logistics.ttypes import LogisticsServiceException, \
        DeliveryType
    from shop2020.thriftpy.model.v1.catalog.ttypes import Item, InsurerType
    from shop2020.thriftpy.model.v1.order.ttypes import Transaction as TTransaction, \
        TransactionStatus as TTransactionStatus, Order as TOrder, LineItem as TLineItem, \
        OrderStatus, OrderSource
    from shop2020.thriftpy.model.v1.user.ttypes import CartStatus, LineStatus, \
        ShoppingCartException, PromotionException, CartPlus
    from shop2020.utils.Utils import to_py_date, to_java_date
    import datetime
    import json
    import math
    import traceback
    
    
    
    
    def get_cart(userId):
        user = User.get_by(id=userId)
        return user.active_cart
    
    def get_cart_by_id(id):
        cart = Cart.get_by(id=id)
        return cart
    
    def create_cart():
        cart = Cart()
        cart.created_on = datetime.datetime.now()
        cart.updated_on = datetime.datetime.now()
        cart.cart_status = CartStatus.ACTIVE
        return cart
    
    def get_carts_between(start_time, end_time, status):
        init_time = to_py_date(start_time)
        finish_time = to_py_date(end_time)
        
        query = Cart.query
        if status:
            query = query.filter(Cart.cart_status==status)
        if init_time:
            query = query.filter(Cart.created_on >= init_time)
        if finish_time:
            query = query.filter(Cart.created_on <= finish_time)
        
        carts = query.all()
        return carts
    
    def get_line(item_id, cart_id, status, single):
        #get cart first 
        try:
            found_cart = Cart.get_by(id=cart_id)
        except:
            raise ShoppingCartException(101, "cart not found ")
        query = Line.query.filter_by(cart = found_cart, item_id = item_id)
        
        if status:
            query = query.filter_by(line_status = status)
        else:
            query = query.filter_by(line_status = LineStatus.LINE_ACTIVE)
        try:
            if single:
                return query.one()
            else:
                return query.all()
        except:
            return None
    
    def add_item_to_cart(cart_id, item_id, quantity, sourceId):
        if not item_id:
            raise ShoppingCartException(101, "item_id cannot be null")
        
        if not quantity:
            raise ShoppingCartException(101, "quantity cannot be null")    
    
        cart = Cart.get_by(id = cart_id)    
        if not cart:
            raise ShoppingCartException(101, "no cart attached to this id" + str(cart_id))
        retval = ""
        catalog_client = CatalogClient().get_client()
        item = catalog_client.getItemForSource(item_id, sourceId)
        dataProtectionInsurer = catalog_client.getPrefferedInsurerForItem(item_id,InsurerType._NAMES_TO_VALUES.get("DATA"))
        item_shipping_info = catalog_client.isActive(item_id)
        if not item_shipping_info.isActive:
            return catalog_client.getItemStatusDescription(item_id)
        
        current_time = datetime.datetime.now()
        cart.updated_on = current_time
        line = get_line(item_id, cart_id, None,True)
        if line:
            #change the quantity only
            line.insuranceAmount = (line.insuranceAmount/line.quantity) * quantity
            line.quantity = quantity
            line.updated_on = current_time
            line.dataProtectionAmount = (line.dataProtectionAmount/line.quantity) * quantity
        else:
            line = Line()
            line.cart = cart
            line.item_id = item_id
            line.quantity = quantity
            line.created_on = current_time
            line.updated_on = current_time
            line.actual_price = item.sellingPrice
            line.line_status = LineStatus.LINE_ACTIVE
            line.insurer = 0
            line.insuranceAmount = 0
            #DATA INSURER IS SET UPON ADD TO CART
            line.dataProtectionInsurer = dataProtectionInsurer
        session.commit()
        return retval
    
    def delete_item_from_cart(cart_id, item_id):
        if not item_id:
            raise ShoppingCartException(101, "item_id cannot be null")
        cart = Cart.get_by(id = cart_id)
        if not cart:
            raise ShoppingCartException(101, "no cart attached to this id")
        item = get_line(item_id, cart_id, None, True)
        count_deleted_discounts = delete_discounts_for_line(item)
        item.delete()
        current_time = datetime.datetime.now()
        cart.updated_on = current_time
        session.commit()
    
    def delete_discounts_for_line(item_line):
        count_deleted = Discount.query.filter_by(line = item_line).delete()
        session.commit()
        return count_deleted
    
    def delete_discounts_from_cart(cart_id, cart = None):
        if cart is None:
            if cart_id is None:
                raise ShoppingCartException(101, 'cart_id and cart, both cannot be null')
            else:
                cart = Cart.get_by(id = cart_id)
        
        if cart.lines:
            for line in cart.lines:
                delete_discounts_for_line(line)
    
    def save_discounts(discounts):
        if not discounts:
            raise ShoppingCartException(101, 'discounts be null')
        
        if len(discounts) > 0:
            cart = Cart.get_by(id = discounts[0].cart_id)
            
            for t_discount in discounts:
                line = Line.query.filter_by(cart = cart, item_id = t_discount.item_id).first()
                if line is not None:
                    discount = Discount()
                    discount.line = line
                    discount.discount = t_discount.discount
                    discount.quantity = t_discount.quantity
                    session.commit()
                
    def add_address_to_cart(cart_id, address_id):
        if not cart_id:
            raise ShoppingCartException(101, "cart id cannot be made null")
        
        if not address_id:
            raise ShoppingCartException(101, "address id cannot be made null")
        
        cart = get_cart_by_id(cart_id)
        if not cart:
            raise ShoppingCartException(101, "no cart for this id")
        
        address = Address.get_by(id=address_id)
        if not address:
            raise ShoppingCartException(101, "No address for this id")
        
        cart.address_id = address_id
        current_time = datetime.datetime.now()
        #cart.updated_on = current_time
        session.commit()
    
    def add_store_to_cart(cartId, storeId):
        if not cartId:
            raise ShoppingCartException(101, "cart id cannot be made null")
        
        cart = get_cart_by_id(cartId)
        if not cart:
            raise ShoppingCartException(101, "no cart for this id")
        
        if storeId:
            cart.pickupStoreId = storeId
        else:
            cart.pickupStoreId = None
            
        session.commit()
        
    def apply_coupon_to_cart(t_cart, coupon_code):
        cart = get_cart_by_id(t_cart.id)
        if not cart:
            raise ShoppingCartException(101, "no cart attached to this id")
        pc = PromotionClient().get_client()
        for t_line in t_cart.lines:
            line = Line.query.filter_by(cart = cart).filter_by(item_id = t_line.itemId).one()
            line.discounted_price = None
            if not pc.isGiftVoucher(coupon_code):
                line.discounted_price = t_line.discountedPrice
            #line.dealText = t_line.dealText
            #line.freebieId = t_line.freebieId
        
        cart.total_price = t_cart.totalPrice
        cart.discounted_price = t_cart.discountedPrice
        cart.coupon_code = coupon_code
        session.commit()
    
    def remove_coupon(cart_id):
        cart = get_cart_by_id(cart_id)
        if not cart:
            raise ShoppingCartException(101, "no cart attached to this id")
        
        #Resetting discounted price of each line in cart to Null
        for line in cart.lines:
            line.discounted_price = None
            line.dealText = None
            line.freebieId = None
        
        delete_discounts_from_cart(cart.id, cart=cart)
        cart.discounted_price = None
        cart.coupon_code = None
        session.commit()
        
    def commit_cart(cart_id, sessionSource, sessionTime, firstSource, firstSourceTime, userId, schemeId, orderSource):   
        cart = get_cart_by_id(cart_id)   
        #now we have a cart. Need to create a transaction with it
        totalCartVal = 0
        totalshippingCost = 0
        for lineObj in cart.lines:
            totalCartVal += lineObj.actual_price * lineObj.quantity
        txn = TTransaction()
        txn.shoppingCartid = cart_id
        txn.customer_id = userId
        txn.createdOn = to_java_date(datetime.datetime.now())
        txn.transactionStatus = TTransactionStatus.INIT
        txn.statusDescription = "New Order"
        txn.coupon_code = cart.coupon_code
        txn.sessionSource = sessionSource
        txn.sessionStartTime = sessionTime
        txn.firstSource = firstSource
        txn.firstSourceTime = firstSourceTime
        txn.emiSchemeId = schemeId
        privateDealUser = PrivateDealUser.query.filter(PrivateDealUser.id == userId).filter(PrivateDealUser.isActive==True).first()
        if privateDealUser is not None:
            if totalCartVal < 500:
                totalshippingCost = 100
            elif totalCartVal >=500 and totalCartVal<1000:
                totalshippingCost = 50
        txn.totalShippingCost = totalshippingCost
            
        txnOrders = create_orders(cart, userId, orderSource, totalshippingCost, totalCartVal)
        shippingCostInOrders = 0
        for order in txnOrders:
            shippingCostInOrders = shippingCostInOrders + order.shippingCost
        
        diff = totalshippingCost - shippingCostInOrders
        if diff > 0:
            txnOrders[0].shippingCost = txnOrders[0].shippingCost + diff
        
        
        txn.orders = txnOrders
        
        transaction_client = TransactionClient().get_client()
        txn_id = transaction_client.createTransaction(txn)
        
        privateDealUser = PrivateDealUser.query.filter(PrivateDealUser.id == userId).filter(PrivateDealUser.isActive==True).first()
        if privateDealUser is not None and privateDealUser.counter is not None:
            privateDealUser.counter.lastPurchasedOn = datetime.datetime.now()
        session.commit()
        
        return txn_id
    
    def create_orders(cart, userId, orderSource, totalshippingCost, totalCartVal):
        cart_lines = cart.lines
        orders = []
        isGv = False
        if cart.coupon_code:
            try:
                pc = PromotionClient().get_client()
                isGv = pc.isGiftVoucher(cart.coupon_code)
            except:
                isGv = False
            
        insuranceDetails = InsuranceDetails.get_by(addressId = cart.address_id)
        
        for line in cart_lines:
            if line.line_status == LineStatus.LINE_ACTIVE:
                quantity_remaining_for_order = line.quantity
            
                for discount in line.discounts:
                    #i = 0
                    #while i < discount.quantity:
                    t_line_item = create_line_item(line, line.actual_price if isGv else (line.actual_price - discount.discount), line.quantity)
                    t_order = create_order(userId, cart.address_id, t_line_item, cart.pickupStoreId, discount.discount if isGv else 0, line.insurer, (line.insuranceAmount/line.quantity), insuranceDetails,line.dataProtectionInsurer,(line.dataProtectionAmount)/line.quantity, orderSource, line.freebieId, totalshippingCost, totalCartVal)
                    orders.append(t_order)
                        #i += 1
                    quantity_remaining_for_order -= discount.quantity
                
                if quantity_remaining_for_order > 0:
                    t_line_item = create_line_item(line, line.actual_price, quantity_remaining_for_order)
                    t_order = create_order(userId, cart.address_id, t_line_item, cart.pickupStoreId, 0, line.insurer, (line.insuranceAmount/line.quantity), insuranceDetails, line.dataProtectionInsurer,(line.dataProtectionAmount)/line.quantity, orderSource, line.freebieId, totalshippingCost, totalCartVal)
                    orders.append(t_order)
                '''
                i = 0
                while i < quantity_remaining_for_order:
                    t_line_item = create_line_item(line, line.actual_price)
                    t_order = create_order(userId, cart.address_id, t_line_item, cart.pickupStoreId, 0, line.insurer, (line.insuranceAmount/line.quantity), insuranceDetails, line.dataProtectionInsurer,(line.dataProtectionAmount)/line.quantity, orderSource, line.freebieId)
                    orders.append(t_order)
                    i += 1
                '''
        return orders
    
    def create_order(userId, address_id, t_line_item, pickupStoreId, gvAmount, insurer, insuranceAmount, insuranceDetails, dataProtectionInsurer, dataProtectionAmount, orderSource, freebieId, totalshippingCost, totalCartVal):
        user = User.get_by(id=userId)
        address = Address.get_by(id=address_id)
        t_order = TOrder()
        
        t_order.customer_id = user.id
        t_order.customer_email = user.email
        
        t_order.customer_name = address.name
        t_order.customer_pincode = address.pin
        t_order.customer_address1 = address.line_1
        t_order.customer_address2 = address.line_2
        t_order.customer_city = address.city
        t_order.customer_state = address.state
        t_order.customer_mobilenumber = address.phone
        
        t_order.total_amount = t_line_item.total_price + insuranceAmount + dataProtectionAmount
        t_order.gvAmount = gvAmount
        
        t_order.total_weight = t_line_item.total_weight
        t_order.lineitems = [t_line_item]
        
        t_order.status = OrderStatus.PAYMENT_PENDING
        t_order.statusDescription = "Payment Pending"
        t_order.created_timestamp = to_java_date(datetime.datetime.now())
        
        t_order.pickupStoreId = pickupStoreId 
        t_order.insuranceAmount = insuranceAmount 
        t_order.insurer = insurer
        if insuranceDetails:
            t_order.dob = insuranceDetails.dob
            t_order.guardianName = insuranceDetails.guardianName
        
        catalog_client = CatalogClient().get_client()
        
        if freebieId is None:
            freebie_item_id = catalog_client.getFreebieForItem(t_line_item.item_id)
            if freebie_item_id:
                t_order.freebieItemId = freebie_item_id
        else:
            freebie_item_id = None if freebieId == 0 else freebieId  
        t_order.source = orderSource
        t_order.dataProtectionInsurer = dataProtectionInsurer
        t_order.dataProtectionAmount = dataProtectionAmount
        t_order.shippingCost = round((t_line_item.total_price*totalshippingCost)/totalCartVal, 0)
        return t_order
            
    def create_line_item(line, final_price, quantity=1):
        inventory_client = CatalogClient().get_client()
        item = inventory_client.getItem(line.item_id)
        t_line_item = TLineItem()
        t_line_item.productGroup = item.productGroup
        t_line_item.brand = item.brand
        t_line_item.model_number = item.modelNumber
        if item.color is None or item.color == "NA":
            t_line_item.color = ""
        else:
            t_line_item.color = item.color
        t_line_item.model_name = item.modelName
        t_line_item.extra_info = item.featureDescription
        t_line_item.item_id = item.id
        t_line_item.quantity = quantity
        
        t_line_item.unit_price = final_price
        t_line_item.total_price = final_price * quantity
        
        t_line_item.unit_weight = item.weight
        t_line_item.total_weight = item.weight if item.weight is None else item.weight * quantity
        if line.dealText is None:
            t_line_item.dealText = item.bestDealText
        elif line.dealText == '':
            t_line_item.dealText = None
        else:
            t_line_item.dealText = line.dealText
            
        if item.warrantyPeriod:
            #Computing Manufacturer Warranty expiry date
            today = datetime.date.today()
            expiry_year = today.year + int((today.month + item.warrantyPeriod) / 12)
            expiry_month = (today.month + item.warrantyPeriod) % 12
            
            try:
                expiry_date = datetime.datetime(expiry_year, expiry_month, today.day, 23, 59, 59, 999999)
            except ValueError:
                try:
                    expiry_date = datetime.date(expiry_year, expiry_month, (today.day - 1), 23, 59, 59, 999999)
                except ValueError:
                    try:
                        expiry_date = datetime.date(expiry_year, expiry_month, (today.day - 2), 23, 59, 59, 999999)
                    except ValueError:
                        expiry_date = datetime.date(expiry_year, expiry_month, (today.day - 3), 23, 59, 59, 999999)
            
            t_line_item.warrantry_expiry_timestamp = to_java_date(expiry_date)
            
        return t_line_item
        
    def validate_cart(cartId, sourceId, couponCode):
        inventory_client = CatalogClient().get_client()
        logistics_client = LogisticsClient().get_client()
        promotion_client = PromotionClient().get_client()
        retval = ""
        emival = ""
        # No need to validate duplicate items since there are only two ways
        # to add items to a cart and both of them check whether the item being
        # added is a duplicate of an already existing item.
        cart = Cart.get_by(id=cartId)
        cart_lines = cart.lines
        customer_pincode = None
        current_time = datetime.datetime.now()
        if cart.pickupStoreId :
            store = logistics_client.getPickupStore(cart.pickupStoreId)
            customer_pincode = store.pin
        if cart.address_id != None and customer_pincode == None:
            address = Address.get_by(id=cart.address_id)
            customer_pincode = address.pin
    
        user = User.get_by(active_cart_id = cartId)
        
        dealItems = []
        privateDealUser = PrivateDealUser.get_by(id=user.id)    
        if privateDealUser is not None and privateDealUser.isActive:
            itemIds = [cartLine.item_id for cartLine in cart.lines]
            deals = inventory_client.getAllActivePrivateDeals(itemIds, 0)
            dealItems = deals.keys()
    
        if not customer_pincode:
            default_address_id = user.default_address_id
            if default_address_id:
                address = Address.get_by(id = default_address_id)
                customer_pincode = address.pin
        if not customer_pincode:
            #FIXME should not be hard coded. May be we can pick from config server.
            customer_pincode = "110001"
        cart.total_price = 0
        for line in cart_lines:
            old_estimate = line.estimate
            item_id = line.item_id
            item = inventory_client.getItemForSource(item_id, sourceId)
            
            item_shipping_info = inventory_client.isActive(item_id) 
            if item_shipping_info.isActive:
                if item_shipping_info.isRisky and item_shipping_info.quantity < line.quantity:
                    line.quantity = 1
                    retval = "Try adding a smaller quantity of " + item.brand + " " + item.modelNumber + " (" + item.color + ")"
                     
                if item_id in dealItems:
                    line.actual_price = deals[item_id].dealPrice
                    if deals[item_id].dealTextOption==0:
                        line.dealText = ''
                    if deals[item_id].dealTextOption==2:
                        line.dealText =  deals[item_id].dealText
                        
                    if deals[item_id].dealFreebieOption==0:
                        line.freebieId = 0
                    if deals[item_id].dealFreebieOption==2:
                        line.freebieId =  deals[item_id].dealFreebieItemId
    
                else:
                    line.actual_price = item.sellingPrice 
                    line.dealText = None
                    line.freebieId = None
                cart.total_price = cart.total_price + (line.actual_price * line.quantity)
                try:
                    item_delivery_estimate = logistics_client.getLogisticsEstimation(item_id, customer_pincode, DeliveryType.PREPAID).deliveryTime
                except LogisticsServiceException:
                    item_delivery_estimate = -1
                    #TODO Use the exception clause to set the retval appropriately
                except :
                    item_delivery_estimate = -1
                    
                if item_delivery_estimate !=-1:
                    inv_client = InventoryClient().get_client()
                    itemAvailability = None
                    try:
                        itemAvailability = inv_client.getItemAvailabilityAtLocation(item_id, 1)
                    except:
                        pass
                    
                    print 'itemAvailability billling Warehouse ', itemAvailability[2]
                    if itemAvailability is not None:
                        billingWarehouse = None
                        try:
                            billingWarehouse = inv_client.getWarehouse(itemAvailability[2])
                        except:
                            pass
                        
                        print 'billingWarehouse Id Location ', billingWarehouse.stateId
                        if billingWarehouse is not None:
                            estimateVal = None
                            if not logistics_client.isAlive() :
                                logistics_client = LogisticsClient().get_client()
                            try:
                                estimateVal = logistics_client.getFirstDeliveryEstimateForWhLocation(customer_pincode, billingWarehouse.stateId)
                                if estimateVal ==-1:
                                    item_delivery_estimate =-1
                            except:
                                pass
                            print 'estimateVal Value ', estimateVal
                if old_estimate != item_delivery_estimate:
                    line.estimate = item_delivery_estimate
                    cart.updated_on = current_time
            else:
                Discount.query.filter(Discount.line==line).delete()
                line.delete()
        if cart.checked_out_on is not None:
            if cart.updated_on > cart.checked_out_on:
                cart.checked_out_on = None
        session.commit()
        
        if cart.coupon_code is not None:
            try:
                updated_cart = promotion_client.applyCoupon(cart.coupon_code, cart.id)
                if updated_cart.message is not None:
                    emival = updated_cart.message
            except PromotionException as ex:
                remove_coupon(cart.id)
                #retval = ex.message
        session.commit()
        
        cart = Cart.get_by(id=cartId)
        cart_lines = cart.lines
        map_lines = {}
        
        insurerFlag = False
        for line in cart_lines:
            if line.insurer > 0 or line.dataProtectionInsurer > 0:
                line_map = {}
                line_map['insurer'] = line.insurer
                line_map['dpinsurer'] = line.dataProtectionInsurer
                line_map['amount'] = line.discounted_price if line.discounted_price else line.actual_price
                line_map['quantity'] = line.quantity
                insurerFlag = True
                map_lines[line.item_id] = line_map
            
        if insurerFlag:
            map_lines = inventory_client.checkServices(map_lines)
            for line in cart_lines :
                if map_lines.has_key(line.item_id):
                    line_map = map_lines[line.item_id]
                    if line_map['insurer'] > 0:
                        if cart.discounted_price:
                            cart.discounted_price = cart.discounted_price + line_map['insureramount']
                        line.insurer = line_map['insurer']
                        line.insuranceAmount = line_map['insureramount']
                        cart.total_price = cart.total_price + line_map['insureramount']
                    if line_map['dpinsurer'] > 0:
                        if cart.discounted_price:
                            cart.discounted_price = cart.discounted_price + line_map['dpinsureramount']
                        line.dataProtectionInsurer = line_map['dpinsurer']
                        line.dataProtectionAmount = line_map['dpinsureramount']
                        cart.total_price = cart.total_price + line_map['dpinsureramount']
                    line.updated_on = datetime.datetime.now()
            cart.updated_on = datetime.datetime.now()
            session.commit()
        session.close()
        return [retval, emival]
    
    def merge_cart(fromCartId, toCartId):
        fromCart = Cart.get_by(id=fromCartId)
        toCart = Cart.get_by(id=toCartId)
        
        old_lines = fromCart.lines
        new_lines = toCart.lines
        
        for line in old_lines:
            for discount in line.discounts:
                discount.delete()
        session.commit()
        
        for line in old_lines:
            flag = True
            for new_line in new_lines:
                if line.item_id == new_line.item_id:
                    flag = False
            
            if flag:
                line.cart_id = toCartId
            else:
                line.delete()
                
        if toCart.coupon_code is None:
            toCart.coupon_code = fromCart.coupon_code
        
        toCart.updated_on = datetime.datetime.now()
        fromCart.expired_on = datetime.datetime.now()
        fromCart.cart_status = CartStatus.INACTIVE
        session.commit()
    
    def check_out(cartId):
        if cartId is None:
            raise ShoppingCartException(101, "Cart id not specified")
        cart = Cart.get_by(id = cartId)
        if cart is None:
            raise ShoppingCartException(102, "The specified cart couldn't be found")
        cart.checked_out_on = datetime.datetime.now()
        session.commit()
        return True
    
    def reset_cart(cartId, items):
        if cartId is None:
            raise ShoppingCartException(101, "Cart id not specified")
        for item_id, quantity in items.iteritems():
            line = Line.query.filter_by(cart_id=cartId, item_id=item_id).one()
            if line is not None:
                delete_discounts_for_line(line)
                line.discounted_price = None
                line.quantity = line.quantity - quantity
                if line.quantity == 0:
                    line.delete()
        cart = Cart.get_by(id=cartId)
        cart.updated_on = datetime.datetime.now()
        cart.checked_out_on = None
        
        # Removing Coupon
        cart.total_price = None
        cart.discounted_price = None
        cart.coupon_code = None
        
        session.commit()
        return True
    
    def get_carts_with_coupon_count(coupon_code):
        return Cart.query.filter_by(coupon_code = coupon_code).count()
    
    def show_cod_option(cartId, sourceId, pincode):
        cart = Cart.get_by(id = cartId)
        cod_option = True
        logistics_client = LogisticsClient().get_client()
        if cart:
            if cart.coupon_code:
                promotion_client = PromotionClient().get_client()
                cod_option = promotion_client.isCodApplicable(to_t_cart(cart))
            
            if cod_option and cart.lines:
                for line in cart.lines:
                    logistics_info = logistics_client.getLogisticsEstimation(line.item_id, pincode, DeliveryType.PREPAID)
                    if not logistics_info.codAllowed:
                        cod_option = False
                        break
                if cart.total_price > 60000:# or cart.total_price <= 250:
                    cod_option = False
        return cod_option
    
    def get_products_added_to_cart(startDate, endDate):
        lines = session.query(Line.item_id).filter(Line.created_on > to_py_date(startDate)).filter(Line.created_on < to_py_date(endDate)).all()
        datas = []
        for line in lines:
            datas.append(line[0])
        return datas
    
    def insure_item(itemId, cartId, toInsure, insurerType):
        cart = Cart.get_by(id = cartId)
        line = None
        for cartLine in cart.lines:
            if(cartLine.item_id == itemId):
                line = cartLine
                break
            
        if not line:
            print("Error : No line found for cartId : " + cartId + " and itemId : " + itemId)
            return False
        
        try:
            if toInsure:
                csc = CatalogClient().get_client()
                item = csc.getItem(itemId)
                insurerId = csc.getPrefferedInsurerForItem(itemId,insurerType)
                insuranceAmount = csc.getInsuranceAmount(itemId, line.discounted_price if line.discounted_price else line.actual_price, insurerId, line.quantity)
                if InsurerType._VALUES_TO_NAMES.get(insurerType)=='DEVICE':
                    if cart.discounted_price:
                        cart.discounted_price = cart.discounted_price - line.insuranceAmount + insuranceAmount
                    line.insurer = insurerId
                    line.insuranceAmount = insuranceAmount
                if InsurerType._VALUES_TO_NAMES.get(insurerType)=='DATA':
                    if cart.discounted_price:
                        cart.discounted_price = cart.discounted_price - line.dataProtectionAmount + insuranceAmount
                    line.dataProtectionInsurer = insurerId
                    line.dataProtectionAmount = insuranceAmount
                cart.total_price = cart.total_price + insuranceAmount
            else:
                if InsurerType._VALUES_TO_NAMES.get(insurerType)=='DEVICE':
                    cart.total_price = cart.total_price - line.insuranceAmount
                    if cart.discounted_price:
                        cart.discounted_price = cart.discounted_price - line.insuranceAmount
                    line.insurer = 0
                    line.insuranceAmount = 0
                if InsurerType._VALUES_TO_NAMES.get(insurerType)=='DATA':
                    cart.total_price = cart.total_price - line.dataProtectionAmount
                    if cart.discounted_price:
                        cart.discounted_price = cart.discounted_price - line.dataProtectionAmount
                    line.dataProtectionInsurer = 0
                    line.dataProtectionAmount = 0
            line.updated_on = datetime.datetime.now()
            cart.updated_on = datetime.datetime.now()
            session.commit()
        except:
            print("Error : Unable to insure")
            print("insurerId : " + str(insurerId) + " ItemId : " + str(itemId) + " CartId : " + str(cartId))
            return False
        
        return True
    
    def cancel_insurance(cartId):
        try:
            cart = Cart.get_by(id = cartId)
            for cartLine in cart.lines:
                cart.total_price = cart.total_price - cartLine.insuranceAmount
                if cart.discounted_price:
                    cart.discounted_price = cart.discounted_price - cartLine.insuranceAmount
                cartLine.insurer = 0
                cartLine.insuranceAmount = 0
                cartLine.updated_on = datetime.datetime.now()
            cart.updated_on = datetime.datetime.now()
            session.commit()
        except:
            print("Error : Unable to cancel insurance for cartId :" + str(cartId))
            return False
        
        return True
    
    def store_insurance_specific_details(addressId, dob, guardianName):
        try:
            insuranceDetails = InsuranceDetails.get_by(addressId = addressId);
            if insuranceDetails is None :
                insuranceDetails = InsuranceDetails()
            insuranceDetails.addressId = addressId
            insuranceDetails.dob = dob
            insuranceDetails.guardianName = guardianName
            session.commit()
        except:
            print("Error : Unable to store insurance details for addressId : " + str(addressId))
            return False
        return True
    
    def is_insurance_detail_present(addressId):
        try:
            insuranceDetails = InsuranceDetails.get_by(addressId = addressId);
            if insuranceDetails is None :
                return False
        except:
            print("Error : Unable to get insurance details for addressId : " + str(addressId))
            return False
        return True
    
    
    def add_items_to_cart(cartId, itemQty, couponCode=None):
        try: 
            found_cart = Cart.get_by(id=cartId)
            itemQtyMap = {}
            current_time = datetime.datetime.now()
            for itemqty in itemQty:
                itemQtyMap[itemqty.itemId] = itemqty.qty 
                
            for line in found_cart.lines:
                if itemQtyMap.has_key(line.item_id):
                    line.delete()
            for itemId,qty in itemQtyMap.iteritems():
                #This condition will ensure that cart is only persisted with non-zero quantities.
                if qty==0:
                    continue
                line = Line()
                line.cart = found_cart
                line.item_id = itemId
                line.quantity = qty
                line.created_on = current_time
                line.updated_on = current_time
                line.line_status = LineStatus.LINE_ACTIVE
                line.insurer = 0
                line.insuranceAmount = 0
            if couponCode:
                found_cart.coupon_code = couponCode
            else:
                found_cart.coupon_code = None
            session.commit()
            return True
        except:
            traceback.print_exc()
            return False
                 
        
    def valiate_cart_new(cartId, customer_pincode, sourceId):
        
        inventory_client = CatalogClient().get_client()
        logistics_client = LogisticsClient().get_client()
        promotion_client = PromotionClient().get_client()
        # No need to validate duplicate items since there are only two ways
        # to add items to a cart and both of them check whether the item being
        # added is a duplicate of an already existing item.
        cart = Cart.get_by(id=cartId)
        cart_lines = cart.lines
        current_time = datetime.datetime.now()
    
        user = User.get_by(active_cart_id = cartId)
        responseMap = {}
        totalQty = 0
        totalAmount = 0 
        shippingCharges=0
        cartMessages=[]
        cartItems = []
        dealItems = []
        
        responseMap['shippingCharges']= shippingCharges
        responseMap['cartMessages']= cartMessages
        responseMap['cartItems']= cartItems
        responseMap['pincode']= customer_pincode
    
        privateDealUser = PrivateDealUser.get_by(id=user.id)    
        itemIds = [cartLine.item_id for cartLine in cart.lines]
        if privateDealUser is not None and privateDealUser.isActive:
            deals = inventory_client.getAllActivePrivateDeals(itemIds, 0)
            dealItems = deals.keys()
    
        cart.total_price = 0
        itemsMap = inventory_client.getItems(itemIds)
        
        cartMessageChanged = 0
        cartMessageOOS = 0
        cartMessageUndeliverable = 0
        
        for line in cart_lines:
            cartItem={}
            
            old_estimate = line.estimate
            item_id = line.item_id
            item = itemsMap.get(item_id)
            cartItem['itemId']=line.item_id
            cartItem['quantity']=0
            cartItem['color'] = item.color
            cartItem['catalogItemId'] = item.catalogItemId
            
            item_shipping_info = inventory_client.isActive(item_id) 
            if item_shipping_info.isActive:
                if item_shipping_info.isRisky and item_shipping_info.quantity < line.quantity:
                    line.quantity = item_shipping_info.quantity
                    cartMessageChanged += 1
                    cartItemMessages.append({"type":"danger", "messageText":"Only " + str(item_shipping_info.quantity) + " available"})
                
                cartItem['maxQuantity'] = min(item_shipping_info.quantity, 20)
                
                if item_id in dealItems:
                    line.actual_price = deals[item_id].dealPrice
                    if deals[item_id].dealTextOption==0:
                        line.dealText = ''
                    if deals[item_id].dealTextOption==2:
                        line.dealText = deals[item_id].dealText
                        
                    if deals[item_id].dealFreebieOption==0:
                        line.freebieId = 0
                    if deals[item_id].dealFreebieOption==2:
                        line.freebieId =  deals[item_id].dealFreebieItemId
                    cartItem['dealText'] = line.dealText
                else:
                    line.actual_price = item.sellingPrice
                    if item.bestDealText:
                        cartItem['dealText'] = item.bestDealText
                    line.dealText = None
                    line.freebieId = None
                cartItem['sellingPrice'] = line.actual_price
                cartItem['quantity'] = line.quantity
                cart.total_price = cart.total_price + (line.actual_price * line.quantity)
                try:
                    item_delivery_estimate = logistics_client.getLogisticsEstimation(item_id, customer_pincode, DeliveryType.PREPAID).deliveryTime
                except LogisticsServiceException:
                    item_delivery_estimate = -1
                    #TODO Use the exception clause to set the retval appropriately
                except :
                    item_delivery_estimate = -1
                    
                if item_delivery_estimate !=-1:
                    inv_client = InventoryClient().get_client()
                    itemAvailability = None
                    try:
                        itemAvailability = inv_client.getItemAvailabilityAtLocation(item_id, 1)
                    except:
                        pass
                    
                    print 'itemAvailability billling Warehouse ', itemAvailability[2]
                    if itemAvailability is not None:
                        billingWarehouse = None
                        try:
                            billingWarehouse = inv_client.getWarehouse(itemAvailability[2])
                        except:
                            pass
                        
                        print 'billingWarehouse Id Location ', billingWarehouse.stateId
                        if billingWarehouse is not None:
                            estimateVal = None
                            if not logistics_client.isAlive() :
                                logistics_client = LogisticsClient().get_client()
                            try:
                                estimateVal = logistics_client.getFirstDeliveryEstimateForWhLocation(customer_pincode, billingWarehouse.stateId)
                                if estimateVal ==-1:
                                    item_delivery_estimate =-1
                            except:
                                pass
                            print 'estimateVal Value ', estimateVal
                cartItem['estimate'] = item_delivery_estimate
                if item_delivery_estimate == -1:
                    cartItem['quantity'] = 0
                    cartMessageUndeliverable += 1
                    cartItemMessages.append({"type":"danget", "messageText":"Undeliverable"})
                if old_estimate != item_delivery_estimate:
                    line.estimate = item_delivery_estimate
                    cart.updated_on = current_time
            else:
                cartItem['quantity'] = 0
                cartMessageOOS += 1
                cartItemMessages.append({"type":"danger", "messageText":"Out of Stock"})
                Discount.query.filter(Discount.line==line).delete()
                line.delete()
            totalQty += cartItem['quantity']
            totalAmount += line.actual_price * cartItem['quantity']
            if cartItemMessages:
                cartItems.insert(0, cartItem)
            else:
                cartItems.append(cartItem)
        if cart.checked_out_on is not None:
            if cart.updated_on > cart.checked_out_on:
                cart.checked_out_on = None
        session.commit()
        
        if cart.coupon_code is not None:
            try:
                updated_cart = promotion_client.applyCoupon(cart.coupon_code, cart.id)
                if updated_cart.message is not None:
                    emival = updated_cart.message
            except PromotionException as ex:
                remove_coupon(cart.id)
                #retval = ex.message
        session.commit()
        
        cart = Cart.get_by(id=cartId)
        cart_lines = cart.lines
        insurerFlag = False
        for line in cart_lines:
            if line.insurer > 0 or line.dataProtectionInsurer > 0:
                line.insurer = 0
                line.insuranceAmount = 0 
                line.dataProtectionInsurer = 0
                line.dataProtectionAmount = 0
                insurerFlag = True
            
        if insurerFlag:
            cart.updated_on = datetime.datetime.now()
            session.commit()
        session.close()
        responseMap['totalQty']= totalQty
        responseMap['totalAmount']= totalAmount
        if totalAmount < 500:
            shippingCharges = 100
        elif totalAmount < 1000:
            shippingCharges = 50
        responseMap['shippingCharge']=shippingCharges
        responseMap['cartMessageChanged'] = cartMessageChanged
        responseMap['cartMessageOOS'] = cartMessageOOS
        responseMap['cartMessageUndeliverable'] = cartMessageUndeliverable
        return json.dumps(responseMap)
        
        
    def validate_cart_plus(cart_id, source_id, couponCode):
        try:
            cart_messages = validate_cart(cart_id, source_id, couponCode)
            found_cart = Cart.get_by(id=cart_id)
            pincode = "110001"
            default_address_id = User.get_by(active_cart_id = cart_id).default_address_id
            
            default_address = None
            if found_cart.address_id is not None and found_cart.address_id > 0:
                pincode = Address.get_by(id=found_cart.address_id).pin
            elif default_address_id is not None:
                default_address = Address.get_by(id = default_address_id) 
                pincode = default_address.pin
            
            needInuranceInfo = False
            if default_address_id is not None:
                for line in found_cart.lines:
                    if line.insurer > 0:
                        needInuranceInfo = not is_insurance_detail_present(default_address_id)
                        break
            cartPlus = CartPlus()
            cartPlus.cart = to_t_cart(found_cart)
            cartPlus.pinCode = pincode
            cartPlus.validateCartMessages = cart_messages
            cartPlus.needInsuranceInfo = needInuranceInfo
            return cartPlus
        finally:
            close_session()
    
    def close_session():
        if session.is_active:
            print "session is active. closing it."
            session.close()