Subversion Repositories SmartDukaan

Rev

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

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