Subversion Repositories SmartDukaan

Rev

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