Subversion Repositories SmartDukaan

Rev

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