Subversion Repositories SmartDukaan

Rev

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