Subversion Repositories SmartDukaan

Rev

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

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