Subversion Repositories SmartDukaan

Rev

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

Rev Author Line No. Line
412 ashish 1
'''
2
Created on 05-Aug-2010
3
 
4
@author: ashish
5
'''
3133 rajveer 6
from shop2020.clients.CatalogClient import CatalogClient
5944 mandeep.dh 7
from shop2020.clients.InventoryClient import InventoryClient
494 rajveer 8
from shop2020.config.client.ConfigClient import ConfigClient
5944 mandeep.dh 9
from shop2020.logistics.service.impl import DataAccessor
10
from shop2020.logistics.service.impl.Converters import to_t_awbupdate, \
11
    to_t_provider, to_t_pickup_store
12
from shop2020.logistics.service.impl.DataAccessor import get_empty_AWB, \
13
    get_shipment_info, initialize, get_logistics_estimation, get_provider, \
14
    get_providers, close_session, get_free_awb_count, get_holidays, is_alive, \
15
    get_provider_for_pickup_type, get_pickup_store, get_all_pickup_stores, \
6322 amar.kumar 16
    get_pickup_store_by_hotspot_id, get_destination_code, update_pincode, \
9840 amit.gupta 17
    add_pincode, store_shipment_info, adjust_delivery_time, get_min_advance_amount, \
19413 amit.gupta 18
    add_new_awbs, run_Logistics_Location_Info_Update, \
19
    get_first_delivery_estimate_for_wh_location, \
20
    get_provider_limit_details_for_pincode, get_new_empty_awb, \
19421 manish.sha 21
    get_logistics_locations, get_costing_and_delivery_estimate_for_pincode
9840 amit.gupta 22
from shop2020.logistics.service.impl.DataService import \
23
    ServiceableLocationDetails
19413 amit.gupta 24
from shop2020.thriftpy.logistics.ttypes import ItemText, LogisticsInfo, \
5944 mandeep.dh 25
    LogisticsServiceException, DeliveryType, PickUpType
26
from shop2020.thriftpy.model.v1.catalog.ttypes import status
9840 amit.gupta 27
from shop2020.utils.Utils import to_java_date, to_py_date
28
import collections
494 rajveer 29
import datetime
644 chandransh 30
import math
1687 vikas 31
import sys
9840 amit.gupta 32
#Start:- Added by Manish Sharma for Multiple Pincode Updation on 05-Jul-2013
33
#End:- Added by Manish Sharma for Multiple Pincode Updation on 05-Jul-2013
472 rajveer 34
 
412 ashish 35
class LogisticsServiceHandler:
36
 
3187 rajveer 37
    def __init__(self, dbname='logistics', db_hostname='localhost'):
38
        initialize(dbname, db_hostname)
746 rajveer 39
        try:
40
            config_client = ConfigClient()
5978 rajveer 41
            self.sourceId = int(config_client.get_property("sourceid"))
746 rajveer 42
            self.cutoff_time = int(config_client.get_property('delivery_cutoff_time'))
5843 mandeep.dh 43
            self.cod_cutoff_time = 24 #int(config_client.get_property('delivery_cutoff_time'))
776 rajveer 44
            self.default_pincode = int(config_client.get_property('default_pincode'))
1687 vikas 45
        except Exception as ex:
46
            print "[ERROR] Unexpected config error:", sys.exc_info()[0]
5978 rajveer 47
            self.sourceId = 1
746 rajveer 48
            self.cutoff_time = 15
5843 mandeep.dh 49
            self.cod_cutoff_time = 24
4866 rajveer 50
            self.default_pincode = "110001"
5978 rajveer 51
 
3064 chandransh 52
 
669 chandransh 53
    def getProvider(self, providerId):
675 chandransh 54
        """
55
        Returns a provider for a given provider ID. Throws an exception if none found.
56
 
57
        Parameters:
58
         - providerId
59
        """
796 rajveer 60
        try:
1137 chandransh 61
            provider = get_provider(providerId)
62
            if provider:
63
                return to_t_provider(provider)
64
            else:
65
                raise LogisticsServiceException(101, "No Provider found for the given id")
796 rajveer 66
        finally:
67
            close_session()
68
 
675 chandransh 69
    def getAllProviders(self, ):
70
        """
71
        Returns a list containing all the providers.
72
        """
796 rajveer 73
        try:
74
            return [to_t_provider(provider) for provider in get_providers()]
75
        finally:
76
            close_session()
77
 
5767 rajveer 78
    def getLogisticsInfo(self, destination_pincode, itemId, type, pickUp):
483 rajveer 79
        """
80
        Parameters:
81
         - destination_pincode
716 rajveer 82
         - item_id
3044 chandransh 83
         - type
483 rajveer 84
        """
796 rajveer 85
        try:
3044 chandransh 86
            logistics_info = self.get_logistics_estimation_with_type(itemId, destination_pincode, type)
5767 rajveer 87
            if pickUp == PickUpType.RUNNER or pickUp == PickUpType.SELF:
88
                logistics_info.providerId = get_provider_for_pickup_type(pickUp)
7946 manish.sha 89
            #logistics_info.airway_billno = get_empty_AWB(logistics_info.providerId, type)
796 rajveer 90
            return logistics_info
91
        finally:
92
            close_session()
93
 
5247 rajveer 94
    def getEmptyAWB(self, providerId, type):
412 ashish 95
        """
96
        Parameters:
97
         - provider_id
5247 rajveer 98
         - type
412 ashish 99
        """
796 rajveer 100
        try:
5247 rajveer 101
            return get_empty_AWB(providerId, type)
796 rajveer 102
        finally:
103
            close_session()
104
 
6643 rajveer 105
    def getShipmentInfo(self, awbNumber, providerId):
412 ashish 106
        """
107
        Parameters:
6643 rajveer 108
         - awbNumber
766 rajveer 109
         - providerId
412 ashish 110
        """
796 rajveer 111
        try:
6643 rajveer 112
            awb_updates = get_shipment_info(awbNumber, providerId)
796 rajveer 113
            t_updates = []
114
            for update in awb_updates:
115
                t_updates.append(to_t_awbupdate(update))
116
            return t_updates
117
        finally:
118
            close_session()
3044 chandransh 119
 
6643 rajveer 120
    def storeShipmentInfo(self, update):
121
        """
122
        Parameters:
123
         - update
124
        """
125
        try:
126
            store_shipment_info(update)
127
        finally:
128
            close_session()
129
 
130
 
4630 mandeep.dh 131
    def getLogisticsEstimation(self, itemId, destination_pin, type):
472 rajveer 132
        """
133
        Parameters:
134
         - itemId
135
         - destination_pin
4630 mandeep.dh 136
         - type
472 rajveer 137
        """
644 chandransh 138
        try:
4630 mandeep.dh 139
            return self.get_logistics_estimation_with_type(itemId, destination_pin, type)
796 rajveer 140
        finally:
141
            close_session()
3044 chandransh 142
 
7256 rajveer 143
 
144
    def getLogisticsEstimationForStore(self, itemId, destination_pin, type):
145
        """
146
        Parameters:
147
         - itemId
148
         - destination_pin
149
         - type
150
        """
151
        try:
152
            todate = datetime.datetime.now()
153
            logistics_info = self.get_logistics_estimation_with_type(itemId, destination_pin, type)
7273 rajveer 154
            logistics_info.deliveryTime = to_java_date(todate +  datetime.timedelta(days = adjust_delivery_time(todate, logistics_info.deliveryTime)))
155
            logistics_info.shippingTime = to_java_date(todate +  datetime.timedelta(days = adjust_delivery_time(todate, logistics_info.shippingTime)))
7275 rajveer 156
            minAdvanceAmount, logistics_info.codAllowed = get_min_advance_amount(itemId, destination_pin, logistics_info.providerId, logistics_info.codAllowed)
157
            ## Send minadvanceamount in providerId field 
158
            logistics_info.providerId = int(minAdvanceAmount)
7256 rajveer 159
            return logistics_info
160
        finally:
161
            close_session()
162
 
4630 mandeep.dh 163
    def get_logistics_estimation_with_type(self, itemId, destination_pin, type):
3044 chandransh 164
        try:
5295 rajveer 165
            #Get the id and location of actual warehouse that'll be used to fulfil this order.
5944 mandeep.dh 166
            client = InventoryClient().get_client()
7589 rajveer 167
            fulfilmentWarehouseId, expected_delay, billingWarehouseId, sellingPrice, totalAvailability, weight = client.getItemAvailabilityAtLocation(itemId, self.sourceId)
3044 chandransh 168
        except Exception as ex:
169
            raise LogisticsServiceException(103, "Unable to fetch inventory information about this item.")
5295 rajveer 170
 
7608 rajveer 171
        delivery_estimate = get_logistics_estimation(destination_pin, sellingPrice, weight, type, billingWarehouseId)
3218 rajveer 172
        if delivery_estimate is None:
3044 chandransh 173
            raise LogisticsServiceException(104, "Unable to fetch delivery estimate for this pincode.")
5295 rajveer 174
 
3044 chandransh 175
 
5270 rajveer 176
        ## Commented below part as we have only Delhi as warehouse city. If we will add some more warehouses in different cities, this could be  useful. 
4009 chandransh 177
        # We are revising the estimates based on the actual warehouse that this order will be assigned to.
178
        # This warehouse may be located in a zone which is different from the one we allocated for this pincode.
5270 rajveer 179
        #delivery_estimate = get_logistics_estimation(destination_pin, item.sellingPrice, warehouse_loc, type)
180
        #if delivery_estimate is None:
181
        #    raise LogisticsServiceException(105, "Unable to fetch delivery estimate for pincode: " + destination_pin + " and revised location: " + str(warehouse_loc))
3044 chandransh 182
 
6537 rajveer 183
        delivery_time = 24 * (delivery_estimate.delivery_time + delivery_estimate.delivery_delay)
3044 chandransh 184
 
4009 chandransh 185
        '''
186
        We're now calculating the expected shipping delay which is independent of
187
        the courier agency and is completely within our control (well, almost).
188
        '''
3355 chandransh 189
        #Always add the expected delay
4009 chandransh 190
        shipping_delay = 24 * expected_delay
3355 chandransh 191
 
4829 rajveer 192
        # Sometimes we set negative shipping delay just in case we know time to procure will be less than the default.
193
        # If we have received inventory and forgot to remove expected delay from item, it could lead to display negative shipping days. 
194
        if shipping_delay < 0:
195
            shipping_delay = 0
196
 
3044 chandransh 197
        #Further increase the estimate if it's late in the day
3064 chandransh 198
        current_hour = datetime.datetime.now().hour
199
        if type == DeliveryType.PREPAID and self.cutoff_time <= current_hour:
4009 chandransh 200
            shipping_delay = shipping_delay + 24
3044 chandransh 201
 
4426 rajveer 202
        #In case of COD,increase delay by one more day
203
        if type == DeliveryType.COD:
204
            shipping_delay = shipping_delay + 24
6524 rajveer 205
            delivery_estimate.otgAvailable = False
4426 rajveer 206
 
4010 chandransh 207
        delivery_time = delivery_time + shipping_delay
208
 
4009 chandransh 209
        shipping_delay = int(math.ceil(shipping_delay/24.0))
4010 chandransh 210
        delivery_time = int(math.ceil(delivery_time/24.0))
3044 chandransh 211
 
212
        logistics_info = LogisticsInfo()
213
        logistics_info.deliveryTime = delivery_time
3218 rajveer 214
        logistics_info.providerId = delivery_estimate.provider_id
5110 mandeep.dh 215
        logistics_info.warehouseId = billingWarehouseId
216
        logistics_info.fulfilmentWarehouseId = fulfilmentWarehouseId
4009 chandransh 217
        logistics_info.shippingTime = shipping_delay
4870 rajveer 218
        logistics_info.codAllowed = delivery_estimate.codAllowed 
6524 rajveer 219
        logistics_info.otgAvailable = delivery_estimate.otgAvailable
6726 rajveer 220
        logistics_info.deliveryDelay = delivery_estimate.delivery_delay
3044 chandransh 221
 
5595 anupam.sin 222
        try:
223
            return logistics_info
224
        finally:
225
            close_session()
3044 chandransh 226
 
731 chandransh 227
    def getDestinationCode(self, providerId, pinCode):
228
        """
229
        Returns the short three letter code of a pincode for the given provider.
230
        Raises an exception if the pin code is not serviced by the given provider.
231
 
232
        Parameters:
233
         - providerId
234
         - pinCode
235
        """
796 rajveer 236
        try:
3217 rajveer 237
            try:
3218 rajveer 238
                dest_code = DataAccessor.serviceable_location_cache[providerId][pinCode][0]
3217 rajveer 239
                return dest_code
240
            except:
6017 amar.kumar 241
                try:
242
                    dest_code = get_destination_code(providerId, pinCode) 
243
                    return dest_code
244
                except:
8182 amar.kumar 245
                    if providerId >7:
246
                        return ""
6017 amar.kumar 247
                    raise LogisticsServiceException(101, "The pincode " + pinCode + " is not serviced by this provider: " + str(providerId))
796 rajveer 248
        finally:
249
            close_session()
1137 chandransh 250
 
3103 chandransh 251
    def getFreeAwbCount(self, providerId, type):
1137 chandransh 252
        """
3103 chandransh 253
        Returns the number of unused AWB numbers for the given provider of the given type
796 rajveer 254
 
1137 chandransh 255
        Parameters:
256
         - providerId
3103 chandransh 257
         - type
1137 chandransh 258
        """
259
        try:
3103 chandransh 260
            return get_free_awb_count(providerId, type)
1137 chandransh 261
        finally:
262
            close_session()
1730 ankur.sing 263
 
264
    def getHolidays(self, fromDate, toDate):
265
        """
266
        Returns list of Holiday dates between fromDate and toDate (both inclusive)
267
        fromDate should be passed as milliseconds corresponding to the start of the day.
268
        If fromDate is passed as -1, fromDate is not considered for filtering
269
        If toDate is passed as -1, toDate is not considered for filtering
1137 chandransh 270
 
1730 ankur.sing 271
        Parameters:
272
         - fromDate
273
         - toDate
274
        """
275
        try:
276
            return get_holidays(fromDate, toDate)
277
        finally:
278
            close_session()
5527 anupam.sin 279
 
280
    def getProviderForPickupType(self, pickUp):
281
        try:
282
            return get_provider_for_pickup_type(pickUp)
283
        finally:
284
            close_session()
3064 chandransh 285
 
766 rajveer 286
    def closeSession(self, ):
287
        close_session()
3376 rajveer 288
 
289
    def isAlive(self, ):
290
        """
291
        For checking weather service is active alive or not. It also checks connectivity with database
292
        """
293
        try:
294
            return is_alive()
295
        finally:
296
            close_session()
4934 amit.gupta 297
 
298
    def getEntityLogisticsEstimation(self, catalogItemId, destination_pin, type):
299
        """
300
        Returns a LogisticsInfo structure w/o an airway bill number. Use this method during the estimation phase.
301
        Raises an exception if this pincode is not allocated to any warehouse zone or provider. Also, if the pincode
302
        is allocated to a warehouse zone but there are no actual warehouses in that zone, an exception is raised.
303
 
304
        Parameters:
305
         - catalogItemId
306
         - destination_pin
307
         - type
308
        """
309
        try:
310
            return self.get_entity_logistics_estimation_with_type(catalogItemId, destination_pin, type)
311
        finally:
312
            close_session()
313
 
314
    def get_entity_logistics_estimation_with_type(self, catalog_item_id, destination_pin, type):
315
        try:
316
            client = CatalogClient().get_client()
317
            items = client.getValidItemsByCatalogId(catalog_item_id)
318
        except Exception as ex:
319
            raise LogisticsServiceException(103, "Unable to fetch inventory information about this entity.")
320
 
321
        estimateList = []
322
 
323
        for item in items:
11254 amit.gupta 324
            try:
325
                estimationInfo = self.get_logistics_estimation_with_type(item.id, destination_pin, type)
326
            except Exception as ex:
327
                estimationInfo = LogisticsInfo()
328
                estimationInfo.deliveryTime = 0
4934 amit.gupta 329
            if item.itemStatus == status.ACTIVE:
9840 amit.gupta 330
                estimateList.append((0, estimationInfo.deliveryTime, "BUY NOW", item.id))
4934 amit.gupta 331
            elif item.itemStatus == status.PAUSED:
9840 amit.gupta 332
                estimateList.append((1, estimationInfo.deliveryTime, "NOTIFY ME", item.id))
4934 amit.gupta 333
            elif item.itemStatus == status.PAUSED_BY_RISK:
9840 amit.gupta 334
                estimateList.append((2, estimationInfo.deliveryTime, "NOTIFY ME", item.id))
6074 amit.gupta 335
            elif item.itemStatus == status.COMING_SOON:
10688 amit.gupta 336
                estimateList.append((3, estimationInfo.deliveryTime, "NOTIFY ME", item.id))
4934 amit.gupta 337
 
338
        estimateList.sort()
5595 anupam.sin 339
        try:
9840 amit.gupta 340
            return [ ItemText(estimate[-1], estimate[-2]) for estimate in estimateList]
5595 anupam.sin 341
        finally:
342
            close_session()
5555 rajveer 343
 
5595 anupam.sin 344
    def getAllPickupStores(self):
345
        try:
346
            return [to_t_pickup_store(pickup_store) for pickup_store in get_all_pickup_stores()]
347
        finally:
348
            close_session()
5555 rajveer 349
 
350
    def getPickupStore(self, storeId):
351
        """
352
        Parameters:
353
         - storeId
354
        """
5595 anupam.sin 355
        try:
356
            storeToReturn = to_t_pickup_store(get_pickup_store(storeId))
357
            return storeToReturn
358
        finally:
5719 rajveer 359
            close_session()
360
 
361
    def getPickupStoreByHotspotId(self, hotspotId):
362
        """
363
        Parameters:
364
         - hotspotId
365
        """
366
        try:
367
            storeToReturn = to_t_pickup_store(get_pickup_store_by_hotspot_id(hotspotId))
368
            return storeToReturn
369
        finally:
6322 amar.kumar 370
            close_session()
6524 rajveer 371
    def addPincode(self, providerId, pincode, destCode, exp, cod, stationType, otgAvailable):
6322 amar.kumar 372
        try:
6524 rajveer 373
            add_pincode(providerId, pincode, destCode, exp, cod, stationType, otgAvailable)
6322 amar.kumar 374
        finally:
375
            close_session()
6524 rajveer 376
    def updatePincode(self, providerId, pincode, exp, cod, otgAvailable):
6322 amar.kumar 377
        try:
6524 rajveer 378
            update_pincode(providerId, pincode, exp, cod, otgAvailable)
6322 amar.kumar 379
        finally:
7567 rajveer 380
            close_session()
381
 
13146 manish.sha 382
    def addNewAwbs(self, providerId, isCod, awbs, awbUsedFor):
7567 rajveer 383
        try:
13146 manish.sha 384
            return add_new_awbs(providerId, isCod, awbs, awbUsedFor)
7567 rajveer 385
        finally:
7733 manish.sha 386
            close_session()
7786 manish.sha 387
 
388
 
389
    def runLogisticsLocationInfoUpdate(self, logisticsLocationInfoList, runCompleteUpdate):
7733 manish.sha 390
        try:
7786 manish.sha 391
            run_Logistics_Location_Info_Update(logisticsLocationInfoList, runCompleteUpdate)
7733 manish.sha 392
        finally:
393
            close_session()
7888 rajveer 394
 
395
    def adjustDeliveryDays(self, startDate, days):
396
        try:
397
            return adjust_delivery_time(to_py_date(startDate), days)
398
        finally:
12895 manish.sha 399
            close_session()
400
 
401
    def getFirstDeliveryEstimateForWhLocation(self, pincode, whLocation):
402
        try:
403
            return get_first_delivery_estimate_for_wh_location(pincode, whLocation)
404
        finally:
13146 manish.sha 405
            close_session()
406
 
407
    def getProviderLimitDetailsForPincode(self, providerId, pincode):
408
        try:
409
            return get_provider_limit_details_for_pincode(providerId, pincode)
410
        finally:
411
            close_session()
412
 
413
    def getNewEmptyAwb(self, providerId, type, orderQuantity):
414
        try:
415
            return get_new_empty_awb(providerId, type, orderQuantity)
416
        finally:
417
            close_session()
19421 manish.sha 418
 
19413 amit.gupta 419
    def getLocationInfoMap(self, destinationPin, sellingPriceList):
420
        try:
421
            return get_logistics_locations(destinationPin, sellingPriceList)
422
        finally:
19421 manish.sha 423
            close_session()
424
 
19474 manish.sha 425
    def getCostingAndDeliveryEstimateForPincode(self, pincode, transactionAmount, isCod, weight, billingWarehouseId, isCompleteTxn):
19421 manish.sha 426
        try:
19474 manish.sha 427
            costingAndDeliveryEstimateObj = get_costing_and_delivery_estimate_for_pincode(pincode, transactionAmount, isCod, weight, billingWarehouseId, isCompleteTxn)
19421 manish.sha 428
            delivery_time = 24 * (costingAndDeliveryEstimateObj.deliveryTime + costingAndDeliveryEstimateObj.delivery_delay)
429
            shipping_delay = 0
430
 
431
            #Further increase the estimate if it's late in the day
432
            current_hour = datetime.datetime.now().hour
433
            if not isCod and self.cutoff_time <= current_hour:
434
                shipping_delay = shipping_delay + 24
435
 
436
            #In case of COD,increase delay by one more day
437
            if isCod:
438
                shipping_delay = shipping_delay + 24
439
                costingAndDeliveryEstimateObj.otgAvailable = False
440
 
441
            delivery_time = delivery_time + shipping_delay
442
 
443
            shipping_delay = int(math.ceil(shipping_delay/24.0))
444
            delivery_time = int(math.ceil(delivery_time/24.0))
445
 
446
            costingAndDeliveryEstimateObj.deliveryTime = delivery_time
447
            costingAndDeliveryEstimateObj.shippingTime = shipping_delay
448
            return costingAndDeliveryEstimateObj
449
        finally:
450
            close_session()
451