Subversion Repositories SmartDukaan

Rev

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