Subversion Repositories SmartDukaan

Rev

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