Subversion Repositories SmartDukaan

Rev

Rev 25481 | Rev 27448 | 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
19413 amit.gupta 9
from shop2020.clients.LogisticsClient import LogisticsClient
5944 mandeep.dh 10
from shop2020.clients.TransactionClient import TransactionClient
11
from shop2020.model.v1.inventory.impl import DataService
6531 vikram.rag 12
from shop2020.model.v1.inventory.impl.Convertors import to_t_warehouse, \
19413 amit.gupta 13
    to_t_itemidwarehouseid, to_t_state, to_t_item_location_availability
5944 mandeep.dh 14
from shop2020.model.v1.inventory.impl.DataService import Warehouse, \
15
    ItemInventoryHistory, CurrentInventorySnapshot, VendorItemPricing, \
16
    VendorItemMapping, Vendor, MissedInventoryUpdate, BadInventorySnapshot, \
19413 amit.gupta 17
    VendorHolidays, ItemAvailabilityCache, CurrentReservationSnapshot, \
18
    IgnoredInventoryUpdateItems, ItemStockPurchaseParams, OOSStatus, \
19
    AmazonInventorySnapshot, StateMaster, HoldInventoryDetail, \
20
    AmazonFbaInventorySnapshot, SnapdealInventorySnapshot, FlipkartInventorySnapshot, \
21
    SnapdealStockAtEOD, FlipkartStockAtEOD, StockWeightedNlcInfo, \
22
    ItemLocationAvailabilityCache
23446 amit.gupta 23
from shop2020.thriftpy.logistics.ttypes import LocationInfo, PickUpType
6531 vikram.rag 24
from shop2020.thriftpy.model.v1.inventory.ttypes import \
23446 amit.gupta 25
    InventoryServiceException, HolidayType, InventoryType, WarehouseType, \
19413 amit.gupta 26
    ItemLocationAvailability, ItemPincodeAvailability
23316 amit.gupta 27
from shop2020.thriftpy.model.v1.order.ttypes import AlertType, TransactionStatus
6531 vikram.rag 28
from shop2020.thriftpy.purchase.ttypes import PurchaseServiceException
5944 mandeep.dh 29
from shop2020.utils import EmailAttachmentSender
30
from shop2020.utils.EmailAttachmentSender import mail
6821 amar.kumar 31
from shop2020.utils.Utils import to_py_date, to_java_date
23446 amit.gupta 32
from shop2020.utils.caching.SimpleCaching import memoized
5944 mandeep.dh 33
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
7410 amar.kumar 34
from sqlalchemy.sql import or_
12363 kshitij.so 35
from sqlalchemy.sql.expression import and_, func, distinct, desc
6531 vikram.rag 36
from sqlalchemy.sql.functions import count
5944 mandeep.dh 37
import calendar
38
import datetime
23446 amit.gupta 39
import json
19413 amit.gupta 40
import math
5944 mandeep.dh 41
import sys
42
import threading
43
 
10687 rajveer 44
to_addresses = ["khushal.bhatia@shop2020.in", "chaitnaya.vats@shop2020.in", "chandan.kumar@shop2020.in",'manoj.kumar@shop2020.in']
6029 rajveer 45
mail_user = "cnc.center@shop2020.in"
46
mail_password = "5h0p2o2o"
5944 mandeep.dh 47
skippedItems = { 175 : [27, 2160, 2175, 2163, 2158, 7128, 26, 2154],
48
                 193 : [5839] }
49
 
19413 amit.gupta 50
pincodePricingServiceabilityMap = {}
51
warehouseMap = {}
52
 
6821 amar.kumar 53
OOS_CALCULATION_TIME = 23
22991 amit.gupta 54
 
55
#right now these warehouse ids are ignored.
23029 amit.gupta 56
#physicalWarehouseIdsForFofo = [7678, 7681]
57
physicalWarehouseIdsForFofo = []
25468 amit.gupta 58
vendorWarehouseIdsForFofo = []
6498 vikram.rag 59
 
19413 amit.gupta 60
last_date = datetime.date.today()
61
adjusted_dates={}
62
 
23446 amit.gupta 63
partnerMap = {}
23442 amit.gupta 64
 
23446 amit.gupta 65
 
23937 amit.gupta 66
default_virtual_vendor = 290 
23446 amit.gupta 67
virtualVendorWarehouses = {}
23475 amit.gupta 68
billingVendorWarehouses = {}
23446 amit.gupta 69
 
5944 mandeep.dh 70
def initialize(dbname='inventory', db_hostname="localhost"):
71
    DataService.initialize(dbname, db_hostname)
19413 amit.gupta 72
    __populateWarehouseMap()
23446 amit.gupta 73
 
74
@memoized(3600)   
19413 amit.gupta 75
def __populateWarehouseMap():
76
    warehouses = Warehouse.query.filter(Warehouse.warehouseType.in_(['OURS', 'THIRD_PARTY'])).filter(Warehouse.inventoryType == 'GOOD').all()
77
    for warehouse in warehouses:
78
        warehouseMap[warehouse.id] = warehouse
23503 amit.gupta 79
        print warehouse.id, warehouse.vendor
23483 amit.gupta 80
        if warehouse.vendor.id==default_virtual_vendor and warehouse.warehouseType == 'THIRD_PARTY':
23606 amit.gupta 81
            virtualVendorWarehouses[warehouse.state_id] = warehouse 
23503 amit.gupta 82
        if warehouse.vendor.id==default_virtual_vendor and warehouse.warehouseType == 'OURS':
83
            billingVendorWarehouses[warehouse.state_id] = warehouse.billingWarehouseId
25468 amit.gupta 84
 
85
        if warehouse.billingWarehouseId in physicalWarehouseIdsForFofo:
86
            vendorWarehouseIdsForFofo.append(warehouse.id)
25481 amit.gupta 87
        warehouse.expunge()
19413 amit.gupta 88
 
24000 amit.gupta 89
    print "billingVendorWarehouses", billingVendorWarehouses
90
    print "virtualVendorWarehouses", virtualVendorWarehouses 
19413 amit.gupta 91
 
5944 mandeep.dh 92
def get_Warehouse(warehouse_id):
93
    return Warehouse.get_by(id=warehouse_id)
94
 
95
def get_vendor(vendorId):
96
    return Vendor.get_by(id=vendorId)
97
 
7410 amar.kumar 98
def get_state(stateId):
99
    return StateMaster.get_by(id=stateId)
100
 
5944 mandeep.dh 101
def get_all_warehouses_by_status(status):
102
    return Warehouse.query.all()
103
 
104
def get_all_items_for_warehouse(warehouse_id):
105
    warehouse = get_Warehouse(warehouse_id)
106
    if not warehouse:
107
        raise InventoryServiceException(108, "bad warehouse")
108
    return warehouse.all_items
109
 
110
def add_warehouse(warehouse):
111
    if not warehouse:
112
        raise InventoryServiceException(108, "Bad warehouse")
113
    if get_Warehouse(warehouse.id):
114
        #warehouse is already present.
115
        raise InventoryServiceException(101, "Warehouse already present")
116
 
117
    ds_warehouse = Warehouse()
118
    ds_warehouse.location = warehouse.location
119
    ds_warehouse.status = 3
120
    ds_warehouse.addedOn = datetime.datetime.now()
121
    ds_warehouse.lastCheckedOn = datetime.datetime.now()
122
    ds_warehouse.tinNumber = warehouse.tinNumber
123
    ds_warehouse.pincode = warehouse.pincode
124
    ds_warehouse.billingType = warehouse.billingType
125
    ds_warehouse.billingWarehouseId = warehouse.billingWarehouseId
126
    ds_warehouse.displayName = warehouse.displayName
127
    ds_warehouse.inventoryType = InventoryType._VALUES_TO_NAMES[warehouse.inventoryType]
128
    ds_warehouse.isAvailabilityMonitored = warehouse.isAvailabilityMonitored
129
    ds_warehouse.logisticsLocation = warehouse.logisticsLocation
130
    ds_warehouse.shippingWarehouseId = warehouse.shippingWarehouseId
131
    ds_warehouse.transferDelayInHours = warehouse.transferDelayInHours
132
    ds_warehouse.vendor = get_vendor(warehouse.vendor.id)
7410 amar.kumar 133
    ds_warehouse.state = get_state(warehouse.stateId)
5944 mandeep.dh 134
    ds_warehouse.warehouseType = WarehouseType._VALUES_TO_NAMES[warehouse.warehouseType]    
135
    if warehouse.vendorString:
136
        ds_warehouse.vendorString = warehouse.vendorString
137
    session.commit()
138
    return ds_warehouse.id
139
 
6498 vikram.rag 140
def get_ignored_items(warehouse_id): 
6531 vikram.rag 141
    Ignored_inventory_items = IgnoredInventoryUpdateItems.query.filter_by(warehouse_id=warehouse_id).all()
6498 vikram.rag 142
    negativeItems = []
143
    for Ignored_inventory_item in Ignored_inventory_items:
144
        try:
145
            item_id = Ignored_inventory_item.item_id
146
            negativeItems.append(item_id)
147
        except:
148
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
149
    return negativeItems
150
 
22630 amit.gupta 151
def get_ignored_warehouses(item_id):
152
    warehouses = []
153
    #No item availability cache for Hotspot Specific Store
154
    #No virtual is allowed
6539 amit.gupta 155
    Ignored_inventory_items = IgnoredInventoryUpdateItems.query.filter_by(item_id=item_id).all()
6510 rajveer 156
    for Ignored_inventory_item in Ignored_inventory_items:
157
        warehouses.append(Ignored_inventory_item.warehouse_id)
25459 amit.gupta 158
    return warehouses
6510 rajveer 159
 
5944 mandeep.dh 160
def update_inventory_history(warehouse_id, timestamp, availability):
161
    warehouse = get_Warehouse(warehouse_id)
162
    if not warehouse:
163
        raise InventoryServiceException(107, "Warehouse? Where?")
164
    vendor = warehouse.vendor
165
    time = datetime.datetime.now()
166
    for item_key, quantity in availability.iteritems():
167
        try:
168
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
5960 mandeep.dh 169
            item_id = vendor_item_mapping.item_id
5944 mandeep.dh 170
        except:
6531 vikram.rag 171
            continue  
5944 mandeep.dh 172
        try:
6510 rajveer 173
            item_inventory_history = ItemInventoryHistory()
174
            item_inventory_history.warehouse = warehouse
175
            item_inventory_history.item_id = item_id
176
            item_inventory_history.timestamp = time
177
            item_inventory_history.availability = quantity
5944 mandeep.dh 178
        except:
179
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
180
    session.commit()
181
 
182
def update_inventory(warehouse_id, timestamp, availability):
183
    warehouse = get_Warehouse(warehouse_id)
184
    if not warehouse:
185
        raise InventoryServiceException(107, "Warehouse? Where?")
6510 rajveer 186
 
5944 mandeep.dh 187
    time = datetime.datetime.now()
188
    warehouse.lastCheckedOn = time
189
    warehouse.vendorString = timestamp
190
    vendor = warehouse.vendor
191
    item_ids = []
192
    for item_key, quantity in availability.iteritems():
193
        try:
194
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
195
            item_id = vendor_item_mapping.item_id
6510 rajveer 196
            item_ids.append(item_id)
5944 mandeep.dh 197
        except:
198
            print 'Skipping update for ' + item_key + ' quantity ' + str(quantity) + ' warehouse id: ' + str(warehouse_id)
199
            __send_mail_for_missing_key(item_key, quantity, warehouse_id)
200
            continue
201
        try:
202
            current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=item_id, warehouse=warehouse)
203
            if not current_inventory_snapshot:
204
                current_inventory_snapshot = CurrentInventorySnapshot()
205
                current_inventory_snapshot.item_id = item_id
206
                current_inventory_snapshot.warehouse = warehouse
207
                current_inventory_snapshot.availability = 0
208
                current_inventory_snapshot.reserved = 0
8204 amar.kumar 209
                current_inventory_snapshot.held = 0
5944 mandeep.dh 210
            # added the difference in the current inventory    
211
            current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
212
            item = __get_item_from_master(item_id)
213
            try:
214
                if quantity > 0 and __get_item_reserved(item_id) > 0:
215
                    cl = TransactionClient().get_client()
216
                    #FIXME hardcoding for warehouse id 
217
                    cl.addAlert(AlertType.NEW_INVENTORY_ALERT, 5, "Inventory received for item " + item.brand + " " + item.modelName + " " + item.modelNumber + " " +  item.color)
218
            except:
219
                print "Not able to raise alert for incoming inventory" 
220
            if current_inventory_snapshot.availability < 0:
221
                __send_alert_for_negative_availability(item, current_inventory_snapshot.availability, warehouse)
222
        except:
223
            print "Some unforeseen error while updating inventory:", sys.exc_info()[0]
224
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
225
    session.commit()
226
 
227
    #**Update item availability cache**#
228
    for item_id in item_ids:
5978 rajveer 229
        clear_item_availability_cache(item_id)
5944 mandeep.dh 230
 
231
def __send_alert_for_negative_reserved(item, reserved, warehouse):
232
    itemName = " ".join([str(item.id), str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
10253 manish.sha 233
    EmailAttachmentSender.mail(mail_user, mail_password, 'manish.sharma@shop2020.in', 'Negative reserved: ' + str(reserved) + ' for Item Id: ' + itemName + ' warehouse id: ' + str(warehouse.id), None)
5944 mandeep.dh 234
 
235
def __send_alert_for_negative_availability(item, availability, warehouse):
236
    itemName = " ".join([str(item.id), str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
5964 amar.kumar 237
    # 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 238
 
239
def __send_mail_for_missing_key(item_key, quantity, warehouse_id):
240
    missedInventoryUpdate = MissedInventoryUpdate.get_by(itemKey = item_key, warehouseId = warehouse_id)
241
    # One email per product key mismatch
242
    if not missedInventoryUpdate:
243
        missedInventoryUpdate = MissedInventoryUpdate()
244
        missedInventoryUpdate.itemKey = item_key
245
        missedInventoryUpdate.quantity = quantity
246
        missedInventoryUpdate.isIgnored = 1
247
        missedInventoryUpdate.timestamp = datetime.datetime.now()
248
        missedInventoryUpdate.warehouseId = warehouse_id
249
        session.commit()
6232 rajveer 250
        try:
8214 amar.kumar 251
            EmailAttachmentSender.mail(mail_user, mail_password, ['chaitnaya.vats@shop2020.in', 'chandan.kumar@shop2020.in', 'khushal.bhatia@shop2020.in', 'manoj.kumar@shop2020.in'], 'Skipped inventory update for ' + item_key + ' quantity ' + str(quantity) + ' warehouse id: ' + str(warehouse_id), None)
6232 rajveer 252
        except:
253
            print "Not able to send email. No issues, we can continue with updates."
5944 mandeep.dh 254
    else:
255
        missedInventoryUpdate.quantity += quantity
256
        session.commit()
257
 
19989 kshitij.so 258
def add_inventory(itemId, warehouseId, quantity, skipAddition=False):
5944 mandeep.dh 259
    current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
260
    if not current_inventory_snapshot:
261
        current_inventory_snapshot = CurrentInventorySnapshot()
262
        current_inventory_snapshot.item_id = itemId
263
        current_inventory_snapshot.warehouse_id = warehouseId
264
        current_inventory_snapshot.availability = 0
265
        current_inventory_snapshot.reserved = 0
8204 amar.kumar 266
        current_inventory_snapshot.held = 0
19989 kshitij.so 267
    # added the difference in the current inventory
268
    if skipAddition is None or not skipAddition:    
269
        current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
270
    else:
271
        current_inventory_snapshot.availability = quantity
5944 mandeep.dh 272
    session.commit()
273
    #**Update item availability cache**#
20849 amit.gupta 274
    clear_item_availability_cache(itemId)
5944 mandeep.dh 275
    if current_inventory_snapshot.availability < 0:
276
        item = __get_item_from_master(itemId)
5978 rajveer 277
        __send_alert_for_negative_availability(item, current_inventory_snapshot.availability, get_Warehouse(warehouseId)) 
5944 mandeep.dh 278
 
279
def add_bad_inventory(itemId, warehouseId, quantity):
280
    bad_inventory_snapshot = BadInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
281
    if not bad_inventory_snapshot:
282
        bad_inventory_snapshot = BadInventorySnapshot()
283
        bad_inventory_snapshot.item_id = itemId
284
        bad_inventory_snapshot.warehouse_id = warehouseId
285
        bad_inventory_snapshot.availability = 0
286
    # added the difference in the current inventory    
287
    bad_inventory_snapshot.availability += quantity
288
    session.commit()
289
    if bad_inventory_snapshot.availability < 0:
290
        item = __get_item_from_master(itemId)
291
        __send_alert_for_negative_availability(item, bad_inventory_snapshot.availability, get_Warehouse(warehouseId))
292
 
293
def get_item_inventory_by_item_id(item_id):
294
    return CurrentInventorySnapshot.query.filter_by(item_id=item_id).all()
295
 
296
def retire_warehouse(warehouse_id):
297
    if not warehouse_id:
298
        raise InventoryServiceException(101, "Bad warehouse id")
299
    warehouse = get_Warehouse(warehouse_id)
300
    if not warehouse:
301
        raise InventoryServiceException(108, "warehouse id not present")
302
    warehouse.status = 0;
303
    session.commit()
304
 
305
def get_item_availability_for_warehouse(warehouse_id, item_id):
6545 rajveer 306
    ignore = IgnoredInventoryUpdateItems.query.filter_by(item_id=item_id).filter_by(warehouse_id = warehouse_id).all()
6544 rajveer 307
    if ignore:
308
        return 0
5944 mandeep.dh 309
 
310
    try:
6544 rajveer 311
        current_inventory_snapshot = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id).filter_by(item_id = item_id).one()
15958 amit.gupta 312
        return current_inventory_snapshot.availability - current_inventory_snapshot.reserved - current_inventory_snapshot.held
5944 mandeep.dh 313
    except:
314
        return 0
315
 
6484 amar.kumar 316
def get_item_availability_for_our_warehouses(item_ids):
7699 amar.kumar 317
    our_warehouses = Warehouse.query.filter_by(warehouseType = 'OURS', inventoryType = 'GOOD').all()
318
    our_thirdparty_warehouses = Warehouse.query.filter_by(warehouseType = 'OURS_THIRDPARTY').all()
6484 amar.kumar 319
    warehouse_ids = []
7699 amar.kumar 320
    for warehouse in our_warehouses :
6484 amar.kumar 321
        warehouse_ids.append(warehouse.id)
10170 amar.kumar 322
    #for warehouse in our_thirdparty_warehouses :
323
    #    warehouse_ids.append(warehouse.id)
7699 amar.kumar 324
 
6484 amar.kumar 325
    availability_map = dict()
326
 
327
    try :
328
        for item_id in item_ids :
329
            total_availability = 0
330
            for current_inventory_snapshot in CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).filter_by(item_id = item_id).all():
331
                total_availability += current_inventory_snapshot.availability
332
            if total_availability >0:
333
                availability_map[item_id] = total_availability
334
    except Exception as e:
335
        print e
336
        raise PurchaseServiceException(101, 'Exception while fetching availability of items in our warehouses')
337
 
338
    return availability_map
339
 
22991 amit.gupta 340
#As of now as warehouse can be managed independently we just need to return itemavailability cache for the item ids provided
22719 amit.gupta 341
def get_fofo_availability(item_ids):
342
    returnMap = {}
343
    if not item_ids:
344
        return returnMap
22991 amit.gupta 345
    for item_id in item_ids:
346
        returnMap[item_id] = get_item_availability_for_location(item_id, 1)[4]
22719 amit.gupta 347
    return returnMap
348
 
22721 amit.gupta 349
def get_fofo_fulfilment_warehouse_map(itemIds):
350
    returnMap = {}
22722 amit.gupta 351
    snapshots = CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id.in_(vendorWarehouseIdsForFofo)).filter(CurrentInventorySnapshot.item_id.in_(itemIds)).all()
22721 amit.gupta 352
    for snapshot in snapshots:
353
        availability = snapshot.availability - snapshot.reserved - snapshot.held
354
        if availability > 0:
355
            if not returnMap.has_key(snapshot.item_id):
356
                returnMap[snapshot.item_id] = to_t_warehouse(snapshot.warehouse)
357
    return returnMap 
358
 
359
 
360
 
5944 mandeep.dh 361
'''
362
This method returns quantity of a particular item across all warehouses whose ids is provided
363
if warehouse_ids is null it checks for inventory in all warehouses.
364
'''
365
def __get_item_availability(item, warehouse_ids):
366
    if warehouse_ids is None:
367
        all_inventory = CurrentInventorySnapshot.query.filter_by(item = item).all()
368
        availability = 0
369
        reserved = 0
370
        for currInv in all_inventory:
371
            availability = availability + currInv.availability
372
            reserved = reserved + currInv.reserved
373
        return availability - reserved
374
    else:
375
        total_availability = 0
376
        for current_inventory_snapshot in CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).filter_by(item_id = item.id).all():
377
            total_availability += current_inventory_snapshot.availability - current_inventory_snapshot.reserved
378
        return total_availability 
379
 
380
def __get_item_reserved(item_id):
381
    all_inventory = CurrentInventorySnapshot.query.filter_by(item_id = item_id).all()
382
    reserved = 0
383
    for currInv in all_inventory:
384
        reserved = reserved + currInv.reserved
385
    return reserved
5966 rajveer 386
 
387
def __get_item_availability_at_warehouse(warehouse_id, item_id):
388
    inventory = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id).one()
389
    return inventory.availability
390
 
391
def is_order_billable(item_id, warehouse_id, source_id, order_id):
392
    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()
393
    availability = __get_item_availability_at_warehouse(warehouse_id, item_id)
394
    for reservation in reservations:
395
        availability = availability - reservation.reserved
396
        if reservation.order_id == order_id and reservation.source_id == source_id:
397
            break
398
    if availability < 0:
399
        return False
400
    return True
5944 mandeep.dh 401
 
19989 kshitij.so 402
def reserve_item_in_warehouse(item_id, warehouse_id, source_id, order_id, created_timestamp, promised_shipping_timestamp, quantity):
403
 
5944 mandeep.dh 404
    if not warehouse_id:
405
        raise InventoryServiceException(101, "bad warehouse_id")
406
 
407
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
408
    try:
409
        current_inventory_snapshot = query.one()
410
    except:
411
        current_inventory_snapshot = CurrentInventorySnapshot()
412
        current_inventory_snapshot.warehouse_id = warehouse_id
413
        current_inventory_snapshot.item_id = item_id
414
        current_inventory_snapshot.availability = 0
415
        current_inventory_snapshot.reserved = 0
8204 amar.kumar 416
        current_inventory_snapshot.held = 0
5944 mandeep.dh 417
 
418
    current_inventory_snapshot.reserved = current_inventory_snapshot.reserved + quantity
5966 rajveer 419
 
420
    reservation = CurrentReservationSnapshot()
421
    reservation.item_id = item_id
422
    reservation.warehouse_id = warehouse_id
423
    reservation.source_id = source_id
424
    reservation.order_id = order_id
5990 rajveer 425
    reservation.created_timestamp = to_py_date(created_timestamp)
426
    reservation.promised_shipping_timestamp = to_py_date(promised_shipping_timestamp)
5966 rajveer 427
    reservation.reserved = quantity
428
 
8720 amar.kumar 429
    session.commit()
8182 amar.kumar 430
 
431
    try:
432
        order_client = TransactionClient().get_client()
433
        order = order_client.getOrder(order_id)
9574 amar.kumar 434
        if order.source:
435
            holdInventoryDetail = HoldInventoryDetail.query.filter_by(item_id = item_id, warehouse_id = warehouse_id, source = order.source).first()
9694 amar.kumar 436
            if holdInventoryDetail is None or holdInventoryDetail.held<=0:
437
                holdInventoryDetails = HoldInventoryDetail.query.filter_by(item_id = item_id, source = order.source).all()
438
                if holdInventoryDetails:
439
                    for hID in holdInventoryDetails:
440
                        if hID.held>0:
441
                            holdInventoryDetail = hID
9574 amar.kumar 442
            if holdInventoryDetail is not None and holdInventoryDetail.held>0:
443
                previousHeld = holdInventoryDetail.held
444
                holdInventoryDetail.held = max(0, holdInventoryDetail.held -quantity)
445
                diff = previousHeld-holdInventoryDetail.held 
9770 amar.kumar 446
                current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=item_id, warehouse_id=holdInventoryDetail.warehouse_id)
9574 amar.kumar 447
                if current_inventory_snapshot is not None:
448
                    current_inventory_snapshot.held = max(0, current_inventory_snapshot.held - diff)
449
                session.commit()
8182 amar.kumar 450
    except:
451
        print "Unable to release hold Inventory for item_id " + str(item_id) + " warehouse_id " + str(warehouse_id) + " source " + str(source_id)
8720 amar.kumar 452
    #session.commit()
5944 mandeep.dh 453
    #**Update item availability cache**#
5978 rajveer 454
    clear_item_availability_cache(item_id)
5944 mandeep.dh 455
    return True
456
 
7968 amar.kumar 457
def update_reservation_for_order(item_id, warehouse_id, source_id, order_id, created_timestamp, promised_shipping_timestamp, quantity):    
458
    if not warehouse_id:
459
        raise InventoryServiceException(101, "bad warehouse_id")
23516 amit.gupta 460
    warehouse = get_Warehouse(warehouse_id)
461
    '''item_pricing = get_item_pricing(item_id, warehouse.vendor.id)
462
    if not item_pricing:
463
        raise InventoryServiceException(101, "No Pricing Info found for vendor and Item")'''
464
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
465
    try:
466
        new_current_inventory_snapshot = query.one()
467
    except:
468
        new_current_inventory_snapshot = CurrentInventorySnapshot()
469
        new_current_inventory_snapshot.warehouse_id = warehouse_id
470
        new_current_inventory_snapshot.item_id = item_id
471
        new_current_inventory_snapshot.availability = 0
472
        new_current_inventory_snapshot.reserved = 0
7968 amar.kumar 473
 
23516 amit.gupta 474
    new_current_inventory_snapshot.reserved = new_current_inventory_snapshot.reserved + quantity
7968 amar.kumar 475
 
476
    new_reservation = CurrentReservationSnapshot()
477
    new_reservation.item_id = item_id
478
    new_reservation.warehouse_id = warehouse_id
479
    new_reservation.source_id = source_id
480
    new_reservation.order_id = order_id
481
    new_reservation.created_timestamp = to_py_date(created_timestamp)
482
    new_reservation.promised_shipping_timestamp = to_py_date(promised_shipping_timestamp)
483
    new_reservation.reserved = quantity
484
 
8182 amar.kumar 485
    try:
486
        order_client = TransactionClient().get_client()
487
        order = order_client.getOrder(order_id)
9574 amar.kumar 488
        if order.source:
489
            holdInventoryDetail = HoldInventoryDetail.query.filter_by(item_id = item_id, warehouse_id = warehouse_id, source = order.source).first()
9694 amar.kumar 490
            if holdInventoryDetail is None or holdInventoryDetail.held<=0:
491
                holdInventoryDetails = HoldInventoryDetail.query.filter_by(item_id = item_id, source = order.source).all()
492
                if holdInventoryDetails:
493
                    for hID in holdInventoryDetails:
494
                        if hID.held>0:
495
                            holdInventoryDetail = hID
9574 amar.kumar 496
            if holdInventoryDetail is not None and holdInventoryDetail.held>0:
497
                previousHeld = holdInventoryDetail.held
498
                holdInventoryDetail.held = max(0, holdInventoryDetail.held -quantity)
499
                diff = previousHeld-holdInventoryDetail.held 
9770 amar.kumar 500
                current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=item_id, warehouse_id=holdInventoryDetail.warehouse_id)
9574 amar.kumar 501
                if current_inventory_snapshot is not None:
502
                    current_inventory_snapshot.held = max(0, current_inventory_snapshot.held - diff)
503
                session.commit()
8182 amar.kumar 504
    except:
505
        print "Unable to release hold Inventory for item_id " + str(item_id) + " warehouse_id " + str(warehouse_id) + " source " + str(source_id)
506
 
7968 amar.kumar 507
    order_client = TransactionClient().get_client()
508
    order = order_client.getOrder(order_id)
509
    for lineitem in order.lineitems:
510
        query = CurrentInventorySnapshot.query.filter_by(warehouse_id = order.fulfilmentWarehouseId, item_id = lineitem.item_id)
511
        try:
512
            current_inventory_snapshot = query.one()
513
            current_inventory_snapshot.reserved = current_inventory_snapshot.reserved - quantity
514
 
515
            reservation = CurrentReservationSnapshot.query.filter_by(warehouse_id = order.fulfilmentWarehouseId, item_id = lineitem.item_id, source_id = source_id, order_id = order_id).one()
516
            if reservation.reserved == quantity:
517
                reservation.delete()
518
            else:
519
                reservation.reserved -= quantity
520
 
521
            clear_item_availability_cache(lineitem.item_id)
522
            session.commit()
523
            try:
524
                if current_inventory_snapshot.reserved < 0:
525
                    item = __get_item_from_master(lineitem.item_id)
526
                    __send_alert_for_negative_reserved(item, current_inventory_snapshot.reserved, get_Warehouse(order.fulfilmentWarehouseId))
527
            except:
8182 amar.kumar 528
                print "Error in sending negative reserved alert:", sys.exc_info()[0]
7968 amar.kumar 529
                return False
530
        except:
531
            print "Error in reducing reservation for item:", sys.exc_info()[0]
532
            return False
533
    session.commit()
534
    #**Update item availability cache**#
535
    clear_item_availability_cache(item_id)
536
    return True
537
 
19419 amit.gupta 538
def get_item_pincode_availability(itemPricingMap, pin_code):
19413 amit.gupta 539
    returnMap = {}
540
    missingItemPricingList = []
541
    for item_id, pricing in itemPricingMap.iteritems():
542
        if not pricing:
543
            missingItemPricingList.append(item_id)
20641 amit.gupta 544
    if missingItemPricingList:
545
        cc = CatalogClient().get_client()
546
        items = cc.getItems(missingItemPricingList)
547
        lc = LogisticsClient().get_client()
548
        #Consider selling price if its missing in itempricing
549
        for item in items:
550
            itemPricingMap[item.id] = item.sellingPrice
19413 amit.gupta 551
    pricingLocationInfoMap = __getLocationInfoMap(pin_code, itemPricingMap)    
552
    if pricingLocationInfoMap == -1:
553
        returnMap = {"pincode_serviceable":False}    
554
    else:
555
        #for item_id, sellingPrice in itemPricingMap.iteritems():
556
        allLocations = pricingLocationInfoMap[1].keys()    
557
        itemLocationAvailabilityList = __get_item_location_availability_bulk(itemPricingMap.keys(), allLocations)
558
        pricingLocationsMap = {}
559
        for itemLocationAvailability in itemLocationAvailabilityList:
560
            sellingPrice = itemPricingMap[itemLocationAvailability.item_id]
561
            if pricingLocationInfoMap[sellingPrice] == -1:
562
                continue
563
            if not pricingLocationsMap.has_key(sellingPrice):
564
                pricingLocationsMap[sellingPrice] = pricingLocationInfoMap[sellingPrice].keys() 
565
 
566
            if itemLocationAvailability.location_id not in pricingLocationsMap[sellingPrice]:
567
                continue
568
            if not returnMap.has_key(itemLocationAvailability.item_id):
569
                returnMap[itemLocationAvailability.item_id] = ItemPincodeAvailability(vatQty = 0, totalQty = 0, minDeliveryDate=-1)
570
            itemPincodeAvailability = ItemPincodeAvailability()
571
            itemPincodeAvailability = returnMap[itemLocationAvailability.item_id]
572
            locationInfo = LocationInfo()
573
            locationInfo = pricingLocationInfoMap[sellingPrice][itemLocationAvailability.location_id]
574
            locationQty = itemLocationAvailability.virtual_availability + itemLocationAvailability.physical_availability
575
            if locationInfo.sameState:
576
                itemPincodeAvailability.vatQty += locationQty
577
            itemPincodeAvailability.totalQty += locationQty
578
            itemPincodeAvailability.isCod = itemPincodeAvailability.isCod or locationInfo.isCod 
579
            itemPincodeAvailability.isOtg = itemPincodeAvailability.isOtg or locationInfo.isOtg 
580
            if itemPincodeAvailability.minDeliveryDate == -1:
581
                itemPincodeAvailability.minDeliveryDate = itemLocationAvailability.min_transfer_delay + locationInfo.minDelay 
582
                itemPincodeAvailability.maxDeliveryDate = itemLocationAvailability.max_transfer_delay + locationInfo.maxDelay
583
            else:
584
                itemPincodeAvailability.minDeliveryDate = min(itemPincodeAvailability.minDeliveryDate, itemLocationAvailability.min_transfer_delay + locationInfo.minDelay) 
585
                itemPincodeAvailability.maxDeliveryDate = max(itemPincodeAvailability.maxDeliveryDate, itemLocationAvailability.max_transfer_delay + locationInfo.maxDelay)
586
        for itemId, itemPincodeAvailability in returnMap.iteritems():
587
            sellingPrice = itemPricingMap[itemId]
588
            locationsMap = pricingLocationsMap[sellingPrice]
589
            minDay = math.ceil(itemPincodeAvailability.minDeliveryDate)
590
            maxDay = math.ceil(itemPincodeAvailability.maxDeliveryDate)
591
            itemPincodeAvailability.minDeliveryDate, itemPincodeAvailability.maxDeliveryDate = __getDeliveryDate(minDay, itemPincodeAvailability.isCod, maxDay)
592
 
593
    return json.dumps(returnMap)
594
 
595
 
596
def __getLocationInfoMap(pin_code, itemPricingMap):
20641 amit.gupta 597
    priceSet = set(itemPricingMap.values() + [1])
19413 amit.gupta 598
    if not pincodePricingServiceabilityMap.has_key(pin_code):
599
        pincodePricingServiceabilityMap[pin_code] = {}
600
    pricingMap = pincodePricingServiceabilityMap[pin_code]
601
    if pricingMap != -1: 
20641 amit.gupta 602
        missingInMap = list(priceSet - set(pricingMap.keys())) 
603
        if missingInMap:
604
            lc = LogisticsClient().get_client()
605
            priceLocationInfoMap = lc.getLocationInfoMap(pin_code, missingInMap)
606
            if not priceLocationInfoMap:
607
                pricingMap = pincodePricingServiceabilityMap[pin_code] = -1
608
            else:
609
                for sellingPrice in missingInMap:
610
                    if priceLocationInfoMap[sellingPrice] == {}:
611
                        pricingMap[sellingPrice] = -1
612
                    else:
613
                        pricingMap[sellingPrice] = priceLocationInfoMap[sellingPrice]
19413 amit.gupta 614
 
615
    return pricingMap
616
 
617
def __getDeliveryDate(minDays, isCod, maxDays=None):
618
    curTime = datetime.datetime.now()
619
    if maxDays is None:
620
        maxDays = minDays 
621
    if isCod and curTime.hour < 15:
622
        maxDays = maxDays + 1
623
    return __getAdjustedDate(minDays), __getAdjustedDate(maxDays) 
7968 amar.kumar 624
 
19413 amit.gupta 625
def __getAdjustedDate(days):
626
    curDate = datetime.date.today()
627
    if curDate == last_date:
628
        if adjusted_dates.has_key(days):
629
            return adjusted_dates[days]
630
    else:
631
        adjusted_dates = {}
632
    lc = LogisticsClient().get_client()
633
    adjusted_day = lc.adjustDeliveryDays(datetime.datetime.now(), to_java_date(days))
634
 
635
    adjusted_date = to_java_date(datetime.datetime.combine(curDate, datetime.datetime.min.time()) + datetime.timedelta(days=adjusted_day))
636
    adjusted_dates[days] = adjusted_date
637
    return adjusted_date
638
 
5966 rajveer 639
def reduce_reservation_count(item_id, warehouse_id, source_id, order_id, quantity):
5944 mandeep.dh 640
    if not warehouse_id:
641
        raise InventoryServiceException(101, "bad warehouse_id")
642
 
643
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
644
    try:
645
        current_inventory_snapshot = query.one()
646
        current_inventory_snapshot.reserved = current_inventory_snapshot.reserved - quantity
5966 rajveer 647
 
648
        reservation = CurrentReservationSnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id, source_id = source_id, order_id = order_id).one()
649
        if reservation.reserved == quantity:
650
            reservation.delete()
651
        else:
652
            reservation.reserved -= quantity
5944 mandeep.dh 653
        session.commit()
654
        #**Update item availability cache**#
5978 rajveer 655
        clear_item_availability_cache(item_id)
5944 mandeep.dh 656
        if current_inventory_snapshot.reserved < 0:
657
            item = __get_item_from_master(item_id)
658
            __send_alert_for_negative_reserved(item, current_inventory_snapshot.reserved, get_Warehouse(warehouse_id))
659
        return True
660
    except:
661
        print "Unexpected error:", sys.exc_info()[0]
662
        return False
663
 
12976 amit.gupta 664
#This is not the source as in snapdeal or website, this source is to incorporate different pricing depending upon source id.
22566 amit.gupta 665
#i.e. if user visiting to our site has specific source he would see pricing on that source basis. Default source is 1.
22719 amit.gupta 666
# Have to add another source id 2 for fofo warehouses
23442 amit.gupta 667
 
23446 amit.gupta 668
def get_item_availability_for_state(itemId, sourceId, stateId):
669
    __populateWarehouseMap()
23442 amit.gupta 670
    currentInventorySnapshots = get_item_inventory_by_item_id(itemId)
23446 amit.gupta 671
    totalAvailability = 0
672
    expectedDelay = 0
23442 amit.gupta 673
    if len(currentInventorySnapshots) > 0:
674
        for currentInventorySnapshot in currentInventorySnapshots:
23630 amit.gupta 675
            if currentInventorySnapshot.warehouse.state_id == stateId:
23446 amit.gupta 676
                availability = currentInventorySnapshot.availability - currentInventorySnapshot.reserved
677
                if availability > 0:
23482 amit.gupta 678
                    warehouse = currentInventorySnapshot.warehouse
23446 amit.gupta 679
                totalAvailability += availability 
680
    if totalAvailability <= 0:
23611 amit.gupta 681
        warehouse = virtualVendorWarehouses.get(stateId)
23446 amit.gupta 682
        expectedDelay = 2
25469 amit.gupta 683
    warehouseId = warehouse.id
23446 amit.gupta 684
    ia = get_item_availability_for_location(itemId, sourceId)
25469 amit.gupta 685
    return [warehouseId, expectedDelay, billingVendorWarehouses[stateId], ia[3], totalAvailability, ia[5]]
23442 amit.gupta 686
 
687
 
5978 rajveer 688
def get_item_availability_for_location(item_id, source_id):
689
    item_availability = ItemAvailabilityCache.get_by(itemId=item_id, sourceId = source_id)
5944 mandeep.dh 690
    if item_availability:
23839 amit.gupta 691
        print "Selling Price",  item_availability.sellingPrice
24741 amit.gupta 692
        if item_availability.sellingPrice is None:
693
            item_availability.sellingPrice = 100000
694
        print "[item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice, item_availability.totalAvailability, item_availability.weight]"
695
        print item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice, item_availability.totalAvailability, item_availability.weight
7589 rajveer 696
        return [item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice, item_availability.totalAvailability, item_availability.weight]
20641 amit.gupta 697
        #return [item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice, 0, item_availability.weight]
5944 mandeep.dh 698
    else:
5978 rajveer 699
        __update_item_availability_cache(item_id, source_id)
700
            ##Check risky status for the source
701
        __check_risky_item(item_id, source_id)
702
        return get_item_availability_for_location(item_id, source_id)
5944 mandeep.dh 703
 
19413 amit.gupta 704
def get_item_location_availability(item_id, locations=[]):
705
    if locations:
706
        newLocations = locations + [-1]
707
        itemisedItemLocationAvailability = ItemLocationAvailabilityCache.filter_by(itemId=item_id).filter(ItemLocationAvailability.locationId.in_(newLocations)).all()
708
    else:
709
        itemisedItemLocationAvailability = ItemLocationAvailabilityCache.filter_by(itemId=item_id).all()
710
    if not itemisedItemLocationAvailability:
711
        __update_item_location(item_id)
712
        return get_item_location_availability(item_id, locations)
713
    else:
714
        thriftList = []
715
        for itemLocationAvailability in itemisedItemLocationAvailability:
716
            if itemLocationAvailability.location_id == -1:
717
                itemisedItemLocationAvailability
718
            else:
719
                thriftList.append(to_t_item_location_availability(itemLocationAvailability))
720
        return thriftList
721
 
722
def __get_item_location_availability_bulk(item_ids, locations=[]):
723
 
724
    query = ItemLocationAvailabilityCache.query.filter(ItemLocationAvailabilityCache.item_id.in_(item_ids))
725
    allPopulated = query.filter(ItemLocationAvailabilityCache.location_id==-1).all()
726
    if len(item_ids) > len(allPopulated):
727
        for item_id in allPopulated:
728
            if item_id not in item_ids:
729
                __update_item_location(item_id)
730
    if locations:
731
        query.filter(ItemLocationAvailabilityCache.location_id.in_(locations)).all()
732
    return query.all()
733
 
734
 
735
def clear_item_location_availability_cache(item_id, locations=[]):
736
    if type(item_id)==list:
737
        ItemLocationAvailabilityCache.query.filter(ItemLocationAvailabilityCache.itemId.in_(item_id)).delete(synchronize_session='fetch')
738
        session.commit()
739
        t = threading.Thread(target=_task_update_item_availability_cache, args=(item_id,))
740
        t.start()
741
    elif item_id:
742
        ItemLocationAvailabilityCache.query.filter_by(itemId = item_id).delete()
743
    session.commit()
744
 
5978 rajveer 745
def clear_item_availability_cache(item_id = None):
13150 manish.sha 746
    print item_id
13149 manish.sha 747
    if type(item_id)==list:
13150 manish.sha 748
        ItemAvailabilityCache.query.filter(ItemAvailabilityCache.itemId.in_(item_id)).delete(synchronize_session='fetch')
13149 manish.sha 749
        session.commit()
13493 amit.gupta 750
        t = threading.Thread(target=_task_update_item_availability_cache, args=(item_id,))
751
        t.start()
752
 
13520 amit.gupta 753
    elif item_id:
5978 rajveer 754
        ItemAvailabilityCache.query.filter_by(itemId = item_id).delete()
12963 amit.gupta 755
        session.commit()
13493 amit.gupta 756
 
757
def _task_update_item_availability_cache(item_ids):
758
    client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
759
    items = client.getItems(item_ids)
760
    for item_id in item_ids:
761
        item_availability = ItemAvailabilityCache.get_by(itemId=item_id, sourceId=1)
762
        if not item_availability:
763
            try:
17974 amit.gupta 764
                __update_item_availability_cache(item_id, 1, items[item_id])
765
                __check_risky_item(item_id, 1)
13493 amit.gupta 766
            except:
767
                print "Could not update cache for "
768
                continue
17990 kshitij.so 769
    return True   
5944 mandeep.dh 770
 
19413 amit.gupta 771
def __update_item_location(item_id):
772
    ignoredWhs = get_ignored_warehouses(item_id)
773
 
774
    itemsnapshot = CurrentInventorySnapshot.query.filter_by(item_id = item_id).all()
775
    locationsMap = {}
776
    for row in itemsnapshot:
777
        warehouse = warehouseMap[row.warehouse_id]
778
        if row.warehouse_id in ignoredWhs:
779
            continue 
780
 
781
        location = warehouse.logisticsLocation
782
        if not locationsMap.has_key(location):
783
            locationsMap[location] = {"physicalQty":0, "virtualQty":0,    "minTransferDelay":100, "maxTransferDelay":0}
784
        locationMap = locationsMap[location]
785
        if warehouse.type == 'THIRD_PARTY':
786
            locationMap["virtualQty"] += max(0, row.availability - row.reserverd - row.held)
787
            locationMap["minTransferDelay"] = min(locationMap["minTransferDelay"], row.transferDelayInHours/24)
788
            locationMap["maxTransferDelay"] = max(locationMap["maxTransferDelay"], row.transferDelayInHours/24)
789
        else:
790
            locationMap["physicalQty"] += max(0, row.availability - row.reserverd - row.held)
791
            locationMap["minTransferDelay"] = 0
792
    for location, locationMap in locationsMap.iteritems():
793
        if locationMap["virtualQty"] > 0 or locationMap["physicalQty"] > 0: 
794
            itemLocationAvailability = ItemLocationAvailabilityCache()
795
            itemLocationAvailability.item_id = item_id
796
            itemLocationAvailability.location_id = location
797
            itemLocationAvailability.max_transfer_delay = locationMap["maxTransferDelay"]
798
            itemLocationAvailability.min_transfer_delay = locationMap["minTransferDelay"]
799
            itemLocationAvailability.virtual_availability = locationMap["virtualQty"]
800
            itemLocationAvailability.physical_availability = locationMap["physicalQty"]
801
    #Add location -1 for each item
802
    itemLocationAvailability = ItemLocationAvailabilityCache()
803
    itemLocationAvailability.item_id = item_id
804
    itemLocationAvailability.location_id = -1
805
    session.commit()
806
 
807
 
808
 
809
 
810
 
12963 amit.gupta 811
def __update_item_availability_cache(item_id, source_id, item=None):
5944 mandeep.dh 812
    """
22719 amit.gupta 813
    Then how shoud we handle virtual because for both source virtual gonna mark
814
    """
815
    """
8954 vikram.rag 816
    Determines the warehouse that should be used to fulfil an order for the given item.
5944 mandeep.dh 817
    Algorithm explained at https://sites.google.com/a/shop2020.in/virtual-w-h-and-inventory/technical-details
818
 
819
    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.
820
    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.
821
 
822
    if item available at any OUR-GOOD warehouse
823
        // OUR-GOOD warehouses have inventory risk; So, we empty them first! 
824
        // We can start with minimum transfer price criterion but down the line we can also bring in Inventory age 
825
        assign OUR-GOOD warehouse with minimum transfer price
826
    else
827
        if Preferred vendor is specified and marked Sticky
828
            // Always purchase from Preferred if its marked sticky
829
            assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
830
        else 
831
            if item available in a THIRDPARTY GOOD/VIRTUAL warehouse
832
                assign THIRDPARTY GOOD/VIRTUAL warehouse where item is available with minimal transfer delay followed by minimum transfer price
833
            else 
834
                // Item not available at any warehouse, OURS or THIRDPARTY
835
                If Preferred vendor is specified
836
                    assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
837
                else
838
                    assign THIRDPARTY GOOD/VIRTUAL warehouse with minimum transfer price
839
 
840
    Returns an ordered list of size 4 with following elements in the given order:
841
    1. Logistics location of the warehouse which was finally picked up to ship the order.
842
    2. Expected delay added by the category manager.
843
    3. Id of the warehouse which was finally picked up.
844
 
845
    Parameters:
846
     - itemId
847
    """
12963 amit.gupta 848
    if item is None:
849
        item = __get_item_from_source(item_id, source_id)
5944 mandeep.dh 850
    item_pricing = {}
851
    for vendorItemPricing in VendorItemPricing.query.filter_by(item_id=item_id).all():
852
        item_pricing[vendorItemPricing.vendor_id] = vendorItemPricing
853
 
6510 rajveer 854
    ignoredWhs = get_ignored_warehouses(item_id)
855
 
5944 mandeep.dh 856
    warehouses = {}
857
    ourGoodWarehouses = {}
858
    thirdpartyWarehouses = {}
859
    preferredThirdpartyWarehouses = {}
860
    for warehouse in Warehouse.query.all():
7410 amar.kumar 861
        if (warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.BAD] or warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.OURS_THIRDPARTY]):
5944 mandeep.dh 862
            continue
863
        warehouses[warehouse.id] = warehouse
864
        if warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.OURS]:
865
            if warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
866
                ourGoodWarehouses[warehouse.id] = warehouse
867
        else:
868
            thirdpartyWarehouses[warehouse.id] = warehouse
869
            if item.preferredVendor == warehouse.vendor_id and warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
870
                preferredThirdpartyWarehouses[warehouse.id] = warehouse
871
 
872
    warehouse_retid = -1
873
    total_availability = 0
874
 
6540 rajveer 875
    [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(ourGoodWarehouses, ignoredWhs, item_id, item_pricing, False)
5944 mandeep.dh 876
    if warehouse_retid == -1:
877
        if item.preferredVendor and item.isWarehousePreferenceSticky:
6540 rajveer 878
            [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(preferredThirdpartyWarehouses, ignoredWhs, item_id, item_pricing)
5944 mandeep.dh 879
            if warehouse_retid == -1:
880
                warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
881
        else:
6540 rajveer 882
            [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(thirdpartyWarehouses, ignoredWhs, item_id, item_pricing)
5944 mandeep.dh 883
            if warehouse_retid == -1:
884
                if item.preferredVendor:
885
                    warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
886
                else:
6540 rajveer 887
                    [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(thirdpartyWarehouses, ignoredWhs, item_id, item_pricing, True)
24741 amit.gupta 888
    print "I am able to reach here wih warehouse_retid", warehouse_retid
5944 mandeep.dh 889
    warehouse = warehouses[warehouse_retid]
890
    billingWarehouseId = warehouse.billingWarehouseId
891
 
892
    # Fetching billing warehouse of a Good billable warehouse corresponding to the virtual one
893
    if not warehouse.billingWarehouseId:
21152 amit.gupta 894
        for w in Warehouse.query.filter_by(vendor_id = warehouse.vendor_id, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD], state_id=warehouse.state_id).all():
5944 mandeep.dh 895
            if w.billingWarehouseId:
896
                billingWarehouseId = w.billingWarehouseId
897
                break
898
 
899
    expectedDelay = item.expectedDelay 
900
    if expectedDelay is None:
901
        print 'expectedDelay field for this item was Null. Resetting it to 0'
902
        expectedDelay = 0
903
    else:
904
        expectedDelay = int(item.expectedDelay)
905
 
906
    if total_availability <= 0:
8026 amar.kumar 907
        if item.preferredVendor in [1, 5]:
6562 rajveer 908
            expectedDelay = expectedDelay + 3
909
        else:
910
            expectedDelay = expectedDelay + 2
6643 rajveer 911
    else:
912
        if warehouse.transferDelayInHours:
913
            expectedDelay = expectedDelay + warehouse.transferDelayInHours / 24
5944 mandeep.dh 914
 
18022 manish.sha 915
    if WarehouseType._NAMES_TO_VALUES[warehouse.warehouseType] == WarehouseType.THIRD_PARTY:
8491 rajveer 916
        expectedDelay = expectedDelay + __get_vendor_holiday_delay(warehouse.vendor_id, expectedDelay) 
917
 
5963 mandeep.dh 918
    total_availability = 0
16029 amit.gupta 919
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
6545 rajveer 920
        if entry.warehouse_id not in ignoredWhs:
16029 amit.gupta 921
            if entry.warehouse_id not in ourGoodWarehouses and entry.warehouse_id not in thirdpartyWarehouses:
16015 amit.gupta 922
                continue
923
            if entry.warehouse_id in ourGoodWarehouses and ourGoodWarehouses[entry.warehouse_id].billingWarehouseId == billingWarehouseId:
924
                total_availability += entry.availability - entry.reserved - entry.held
925
            elif entry.warehouse_id in thirdpartyWarehouses:
926
                vendorId = thirdpartyWarehouses[entry.warehouse_id].vendor_id
927
                for goodWarehouse in ourGoodWarehouses.values():
21152 amit.gupta 928
                    if goodWarehouse.vendor_id==vendorId and goodWarehouse.billingWarehouseId == billingWarehouseId and warehouse.state_id==goodWarehouse.state_id:
16015 amit.gupta 929
                        total_availability += entry.availability - entry.reserved - entry.held
930
                        break
5963 mandeep.dh 931
 
5978 rajveer 932
    item_availability_cache = ItemAvailabilityCache.get_by(itemId=item_id, sourceId=source_id)
5944 mandeep.dh 933
    if item_availability_cache is None:
934
        item_availability_cache = ItemAvailabilityCache()
935
        item_availability_cache.itemId = item_id
5978 rajveer 936
        item_availability_cache.sourceId = source_id
5944 mandeep.dh 937
    item_availability_cache.warehouseId = int(warehouse_retid)
938
    item_availability_cache.expectedDelay = expectedDelay
939
    item_availability_cache.billingWarehouseId = billingWarehouseId
940
    item_availability_cache.sellingPrice = item.sellingPrice
941
    item_availability_cache.totalAvailability = total_availability
16029 amit.gupta 942
    #item_availability_cache.location = warehouse.logisticsLocation 
7589 rajveer 943
    item_availability_cache.weight = 1000*item.weight if item.weight else 300
5944 mandeep.dh 944
    session.commit()
945
 
6540 rajveer 946
def __get_warehouse_with_min_transfer_price(warehouses, ignoredWhs, item_id, item_pricing, ignoreAvailability):
5944 mandeep.dh 947
    warehouse_retid = -1
948
    minTransferPrice = None
949
    total_availability = 0
6013 amar.kumar 950
    availabilityForBillingWarehouses = {}
951
    warehousesAvailability = {}
952
    availability = 0
953
    billing_warehouse_retid = None
5944 mandeep.dh 954
 
955
    if not ignoreAvailability:
956
        for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
7242 amar.kumar 957
            entry.reserved = max(entry.reserved, 0)
8524 amar.kumar 958
            entry.held = max(entry.held, 0)
6013 amar.kumar 959
            #if entry.availability > entry.reserved:
8182 amar.kumar 960
            warehousesAvailability[entry.warehouse_id] = [entry.availability, entry.reserved, entry.held] 
5944 mandeep.dh 961
 
6540 rajveer 962
    if len(ignoredWhs) > 0:
963
        for whid in ignoredWhs:
964
            if warehousesAvailability.has_key(whid):
6542 rajveer 965
                warehousesAvailability[whid][0] = 0
6683 rajveer 966
                warehousesAvailability[whid][1] = 0
8182 amar.kumar 967
                warehousesAvailability[whid][2] = 0
6540 rajveer 968
 
5944 mandeep.dh 969
    for warehouse in warehouses.values():
970
        if not ignoreAvailability:
6013 amar.kumar 971
            #TODO Mistake no entry for this warehouse.id in warehouseswithAvailab
972
            if warehouse.id not in warehousesAvailability:
973
                continue
974
            entry = warehousesAvailability[warehouse.id]
975
            if warehouse.billingWarehouseId in availabilityForBillingWarehouses:
976
                if warehouse.billingWarehouseId is not None or warehouse.billingWarehouseId != 0: 
8182 amar.kumar 977
                    availabilityForBillingWarehouses[warehouse.billingWarehouseId] = availabilityForBillingWarehouses[warehouse.billingWarehouseId] + entry[0] - entry[1] - entry[2]  
5944 mandeep.dh 978
            else:
6013 amar.kumar 979
                if warehouse.billingWarehouseId is not None or warehouse.billingWarehouseId != 0: 
8182 amar.kumar 980
                    availabilityForBillingWarehouses[warehouse.billingWarehouseId] = entry[0] - entry[1] - entry[2]
981
            if entry[0] <= (entry[1] + entry[2]):
5944 mandeep.dh 982
                continue
8182 amar.kumar 983
            total_availability += entry[0] - entry[1] - entry[2]
5944 mandeep.dh 984
 
985
        # Missing transfer price cases should not impact warehouse assignment
986
        transferPrice = None
987
        if item_pricing.has_key(warehouse.vendor_id):
6778 rajveer 988
            transferPrice = item_pricing[warehouse.vendor_id].nlc
5944 mandeep.dh 989
        if minTransferPrice is None or (transferPrice and minTransferPrice > transferPrice):
990
            warehouse_retid = warehouse.id
6013 amar.kumar 991
            billing_warehouse_retid = warehouse.billingWarehouseId
5944 mandeep.dh 992
            minTransferPrice = transferPrice
6013 amar.kumar 993
 
994
 
995
    if billing_warehouse_retid in availabilityForBillingWarehouses: 
996
        availability = availabilityForBillingWarehouses[billing_warehouse_retid]
997
    else:
998
        availability = total_availability
999
 
24741 amit.gupta 1000
    print "[warehouse_retid, availability]", warehouse_retid, availability
6013 amar.kumar 1001
    return [warehouse_retid, availability]
5944 mandeep.dh 1002
 
6540 rajveer 1003
def __get_warehouse_with_min_transfer_delay(warehouses, ignoredWhs, item_id, item_pricing):
5944 mandeep.dh 1004
    minTransferDelay = None
1005
    minTransferDelayWarehouses = {}
1006
    total_availability = 0
1007
 
1008
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
7242 amar.kumar 1009
        entry.reserved = max(entry.reserved, 0)
8524 amar.kumar 1010
        entry.held = max(entry.held, 0)
5944 mandeep.dh 1011
        if warehouses.has_key(entry.warehouse_id):
1012
            warehouse = warehouses[entry.warehouse_id]
6013 amar.kumar 1013
            #if entry.availability > entry.reserved:
6683 rajveer 1014
            if entry.warehouse_id not in ignoredWhs:
8182 amar.kumar 1015
                total_availability += entry.availability - entry.reserved - entry.held
1016
            if entry.availability - entry.reserved - entry.held <= 0:
6780 amar.kumar 1017
                continue
6013 amar.kumar 1018
            transferDelay = warehouse.transferDelayInHours
1019
            if minTransferDelay is None or minTransferDelay >= transferDelay:
1020
                if minTransferDelay != transferDelay:
1021
                    minTransferDelayWarehouses = {}
1022
                minTransferDelayWarehouses[warehouse.id] = warehouse
1023
                minTransferDelay = transferDelay
5944 mandeep.dh 1024
 
6540 rajveer 1025
    return [__get_warehouse_with_min_transfer_price(minTransferDelayWarehouses, ignoredWhs, item_id, item_pricing, False)[0], total_availability]
5944 mandeep.dh 1026
 
1027
def __get_warehouse_with_max_availability(warehouse_ids, item_id):
1028
    warehouse_retid = -1
1029
    max_availability = 0
1030
    total_availability = 0
1031
 
1032
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
7242 amar.kumar 1033
        entry.reserved = max(entry.reserved, 0)
8524 amar.kumar 1034
        entry.held = max(entry.held, 0)
5944 mandeep.dh 1035
        if entry.warehouse_id in warehouse_ids:
1036
            availability = entry.availability - entry.reserved
1037
            if availability > max_availability:
1038
                warehouse_retid = entry.warehouse_id
1039
                max_availability = availability
1040
            total_availability += availability
1041
 
1042
    return [warehouse_retid, total_availability]
1043
 
8491 rajveer 1044
def __get_vendor_holiday_delay(vendor_id, expectedDelay):
1045
    ## If vendor is closed two days continuously
5944 mandeep.dh 1046
    holidayDelay = 0
8491 rajveer 1047
    currentDate = datetime.date.today()
1048
    expectedDate = currentDate + datetime.timedelta(days = expectedDelay)
1049
    holidays = VendorHolidays.query.filter(VendorHolidays.vendor_id == vendor_id).filter(VendorHolidays.date.between(currentDate, expectedDate)).all()
1050
    if holidays:
1051
        holidayDelay = holidayDelay + len(holidays)
5944 mandeep.dh 1052
    return holidayDelay 
1053
 
1054
def get_item_pricing(item_id, vendorId):
1055
    '''
1056
    if vendor id is -1 then we calculate an average transfer price to be populated
1057
    at the time of order creation. This will be later updated with actual transfer price
1058
    at the time of billing.
1059
    '''
1060
    if(vendorId == -1):
6778 rajveer 1061
        tp_total = 0
1062
        nlc_total = 0
5944 mandeep.dh 1063
        try:
1064
            item_pricings = []
1065
            item = __get_item_from_master(item_id)
1066
            if item.preferredVendor is not None:
1067
                item_pricing = VendorItemPricing.query.filter_by(item_id=item_id, vendor_id=item.preferredVendor).first()
1068
                if item_pricing:
1069
                    item_pricings.append(item_pricing)                    
1070
            else :
1071
                item_pricings = VendorItemPricing.query.filter_by(item_id=item_id).all()
1072
            if item_pricings:
1073
                for item_pricing in item_pricings:
6778 rajveer 1074
                    tp_total += item_pricing.transfer_price
1075
                    nlc_total += item_pricing.nlc
1076
                tp_avg = tp_total / len(item_pricings)
1077
                nlc_avg = nlc_total / len(item_pricings)
1078
                item_pricing.transfer_price = tp_avg
1079
                item_pricing.nlc = nlc_avg
5944 mandeep.dh 1080
            else:
1081
                item_pricing = VendorItemPricing()
1082
                item_pricing.transfer_price = item.sellingPrice
6778 rajveer 1083
                item_pricing.nlc = item.sellingPrice
5944 mandeep.dh 1084
                vendor = Vendor()
1085
                vendor.id = vendorId
1086
                item_pricing.vendor = vendor
1087
                item_pricing.item_id = item_id
1088
 
1089
            return item_pricing
1090
        except:
1091
            raise InventoryServiceException(101, "Item pricing not found ")
1092
    vendor = Vendor.get_by(id=vendorId)    
1093
    try:
1094
        item_pricing = VendorItemPricing.query.filter_by(vendor=vendor, item_id=item_id).one()
1095
        return item_pricing
1096
    except MultipleResultsFound:
1097
        raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
1098
    except NoResultFound:
1099
        raise InventoryServiceException(111, "Missing pricing information for Vendor: " + vendor.name + " and Item: " + str(item_id))
1100
 
1101
def get_all_item_pricing(item_id):
1102
    item_pricing = VendorItemPricing.query.filter_by(item_id=item_id).all()
1103
    return item_pricing
10126 amar.kumar 1104
def get_all_vendor_item_pricing(item_id, vendor_id):
1105
    query = VendorItemPricing.query
1106
    if item_id:
1107
        query = query.filter_by(item_id = item_id)
1108
    if item_id:
1109
        query = query.filter_by(vendor_id = vendor_id)
1110
    item_pricing = query.all()
1111
    return item_pricing
1112
 
5944 mandeep.dh 1113
def get_item_mappings(item_id):
1114
    item_mappings = VendorItemMapping.query.filter_by(item_id=item_id).all()
1115
    return item_mappings
1116
 
19247 kshitij.so 1117
def add_vendor_pricing(vendorItemPricing, sendMail = True):
5944 mandeep.dh 1118
    if not vendorItemPricing:
1119
        raise InventoryServiceException(108, "Bad vendorItemPricing in request")
1120
    vendorId = vendorItemPricing.vendorId
1121
    itemId = vendorItemPricing.itemId
1122
 
1123
    try:
1124
        vendor = Vendor.query.filter_by(id=vendorId).one()
1125
    except:
1126
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
1127
 
1128
    try:
1129
        item = __get_item_from_master(itemId)
1130
    except:
1131
        raise InventoryServiceException(101, "Item not found for itemId " + str(itemId))
1132
 
1133
    validate_vendor_prices(item, vendorItemPricing)
1134
 
1135
    try:
1136
        ds_vendorItemPricing = VendorItemPricing.query.filter(and_(VendorItemPricing.vendor==vendor, VendorItemPricing.item_id==itemId)).one()
1137
    except:
1138
        ds_vendorItemPricing = VendorItemPricing()
1139
        ds_vendorItemPricing.vendor = vendor
1140
        ds_vendorItemPricing.item_id = itemId
1141
 
1142
    subject = ""
1143
    message = ""
1144
    if vendorItemPricing.mop:
1145
        ds_vendorItemPricing.mop = vendorItemPricing.mop
1146
    if vendorItemPricing.dealerPrice:
1147
        ds_vendorItemPricing.dealerPrice = vendorItemPricing.dealerPrice
1148
    if vendorItemPricing.transferPrice:
26911 amit.gupta 1149
        #if vendorItemPricing.transferPrice != ds_vendorItemPricing.transfer_price:
1150
        #    client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
1151
        #    item = client.getItem(itemId)
1152
        #    message = "Transfer price for Item {0} {1} {2} {3} \nand Vendor:{4} is changed from {5} to {6}.".format(item.brand, item.modelName, item.modelNumber, item.color, vendor.name, ds_vendorItemPricing.transfer_price, vendorItemPricing.transferPrice)
1153
        #    subject = "Alert:Change in Transfer Price {0} {1} {2} {3} {4}".format(item.brand, item.modelName, item.modelNumber, item.color, itemId)
5944 mandeep.dh 1154
        ds_vendorItemPricing.transfer_price = vendorItemPricing.transferPrice
6751 amar.kumar 1155
    if vendorItemPricing.nlc:
26911 amit.gupta 1156
        #if vendorItemPricing.nlc != ds_vendorItemPricing.nlc:
1157
        #    client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
1158
        #    item = client.getItem(itemId)
1159
        #    message = message + "\nNLC for Item {0} {1} {2} {3} \nand Vendor:{4} is changed from {5} to {6}.".format(item.brand, item.modelName, item.modelNumber, item.color, vendor.name, ds_vendorItemPricing.nlc, vendorItemPricing.nlc)
1160
        #    subject = "Alert:Change in NLC {0} {1} {2} {3} {4}".format(item.brand, item.modelName, item.modelNumber, item.color, itemId)
6751 amar.kumar 1161
        ds_vendorItemPricing.nlc = vendorItemPricing.nlc
9895 vikram.rag 1162
    session.commit()    
26911 amit.gupta 1163
    #client = CatalogClient("catalog_service_server_host_staging", "catalog_service_server_port").get_client()
1164
    #client.updateNlcAtMarketplaces(itemId,vendorId,ds_vendorItemPricing.nlc)
1165
    #if subject and sendMail:
1166
    #    __send_mail(subject, message)
5944 mandeep.dh 1167
    return
1168
 
1169
def add_vendor_item_mapping(key, vendorItemMapping):
1170
    if not vendorItemMapping:
1171
        raise InventoryServiceException(108, "Bad vendorItemMapping in request")
1172
    vendorId = vendorItemMapping.vendorId
1173
    itemId = vendorItemMapping.itemId
1174
 
1175
    try:
1176
        vendor = Vendor.query.filter_by(id=vendorId).one()
1177
    except:
1178
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
1179
 
1180
    try:
1181
        ds_vendorItemMapping = VendorItemMapping.query.filter(and_(VendorItemMapping.vendor==vendor, VendorItemMapping.item_id==itemId, VendorItemMapping.item_key==key)).one()
1182
    except:
1183
        ds_vendorItemMapping = VendorItemMapping()
1184
        ds_vendorItemMapping.vendor = vendor
1185
        ds_vendorItemMapping.item_id = itemId
1186
    ds_vendorItemMapping.item_key = vendorItemMapping.itemKey
1187
 
1188
    session.commit()
1189
 
1190
    # Marking the missed inventory as not ignored as the catalog dashboard user has updated their key
1191
    for missedInventoryUpdate in MissedInventoryUpdate.query.filter_by(itemKey = vendorItemMapping.itemKey).all():
1192
        missedInventoryUpdate.isIgnored = 0
1193
    session.commit()
1194
 
1195
    return
1196
 
1197
def validate_vendor_prices(item, vendorPrices):
1198
    if item.mrp != None and item.mrp != "" and vendorPrices.mop != "" and item.mrp <  vendorPrices.mop:
1199
        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))
1200
        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)))
18460 kshitij.so 1201
    return
18459 kshitij.so 1202
    #if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
18460 kshitij.so 1203
#         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))
1204
#         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)))
1205
    #return 
5944 mandeep.dh 1206
 
1207
def get_all_vendors():
1208
    return Vendor.query.all()
1209
 
1210
def get_pending_orders_inventory(vendor_id=1):
1211
    """
1212
    Returns a list of inventory stock for items for which there are pending orders.
1213
    """
1214
 
1215
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter_by(vendor_id = vendor_id)]
1216
    pending_items_inventory = []
1217
    if warehouse_ids:
1218
        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()
1219
    return pending_items_inventory
1220
 
7149 amar.kumar 1221
def get_billable_inventory_and_pending_orders():
1222
    """
1223
    Returns a list of inventory Availability and Reserved Count for items which either have real inventory
1224
    or have pending orders.
1225
    """
1226
 
1227
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter(Warehouse.isAvailabilityMonitored == 1).filter(or_(Warehouse.inventoryType == 'GOOD', Warehouse.warehouseType == 'OURS'))]
1228
    items_inventory = []
1229
    reserved_items_inventory = []
1230
    available_items_inventory = []
1231
    if warehouse_ids:
1232
        reserved_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()
1233
        available_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.availability) > 0).all()
1234
 
1235
    items_inventory.extend(reserved_items_inventory)
1236
    items_inventory.extend(available_items_inventory)
1237
    return items_inventory
1238
 
1239
 
5944 mandeep.dh 1240
def close_session():
1241
    if session.is_active:
1242
        print "session is active. closing it."
1243
        session.close()
1244
 
1245
def is_alive():
1246
    try:
1247
        session.query(Vendor.id).limit(1).one()
1248
        return True
1249
    except:
1250
        return False
1251
 
1252
def add_vendor(vendor):
1253
    if not vendor:
1254
        raise InventoryServiceException(108, "Bad vendor")
1255
    if get_vendor(vendor.id):
1256
        #vendor is already present.
1257
        raise InventoryServiceException(101, "Vendor already present")
1258
 
1259
    ds_vendor = Vendor()
1260
    ds_vendor.id = vendor.id
1261
    ds_vendor.name = vendor.name
1262
    session.commit()
1263
    return ds_vendor.id
1264
 
1265
def add_warehouse_vendor_mapping(warehouse_id, VendorId):
1266
    return True
1267
 
1268
def mark_missed_inventory_updates_as_processed(itemKey, warehouseId):
1269
    MissedInventoryUpdate.query.filter_by(itemKey = itemKey, warehouseId = warehouseId).delete()
1270
    session.commit()
1271
 
1272
def get_item_keys_to_be_processed(warehouseId):
1273
    return [i.itemKey for i in MissedInventoryUpdate.query.filter_by(warehouseId = warehouseId, isIgnored = 0)]
1274
 
1275
def reset_availability(itemKey, vendorId, quantity, warehouseId):
1276
    vendorItemMapping = VendorItemMapping.get_by(vendor_id = vendorId, item_key = itemKey)
1277
    if vendorItemMapping:
1278
        itemId = vendorItemMapping.item_id
1279
 
1280
        if skippedItems.has_key(warehouseId) and itemId in skippedItems[warehouseId]:
1281
            quantity = 0
1282
 
1283
        currentInventorySnapshot = CurrentInventorySnapshot.get_by(item_id = itemId, warehouse_id = warehouseId)
1284
        if currentInventorySnapshot:
1285
            currentInventorySnapshot.availability = quantity
5978 rajveer 1286
            clear_item_availability_cache(itemId) 
5944 mandeep.dh 1287
        else:
1288
            add_inventory(itemId, warehouseId, quantity)
1289
 
1290
    else:
1291
        raise InventoryServiceException(101, 'VendorMapping not found for: ' + itemKey)
1292
    session.commit()
1293
 
1294
def reset_availability_for_warehouse(warehouseId):
13149 manish.sha 1295
    itemIds = []
5944 mandeep.dh 1296
    for currentInventorySnapshot in CurrentInventorySnapshot.query.filter_by(warehouse_id=warehouseId).all():
1297
        currentInventorySnapshot.availability = 0
13149 manish.sha 1298
        itemIds.append(currentInventorySnapshot.item_id)
1299
    clear_item_availability_cache(itemIds) 
5944 mandeep.dh 1300
    session.commit()
1301
 
7718 amar.kumar 1302
def get_our_warehouse_id_for_vendor(vendor_id, billing_warehouse_id):
6467 amar.kumar 1303
    try:
7718 amar.kumar 1304
        warehouse = Warehouse.query.filter_by(vendor_id = vendor_id, warehouseType = 'OURS', inventoryType = 'GOOD', billingWarehouseId = billing_warehouse_id).first()
6467 amar.kumar 1305
        return warehouse.id
1306
    except Exception as e:
1307
        print e;
7755 amar.kumar 1308
        raise InventoryServiceException(101, 'No our warehouse found for vendorId: ' + str(vendor_id))
5944 mandeep.dh 1309
 
1310
def __send_mail(subject, message):
1311
    try:
6029 rajveer 1312
        thread = threading.Thread(target=partial(mail, mail_user, mail_password, to_addresses, subject, message))
5944 mandeep.dh 1313
        thread.start()
1314
    except Exception as ex:
1315
        print ex    
1316
 
1317
def get_shipping_locations():
1318
    shippingLocationIds = {}
1319
    warehouses = Warehouse.query.all()
1320
    for warehouse in warehouses:
1321
        if warehouse.shippingWarehouseId:
1322
            shippingLocationIds[warehouse.shippingWarehouseId] = 1
1323
 
1324
    shippingLocations = []
1325
    for shippingLocationId in shippingLocationIds:
1326
        shippingLocations.append(get_Warehouse(shippingLocationId))
1327
 
1328
    return shippingLocations
1329
 
1330
def get_inventory_snapshot(warehouseId):
1331
    query = CurrentInventorySnapshot.query
1332
 
1333
    if warehouseId:
1334
        query = query.filter_by(warehouse_id = warehouseId)
1335
 
1336
    itemInventoryMap = {}
1337
    for row in query.all():
1338
        if not itemInventoryMap.has_key(row.item_id):
1339
            itemInventoryMap[row.item_id] = []
1340
 
1341
        itemInventoryMap[row.item_id].append(row)
1342
 
1343
    return itemInventoryMap
1344
 
1345
def update_vendor_string(warehouseId, vendorString):
1346
    warehouse = get_Warehouse(warehouseId)
1347
    warehouse.vendorString = vendorString
1348
    session.commit()
1349
 
1350
def __get_item_from_master(item_id):
1351
    client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
5978 rajveer 1352
    return client.getItem(item_id)
1353
 
1354
def __check_risky_item(item_id, source_id):
1355
    ## We should get the list of strings which will identify to the catalog servers
1356
    if source_id == 1:
1357
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
1358
        client.validateRiskyStatus(item_id)
1359
    if source_id == 2:
1360
        client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
1361
        client.validateRiskyStatus(item_id)
1362
 
1363
def __get_item_from_source(item_id, source_id):
1364
    if source_id == 1:
1365
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
1366
        return client.getItem(item_id)
1367
    if source_id == 2:
1368
        client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
6531 vikram.rag 1369
        return client.getItem(item_id)
1370
 
1371
def get_monitored_warehouses_for_vendors(vendorIds):
1372
    w = []
1373
    for wh in Warehouse.query.filter_by(isAvailabilityMonitored = 1).all():
1374
        if wh.vendor.id in (vendorIds):
1375
            w.append(to_t_warehouse(wh).id)
1376
    return w
1377
def get_ignored_warehouseids_and_itemids():
1378
    iw = []
1379
    for i in IgnoredInventoryUpdateItems.query.all():
1380
        iw.append(to_t_itemidwarehouseid(i)) 
1381
    return iw
1382
def insert_item_to_ignore_inventory_update_list(item_id,warehouse_id):
1383
    try:
1384
        ds_warehouse=IgnoredInventoryUpdateItems()
1385
        ds_warehouse.item_id=item_id
1386
        ds_warehouse.warehouse_id=warehouse_id
6532 amit.gupta 1387
        clear_item_availability_cache(item_id)
6531 vikram.rag 1388
        session.commit()
1389
        return True
1390
    except:
1391
        return False       
1392
def delete_item_from_ignore_inventory_update_list(item_id,warehouse_id):
1393
    try:
1394
        session.query(IgnoredInventoryUpdateItems).filter_by(item_id=item_id,warehouse_id=warehouse_id).delete()
6532 amit.gupta 1395
        clear_item_availability_cache(item_id)
6531 vikram.rag 1396
        session.commit()
1397
        return True
1398
    except:
1399
        return False           
1400
 
1401
def get_all_ignored_inventoryupdate_items_count():
1402
    return  session.query(func.count(distinct(IgnoredInventoryUpdateItems.item_id))).scalar()
1403
 
1404
def get_ignored_inventoryupdate_itemids(offset=0,limit=None):
1405
    itemIds = session.query(distinct(IgnoredInventoryUpdateItems.item_id))
1406
    '''if limit is not None:
1407
        itemIds = itemIds.limit(limit)'''
1408
    print itemIds.all()
1409
    return [id for (id, ) in itemIds.all()]
6821 amar.kumar 1410
 
1411
def update_item_stock_purchase_params(item_id, numOfDaysStock, minStockLevel):
1412
    if numOfDaysStock is None or minStockLevel is None:
1413
        raise InventoryServiceException(108, "Bad params : numOfDaysStock = " + str(numOfDaysStock) + "minStockLevel = " + str(minStockLevel))
1414
    itemStockPurchaseParams = ItemStockPurchaseParams.query.filter_by(item_id = item_id).first()
1415
    if itemStockPurchaseParams is None:
1416
        itemStockPurchaseParams = ItemStockPurchaseParams()
1417
    itemStockPurchaseParams.item_id = item_id
1418
    itemStockPurchaseParams.numOfDaysStock = numOfDaysStock
1419
    itemStockPurchaseParams.minStockLevel = minStockLevel
1420
    session.commit()
1421
 
1422
def get_item_stock_purchase_params(item_id):
1423
    return ItemStockPurchaseParams.query.filter_by(item_id = item_id).first()
1424
 
1425
def add_oos_status_for_item(oosStatusMap, date):
1426
 
1427
    oosDate = to_py_date(date)
1428
    oosDate.replace(second=0, microsecond=0)
1429
 
1430
    cartAdditionStartDate = oosDate - datetime.timedelta(days = 1)
1431
 
1432
    client = TransactionClient().get_client()
1433
 
1434
    #Gets physical orders in the last day
1435
    orders = client.getPhysicalOrders(to_java_date(cartAdditionStartDate), to_java_date(oosDate))
8019 amar.kumar 1436
    rtoOrders = client.getAllOrders([20], 0, 0, 0)
9665 rajveer 1437
    orderCountByItemIdSourceId = {}
1438
    rtoOrderCountByItemIdSourceId = {}
1439
 
6821 amar.kumar 1440
    for order in orders:
9665 rajveer 1441
        if not orderCountByItemIdSourceId.has_key(order.lineitems[0].item_id):
1442
            orderCountByItemIdSourceId[order.lineitems[0].item_id] = {}
1443
 
1444
        if orderCountByItemIdSourceId[order.lineitems[0].item_id].has_key(order.source):
18430 manish.sha 1445
            orderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = orderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] + order.lineitems[0].quantity
6821 amar.kumar 1446
        else:
18430 manish.sha 1447
            orderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = order.lineitems[0].quantity
9665 rajveer 1448
 
8019 amar.kumar 1449
 
1450
    for order in rtoOrders:
9665 rajveer 1451
        if not rtoOrderCountByItemIdSourceId.has_key(order.lineitems[0].item_id):
1452
            rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id] = {}
1453
 
1454
        if rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id].has_key(order.source):
18430 manish.sha 1455
            rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] + order.lineitems[0].quantity 
8019 amar.kumar 1456
        else:
18430 manish.sha 1457
            rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = order.lineitems[0].quantity
9665 rajveer 1458
 
1459
 
6821 amar.kumar 1460
    for itemId, status in oosStatusMap.iteritems():
9665 rajveer 1461
        total_order_count = 0 
9791 rajveer 1462
        total_rto_count = 0
13726 manish.sha 1463
        for sid in (1,3,4,6,7,8):
6821 amar.kumar 1464
            oosStatus = OOSStatus()
1465
            oosStatus.item_id = itemId
1466
            oosStatus.date = oosDate
9791 rajveer 1467
            oosStatus.sourceId  = sid
1468
            order_count = 0
1469
            rto_count = 0
1470
            if orderCountByItemIdSourceId.has_key(itemId) and orderCountByItemIdSourceId[itemId].has_key(sid):
1471
                order_count = orderCountByItemIdSourceId[itemId][sid]
1472
            if rtoOrderCountByItemIdSourceId.has_key(itemId) and rtoOrderCountByItemIdSourceId[itemId].has_key(sid):
18430 manish.sha 1473
                rto_count = rtoOrderCountByItemIdSourceId[itemId][sid]
9791 rajveer 1474
            oosStatus.num_orders = order_count
1475
            oosStatus.rto_orders = rto_count
9666 rajveer 1476
            oosStatus.is_oos = status
9791 rajveer 1477
            if oosStatus.is_oos and order_count > 0:
1478
                oosStatus.is_oos = False
1479
            total_order_count = total_order_count + order_count
1480
            total_rto_count = total_rto_count + rto_count
1481
        oosStatus = OOSStatus()
1482
        oosStatus.item_id = itemId
1483
        oosStatus.date = oosDate
1484
        oosStatus.sourceId  = 0
1485
        oosStatus.num_orders = total_order_count
1486
        oosStatus.rto_orders = total_rto_count
9804 rajveer 1487
        if itemId in orderCountByItemIdSourceId and 1 in orderCountByItemIdSourceId[itemId]:
1488
            order_count = orderCountByItemIdSourceId[itemId][1]
9791 rajveer 1489
        oosStatus.is_oos = status
1490
        if oosStatus.is_oos and order_count > 0:
1491
            oosStatus.is_oos = False
6821 amar.kumar 1492
 
9791 rajveer 1493
        session.commit()
1494
 
9861 rajveer 1495
 
1496
    itemCountMap = {}
1497
    oosDate = oosDate - datetime.timedelta(days = 1) - datetime.timedelta(hours = 1)
1498
    lines = session.query(OOSStatus.item_id, func.sum(OOSStatus.num_orders)/func.count(OOSStatus.num_orders)).filter(OOSStatus.date >= oosDate).filter(OOSStatus.sourceId == 1).filter(OOSStatus.is_oos == 0).group_by(OOSStatus.item_id).all()
1499
    for line in lines:
1500
        item_id = line[0]
9896 rajveer 1501
        quantity = int(math.ceil(max(1,2*line[1])))
9861 rajveer 1502
        itemCountMap[item_id] = quantity
9862 rajveer 1503
    cl = CatalogClient('catalog_service_server_host_prod','catalog_service_server_port').get_client()
9861 rajveer 1504
    cl.updateItemHoldInventory(itemCountMap)
9791 rajveer 1505
 
9665 rajveer 1506
def get_oos_statuses_for_x_days_for_item(itemId, sourceId, days):
6832 amar.kumar 1507
    timestamp = datetime.datetime.now()
9640 amar.kumar 1508
    timestamp = timestamp - datetime.timedelta(days = days)
9665 rajveer 1509
    return OOSStatus.query.filter_by(item_id = itemId).filter_by(sourceId = sourceId).filter(OOSStatus.date > timestamp).all()
6857 amar.kumar 1510
 
10126 amar.kumar 1511
def get_oos_statuses_for_x_days(sourceId, days):
1512
    timestamp = datetime.datetime.now()
1513
    timestamp = timestamp - datetime.timedelta(days = days)
1514
    if sourceId == -1:
1515
        return OOSStatus.query.filter(OOSStatus.date > timestamp).all()
1516
    else:
1517
        return OOSStatus.query.filter_by(sourceId = sourceId).filter(OOSStatus.date > timestamp).all()
1518
 
6857 amar.kumar 1519
def get_non_zero_item_stock_purchase_params():
7281 kshitij.so 1520
    return ItemStockPurchaseParams.query.filter(or_("numOfDaysStock!=0","minStockLevel!=0"))
1521
 
7972 amar.kumar 1522
def get_last_n_day_sale_for_item(itemId, numberOfDays):
1523
    lastNdaySale = ""
9685 rajveer 1524
    oosStatuses = get_oos_statuses_for_x_days_for_item(itemId, 0, numberOfDays)
7972 amar.kumar 1525
    for oosStatus in oosStatuses:
1526
        if oosStatus.is_oos == True:
1527
            lastNdaySale +="X-"
1528
        else:
1529
            lastNdaySale +=str(oosStatus.num_orders) + "-"
1530
    return lastNdaySale[:-1] 
1531
 
7281 kshitij.so 1532
def get_warehouse_name(warehouseId):
1533
    row = Warehouse.get_by(id = warehouseId)
1534
    return row.displayName
1535
 
1536
def get_amazon_inventory_for_item(amazonItemId):
1537
    inventory = AmazonInventorySnapshot.get_by(item_id=amazonItemId)
1538
    return inventory
1539
 
1540
def get_all_amazon_inventory():
1541
    return session.query(AmazonInventorySnapshot).all()
1542
 
10450 vikram.rag 1543
def add_or_update_amazon_inventory_for_item(amazoninventorysnapshot,time):
7281 kshitij.so 1544
    inventory = AmazonInventorySnapshot.get_by(item_id = amazoninventorysnapshot.item_id)
1545
    if inventory is None:
1546
        amazon_inventory = AmazonInventorySnapshot()
1547
        amazon_inventory.item_id = amazoninventorysnapshot.item_id
1548
        amazon_inventory.availability = amazoninventorysnapshot.availability
1549
        amazon_inventory.reserved = amazoninventorysnapshot.reserved
10450 vikram.rag 1550
        amazon_inventory.is_oos = amazoninventorysnapshot.is_oos
1551
        if time != 0:
1552
            amazon_inventory.lastUpdatedOnAmazon = to_py_date(time)
1553
    else: 
7281 kshitij.so 1554
        inventory.availability = amazoninventorysnapshot.availability
1555
        inventory.reserved = amazoninventorysnapshot.reserved
10450 vikram.rag 1556
        if not inventory.is_oos and (to_py_date(time) - inventory.lastUpdatedOnAmazon).days == 0:
1557
            pass
1558
        else:
1559
            inventory.is_oos = amazoninventorysnapshot.is_oos
1560
        if time != 0:    
1561
            inventory.lastUpdatedOnAmazon = to_py_date(time)      
7281 kshitij.so 1562
    session.commit()
1563
 
8182 amar.kumar 1564
def add_update_hold_inventory(itemId, warehouseId, holdQuantity, source):
9762 amar.kumar 1565
    if holdQuantity <0:
1566
        print "Negative holdQuantity : " + str(holdQuantity) + " is not allowed"
1567
        raise InventoryServiceException(108, "Negative heldQuantity is not allowed")
8197 amar.kumar 1568
    hold_inventory_detail = HoldInventoryDetail.get_by(item_id = itemId, warehouse_id=warehouseId, source = source)
1569
    if  hold_inventory_detail is None:
8182 amar.kumar 1570
        diffTobeAddedInCIS = holdQuantity
1571
        hold_inventory_detail = HoldInventoryDetail()
1572
        hold_inventory_detail.item_id = itemId 
1573
        hold_inventory_detail.warehouse_id = warehouseId 
1574
        hold_inventory_detail.held = holdQuantity 
1575
        hold_inventory_detail.source = source
1576
    else:
8497 amar.kumar 1577
        diffTobeAddedInCIS = holdQuantity - hold_inventory_detail.held
8182 amar.kumar 1578
        hold_inventory_detail.held = holdQuantity
1579
 
1580
    current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
1581
    if not current_inventory_snapshot:
1582
        current_inventory_snapshot = CurrentInventorySnapshot()
1583
        current_inventory_snapshot.item_id = itemId
1584
        current_inventory_snapshot.warehouse_id = warehouseId
1585
        current_inventory_snapshot.availability = 0
1586
        current_inventory_snapshot.reserved = 0
1587
        current_inventory_snapshot.held = 0
1588
    current_inventory_snapshot.held = current_inventory_snapshot.held + diffTobeAddedInCIS
1589
    session.commit()
1590
    #**Update item availability cache**#
1591
    clear_item_availability_cache(itemId)
8282 kshitij.so 1592
 
1593
def add_or_update_amazon_fba_inventory(amazonfbainventorysnapshot):
11173 vikram.rag 1594
    inventory = AmazonFbaInventorySnapshot.query.filter_by(item_id = amazonfbainventorysnapshot.item_id,location=amazonfbainventorysnapshot.location).first()
8282 kshitij.so 1595
    if inventory is None:
1596
        amazon_fba_inventory = AmazonFbaInventorySnapshot()
1597
        amazon_fba_inventory.item_id = amazonfbainventorysnapshot.item_id
1598
        amazon_fba_inventory.availability = amazonfbainventorysnapshot.availability
11173 vikram.rag 1599
        amazon_fba_inventory.location = amazonfbainventorysnapshot.location
1600
        amazon_fba_inventory.reserved = amazonfbainventorysnapshot.reserved
1601
        amazon_fba_inventory.inbound = amazonfbainventorysnapshot.inbound
1602
        amazon_fba_inventory.unfulfillable = amazonfbainventorysnapshot.unfulfillable
1603
 
8282 kshitij.so 1604
    else:
11173 vikram.rag 1605
        print 'updating'
8282 kshitij.so 1606
        inventory.availability = amazonfbainventorysnapshot.availability
11173 vikram.rag 1607
        inventory.location = amazonfbainventorysnapshot.location
1608
        inventory.reserved = amazonfbainventorysnapshot.reserved
1609
        inventory.inbound = amazonfbainventorysnapshot.inbound
1610
        inventory.unfulfillable = amazonfbainventorysnapshot.unfulfillable
8282 kshitij.so 1611
 
1612
 
1613
def get_amazon_fba_inventory(itemId):
11173 vikram.rag 1614
    return AmazonFbaInventorySnapshot.query.filter_by(item_id = itemId)
8282 kshitij.so 1615
 
8363 vikram.rag 1616
def get_all_amazon_fba_inventory():
1617
    return AmazonFbaInventorySnapshot.query.all() 
1618
 
12799 manish.sha 1619
def get_oursgood_warehouseids_for_location(stateId):
8363 vikram.rag 1620
    warehouseId=[]
12799 manish.sha 1621
    x= session.query(Warehouse.id).filter(Warehouse.id==Warehouse.billingWarehouseId).filter(Warehouse.warehouseType=='OURS').filter(Warehouse.state_id==stateId).all()
8363 vikram.rag 1622
    for id in x:
1623
        warehouseId.append(id[0])
1624
    return session.query(Warehouse.id).filter(Warehouse.inventoryType=='GOOD').filter(Warehouse.warehouseType=='OURS').filter(Warehouse.billingWarehouseId.in_(warehouseId)).all()
8954 vikram.rag 1625
 
1626
def get_holdinventorydetail_forItem_forWarehouseId_exceptsource(item_id,warehouse_id,source):
1627
    holddetails = HoldInventoryDetail.query.filter(HoldInventoryDetail.item_id == item_id).all()
1628
    print holddetails
1629
    hold = 0
1630
    for holddetail in holddetails:
1631
        if holddetail.source !=source and holddetail.warehouse_id == warehouse_id:
1632
            hold = hold + holddetail.held
9404 vikram.rag 1633
    return hold
1634
 
1635
def get_snapdeal_inventory_for_item(id):
1636
    print SnapdealInventorySnapshot.get_by(item_id = id)
1637
    return SnapdealInventorySnapshot.get_by(item_id = id)
1638
 
1639
def add_or_update_snapdeal_inventor_for_item(snapdealinventoryitem):
1640
    snapdeal_inventory_item = SnapdealInventorySnapshot.get_by(item_id = snapdealinventoryitem.item_id)
1641
    if snapdeal_inventory_item is None:
1642
        snapdeal_inventory_item = SnapdealInventorySnapshot()
1643
        snapdeal_inventory_item.item_id = snapdealinventoryitem.item_id
1644
        snapdeal_inventory_item.availability = snapdealinventoryitem.availability
9495 vikram.rag 1645
        snapdeal_inventory_item.pendingOrders = snapdealinventoryitem.pendingOrders
9404 vikram.rag 1646
        snapdeal_inventory_item.lastUpdatedOnSnapdeal = to_py_date(snapdealinventoryitem.lastUpdatedOnSnapdeal)
10450 vikram.rag 1647
        snapdeal_inventory_item.is_oos = snapdealinventoryitem.is_oos
9404 vikram.rag 1648
    else:
1649
        snapdeal_inventory_item.availability = snapdealinventoryitem.availability
9495 vikram.rag 1650
        snapdeal_inventory_item.pendingOrders = snapdealinventoryitem.pendingOrders
10450 vikram.rag 1651
        if not snapdeal_inventory_item.is_oos and (to_py_date(snapdealinventoryitem.lastUpdatedOnSnapdeal) - snapdeal_inventory_item.lastUpdatedOnSnapdeal).days == 0:
1652
            pass
1653
        else:
1654
            snapdeal_inventory_item.is_oos = snapdealinventoryitem.is_oos
9404 vikram.rag 1655
        snapdeal_inventory_item.lastUpdatedOnSnapdeal = to_py_date(snapdealinventoryitem.lastUpdatedOnSnapdeal)
1656
    session.commit()
8954 vikram.rag 1657
 
9404 vikram.rag 1658
def get_nlc_for_warehouse(warehouse_id,itemid):
1659
    warehouse = Warehouse.get_by(id=warehouse_id)
1660
    if warehouse is None:
1661
        return 0
1662
    vendoritempricing = VendorItemPricing.query.filter_by(item_id=itemid, vendor_id=warehouse.vendor_id).first()
1663
    '''vendoritempricing = VendorItemPricing.get_by(id=warehouse.vendor_id,item_id=itemid)'''
1664
    if vendoritempricing is None:
1665
        return 0
9456 vikram.rag 1666
    return vendoritempricing.nlc
1667
 
9495 vikram.rag 1668
def get_snapdeal_inventory_snapshot():
9640 amar.kumar 1669
    return SnapdealInventorySnapshot.query.all()
10050 vikram.rag 1670
 
9640 amar.kumar 1671
def get_held_inventory_map_for_item(itemId, warehouseId):
1672
    heldInventoryMap = {}
1673
    holdInventories = HoldInventoryDetail.query.filter_by(item_id= itemId, warehouse_id = warehouseId).all()
1674
    for holdInventory in holdInventories:
1675
        heldInventoryMap[holdInventory.source] = holdInventory.held
1676
    return heldInventoryMap 
10050 vikram.rag 1677
 
9761 amar.kumar 1678
def get_hold_inventory_details(itemId, warehouseId, source):
1679
    heldInventoryQuery = HoldInventoryDetail.query
1680
    if itemId:
1681
        heldInventoryQuery = heldInventoryQuery.filter_by(item_id = itemId)
1682
    if warehouseId:
1683
        heldInventoryQuery = heldInventoryQuery.filter_by(warehouse_id = warehouseId)
1684
    if source:
1685
        heldInventoryQuery = heldInventoryQuery.filter_by(source = source)
1686
    holdInventoryDetails = heldInventoryQuery.all()
1687
    return holdInventoryDetails
9896 rajveer 1688
 
10450 vikram.rag 1689
def add_or_update_flipkart_inventory_snapshot(flipkartInventorySnapshot,time):
10050 vikram.rag 1690
    for snapshot in flipkartInventorySnapshot:
1691
        flipkart_inventory = FlipkartInventorySnapshot.get_by(item_id = snapshot.item_id)
1692
        if flipkart_inventory is None:
1693
            flipkart_inventory = FlipkartInventorySnapshot()
1694
            flipkart_inventory.item_id = snapshot.item_id
1695
            flipkart_inventory.availability = snapshot.availability
1696
            flipkart_inventory.createdOrders = snapshot.createdOrders
1697
            flipkart_inventory.heldOrders = snapshot.heldOrders
10450 vikram.rag 1698
            flipkart_inventory.is_oos = snapshot.is_oos
1699
            flipkart_inventory.lastUpdatedOnFlipkart = to_py_date(time) 
10050 vikram.rag 1700
        else:
1701
            flipkart_inventory.availability = snapshot.availability
1702
            flipkart_inventory.createdOrders = snapshot.createdOrders
1703
            flipkart_inventory.heldOrders = snapshot.heldOrders
10450 vikram.rag 1704
            if not flipkart_inventory.is_oos and (to_py_date(time) - flipkart_inventory.lastUpdatedOnFlipkart).days == 0:
1705
                pass
1706
            else:
1707
                flipkart_inventory.is_oos = snapshot.is_oos
1708
            flipkart_inventory.lastUpdatedOnFlipkart = to_py_date(time) 
10050 vikram.rag 1709
    session.commit()
1710
 
1711
def get_flipkart_inventory_snapshot():
1712
    return FlipkartInventorySnapshot.query.all()     
1713
 
10097 kshitij.so 1714
def get_flipkart_inventory_for_Item(itemId):
10485 vikram.rag 1715
    return FlipkartInventorySnapshot.get_by(item_id = itemId)
1716
 
1717
def get_state_master():
1718
    stateIdNameMap = {} 
1719
    statemaster = StateMaster.query.all()
1720
    for state in statemaster:
12280 amit.gupta 1721
        stateIdNameMap[state.id] = to_t_state(state)
10544 vikram.rag 1722
    return stateIdNameMap    
1723
 
1724
def update_snapdeal_stock_at_eod(allsnapdealstock):
1725
    for stockitem in allsnapdealstock:
1726
        snapdealstockateod = SnapdealStockAtEOD()
1727
        snapdealstockateod.item_id = stockitem.item_id
1728
        snapdealstockateod.availability = stockitem.availability
1729
        snapdealstockateod.date =  to_py_date(stockitem.date)
1730
    session.commit()
1731
 
1732
def update_flipkart_stock_at_eod(allflipkartstock):
1733
    for stockitem in allflipkartstock:
1734
        snapdealstockateod = FlipkartStockAtEOD()
1735
        snapdealstockateod.item_id = stockitem.item_id
1736
        snapdealstockateod.availability = stockitem.availability
1737
        snapdealstockateod.date =  to_py_date(stockitem.date)
1738
    session.commit()
10687 rajveer 1739
 
12363 kshitij.so 1740
def get_wanlc_for_source(item_id,sourceId):
1741
    stockWanlc = StockWeightedNlcInfo.query.filter(StockWeightedNlcInfo.itemId==item_id).filter(StockWeightedNlcInfo.source==sourceId).order_by(desc(StockWeightedNlcInfo.updatedTimestamp)).limit(1).all()
1742
    if stockWanlc is None or len(stockWanlc)==0:
1743
        return 0.0
1744
    else:
1745
        return stockWanlc[0].avgWeightedNlc
1746
 
1747
def get_all_available_amazon_inventory():
19247 kshitij.so 1748
    return AmazonFbaInventorySnapshot.query.filter(AmazonFbaInventorySnapshot.availability>0).all()
1749
 
1750
def add_vendor_item_pricing_in_bulk(vendorItemPricingList):
1751
    exceptionItems = []
1752
    for vendorItemPricing in vendorItemPricingList:
1753
        try:
1754
            add_vendor_pricing(vendorItemPricing, False)
1755
        except:
1756
            exceptionItems.append(vendorItemPricing.itemId)
1757
    return exceptionItems
1758
 
1759
def add_inventory_in_bulk(bulkInventoryList):
1760
    for item in bulkInventoryList:
19989 kshitij.so 1761
        add_inventory(item.item_id, item.warehouse_id, item.inventory, True)
19247 kshitij.so 1762
 
1763
 
23316 amit.gupta 1764
 
1765
#from shop2020.clients.TransactionClient import TransactionClient
1766
#from shop2020.thriftpy.model.v1.order.ttypes import OrderType, OrderSource, TransactionStatus
1767
#from shop2020.thriftpy.logistics.ttypes import LocationInfo, PickUpType
1768
#tc = TransactionClient().get_client()
1769
#tc.changeTransactionStatus(1037182, TransactionStatus.COD_IN_PROCESS, 'Cod Payment Awaited', PickUpType.COURIER, OrderType.B2C, OrderSource.WEBSITE)