Subversion Repositories SmartDukaan

Rev

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