Subversion Repositories SmartDukaan

Rev

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