Rev 16025 | Rev 19230 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
'''Created on 13-Sep-2010@author: rajveer'''from elixir import sessionfrom shop2020.clients.CatalogClient import CatalogClientfrom shop2020.clients.InventoryClient import InventoryClientfrom shop2020.logistics.service.impl import DataServicefrom shop2020.logistics.service.impl.DataService import Awb, AwbUpdate, Provider, \DeliveryEstimate, WarehouseAllocation, PublicHolidays, \ServiceableLocationDetails, PickupStorefrom shop2020.thriftpy.logistics.ttypes import LogisticsServiceException, \DeliveryType, LogisticsLocationInfofrom shop2020.thriftpy.model.v1.inventory.ttypes import Warehouse, BillingType,\WarehouseTypefrom shop2020.utils.Utils import log_entry, to_py_date, to_java_datefrom sqlalchemy.sql import or_import datetimeimport loggingimport osimport sysimport timelogging.basicConfig(level=logging.DEBUG)warehouse_allocation_cache = {}serviceable_location_cache = {}delivery_estimate_cache = {}warehouse_location_cache = {}'''This class is for only data transfer. Never used outside this module.'''class _DeliveryEstimateObject:def __init__(self, delivery_time, delivery_delay, provider_id, codAllowed, otgAvailable):self.delivery_time = delivery_timeself.delivery_delay = delivery_delayself.provider_id = provider_idself.codAllowed = codAllowedself.otgAvailable = otgAvailabledef initialize(dbname="logistics", db_hostname="localhost"):log_entry("initialize@DataAccessor", "Initializing data service")DataService.initialize(dbname, db_hostname)print "Starting cache population at: " + str(datetime.datetime.now())#__cache_warehouse_allocation_table()__cache_warehouse_locations()__cache_serviceable_location_details_table()__cache_delivery_estimate_table()close_session()print "Done cache population at: " + str(datetime.datetime.now())def __cache_delivery_estimate_table():delivery_estimates = DeliveryEstimate.query.all()for delivery_estimate in delivery_estimates:delivery_estimate_cache[delivery_estimate.destination_pin, delivery_estimate.provider_id, delivery_estimate.warehouse_location]\=delivery_estimate.delivery_time, delivery_estimate.delivery_delaydef __cache_serviceable_location_details_table():serviceable_locations = ServiceableLocationDetails.query.filter(or_("exp!=0","cod!=0"))for serviceable_location in serviceable_locations:try:provider_pincodes = serviceable_location_cache[serviceable_location.provider_id]except:provider_pincodes = {}serviceable_location_cache[serviceable_location.provider_id] = provider_pincodesprovider_pincodes[serviceable_location.dest_pincode] = serviceable_location.dest_code, serviceable_location.exp, serviceable_location.cod, serviceable_location.otgAvailable, serviceable_location.websiteCodLimit, serviceable_location.storeCodLimit, serviceable_location.providerPrepaidLimitdef __cache_warehouse_allocation_table():warehouse_allocations = WarehouseAllocation.query.all()for warehouse_allocation in warehouse_allocations:warehouse_allocation_cache[warehouse_allocation.pincode]=warehouse_allocation.primary_warehouse_locationdef __cache_warehouse_locations():client = InventoryClient().get_client()client.getAllWarehouses(True)#for WarehouseAllocation.query.all()warehouse = Warehouse()for warehouse in client.getAllWarehouses(True):warehouse_location_cache[warehouse.billingWarehouseId]=warehouse.logisticsLocationdef get_provider(provider_id):provider = Provider.get_by(id=provider_id)return providerdef get_providers():providers = Provider.query.filter_by(isActive = 1).all()return providersdef get_logistics_estimation(destination_pin, item_selling_price, weight, type, billingWarehouseId):logging.info("Getting logistics estimation for pincode:" + destination_pin )provider_id, codAllowed, otgAvailable = __get_logistics_provider_for_destination_pincode(destination_pin, item_selling_price, weight, type, billingWarehouseId)logging.info("Provider Id: " + str(provider_id) +" codAllowed: "+str(codAllowed)+" otgAvailable: "+str(otgAvailable)+ " item_selling_price: "+str(item_selling_price))if item_selling_price > 60000:# or item_selling_price <= 250:codAllowed = Falsewarehouse_location = warehouse_location_cache.get(billingWarehouseId)if warehouse_location is None:warehouse_location = 0if not provider_id:raise LogisticsServiceException(101, "No provider assigned for pincode: " + str(destination_pin))try:logging.info( "destination_pin %s, provider_id %s, warehouse_location %s"%(destination_pin, provider_id, warehouse_location))logging.info( "Estimates %s, %s"%(delivery_estimate_cache[destination_pin, provider_id, warehouse_location]))delivery_time = delivery_estimate_cache[destination_pin, provider_id, warehouse_location][0]delivery_delay = delivery_estimate_cache[destination_pin, provider_id, warehouse_location][1]delivery_estimate = _DeliveryEstimateObject(delivery_time, delivery_delay, provider_id, codAllowed, otgAvailable)return delivery_estimateexcept Exception as ex:print exraise LogisticsServiceException(103, "No Logistics partner listed for this destination pincode and the primary warehouse")def __get_logistics_provider_for_destination_pincode(destination_pin, item_selling_price, weight, type, billingWarehouseId):'''if serviceable_location_cache.get(6).has_key(destination_pin):if weight < 480 and serviceable_location_cache.get(3).has_key(destination_pin) and type == DeliveryType.PREPAID:dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(3).get(destination_pin)if item_selling_price <= providerPrepaidLimit:iscod = iscod and item_selling_price <= websiteCodLimitotgAvailable = otgAvailable and item_selling_price >= 2000return 3, iscod, otgAvailableelse:dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(6).get(destination_pin)if item_selling_price <= providerPrepaidLimit:iscod = iscod and item_selling_price <= websiteCodLimitotgAvailable = otgAvailable and item_selling_price >= 2000return 6, iscod, otgAvailable'''if serviceable_location_cache.get(3).has_key(destination_pin):dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(3).get(destination_pin)if item_selling_price <= providerPrepaidLimit:iscod = iscod and item_selling_price <= websiteCodLimitotgAvailable = otgAvailable and item_selling_price >= 2000return 3, iscod, otgAvailableif billingWarehouseId not in [12,13] and serviceable_location_cache.get(7).has_key(destination_pin):if item_selling_price < 3000 and serviceable_location_cache.get(1).has_key(destination_pin):dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(1).get(destination_pin)if item_selling_price <= providerPrepaidLimit:iscod = iscod and item_selling_price <= websiteCodLimitotgAvailable = otgAvailable and item_selling_price >= 2000return 1, iscod, otgAvailableelse:dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(7).get(destination_pin)if item_selling_price <= providerPrepaidLimit:iscod = iscod and item_selling_price <= websiteCodLimitotgAvailable = otgAvailable and item_selling_price >= 2000return 7, iscod, otgAvailableif serviceable_location_cache.get(1).has_key(destination_pin):dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(1).get(destination_pin)if item_selling_price <= providerPrepaidLimit:iscod = iscod and item_selling_price <= websiteCodLimitotgAvailable = otgAvailable and item_selling_price >= 2000return 1, iscod, otgAvailablereturn None, False, Falsedef get_destination_code(providerId, pinCode):serviceableLocationDetail = ServiceableLocationDetails.query.filter_by(provider_id = providerId, dest_pincode = pinCode).one()return serviceableLocationDetail.dest_codedef add_empty_AWBs(numbers, provider_id, type):for number in numbers:query = Awb.query.filter_by(awb_number = number, provider_id = provider_id)try:query.one()except:awb = Awb()awb.awb_number = numberawb.provider_id = provider_idawb.is_available = Trueawb.type = typesession.commit()def set_AWB_as_used(awb_number):query = Awb.query.filter_by(awb_number = awb_number)awb = query.one()awb.is_available=Falsesession.commit()def get_empty_AWB(provider_id, type = DeliveryType.PREPAID):query = Awb.query.with_lockmode("update").filter_by(provider_id = provider_id, is_available = True) #check the provider thingif type == DeliveryType.PREPAID:query = query.filter_by(type="Prepaid")if type == DeliveryType.COD:query = query.filter_by(type="COD")additionalQuery = queryquery = query.filter_by(awbUsedFor=0)try:awb = query.first()if awb is None:additionalQuery = additionalQuery.filter_by(awbUsedFor=2)awb = additionalQuery.first()awb.is_available = Falsesession.commit()return awb.awb_numberexcept:raise LogisticsServiceException(103, "Unable to get an AWB for the given Provider: " + str(provider_id))def get_free_awb_count(provider_id, type):count = Awb.query.filter_by(provider_id = provider_id, is_available = True, type=type).count()if count == None:count = 0return countdef get_shipment_info(awb_number, provider_id):awb = Awb.get_by(awb_number = awb_number, provider_id = provider_id)query = AwbUpdate.query.filter_by(awb = awb)info = query.all()return infodef store_shipment_info(update):updates = AwbUpdate.query.filter_by(providerId = update.providerId, awbNumber = update.awbNumber, location = update.location, date = to_py_date(update.date), status = update.status, description = update.description).all()if not updates:dupdate = AwbUpdate()dupdate.providerId = update.providerIddupdate.awbNumber = update.awbNumberdupdate.location = update.locationdupdate.date = to_py_date(update.date)dupdate.status = update.statusdupdate.description = update.descriptionsession.commit()def get_holidays(start_date, end_date):query = PublicHolidays.queryif start_date != -1:query = query.filter(PublicHolidays.date >= to_py_date(start_date))if end_date != -1:query = query.filter(PublicHolidays.date <= to_py_date(end_date))holidays = query.all()holiday_dates = [to_java_date(datetime.datetime(*time.strptime(str(holiday.date), '%Y-%m-%d')[:3])) for holiday in holidays]return holiday_datesdef get_provider_for_pickup_type(pickUp):return Provider.query.filter(Provider.pickup == pickUp).first().iddef close_session():if session.is_active:print "session is active. closing it."session.close()def is_alive():try:session.query(Awb.id).limit(1).one()return Trueexcept:return Falsedef get_all_pickup_stores():pickupStores = PickupStore.query.all()return pickupStoresdef get_pickup_store(storeId):return PickupStore.query.filter_by(id = storeId).one()def get_pickup_store_by_hotspot_id(hotspotId):return PickupStore.query.filter_by(hotspotId = hotspotId).one()def add_pincode(provider, pincode, destCode, exp, cod, stationType, otgAvailable):provider = Provider.query.filter_by(id = provider).one()serviceableLocationDetails = ServiceableLocationDetails()serviceableLocationDetails.provider = providerserviceableLocationDetails.dest_pincode = pincodeserviceableLocationDetails.dest_code = destCodeserviceableLocationDetails.exp = expserviceableLocationDetails.cod = codserviceableLocationDetails.station_type = stationTypeserviceableLocationDetails.otgAvailable = otgAvailableif provider.id == 1:codlimit = 10000prepaidlimit = 50000elif provider.id == 3:codlimit = 25000prepaidlimit = 100000elif provider.id == 6:codlimit = 25000prepaidlimit = 100000serviceableLocationDetails.providerPrepaidLimit = prepaidlimitserviceableLocationDetails.providerCodLimit = codlimitserviceableLocationDetails.websiteCodLimit = codlimitserviceableLocationDetails.storeCodLimit = codlimitsession.commit()def update_pincode(providerId, pincode, exp, cod, otgAvailable):serviceableLocationDetails = ServiceableLocationDetails.get_by(provider_id = providerId, dest_pincode = pincode)serviceableLocationDetails.exp = expserviceableLocationDetails.cod = codserviceableLocationDetails.otgAvailable = otgAvailablesession.commit()def add_new_awbs(provider_id, isCod, awbs, awbUsedFor):provider = get_provider(provider_id)if isCod:dtype = 'Cod'else:dtype = 'Prepaid'for awb in awbs:a = Awb()a.type = dtypea.is_available = Truea.awb_number = awba.awbUsedFor = awbUsedFora.provider = providersession.commit()return Truedef adjust_delivery_time(start_time, delivery_days):'''Returns the actual no. of days which will pass while 'delivery_days'no. of business days will pass since 'order_time'.'''start_date = start_time.date()end_date = start_date + datetime.timedelta(days = delivery_days)holidays = get_holidays(to_java_date(start_time), -1)holidays = [to_py_date(holiday).date() for holiday in holidays]while start_date <= end_date:if start_date.weekday() == 6 or start_date in holidays:delivery_days = delivery_days + 1end_date = end_date + datetime.timedelta(days = 1)start_date = start_date + datetime.timedelta(days = 1)return delivery_daysdef get_min_advance_amount(itemId, destination_pin, providerId, codAllowed):client = CatalogClient().get_client()sp = client.getStorePricing(itemId)if codAllowed:return sp.minAdvancePrice, Trueelse:dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit = serviceable_location_cache.get(providerId).get(destination_pin)if iscod:if providerId == 6:return max(sp.minAdvancePrice, sp.recommendedPrice - storeCodLimit), Trueif providerId == 3:return max(sp.minAdvancePrice, sp.recommendedPrice - storeCodLimit), Trueif providerId == 1:return max(sp.minAdvancePrice, sp.recommendedPrice - storeCodLimit), Trueelse:return sp.recommendedPrice, False#Start:- Added by Manish Sharma for Multiple Pincode Updation on 05-Jul-2013def run_Logistics_Location_Info_Update(logisticsLocationInfoList, runCompleteUpdate):if runCompleteUpdate == True :serviceableLocationDetails = ServiceableLocationDetails.query.all()for serviceableLocationDetail in serviceableLocationDetails:serviceableLocationDetail.exp = FalseserviceableLocationDetail.cod = Falsefor logisticsLocationInfo in logisticsLocationInfoList:serviceableLocationDetail = ServiceableLocationDetails.get_by(provider_id = logisticsLocationInfo.providerId, dest_pincode = logisticsLocationInfo.pinCode)provider = Provider.query.filter_by(id = logisticsLocationInfo.providerId).one()if serviceableLocationDetail:serviceableLocationDetail.exp = logisticsLocationInfo.expAvailableserviceableLocationDetail.cod = logisticsLocationInfo.codAvailableserviceableLocationDetail.otgAvailable = logisticsLocationInfo.otgAvailableserviceableLocationDetail.providerCodLimit = logisticsLocationInfo.codLimitserviceableLocationDetail.providerPrepaidLimit = logisticsLocationInfo.prepaidLimitserviceableLocationDetail.storeCodLimit = logisticsLocationInfo.codLimitserviceableLocationDetail.websiteCodLimit = min(26000,logisticsLocationInfo.codLimit)else:serviceableLocationDetail= ServiceableLocationDetails()serviceableLocationDetail.provider = providerserviceableLocationDetail.dest_pincode = logisticsLocationInfo.pinCodeserviceableLocationDetail.dest_code = logisticsLocationInfo.destinationCodeserviceableLocationDetail.exp = logisticsLocationInfo.expAvailableserviceableLocationDetail.cod = logisticsLocationInfo.codAvailableserviceableLocationDetail.station_type = 0serviceableLocationDetail.otgAvailable = logisticsLocationInfo.otgAvailableserviceableLocationDetail.providerCodLimit = logisticsLocationInfo.codLimitserviceableLocationDetail.providerPrepaidLimit = logisticsLocationInfo.prepaidLimitserviceableLocationDetail.storeCodLimit = logisticsLocationInfo.codLimitserviceableLocationDetail.websiteCodLimit = min(26000,logisticsLocationInfo.codLimit)deliveryEstimate = DeliveryEstimate.get_by(provider_id = logisticsLocationInfo.providerId, destination_pin = logisticsLocationInfo.pinCode, warehouse_location = logisticsLocationInfo.warehouseId)if deliveryEstimate:deliveryEstimate.warehouse_location= logisticsLocationInfo.warehouseIddeliveryEstimate.delivery_time= logisticsLocationInfo.deliveryTimedeliveryEstimate.delivery_delay= logisticsLocationInfo.delivery_delayelse:deliveryEstimate = DeliveryEstimate()deliveryEstimate.destination_pin= logisticsLocationInfo.pinCodedeliveryEstimate.provider = providerdeliveryEstimate.warehouse_location= logisticsLocationInfo.warehouseIddeliveryEstimate.delivery_time= logisticsLocationInfo.deliveryTimedeliveryEstimate.delivery_delay= logisticsLocationInfo.delivery_delaysession.commit()#End:- Added by Manish Sharma for Multiple Pincode Updation on 05-Jul-2013def get_first_delivery_estimate_for_wh_location(pincode, whLocation):delEstimate = DeliveryEstimate.query.filter(DeliveryEstimate.destination_pin == pincode).filter(DeliveryEstimate.warehouse_location == whLocation).first()if delEstimate is None:return -1else:return 1def get_provider_limit_details_for_pincode(provider, pincode):serviceAbleDetails = ServiceableLocationDetails.get_by(provider_id = provider, dest_pincode = pincode)returnDataMap = {}if serviceAbleDetails:returnDataMap["websiteCodLimit"] = str(serviceAbleDetails.websiteCodLimit)returnDataMap["providerPrepaidLimit"] = str(serviceAbleDetails.providerPrepaidLimit)return returnDataMapdef get_new_empty_awb(providerId, type, orderQuantity):query = Awb.query.with_lockmode("update").filter_by(provider_id = providerId, is_available = True) #check the provider thingif type == DeliveryType.PREPAID:query = query.filter_by(type="Prepaid")if type == DeliveryType.COD:query = query.filter_by(type="COD")additionalQuery = queryif orderQuantity == 1:query = query.filter_by(awbUsedFor=0)if orderQuantity >1:query = query.filter_by(awbUsedFor=1)try:awb = query.first()if awb is None:additionalQuery = additionalQuery.filter_by(awbUsedFor=2)awb = additionalQuery.first()awb.is_available = Falsesession.commit()return awb.awb_numberexcept:raise LogisticsServiceException(103, "Unable to get an AWB for the given Provider: " + str(providerId))