Subversion Repositories SmartDukaan

Rev

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