Subversion Repositories SmartDukaan

Rev

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

'''
Created on 23-Mar-2010

@author: ashish
'''
from elixir import *
from shop2020.model.v1.catalog.impl import DataService
from shop2020.model.v1.catalog.impl.DataService import Item, \
    Warehouse, ItemInventoryHistory, CurrentInventorySnapshot, ItemInfo,\
    ItemChangeLog, BestSellers, Category
from shop2020.thriftpy.model.v1.catalog.ttypes import \
    InventoryServiceException, status
from shop2020.model.v1.catalog.impl.Convertors import to_t_item
import datetime
from shop2020.utils.Utils import log_entry, to_py_date
from sqlalchemy import desc, asc


def initialize():
    DataService.initialize()
    

def get_all_items(is_active):
    if is_active:
        return Item.query.filter_by(status= status.ACTIVE).all()
    else:
        return Item.query.all()
    
def get_all_items_by_status(status):
    if not status:
        #return all items
        return get_all_items(False)
    else:
        return Item.query.filter_by(status=status).all()

def get_item(item_id):
    return Item.get_by(id=item_id)

def get_items_by_catalog_id(catalog_id):
    query = Item.query.filter_by(catalog_item_id=catalog_id)
    try:
        items = query.all()
        return get_thrift_item_list(items)
    except:
        raise InventoryServiceException(109, "Item not found")
        
def get_item_by_vendor_id(vendor_id):
    query = Item.query.filter_by(vendor_item_id=vendor_id)
    #query = Item.query.filter_by(vendor_item_id='6417182037054')
    try:
        return query.one()
    except:
        raise InventoryServiceException(109, "Item not found")
        
def is_active(item_id):
    try:
        item = get_item(item_id)
        return item.status == status.ACTIVE
    except InventoryServiceException:
        return False
        
def get_Warehouse(warehouse_id):
    return Warehouse.get_by(id=warehouse_id)

def get_all_warehouses_by_status(status):
    if not status:
        return Warehouse.query.all()
    else:
        return Warehouse.query.filter_by(status=status)

def get_all_warehouses_for_item(item_id):
    item = get_item(item_id)
    if not item:
        raise InventoryServiceException(108, "Some unforeseen error while obtaining item")
    return item.get_all_warehouses

def get_all_items_for_warehouse(warehouse_id):
    warehouse = get_Warehouse(warehouse_id)
    if not warehouse:
        raise InventoryServiceException(108, "bad warehouse")
    return warehouse.all_items

def add_warehouse(warehouse):
    if not warehouse:
        raise InventoryServiceException(108, "Bad warehouse")
    if get_Warehouse(warehouse.id):
        #warehouse is already present.
        raise InventoryServiceException(101, "Warehouse already present")
    
    ds_warehouse = Warehouse()
    ds_warehouse.id = warehouse.id
    ds_warehouse.location = warehouse.location
    ds_warehouse.status = status.ACTIVE
    ds_warehouse.addedOn = datetime.datetime.now()
    ds_warehouse.lastCheckedOn = datetime.datetime.now()
    ds_warehouse.tinNumber = warehouse.tinNumber
    ds_warehouse.pincode = warehouse.pincode
    if warehouse.vendorString:
        ds_warehouse.vendorString = warehouse.vendorString
    session.commit()
    return ds_warehouse.id

def update_item(item):
    if not item:
        raise InventoryServiceException(108, "Bad item in request")
    
    if not item.id:
        raise InventoryServiceException(101, "Missing id for update")
    
    ds_item = get_item(item.id)
    
    if not ds_item:
        raise InventoryServiceException(101, "Item missing in our database")
    
    if item.manufacturerName:
        ds_item.manufacturer_name = item.manufacturerName
    if item.modelName:
        ds_item.model_name = item.modelName
    if item.modelNumber:
        ds_item.model_number = item.modelNumber
    if item.color:
        ds_item.color = item.color
    if item.category:
        ds_item.category = item.category
    if item.comments:
        ds_item.comments = item.comments
    
    if item.catalogItemId:
        ds_item.catalog_item_id = item.catalogItemId
    if item.vendorItemId:
        ds_item.vendor_item_id = item.vendorItemId
    else:
        raise InventoryServiceException(101, "Vendor item id cannot be missing")

    if item.mrp:
        ds_item.mrp = item.mrp
    if item.mop:
        ds_item.mop = item.mop
    if item.sellingPrice:
        ds_item.sellingPrice = item.sellingPrice
    if item.dealerPrice:
        ds_item.dealerPrice = item.dealerPrice
    if item.weight:
        ds_item.weight = item.weight
    if item.itemStatus:
        ds_item.status = item.itemStatus
    
    if item.startDate:
        ds_item.startDate = item.startDate
    if item.retireDate:
        ds_item.retireDate = item.retireDate
    
    if item.featureId:
        ds_item.feature_id = item.featureId
    if item.featureDescription:
        ds_item.feature_description = item.featureDescription
    
    if item.bestDealText:
        ds_item.bestDealText = item.bestDealText
    if item.bestDealValue:
        ds_item.bestDealValue = item.bestDealValue
    
    ds_item.updated_on = datetime.datetime.now()
    session.commit();
    return ds_item.id

def add_item(item):
    if not item:
        raise InventoryServiceException(108, "Bad item in request")
    if get_item(item.id):
        raise InventoryServiceException(101, "Item already exists")

    ds_item = Item()
    if item.id:
        ds_item.id = item.id
    if item.manufacturerName:
        ds_item.manufacturer_name = item.manufacturerName
    if item.modelName:
        ds_item.model_name = item.modelName
    if item.modelNumber:
        ds_item.model_number = item.modelNumber
    if item.color:
        ds_item.color = item.color
    if item.category:
        ds_item.category = item.category
    if item.comments:
        ds_item.comments = item.comments

    if item.catalogItemId:
        ds_item.catalog_item_id = item.catalogItemId
    if item.vendorItemId:
        ds_item.vendor_item_id = item.vendorItemId
    else:
        raise InventoryServiceException(101, "vendor item id cannot be missing")
    if item.itemStatus:
        ds_item.status = item.itemStatus
    else: #this is for update calls
        ds_item.status = status.IN_PROCESS
    ds_item.addedOn = datetime.datetime.now()
    ds_item.updatedOn = datetime.datetime.now()
    
    if item.mrp:
        ds_item.mrp = item.mrp
    if item.mop:
        ds_item.mop = item.mop
    if item.sellingPrice:
        ds_item.sellingPrice = item.sellingPrice
    if item.dealerPrice:
        ds_item.dealerPrice = item.dealerPrice
    if item.weight:
        ds_item.weight = item.weight
    
    if item.featureId:
        ds_item.feature_id = item.featureId
    if item.featureDescription:
        ds_item.feature_description = item.featureDescription
    
    if item.otherInfo:
        for k,v in item.otherInfo.iteritems():
            info = ItemInfo()
            info.key = k
            info.value = v
            ds_item.iteminfo.append(info)
    #check if categories present. If yes, add them to system
    
    if item.bestDealValue:
        ds_item.bestDealValue = item.bestDealValue
    if item.bestDealText:
        ds_item.bestDealText = item.bestDealText
    
    session.commit();
    return ds_item.id       
    
def update_inventory(warehouse_id, timestamp, availability):
    warehouse = get_Warehouse(warehouse_id)
    if not warehouse:
        raise InventoryServiceException(107, "Warehouse? Where?")
     
    time = datetime.datetime.now()
    warehouse.lastCheckedOn = time
    warehouse.vendorString = timestamp
    
    for item_pk, quantity in availability.iteritems():
        try:
            brand, model, color = item_pk.split(';')
            item = Item.query.filter_by(manufacturer_name=brand, model_number=model, color=color).one()
        except:
            continue  
        try:
            item_inventory_history = ItemInventoryHistory()
            item_inventory_history.warehouse = warehouse
            item_inventory_history.item = item
            item_inventory_history.timestamp = time
            item_inventory_history.availibility = quantity

            current_inventory_snapshot = CurrentInventorySnapshot.get_by(item=item, warehouse=warehouse)
            if not current_inventory_snapshot:
                current_inventory_snapshot = CurrentInventorySnapshot()
                current_inventory_snapshot.item = item
                current_inventory_snapshot.warehouse = warehouse
                current_inventory_snapshot.availibility = 0
            # added the difference in the current inventory    
            current_inventory_snapshot.availibility = current_inventory_snapshot.availibility + quantity
        except:
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
    session.commit() 

def get_item_inventoy(item_id):
    
    inventory = Item.get_by(id=item_id).currentInventory
    if not inventory:
        raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
    return inventory

def get_item_inventory_by_item_id(item_id):
    inventory = Item.get_by(id=item_id).currentInventory
    if not inventory:
        raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
    return inventory

    
def retire_warehouse(warehouse_id):
    if not warehouse_id:
        raise InventoryServiceException(101, "Bad warehouse id")
    warehouse = get_Warehouse(warehouse_id)
    if not warehouse:
        raise InventoryServiceException(108, "warehouse id not present")
    warehouse.status = status.DELETED;
    session.commit()
    
def retire_item(item_id):
    if not item_id:
        raise InventoryServiceException(101, "bad item id")
    item = get_item(item_id)
    if not item:
        raise InventoryServiceException(108, "item id not present")
    item.status = status.PHASED_OUT
    item.retireDate = datetime.datetime.now()
    session.commit()
    
#need to implement threads based solution here
def start_item_on(item_id, timestamp):
    if not item_id:
        raise InventoryServiceException(101, "bad item id")
    item = get_item(item_id)
    if not item:
        raise InventoryServiceException(108, "item id not present")
    
    item.status = status.ACTIVE
    item.startDate = datetime.datetime.fromtimestamp(to_py_date(timestamp))
    add_status_change_log(item, status.ACTIVE)
    session.commit()
    
#need to implement threads here
def retire_item_on(item_id, timestamp):
    if not item_id:
        raise InventoryServiceException(101, "bad item id")
    item = get_item(item_id)
    if not item:
        raise InventoryServiceException(108, "item id not present")
    
    item.status = status.PHASED_OUT
    item.retireDate = datetime.datetime.fromtimestamp(to_py_date(timestamp))
    add_status_change_log(item, status.PHASED_OUT)
    session.commit()
    
def add_status_change_log(item, new_status):
    item_change_log = ItemChangeLog()
    item_change_log.new_status = new_status
    item_change_log.old_status = item.status
    item_change_log.timestamp = datetime.datetime.now()
    item_change_log.item = item
    session.commit()
    
def change_item_status(item_id, new_status):
    if not item_id:
        raise InventoryServiceException(101, "bad item id")
    item = get_item(item_id)
    if not item:
        raise InventoryServiceException(108, "item id not present")
    
    item.status = new_status
    add_status_change_log(item, new_status)
    session.commit()
    
def get_item_availability_for_warehouse(warehouse_id, item_id):
    if not warehouse_id:
        raise InventoryServiceException(101, "bad warehouse_id")
    if not item_id:
        raise InventoryServiceException(101, "bad item_id")
    
    warehouse = get_Warehouse(warehouse_id)
    if not warehouse:
        raise InventoryServiceException(108, "warehouse does not exist")
    item = get_item(item_id)

    if not item:
            raise InventoryServiceException(108, "item does not exist")
        
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id)
    query = query.filter_by(item_id = item.id)
    try:
        current_inventory_snapshot = query.one()
        return current_inventory_snapshot.availibility
    except:
        return 0
    """
    current_inventory_snapshot = CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id == warehouse_id, CurrentInventorySnapshot.item_id == item_id).one()
    if not current_inventory_snapshot:
        return 0
    else:
        return current_inventory_snapshot.availibility
    """
    
def mark_item_as_content_complete(entity_id):
    content_complete_status = status.CONTENT_COMPLETE
    items = Item.query.filter_by(catalog_item_id=entity_id).all()
    current_timestamp = datetime.datetime.now()
    for item in items:
        item_change_log = ItemChangeLog()
        item_change_log.old_status = item.status
        item_change_log.new_status = content_complete_status
        item_change_log.timestamp = current_timestamp
        item_change_log.item = item
        
        item.status = content_complete_status
        item.updatedOn = current_timestamp
    session.commit()
    return True
    
def get_item_availability_for_location(warehouse_loc, item_id):
    if warehouse_loc is None:
        raise InventoryServiceException(101, "Bad Warehouse Location")
    if not item_id:
        raise InventoryServiceException(101, "Bas Item id")
    
    warehouses = Warehouse.query.filter_by(logisticsLocation=warehouse_loc).all()
    warehouse_ids = [warehouse.id for warehouse in warehouses]
    warehouse_retid = -1
    global_availability = 0
    for warehouse_id in warehouse_ids:
        availability = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id).one().availibility
        if availability > global_availability:
            warehouse_retid = warehouse_id
            global_availability = availability
    if warehouse_retid == -1:
        # This is the case when all warehouses have exhausted their
        # inventory of this item or no warehouse is available in this
        # location.
        #TODO: Change 1 to be a constant read from the Config client.
        warehouse_retid = 1
    return [warehouse_retid, global_availability]

def get_warehouses_for_item(item_id):
    
    if not item_id:
        raise InventoryServiceException(101, "bad item_id")
    item = get_item(item_id)
    
    if not item:
        raise InventoryServiceException(101, "bad item")
    
    warehouses = item.currentInventory.warehouse
    return warehouses

def get_best_sellers(start_index, stop_index, category=-1):
    query = get_best_sellers_query(category)
    best_sellers = query.order_by(asc(Item.bestSellingRank)).all()[start_index:stop_index]
    return get_thrift_item_list(best_sellers)

def get_best_sellers_count(category):
    query = get_best_sellers_query(category)
    return query.count()

def get_best_sellers_catalog_ids(start_index, stop_index, category=-1):
    query = get_best_sellers_query(category)
    best_sellers = query.order_by(asc(Item.bestSellingRank)).all()[start_index:stop_index]
    return [item.catalog_item_id for item in best_sellers]
    
def get_best_sellers_query(category):
    query = Item.query.filter(Item.bestSellingRank != None)
    if category != -1:
        query = query.filter_by(category=category)
    return query

def get_best_deals():
    items = Item.query.filter(Item.bestDealValue != None).order_by(desc(Item.bestDealValue)).all()
    return get_thrift_item_list(items)

def get_best_deals_count():
    return Item.query.filter(Item.bestDealValue != None).count()
    
def get_best_deals_catalog_ids(start_index, stop_index, category=-1):
    query = Item.query.filter(Item.bestDealValue != None)
    if category != -1:
        query = query.filter_by(category=category)
    best_deal_items = query.order_by(desc(Item.bestDealValue)).all()[start_index:stop_index]
    return [item.catalog_item_id for item in best_deal_items]

def get_latest_arrivals(limit):
    items = Item.query.order_by(desc(Item.startDate)).all()[0:limit]
    return get_thrift_item_list(items)
    
def get_latest_arrivals_count(limit):
    #FIXME: This method has not been functionally tested. Have to talk to Rajveer to check where is it used.
    return min(Item.query.count(), limit)
    
def get_latest_arrivals_catalog_ids(start_index, stop_index, category=-1):
    query = Item.query
    if category != -1:
        query = query.filter_by(category=category)
    latest_arrivals = query.order_by(desc(Item.startDate)).all()[start_index:stop_index]
    return [item.catalog_item_id for item in latest_arrivals] 

def get_thrift_item_list(items):
    ret_items = []
    for item in items:
        if item:
            ret_items.append(to_t_item(item))    
    return ret_items

def put_category_object(object):
    category = Category.get_by(id=1)
    if category is None:
        category = Category()
    category.object = object    
    session.commit()
    return True

def get_category_object():
    return Category.get_by(id=1).object