Subversion Repositories SmartDukaan

Rev

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

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