Subversion Repositories SmartDukaan

Rev

Rev 12799 | Rev 12976 | 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
5944 mandeep.dh 9
from shop2020.clients.TransactionClient import TransactionClient
10
from shop2020.model.v1.inventory.impl import DataService
6531 vikram.rag 11
from shop2020.model.v1.inventory.impl.Convertors import to_t_warehouse, \
12280 amit.gupta 12
    to_t_itemidwarehouseid, to_t_state
5944 mandeep.dh 13
from shop2020.model.v1.inventory.impl.DataService import Warehouse, \
14
    ItemInventoryHistory, CurrentInventorySnapshot, VendorItemPricing, \
15
    VendorItemMapping, Vendor, MissedInventoryUpdate, BadInventorySnapshot, \
8491 rajveer 16
    VendorHolidays, ItemAvailabilityCache, \
7410 amar.kumar 17
    CurrentReservationSnapshot, IgnoredInventoryUpdateItems, ItemStockPurchaseParams, \
9404 vikram.rag 18
    OOSStatus, AmazonInventorySnapshot, StateMaster, HoldInventoryDetail, AmazonFbaInventorySnapshot, \
12363 kshitij.so 19
    SnapdealInventorySnapshot, FlipkartInventorySnapshot, SnapdealStockAtEOD, FlipkartStockAtEOD, StockWeightedNlcInfo
6531 vikram.rag 20
from shop2020.thriftpy.model.v1.inventory.ttypes import \
21
    InventoryServiceException, HolidayType, InventoryType, WarehouseType
5944 mandeep.dh 22
from shop2020.thriftpy.model.v1.order.ttypes import AlertType
6531 vikram.rag 23
from shop2020.thriftpy.purchase.ttypes import PurchaseServiceException
5944 mandeep.dh 24
from shop2020.utils import EmailAttachmentSender
25
from shop2020.utils.EmailAttachmentSender import mail
6821 amar.kumar 26
from shop2020.utils.Utils import to_py_date, to_java_date
5944 mandeep.dh 27
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
7410 amar.kumar 28
from sqlalchemy.sql import or_
12363 kshitij.so 29
from sqlalchemy.sql.expression import and_, func, distinct, desc
6531 vikram.rag 30
from sqlalchemy.sql.functions import count
5944 mandeep.dh 31
import calendar
32
import datetime
33
import sys
34
import threading
9861 rajveer 35
import math
5944 mandeep.dh 36
 
10687 rajveer 37
to_addresses = ["khushal.bhatia@shop2020.in", "chaitnaya.vats@shop2020.in", "chandan.kumar@shop2020.in",'manoj.kumar@shop2020.in']
6029 rajveer 38
mail_user = "cnc.center@shop2020.in"
39
mail_password = "5h0p2o2o"
5944 mandeep.dh 40
skippedItems = { 175 : [27, 2160, 2175, 2163, 2158, 7128, 26, 2154],
41
                 193 : [5839] }
42
 
6821 amar.kumar 43
OOS_CALCULATION_TIME = 23
6498 vikram.rag 44
 
5944 mandeep.dh 45
def initialize(dbname='inventory', db_hostname="localhost"):
46
    DataService.initialize(dbname, db_hostname)
47
 
48
def get_Warehouse(warehouse_id):
49
    return Warehouse.get_by(id=warehouse_id)
50
 
51
def get_vendor(vendorId):
52
    return Vendor.get_by(id=vendorId)
53
 
7410 amar.kumar 54
def get_state(stateId):
55
    return StateMaster.get_by(id=stateId)
56
 
5944 mandeep.dh 57
def get_all_warehouses_by_status(status):
58
    return Warehouse.query.all()
59
 
60
def get_all_items_for_warehouse(warehouse_id):
61
    warehouse = get_Warehouse(warehouse_id)
62
    if not warehouse:
63
        raise InventoryServiceException(108, "bad warehouse")
64
    return warehouse.all_items
65
 
66
def add_warehouse(warehouse):
67
    if not warehouse:
68
        raise InventoryServiceException(108, "Bad warehouse")
69
    if get_Warehouse(warehouse.id):
70
        #warehouse is already present.
71
        raise InventoryServiceException(101, "Warehouse already present")
72
 
73
    ds_warehouse = Warehouse()
74
    ds_warehouse.location = warehouse.location
75
    ds_warehouse.status = 3
76
    ds_warehouse.addedOn = datetime.datetime.now()
77
    ds_warehouse.lastCheckedOn = datetime.datetime.now()
78
    ds_warehouse.tinNumber = warehouse.tinNumber
79
    ds_warehouse.pincode = warehouse.pincode
80
    ds_warehouse.billingType = warehouse.billingType
81
    ds_warehouse.billingWarehouseId = warehouse.billingWarehouseId
82
    ds_warehouse.displayName = warehouse.displayName
83
    ds_warehouse.inventoryType = InventoryType._VALUES_TO_NAMES[warehouse.inventoryType]
84
    ds_warehouse.isAvailabilityMonitored = warehouse.isAvailabilityMonitored
85
    ds_warehouse.logisticsLocation = warehouse.logisticsLocation
86
    ds_warehouse.shippingWarehouseId = warehouse.shippingWarehouseId
87
    ds_warehouse.transferDelayInHours = warehouse.transferDelayInHours
88
    ds_warehouse.vendor = get_vendor(warehouse.vendor.id)
7410 amar.kumar 89
    ds_warehouse.state = get_state(warehouse.stateId)
5944 mandeep.dh 90
    ds_warehouse.warehouseType = WarehouseType._VALUES_TO_NAMES[warehouse.warehouseType]    
91
    if warehouse.vendorString:
92
        ds_warehouse.vendorString = warehouse.vendorString
93
    session.commit()
94
    return ds_warehouse.id
95
 
6498 vikram.rag 96
def get_ignored_items(warehouse_id): 
6531 vikram.rag 97
    Ignored_inventory_items = IgnoredInventoryUpdateItems.query.filter_by(warehouse_id=warehouse_id).all()
6498 vikram.rag 98
    negativeItems = []
99
    for Ignored_inventory_item in Ignored_inventory_items:
100
        try:
101
            item_id = Ignored_inventory_item.item_id
102
            negativeItems.append(item_id)
103
        except:
104
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
105
    return negativeItems
106
 
6510 rajveer 107
def get_ignored_warehouses(item_id): 
6539 amit.gupta 108
    Ignored_inventory_items = IgnoredInventoryUpdateItems.query.filter_by(item_id=item_id).all()
6510 rajveer 109
    warehouses = []
110
    for Ignored_inventory_item in Ignored_inventory_items:
111
        warehouses.append(Ignored_inventory_item.warehouse_id)
112
    return warehouses
113
 
5944 mandeep.dh 114
def update_inventory_history(warehouse_id, timestamp, availability):
115
    warehouse = get_Warehouse(warehouse_id)
116
    if not warehouse:
117
        raise InventoryServiceException(107, "Warehouse? Where?")
118
    vendor = warehouse.vendor
119
    time = datetime.datetime.now()
120
    for item_key, quantity in availability.iteritems():
121
        try:
122
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
5960 mandeep.dh 123
            item_id = vendor_item_mapping.item_id
5944 mandeep.dh 124
        except:
6531 vikram.rag 125
            continue  
5944 mandeep.dh 126
        try:
6510 rajveer 127
            item_inventory_history = ItemInventoryHistory()
128
            item_inventory_history.warehouse = warehouse
129
            item_inventory_history.item_id = item_id
130
            item_inventory_history.timestamp = time
131
            item_inventory_history.availability = quantity
5944 mandeep.dh 132
        except:
133
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
134
    session.commit()
135
 
136
def update_inventory(warehouse_id, timestamp, availability):
137
    warehouse = get_Warehouse(warehouse_id)
138
    if not warehouse:
139
        raise InventoryServiceException(107, "Warehouse? Where?")
6510 rajveer 140
 
5944 mandeep.dh 141
    time = datetime.datetime.now()
142
    warehouse.lastCheckedOn = time
143
    warehouse.vendorString = timestamp
144
    vendor = warehouse.vendor
145
    item_ids = []
146
    for item_key, quantity in availability.iteritems():
147
        try:
148
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
149
            item_id = vendor_item_mapping.item_id
6510 rajveer 150
            item_ids.append(item_id)
5944 mandeep.dh 151
        except:
152
            print 'Skipping update for ' + item_key + ' quantity ' + str(quantity) + ' warehouse id: ' + str(warehouse_id)
153
            __send_mail_for_missing_key(item_key, quantity, warehouse_id)
154
            continue
155
        try:
156
            current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=item_id, warehouse=warehouse)
157
            if not current_inventory_snapshot:
158
                current_inventory_snapshot = CurrentInventorySnapshot()
159
                current_inventory_snapshot.item_id = item_id
160
                current_inventory_snapshot.warehouse = warehouse
161
                current_inventory_snapshot.availability = 0
162
                current_inventory_snapshot.reserved = 0
8204 amar.kumar 163
                current_inventory_snapshot.held = 0
5944 mandeep.dh 164
            # added the difference in the current inventory    
165
            current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
166
            item = __get_item_from_master(item_id)
167
            try:
168
                if quantity > 0 and __get_item_reserved(item_id) > 0:
169
                    cl = TransactionClient().get_client()
170
                    #FIXME hardcoding for warehouse id 
171
                    cl.addAlert(AlertType.NEW_INVENTORY_ALERT, 5, "Inventory received for item " + item.brand + " " + item.modelName + " " + item.modelNumber + " " +  item.color)
172
            except:
173
                print "Not able to raise alert for incoming inventory" 
174
            if current_inventory_snapshot.availability < 0:
175
                __send_alert_for_negative_availability(item, current_inventory_snapshot.availability, warehouse)
176
        except:
177
            print "Some unforeseen error while updating inventory:", sys.exc_info()[0]
178
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
179
    session.commit()
180
 
181
    #**Update item availability cache**#
182
    for item_id in item_ids:
5978 rajveer 183
        clear_item_availability_cache(item_id)
5944 mandeep.dh 184
 
185
def __send_alert_for_negative_reserved(item, reserved, warehouse):
186
    itemName = " ".join([str(item.id), str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
10253 manish.sha 187
    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 188
 
189
def __send_alert_for_negative_availability(item, availability, warehouse):
190
    itemName = " ".join([str(item.id), str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
5964 amar.kumar 191
    # 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 192
 
193
def __send_mail_for_missing_key(item_key, quantity, warehouse_id):
194
    missedInventoryUpdate = MissedInventoryUpdate.get_by(itemKey = item_key, warehouseId = warehouse_id)
195
    # One email per product key mismatch
196
    if not missedInventoryUpdate:
197
        missedInventoryUpdate = MissedInventoryUpdate()
198
        missedInventoryUpdate.itemKey = item_key
199
        missedInventoryUpdate.quantity = quantity
200
        missedInventoryUpdate.isIgnored = 1
201
        missedInventoryUpdate.timestamp = datetime.datetime.now()
202
        missedInventoryUpdate.warehouseId = warehouse_id
203
        session.commit()
6232 rajveer 204
        try:
8214 amar.kumar 205
            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 206
        except:
207
            print "Not able to send email. No issues, we can continue with updates."
5944 mandeep.dh 208
    else:
209
        missedInventoryUpdate.quantity += quantity
210
        session.commit()
211
 
212
def add_inventory(itemId, warehouseId, quantity):
213
    current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
214
    if not current_inventory_snapshot:
215
        current_inventory_snapshot = CurrentInventorySnapshot()
216
        current_inventory_snapshot.item_id = itemId
217
        current_inventory_snapshot.warehouse_id = warehouseId
218
        current_inventory_snapshot.availability = 0
219
        current_inventory_snapshot.reserved = 0
8204 amar.kumar 220
        current_inventory_snapshot.held = 0
5944 mandeep.dh 221
    # added the difference in the current inventory    
222
    current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
223
    session.commit()
224
    #**Update item availability cache**#
5978 rajveer 225
    clear_item_availability_cache(itemId)
5944 mandeep.dh 226
    if current_inventory_snapshot.availability < 0:
227
        item = __get_item_from_master(itemId)
5978 rajveer 228
        __send_alert_for_negative_availability(item, current_inventory_snapshot.availability, get_Warehouse(warehouseId)) 
5944 mandeep.dh 229
 
230
def add_bad_inventory(itemId, warehouseId, quantity):
231
    bad_inventory_snapshot = BadInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
232
    if not bad_inventory_snapshot:
233
        bad_inventory_snapshot = BadInventorySnapshot()
234
        bad_inventory_snapshot.item_id = itemId
235
        bad_inventory_snapshot.warehouse_id = warehouseId
236
        bad_inventory_snapshot.availability = 0
237
    # added the difference in the current inventory    
238
    bad_inventory_snapshot.availability += quantity
239
    session.commit()
240
    if bad_inventory_snapshot.availability < 0:
241
        item = __get_item_from_master(itemId)
242
        __send_alert_for_negative_availability(item, bad_inventory_snapshot.availability, get_Warehouse(warehouseId))
243
 
244
def get_item_inventory_by_item_id(item_id):
245
    return CurrentInventorySnapshot.query.filter_by(item_id=item_id).all()
246
 
247
def retire_warehouse(warehouse_id):
248
    if not warehouse_id:
249
        raise InventoryServiceException(101, "Bad warehouse id")
250
    warehouse = get_Warehouse(warehouse_id)
251
    if not warehouse:
252
        raise InventoryServiceException(108, "warehouse id not present")
253
    warehouse.status = 0;
254
    session.commit()
255
 
256
def get_item_availability_for_warehouse(warehouse_id, item_id):
6545 rajveer 257
    ignore = IgnoredInventoryUpdateItems.query.filter_by(item_id=item_id).filter_by(warehouse_id = warehouse_id).all()
6544 rajveer 258
    if ignore:
259
        return 0
5944 mandeep.dh 260
 
261
    try:
6544 rajveer 262
        current_inventory_snapshot = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id).filter_by(item_id = item_id).one()
5944 mandeep.dh 263
        return current_inventory_snapshot.availability - current_inventory_snapshot.reserved
264
    except:
265
        return 0
266
 
6484 amar.kumar 267
def get_item_availability_for_our_warehouses(item_ids):
7699 amar.kumar 268
    our_warehouses = Warehouse.query.filter_by(warehouseType = 'OURS', inventoryType = 'GOOD').all()
269
    our_thirdparty_warehouses = Warehouse.query.filter_by(warehouseType = 'OURS_THIRDPARTY').all()
6484 amar.kumar 270
    warehouse_ids = []
7699 amar.kumar 271
    for warehouse in our_warehouses :
6484 amar.kumar 272
        warehouse_ids.append(warehouse.id)
10170 amar.kumar 273
    #for warehouse in our_thirdparty_warehouses :
274
    #    warehouse_ids.append(warehouse.id)
7699 amar.kumar 275
 
6484 amar.kumar 276
    availability_map = dict()
277
 
278
    try :
279
        for item_id in item_ids :
280
            total_availability = 0
281
            for current_inventory_snapshot in CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).filter_by(item_id = item_id).all():
282
                total_availability += current_inventory_snapshot.availability
283
            if total_availability >0:
284
                availability_map[item_id] = total_availability
285
    except Exception as e:
286
        print e
287
        raise PurchaseServiceException(101, 'Exception while fetching availability of items in our warehouses')
288
 
289
    return availability_map
290
 
5944 mandeep.dh 291
'''
292
This method returns quantity of a particular item across all warehouses whose ids is provided
293
if warehouse_ids is null it checks for inventory in all warehouses.
294
'''
295
def __get_item_availability(item, warehouse_ids):
296
    if warehouse_ids is None:
297
        all_inventory = CurrentInventorySnapshot.query.filter_by(item = item).all()
298
        availability = 0
299
        reserved = 0
300
        for currInv in all_inventory:
301
            availability = availability + currInv.availability
302
            reserved = reserved + currInv.reserved
303
        return availability - reserved
304
    else:
305
        total_availability = 0
306
        for current_inventory_snapshot in CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).filter_by(item_id = item.id).all():
307
            total_availability += current_inventory_snapshot.availability - current_inventory_snapshot.reserved
308
        return total_availability 
309
 
310
def __get_item_reserved(item_id):
311
    all_inventory = CurrentInventorySnapshot.query.filter_by(item_id = item_id).all()
312
    reserved = 0
313
    for currInv in all_inventory:
314
        reserved = reserved + currInv.reserved
315
    return reserved
5966 rajveer 316
 
317
def __get_item_availability_at_warehouse(warehouse_id, item_id):
318
    inventory = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id).one()
319
    return inventory.availability
320
 
321
def is_order_billable(item_id, warehouse_id, source_id, order_id):
322
    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()
323
    availability = __get_item_availability_at_warehouse(warehouse_id, item_id)
324
    for reservation in reservations:
325
        availability = availability - reservation.reserved
326
        if reservation.order_id == order_id and reservation.source_id == source_id:
327
            break
328
    if availability < 0:
329
        return False
330
    return True
5944 mandeep.dh 331
 
5966 rajveer 332
def reserve_item_in_warehouse(item_id, warehouse_id, source_id, order_id, created_timestamp, promised_shipping_timestamp, quantity):    
5944 mandeep.dh 333
    if not warehouse_id:
334
        raise InventoryServiceException(101, "bad warehouse_id")
335
 
336
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
337
    try:
338
        current_inventory_snapshot = query.one()
339
    except:
340
        current_inventory_snapshot = CurrentInventorySnapshot()
341
        current_inventory_snapshot.warehouse_id = warehouse_id
342
        current_inventory_snapshot.item_id = item_id
343
        current_inventory_snapshot.availability = 0
344
        current_inventory_snapshot.reserved = 0
8204 amar.kumar 345
        current_inventory_snapshot.held = 0
5944 mandeep.dh 346
 
347
    current_inventory_snapshot.reserved = current_inventory_snapshot.reserved + quantity
5966 rajveer 348
 
349
    reservation = CurrentReservationSnapshot()
350
    reservation.item_id = item_id
351
    reservation.warehouse_id = warehouse_id
352
    reservation.source_id = source_id
353
    reservation.order_id = order_id
5990 rajveer 354
    reservation.created_timestamp = to_py_date(created_timestamp)
355
    reservation.promised_shipping_timestamp = to_py_date(promised_shipping_timestamp)
5966 rajveer 356
    reservation.reserved = quantity
357
 
8720 amar.kumar 358
    session.commit()
8182 amar.kumar 359
 
360
    try:
361
        order_client = TransactionClient().get_client()
362
        order = order_client.getOrder(order_id)
9574 amar.kumar 363
        if order.source:
364
            holdInventoryDetail = HoldInventoryDetail.query.filter_by(item_id = item_id, warehouse_id = warehouse_id, source = order.source).first()
9694 amar.kumar 365
            if holdInventoryDetail is None or holdInventoryDetail.held<=0:
366
                holdInventoryDetails = HoldInventoryDetail.query.filter_by(item_id = item_id, source = order.source).all()
367
                if holdInventoryDetails:
368
                    for hID in holdInventoryDetails:
369
                        if hID.held>0:
370
                            holdInventoryDetail = hID
9574 amar.kumar 371
            if holdInventoryDetail is not None and holdInventoryDetail.held>0:
372
                previousHeld = holdInventoryDetail.held
373
                holdInventoryDetail.held = max(0, holdInventoryDetail.held -quantity)
374
                diff = previousHeld-holdInventoryDetail.held 
9770 amar.kumar 375
                current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=item_id, warehouse_id=holdInventoryDetail.warehouse_id)
9574 amar.kumar 376
                if current_inventory_snapshot is not None:
377
                    current_inventory_snapshot.held = max(0, current_inventory_snapshot.held - diff)
378
                session.commit()
8182 amar.kumar 379
    except:
380
        print "Unable to release hold Inventory for item_id " + str(item_id) + " warehouse_id " + str(warehouse_id) + " source " + str(source_id)
8720 amar.kumar 381
    #session.commit()
5944 mandeep.dh 382
    #**Update item availability cache**#
5978 rajveer 383
    clear_item_availability_cache(item_id)
5944 mandeep.dh 384
    return True
385
 
7968 amar.kumar 386
def update_reservation_for_order(item_id, warehouse_id, source_id, order_id, created_timestamp, promised_shipping_timestamp, quantity):    
387
    if not warehouse_id:
388
        raise InventoryServiceException(101, "bad warehouse_id")
389
    warehouse = get_Warehouse(warehouse_id)
390
    item_pricing = get_item_pricing(item_id, warehouse.vendor.id)
391
    if not item_pricing:
392
        raise InventoryServiceException(101, "No Pricing Info found for vendor and Item")
393
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
394
    try:
395
        new_current_inventory_snapshot = query.one()
396
    except:
397
        new_current_inventory_snapshot = CurrentInventorySnapshot()
398
        new_current_inventory_snapshot.warehouse_id = warehouse_id
399
        new_current_inventory_snapshot.item_id = item_id
400
        new_current_inventory_snapshot.availability = 0
401
        new_current_inventory_snapshot.reserved = 0
402
 
403
    new_current_inventory_snapshot.reserved = new_current_inventory_snapshot.reserved + quantity
404
 
405
    new_reservation = CurrentReservationSnapshot()
406
    new_reservation.item_id = item_id
407
    new_reservation.warehouse_id = warehouse_id
408
    new_reservation.source_id = source_id
409
    new_reservation.order_id = order_id
410
    new_reservation.created_timestamp = to_py_date(created_timestamp)
411
    new_reservation.promised_shipping_timestamp = to_py_date(promised_shipping_timestamp)
412
    new_reservation.reserved = quantity
413
 
8182 amar.kumar 414
    try:
415
        order_client = TransactionClient().get_client()
416
        order = order_client.getOrder(order_id)
9574 amar.kumar 417
        if order.source:
418
            holdInventoryDetail = HoldInventoryDetail.query.filter_by(item_id = item_id, warehouse_id = warehouse_id, source = order.source).first()
9694 amar.kumar 419
            if holdInventoryDetail is None or holdInventoryDetail.held<=0:
420
                holdInventoryDetails = HoldInventoryDetail.query.filter_by(item_id = item_id, source = order.source).all()
421
                if holdInventoryDetails:
422
                    for hID in holdInventoryDetails:
423
                        if hID.held>0:
424
                            holdInventoryDetail = hID
9574 amar.kumar 425
            if holdInventoryDetail is not None and holdInventoryDetail.held>0:
426
                previousHeld = holdInventoryDetail.held
427
                holdInventoryDetail.held = max(0, holdInventoryDetail.held -quantity)
428
                diff = previousHeld-holdInventoryDetail.held 
9770 amar.kumar 429
                current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=item_id, warehouse_id=holdInventoryDetail.warehouse_id)
9574 amar.kumar 430
                if current_inventory_snapshot is not None:
431
                    current_inventory_snapshot.held = max(0, current_inventory_snapshot.held - diff)
432
                session.commit()
8182 amar.kumar 433
    except:
434
        print "Unable to release hold Inventory for item_id " + str(item_id) + " warehouse_id " + str(warehouse_id) + " source " + str(source_id)
435
 
7968 amar.kumar 436
    order_client = TransactionClient().get_client()
437
    order = order_client.getOrder(order_id)
438
    for lineitem in order.lineitems:
439
        query = CurrentInventorySnapshot.query.filter_by(warehouse_id = order.fulfilmentWarehouseId, item_id = lineitem.item_id)
440
        try:
441
            current_inventory_snapshot = query.one()
442
            current_inventory_snapshot.reserved = current_inventory_snapshot.reserved - quantity
443
 
444
            reservation = CurrentReservationSnapshot.query.filter_by(warehouse_id = order.fulfilmentWarehouseId, item_id = lineitem.item_id, source_id = source_id, order_id = order_id).one()
445
            if reservation.reserved == quantity:
446
                reservation.delete()
447
            else:
448
                reservation.reserved -= quantity
449
 
450
            clear_item_availability_cache(lineitem.item_id)
451
            session.commit()
452
            try:
453
                if current_inventory_snapshot.reserved < 0:
454
                    item = __get_item_from_master(lineitem.item_id)
455
                    __send_alert_for_negative_reserved(item, current_inventory_snapshot.reserved, get_Warehouse(order.fulfilmentWarehouseId))
456
            except:
8182 amar.kumar 457
                print "Error in sending negative reserved alert:", sys.exc_info()[0]
7968 amar.kumar 458
                return False
459
        except:
460
            print "Error in reducing reservation for item:", sys.exc_info()[0]
461
            return False
462
    session.commit()
463
    #**Update item availability cache**#
464
    clear_item_availability_cache(item_id)
465
    return True
466
 
467
 
5966 rajveer 468
def reduce_reservation_count(item_id, warehouse_id, source_id, order_id, quantity):
5944 mandeep.dh 469
    if not warehouse_id:
470
        raise InventoryServiceException(101, "bad warehouse_id")
471
 
472
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
473
    try:
474
        current_inventory_snapshot = query.one()
475
        current_inventory_snapshot.reserved = current_inventory_snapshot.reserved - quantity
5966 rajveer 476
 
477
        reservation = CurrentReservationSnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id, source_id = source_id, order_id = order_id).one()
478
        if reservation.reserved == quantity:
479
            reservation.delete()
480
        else:
481
            reservation.reserved -= quantity
5944 mandeep.dh 482
        session.commit()
483
        #**Update item availability cache**#
5978 rajveer 484
        clear_item_availability_cache(item_id)
5944 mandeep.dh 485
        if current_inventory_snapshot.reserved < 0:
486
            item = __get_item_from_master(item_id)
487
            __send_alert_for_negative_reserved(item, current_inventory_snapshot.reserved, get_Warehouse(warehouse_id))
488
        return True
489
    except:
490
        print "Unexpected error:", sys.exc_info()[0]
491
        return False
492
 
5978 rajveer 493
def get_item_availability_for_location(item_id, source_id):
494
    item_availability = ItemAvailabilityCache.get_by(itemId=item_id, sourceId = source_id)
5944 mandeep.dh 495
    if item_availability:
7589 rajveer 496
        return [item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice, item_availability.totalAvailability, item_availability.weight]
5944 mandeep.dh 497
    else:
5978 rajveer 498
        __update_item_availability_cache(item_id, source_id)
499
            ##Check risky status for the source
500
        __check_risky_item(item_id, source_id)
501
        return get_item_availability_for_location(item_id, source_id)
5944 mandeep.dh 502
 
5978 rajveer 503
def clear_item_availability_cache(item_id = None):
504
    if item_id:
505
        ItemAvailabilityCache.query.filter_by(itemId = item_id).delete()
12963 amit.gupta 506
        session.commit()
5978 rajveer 507
    else:
508
        ItemAvailabilityCache.query.delete()
12963 amit.gupta 509
        session.commit()
510
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
511
        for item in client.getItemsByRiskyFlag():
512
            __update_item_availability_cache(None, 1, item)
5944 mandeep.dh 513
 
12963 amit.gupta 514
def __update_item_availability_cache(item_id, source_id, item=None):
5944 mandeep.dh 515
    """
8954 vikram.rag 516
    Determines the warehouse that should be used to fulfil an order for the given item.
5944 mandeep.dh 517
    Algorithm explained at https://sites.google.com/a/shop2020.in/virtual-w-h-and-inventory/technical-details
518
 
519
    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.
520
    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.
521
 
522
    if item available at any OUR-GOOD warehouse
523
        // OUR-GOOD warehouses have inventory risk; So, we empty them first! 
524
        // We can start with minimum transfer price criterion but down the line we can also bring in Inventory age 
525
        assign OUR-GOOD warehouse with minimum transfer price
526
    else
527
        if Preferred vendor is specified and marked Sticky
528
            // Always purchase from Preferred if its marked sticky
529
            assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
530
        else 
531
            if item available in a THIRDPARTY GOOD/VIRTUAL warehouse
532
                assign THIRDPARTY GOOD/VIRTUAL warehouse where item is available with minimal transfer delay followed by minimum transfer price
533
            else 
534
                // Item not available at any warehouse, OURS or THIRDPARTY
535
                If Preferred vendor is specified
536
                    assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
537
                else
538
                    assign THIRDPARTY GOOD/VIRTUAL warehouse with minimum transfer price
539
 
540
    Returns an ordered list of size 4 with following elements in the given order:
541
    1. Logistics location of the warehouse which was finally picked up to ship the order.
542
    2. Expected delay added by the category manager.
543
    3. Id of the warehouse which was finally picked up.
544
 
545
    Parameters:
546
     - itemId
547
    """
12963 amit.gupta 548
    if item is None:
549
        item = __get_item_from_source(item_id, source_id)
5944 mandeep.dh 550
    item_pricing = {}
551
    for vendorItemPricing in VendorItemPricing.query.filter_by(item_id=item_id).all():
552
        item_pricing[vendorItemPricing.vendor_id] = vendorItemPricing
553
 
6510 rajveer 554
    ignoredWhs = get_ignored_warehouses(item_id)
555
 
5944 mandeep.dh 556
    warehouses = {}
557
    ourGoodWarehouses = {}
558
    thirdpartyWarehouses = {}
559
    preferredThirdpartyWarehouses = {}
560
    for warehouse in Warehouse.query.all():
7410 amar.kumar 561
        if (warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.BAD] or warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.OURS_THIRDPARTY]):
5944 mandeep.dh 562
            continue
563
        warehouses[warehouse.id] = warehouse
564
        if warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.OURS]:
565
            if warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
566
                ourGoodWarehouses[warehouse.id] = warehouse
567
        else:
568
            thirdpartyWarehouses[warehouse.id] = warehouse
569
            if item.preferredVendor == warehouse.vendor_id and warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
570
                preferredThirdpartyWarehouses[warehouse.id] = warehouse
571
 
572
    warehouse_retid = -1
573
    total_availability = 0
574
 
6540 rajveer 575
    [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(ourGoodWarehouses, ignoredWhs, item_id, item_pricing, False)
5944 mandeep.dh 576
    if warehouse_retid == -1:
577
        if item.preferredVendor and item.isWarehousePreferenceSticky:
6540 rajveer 578
            [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(preferredThirdpartyWarehouses, ignoredWhs, item_id, item_pricing)
5944 mandeep.dh 579
            if warehouse_retid == -1:
580
                warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
581
        else:
6540 rajveer 582
            [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(thirdpartyWarehouses, ignoredWhs, item_id, item_pricing)
5944 mandeep.dh 583
            if warehouse_retid == -1:
584
                if item.preferredVendor:
585
                    warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
586
                else:
6540 rajveer 587
                    [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(thirdpartyWarehouses, ignoredWhs, item_id, item_pricing, True)
5944 mandeep.dh 588
 
589
    warehouse = warehouses[warehouse_retid]
590
    billingWarehouseId = warehouse.billingWarehouseId
591
 
592
    # Fetching billing warehouse of a Good billable warehouse corresponding to the virtual one
593
    if not warehouse.billingWarehouseId:
594
        for w in Warehouse.query.filter_by(vendor_id = warehouse.vendor_id, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]).all():
595
            if w.billingWarehouseId:
596
                billingWarehouseId = w.billingWarehouseId
597
                break
598
 
599
    expectedDelay = item.expectedDelay 
600
    if expectedDelay is None:
601
        print 'expectedDelay field for this item was Null. Resetting it to 0'
602
        expectedDelay = 0
603
    else:
604
        expectedDelay = int(item.expectedDelay)
605
 
606
    if total_availability <= 0:
8026 amar.kumar 607
        if item.preferredVendor in [1, 5]:
6562 rajveer 608
            expectedDelay = expectedDelay + 3
609
        else:
610
            expectedDelay = expectedDelay + 2
6643 rajveer 611
    else:
612
        if warehouse.transferDelayInHours:
613
            expectedDelay = expectedDelay + warehouse.transferDelayInHours / 24
5944 mandeep.dh 614
 
8491 rajveer 615
    if warehouse.warehouseType == WarehouseType.THIRD_PARTY:
616
        expectedDelay = expectedDelay + __get_vendor_holiday_delay(warehouse.vendor_id, expectedDelay) 
617
 
5963 mandeep.dh 618
    total_availability = 0
619
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
6545 rajveer 620
        if entry.warehouse_id not in ignoredWhs:
621
            total_availability += entry.availability - entry.reserved
5963 mandeep.dh 622
 
5978 rajveer 623
    item_availability_cache = ItemAvailabilityCache.get_by(itemId=item_id, sourceId=source_id)
5944 mandeep.dh 624
    if item_availability_cache is None:
625
        item_availability_cache = ItemAvailabilityCache()
626
        item_availability_cache.itemId = item_id
5978 rajveer 627
        item_availability_cache.sourceId = source_id
5944 mandeep.dh 628
    item_availability_cache.warehouseId = int(warehouse_retid)
629
    item_availability_cache.expectedDelay = expectedDelay
630
    item_availability_cache.billingWarehouseId = billingWarehouseId
631
    item_availability_cache.sellingPrice = item.sellingPrice
632
    item_availability_cache.totalAvailability = total_availability
7589 rajveer 633
    item_availability_cache.weight = 1000*item.weight if item.weight else 300
5944 mandeep.dh 634
    session.commit()
635
 
6540 rajveer 636
def __get_warehouse_with_min_transfer_price(warehouses, ignoredWhs, item_id, item_pricing, ignoreAvailability):
5944 mandeep.dh 637
    warehouse_retid = -1
638
    minTransferPrice = None
639
    total_availability = 0
6013 amar.kumar 640
    availabilityForBillingWarehouses = {}
641
    warehousesAvailability = {}
642
    availability = 0
643
    billing_warehouse_retid = None
5944 mandeep.dh 644
 
645
    if not ignoreAvailability:
646
        for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
7242 amar.kumar 647
            entry.reserved = max(entry.reserved, 0)
8524 amar.kumar 648
            entry.held = max(entry.held, 0)
6013 amar.kumar 649
            #if entry.availability > entry.reserved:
8182 amar.kumar 650
            warehousesAvailability[entry.warehouse_id] = [entry.availability, entry.reserved, entry.held] 
5944 mandeep.dh 651
 
6540 rajveer 652
    if len(ignoredWhs) > 0:
653
        for whid in ignoredWhs:
654
            if warehousesAvailability.has_key(whid):
6542 rajveer 655
                warehousesAvailability[whid][0] = 0
6683 rajveer 656
                warehousesAvailability[whid][1] = 0
8182 amar.kumar 657
                warehousesAvailability[whid][2] = 0
6540 rajveer 658
 
5944 mandeep.dh 659
    for warehouse in warehouses.values():
660
        if not ignoreAvailability:
6013 amar.kumar 661
            #TODO Mistake no entry for this warehouse.id in warehouseswithAvailab
662
            if warehouse.id not in warehousesAvailability:
663
                continue
664
            entry = warehousesAvailability[warehouse.id]
665
            if warehouse.billingWarehouseId in availabilityForBillingWarehouses:
666
                if warehouse.billingWarehouseId is not None or warehouse.billingWarehouseId != 0: 
8182 amar.kumar 667
                    availabilityForBillingWarehouses[warehouse.billingWarehouseId] = availabilityForBillingWarehouses[warehouse.billingWarehouseId] + entry[0] - entry[1] - entry[2]  
5944 mandeep.dh 668
            else:
6013 amar.kumar 669
                if warehouse.billingWarehouseId is not None or warehouse.billingWarehouseId != 0: 
8182 amar.kumar 670
                    availabilityForBillingWarehouses[warehouse.billingWarehouseId] = entry[0] - entry[1] - entry[2]
671
            if entry[0] <= (entry[1] + entry[2]):
5944 mandeep.dh 672
                continue
8182 amar.kumar 673
            total_availability += entry[0] - entry[1] - entry[2]
5944 mandeep.dh 674
 
675
        # Missing transfer price cases should not impact warehouse assignment
676
        transferPrice = None
677
        if item_pricing.has_key(warehouse.vendor_id):
6778 rajveer 678
            transferPrice = item_pricing[warehouse.vendor_id].nlc
5944 mandeep.dh 679
        if minTransferPrice is None or (transferPrice and minTransferPrice > transferPrice):
680
            warehouse_retid = warehouse.id
6013 amar.kumar 681
            billing_warehouse_retid = warehouse.billingWarehouseId
5944 mandeep.dh 682
            minTransferPrice = transferPrice
6013 amar.kumar 683
 
684
 
685
    if billing_warehouse_retid in availabilityForBillingWarehouses: 
686
        availability = availabilityForBillingWarehouses[billing_warehouse_retid]
687
    else:
688
        availability = total_availability
689
 
690
    return [warehouse_retid, availability]
5944 mandeep.dh 691
 
6540 rajveer 692
def __get_warehouse_with_min_transfer_delay(warehouses, ignoredWhs, item_id, item_pricing):
5944 mandeep.dh 693
    minTransferDelay = None
694
    minTransferDelayWarehouses = {}
695
    total_availability = 0
696
 
697
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
7242 amar.kumar 698
        entry.reserved = max(entry.reserved, 0)
8524 amar.kumar 699
        entry.held = max(entry.held, 0)
5944 mandeep.dh 700
        if warehouses.has_key(entry.warehouse_id):
701
            warehouse = warehouses[entry.warehouse_id]
6013 amar.kumar 702
            #if entry.availability > entry.reserved:
6683 rajveer 703
            if entry.warehouse_id not in ignoredWhs:
8182 amar.kumar 704
                total_availability += entry.availability - entry.reserved - entry.held
705
            if entry.availability - entry.reserved - entry.held <= 0:
6780 amar.kumar 706
                continue
6013 amar.kumar 707
            transferDelay = warehouse.transferDelayInHours
708
            if minTransferDelay is None or minTransferDelay >= transferDelay:
709
                if minTransferDelay != transferDelay:
710
                    minTransferDelayWarehouses = {}
711
                minTransferDelayWarehouses[warehouse.id] = warehouse
712
                minTransferDelay = transferDelay
5944 mandeep.dh 713
 
6540 rajveer 714
    return [__get_warehouse_with_min_transfer_price(minTransferDelayWarehouses, ignoredWhs, item_id, item_pricing, False)[0], total_availability]
5944 mandeep.dh 715
 
716
def __get_warehouse_with_max_availability(warehouse_ids, item_id):
717
    warehouse_retid = -1
718
    max_availability = 0
719
    total_availability = 0
720
 
721
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
7242 amar.kumar 722
        entry.reserved = max(entry.reserved, 0)
8524 amar.kumar 723
        entry.held = max(entry.held, 0)
5944 mandeep.dh 724
        if entry.warehouse_id in warehouse_ids:
725
            availability = entry.availability - entry.reserved
726
            if availability > max_availability:
727
                warehouse_retid = entry.warehouse_id
728
                max_availability = availability
729
            total_availability += availability
730
 
731
    return [warehouse_retid, total_availability]
732
 
8491 rajveer 733
def __get_vendor_holiday_delay(vendor_id, expectedDelay):
734
    ## If vendor is closed two days continuously
5944 mandeep.dh 735
    holidayDelay = 0
8491 rajveer 736
    currentDate = datetime.date.today()
737
    expectedDate = currentDate + datetime.timedelta(days = expectedDelay)
738
    holidays = VendorHolidays.query.filter(VendorHolidays.vendor_id == vendor_id).filter(VendorHolidays.date.between(currentDate, expectedDate)).all()
739
    if holidays:
740
        holidayDelay = holidayDelay + len(holidays)
5944 mandeep.dh 741
    return holidayDelay 
742
 
743
def get_item_pricing(item_id, vendorId):
744
    '''
745
    if vendor id is -1 then we calculate an average transfer price to be populated
746
    at the time of order creation. This will be later updated with actual transfer price
747
    at the time of billing.
748
    '''
749
    if(vendorId == -1):
6778 rajveer 750
        tp_total = 0
751
        nlc_total = 0
5944 mandeep.dh 752
        try:
753
            item_pricings = []
754
            item = __get_item_from_master(item_id)
755
            if item.preferredVendor is not None:
756
                item_pricing = VendorItemPricing.query.filter_by(item_id=item_id, vendor_id=item.preferredVendor).first()
757
                if item_pricing:
758
                    item_pricings.append(item_pricing)                    
759
            else :
760
                item_pricings = VendorItemPricing.query.filter_by(item_id=item_id).all()
761
            if item_pricings:
762
                for item_pricing in item_pricings:
6778 rajveer 763
                    tp_total += item_pricing.transfer_price
764
                    nlc_total += item_pricing.nlc
765
                tp_avg = tp_total / len(item_pricings)
766
                nlc_avg = nlc_total / len(item_pricings)
767
                item_pricing.transfer_price = tp_avg
768
                item_pricing.nlc = nlc_avg
5944 mandeep.dh 769
            else:
770
                item_pricing = VendorItemPricing()
771
                item_pricing.transfer_price = item.sellingPrice
6778 rajveer 772
                item_pricing.nlc = item.sellingPrice
5944 mandeep.dh 773
                vendor = Vendor()
774
                vendor.id = vendorId
775
                item_pricing.vendor = vendor
776
                item_pricing.item_id = item_id
777
 
778
            return item_pricing
779
        except:
780
            raise InventoryServiceException(101, "Item pricing not found ")
781
    vendor = Vendor.get_by(id=vendorId)    
782
    try:
783
        item_pricing = VendorItemPricing.query.filter_by(vendor=vendor, item_id=item_id).one()
784
        return item_pricing
785
    except MultipleResultsFound:
786
        raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
787
    except NoResultFound:
788
        raise InventoryServiceException(111, "Missing pricing information for Vendor: " + vendor.name + " and Item: " + str(item_id))
789
 
790
def get_all_item_pricing(item_id):
791
    item_pricing = VendorItemPricing.query.filter_by(item_id=item_id).all()
792
    return item_pricing
10126 amar.kumar 793
def get_all_vendor_item_pricing(item_id, vendor_id):
794
    query = VendorItemPricing.query
795
    if item_id:
796
        query = query.filter_by(item_id = item_id)
797
    if item_id:
798
        query = query.filter_by(vendor_id = vendor_id)
799
    item_pricing = query.all()
800
    return item_pricing
801
 
5944 mandeep.dh 802
def get_item_mappings(item_id):
803
    item_mappings = VendorItemMapping.query.filter_by(item_id=item_id).all()
804
    return item_mappings
805
 
806
def add_vendor_pricing(vendorItemPricing):
807
    if not vendorItemPricing:
808
        raise InventoryServiceException(108, "Bad vendorItemPricing in request")
809
    vendorId = vendorItemPricing.vendorId
810
    itemId = vendorItemPricing.itemId
811
 
812
    try:
813
        vendor = Vendor.query.filter_by(id=vendorId).one()
814
    except:
815
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
816
 
817
    try:
818
        item = __get_item_from_master(itemId)
819
    except:
820
        raise InventoryServiceException(101, "Item not found for itemId " + str(itemId))
821
 
822
    validate_vendor_prices(item, vendorItemPricing)
823
 
824
    try:
825
        ds_vendorItemPricing = VendorItemPricing.query.filter(and_(VendorItemPricing.vendor==vendor, VendorItemPricing.item_id==itemId)).one()
826
    except:
827
        ds_vendorItemPricing = VendorItemPricing()
828
        ds_vendorItemPricing.vendor = vendor
829
        ds_vendorItemPricing.item_id = itemId
830
 
831
    subject = ""
832
    message = ""
833
    if vendorItemPricing.mop:
834
        ds_vendorItemPricing.mop = vendorItemPricing.mop
835
    if vendorItemPricing.dealerPrice:
836
        ds_vendorItemPricing.dealerPrice = vendorItemPricing.dealerPrice
837
    if vendorItemPricing.transferPrice:
838
        if vendorItemPricing.transferPrice != ds_vendorItemPricing.transfer_price:
6617 amar.kumar 839
            client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
840
            item = client.getItem(itemId)
841
            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 842
            subject = "Alert:Change in Transfer Price {0} {1} {2} {3} {4}".format(item.brand, item.modelName, item.modelNumber, item.color, itemId)
5944 mandeep.dh 843
        ds_vendorItemPricing.transfer_price = vendorItemPricing.transferPrice
6751 amar.kumar 844
    if vendorItemPricing.nlc:
845
        if vendorItemPricing.nlc != ds_vendorItemPricing.nlc:
846
            client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
847
            item = client.getItem(itemId)
7315 amit.gupta 848
            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 849
            subject = "Alert:Change in NLC {0} {1} {2} {3} {4}".format(item.brand, item.modelName, item.modelNumber, item.color, itemId)
850
        ds_vendorItemPricing.nlc = vendorItemPricing.nlc
9895 vikram.rag 851
    session.commit()    
852
    client = CatalogClient("catalog_service_server_host_staging", "catalog_service_server_port").get_client()
853
    client.updateNlcAtMarketplaces(itemId,vendorId,ds_vendorItemPricing.nlc)
5944 mandeep.dh 854
    if subject:
855
        __send_mail(subject, message)
856
    return
857
 
858
def add_vendor_item_mapping(key, vendorItemMapping):
859
    if not vendorItemMapping:
860
        raise InventoryServiceException(108, "Bad vendorItemMapping in request")
861
    vendorId = vendorItemMapping.vendorId
862
    itemId = vendorItemMapping.itemId
863
 
864
    try:
865
        vendor = Vendor.query.filter_by(id=vendorId).one()
866
    except:
867
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
868
 
869
    try:
870
        ds_vendorItemMapping = VendorItemMapping.query.filter(and_(VendorItemMapping.vendor==vendor, VendorItemMapping.item_id==itemId, VendorItemMapping.item_key==key)).one()
871
    except:
872
        ds_vendorItemMapping = VendorItemMapping()
873
        ds_vendorItemMapping.vendor = vendor
874
        ds_vendorItemMapping.item_id = itemId
875
    ds_vendorItemMapping.item_key = vendorItemMapping.itemKey
876
 
877
    session.commit()
878
 
879
    # Marking the missed inventory as not ignored as the catalog dashboard user has updated their key
880
    for missedInventoryUpdate in MissedInventoryUpdate.query.filter_by(itemKey = vendorItemMapping.itemKey).all():
881
        missedInventoryUpdate.isIgnored = 0
882
    session.commit()
883
 
884
    return
885
 
886
def validate_vendor_prices(item, vendorPrices):
887
    if item.mrp != None and item.mrp != "" and vendorPrices.mop != "" and item.mrp <  vendorPrices.mop:
888
        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))
889
        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)))
890
    if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
891
        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))
892
        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)))
893
    return
894
 
895
def get_all_vendors():
896
    return Vendor.query.all()
897
 
898
def get_pending_orders_inventory(vendor_id=1):
899
    """
900
    Returns a list of inventory stock for items for which there are pending orders.
901
    """
902
 
903
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter_by(vendor_id = vendor_id)]
904
    pending_items_inventory = []
905
    if warehouse_ids:
906
        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()
907
    return pending_items_inventory
908
 
7149 amar.kumar 909
def get_billable_inventory_and_pending_orders():
910
    """
911
    Returns a list of inventory Availability and Reserved Count for items which either have real inventory
912
    or have pending orders.
913
    """
914
 
915
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter(Warehouse.isAvailabilityMonitored == 1).filter(or_(Warehouse.inventoryType == 'GOOD', Warehouse.warehouseType == 'OURS'))]
916
    items_inventory = []
917
    reserved_items_inventory = []
918
    available_items_inventory = []
919
    if warehouse_ids:
920
        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()
921
        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()
922
 
923
    items_inventory.extend(reserved_items_inventory)
924
    items_inventory.extend(available_items_inventory)
925
    return items_inventory
926
 
927
 
5944 mandeep.dh 928
def close_session():
929
    if session.is_active:
930
        print "session is active. closing it."
931
        session.close()
932
 
933
def is_alive():
934
    try:
935
        session.query(Vendor.id).limit(1).one()
936
        return True
937
    except:
938
        return False
939
 
940
def add_vendor(vendor):
941
    if not vendor:
942
        raise InventoryServiceException(108, "Bad vendor")
943
    if get_vendor(vendor.id):
944
        #vendor is already present.
945
        raise InventoryServiceException(101, "Vendor already present")
946
 
947
    ds_vendor = Vendor()
948
    ds_vendor.id = vendor.id
949
    ds_vendor.name = vendor.name
950
    session.commit()
951
    return ds_vendor.id
952
 
953
def add_warehouse_vendor_mapping(warehouse_id, VendorId):
954
    return True
955
 
956
def mark_missed_inventory_updates_as_processed(itemKey, warehouseId):
957
    MissedInventoryUpdate.query.filter_by(itemKey = itemKey, warehouseId = warehouseId).delete()
958
    session.commit()
959
 
960
def get_item_keys_to_be_processed(warehouseId):
961
    return [i.itemKey for i in MissedInventoryUpdate.query.filter_by(warehouseId = warehouseId, isIgnored = 0)]
962
 
963
def reset_availability(itemKey, vendorId, quantity, warehouseId):
964
    vendorItemMapping = VendorItemMapping.get_by(vendor_id = vendorId, item_key = itemKey)
965
    if vendorItemMapping:
966
        itemId = vendorItemMapping.item_id
967
 
968
        if skippedItems.has_key(warehouseId) and itemId in skippedItems[warehouseId]:
969
            quantity = 0
970
 
971
        currentInventorySnapshot = CurrentInventorySnapshot.get_by(item_id = itemId, warehouse_id = warehouseId)
972
        if currentInventorySnapshot:
973
            currentInventorySnapshot.availability = quantity
5978 rajveer 974
            clear_item_availability_cache(itemId) 
5944 mandeep.dh 975
        else:
976
            add_inventory(itemId, warehouseId, quantity)
977
 
978
    else:
979
        raise InventoryServiceException(101, 'VendorMapping not found for: ' + itemKey)
980
    session.commit()
981
 
982
def reset_availability_for_warehouse(warehouseId):
983
    for currentInventorySnapshot in CurrentInventorySnapshot.query.filter_by(warehouse_id=warehouseId).all():
984
        currentInventorySnapshot.availability = 0
5978 rajveer 985
        clear_item_availability_cache(currentInventorySnapshot.item_id) 
5944 mandeep.dh 986
    session.commit()
987
 
7718 amar.kumar 988
def get_our_warehouse_id_for_vendor(vendor_id, billing_warehouse_id):
6467 amar.kumar 989
    try:
7718 amar.kumar 990
        warehouse = Warehouse.query.filter_by(vendor_id = vendor_id, warehouseType = 'OURS', inventoryType = 'GOOD', billingWarehouseId = billing_warehouse_id).first()
6467 amar.kumar 991
        return warehouse.id
992
    except Exception as e:
993
        print e;
7755 amar.kumar 994
        raise InventoryServiceException(101, 'No our warehouse found for vendorId: ' + str(vendor_id))
5944 mandeep.dh 995
 
996
def __send_mail(subject, message):
997
    try:
6029 rajveer 998
        thread = threading.Thread(target=partial(mail, mail_user, mail_password, to_addresses, subject, message))
5944 mandeep.dh 999
        thread.start()
1000
    except Exception as ex:
1001
        print ex    
1002
 
1003
def get_shipping_locations():
1004
    shippingLocationIds = {}
1005
    warehouses = Warehouse.query.all()
1006
    for warehouse in warehouses:
1007
        if warehouse.shippingWarehouseId:
1008
            shippingLocationIds[warehouse.shippingWarehouseId] = 1
1009
 
1010
    shippingLocations = []
1011
    for shippingLocationId in shippingLocationIds:
1012
        shippingLocations.append(get_Warehouse(shippingLocationId))
1013
 
1014
    return shippingLocations
1015
 
1016
def get_inventory_snapshot(warehouseId):
1017
    query = CurrentInventorySnapshot.query
1018
 
1019
    if warehouseId:
1020
        query = query.filter_by(warehouse_id = warehouseId)
1021
 
1022
    itemInventoryMap = {}
1023
    for row in query.all():
1024
        if not itemInventoryMap.has_key(row.item_id):
1025
            itemInventoryMap[row.item_id] = []
1026
 
1027
        itemInventoryMap[row.item_id].append(row)
1028
 
1029
    return itemInventoryMap
1030
 
1031
def update_vendor_string(warehouseId, vendorString):
1032
    warehouse = get_Warehouse(warehouseId)
1033
    warehouse.vendorString = vendorString
1034
    session.commit()
1035
 
1036
def __get_item_from_master(item_id):
1037
    client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
5978 rajveer 1038
    return client.getItem(item_id)
1039
 
1040
def __check_risky_item(item_id, source_id):
1041
    ## We should get the list of strings which will identify to the catalog servers
1042
    if source_id == 1:
1043
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
1044
        client.validateRiskyStatus(item_id)
1045
    if source_id == 2:
1046
        client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
1047
        client.validateRiskyStatus(item_id)
1048
 
1049
def __get_item_from_source(item_id, source_id):
1050
    if source_id == 1:
1051
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
1052
        return client.getItem(item_id)
1053
    if source_id == 2:
1054
        client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
6531 vikram.rag 1055
        return client.getItem(item_id)
1056
 
1057
def get_monitored_warehouses_for_vendors(vendorIds):
1058
    w = []
1059
    for wh in Warehouse.query.filter_by(isAvailabilityMonitored = 1).all():
1060
        if wh.vendor.id in (vendorIds):
1061
            w.append(to_t_warehouse(wh).id)
1062
    return w
1063
def get_ignored_warehouseids_and_itemids():
1064
    iw = []
1065
    for i in IgnoredInventoryUpdateItems.query.all():
1066
        iw.append(to_t_itemidwarehouseid(i)) 
1067
    return iw
1068
def insert_item_to_ignore_inventory_update_list(item_id,warehouse_id):
1069
    try:
1070
        ds_warehouse=IgnoredInventoryUpdateItems()
1071
        ds_warehouse.item_id=item_id
1072
        ds_warehouse.warehouse_id=warehouse_id
6532 amit.gupta 1073
        clear_item_availability_cache(item_id)
6531 vikram.rag 1074
        session.commit()
1075
        return True
1076
    except:
1077
        return False       
1078
def delete_item_from_ignore_inventory_update_list(item_id,warehouse_id):
1079
    try:
1080
        session.query(IgnoredInventoryUpdateItems).filter_by(item_id=item_id,warehouse_id=warehouse_id).delete()
6532 amit.gupta 1081
        clear_item_availability_cache(item_id)
6531 vikram.rag 1082
        session.commit()
1083
        return True
1084
    except:
1085
        return False           
1086
 
1087
def get_all_ignored_inventoryupdate_items_count():
1088
    return  session.query(func.count(distinct(IgnoredInventoryUpdateItems.item_id))).scalar()
1089
 
1090
def get_ignored_inventoryupdate_itemids(offset=0,limit=None):
1091
    itemIds = session.query(distinct(IgnoredInventoryUpdateItems.item_id))
1092
    '''if limit is not None:
1093
        itemIds = itemIds.limit(limit)'''
1094
    print itemIds.all()
1095
    return [id for (id, ) in itemIds.all()]
6821 amar.kumar 1096
 
1097
def update_item_stock_purchase_params(item_id, numOfDaysStock, minStockLevel):
1098
    if numOfDaysStock is None or minStockLevel is None:
1099
        raise InventoryServiceException(108, "Bad params : numOfDaysStock = " + str(numOfDaysStock) + "minStockLevel = " + str(minStockLevel))
1100
    itemStockPurchaseParams = ItemStockPurchaseParams.query.filter_by(item_id = item_id).first()
1101
    if itemStockPurchaseParams is None:
1102
        itemStockPurchaseParams = ItemStockPurchaseParams()
1103
    itemStockPurchaseParams.item_id = item_id
1104
    itemStockPurchaseParams.numOfDaysStock = numOfDaysStock
1105
    itemStockPurchaseParams.minStockLevel = minStockLevel
1106
    session.commit()
1107
 
1108
def get_item_stock_purchase_params(item_id):
1109
    return ItemStockPurchaseParams.query.filter_by(item_id = item_id).first()
1110
 
1111
def add_oos_status_for_item(oosStatusMap, date):
1112
 
1113
    oosDate = to_py_date(date)
1114
    oosDate.replace(second=0, microsecond=0)
1115
 
1116
    cartAdditionStartDate = oosDate - datetime.timedelta(days = 1)
1117
 
1118
    client = TransactionClient().get_client()
1119
 
1120
    #Gets physical orders in the last day
1121
    orders = client.getPhysicalOrders(to_java_date(cartAdditionStartDate), to_java_date(oosDate))
8019 amar.kumar 1122
    rtoOrders = client.getAllOrders([20], 0, 0, 0)
9665 rajveer 1123
    orderCountByItemIdSourceId = {}
1124
    rtoOrderCountByItemIdSourceId = {}
1125
 
6821 amar.kumar 1126
    for order in orders:
9665 rajveer 1127
        if not orderCountByItemIdSourceId.has_key(order.lineitems[0].item_id):
1128
            orderCountByItemIdSourceId[order.lineitems[0].item_id] = {}
1129
 
1130
        if orderCountByItemIdSourceId[order.lineitems[0].item_id].has_key(order.source):
9791 rajveer 1131
            orderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = orderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] + 1
6821 amar.kumar 1132
        else:
9665 rajveer 1133
            orderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = 1
1134
 
8019 amar.kumar 1135
 
1136
    for order in rtoOrders:
9665 rajveer 1137
        if not rtoOrderCountByItemIdSourceId.has_key(order.lineitems[0].item_id):
1138
            rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id] = {}
1139
 
1140
        if rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id].has_key(order.source):
1141
            rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] + 1 
8019 amar.kumar 1142
        else:
9665 rajveer 1143
            rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = 1
1144
 
1145
 
6821 amar.kumar 1146
    for itemId, status in oosStatusMap.iteritems():
9665 rajveer 1147
        total_order_count = 0 
9791 rajveer 1148
        total_rto_count = 0
9665 rajveer 1149
        for sid in (1,3,6,7,8):
6821 amar.kumar 1150
            oosStatus = OOSStatus()
1151
            oosStatus.item_id = itemId
1152
            oosStatus.date = oosDate
9791 rajveer 1153
            oosStatus.sourceId  = sid
1154
            order_count = 0
1155
            rto_count = 0
1156
            if orderCountByItemIdSourceId.has_key(itemId) and orderCountByItemIdSourceId[itemId].has_key(sid):
1157
                order_count = orderCountByItemIdSourceId[itemId][sid]
1158
            if rtoOrderCountByItemIdSourceId.has_key(itemId) and rtoOrderCountByItemIdSourceId[itemId].has_key(sid):
1159
                    rto_count = rtoOrderCountByItemIdSourceId[itemId][sid]
1160
            oosStatus.num_orders = order_count
1161
            oosStatus.rto_orders = rto_count
9666 rajveer 1162
            oosStatus.is_oos = status
9791 rajveer 1163
            if oosStatus.is_oos and order_count > 0:
1164
                oosStatus.is_oos = False
1165
            total_order_count = total_order_count + order_count
1166
            total_rto_count = total_rto_count + rto_count
1167
        oosStatus = OOSStatus()
1168
        oosStatus.item_id = itemId
1169
        oosStatus.date = oosDate
1170
        oosStatus.sourceId  = 0
1171
        oosStatus.num_orders = total_order_count
1172
        oosStatus.rto_orders = total_rto_count
9804 rajveer 1173
        if itemId in orderCountByItemIdSourceId and 1 in orderCountByItemIdSourceId[itemId]:
1174
            order_count = orderCountByItemIdSourceId[itemId][1]
9791 rajveer 1175
        oosStatus.is_oos = status
1176
        if oosStatus.is_oos and order_count > 0:
1177
            oosStatus.is_oos = False
6821 amar.kumar 1178
 
9791 rajveer 1179
        session.commit()
1180
 
9861 rajveer 1181
 
1182
    itemCountMap = {}
1183
    oosDate = oosDate - datetime.timedelta(days = 1) - datetime.timedelta(hours = 1)
1184
    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()
1185
    for line in lines:
1186
        item_id = line[0]
9896 rajveer 1187
        quantity = int(math.ceil(max(1,2*line[1])))
9861 rajveer 1188
        itemCountMap[item_id] = quantity
9862 rajveer 1189
    cl = CatalogClient('catalog_service_server_host_prod','catalog_service_server_port').get_client()
9861 rajveer 1190
    cl.updateItemHoldInventory(itemCountMap)
9791 rajveer 1191
 
9665 rajveer 1192
def get_oos_statuses_for_x_days_for_item(itemId, sourceId, days):
6832 amar.kumar 1193
    timestamp = datetime.datetime.now()
9640 amar.kumar 1194
    timestamp = timestamp - datetime.timedelta(days = days)
9665 rajveer 1195
    return OOSStatus.query.filter_by(item_id = itemId).filter_by(sourceId = sourceId).filter(OOSStatus.date > timestamp).all()
6857 amar.kumar 1196
 
10126 amar.kumar 1197
def get_oos_statuses_for_x_days(sourceId, days):
1198
    timestamp = datetime.datetime.now()
1199
    timestamp = timestamp - datetime.timedelta(days = days)
1200
    if sourceId == -1:
1201
        return OOSStatus.query.filter(OOSStatus.date > timestamp).all()
1202
    else:
1203
        return OOSStatus.query.filter_by(sourceId = sourceId).filter(OOSStatus.date > timestamp).all()
1204
 
6857 amar.kumar 1205
def get_non_zero_item_stock_purchase_params():
7281 kshitij.so 1206
    return ItemStockPurchaseParams.query.filter(or_("numOfDaysStock!=0","minStockLevel!=0"))
1207
 
7972 amar.kumar 1208
def get_last_n_day_sale_for_item(itemId, numberOfDays):
1209
    lastNdaySale = ""
9685 rajveer 1210
    oosStatuses = get_oos_statuses_for_x_days_for_item(itemId, 0, numberOfDays)
7972 amar.kumar 1211
    for oosStatus in oosStatuses:
1212
        if oosStatus.is_oos == True:
1213
            lastNdaySale +="X-"
1214
        else:
1215
            lastNdaySale +=str(oosStatus.num_orders) + "-"
1216
    return lastNdaySale[:-1] 
1217
 
7281 kshitij.so 1218
def get_warehouse_name(warehouseId):
1219
    row = Warehouse.get_by(id = warehouseId)
1220
    return row.displayName
1221
 
1222
def get_amazon_inventory_for_item(amazonItemId):
1223
    inventory = AmazonInventorySnapshot.get_by(item_id=amazonItemId)
1224
    return inventory
1225
 
1226
def get_all_amazon_inventory():
1227
    return session.query(AmazonInventorySnapshot).all()
1228
 
10450 vikram.rag 1229
def add_or_update_amazon_inventory_for_item(amazoninventorysnapshot,time):
7281 kshitij.so 1230
    inventory = AmazonInventorySnapshot.get_by(item_id = amazoninventorysnapshot.item_id)
1231
    if inventory is None:
1232
        amazon_inventory = AmazonInventorySnapshot()
1233
        amazon_inventory.item_id = amazoninventorysnapshot.item_id
1234
        amazon_inventory.availability = amazoninventorysnapshot.availability
1235
        amazon_inventory.reserved = amazoninventorysnapshot.reserved
10450 vikram.rag 1236
        amazon_inventory.is_oos = amazoninventorysnapshot.is_oos
1237
        if time != 0:
1238
            amazon_inventory.lastUpdatedOnAmazon = to_py_date(time)
1239
    else: 
7281 kshitij.so 1240
        inventory.availability = amazoninventorysnapshot.availability
1241
        inventory.reserved = amazoninventorysnapshot.reserved
10450 vikram.rag 1242
        if not inventory.is_oos and (to_py_date(time) - inventory.lastUpdatedOnAmazon).days == 0:
1243
            pass
1244
        else:
1245
            inventory.is_oos = amazoninventorysnapshot.is_oos
1246
        if time != 0:    
1247
            inventory.lastUpdatedOnAmazon = to_py_date(time)      
7281 kshitij.so 1248
    session.commit()
1249
 
8182 amar.kumar 1250
def add_update_hold_inventory(itemId, warehouseId, holdQuantity, source):
9762 amar.kumar 1251
    if holdQuantity <0:
1252
        print "Negative holdQuantity : " + str(holdQuantity) + " is not allowed"
1253
        raise InventoryServiceException(108, "Negative heldQuantity is not allowed")
8197 amar.kumar 1254
    hold_inventory_detail = HoldInventoryDetail.get_by(item_id = itemId, warehouse_id=warehouseId, source = source)
1255
    if  hold_inventory_detail is None:
8182 amar.kumar 1256
        diffTobeAddedInCIS = holdQuantity
1257
        hold_inventory_detail = HoldInventoryDetail()
1258
        hold_inventory_detail.item_id = itemId 
1259
        hold_inventory_detail.warehouse_id = warehouseId 
1260
        hold_inventory_detail.held = holdQuantity 
1261
        hold_inventory_detail.source = source
1262
    else:
8497 amar.kumar 1263
        diffTobeAddedInCIS = holdQuantity - hold_inventory_detail.held
8182 amar.kumar 1264
        hold_inventory_detail.held = holdQuantity
1265
 
1266
    current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
1267
    if not current_inventory_snapshot:
1268
        current_inventory_snapshot = CurrentInventorySnapshot()
1269
        current_inventory_snapshot.item_id = itemId
1270
        current_inventory_snapshot.warehouse_id = warehouseId
1271
        current_inventory_snapshot.availability = 0
1272
        current_inventory_snapshot.reserved = 0
1273
        current_inventory_snapshot.held = 0
1274
    current_inventory_snapshot.held = current_inventory_snapshot.held + diffTobeAddedInCIS
1275
    session.commit()
1276
    #**Update item availability cache**#
1277
    clear_item_availability_cache(itemId)
8282 kshitij.so 1278
 
1279
def add_or_update_amazon_fba_inventory(amazonfbainventorysnapshot):
11173 vikram.rag 1280
    inventory = AmazonFbaInventorySnapshot.query.filter_by(item_id = amazonfbainventorysnapshot.item_id,location=amazonfbainventorysnapshot.location).first()
8282 kshitij.so 1281
    if inventory is None:
1282
        amazon_fba_inventory = AmazonFbaInventorySnapshot()
1283
        amazon_fba_inventory.item_id = amazonfbainventorysnapshot.item_id
1284
        amazon_fba_inventory.availability = amazonfbainventorysnapshot.availability
11173 vikram.rag 1285
        amazon_fba_inventory.location = amazonfbainventorysnapshot.location
1286
        amazon_fba_inventory.reserved = amazonfbainventorysnapshot.reserved
1287
        amazon_fba_inventory.inbound = amazonfbainventorysnapshot.inbound
1288
        amazon_fba_inventory.unfulfillable = amazonfbainventorysnapshot.unfulfillable
1289
 
8282 kshitij.so 1290
    else:
11173 vikram.rag 1291
        print 'updating'
8282 kshitij.so 1292
        inventory.availability = amazonfbainventorysnapshot.availability
11173 vikram.rag 1293
        inventory.location = amazonfbainventorysnapshot.location
1294
        inventory.reserved = amazonfbainventorysnapshot.reserved
1295
        inventory.inbound = amazonfbainventorysnapshot.inbound
1296
        inventory.unfulfillable = amazonfbainventorysnapshot.unfulfillable
8282 kshitij.so 1297
 
1298
 
1299
def get_amazon_fba_inventory(itemId):
11173 vikram.rag 1300
    return AmazonFbaInventorySnapshot.query.filter_by(item_id = itemId)
8282 kshitij.so 1301
 
8363 vikram.rag 1302
def get_all_amazon_fba_inventory():
1303
    return AmazonFbaInventorySnapshot.query.all() 
1304
 
12799 manish.sha 1305
def get_oursgood_warehouseids_for_location(stateId):
8363 vikram.rag 1306
    warehouseId=[]
12799 manish.sha 1307
    x= session.query(Warehouse.id).filter(Warehouse.id==Warehouse.billingWarehouseId).filter(Warehouse.warehouseType=='OURS').filter(Warehouse.state_id==stateId).all()
8363 vikram.rag 1308
    for id in x:
1309
        warehouseId.append(id[0])
1310
    return session.query(Warehouse.id).filter(Warehouse.inventoryType=='GOOD').filter(Warehouse.warehouseType=='OURS').filter(Warehouse.billingWarehouseId.in_(warehouseId)).all()
8954 vikram.rag 1311
 
1312
def get_holdinventorydetail_forItem_forWarehouseId_exceptsource(item_id,warehouse_id,source):
1313
    holddetails = HoldInventoryDetail.query.filter(HoldInventoryDetail.item_id == item_id).all()
1314
    print holddetails
1315
    hold = 0
1316
    for holddetail in holddetails:
1317
        if holddetail.source !=source and holddetail.warehouse_id == warehouse_id:
1318
            hold = hold + holddetail.held
9404 vikram.rag 1319
    return hold
1320
 
1321
def get_snapdeal_inventory_for_item(id):
1322
    print SnapdealInventorySnapshot.get_by(item_id = id)
1323
    return SnapdealInventorySnapshot.get_by(item_id = id)
1324
 
1325
def add_or_update_snapdeal_inventor_for_item(snapdealinventoryitem):
1326
    snapdeal_inventory_item = SnapdealInventorySnapshot.get_by(item_id = snapdealinventoryitem.item_id)
1327
    if snapdeal_inventory_item is None:
1328
        snapdeal_inventory_item = SnapdealInventorySnapshot()
1329
        snapdeal_inventory_item.item_id = snapdealinventoryitem.item_id
1330
        snapdeal_inventory_item.availability = snapdealinventoryitem.availability
9495 vikram.rag 1331
        snapdeal_inventory_item.pendingOrders = snapdealinventoryitem.pendingOrders
9404 vikram.rag 1332
        snapdeal_inventory_item.lastUpdatedOnSnapdeal = to_py_date(snapdealinventoryitem.lastUpdatedOnSnapdeal)
10450 vikram.rag 1333
        snapdeal_inventory_item.is_oos = snapdealinventoryitem.is_oos
9404 vikram.rag 1334
    else:
1335
        snapdeal_inventory_item.availability = snapdealinventoryitem.availability
9495 vikram.rag 1336
        snapdeal_inventory_item.pendingOrders = snapdealinventoryitem.pendingOrders
10450 vikram.rag 1337
        if not snapdeal_inventory_item.is_oos and (to_py_date(snapdealinventoryitem.lastUpdatedOnSnapdeal) - snapdeal_inventory_item.lastUpdatedOnSnapdeal).days == 0:
1338
            pass
1339
        else:
1340
            snapdeal_inventory_item.is_oos = snapdealinventoryitem.is_oos
9404 vikram.rag 1341
        snapdeal_inventory_item.lastUpdatedOnSnapdeal = to_py_date(snapdealinventoryitem.lastUpdatedOnSnapdeal)
1342
    session.commit()
8954 vikram.rag 1343
 
9404 vikram.rag 1344
def get_nlc_for_warehouse(warehouse_id,itemid):
1345
    warehouse = Warehouse.get_by(id=warehouse_id)
1346
    if warehouse is None:
1347
        return 0
1348
    vendoritempricing = VendorItemPricing.query.filter_by(item_id=itemid, vendor_id=warehouse.vendor_id).first()
1349
    '''vendoritempricing = VendorItemPricing.get_by(id=warehouse.vendor_id,item_id=itemid)'''
1350
    if vendoritempricing is None:
1351
        return 0
9456 vikram.rag 1352
    return vendoritempricing.nlc
1353
 
9495 vikram.rag 1354
def get_snapdeal_inventory_snapshot():
9640 amar.kumar 1355
    return SnapdealInventorySnapshot.query.all()
10050 vikram.rag 1356
 
9640 amar.kumar 1357
def get_held_inventory_map_for_item(itemId, warehouseId):
1358
    heldInventoryMap = {}
1359
    holdInventories = HoldInventoryDetail.query.filter_by(item_id= itemId, warehouse_id = warehouseId).all()
1360
    for holdInventory in holdInventories:
1361
        heldInventoryMap[holdInventory.source] = holdInventory.held
1362
    return heldInventoryMap 
10050 vikram.rag 1363
 
9761 amar.kumar 1364
def get_hold_inventory_details(itemId, warehouseId, source):
1365
    heldInventoryQuery = HoldInventoryDetail.query
1366
    if itemId:
1367
        heldInventoryQuery = heldInventoryQuery.filter_by(item_id = itemId)
1368
    if warehouseId:
1369
        heldInventoryQuery = heldInventoryQuery.filter_by(warehouse_id = warehouseId)
1370
    if source:
1371
        heldInventoryQuery = heldInventoryQuery.filter_by(source = source)
1372
    holdInventoryDetails = heldInventoryQuery.all()
1373
    return holdInventoryDetails
9896 rajveer 1374
 
10450 vikram.rag 1375
def add_or_update_flipkart_inventory_snapshot(flipkartInventorySnapshot,time):
10050 vikram.rag 1376
    for snapshot in flipkartInventorySnapshot:
1377
        flipkart_inventory = FlipkartInventorySnapshot.get_by(item_id = snapshot.item_id)
1378
        if flipkart_inventory is None:
1379
            flipkart_inventory = FlipkartInventorySnapshot()
1380
            flipkart_inventory.item_id = snapshot.item_id
1381
            flipkart_inventory.availability = snapshot.availability
1382
            flipkart_inventory.createdOrders = snapshot.createdOrders
1383
            flipkart_inventory.heldOrders = snapshot.heldOrders
10450 vikram.rag 1384
            flipkart_inventory.is_oos = snapshot.is_oos
1385
            flipkart_inventory.lastUpdatedOnFlipkart = to_py_date(time) 
10050 vikram.rag 1386
        else:
1387
            flipkart_inventory.availability = snapshot.availability
1388
            flipkart_inventory.createdOrders = snapshot.createdOrders
1389
            flipkart_inventory.heldOrders = snapshot.heldOrders
10450 vikram.rag 1390
            if not flipkart_inventory.is_oos and (to_py_date(time) - flipkart_inventory.lastUpdatedOnFlipkart).days == 0:
1391
                pass
1392
            else:
1393
                flipkart_inventory.is_oos = snapshot.is_oos
1394
            flipkart_inventory.lastUpdatedOnFlipkart = to_py_date(time) 
10050 vikram.rag 1395
    session.commit()
1396
 
1397
def get_flipkart_inventory_snapshot():
1398
    return FlipkartInventorySnapshot.query.all()     
1399
 
10097 kshitij.so 1400
def get_flipkart_inventory_for_Item(itemId):
10485 vikram.rag 1401
    return FlipkartInventorySnapshot.get_by(item_id = itemId)
1402
 
1403
def get_state_master():
1404
    stateIdNameMap = {} 
1405
    statemaster = StateMaster.query.all()
1406
    for state in statemaster:
12280 amit.gupta 1407
        stateIdNameMap[state.id] = to_t_state(state)
10544 vikram.rag 1408
    return stateIdNameMap    
1409
 
1410
def update_snapdeal_stock_at_eod(allsnapdealstock):
1411
    for stockitem in allsnapdealstock:
1412
        snapdealstockateod = SnapdealStockAtEOD()
1413
        snapdealstockateod.item_id = stockitem.item_id
1414
        snapdealstockateod.availability = stockitem.availability
1415
        snapdealstockateod.date =  to_py_date(stockitem.date)
1416
    session.commit()
1417
 
1418
def update_flipkart_stock_at_eod(allflipkartstock):
1419
    for stockitem in allflipkartstock:
1420
        snapdealstockateod = FlipkartStockAtEOD()
1421
        snapdealstockateod.item_id = stockitem.item_id
1422
        snapdealstockateod.availability = stockitem.availability
1423
        snapdealstockateod.date =  to_py_date(stockitem.date)
1424
    session.commit()
10687 rajveer 1425
 
12363 kshitij.so 1426
def get_wanlc_for_source(item_id,sourceId):
1427
    stockWanlc = StockWeightedNlcInfo.query.filter(StockWeightedNlcInfo.itemId==item_id).filter(StockWeightedNlcInfo.source==sourceId).order_by(desc(StockWeightedNlcInfo.updatedTimestamp)).limit(1).all()
1428
    if stockWanlc is None or len(stockWanlc)==0:
1429
        return 0.0
1430
    else:
1431
        return stockWanlc[0].avgWeightedNlc
1432
 
1433
def get_all_available_amazon_inventory():
1434
    return AmazonFbaInventorySnapshot.query.filter(AmazonFbaInventorySnapshot.availability>0).all() 
1435