Rev 23316 | Blame | Compare with Previous | Last modification | View Log | RSS feed
'''Created on 13-Sep-2010@author: rajveer'''from collections import namedtuplefrom elixir import sessionfrom shop2020.clients.CatalogClient import CatalogClientfrom shop2020.clients.InventoryClient import InventoryClientfrom shop2020.clients.TransactionClient import TransactionClientfrom shop2020.logistics.service.impl import BluedartService, DataService, \EcomExpressServicefrom shop2020.logistics.service.impl.DataService import Awb, AwbUpdate, Provider, \DeliveryEstimate, WarehouseAllocation, PublicHolidays, \ServiceableLocationDetails, PickupStore, Locations, ProviderCosting, \BluedartAttribute, PincodeStatesfrom shop2020.thriftpy.logistics.ttypes import LogisticsServiceException, \DeliveryType, LogisticsLocationInfo, LocationInfo, ProviderInfo, \DeliveryEstimateAndCostingfrom shop2020.thriftpy.model.v1.inventory.ttypes import Warehouse, BillingType, \WarehouseTypefrom shop2020.utils.Utils import log_entry, to_py_date, to_java_datefrom shop2020.utils.caching.SimpleCaching import memoizedfrom sqlalchemy.sql import or_import datetimeimport loggingimport mathimport osimport sysimport timeimport tracebacklogging.basicConfig(level=logging.DEBUG)PincodeProvider = namedtuple("PincodeProvider", ["dest_pin", "provider"])warehouse_allocation_cache = {}serviceable_location_cache = {}delivery_estimate_cache = {}warehouse_location_cache = {}location_state={}'Delhivery Bluedart, Fedex Surface, Fedex Air'state_locations = {}provider_costing_sheet = {}DELHIVERY = 3RQUICK = 47RQUICKSURFACE = 48ARAMEX = 2ECOMEXPRESS = 49PROVIDER_PRIORITY = [RQUICKSURFACE, RQUICK, ARAMEX, ECOMEXPRESS]#pincode location map is ab#{'110001':{1:{"sameState":False, "providerInfo":{1:(1,1), 2:(1,1)}}},}pincode_locations = {}#{(dest_pin, provider):(otgAvailable,providerCodLimit, websiteCodLimit, storeCodLimit, providerPrepaidLimit)}serviceable_map = {}#Need to identify a better waystatepinmap={'11':0,'40':1,'41':1,'42':1,'43':1,'44':1,'56':2, '57':2, '58':2, '59':2,'12':3, '13':3,'30':4, '31':4, '32':4, '33':4, '34':4,'36':6,'37':6,'38':6,'39':6}'''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()__cache_pincode_provider_serviceability()__cache_locations()__cache_pincode_estimates()__cache_courier_costing_table()close_session()print "Done cache population at: " + str(datetime.datetime.now())@memoized(3600)def fetchStateMaster():inventory_client = InventoryClient().get_client()return inventory_client.getStateMaster()def __cache_locations():locations = Locations.query.all()for location in locations:location_state[location.id] = location.state_idif not state_locations.has_key(location.state_id):state_locations[location.state_id] = []state_locations[location.state_id] = state_locations[location.state_id].append(location.state_id)def __cache_pincode_estimates():delivery_estimates = DeliveryEstimate.query.all()for delivery_estimate in delivery_estimates:if not pincode_locations.has_key(delivery_estimate.destination_pin):pincode_locations[delivery_estimate.destination_pin] = {}destination_pinMap = pincode_locations[delivery_estimate.destination_pin]if not destination_pinMap.has_key(delivery_estimate.warehouse_location):destination_pinMap[delivery_estimate.warehouse_location] = {}state_id = location_state.get(delivery_estimate.warehouse_location)sameState = __getStateFromPin(delivery_estimate.destination_pin) == state_iddestination_pinMap[delivery_estimate.warehouse_location]['sameState']=sameStatedestination_pinMap[delivery_estimate.warehouse_location]['providerInfo'] = {}destination_pinMap[delivery_estimate.warehouse_location]['providerInfo'][delivery_estimate.provider_id] = delivery_estimate.delivery_time + delivery_estimate.delivery_delaydef __cache_pincode_provider_serviceability():pincode_providers = ServiceableLocationDetails.query.filter(ServiceableLocationDetails.exp==1)for pp in pincode_providers:serviceable_map[PincodeProvider(pp.dest_pincode, pp.provider_id)] = (pp.cod, pp.otgAvailable,pp.providerCodLimit, pp.websiteCodLimit, pp.storeCodLimit, pp.providerPrepaidLimit)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_delay, delivery_estimate.providerZoneCodedef __cache_serviceable_location_details_table():serviceable_locations = ServiceableLocationDetails.query.filter(or_("exp!=0","cod!=0"))for serviceable_location in serviceable_locations:#Bluedart is temporarily not serviceableif serviceable_location.provider_id==1:continuetry: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.providerPrepaidLimit, serviceable_location.providerCodLimitdef __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 warehouse in client.getAllWarehouses(True):if warehouse.billingWarehouseId == warehouse.id:warehouse_location_cache[warehouse.billingWarehouseId]=warehouse.logisticsLocationdef __cache_courier_costing_table():allCostings = ProviderCosting.query.all()for costing in allCostings:if provider_costing_sheet.has_key(costing.provider_id):costingMap = provider_costing_sheet.get(costing.provider_id)costingMap[costing.zoneCode] = costingprovider_costing_sheet[costing.provider_id] = costingMapelse:costingMap = {}costingMap[costing.zoneCode] = costingprovider_costing_sheet[costing.provider_id] = costingMapdef get_provider(provider_id):provider = Provider.get_by(id=provider_id)return providerdef get_providers():providers = Provider.query.filter_by(isActive = 1).all()return providers#it would return only states where our warehouses are present else return -1def __getStateFromPin(pin):if pin[:3] in ['744', '682']:return -1elif statepinmap.has_key(pin[:2]):return statepinmap[pin[:2]]else:return -1def get_logistics_locations(destination_pin, selling_price_list):#pincode_locations = {1:{"sameState":False, "providerInfo":{<provider_id>:<delay_days>}},}#pp.otgAvailable,pp.providerCodLimit, pp.websiteCodLimit, pp.storeCodLimit, pp.providerPrepaidLimitreturnMap = {}if pincode_locations.has_key(destination_pin):locations = pincode_locations[destination_pin]for item_selling_price in selling_price_list:returnMap[item_selling_price] = {}for location_id, value in locations.iteritems():#put weight logic hereotgAvailable = FalsecodAvailable = FalseminDelay = -1maxDelay = -1serviceable = Falsefor provider_id, delay_days in value['providerInfo'].iteritems():pp = PincodeProvider(destination_pin, provider_id)if not serviceable_map.has_key(pp):continueiscod, isotg, providerCodLimit, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_map[pp]if item_selling_price <= providerPrepaidLimit:if not serviceable:returnMap[item_selling_price][location_id] = LocationInfo(locationId = location_id, sameState=value['sameState'])serviceable = TrueminDelay = delay_daysmaxDelay = delay_dayselse:minDelay = min(delay_days,minDelay)maxDelay = max(delay_days,maxDelay)iscod = iscod and item_selling_price <= min(providerCodLimit, websiteCodLimit)isotg = (isotg and item_selling_price >= 2000)otgAvailable = otgAvailable or isotgcodAvailable = codAvailable or iscodif serviceable:returnMap[item_selling_price][location_id].isOtg = otgAvailablereturnMap[item_selling_price][location_id].isCod = codAvailablereturnMap[item_selling_price][location_id].minDelay = minDelayreturnMap[item_selling_price][location_id].maxDelay = maxDelayreturn returnMapdef 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, %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_provider(providerList, destination_pin, item_selling_price, weight, type, billingWarehouseId):provider_id = providerList[0]provider_serviable = serviceable_location_cache.has_key(provider_id) and serviceable_location_cache.get(provider_id).has_key(destination_pin)if provider_serviable:dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit, providerCodLimit = serviceable_location_cache.get(provider_id).get(destination_pin)if item_selling_price <= providerPrepaidLimit:iscod = iscod and item_selling_price <= websiteCodLimitif iscod:return provider_id, Trueelif len(providerList) > 1:providerList = providerList[1:]next_provider_id, next_cod = __get_provider(providerList, destination_pin, item_selling_price, weight, type, billingWarehouseId)if next_cod:return next_provider_id, next_codelse:return provider_id, Falseelse:return provider_id, Falseelif len(providerList) > 1:providerList = providerList[1:]return __get_provider(providerList, destination_pin, item_selling_price, weight, type, billingWarehouseId)else:return None, Falsedef __get_logistics_provider_for_destination_pincode(destination_pin, item_selling_price, weight, type, billingWarehouseId):otg=FalseproviderList = list(PROVIDER_PRIORITY)provider_id, isCod = __get_provider(providerList, destination_pin, item_selling_price, weight, type, billingWarehouseId)print "provider_id", provider_idreturn provider_id, isCod, otgdef __getStateByPin(destination_pin):pinCodeState = PincodeStates.get_by(pin=destination_pin)if pinCodeState is not None:return pinCodeState.statenameelse:return Nonedef __get_logistics_provider_for_destination_pincode_old(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.has_key(3) and serviceable_location_cache.get(3).has_key(destination_pin):dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit, providerCodLimit = 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.has_key(7) and serviceable_location_cache.get(7).has_key(destination_pin):if item_selling_price < 3000 and serviceable_location_cache.has_key(1) and serviceable_location_cache.get(1).has_key(destination_pin):dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit, providerCodLimit = 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 >= 2000if iscod:return 1, iscod, otgAvailableelse:dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit, providerCodLimit = 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 >= 2000if iscod:return 7, iscod, otgAvailableif billingWarehouseId not in [12,13] and serviceable_location_cache.has_key(46) and serviceable_location_cache.get(46).has_key(destination_pin):if item_selling_price < 3000 and serviceable_location_cache.has_key(1) and serviceable_location_cache.get(1).has_key(destination_pin):dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit, providerCodLimit = 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 >= 2000if iscod:return 1, iscod, otgAvailableelse:dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit, providerCodLimit = serviceable_location_cache.get(46).get(destination_pin)if item_selling_price <= providerPrepaidLimit:iscod = iscod and item_selling_price <= websiteCodLimitotgAvailable = otgAvailable and item_selling_price >= 2000if iscod:return 46, iscod, otgAvailableif serviceable_location_cache.has_key(1) and serviceable_location_cache.get(1).has_key(destination_pin):dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit, providerCodLimit = 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 >= 2000if iscod:return 1, iscod, otgAvailableif serviceable_location_cache.has_key(3) and serviceable_location_cache.get(3).has_key(destination_pin):dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit, providerCodLimit = 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, 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 = typeawb.awbUsedFor = 2session.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_awb(provider_id, logisticsTransactionId, type):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:success = Trueawb = query.first()if awb is None:additionalQuery = additionalQuery.filter_by(awbUsedFor=2)awb = additionalQuery.first()print "-------", awb.awb_number, awb.is_availableawb.is_available = Falsesession.commit()return awb.awb_numberexcept:traceback.print_exc()session.close()raise LogisticsServiceException(103, "Unable to get an AWB for the given Provider: " + str(provider_id))def get_empty_AWB(provider_id, logisticsTransactionId):try:if logisticsTransactionId is None:return ""if provider_id ==1:bluedartAttribute = BluedartAttribute.get_by(logisticsTransactionId=logisticsTransactionId,name="awb")if bluedartAttribute is None:client = TransactionClient().get_client()orders_list = client.getGroupOrdersByLogisticsTxnId(logisticsTransactionId)bluedartResponse = BluedartService.generate_awb(orders_list)bluedartAttribute = BluedartAttribute()bluedartAttribute.logisticsTransactionId = logisticsTransactionIdbluedartAttribute.name = "awb"bluedartAttribute.value = bluedartResponse.awbNobluedartAttribute_destcode = BluedartAttribute()bluedartAttribute_destcode.logisticsTransactionId = logisticsTransactionIdbluedartAttribute_destcode.name = "destCode"bluedartAttribute_destcode.value = bluedartResponse.destArea +"/"+ bluedartResponse.destLocationsession.commit()return bluedartAttribute.valueelse :client = TransactionClient().get_client()return get_awb(provider_id, logisticsTransactionId, DeliveryType.COD if client.isShipmentCod(logisticsTransactionId) else DeliveryType.PREPAID)except:traceback.print_exc()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, providerPrepaidLimit, providerCodLimit = 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, providerId):if runCompleteUpdate == True :serviceableLocationDetails = ServiceableLocationDetails.query.filter_by(provider_id=providerId).all()provider = Provider.query.filter_by(id = providerId).one()for serviceableLocationDetail in serviceableLocationDetails:serviceableLocationDetail.exp = FalseserviceableLocationDetail.cod = Falsefor logisticsLocationInfo in logisticsLocationInfoList:serviceableLocationDetail = ServiceableLocationDetails.get_by(provider_id = logisticsLocationInfo.providerId, dest_pincode = logisticsLocationInfo.pinCode)if provider is None: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_delaydeliveryEstimate.providerZoneCode = logisticsLocationInfo.zoneCodeelse:deliveryEstimate = DeliveryEstimate()deliveryEstimate.destination_pin= logisticsLocationInfo.pinCodedeliveryEstimate.provider = providerdeliveryEstimate.warehouse_location= logisticsLocationInfo.warehouseIddeliveryEstimate.delivery_time= logisticsLocationInfo.deliveryTimedeliveryEstimate.delivery_delay= logisticsLocationInfo.delivery_delaydeliveryEstimate.providerZoneCode = logisticsLocationInfo.zoneCodesession.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["providerCodLimit"] = str(serviceAbleDetails.providerCodLimit)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))def get_costing_and_delivery_estimate_for_pincode(pincode, transactionAmount, isCod, weight, billingWarehouseId, isCompleteTxn):print pincode, transactionAmount, isCod, weight, billingWarehouseIddeliveryEstimate = {}logsiticsCosting = {}providerCostingMap = {}serviceability = {}providerList = list(PROVIDER_PRIORITY)#for now this part is disabled and only the same logistics partner is used as priorityprovider_id, cod = __get_provider(providerList, pincode, transactionAmount, weight, type, billingWarehouseId)providerIds = [provider_id]#for providerId in serviceable_location_cache.keys():for providerId in providerIds:if serviceable_location_cache.has_key(providerId) and serviceable_location_cache.get(providerId).has_key(pincode):dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit, providerCodLimit = serviceable_location_cache.get(providerId).get(pincode)if isCod and iscod:if not isCompleteTxn:if transactionAmount <= providerCodLimit:serviceability[providerId] = serviceable_location_cache.get(providerId).get(pincode)else:continueelse:serviceability[providerId] = serviceable_location_cache.get(providerId).get(pincode)elif isCod and not iscod:continueelse:if not isCompleteTxn:if transactionAmount <= providerPrepaidLimit:serviceability[providerId] = serviceable_location_cache.get(providerId).get(pincode)else:continueelse:serviceability[providerId] = serviceable_location_cache.get(providerId).get(pincode)warehouse_location = warehouse_location_cache.get(billingWarehouseId)if warehouse_location is None:warehouse_location = 0noCostFoundCount = 0if len(serviceability)>0:for providerId, serviceableDetails in serviceability.items():delivery_time = delivery_estimate_cache[pincode, providerId, warehouse_location][0]delivery_delay = delivery_estimate_cache[pincode, providerId, warehouse_location][1]zoneCode = delivery_estimate_cache[pincode, providerId, warehouse_location][2]sla = delivery_time + delivery_delayif deliveryEstimate.has_key(sla):estimate = deliveryEstimate.get(sla)estimate.append(providerId)deliveryEstimate[sla] = estimateelse:estimate = []estimate.append(providerId)deliveryEstimate[sla] = estimatelogisticsCost = 0codCollectionCharges = 0logisticsCostObj = Noneif provider_costing_sheet.has_key(providerId) and provider_costing_sheet.get(providerId).has_key(zoneCode):logisticsCostObj = provider_costing_sheet.get(providerId).get(zoneCode)logisticsCost = logisticsCostObj.initialLogisticsCostif weight > logisticsCostObj.initialWeightUpperLimit:additionalWeight = weight-logisticsCostObj.initialWeightUpperLimitadditionalWeight = round(additionalWeight,0)additionalCostMultiplier = math.ceil(additionalWeight/logisticsCostObj.additionalUnitWeight)additionalCost = additionalCostMultiplier*logisticsCostObj.additionalUnitLogisticsCostlogisticsCost = logisticsCost + additionalCostif isCod:if logisticsCostObj.codCollectionFactor:codCollectionCharges = max(logisticsCostObj.minimumCodCollectionCharges, (transactionAmount*logisticsCostObj.codCollectionFactor)/100)logisticsCost = logisticsCost + max(logisticsCostObj.minimumCodCollectionCharges, (transactionAmount*logisticsCostObj.codCollectionFactor)/100)else:codCollectionCharges = logisticsCostObj.minimumCodCollectionChargeslogisticsCost = logisticsCost + logisticsCostObj.minimumCodCollectionChargesif logsiticsCosting.has_key(round(logisticsCost,0)):costingList = logsiticsCosting.get(round(logisticsCost,0))costingList.append(providerId)logsiticsCosting[round(logisticsCost,0)] = costingListelse:costingList = []costingList.append(providerId)logsiticsCosting[round(logisticsCost,0)] = costingListproviderCostingMap[providerId] = [logisticsCost,codCollectionCharges]else:noCostFoundCount = noCostFoundCount +1continueelse:print "No provider assigned for pincode: " + str(pincode)raise LogisticsServiceException(103, "Unable to get Provider for given pincode: " + str(pincode)+" Amount:- "+str(transactionAmount)+" Weight:- "+ str(weight))if noCostFoundCount == len(serviceability):print "No Costing Found for this pincode: " + str(pincode) +" for any of the provider"raise LogisticsServiceException(103, "Unable to get Provider for given pincode: " + str(pincode)+" Amount:- "+str(transactionAmount)+" Weight:- "+ str(weight)+". Due to no costing found")allSla = sorted(deliveryEstimate.keys())if len(allSla)==1:allEligibleProviders = deliveryEstimate.get(allSla[0])if len(allEligibleProviders)==1:try:costingDetails = providerCostingMap.get(allEligibleProviders[0])delEstCostObj = DeliveryEstimateAndCosting()delEstCostObj.logistics_provider_id = allEligibleProviders[0]delEstCostObj.pincode = pincodedelEstCostObj.deliveryTime = delivery_estimate_cache[pincode, allEligibleProviders[0], warehouse_location][0]delEstCostObj.delivery_delay = delivery_estimate_cache[pincode, allEligibleProviders[0], warehouse_location][1]delEstCostObj.codAllowed = serviceability[allEligibleProviders[0]][2]delEstCostObj.otgAvailable = serviceability[allEligibleProviders[0]][3]delEstCostObj.logisticsCost = costingDetails[0]-costingDetails[1]delEstCostObj.codCollectionCharges = costingDetails[1]return delEstCostObjexcept:raise LogisticsServiceException(103, "Unable to get Provider for given pincode: " + str(pincode)+" Amount:- "+str(transactionAmount)+" Weight:- "+ str(weight)+".")else:costingListOrder = []for providerId in allEligibleProviders:costingDetails = providerCostingMap.get(providerId)if costingDetails and costingDetails[0] not in costingListOrder:costingListOrder.append(round(costingDetails[0],0))costingListOrder = sorted(costingListOrder)eligibleProviders = logsiticsCosting.get(costingListOrder[0])for providerId in eligibleProviders:if providerCostingMap.has_key(providerId):costingDetails = providerCostingMap.get(providerId)delEstCostObj = DeliveryEstimateAndCosting()delEstCostObj.logistics_provider_id = providerIddelEstCostObj.pincode = pincodedelEstCostObj.deliveryTime = delivery_estimate_cache[pincode, providerId, warehouse_location][0]delEstCostObj.delivery_delay = delivery_estimate_cache[pincode, providerId, warehouse_location][1]delEstCostObj.codAllowed = serviceability[providerId][2]delEstCostObj.otgAvailable = serviceability[providerId][3]delEstCostObj.logisticsCost = costingDetails[0]-costingDetails[1]delEstCostObj.codCollectionCharges = costingDetails[1]return delEstCostObjelse:continueraise LogisticsServiceException(103, "Unable to get Provider for given pincode: " + str(pincode)+" Amount:- "+str(transactionAmount)+" Weight:- "+ str(weight)+".")else:allEligibleProviders = []virtualDelayCostMap = {}virtualCommercialsCostMap = {}for sla in allSla:if sla-allSla[0]<=1:consideredProviders = deliveryEstimate.get(sla)for providerId in consideredProviders:if isCod and providerId in [7,46]:virtualCommercialsCostMap[providerId] = 10if providerId not in allEligibleProviders:allEligibleProviders.append(providerId)virtualDelayCostMap[providerId] = 0elif sla-allSla[0]==2:consideredProviders = deliveryEstimate.get(sla)for providerId in consideredProviders:if isCod and providerId in [7,46]:virtualCommercialsCostMap[providerId] = 10if providerId not in allEligibleProviders:allEligibleProviders.append(providerId)virtualDelayCostMap[providerId] = 20+round((0.3*transactionAmount)/100,0)elif sla-allSla[0]==3:consideredProviders = deliveryEstimate.get(sla)for providerId in consideredProviders:if isCod and providerId in [7,46]:virtualCommercialsCostMap[providerId] = 10if providerId not in allEligibleProviders:allEligibleProviders.append(providerId)virtualDelayCostMap[providerId] = 40+round((0.6*transactionAmount)/100,0)costingListOrder = []costingListMap = {}for providerId in allEligibleProviders:costingDetails = providerCostingMap.get(providerId)if costingDetails:cost = round(costingDetails[0],0)if virtualDelayCostMap.has_key(providerId):cost = cost + virtualDelayCostMap.get(providerId)if virtualCommercialsCostMap.has_key(providerId):cost = cost + virtualCommercialsCostMap.get(providerId)if costingListMap.has_key(cost):providers = costingListMap.get(cost)providers.append(providerId)costingListMap[cost] = providerselse:providers = []providers.append(providerId)costingListMap[cost] = providersif cost not in costingListOrder:costingListOrder.append(cost)costingListOrder = sorted(costingListOrder)print costingListMapeligibleProviders = costingListMap.get(costingListOrder[0])for providerId in eligibleProviders:if providerCostingMap.has_key(providerId):costingDetails = providerCostingMap.get(providerId)delEstCostObj = DeliveryEstimateAndCosting()delEstCostObj.logistics_provider_id = providerIddelEstCostObj.pincode = pincodedelEstCostObj.deliveryTime = delivery_estimate_cache[pincode, providerId, warehouse_location][0]delEstCostObj.delivery_delay = delivery_estimate_cache[pincode, providerId, warehouse_location][1]delEstCostObj.codAllowed = serviceability[providerId][2]delEstCostObj.otgAvailable = serviceability[providerId][3]delEstCostObj.logisticsCost = costingDetails[0]-costingDetails[1]delEstCostObj.codCollectionCharges = costingDetails[1]return delEstCostObjelse:continueraise LogisticsServiceException(103, "Unable to get Provider for given pincode: " + str(pincode)+" Amount:- "+str(transactionAmount)+" Weight:- "+ str(weight)+".")def get_bluedart_attributes_for_logistics_txn_id(logisticsTxnId, name):bluedartAttr = BluedartAttribute.get_by(logisticsTransactionId=logisticsTxnId,name=name)if bluedartAttr is None:raise LogisticsServiceException(103, "Unable to get bluedart attributes for logisticsTxnId "+logisticsTxnId+" and name "+name)return bluedartAttr