Subversion Repositories SmartDukaan

Rev

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

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