Subversion Repositories SmartDukaan

Rev

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