Subversion Repositories SmartDukaan

Rev

Rev 20724 | Rev 22634 | 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, \
22
    get_bluedart_attributes_for_logistics_txn_id
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:
3044 chandransh 87
            logistics_info = self.get_logistics_estimation_with_type(itemId, destination_pincode, type)
5767 rajveer 88
            if pickUp == PickUpType.RUNNER or pickUp == PickUpType.SELF:
89
                logistics_info.providerId = get_provider_for_pickup_type(pickUp)
7946 manish.sha 90
            #logistics_info.airway_billno = get_empty_AWB(logistics_info.providerId, type)
796 rajveer 91
            return logistics_info
92
        finally:
93
            close_session()
94
 
20724 kshitij.so 95
    def getEmptyAWB(self, providerId, logisticsTransactionId):
412 ashish 96
        """
97
        Parameters:
98
         - provider_id
5247 rajveer 99
         - type
412 ashish 100
        """
796 rajveer 101
        try:
20724 kshitij.so 102
            return get_empty_AWB(providerId, logisticsTransactionId)
796 rajveer 103
        finally:
104
            close_session()
105
 
6643 rajveer 106
    def getShipmentInfo(self, awbNumber, providerId):
412 ashish 107
        """
108
        Parameters:
6643 rajveer 109
         - awbNumber
766 rajveer 110
         - providerId
412 ashish 111
        """
796 rajveer 112
        try:
6643 rajveer 113
            awb_updates = get_shipment_info(awbNumber, providerId)
796 rajveer 114
            t_updates = []
115
            for update in awb_updates:
116
                t_updates.append(to_t_awbupdate(update))
117
            return t_updates
118
        finally:
119
            close_session()
3044 chandransh 120
 
6643 rajveer 121
    def storeShipmentInfo(self, update):
122
        """
123
        Parameters:
124
         - update
125
        """
126
        try:
127
            store_shipment_info(update)
128
        finally:
129
            close_session()
130
 
131
 
4630 mandeep.dh 132
    def getLogisticsEstimation(self, itemId, destination_pin, type):
472 rajveer 133
        """
134
        Parameters:
135
         - itemId
136
         - destination_pin
4630 mandeep.dh 137
         - type
472 rajveer 138
        """
644 chandransh 139
        try:
4630 mandeep.dh 140
            return self.get_logistics_estimation_with_type(itemId, destination_pin, type)
796 rajveer 141
        finally:
142
            close_session()
3044 chandransh 143
 
7256 rajveer 144
 
145
    def getLogisticsEstimationForStore(self, itemId, destination_pin, type):
146
        """
147
        Parameters:
148
         - itemId
149
         - destination_pin
150
         - type
151
        """
152
        try:
153
            todate = datetime.datetime.now()
154
            logistics_info = self.get_logistics_estimation_with_type(itemId, destination_pin, type)
7273 rajveer 155
            logistics_info.deliveryTime = to_java_date(todate +  datetime.timedelta(days = adjust_delivery_time(todate, logistics_info.deliveryTime)))
156
            logistics_info.shippingTime = to_java_date(todate +  datetime.timedelta(days = adjust_delivery_time(todate, logistics_info.shippingTime)))
7275 rajveer 157
            minAdvanceAmount, logistics_info.codAllowed = get_min_advance_amount(itemId, destination_pin, logistics_info.providerId, logistics_info.codAllowed)
158
            ## Send minadvanceamount in providerId field 
159
            logistics_info.providerId = int(minAdvanceAmount)
7256 rajveer 160
            return logistics_info
161
        finally:
162
            close_session()
163
 
4630 mandeep.dh 164
    def get_logistics_estimation_with_type(self, itemId, destination_pin, type):
3044 chandransh 165
        try:
5295 rajveer 166
            #Get the id and location of actual warehouse that'll be used to fulfil this order.
5944 mandeep.dh 167
            client = InventoryClient().get_client()
7589 rajveer 168
            fulfilmentWarehouseId, expected_delay, billingWarehouseId, sellingPrice, totalAvailability, weight = client.getItemAvailabilityAtLocation(itemId, self.sourceId)
3044 chandransh 169
        except Exception as ex:
170
            raise LogisticsServiceException(103, "Unable to fetch inventory information about this item.")
5295 rajveer 171
 
7608 rajveer 172
        delivery_estimate = get_logistics_estimation(destination_pin, sellingPrice, weight, type, billingWarehouseId)
3218 rajveer 173
        if delivery_estimate is None:
3044 chandransh 174
            raise LogisticsServiceException(104, "Unable to fetch delivery estimate for this pincode.")
5295 rajveer 175
 
3044 chandransh 176
 
5270 rajveer 177
        ## 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 178
        # We are revising the estimates based on the actual warehouse that this order will be assigned to.
179
        # This warehouse may be located in a zone which is different from the one we allocated for this pincode.
5270 rajveer 180
        #delivery_estimate = get_logistics_estimation(destination_pin, item.sellingPrice, warehouse_loc, type)
181
        #if delivery_estimate is None:
182
        #    raise LogisticsServiceException(105, "Unable to fetch delivery estimate for pincode: " + destination_pin + " and revised location: " + str(warehouse_loc))
3044 chandransh 183
 
6537 rajveer 184
        delivery_time = 24 * (delivery_estimate.delivery_time + delivery_estimate.delivery_delay)
3044 chandransh 185
 
4009 chandransh 186
        '''
187
        We're now calculating the expected shipping delay which is independent of
188
        the courier agency and is completely within our control (well, almost).
189
        '''
3355 chandransh 190
        #Always add the expected delay
4009 chandransh 191
        shipping_delay = 24 * expected_delay
3355 chandransh 192
 
4829 rajveer 193
        # Sometimes we set negative shipping delay just in case we know time to procure will be less than the default.
194
        # If we have received inventory and forgot to remove expected delay from item, it could lead to display negative shipping days. 
195
        if shipping_delay < 0:
196
            shipping_delay = 0
197
 
3044 chandransh 198
        #Further increase the estimate if it's late in the day
3064 chandransh 199
        current_hour = datetime.datetime.now().hour
200
        if type == DeliveryType.PREPAID and self.cutoff_time <= current_hour:
4009 chandransh 201
            shipping_delay = shipping_delay + 24
3044 chandransh 202
 
4426 rajveer 203
        #In case of COD,increase delay by one more day
204
        if type == DeliveryType.COD:
205
            shipping_delay = shipping_delay + 24
6524 rajveer 206
            delivery_estimate.otgAvailable = False
4426 rajveer 207
 
4010 chandransh 208
        delivery_time = delivery_time + shipping_delay
209
 
4009 chandransh 210
        shipping_delay = int(math.ceil(shipping_delay/24.0))
4010 chandransh 211
        delivery_time = int(math.ceil(delivery_time/24.0))
3044 chandransh 212
 
213
        logistics_info = LogisticsInfo()
214
        logistics_info.deliveryTime = delivery_time
3218 rajveer 215
        logistics_info.providerId = delivery_estimate.provider_id
5110 mandeep.dh 216
        logistics_info.warehouseId = billingWarehouseId
217
        logistics_info.fulfilmentWarehouseId = fulfilmentWarehouseId
4009 chandransh 218
        logistics_info.shippingTime = shipping_delay
4870 rajveer 219
        logistics_info.codAllowed = delivery_estimate.codAllowed 
6524 rajveer 220
        logistics_info.otgAvailable = delivery_estimate.otgAvailable
6726 rajveer 221
        logistics_info.deliveryDelay = delivery_estimate.delivery_delay
3044 chandransh 222
 
5595 anupam.sin 223
        try:
224
            return logistics_info
225
        finally:
226
            close_session()
3044 chandransh 227
 
731 chandransh 228
    def getDestinationCode(self, providerId, pinCode):
229
        """
230
        Returns the short three letter code of a pincode for the given provider.
231
        Raises an exception if the pin code is not serviced by the given provider.
232
 
233
        Parameters:
234
         - providerId
235
         - pinCode
236
        """
796 rajveer 237
        try:
3217 rajveer 238
            try:
3218 rajveer 239
                dest_code = DataAccessor.serviceable_location_cache[providerId][pinCode][0]
3217 rajveer 240
                return dest_code
241
            except:
6017 amar.kumar 242
                try:
243
                    dest_code = get_destination_code(providerId, pinCode) 
244
                    return dest_code
245
                except:
8182 amar.kumar 246
                    if providerId >7:
247
                        return ""
6017 amar.kumar 248
                    raise LogisticsServiceException(101, "The pincode " + pinCode + " is not serviced by this provider: " + str(providerId))
796 rajveer 249
        finally:
250
            close_session()
1137 chandransh 251
 
3103 chandransh 252
    def getFreeAwbCount(self, providerId, type):
1137 chandransh 253
        """
3103 chandransh 254
        Returns the number of unused AWB numbers for the given provider of the given type
796 rajveer 255
 
1137 chandransh 256
        Parameters:
257
         - providerId
3103 chandransh 258
         - type
1137 chandransh 259
        """
260
        try:
3103 chandransh 261
            return get_free_awb_count(providerId, type)
1137 chandransh 262
        finally:
263
            close_session()
1730 ankur.sing 264
 
265
    def getHolidays(self, fromDate, toDate):
266
        """
267
        Returns list of Holiday dates between fromDate and toDate (both inclusive)
268
        fromDate should be passed as milliseconds corresponding to the start of the day.
269
        If fromDate is passed as -1, fromDate is not considered for filtering
270
        If toDate is passed as -1, toDate is not considered for filtering
1137 chandransh 271
 
1730 ankur.sing 272
        Parameters:
273
         - fromDate
274
         - toDate
275
        """
276
        try:
277
            return get_holidays(fromDate, toDate)
278
        finally:
279
            close_session()
5527 anupam.sin 280
 
281
    def getProviderForPickupType(self, pickUp):
282
        try:
283
            return get_provider_for_pickup_type(pickUp)
284
        finally:
285
            close_session()
3064 chandransh 286
 
766 rajveer 287
    def closeSession(self, ):
288
        close_session()
3376 rajveer 289
 
290
    def isAlive(self, ):
291
        """
292
        For checking weather service is active alive or not. It also checks connectivity with database
293
        """
294
        try:
295
            return is_alive()
296
        finally:
297
            close_session()
4934 amit.gupta 298
 
299
    def getEntityLogisticsEstimation(self, catalogItemId, destination_pin, type):
300
        """
301
        Returns a LogisticsInfo structure w/o an airway bill number. Use this method during the estimation phase.
302
        Raises an exception if this pincode is not allocated to any warehouse zone or provider. Also, if the pincode
303
        is allocated to a warehouse zone but there are no actual warehouses in that zone, an exception is raised.
304
 
305
        Parameters:
306
         - catalogItemId
307
         - destination_pin
308
         - type
309
        """
310
        try:
311
            return self.get_entity_logistics_estimation_with_type(catalogItemId, destination_pin, type)
312
        finally:
313
            close_session()
314
 
315
    def get_entity_logistics_estimation_with_type(self, catalog_item_id, destination_pin, type):
316
        try:
317
            client = CatalogClient().get_client()
318
            items = client.getValidItemsByCatalogId(catalog_item_id)
319
        except Exception as ex:
320
            raise LogisticsServiceException(103, "Unable to fetch inventory information about this entity.")
321
 
322
        estimateList = []
323
 
324
        for item in items:
11254 amit.gupta 325
            try:
326
                estimationInfo = self.get_logistics_estimation_with_type(item.id, destination_pin, type)
327
            except Exception as ex:
328
                estimationInfo = LogisticsInfo()
329
                estimationInfo.deliveryTime = 0
4934 amit.gupta 330
            if item.itemStatus == status.ACTIVE:
9840 amit.gupta 331
                estimateList.append((0, estimationInfo.deliveryTime, "BUY NOW", item.id))
4934 amit.gupta 332
            elif item.itemStatus == status.PAUSED:
9840 amit.gupta 333
                estimateList.append((1, estimationInfo.deliveryTime, "NOTIFY ME", item.id))
4934 amit.gupta 334
            elif item.itemStatus == status.PAUSED_BY_RISK:
9840 amit.gupta 335
                estimateList.append((2, estimationInfo.deliveryTime, "NOTIFY ME", item.id))
6074 amit.gupta 336
            elif item.itemStatus == status.COMING_SOON:
10688 amit.gupta 337
                estimateList.append((3, estimationInfo.deliveryTime, "NOTIFY ME", item.id))
4934 amit.gupta 338
 
339
        estimateList.sort()
5595 anupam.sin 340
        try:
9840 amit.gupta 341
            return [ ItemText(estimate[-1], estimate[-2]) for estimate in estimateList]
5595 anupam.sin 342
        finally:
343
            close_session()
5555 rajveer 344
 
5595 anupam.sin 345
    def getAllPickupStores(self):
346
        try:
347
            return [to_t_pickup_store(pickup_store) for pickup_store in get_all_pickup_stores()]
348
        finally:
349
            close_session()
5555 rajveer 350
 
351
    def getPickupStore(self, storeId):
352
        """
353
        Parameters:
354
         - storeId
355
        """
5595 anupam.sin 356
        try:
357
            storeToReturn = to_t_pickup_store(get_pickup_store(storeId))
358
            return storeToReturn
359
        finally:
5719 rajveer 360
            close_session()
361
 
362
    def getPickupStoreByHotspotId(self, hotspotId):
363
        """
364
        Parameters:
365
         - hotspotId
366
        """
367
        try:
368
            storeToReturn = to_t_pickup_store(get_pickup_store_by_hotspot_id(hotspotId))
369
            return storeToReturn
370
        finally:
6322 amar.kumar 371
            close_session()
6524 rajveer 372
    def addPincode(self, providerId, pincode, destCode, exp, cod, stationType, otgAvailable):
6322 amar.kumar 373
        try:
6524 rajveer 374
            add_pincode(providerId, pincode, destCode, exp, cod, stationType, otgAvailable)
6322 amar.kumar 375
        finally:
376
            close_session()
6524 rajveer 377
    def updatePincode(self, providerId, pincode, exp, cod, otgAvailable):
6322 amar.kumar 378
        try:
6524 rajveer 379
            update_pincode(providerId, pincode, exp, cod, otgAvailable)
6322 amar.kumar 380
        finally:
7567 rajveer 381
            close_session()
382
 
13146 manish.sha 383
    def addNewAwbs(self, providerId, isCod, awbs, awbUsedFor):
7567 rajveer 384
        try:
13146 manish.sha 385
            return add_new_awbs(providerId, isCod, awbs, awbUsedFor)
7567 rajveer 386
        finally:
7733 manish.sha 387
            close_session()
7786 manish.sha 388
 
389
 
390
    def runLogisticsLocationInfoUpdate(self, logisticsLocationInfoList, runCompleteUpdate):
7733 manish.sha 391
        try:
7786 manish.sha 392
            run_Logistics_Location_Info_Update(logisticsLocationInfoList, runCompleteUpdate)
7733 manish.sha 393
        finally:
394
            close_session()
7888 rajveer 395
 
396
    def adjustDeliveryDays(self, startDate, days):
397
        try:
398
            return adjust_delivery_time(to_py_date(startDate), days)
399
        finally:
12895 manish.sha 400
            close_session()
401
 
402
    def getFirstDeliveryEstimateForWhLocation(self, pincode, whLocation):
403
        try:
404
            return get_first_delivery_estimate_for_wh_location(pincode, whLocation)
405
        finally:
13146 manish.sha 406
            close_session()
407
 
408
    def getProviderLimitDetailsForPincode(self, providerId, pincode):
409
        try:
410
            return get_provider_limit_details_for_pincode(providerId, pincode)
411
        finally:
412
            close_session()
413
 
414
    def getNewEmptyAwb(self, providerId, type, orderQuantity):
415
        try:
416
            return get_new_empty_awb(providerId, type, orderQuantity)
417
        finally:
418
            close_session()
19421 manish.sha 419
 
19413 amit.gupta 420
    def getLocationInfoMap(self, destinationPin, sellingPriceList):
421
        try:
422
            return get_logistics_locations(destinationPin, sellingPriceList)
423
        finally:
19421 manish.sha 424
            close_session()
425
 
19474 manish.sha 426
    def getCostingAndDeliveryEstimateForPincode(self, pincode, transactionAmount, isCod, weight, billingWarehouseId, isCompleteTxn):
19421 manish.sha 427
        try:
19474 manish.sha 428
            costingAndDeliveryEstimateObj = get_costing_and_delivery_estimate_for_pincode(pincode, transactionAmount, isCod, weight, billingWarehouseId, isCompleteTxn)
19421 manish.sha 429
            delivery_time = 24 * (costingAndDeliveryEstimateObj.deliveryTime + costingAndDeliveryEstimateObj.delivery_delay)
430
            shipping_delay = 0
431
 
432
            #Further increase the estimate if it's late in the day
433
            current_hour = datetime.datetime.now().hour
434
            if not isCod and self.cutoff_time <= current_hour:
435
                shipping_delay = shipping_delay + 24
436
 
437
            #In case of COD,increase delay by one more day
438
            if isCod:
439
                shipping_delay = shipping_delay + 24
440
                costingAndDeliveryEstimateObj.otgAvailable = False
441
 
442
            delivery_time = delivery_time + shipping_delay
443
 
444
            shipping_delay = int(math.ceil(shipping_delay/24.0))
445
            delivery_time = int(math.ceil(delivery_time/24.0))
446
 
447
            costingAndDeliveryEstimateObj.deliveryTime = delivery_time
448
            costingAndDeliveryEstimateObj.shippingTime = shipping_delay
449
            return costingAndDeliveryEstimateObj
450
        finally:
451
            close_session()
20745 kshitij.so 452
 
453
    def getBluedartAttributesForLogisticsTxnId(self, logisticsTxnId, name):
454
        try:
455
            return to_t_bluedart_attribute(get_bluedart_attributes_for_logistics_txn_id(logisticsTxnId, name))
456
        finally:
457
            close_session()