Subversion Repositories SmartDukaan

Rev

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