Subversion Repositories SmartDukaan

Rev

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