Subversion Repositories SmartDukaan

Rev

Rev 3133 | Rev 3554 | 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.model.v1.user.impl.Dataservice import Cart, Line, Address, User
from shop2020.thriftpy.model.v1.user.ttypes import CartStatus, LineStatus, ShoppingCartException,\
    PromotionException
import datetime
from shop2020.utils.Utils import to_py_date, to_java_date

from shop2020.thriftpy.model.v1.order.ttypes import Transaction as TTransaction,\
    TransactionStatus as TTransactionStatus, Order as TOrder, LineItem as TLineItem, OrderStatus 

from shop2020.thriftpy.model.v1.catalog.ttypes import Item as TItem
from shop2020.thriftpy.logistics.ttypes import LogisticsInfo as TLogisticsInfo,\
    LogisticsServiceException

from shop2020.clients.TransactionClient import TransactionClient
from shop2020.clients.CatalogClient import CatalogClient
from shop2020.clients.LogisticsClient import LogisticsClient
from shop2020.model.v1 import user
from shop2020.clients.PromotionClient import PromotionClient
from shop2020.model.v1.user.impl import UserDataAccessors

def get_cart(user_id):
    query = Cart.query.filter_by(user_id=user_id)      
    query = query.filter_by(cart_status = CartStatus.ACTIVE)
    try:
        cart = query.one()
        session.commit()
    except:
        return None
#        raise ShoppingCartException(101, "Cart does not exist")
    return cart

def get_cart_by_id(id):
    cart = Cart.get_by(id=id)
    return cart

def create_cart(user_id):
    cart = get_cart(user_id)
    if not cart: 
        cart = Cart()
        cart.user_id = user_id
        cart.created_on = datetime.datetime.now()
        cart.updated_on = datetime.datetime.now()
        cart.cart_status = CartStatus.ACTIVE
        session.commit()
    return cart

def get_cart_by_user_id_and_status(user_id, status):
    query = Cart.query.filter_by(user_id=user_id)
    if status:
        query = query.filter_by(cart_status=status)
    carts = query.all()
    return carts

def get_carts_by_status(status):
    return Cart.query.filter_by(cart_status=status).all()

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 change_cart_status(cart_id, status):
    cart = get_cart_by_id(id)
    if not cart:
        raise ShoppingCartException(101, "no cart attached to this id")
    if not status:
        raise ShoppingCartException(101, "invalid status")
    cart.cart_status = status
    session.commit()
    
def add_item_to_cart(cart_id, item_id, quantity):
    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")
    retval = ""
    inventory_client = CatalogClient().get_client()
    item = inventory_client.getItem(item_id)
    item_shipping_info = inventory_client.isActive(item_id)
    if not item_shipping_info.isActive:
        return inventory_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.quantity = quantity
        line.updated_on = current_time
    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.line_status = LineStatus.LINE_ACTIVE
    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)
    item.delete()
    current_time = datetime.datetime.now()
    cart.updated_on = current_time
    session.commit()

def change_item_status(cart_id, item_id, status):
    if not status:
        raise ShoppingCartException(101, "Status cannot be made null")
    line = get_line(item_id, cart_id, None, True)
    if line:
        line.line_status = status
        current_time = datetime.datetime.now()
        line.updated_on = current_time
        line.cart.updated_on = current_time
        session.commit()
    else:
        raise ShoppingCartException(101, "Unable to probe the line you desired")
    
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 apply_coupon_to_cart(cart_id, coupon_code, total_price, discounted_price):
    cart = get_cart_by_id(cart_id)
    if not cart:
        raise ShoppingCartException(101, "no cart attached to this id")
    cart.total_price = total_price
    cart.discounted_price = discounted_price
    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
    
    cart.discounted_price = None
    cart.coupon_code = None
    session.commit()
    
def commit_cart(cart_id, sessionSource, sessionTime):   
    cart = get_cart_by_id(cart_id)   
    #now we have a cart. Need to create a transaction with it
    txn = TTransaction()
    txn.shoppingCartid = cart_id
    txn.customer_id = cart.user_id
    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.orders = create_orders(cart)
    
    transaction_client = TransactionClient().get_client()
    txn_id = transaction_client.createTransaction(txn)
    session.commit()
    
    #new_cart = create_cart(cart.user_id)
    #user = User.get_by(id=cart.user_id)
    #user.active_cart_id = new_cart.id
    #session.commit()
    return txn_id

def create_orders(cart):
    cart_lines = cart.lines
    orders = []
    
    for line in cart_lines:
        if line.line_status == LineStatus.LINE_ACTIVE:
            i = 0
            while i< line.quantity:
                t_line_item = create_line_item(line.item_id, line.discounted_price)
                t_order = create_order(cart.user_id, cart.address_id, t_line_item)
                orders.append(t_order)
                i += 1
    return orders

def create_order(user_id, address_id, t_line_item):
    user = User.get_by(id=user_id)
    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
    
    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())
    
    return t_order
        
def create_line_item(item_id, discounted_price):
    inventory_client = CatalogClient().get_client()
    item = inventory_client.getItem(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 = 1
    
    if discounted_price is None or discounted_price == 0:
        t_line_item.unit_price = item.sellingPrice
        t_line_item.total_price = item.sellingPrice
    else:
        t_line_item.unit_price = discounted_price
        t_line_item.total_price = discounted_price
    
    t_line_item.unit_weight = item.weight
    t_line_item.total_weight = item.weight
    return t_line_item
    
def validate_cart(cartId):
    inventory_client = CatalogClient().get_client()
    logistics_client = LogisticsClient().get_client()
    promotion_client = PromotionClient().get_client()
    retval = ""
    # 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.address_id:
        address = Address.get_by(id=cart.address_id)
        customer_pincode = address.pin
    if not customer_pincode:
        user = User.get_by(active_cart_id = cartId)
        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.getItem(item_id)
        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 + ")"
            
            line.actual_price = item.sellingPrice 
            cart.total_price = cart.total_price + (line.actual_price * line.quantity)
            try:
                item_delivery_estimate = logistics_client.getLogisticsEstimation(item_id, customer_pincode).deliveryTime
            except LogisticsServiceException:
                item_delivery_estimate = -1
                #TODO Use the exception clause to set the retval appropriately
            except :
                item_delivery_estimate = -1
            if old_estimate != item_delivery_estimate:
                line.estimate = item_delivery_estimate
                cart.updated_on = current_time
                if old_estimate != None:
                    retval = "Delivery Estimates updated."
        else:
            line.delete()
            retval = "Some items have been removed from the cart."
    if cart.checked_out_on is not None:
        if cart.updated_on > cart.checked_out_on:
            cart.checked_out_on = None
            if retval == "":
                retval = "Your cart has been updated after the last checkout."
    session.commit()
    
    if cart.coupon_code is not None:
        try:
            updated_cart = promotion_client.applyCoupon(cart.coupon_code, cart.id)
            for t_line in updated_cart.lines:
            #Find the line in the database which corresponds to this line
                line = Line.query.filter_by(cart = cart).filter_by(item_id = t_line.itemId).one()
            #Update its discounted price.
                line.discounted_price = t_line.discountedPrice
            cart.discounted_price = updated_cart.discountedPrice
            session.commit()
        except PromotionException as ex:
            remove_coupon(cart.id)
            retval = ex.message
    return retval

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:
        flag = True
        for new_line in new_lines:
            if line.item_id == new_line.item_id:
                flag = False
        if flag:
            toCart.lines.append(line)
    
    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:
            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 close_session():
    if session.is_active:
        print "session is active. closing it."
        session.close()