Subversion Repositories SmartDukaan

Rev

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