Subversion Repositories SmartDukaan

Rev

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