Subversion Repositories SmartDukaan

Rev

Rev 7187 | Rev 7273 | 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, \
7256 rajveer 17
    add_pincode, store_shipment_info, adjust_delivery_time
5944 mandeep.dh 18
from shop2020.thriftpy.logistics.ttypes import LogisticsInfo, \
19
    LogisticsServiceException, DeliveryType, PickUpType
20
from shop2020.thriftpy.model.v1.catalog.ttypes import status
494 rajveer 21
import datetime
644 chandransh 22
import math
1687 vikas 23
import sys
6322 amar.kumar 24
from shop2020.logistics.service.impl.DataService import ServiceableLocationDetails
472 rajveer 25
 
412 ashish 26
class LogisticsServiceHandler:
27
 
3187 rajveer 28
    def __init__(self, dbname='logistics', db_hostname='localhost'):
29
        initialize(dbname, db_hostname)
746 rajveer 30
        try:
31
            config_client = ConfigClient()
5978 rajveer 32
            self.sourceId = int(config_client.get_property("sourceid"))
746 rajveer 33
            self.cutoff_time = int(config_client.get_property('delivery_cutoff_time'))
5843 mandeep.dh 34
            self.cod_cutoff_time = 24 #int(config_client.get_property('delivery_cutoff_time'))
776 rajveer 35
            self.default_pincode = int(config_client.get_property('default_pincode'))
1687 vikas 36
        except Exception as ex:
37
            print "[ERROR] Unexpected config error:", sys.exc_info()[0]
5978 rajveer 38
            self.sourceId = 1
746 rajveer 39
            self.cutoff_time = 15
5843 mandeep.dh 40
            self.cod_cutoff_time = 24
4866 rajveer 41
            self.default_pincode = "110001"
5978 rajveer 42
 
3064 chandransh 43
 
669 chandransh 44
    def getProvider(self, providerId):
675 chandransh 45
        """
46
        Returns a provider for a given provider ID. Throws an exception if none found.
47
 
48
        Parameters:
49
         - providerId
50
        """
796 rajveer 51
        try:
1137 chandransh 52
            provider = get_provider(providerId)
53
            if provider:
54
                return to_t_provider(provider)
55
            else:
56
                raise LogisticsServiceException(101, "No Provider found for the given id")
796 rajveer 57
        finally:
58
            close_session()
59
 
675 chandransh 60
    def getAllProviders(self, ):
61
        """
62
        Returns a list containing all the providers.
63
        """
796 rajveer 64
        try:
65
            return [to_t_provider(provider) for provider in get_providers()]
66
        finally:
67
            close_session()
68
 
5767 rajveer 69
    def getLogisticsInfo(self, destination_pincode, itemId, type, pickUp):
483 rajveer 70
        """
71
        Parameters:
72
         - destination_pincode
716 rajveer 73
         - item_id
3044 chandransh 74
         - type
483 rajveer 75
        """
796 rajveer 76
        try:
3044 chandransh 77
            logistics_info = self.get_logistics_estimation_with_type(itemId, destination_pincode, type)
5767 rajveer 78
            if pickUp == PickUpType.RUNNER or pickUp == PickUpType.SELF:
79
                logistics_info.providerId = get_provider_for_pickup_type(pickUp)
3044 chandransh 80
            logistics_info.airway_billno = get_empty_AWB(logistics_info.providerId, type)
796 rajveer 81
            return logistics_info
82
        finally:
83
            close_session()
84
 
5247 rajveer 85
    def getEmptyAWB(self, providerId, type):
412 ashish 86
        """
87
        Parameters:
88
         - provider_id
5247 rajveer 89
         - type
412 ashish 90
        """
796 rajveer 91
        try:
5247 rajveer 92
            return get_empty_AWB(providerId, type)
796 rajveer 93
        finally:
94
            close_session()
95
 
6643 rajveer 96
    def getShipmentInfo(self, awbNumber, providerId):
412 ashish 97
        """
98
        Parameters:
6643 rajveer 99
         - awbNumber
766 rajveer 100
         - providerId
412 ashish 101
        """
796 rajveer 102
        try:
6643 rajveer 103
            awb_updates = get_shipment_info(awbNumber, providerId)
796 rajveer 104
            t_updates = []
105
            for update in awb_updates:
106
                t_updates.append(to_t_awbupdate(update))
107
            return t_updates
108
        finally:
109
            close_session()
3044 chandransh 110
 
6643 rajveer 111
    def storeShipmentInfo(self, update):
112
        """
113
        Parameters:
114
         - update
115
        """
116
        try:
117
            store_shipment_info(update)
118
        finally:
119
            close_session()
120
 
121
 
4630 mandeep.dh 122
    def getLogisticsEstimation(self, itemId, destination_pin, type):
472 rajveer 123
        """
124
        Parameters:
125
         - itemId
126
         - destination_pin
4630 mandeep.dh 127
         - type
472 rajveer 128
        """
644 chandransh 129
        try:
4630 mandeep.dh 130
            return self.get_logistics_estimation_with_type(itemId, destination_pin, type)
796 rajveer 131
        finally:
132
            close_session()
3044 chandransh 133
 
7256 rajveer 134
 
135
    def getLogisticsEstimationForStore(self, itemId, destination_pin, type):
136
        """
137
        Parameters:
138
         - itemId
139
         - destination_pin
140
         - type
141
        """
142
        try:
143
            todate = datetime.datetime.now()
144
            logistics_info = self.get_logistics_estimation_with_type(itemId, destination_pin, type)
145
            logistics_info.deliveryTime = adjust_delivery_time(todate, logistics_info.deliveryTime)
146
            logistics_info.shippingTime = adjust_delivery_time(todate, logistics_info.shippingTime)
147
            return logistics_info
148
        finally:
149
            close_session()
150
 
4630 mandeep.dh 151
    def get_logistics_estimation_with_type(self, itemId, destination_pin, type):
3044 chandransh 152
        try:
5295 rajveer 153
            #Get the id and location of actual warehouse that'll be used to fulfil this order.
5944 mandeep.dh 154
            client = InventoryClient().get_client()
5983 rajveer 155
            fulfilmentWarehouseId, expected_delay, billingWarehouseId, sellingPrice, totalAvailability = client.getItemAvailabilityAtLocation(itemId, self.sourceId)
3044 chandransh 156
        except Exception as ex:
157
            raise LogisticsServiceException(103, "Unable to fetch inventory information about this item.")
5295 rajveer 158
 
6524 rajveer 159
        delivery_estimate = get_logistics_estimation(destination_pin, sellingPrice)
3218 rajveer 160
        if delivery_estimate is None:
3044 chandransh 161
            raise LogisticsServiceException(104, "Unable to fetch delivery estimate for this pincode.")
5295 rajveer 162
 
3044 chandransh 163
 
5270 rajveer 164
        ## 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 165
        # We are revising the estimates based on the actual warehouse that this order will be assigned to.
166
        # This warehouse may be located in a zone which is different from the one we allocated for this pincode.
5270 rajveer 167
        #delivery_estimate = get_logistics_estimation(destination_pin, item.sellingPrice, warehouse_loc, type)
168
        #if delivery_estimate is None:
169
        #    raise LogisticsServiceException(105, "Unable to fetch delivery estimate for pincode: " + destination_pin + " and revised location: " + str(warehouse_loc))
3044 chandransh 170
 
6537 rajveer 171
        delivery_time = 24 * (delivery_estimate.delivery_time + delivery_estimate.delivery_delay)
3044 chandransh 172
 
4009 chandransh 173
        '''
174
        We're now calculating the expected shipping delay which is independent of
175
        the courier agency and is completely within our control (well, almost).
176
        '''
3355 chandransh 177
        #Always add the expected delay
4009 chandransh 178
        shipping_delay = 24 * expected_delay
3355 chandransh 179
 
4829 rajveer 180
        # Sometimes we set negative shipping delay just in case we know time to procure will be less than the default.
181
        # If we have received inventory and forgot to remove expected delay from item, it could lead to display negative shipping days. 
182
        if shipping_delay < 0:
183
            shipping_delay = 0
184
 
3044 chandransh 185
        #Further increase the estimate if it's late in the day
3064 chandransh 186
        current_hour = datetime.datetime.now().hour
187
        if type == DeliveryType.PREPAID and self.cutoff_time <= current_hour:
4009 chandransh 188
            shipping_delay = shipping_delay + 24
3044 chandransh 189
 
4426 rajveer 190
        #In case of COD,increase delay by one more day
191
        if type == DeliveryType.COD:
192
            shipping_delay = shipping_delay + 24
6524 rajveer 193
            delivery_estimate.otgAvailable = False
4426 rajveer 194
 
4010 chandransh 195
        delivery_time = delivery_time + shipping_delay
196
 
4009 chandransh 197
        shipping_delay = int(math.ceil(shipping_delay/24.0))
4010 chandransh 198
        delivery_time = int(math.ceil(delivery_time/24.0))
3044 chandransh 199
 
7187 rajveer 200
        if itemId in (7943,8195):
6987 rajveer 201
            delivery_estimate.codAllowed = False
3044 chandransh 202
        logistics_info = LogisticsInfo()
203
        logistics_info.deliveryTime = delivery_time
3218 rajveer 204
        logistics_info.providerId = delivery_estimate.provider_id
5110 mandeep.dh 205
        logistics_info.warehouseId = billingWarehouseId
206
        logistics_info.fulfilmentWarehouseId = fulfilmentWarehouseId
4009 chandransh 207
        logistics_info.shippingTime = shipping_delay
4870 rajveer 208
        logistics_info.codAllowed = delivery_estimate.codAllowed 
6524 rajveer 209
        logistics_info.otgAvailable = delivery_estimate.otgAvailable
6726 rajveer 210
        logistics_info.deliveryDelay = delivery_estimate.delivery_delay
3044 chandransh 211
 
5595 anupam.sin 212
        try:
213
            return logistics_info
214
        finally:
215
            close_session()
3044 chandransh 216
 
731 chandransh 217
    def getDestinationCode(self, providerId, pinCode):
218
        """
219
        Returns the short three letter code of a pincode for the given provider.
220
        Raises an exception if the pin code is not serviced by the given provider.
221
 
222
        Parameters:
223
         - providerId
224
         - pinCode
225
        """
796 rajveer 226
        try:
3217 rajveer 227
            try:
3218 rajveer 228
                dest_code = DataAccessor.serviceable_location_cache[providerId][pinCode][0]
3217 rajveer 229
                return dest_code
230
            except:
6017 amar.kumar 231
                try:
232
                    dest_code = get_destination_code(providerId, pinCode) 
233
                    return dest_code
234
                except:
235
                    raise LogisticsServiceException(101, "The pincode " + pinCode + " is not serviced by this provider: " + str(providerId))
796 rajveer 236
        finally:
237
            close_session()
1137 chandransh 238
 
3103 chandransh 239
    def getFreeAwbCount(self, providerId, type):
1137 chandransh 240
        """
3103 chandransh 241
        Returns the number of unused AWB numbers for the given provider of the given type
796 rajveer 242
 
1137 chandransh 243
        Parameters:
244
         - providerId
3103 chandransh 245
         - type
1137 chandransh 246
        """
247
        try:
3103 chandransh 248
            return get_free_awb_count(providerId, type)
1137 chandransh 249
        finally:
250
            close_session()
1730 ankur.sing 251
 
252
    def getHolidays(self, fromDate, toDate):
253
        """
254
        Returns list of Holiday dates between fromDate and toDate (both inclusive)
255
        fromDate should be passed as milliseconds corresponding to the start of the day.
256
        If fromDate is passed as -1, fromDate is not considered for filtering
257
        If toDate is passed as -1, toDate is not considered for filtering
1137 chandransh 258
 
1730 ankur.sing 259
        Parameters:
260
         - fromDate
261
         - toDate
262
        """
263
        try:
264
            return get_holidays(fromDate, toDate)
265
        finally:
266
            close_session()
5527 anupam.sin 267
 
268
    def getProviderForPickupType(self, pickUp):
269
        try:
270
            return get_provider_for_pickup_type(pickUp)
271
        finally:
272
            close_session()
3064 chandransh 273
 
766 rajveer 274
    def closeSession(self, ):
275
        close_session()
3376 rajveer 276
 
277
    def isAlive(self, ):
278
        """
279
        For checking weather service is active alive or not. It also checks connectivity with database
280
        """
281
        try:
282
            return is_alive()
283
        finally:
284
            close_session()
4934 amit.gupta 285
 
286
    def getEntityLogisticsEstimation(self, catalogItemId, destination_pin, type):
287
        """
288
        Returns a LogisticsInfo structure w/o an airway bill number. Use this method during the estimation phase.
289
        Raises an exception if this pincode is not allocated to any warehouse zone or provider. Also, if the pincode
290
        is allocated to a warehouse zone but there are no actual warehouses in that zone, an exception is raised.
291
 
292
        Parameters:
293
         - catalogItemId
294
         - destination_pin
295
         - type
296
        """
297
        try:
298
            return self.get_entity_logistics_estimation_with_type(catalogItemId, destination_pin, type)
299
        finally:
300
            close_session()
301
 
302
    def get_entity_logistics_estimation_with_type(self, catalog_item_id, destination_pin, type):
303
        try:
304
            client = CatalogClient().get_client()
305
            items = client.getValidItemsByCatalogId(catalog_item_id)
306
        except Exception as ex:
307
            raise LogisticsServiceException(103, "Unable to fetch inventory information about this entity.")
308
 
309
        estimateList = []
310
 
311
        for item in items:
312
            estimationInfo = self.get_logistics_estimation_with_type(item.id, destination_pin, type)
313
            if item.itemStatus == status.ACTIVE:
314
                estimateList.append((0, estimationInfo.deliveryTime, item.id))
315
            elif item.itemStatus == status.PAUSED:
316
                estimateList.append((1, estimationInfo.deliveryTime, item.id))
317
            elif item.itemStatus == status.PAUSED_BY_RISK:
318
                estimateList.append((2, estimationInfo.deliveryTime, item.id))
6074 amit.gupta 319
            elif item.itemStatus == status.COMING_SOON:
320
                estimateList.append((3, estimationInfo.deliveryTime, item.id))
4934 amit.gupta 321
 
322
        estimateList.sort()
5595 anupam.sin 323
        try:
324
            return [estimate[-1] for estimate in estimateList]
325
        finally:
326
            close_session()
5555 rajveer 327
 
5595 anupam.sin 328
    def getAllPickupStores(self):
329
        try:
330
            return [to_t_pickup_store(pickup_store) for pickup_store in get_all_pickup_stores()]
331
        finally:
332
            close_session()
5555 rajveer 333
 
334
    def getPickupStore(self, storeId):
335
        """
336
        Parameters:
337
         - storeId
338
        """
5595 anupam.sin 339
        try:
340
            storeToReturn = to_t_pickup_store(get_pickup_store(storeId))
341
            return storeToReturn
342
        finally:
5719 rajveer 343
            close_session()
344
 
345
    def getPickupStoreByHotspotId(self, hotspotId):
346
        """
347
        Parameters:
348
         - hotspotId
349
        """
350
        try:
351
            storeToReturn = to_t_pickup_store(get_pickup_store_by_hotspot_id(hotspotId))
352
            return storeToReturn
353
        finally:
6322 amar.kumar 354
            close_session()
6524 rajveer 355
    def addPincode(self, providerId, pincode, destCode, exp, cod, stationType, otgAvailable):
6322 amar.kumar 356
        try:
6524 rajveer 357
            add_pincode(providerId, pincode, destCode, exp, cod, stationType, otgAvailable)
6322 amar.kumar 358
        finally:
359
            close_session()
6524 rajveer 360
    def updatePincode(self, providerId, pincode, exp, cod, otgAvailable):
6322 amar.kumar 361
        try:
6524 rajveer 362
            update_pincode(providerId, pincode, exp, cod, otgAvailable)
6322 amar.kumar 363
        finally:
5595 anupam.sin 364
            close_session()