Subversion Repositories SmartDukaan

Rev

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