Subversion Repositories SmartDukaan

Rev

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