Subversion Repositories SmartDukaan

Rev

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