Subversion Repositories SmartDukaan

Rev

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