Subversion Repositories SmartDukaan

Rev

Rev 12895 | Rev 13158 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
442 rajveer 1
'''
2
Created on 13-Sep-2010
3
 
4
@author: rajveer
5
'''
6
 
7
from shop2020.logistics.service.impl import DataService
644 chandransh 8
from shop2020.logistics.service.impl.DataService import Awb, AwbUpdate, Provider, \
3218 rajveer 9
     DeliveryEstimate, WarehouseAllocation, \
5555 rajveer 10
    PublicHolidays, ServiceableLocationDetails, PickupStore
3044 chandransh 11
from shop2020.thriftpy.logistics.ttypes import LogisticsServiceException,\
7786 manish.sha 12
    DeliveryType, LogisticsLocationInfo
442 rajveer 13
from shop2020.utils.Utils import log_entry, to_py_date, to_java_date
5964 amar.kumar 14
from sqlalchemy.sql import or_
442 rajveer 15
from elixir import session
1730 ankur.sing 16
import datetime, time
1504 ankur.sing 17
import sys
3355 chandransh 18
import logging
13146 manish.sha 19
import os
7293 anupam.sin 20
from shop2020.clients.CatalogClient import CatalogClient
3355 chandransh 21
logging.basicConfig(level=logging.DEBUG)
442 rajveer 22
 
3217 rajveer 23
warehouse_allocation_cache = {}
24
serviceable_location_cache = {}
25
delivery_estimate_cache = {}
6370 rajveer 26
 
3218 rajveer 27
'''
28
This class is for only data transfer. Never used outside this module.
29
'''
30
class _DeliveryEstimateObject:
6537 rajveer 31
    def __init__(self, delivery_time, delivery_delay, provider_id, codAllowed, otgAvailable):
3218 rajveer 32
        self.delivery_time = delivery_time
6537 rajveer 33
        self.delivery_delay = delivery_delay
3218 rajveer 34
        self.provider_id = provider_id
4866 rajveer 35
        self.codAllowed = codAllowed
6524 rajveer 36
        self.otgAvailable = otgAvailable
3218 rajveer 37
 
3187 rajveer 38
def initialize(dbname="logistics", db_hostname="localhost"):
442 rajveer 39
    log_entry("initialize@DataAccessor", "Initializing data service")
3187 rajveer 40
    DataService.initialize(dbname, db_hostname)
3218 rajveer 41
    print "Starting cache population at: " + str(datetime.datetime.now())
3217 rajveer 42
    __cache_warehouse_allocation_table()
43
    __cache_serviceable_location_details_table()
44
    __cache_delivery_estimate_table()
45
    close_session()
3218 rajveer 46
    print "Done cache population at: " + str(datetime.datetime.now())
442 rajveer 47
 
3217 rajveer 48
def __cache_delivery_estimate_table():
49
    delivery_estimates = DeliveryEstimate.query.all()
50
    for delivery_estimate in delivery_estimates:
7857 rajveer 51
        delivery_estimate_cache[delivery_estimate.destination_pin, delivery_estimate.provider_id, delivery_estimate.warehouse_location]\
6537 rajveer 52
        =delivery_estimate.delivery_time, delivery_estimate.delivery_delay
3217 rajveer 53
 
54
def __cache_serviceable_location_details_table():
5964 amar.kumar 55
    serviceable_locations = ServiceableLocationDetails.query.filter(or_("exp!=0","cod!=0"))
3217 rajveer 56
    for serviceable_location in serviceable_locations:
57
        try:
58
            provider_pincodes = serviceable_location_cache[serviceable_location.provider_id]
59
        except:
60
            provider_pincodes = {}
61
            serviceable_location_cache[serviceable_location.provider_id] = provider_pincodes 
7627 rajveer 62
        provider_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
3217 rajveer 63
 
64
def __cache_warehouse_allocation_table():
65
    warehouse_allocations = WarehouseAllocation.query.all()
66
    for warehouse_allocation in warehouse_allocations:
67
        warehouse_allocation_cache[warehouse_allocation.pincode]=warehouse_allocation.primary_warehouse_location
68
 
644 chandransh 69
def get_provider(provider_id):
766 rajveer 70
    provider =  Provider.get_by(id=provider_id)
71
    return provider
644 chandransh 72
 
73
def get_providers():
5387 rajveer 74
    providers = Provider.query.filter_by(isActive = 1).all()
766 rajveer 75
    return providers 
644 chandransh 76
 
7608 rajveer 77
def get_logistics_estimation(destination_pin, item_selling_price, weight, type, billingWarehouseId):
5692 rajveer 78
    logging.info("Getting logistics estimation for pincode:" + destination_pin )
1504 ankur.sing 79
 
7608 rajveer 80
    provider_id, codAllowed, otgAvailable = __get_logistics_provider_for_destination_pincode(destination_pin, item_selling_price, weight, type, billingWarehouseId)
9964 anupam.sin 81
 
82
    if item_selling_price > 60000 or item_selling_price <= 250:
83
        codAllowed = False
84
 
7857 rajveer 85
    warehouse_location = 0
86
    if billingWarehouseId in [12,13]:
87
        warehouse_location = 1
88
 
3217 rajveer 89
    if not provider_id:
5692 rajveer 90
        raise LogisticsServiceException(101, "No provider assigned for pincode: " + str(destination_pin))
644 chandransh 91
    try:
7857 rajveer 92
        delivery_time = delivery_estimate_cache[destination_pin, provider_id, warehouse_location][0]
93
        delivery_delay = delivery_estimate_cache[destination_pin, provider_id, warehouse_location][1]
6537 rajveer 94
        delivery_estimate = _DeliveryEstimateObject(delivery_time, delivery_delay, provider_id, codAllowed, otgAvailable)
3218 rajveer 95
        return delivery_estimate
1504 ankur.sing 96
    except Exception as ex:
97
        print ex
644 chandransh 98
        raise LogisticsServiceException(103, "No Logistics partner listed for this destination pincode and the primary warehouse")
3150 rajveer 99
 
7608 rajveer 100
def __get_logistics_provider_for_destination_pincode(destination_pin, item_selling_price, weight, type, billingWarehouseId):
9154 rajveer 101
    if serviceable_location_cache.get(6).has_key(destination_pin):
102
        if weight < 480 and serviceable_location_cache.get(3).has_key(destination_pin) and type == DeliveryType.PREPAID:
7981 rajveer 103
            dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(3).get(destination_pin)
104
            if item_selling_price <= providerPrepaidLimit:
105
                iscod = iscod and item_selling_price <= websiteCodLimit
106
                otgAvailable = otgAvailable and item_selling_price >= 2000
107
                return 3, iscod, otgAvailable
108
        else:
109
            dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(6).get(destination_pin)
110
            if item_selling_price <= providerPrepaidLimit:
111
                iscod = iscod and item_selling_price <= websiteCodLimit
112
                otgAvailable = otgAvailable and item_selling_price >= 2000
113
                return 6, iscod, otgAvailable
114
 
115
    if serviceable_location_cache.get(3).has_key(destination_pin):
116
        dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(3).get(destination_pin)
7627 rajveer 117
        if item_selling_price <= providerPrepaidLimit:
7608 rajveer 118
            iscod = iscod and item_selling_price <= websiteCodLimit
119
            otgAvailable = otgAvailable and item_selling_price >= 2000
7981 rajveer 120
            return 3, iscod, otgAvailable
8575 rajveer 121
 
122
    if billingWarehouseId not in [12,13] and serviceable_location_cache.get(7).has_key(destination_pin):
123
        if item_selling_price < 3000 and serviceable_location_cache.get(1).has_key(destination_pin):
124
            dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(1).get(destination_pin)
125
            if item_selling_price <= providerPrepaidLimit:
126
                iscod = iscod and item_selling_price <= websiteCodLimit
127
                otgAvailable = otgAvailable and item_selling_price >= 2000
128
                return 1, iscod, otgAvailable
129
        else:
130
            dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(7).get(destination_pin)
131
            if item_selling_price <= providerPrepaidLimit:
132
                iscod = iscod and item_selling_price <= websiteCodLimit
133
                otgAvailable = otgAvailable and item_selling_price >= 2000
134
                return 7, iscod, otgAvailable
135
 
7627 rajveer 136
    if serviceable_location_cache.get(1).has_key(destination_pin):
137
        dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit, providerPrepaidLimit = serviceable_location_cache.get(1).get(destination_pin)
138
        if item_selling_price <= providerPrepaidLimit:
7608 rajveer 139
            iscod = iscod and item_selling_price <= websiteCodLimit
140
            otgAvailable = otgAvailable and item_selling_price >= 2000
7627 rajveer 141
            return 1, iscod, otgAvailable
7981 rajveer 142
 
10185 amit.gupta 143
    return None, False, False    
5278 rajveer 144
 
6017 amar.kumar 145
def get_destination_code(providerId, pinCode):
146
    serviceableLocationDetail = ServiceableLocationDetails.query.filter_by(provider_id = providerId, dest_pincode = pinCode).one()
147
    return serviceableLocationDetail.dest_code
148
 
644 chandransh 149
def add_empty_AWBs(numbers, provider_id, type):
442 rajveer 150
    for number in numbers:
644 chandransh 151
        query = Awb.query.filter_by(awb_number = number, provider_id = provider_id)
444 rajveer 152
        try:
153
            query.one()
154
        except:    
644 chandransh 155
            awb = Awb()
444 rajveer 156
            awb.awb_number = number
644 chandransh 157
            awb.provider_id = provider_id
444 rajveer 158
            awb.is_available = True
644 chandransh 159
            awb.type = type
160
    session.commit()
442 rajveer 161
 
444 rajveer 162
def set_AWB_as_used(awb_number):
644 chandransh 163
    query = Awb.query.filter_by(awb_number = awb_number)
444 rajveer 164
    awb = query.one() 
165
    awb.is_available=False
166
    session.commit()
167
 
3044 chandransh 168
def get_empty_AWB(provider_id, type = DeliveryType.PREPAID):
2342 chandransh 169
    query = Awb.query.with_lockmode("update").filter_by(provider_id = provider_id, is_available = True)  #check the provider thing
3044 chandransh 170
    if type == DeliveryType.PREPAID:
171
        query = query.filter_by(type="Prepaid")
172
    if type == DeliveryType.COD:
173
        query = query.filter_by(type="COD")
174
 
442 rajveer 175
    try:
644 chandransh 176
        awb = query.first()
177
        awb.is_available = False
178
        session.commit()
444 rajveer 179
        return awb.awb_number
442 rajveer 180
    except:
644 chandransh 181
        raise LogisticsServiceException(103, "Unable to get an AWB for the given Provider: " + str(provider_id))
1137 chandransh 182
 
3103 chandransh 183
def get_free_awb_count(provider_id, type):
184
    count = Awb.query.filter_by(provider_id = provider_id, is_available = True, type=type).count()
1137 chandransh 185
    if count == None:
186
        count = 0
187
    return count
442 rajveer 188
 
644 chandransh 189
def get_shipment_info(awb_number, provider_id):
190
    awb = Awb.get_by(awb_number = awb_number, provider_id = provider_id)
191
    query = AwbUpdate.query.filter_by(awb = awb)
766 rajveer 192
    info = query.all()
193
    return info
194
 
6643 rajveer 195
def store_shipment_info(update):
196
    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()
197
    if not updates:
198
        dupdate = AwbUpdate()
199
        dupdate.providerId = update.providerId
200
        dupdate.awbNumber  = update.awbNumber
201
        dupdate.location = update.location
202
        dupdate.date = to_py_date(update.date)
203
        dupdate.status = update.status
204
        dupdate.description = update.description
205
        session.commit()
206
 
1730 ankur.sing 207
def get_holidays(start_date, end_date):
208
    query = PublicHolidays.query
209
    if start_date != -1:
210
        query = query.filter(PublicHolidays.date >= to_py_date(start_date))
211
    if end_date != -1:
212
        query = query.filter(PublicHolidays.date <= to_py_date(end_date))
213
    holidays = query.all()
214
    holiday_dates = [to_java_date(datetime.datetime(*time.strptime(str(holiday.date), '%Y-%m-%d')[:3])) for holiday in holidays] 
215
    return holiday_dates
216
 
5527 anupam.sin 217
def get_provider_for_pickup_type(pickUp):
218
    return Provider.query.filter(Provider.pickup == pickUp).first().id
219
 
766 rajveer 220
def close_session():
221
    if session.is_active:
222
        print "session is active. closing it."
2823 chandransh 223
        session.close()
3376 rajveer 224
 
225
def is_alive():
226
    try:
227
        session.query(Awb.id).limit(1).one()
228
        return True
229
    except:
5555 rajveer 230
        return False
231
 
232
def get_all_pickup_stores():
5572 anupam.sin 233
    pickupStores = PickupStore.query.all()
234
    return pickupStores
5555 rajveer 235
 
236
def get_pickup_store(storeId):
5719 rajveer 237
    return PickupStore.query.filter_by(id = storeId).one()
238
 
239
def get_pickup_store_by_hotspot_id(hotspotId):
240
    return PickupStore.query.filter_by(hotspotId = hotspotId).one()
6322 amar.kumar 241
 
6524 rajveer 242
def add_pincode(provider, pincode, destCode, exp, cod, stationType, otgAvailable):
7914 rajveer 243
    provider = Provider.query.filter_by(id = provider).one()
6322 amar.kumar 244
    serviceableLocationDetails = ServiceableLocationDetails()
245
    serviceableLocationDetails.provider = provider
246
    serviceableLocationDetails.dest_pincode = pincode
247
    serviceableLocationDetails.dest_code = destCode
248
    serviceableLocationDetails.exp = exp
249
    serviceableLocationDetails.cod = cod
250
    serviceableLocationDetails.station_type = stationType
6524 rajveer 251
    serviceableLocationDetails.otgAvailable = otgAvailable
7733 manish.sha 252
    if provider.id == 1:
7627 rajveer 253
        codlimit = 10000
254
        prepaidlimit = 50000
7733 manish.sha 255
    elif provider.id == 3:
7627 rajveer 256
        codlimit = 25000
257
        prepaidlimit = 100000
7733 manish.sha 258
    elif provider.id == 6:
7627 rajveer 259
        codlimit = 25000
260
        prepaidlimit = 100000
261
    serviceableLocationDetails.providerPrepaidLimit = prepaidlimit
262
    serviceableLocationDetails.providerCodLimit = codlimit
263
    serviceableLocationDetails.websiteCodLimit = codlimit
264
    serviceableLocationDetails.storeCodLimit = codlimit
6322 amar.kumar 265
    session.commit()
266
 
6524 rajveer 267
def update_pincode(providerId, pincode, exp, cod, otgAvailable):
6615 amar.kumar 268
    serviceableLocationDetails = ServiceableLocationDetails.get_by(provider_id = providerId, dest_pincode = pincode)
6322 amar.kumar 269
    serviceableLocationDetails.exp = exp
270
    serviceableLocationDetails.cod = cod
6524 rajveer 271
    serviceableLocationDetails.otgAvailable = otgAvailable
7256 rajveer 272
    session.commit()
7567 rajveer 273
 
13146 manish.sha 274
def add_new_awbs(provider_id, isCod, awbs, awbUsedFor):
7567 rajveer 275
    provider = get_provider(provider_id)
276
    if isCod:
277
        dtype = 'Cod'
278
    else:
279
        dtype = 'Prepaid'
280
    for awb in awbs:
281
        a = Awb()
282
        a.type =  dtype
283
        a.is_available = True
284
        a.awb_number = awb
13146 manish.sha 285
        a.awbUsedFor = awbUsedFor
7567 rajveer 286
        a.provider = provider 
287
    session.commit()
7608 rajveer 288
    return True
7256 rajveer 289
 
290
def adjust_delivery_time(start_time, delivery_days):
291
    '''
292
    Returns the actual no. of days which will pass while 'delivery_days'
293
    no. of business days will pass since 'order_time'. 
294
    '''
295
    start_date = start_time.date()
296
    end_date = start_date + datetime.timedelta(days = delivery_days)
7272 amit.gupta 297
    holidays = get_holidays(to_java_date(start_time), -1)
7256 rajveer 298
    holidays = [to_py_date(holiday).date() for holiday in holidays]
299
 
300
    while start_date <= end_date:
301
        if start_date.weekday() == 6 or start_date in holidays:
302
            delivery_days = delivery_days + 1
303
            end_date = end_date + datetime.timedelta(days = 1)
304
        start_date = start_date + datetime.timedelta(days = 1)
305
 
306
    return delivery_days
7275 rajveer 307
 
308
def get_min_advance_amount(itemId, destination_pin, providerId, codAllowed):
309
    client = CatalogClient().get_client()
310
    sp = client.getStorePricing(itemId)
311
 
312
    if codAllowed:
313
        return sp.minAdvancePrice, True
314
    else:
7857 rajveer 315
        dest_code, exp, iscod, otgAvailable, websiteCodLimit, storeCodLimit = serviceable_location_cache.get(providerId).get(destination_pin)
7275 rajveer 316
        if iscod:
317
            if providerId == 6:
7489 rajveer 318
                return max(sp.minAdvancePrice, sp.recommendedPrice - storeCodLimit), True
7275 rajveer 319
            if providerId == 3:
7489 rajveer 320
                return max(sp.minAdvancePrice, sp.recommendedPrice - storeCodLimit), True
7275 rajveer 321
            if providerId == 1:
7489 rajveer 322
                return max(sp.minAdvancePrice, sp.recommendedPrice - storeCodLimit), True
7275 rajveer 323
        else:
7425 rajveer 324
            return sp.recommendedPrice, False
7733 manish.sha 325
#Start:- Added by Manish Sharma for Multiple Pincode Updation on 05-Jul-2013
326
 
7786 manish.sha 327
def run_Logistics_Location_Info_Update(logisticsLocationInfoList, runCompleteUpdate):
328
    if runCompleteUpdate == True :
329
        serviceableLocationDetails = ServiceableLocationDetails.query.all()
330
        for serviceableLocationDetail in serviceableLocationDetails:
7841 manish.sha 331
            serviceableLocationDetail.exp = False
332
            serviceableLocationDetail.cod = False
7786 manish.sha 333
    for logisticsLocationInfo in logisticsLocationInfoList:
7841 manish.sha 334
        serviceableLocationDetail = ServiceableLocationDetails.get_by(provider_id = logisticsLocationInfo.providerId, dest_pincode = logisticsLocationInfo.pinCode)
7914 rajveer 335
        provider = Provider.query.filter_by(id = logisticsLocationInfo.providerId).one()
7841 manish.sha 336
        if serviceableLocationDetail:
337
            serviceableLocationDetail.exp = logisticsLocationInfo.expAvailable
338
            serviceableLocationDetail.cod = logisticsLocationInfo.codAvailable
339
            serviceableLocationDetail.otgAvailable = logisticsLocationInfo.otgAvailable
340
            serviceableLocationDetail.providerCodLimit = logisticsLocationInfo.codLimit
341
            serviceableLocationDetail.providerPrepaidLimit = logisticsLocationInfo.prepaidLimit
342
            serviceableLocationDetail.storeCodLimit = logisticsLocationInfo.codLimit
8219 manish.sha 343
            serviceableLocationDetail.websiteCodLimit = min(26000,logisticsLocationInfo.codLimit)
7841 manish.sha 344
        else:
345
            serviceableLocationDetail= ServiceableLocationDetails()
346
            serviceableLocationDetail.provider = provider
347
            serviceableLocationDetail.dest_pincode = logisticsLocationInfo.pinCode
348
            serviceableLocationDetail.dest_code = logisticsLocationInfo.destinationCode
349
            serviceableLocationDetail.exp = logisticsLocationInfo.expAvailable
350
            serviceableLocationDetail.cod = logisticsLocationInfo.codAvailable
351
            serviceableLocationDetail.station_type = 0
352
            serviceableLocationDetail.otgAvailable = logisticsLocationInfo.otgAvailable
353
            serviceableLocationDetail.providerCodLimit = logisticsLocationInfo.codLimit
354
            serviceableLocationDetail.providerPrepaidLimit = logisticsLocationInfo.prepaidLimit
355
            serviceableLocationDetail.storeCodLimit = logisticsLocationInfo.codLimit
8219 manish.sha 356
            serviceableLocationDetail.websiteCodLimit = min(26000,logisticsLocationInfo.codLimit)
7841 manish.sha 357
 
7870 rajveer 358
        deliveryEstimate = DeliveryEstimate.get_by(provider_id = logisticsLocationInfo.providerId, destination_pin = logisticsLocationInfo.pinCode, warehouse_location = logisticsLocationInfo.warehouseId) 
7841 manish.sha 359
        if deliveryEstimate:
360
            deliveryEstimate.warehouse_location= logisticsLocationInfo.warehouseId
361
            deliveryEstimate.delivery_time= logisticsLocationInfo.deliveryTime
362
            deliveryEstimate.delivery_delay= logisticsLocationInfo.delivery_delay
363
        else:
364
            deliveryEstimate = DeliveryEstimate()
365
            deliveryEstimate.destination_pin= logisticsLocationInfo.pinCode
366
            deliveryEstimate.provider = provider
367
            deliveryEstimate.warehouse_location= logisticsLocationInfo.warehouseId
368
            deliveryEstimate.delivery_time= logisticsLocationInfo.deliveryTime
369
            deliveryEstimate.delivery_delay= logisticsLocationInfo.delivery_delay
7733 manish.sha 370
    session.commit()
7786 manish.sha 371
 
7733 manish.sha 372
#End:- Added by Manish Sharma for Multiple Pincode Updation on 05-Jul-2013             
7275 rajveer 373
 
12895 manish.sha 374
def get_first_delivery_estimate_for_wh_location(pincode, whLocation):
375
    delEstimate = DeliveryEstimate.query.filter(DeliveryEstimate.destination_pin == pincode).filter(DeliveryEstimate.warehouse_location == whLocation).first()
376
    if delEstimate is None:
377
        return -1
378
    else:
379
        return 1
13146 manish.sha 380
 
381
def get_provider_limit_details_for_pincode(provider, pincode):
382
    serviceAbleDetails = ServiceableLocationDetails.get_by(provider_id = provider, dest_pincode = pincode)
383
    returnDataMap = {}
384
    if serviceAbleDetails:
385
        returnDataMap["websiteCodLimit"] = str(serviceAbleDetails.websiteCodLimit)
386
        returnDataMap["providerPrepaidLimit"] = str(serviceAbleDetails.providerPrepaidLimit)
387
 
388
    return returnDataMap
389
 
390
def get_new_empty_awb(providerId, type, orderQuantity):
391
    query = Awb.query.with_lockmode("update").filter_by(provider_id = providerId, is_available = True)  #check the provider thing
392
    if type == DeliveryType.PREPAID:
393
        query = query.filter_by(type="Prepaid")
394
    if type == DeliveryType.COD:
395
        query = query.filter_by(type="COD")
396
 
397
    additionalQuery = query
398
    if orderQuantity == 1:
399
        query = query.filter_by(awbUsedFor=0)
400
    if orderQuantity >1:
401
        query = query.filter_by(awbUsedFor=1) 
402
 
403
    try:
404
        awb = query.first()
405
        if awb is None:
406
            additionalQuery = additionalQuery.filter_by(awbUsedFor=2)
407
            awb = additionalQuery.first()
408
        awb.is_available = False
409
        session.commit()
410
        return awb.awb_number
411
    except:
412
        raise LogisticsServiceException(103, "Unable to get an AWB for the given Provider: " + str(providerId))
413