Subversion Repositories SmartDukaan

Rev

Rev 6524 | Rev 6532 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5944 mandeep.dh 1
'''
2
Created on 23-Mar-2010
3
 
4
@author: ashish
5
'''
6
from elixir import *
7
from functools import partial
6531 vikram.rag 8
from shop2020.clients.CatalogClient import CatalogClient
5944 mandeep.dh 9
from shop2020.clients.TransactionClient import TransactionClient
10
from shop2020.model.v1.inventory.impl import DataService
6531 vikram.rag 11
from shop2020.model.v1.inventory.impl.Convertors import to_t_warehouse, \
12
    to_t_itemidwarehouseid
5944 mandeep.dh 13
from shop2020.model.v1.inventory.impl.DataService import Warehouse, \
14
    ItemInventoryHistory, CurrentInventorySnapshot, VendorItemPricing, \
15
    VendorItemMapping, Vendor, MissedInventoryUpdate, BadInventorySnapshot, \
6531 vikram.rag 16
    VendorItemProcurementDelay, VendorHolidays, ItemAvailabilityCache, \
17
    CurrentReservationSnapshot, IgnoredInventoryUpdateItems
18
from shop2020.thriftpy.model.v1.inventory.ttypes import \
19
    InventoryServiceException, HolidayType, InventoryType, WarehouseType
5944 mandeep.dh 20
from shop2020.thriftpy.model.v1.order.ttypes import AlertType
6531 vikram.rag 21
from shop2020.thriftpy.purchase.ttypes import PurchaseServiceException
5944 mandeep.dh 22
from shop2020.utils import EmailAttachmentSender
23
from shop2020.utils.EmailAttachmentSender import mail
6531 vikram.rag 24
from shop2020.utils.Utils import to_py_date
5944 mandeep.dh 25
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
6531 vikram.rag 26
from sqlalchemy.sql.expression import and_, func, distinct
27
from sqlalchemy.sql.functions import count
5944 mandeep.dh 28
import calendar
29
import datetime
30
import sys
31
import threading
32
 
6501 rajveer 33
to_addresses = ["chaitnaya.vats@shop2020.in", "chandan.kumar@shop2020.in"]
6029 rajveer 34
mail_user = "cnc.center@shop2020.in"
35
mail_password = "5h0p2o2o"
5944 mandeep.dh 36
skippedItems = { 175 : [27, 2160, 2175, 2163, 2158, 7128, 26, 2154],
37
                 193 : [5839] }
38
 
6498 vikram.rag 39
 
40
 
5944 mandeep.dh 41
def initialize(dbname='inventory', db_hostname="localhost"):
42
    DataService.initialize(dbname, db_hostname)
43
 
44
def get_Warehouse(warehouse_id):
45
    return Warehouse.get_by(id=warehouse_id)
46
 
47
def get_vendor(vendorId):
48
    return Vendor.get_by(id=vendorId)
49
 
50
def get_all_warehouses_by_status(status):
51
    return Warehouse.query.all()
52
 
53
def get_all_items_for_warehouse(warehouse_id):
54
    warehouse = get_Warehouse(warehouse_id)
55
    if not warehouse:
56
        raise InventoryServiceException(108, "bad warehouse")
57
    return warehouse.all_items
58
 
59
def add_warehouse(warehouse):
60
    if not warehouse:
61
        raise InventoryServiceException(108, "Bad warehouse")
62
    if get_Warehouse(warehouse.id):
63
        #warehouse is already present.
64
        raise InventoryServiceException(101, "Warehouse already present")
65
 
66
    ds_warehouse = Warehouse()
67
    ds_warehouse.location = warehouse.location
68
    ds_warehouse.status = 3
69
    ds_warehouse.addedOn = datetime.datetime.now()
70
    ds_warehouse.lastCheckedOn = datetime.datetime.now()
71
    ds_warehouse.tinNumber = warehouse.tinNumber
72
    ds_warehouse.pincode = warehouse.pincode
73
    ds_warehouse.billingType = warehouse.billingType
74
    ds_warehouse.billingWarehouseId = warehouse.billingWarehouseId
75
    ds_warehouse.displayName = warehouse.displayName
76
    ds_warehouse.inventoryType = InventoryType._VALUES_TO_NAMES[warehouse.inventoryType]
77
    ds_warehouse.isAvailabilityMonitored = warehouse.isAvailabilityMonitored
78
    ds_warehouse.logisticsLocation = warehouse.logisticsLocation
79
    ds_warehouse.shippingWarehouseId = warehouse.shippingWarehouseId
80
    ds_warehouse.transferDelayInHours = warehouse.transferDelayInHours
81
    ds_warehouse.vendor = get_vendor(warehouse.vendor.id)
82
    ds_warehouse.warehouseType = WarehouseType._VALUES_TO_NAMES[warehouse.warehouseType]    
83
    if warehouse.vendorString:
84
        ds_warehouse.vendorString = warehouse.vendorString
85
    session.commit()
86
    return ds_warehouse.id
87
 
6498 vikram.rag 88
def get_ignored_items(warehouse_id): 
6531 vikram.rag 89
    Ignored_inventory_items = IgnoredInventoryUpdateItems.query.filter_by(warehouse_id=warehouse_id).all()
6498 vikram.rag 90
    negativeItems = []
91
    for Ignored_inventory_item in Ignored_inventory_items:
92
        try:
93
            item_id = Ignored_inventory_item.item_id
94
            negativeItems.append(item_id)
95
        except:
96
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
97
    return negativeItems
98
 
6510 rajveer 99
def get_ignored_warehouses(item_id): 
100
    Ignored_inventory_items = Ignoredinventoryupdateitems.query.filter_by(item_id=item_id).all()
101
    warehouses = []
102
    for Ignored_inventory_item in Ignored_inventory_items:
103
        warehouses.append(Ignored_inventory_item.warehouse_id)
104
    return warehouses
105
 
5944 mandeep.dh 106
def update_inventory_history(warehouse_id, timestamp, availability):
107
    warehouse = get_Warehouse(warehouse_id)
108
    if not warehouse:
109
        raise InventoryServiceException(107, "Warehouse? Where?")
110
    vendor = warehouse.vendor
111
    time = datetime.datetime.now()
112
    for item_key, quantity in availability.iteritems():
113
        try:
114
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
5960 mandeep.dh 115
            item_id = vendor_item_mapping.item_id
5944 mandeep.dh 116
        except:
6531 vikram.rag 117
            continue  
5944 mandeep.dh 118
        try:
6510 rajveer 119
            item_inventory_history = ItemInventoryHistory()
120
            item_inventory_history.warehouse = warehouse
121
            item_inventory_history.item_id = item_id
122
            item_inventory_history.timestamp = time
123
            item_inventory_history.availability = quantity
5944 mandeep.dh 124
        except:
125
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
126
    session.commit()
127
 
128
def update_inventory(warehouse_id, timestamp, availability):
129
    warehouse = get_Warehouse(warehouse_id)
130
    if not warehouse:
131
        raise InventoryServiceException(107, "Warehouse? Where?")
6510 rajveer 132
 
5944 mandeep.dh 133
    time = datetime.datetime.now()
134
    warehouse.lastCheckedOn = time
135
    warehouse.vendorString = timestamp
136
    vendor = warehouse.vendor
137
    item_ids = []
138
    for item_key, quantity in availability.iteritems():
139
        try:
140
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
141
            item_id = vendor_item_mapping.item_id
6510 rajveer 142
            item_ids.append(item_id)
5944 mandeep.dh 143
        except:
144
            print 'Skipping update for ' + item_key + ' quantity ' + str(quantity) + ' warehouse id: ' + str(warehouse_id)
145
            __send_mail_for_missing_key(item_key, quantity, warehouse_id)
146
            continue
147
        try:
148
            current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=item_id, warehouse=warehouse)
149
            if not current_inventory_snapshot:
150
                current_inventory_snapshot = CurrentInventorySnapshot()
151
                current_inventory_snapshot.item_id = item_id
152
                current_inventory_snapshot.warehouse = warehouse
153
                current_inventory_snapshot.availability = 0
154
                current_inventory_snapshot.reserved = 0
155
            # added the difference in the current inventory    
156
            current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
157
            item = __get_item_from_master(item_id)
158
            try:
159
                if quantity > 0 and __get_item_reserved(item_id) > 0:
160
                    cl = TransactionClient().get_client()
161
                    #FIXME hardcoding for warehouse id 
162
                    cl.addAlert(AlertType.NEW_INVENTORY_ALERT, 5, "Inventory received for item " + item.brand + " " + item.modelName + " " + item.modelNumber + " " +  item.color)
163
            except:
164
                print "Not able to raise alert for incoming inventory" 
165
            if current_inventory_snapshot.availability < 0:
166
                __send_alert_for_negative_availability(item, current_inventory_snapshot.availability, warehouse)
167
        except:
168
            print "Some unforeseen error while updating inventory:", sys.exc_info()[0]
169
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
170
    session.commit()
171
 
172
    #**Update item availability cache**#
173
    for item_id in item_ids:
5978 rajveer 174
        clear_item_availability_cache(item_id)
5944 mandeep.dh 175
 
176
def __send_alert_for_negative_reserved(item, reserved, warehouse):
177
    itemName = " ".join([str(item.id), str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
6029 rajveer 178
    EmailAttachmentSender.mail(mail_user, mail_password, 'amar.kumar@shop2020.in', 'Negative reserved: ' + str(reserved) + ' for Item Id: ' + itemName + ' warehouse id: ' + str(warehouse.id), None)
5944 mandeep.dh 179
 
180
def __send_alert_for_negative_availability(item, availability, warehouse):
181
    itemName = " ".join([str(item.id), str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
5964 amar.kumar 182
    # EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', 'amar.kumar@shop2020.in', 'Negative availability ' + str(availability) + ' for Item id: ' + itemName + ' warehouse id: ' + str(warehouse.id), None)
5944 mandeep.dh 183
 
184
def __send_mail_for_missing_key(item_key, quantity, warehouse_id):
185
    missedInventoryUpdate = MissedInventoryUpdate.get_by(itemKey = item_key, warehouseId = warehouse_id)
186
    # One email per product key mismatch
187
    if not missedInventoryUpdate:
188
        missedInventoryUpdate = MissedInventoryUpdate()
189
        missedInventoryUpdate.itemKey = item_key
190
        missedInventoryUpdate.quantity = quantity
191
        missedInventoryUpdate.isIgnored = 1
192
        missedInventoryUpdate.timestamp = datetime.datetime.now()
193
        missedInventoryUpdate.warehouseId = warehouse_id
194
        session.commit()
6232 rajveer 195
        try:
6242 amar.kumar 196
            EmailAttachmentSender.mail(mail_user, mail_password, ['chaitnaya.vats@shop2020.in', 'chandan.kumar@spiceretail.co.in', 'amar.kumar@shop2020.in'], 'Skipped inventory update for ' + item_key + ' quantity ' + str(quantity) + ' warehouse id: ' + str(warehouse_id), None)
6232 rajveer 197
        except:
198
            print "Not able to send email. No issues, we can continue with updates."
5944 mandeep.dh 199
    else:
200
        missedInventoryUpdate.quantity += quantity
201
        session.commit()
202
 
203
def add_inventory(itemId, warehouseId, quantity):
204
    current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
205
    if not current_inventory_snapshot:
206
        current_inventory_snapshot = CurrentInventorySnapshot()
207
        current_inventory_snapshot.item_id = itemId
208
        current_inventory_snapshot.warehouse_id = warehouseId
209
        current_inventory_snapshot.availability = 0
210
        current_inventory_snapshot.reserved = 0
211
    # added the difference in the current inventory    
212
    current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
213
    session.commit()
214
    #**Update item availability cache**#
5978 rajveer 215
    clear_item_availability_cache(itemId)
5944 mandeep.dh 216
    if current_inventory_snapshot.availability < 0:
217
        item = __get_item_from_master(itemId)
5978 rajveer 218
        __send_alert_for_negative_availability(item, current_inventory_snapshot.availability, get_Warehouse(warehouseId)) 
5944 mandeep.dh 219
 
220
def add_bad_inventory(itemId, warehouseId, quantity):
221
    bad_inventory_snapshot = BadInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
222
    if not bad_inventory_snapshot:
223
        bad_inventory_snapshot = BadInventorySnapshot()
224
        bad_inventory_snapshot.item_id = itemId
225
        bad_inventory_snapshot.warehouse_id = warehouseId
226
        bad_inventory_snapshot.availability = 0
227
    # added the difference in the current inventory    
228
    bad_inventory_snapshot.availability += quantity
229
    session.commit()
230
    if bad_inventory_snapshot.availability < 0:
231
        item = __get_item_from_master(itemId)
232
        __send_alert_for_negative_availability(item, bad_inventory_snapshot.availability, get_Warehouse(warehouseId))
233
 
234
def get_item_inventory_by_item_id(item_id):
235
    return CurrentInventorySnapshot.query.filter_by(item_id=item_id).all()
236
 
237
def retire_warehouse(warehouse_id):
238
    if not warehouse_id:
239
        raise InventoryServiceException(101, "Bad warehouse id")
240
    warehouse = get_Warehouse(warehouse_id)
241
    if not warehouse:
242
        raise InventoryServiceException(108, "warehouse id not present")
243
    warehouse.status = 0;
244
    session.commit()
245
 
246
def get_item_availability_for_warehouse(warehouse_id, item_id):
247
    if not warehouse_id:
248
        raise InventoryServiceException(101, "bad warehouse_id")
249
    if not item_id:
250
        raise InventoryServiceException(101, "bad item_id")
251
 
252
    warehouse = get_Warehouse(warehouse_id)
253
    if not warehouse:
254
        raise InventoryServiceException(108, "warehouse does not exist")
255
 
256
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id)
257
    query = query.filter_by(item_id = item_id)
258
    try:
259
        current_inventory_snapshot = query.one()
260
        return current_inventory_snapshot.availability - current_inventory_snapshot.reserved
261
    except:
262
        return 0
263
 
6484 amar.kumar 264
def get_item_availability_for_our_warehouses(item_ids):
265
    warehouses = Warehouse.query.filter_by(warehouseType = 'OURS', inventoryType = 'GOOD').all()
266
    warehouse_ids = []
267
    for warehouse in warehouses :
268
        warehouse_ids.append(warehouse.id)
269
 
270
    availability_map = dict()
271
 
272
    try :
273
        for item_id in item_ids :
274
            total_availability = 0
275
            for current_inventory_snapshot in CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).filter_by(item_id = item_id).all():
276
                total_availability += current_inventory_snapshot.availability
277
            if total_availability >0:
278
                availability_map[item_id] = total_availability
279
    except Exception as e:
280
        print e
281
        raise PurchaseServiceException(101, 'Exception while fetching availability of items in our warehouses')
282
 
283
    return availability_map
284
 
5944 mandeep.dh 285
'''
286
This method returns quantity of a particular item across all warehouses whose ids is provided
287
if warehouse_ids is null it checks for inventory in all warehouses.
288
'''
289
def __get_item_availability(item, warehouse_ids):
290
    if warehouse_ids is None:
291
        all_inventory = CurrentInventorySnapshot.query.filter_by(item = item).all()
292
        availability = 0
293
        reserved = 0
294
        for currInv in all_inventory:
295
            availability = availability + currInv.availability
296
            reserved = reserved + currInv.reserved
297
        return availability - reserved
298
    else:
299
        total_availability = 0
300
        for current_inventory_snapshot in CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).filter_by(item_id = item.id).all():
301
            total_availability += current_inventory_snapshot.availability - current_inventory_snapshot.reserved
302
        return total_availability 
303
 
304
def __get_item_reserved(item_id):
305
    all_inventory = CurrentInventorySnapshot.query.filter_by(item_id = item_id).all()
306
    reserved = 0
307
    for currInv in all_inventory:
308
        reserved = reserved + currInv.reserved
309
    return reserved
5966 rajveer 310
 
311
def __get_item_availability_at_warehouse(warehouse_id, item_id):
312
    inventory = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id).one()
313
    return inventory.availability
314
 
315
def is_order_billable(item_id, warehouse_id, source_id, order_id):
316
    reservations = CurrentReservationSnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id).order_by(CurrentReservationSnapshot.promised_shipping_timestamp).order_by(CurrentReservationSnapshot.created_timestamp).all()
317
    availability = __get_item_availability_at_warehouse(warehouse_id, item_id)
318
    for reservation in reservations:
319
        availability = availability - reservation.reserved
320
        if reservation.order_id == order_id and reservation.source_id == source_id:
321
            break
322
    if availability < 0:
323
        return False
324
    return True
5944 mandeep.dh 325
 
5966 rajveer 326
def reserve_item_in_warehouse(item_id, warehouse_id, source_id, order_id, created_timestamp, promised_shipping_timestamp, quantity):    
5944 mandeep.dh 327
    if not warehouse_id:
328
        raise InventoryServiceException(101, "bad warehouse_id")
329
 
330
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
331
    try:
332
        current_inventory_snapshot = query.one()
333
    except:
334
        current_inventory_snapshot = CurrentInventorySnapshot()
335
        current_inventory_snapshot.warehouse_id = warehouse_id
336
        current_inventory_snapshot.item_id = item_id
337
        current_inventory_snapshot.availability = 0
338
        current_inventory_snapshot.reserved = 0
339
 
340
    current_inventory_snapshot.reserved = current_inventory_snapshot.reserved + quantity
5966 rajveer 341
 
342
    reservation = CurrentReservationSnapshot()
343
    reservation.item_id = item_id
344
    reservation.warehouse_id = warehouse_id
345
    reservation.source_id = source_id
346
    reservation.order_id = order_id
5990 rajveer 347
    reservation.created_timestamp = to_py_date(created_timestamp)
348
    reservation.promised_shipping_timestamp = to_py_date(promised_shipping_timestamp)
5966 rajveer 349
    reservation.reserved = quantity
350
 
5944 mandeep.dh 351
    session.commit()
352
    #**Update item availability cache**#
5978 rajveer 353
    clear_item_availability_cache(item_id)
5944 mandeep.dh 354
    return True
355
 
5966 rajveer 356
def reduce_reservation_count(item_id, warehouse_id, source_id, order_id, quantity):
5944 mandeep.dh 357
    if not warehouse_id:
358
        raise InventoryServiceException(101, "bad warehouse_id")
359
 
360
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
361
    try:
362
        current_inventory_snapshot = query.one()
363
        current_inventory_snapshot.reserved = current_inventory_snapshot.reserved - quantity
5966 rajveer 364
 
365
        reservation = CurrentReservationSnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id, source_id = source_id, order_id = order_id).one()
366
        if reservation.reserved == quantity:
367
            reservation.delete()
368
        else:
369
            reservation.reserved -= quantity
5944 mandeep.dh 370
        session.commit()
371
        #**Update item availability cache**#
5978 rajveer 372
        clear_item_availability_cache(item_id)
5944 mandeep.dh 373
        if current_inventory_snapshot.reserved < 0:
374
            item = __get_item_from_master(item_id)
375
            __send_alert_for_negative_reserved(item, current_inventory_snapshot.reserved, get_Warehouse(warehouse_id))
376
        return True
377
    except:
378
        print "Unexpected error:", sys.exc_info()[0]
379
        return False
380
 
5978 rajveer 381
def get_item_availability_for_location(item_id, source_id):
382
    item_availability = ItemAvailabilityCache.get_by(itemId=item_id, sourceId = source_id)
5944 mandeep.dh 383
    if item_availability:
384
        return [item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice, item_availability.totalAvailability]
385
    else:
5978 rajveer 386
        __update_item_availability_cache(item_id, source_id)
387
            ##Check risky status for the source
388
        __check_risky_item(item_id, source_id)
389
        return get_item_availability_for_location(item_id, source_id)
5944 mandeep.dh 390
 
5978 rajveer 391
def clear_item_availability_cache(item_id = None):
392
    if item_id:
393
        ItemAvailabilityCache.query.filter_by(itemId = item_id).delete()
394
    else:
395
        ItemAvailabilityCache.query.delete()
5944 mandeep.dh 396
    session.commit()
397
 
5978 rajveer 398
def __update_item_availability_cache(item_id, source_id):
5944 mandeep.dh 399
    """
400
    Determines the warehouse that should be used to fulfil an order for the given item.
401
    Algorithm explained at https://sites.google.com/a/shop2020.in/virtual-w-h-and-inventory/technical-details
402
 
403
    It will be ensured that every item has either a preferred vendor specified or at least for one vendor its transfer price should be defined.
404
    This is needed to associate an item with at least one vendor so that in default case when its available no where, we know from where to procure it.
405
 
406
    if item available at any OUR-GOOD warehouse
407
        // OUR-GOOD warehouses have inventory risk; So, we empty them first! 
408
        // We can start with minimum transfer price criterion but down the line we can also bring in Inventory age 
409
        assign OUR-GOOD warehouse with minimum transfer price
410
    else
411
        if Preferred vendor is specified and marked Sticky
412
            // Always purchase from Preferred if its marked sticky
413
            assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
414
        else 
415
            if item available in a THIRDPARTY GOOD/VIRTUAL warehouse
416
                assign THIRDPARTY GOOD/VIRTUAL warehouse where item is available with minimal transfer delay followed by minimum transfer price
417
            else 
418
                // Item not available at any warehouse, OURS or THIRDPARTY
419
                If Preferred vendor is specified
420
                    assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
421
                else
422
                    assign THIRDPARTY GOOD/VIRTUAL warehouse with minimum transfer price
423
 
424
    Returns an ordered list of size 4 with following elements in the given order:
425
    1. Logistics location of the warehouse which was finally picked up to ship the order.
426
    2. Expected delay added by the category manager.
427
    3. Id of the warehouse which was finally picked up.
428
 
429
    Parameters:
430
     - itemId
431
    """
5978 rajveer 432
    item = __get_item_from_source(item_id, source_id)
5944 mandeep.dh 433
    item_pricing = {}
434
    for vendorItemPricing in VendorItemPricing.query.filter_by(item_id=item_id).all():
435
        item_pricing[vendorItemPricing.vendor_id] = vendorItemPricing
436
 
6510 rajveer 437
    ignoredWhs = get_ignored_warehouses(item_id)
438
 
5944 mandeep.dh 439
    warehouses = {}
440
    ourGoodWarehouses = {}
441
    thirdpartyWarehouses = {}
442
    preferredThirdpartyWarehouses = {}
443
    for warehouse in Warehouse.query.all():
6510 rajveer 444
        if warehouse.id in ignoredWhs:
445
            continue
5944 mandeep.dh 446
        if (warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.BAD]):
447
            continue
448
        warehouses[warehouse.id] = warehouse
449
        if warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.OURS]:
450
            if warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
451
                ourGoodWarehouses[warehouse.id] = warehouse
452
        else:
453
            thirdpartyWarehouses[warehouse.id] = warehouse
454
            if item.preferredVendor == warehouse.vendor_id and warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
455
                preferredThirdpartyWarehouses[warehouse.id] = warehouse
456
 
457
    warehouse_retid = -1
458
    total_availability = 0
459
 
460
    [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(ourGoodWarehouses, item_id, item_pricing, False)
461
    if warehouse_retid == -1:
462
        if item.preferredVendor and item.isWarehousePreferenceSticky:
463
            [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(preferredThirdpartyWarehouses, item_id, item_pricing)
464
            if warehouse_retid == -1:
465
                warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
466
        else:
467
            [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(thirdpartyWarehouses, item_id, item_pricing)
468
            if warehouse_retid == -1:
469
                if item.preferredVendor:
470
                    warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
471
                else:
472
                    [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(thirdpartyWarehouses, item_id, item_pricing, True)
473
 
474
    warehouse = warehouses[warehouse_retid]
475
    billingWarehouseId = warehouse.billingWarehouseId
476
 
477
    # Fetching billing warehouse of a Good billable warehouse corresponding to the virtual one
478
    if not warehouse.billingWarehouseId:
479
        for w in Warehouse.query.filter_by(vendor_id = warehouse.vendor_id, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]).all():
480
            if w.billingWarehouseId:
481
                billingWarehouseId = w.billingWarehouseId
482
                break
483
 
484
    expectedDelay = item.expectedDelay 
485
    if expectedDelay is None:
486
        print 'expectedDelay field for this item was Null. Resetting it to 0'
487
        expectedDelay = 0
488
    else:
489
        expectedDelay = int(item.expectedDelay)
490
 
491
    if total_availability <= 0:
5978 rajveer 492
        expectedDelay = expectedDelay + __get_expected_procurement_delay(item.id, item.preferredVendor)
493
        expectedDelay = expectedDelay + __get_vendor_holiday_delay(item.preferredVendor, expectedDelay)
5944 mandeep.dh 494
    else:
495
        if warehouse.transferDelayInHours:
496
            expectedDelay = expectedDelay + warehouse.transferDelayInHours / 24
497
 
5963 mandeep.dh 498
    total_availability = 0
499
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
500
        total_availability += entry.availability - entry.reserved
501
 
5978 rajveer 502
    item_availability_cache = ItemAvailabilityCache.get_by(itemId=item_id, sourceId=source_id)
5944 mandeep.dh 503
    if item_availability_cache is None:
504
        item_availability_cache = ItemAvailabilityCache()
505
        item_availability_cache.itemId = item_id
5978 rajveer 506
        item_availability_cache.sourceId = source_id
5944 mandeep.dh 507
    item_availability_cache.warehouseId = int(warehouse_retid)
508
    item_availability_cache.expectedDelay = expectedDelay
509
    item_availability_cache.billingWarehouseId = billingWarehouseId
510
    item_availability_cache.sellingPrice = item.sellingPrice
511
    item_availability_cache.totalAvailability = total_availability
512
    session.commit()
513
 
514
def __get_warehouse_with_min_transfer_price(warehouses, item_id, item_pricing, ignoreAvailability):
515
    warehouse_retid = -1
516
    minTransferPrice = None
517
    total_availability = 0
6013 amar.kumar 518
    availabilityForBillingWarehouses = {}
519
    warehousesAvailability = {}
520
    availability = 0
521
    billing_warehouse_retid = None
5944 mandeep.dh 522
 
523
    if not ignoreAvailability:
524
        for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
6013 amar.kumar 525
            #if entry.availability > entry.reserved:
526
            warehousesAvailability[entry.warehouse_id] = entry
5944 mandeep.dh 527
 
528
    for warehouse in warehouses.values():
529
        if not ignoreAvailability:
6013 amar.kumar 530
            #TODO Mistake no entry for this warehouse.id in warehouseswithAvailab
531
            if warehouse.id not in warehousesAvailability:
532
                continue
533
            entry = warehousesAvailability[warehouse.id]
534
            if warehouse.billingWarehouseId in availabilityForBillingWarehouses:
535
                if warehouse.billingWarehouseId is not None or warehouse.billingWarehouseId != 0: 
536
                    availabilityForBillingWarehouses[warehouse.billingWarehouseId] = availabilityForBillingWarehouses[warehouse.billingWarehouseId] + entry.availability - entry.reserved  
5944 mandeep.dh 537
            else:
6013 amar.kumar 538
                if warehouse.billingWarehouseId is not None or warehouse.billingWarehouseId != 0: 
539
                    availabilityForBillingWarehouses[warehouse.billingWarehouseId] = entry.availability - entry.reserved
540
            if entry.availability <= entry.reserved:
5944 mandeep.dh 541
                continue
6013 amar.kumar 542
            total_availability += entry.availability - entry.reserved
5944 mandeep.dh 543
 
544
        # Missing transfer price cases should not impact warehouse assignment
545
        transferPrice = None
546
        if item_pricing.has_key(warehouse.vendor_id):
547
            transferPrice = item_pricing[warehouse.vendor_id].transfer_price
548
        if minTransferPrice is None or (transferPrice and minTransferPrice > transferPrice):
549
            warehouse_retid = warehouse.id
6013 amar.kumar 550
            billing_warehouse_retid = warehouse.billingWarehouseId
5944 mandeep.dh 551
            minTransferPrice = transferPrice
6013 amar.kumar 552
 
553
 
554
    if billing_warehouse_retid in availabilityForBillingWarehouses: 
555
        availability = availabilityForBillingWarehouses[billing_warehouse_retid]
556
    else:
557
        availability = total_availability
558
 
559
    return [warehouse_retid, availability]
5944 mandeep.dh 560
 
561
def __get_warehouse_with_min_transfer_delay(warehouses, item_id, item_pricing):
562
    minTransferDelay = None
563
    minTransferDelayWarehouses = {}
564
    total_availability = 0
565
 
566
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
567
        if warehouses.has_key(entry.warehouse_id):
568
            warehouse = warehouses[entry.warehouse_id]
6013 amar.kumar 569
            #if entry.availability > entry.reserved:
570
            total_availability += entry.availability - entry.reserved
571
            transferDelay = warehouse.transferDelayInHours
572
            if minTransferDelay is None or minTransferDelay >= transferDelay:
573
                if minTransferDelay != transferDelay:
574
                    minTransferDelayWarehouses = {}
575
                minTransferDelayWarehouses[warehouse.id] = warehouse
576
                minTransferDelay = transferDelay
5944 mandeep.dh 577
 
578
    return [__get_warehouse_with_min_transfer_price(minTransferDelayWarehouses, item_id, item_pricing, False)[0], total_availability]
579
 
580
def __get_warehouse_with_max_availability(warehouse_ids, item_id):
581
    warehouse_retid = -1
582
    max_availability = 0
583
    total_availability = 0
584
 
585
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
586
        if entry.warehouse_id in warehouse_ids:
587
            availability = entry.availability - entry.reserved
588
            if availability > max_availability:
589
                warehouse_retid = entry.warehouse_id
590
                max_availability = availability
591
            total_availability += availability
592
 
593
    return [warehouse_retid, total_availability]
594
 
5978 rajveer 595
def __get_expected_procurement_delay(item_id, preferredVendor):
5944 mandeep.dh 596
    procurementDelay = 2
597
    try:
5978 rajveer 598
        if preferredVendor:
599
            delays = VendorItemProcurementDelay.query.filter_by(vendor_id = preferredVendor, item_id = item_id).all()
5944 mandeep.dh 600
        else:
5978 rajveer 601
            delays = VendorItemProcurementDelay.query.filter_by(item_id = item_id).all()
5944 mandeep.dh 602
 
603
        procurementDelay= min([delay.procurementDelay for delay in delays])
604
    except Exception as e:
605
        print e
606
    return procurementDelay
607
 
5978 rajveer 608
def __get_vendor_holiday_delay(preferredVendor, expectedDelay):
5944 mandeep.dh 609
    holidayDelay = 0
610
    try:
5978 rajveer 611
        if preferredVendor:
612
            holidays = VendorHolidays.query.filter_by(vendor_id = preferredVendor).all()
5944 mandeep.dh 613
            currentDate = datetime.date.today()
614
            expectedDate = currentDate + datetime.timedelta(days = expectedDelay)
615
            for holiday in holidays:
616
                if holiday.holidayType == HolidayType.WEEKLY and holiday.holidayValue != calendar.SUNDAY:
617
                    if currentDate.weekday() > holiday.holidayValue:
618
                        holidayDate = currentDate + datetime.timedelta(days=holiday.holidayValue-currentDate.weekday(), weeks=1)
619
                    else:
620
                        holidayDate = currentDate + datetime.timedelta(days=holiday.holidayValue-currentDate.weekday())
621
                    if holidayDate >=  currentDate and holidayDate <= expectedDate:
622
                        holidayDelay = holidayDelay + 1
623
                elif holiday.holidayType == HolidayType.MONTHLY:
624
                    holidayDate = datetime.date(currentDate.year, currentDate.month, holiday.holidayValue)
625
                    if holidayDate >=  currentDate and holidayDate <= expectedDate:
626
                        holidayDelay = holidayDelay + 1    
627
                elif holiday.holidayType == HolidayType.SPECIFIC:
628
                    holidayValue = str(holiday.holidayValue)
629
                    holidayDate = datetime.date(int(holidayValue[:4]), int(holidayValue[4:6]), int(holidayValue[6:8]))
630
                    if holidayDate >=  currentDate and holidayDate <= expectedDate:
631
                        holidayDelay = holidayDelay + 1                
632
    except Exception as e:
633
        print e
634
    return holidayDelay 
635
 
636
def get_item_pricing(item_id, vendorId):
637
    '''
638
    if vendor id is -1 then we calculate an average transfer price to be populated
639
    at the time of order creation. This will be later updated with actual transfer price
640
    at the time of billing.
641
    '''
642
    if(vendorId == -1):
643
        total = 0
644
        try:
645
            item_pricings = []
646
            item = __get_item_from_master(item_id)
647
            if item.preferredVendor is not None:
648
                item_pricing = VendorItemPricing.query.filter_by(item_id=item_id, vendor_id=item.preferredVendor).first()
649
                if item_pricing:
650
                    item_pricings.append(item_pricing)                    
651
            else :
652
                item_pricings = VendorItemPricing.query.filter_by(item_id=item_id).all()
653
            if item_pricings:
654
                for item_pricing in item_pricings:
655
                    total += item_pricing.transfer_price
656
                avg = total / len(item_pricings)
657
                item_pricing.transfer_price = avg
658
            else:
659
                item_pricing = VendorItemPricing()
660
                item_pricing.transfer_price = item.sellingPrice
661
                vendor = Vendor()
662
                vendor.id = vendorId
663
                item_pricing.vendor = vendor
664
                item_pricing.item_id = item_id
665
 
666
            return item_pricing
667
        except:
668
            raise InventoryServiceException(101, "Item pricing not found ")
669
    vendor = Vendor.get_by(id=vendorId)    
670
    try:
671
        item_pricing = VendorItemPricing.query.filter_by(vendor=vendor, item_id=item_id).one()
672
        return item_pricing
673
    except MultipleResultsFound:
674
        raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
675
    except NoResultFound:
676
        raise InventoryServiceException(111, "Missing pricing information for Vendor: " + vendor.name + " and Item: " + str(item_id))
677
 
678
def get_all_item_pricing(item_id):
679
    item_pricing = VendorItemPricing.query.filter_by(item_id=item_id).all()
680
    return item_pricing
681
 
682
def get_item_mappings(item_id):
683
    item_mappings = VendorItemMapping.query.filter_by(item_id=item_id).all()
684
    return item_mappings
685
 
686
def add_vendor_pricing(vendorItemPricing):
687
    if not vendorItemPricing:
688
        raise InventoryServiceException(108, "Bad vendorItemPricing in request")
689
    vendorId = vendorItemPricing.vendorId
690
    itemId = vendorItemPricing.itemId
691
 
692
    try:
693
        vendor = Vendor.query.filter_by(id=vendorId).one()
694
    except:
695
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
696
 
697
    try:
698
        item = __get_item_from_master(itemId)
699
    except:
700
        raise InventoryServiceException(101, "Item not found for itemId " + str(itemId))
701
 
702
    validate_vendor_prices(item, vendorItemPricing)
703
 
704
    try:
705
        ds_vendorItemPricing = VendorItemPricing.query.filter(and_(VendorItemPricing.vendor==vendor, VendorItemPricing.item_id==itemId)).one()
706
    except:
707
        ds_vendorItemPricing = VendorItemPricing()
708
        ds_vendorItemPricing.vendor = vendor
709
        ds_vendorItemPricing.item_id = itemId
710
 
711
    subject = ""
712
    message = ""
713
    if vendorItemPricing.mop:
714
        ds_vendorItemPricing.mop = vendorItemPricing.mop
715
    if vendorItemPricing.dealerPrice:
716
        ds_vendorItemPricing.dealerPrice = vendorItemPricing.dealerPrice
717
    if vendorItemPricing.transferPrice:
718
        if vendorItemPricing.transferPrice != ds_vendorItemPricing.transfer_price:
6014 amit.gupta 719
            message = "Transfer price for Item '{0}' \nand Vendor:{1} is changed from {2} to {3}.".format(itemId, vendor.name, ds_vendorItemPricing.transfer_price, vendorItemPricing.transferPrice)
5944 mandeep.dh 720
            subject = "Alert:Change in Transfer Price"
721
        ds_vendorItemPricing.transfer_price = vendorItemPricing.transferPrice
722
 
723
    session.commit()
724
    if subject:
725
        __send_mail(subject, message)
726
    return
727
 
728
def add_vendor_item_mapping(key, vendorItemMapping):
729
    if not vendorItemMapping:
730
        raise InventoryServiceException(108, "Bad vendorItemMapping in request")
731
    vendorId = vendorItemMapping.vendorId
732
    itemId = vendorItemMapping.itemId
733
 
734
    try:
735
        vendor = Vendor.query.filter_by(id=vendorId).one()
736
    except:
737
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
738
 
739
    try:
740
        ds_vendorItemMapping = VendorItemMapping.query.filter(and_(VendorItemMapping.vendor==vendor, VendorItemMapping.item_id==itemId, VendorItemMapping.item_key==key)).one()
741
    except:
742
        ds_vendorItemMapping = VendorItemMapping()
743
        ds_vendorItemMapping.vendor = vendor
744
        ds_vendorItemMapping.item_id = itemId
745
    ds_vendorItemMapping.item_key = vendorItemMapping.itemKey
746
 
747
    session.commit()
748
 
749
    # Marking the missed inventory as not ignored as the catalog dashboard user has updated their key
750
    for missedInventoryUpdate in MissedInventoryUpdate.query.filter_by(itemKey = vendorItemMapping.itemKey).all():
751
        missedInventoryUpdate.isIgnored = 0
752
    session.commit()
753
 
754
    return
755
 
756
def validate_vendor_prices(item, vendorPrices):
757
    if item.mrp != None and item.mrp != "" and vendorPrices.mop != "" and item.mrp <  vendorPrices.mop:
758
        print "[BAD MRP and MOP:] for {0} {1} {2} {3}. MRP={4}. MOP={5}, Vendor={6}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(item.mrp), str(vendorPrices.mop), str(vendorPrices.vendorId))
759
        raise InventoryServiceException(101, "[BAD MRP and MOP:] for {0} {1} {2} {3}. MRP={4}. MOP={5}, Vendor={6}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(item.mrp), str(vendorPrices.mop), str(vendorPrices.vendorId)))
760
    if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
761
        print "[BAD MOP and TP:] for {0} {1} {2} {3}. TP={4}. MOP={5}, Vendor={6}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(vendorPrices.transferPrice), str(vendorPrices.mop), str(vendorPrices.vendorId))
762
        raise InventoryServiceException(101, "[BAD MOP and TP:] for {0} {1} {2} {3}. TP={4}. MOP={5}, Vendor={6}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(vendorPrices.transferPrice), str(vendorPrices.mop), str(vendorPrices.vendorId)))
763
    return
764
 
765
def get_all_vendors():
766
    return Vendor.query.all()
767
 
768
def get_pending_orders_inventory(vendor_id=1):
769
    """
770
    Returns a list of inventory stock for items for which there are pending orders.
771
    """
772
 
773
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter_by(vendor_id = vendor_id)]
774
    pending_items_inventory = []
775
    if warehouse_ids:
776
        pending_items_inventory = session.query(CurrentInventorySnapshot.item_id, func.sum(CurrentInventorySnapshot.availability), func.sum(CurrentInventorySnapshot.reserved)).filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).group_by(CurrentInventorySnapshot.item_id).having(func.sum(CurrentInventorySnapshot.reserved) > 0).all()
777
    return pending_items_inventory
778
 
779
def close_session():
780
    if session.is_active:
781
        print "session is active. closing it."
782
        session.close()
783
 
784
def is_alive():
785
    try:
786
        session.query(Vendor.id).limit(1).one()
787
        return True
788
    except:
789
        return False
790
 
791
def add_vendor(vendor):
792
    if not vendor:
793
        raise InventoryServiceException(108, "Bad vendor")
794
    if get_vendor(vendor.id):
795
        #vendor is already present.
796
        raise InventoryServiceException(101, "Vendor already present")
797
 
798
    ds_vendor = Vendor()
799
    ds_vendor.id = vendor.id
800
    ds_vendor.name = vendor.name
801
    session.commit()
802
    return ds_vendor.id
803
 
804
def add_warehouse_vendor_mapping(warehouse_id, VendorId):
805
    return True
806
 
807
def mark_missed_inventory_updates_as_processed(itemKey, warehouseId):
808
    MissedInventoryUpdate.query.filter_by(itemKey = itemKey, warehouseId = warehouseId).delete()
809
    session.commit()
810
 
811
def get_item_keys_to_be_processed(warehouseId):
812
    return [i.itemKey for i in MissedInventoryUpdate.query.filter_by(warehouseId = warehouseId, isIgnored = 0)]
813
 
814
def reset_availability(itemKey, vendorId, quantity, warehouseId):
815
    vendorItemMapping = VendorItemMapping.get_by(vendor_id = vendorId, item_key = itemKey)
816
    if vendorItemMapping:
817
        itemId = vendorItemMapping.item_id
818
 
819
        if skippedItems.has_key(warehouseId) and itemId in skippedItems[warehouseId]:
820
            quantity = 0
821
 
822
        currentInventorySnapshot = CurrentInventorySnapshot.get_by(item_id = itemId, warehouse_id = warehouseId)
823
        if currentInventorySnapshot:
824
            currentInventorySnapshot.availability = quantity
5978 rajveer 825
            clear_item_availability_cache(itemId) 
5944 mandeep.dh 826
        else:
827
            add_inventory(itemId, warehouseId, quantity)
828
 
829
    else:
830
        raise InventoryServiceException(101, 'VendorMapping not found for: ' + itemKey)
831
    session.commit()
832
 
833
def reset_availability_for_warehouse(warehouseId):
834
    for currentInventorySnapshot in CurrentInventorySnapshot.query.filter_by(warehouse_id=warehouseId).all():
835
        currentInventorySnapshot.availability = 0
5978 rajveer 836
        clear_item_availability_cache(currentInventorySnapshot.item_id) 
5944 mandeep.dh 837
    session.commit()
838
 
6467 amar.kumar 839
def get_our_warehouse_id_for_vendor(vendor_id):
840
    try:
841
        warehouse = Warehouse.query.filter_by(vendor_id = vendor_id, warehouseType = 'OURS', inventoryType = 'GOOD').first()
842
        return warehouse.id
843
    except Exception as e:
844
        print e;
845
        raise InventoryServiceException(101, 'No our warehouse found for vendorId: ' + vendor_id)
5944 mandeep.dh 846
 
847
def __send_mail(subject, message):
848
    try:
6029 rajveer 849
        thread = threading.Thread(target=partial(mail, mail_user, mail_password, to_addresses, subject, message))
5944 mandeep.dh 850
        thread.start()
851
    except Exception as ex:
852
        print ex    
853
 
854
def get_shipping_locations():
855
    shippingLocationIds = {}
856
    warehouses = Warehouse.query.all()
857
    for warehouse in warehouses:
858
        if warehouse.shippingWarehouseId:
859
            shippingLocationIds[warehouse.shippingWarehouseId] = 1
860
 
861
    shippingLocations = []
862
    for shippingLocationId in shippingLocationIds:
863
        shippingLocations.append(get_Warehouse(shippingLocationId))
864
 
865
    return shippingLocations
866
 
867
def get_inventory_snapshot(warehouseId):
868
    query = CurrentInventorySnapshot.query
869
 
870
    if warehouseId:
871
        query = query.filter_by(warehouse_id = warehouseId)
872
 
873
    itemInventoryMap = {}
874
    for row in query.all():
875
        if not itemInventoryMap.has_key(row.item_id):
876
            itemInventoryMap[row.item_id] = []
877
 
878
        itemInventoryMap[row.item_id].append(row)
879
 
880
    return itemInventoryMap
881
 
882
def update_vendor_string(warehouseId, vendorString):
883
    warehouse = get_Warehouse(warehouseId)
884
    warehouse.vendorString = vendorString
885
    session.commit()
886
 
887
def __get_item_from_master(item_id):
888
    client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
5978 rajveer 889
    return client.getItem(item_id)
890
 
891
def __check_risky_item(item_id, source_id):
892
    ## We should get the list of strings which will identify to the catalog servers
893
    if source_id == 1:
894
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
895
        client.validateRiskyStatus(item_id)
896
    if source_id == 2:
897
        client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
898
        client.validateRiskyStatus(item_id)
899
 
900
def __get_item_from_source(item_id, source_id):
901
    if source_id == 1:
902
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
903
        return client.getItem(item_id)
904
    if source_id == 2:
905
        client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
6531 vikram.rag 906
        return client.getItem(item_id)
907
 
908
def get_monitored_warehouses_for_vendors(vendorIds):
909
    w = []
910
    for wh in Warehouse.query.filter_by(isAvailabilityMonitored = 1).all():
911
        if wh.vendor.id in (vendorIds):
912
            w.append(to_t_warehouse(wh).id)
913
    return w
914
def get_ignored_warehouseids_and_itemids():
915
    iw = []
916
    for i in IgnoredInventoryUpdateItems.query.all():
917
        iw.append(to_t_itemidwarehouseid(i)) 
918
    return iw
919
def insert_item_to_ignore_inventory_update_list(item_id,warehouse_id):
920
    try:
921
        ds_warehouse=IgnoredInventoryUpdateItems()
922
        ds_warehouse.item_id=item_id
923
        ds_warehouse.warehouse_id=warehouse_id
924
        session.commit()
925
        return True
926
    except:
927
        return False       
928
def delete_item_from_ignore_inventory_update_list(item_id,warehouse_id):
929
    try:
930
        session.query(IgnoredInventoryUpdateItems).filter_by(item_id=item_id,warehouse_id=warehouse_id).delete()
931
        session.commit()
932
        return True
933
    except:
934
        return False           
935
 
936
def get_all_ignored_inventoryupdate_items_count():
937
    return  session.query(func.count(distinct(IgnoredInventoryUpdateItems.item_id))).scalar()
938
 
939
def get_ignored_inventoryupdate_itemids(offset=0,limit=None):
940
    itemIds = session.query(distinct(IgnoredInventoryUpdateItems.item_id))
941
    '''if limit is not None:
942
        itemIds = itemIds.limit(limit)'''
943
    print itemIds.all()
944
    return [id for (id, ) in itemIds.all()]
945