Subversion Repositories SmartDukaan

Rev

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

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