Subversion Repositories SmartDukaan

Rev

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

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