Subversion Repositories SmartDukaan

Rev

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

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