Subversion Repositories SmartDukaan

Rev

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