Subversion Repositories SmartDukaan

Rev

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