Subversion Repositories SmartDukaan

Rev

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

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