Subversion Repositories SmartDukaan

Rev

Rev 18459 | Rev 19247 | 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()
15958 amit.gupta 263
        return current_inventory_snapshot.availability - current_inventory_snapshot.reserved - current_inventory_snapshot.held
5944 mandeep.dh 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
 
12976 amit.gupta 493
#This is not the source as in snapdeal or website, this source is to incorporate different pricing depending upon source id.
494
#i.e. if user visiting to our site has specific source he would se pricing on that souce basis. Default source is 1.
5978 rajveer 495
def get_item_availability_for_location(item_id, source_id):
496
    item_availability = ItemAvailabilityCache.get_by(itemId=item_id, sourceId = source_id)
5944 mandeep.dh 497
    if item_availability:
7589 rajveer 498
        return [item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice, item_availability.totalAvailability, item_availability.weight]
5944 mandeep.dh 499
    else:
5978 rajveer 500
        __update_item_availability_cache(item_id, source_id)
501
            ##Check risky status for the source
502
        __check_risky_item(item_id, source_id)
503
        return get_item_availability_for_location(item_id, source_id)
5944 mandeep.dh 504
 
5978 rajveer 505
def clear_item_availability_cache(item_id = None):
13150 manish.sha 506
    print item_id
13149 manish.sha 507
    if type(item_id)==list:
13150 manish.sha 508
        ItemAvailabilityCache.query.filter(ItemAvailabilityCache.itemId.in_(item_id)).delete(synchronize_session='fetch')
13149 manish.sha 509
        session.commit()
13493 amit.gupta 510
        t = threading.Thread(target=_task_update_item_availability_cache, args=(item_id,))
511
        t.start()
512
 
13520 amit.gupta 513
    elif item_id:
5978 rajveer 514
        ItemAvailabilityCache.query.filter_by(itemId = item_id).delete()
12963 amit.gupta 515
        session.commit()
13493 amit.gupta 516
 
517
def _task_update_item_availability_cache(item_ids):
518
    client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
519
    items = client.getItems(item_ids)
520
    for item_id in item_ids:
521
        item_availability = ItemAvailabilityCache.get_by(itemId=item_id, sourceId=1)
522
        if not item_availability:
523
            try:
17974 amit.gupta 524
                __update_item_availability_cache(item_id, 1, items[item_id])
525
                __check_risky_item(item_id, 1)
13493 amit.gupta 526
            except:
527
                print "Could not update cache for "
528
                continue
17990 kshitij.so 529
    return True   
5944 mandeep.dh 530
 
12963 amit.gupta 531
def __update_item_availability_cache(item_id, source_id, item=None):
5944 mandeep.dh 532
    """
8954 vikram.rag 533
    Determines the warehouse that should be used to fulfil an order for the given item.
5944 mandeep.dh 534
    Algorithm explained at https://sites.google.com/a/shop2020.in/virtual-w-h-and-inventory/technical-details
535
 
536
    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.
537
    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.
538
 
539
    if item available at any OUR-GOOD warehouse
540
        // OUR-GOOD warehouses have inventory risk; So, we empty them first! 
541
        // We can start with minimum transfer price criterion but down the line we can also bring in Inventory age 
542
        assign OUR-GOOD warehouse with minimum transfer price
543
    else
544
        if Preferred vendor is specified and marked Sticky
545
            // Always purchase from Preferred if its marked sticky
546
            assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
547
        else 
548
            if item available in a THIRDPARTY GOOD/VIRTUAL warehouse
549
                assign THIRDPARTY GOOD/VIRTUAL warehouse where item is available with minimal transfer delay followed by minimum transfer price
550
            else 
551
                // Item not available at any warehouse, OURS or THIRDPARTY
552
                If Preferred vendor is specified
553
                    assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
554
                else
555
                    assign THIRDPARTY GOOD/VIRTUAL warehouse with minimum transfer price
556
 
557
    Returns an ordered list of size 4 with following elements in the given order:
558
    1. Logistics location of the warehouse which was finally picked up to ship the order.
559
    2. Expected delay added by the category manager.
560
    3. Id of the warehouse which was finally picked up.
561
 
562
    Parameters:
563
     - itemId
564
    """
12963 amit.gupta 565
    if item is None:
566
        item = __get_item_from_source(item_id, source_id)
5944 mandeep.dh 567
    item_pricing = {}
568
    for vendorItemPricing in VendorItemPricing.query.filter_by(item_id=item_id).all():
569
        item_pricing[vendorItemPricing.vendor_id] = vendorItemPricing
570
 
6510 rajveer 571
    ignoredWhs = get_ignored_warehouses(item_id)
572
 
5944 mandeep.dh 573
    warehouses = {}
574
    ourGoodWarehouses = {}
575
    thirdpartyWarehouses = {}
576
    preferredThirdpartyWarehouses = {}
577
    for warehouse in Warehouse.query.all():
7410 amar.kumar 578
        if (warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.BAD] or warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.OURS_THIRDPARTY]):
5944 mandeep.dh 579
            continue
580
        warehouses[warehouse.id] = warehouse
581
        if warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.OURS]:
582
            if warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
583
                ourGoodWarehouses[warehouse.id] = warehouse
584
        else:
585
            thirdpartyWarehouses[warehouse.id] = warehouse
586
            if item.preferredVendor == warehouse.vendor_id and warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
587
                preferredThirdpartyWarehouses[warehouse.id] = warehouse
588
 
589
    warehouse_retid = -1
590
    total_availability = 0
591
 
6540 rajveer 592
    [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(ourGoodWarehouses, ignoredWhs, item_id, item_pricing, False)
5944 mandeep.dh 593
    if warehouse_retid == -1:
594
        if item.preferredVendor and item.isWarehousePreferenceSticky:
6540 rajveer 595
            [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(preferredThirdpartyWarehouses, ignoredWhs, item_id, item_pricing)
5944 mandeep.dh 596
            if warehouse_retid == -1:
597
                warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
598
        else:
6540 rajveer 599
            [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(thirdpartyWarehouses, ignoredWhs, item_id, item_pricing)
5944 mandeep.dh 600
            if warehouse_retid == -1:
601
                if item.preferredVendor:
602
                    warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
603
                else:
6540 rajveer 604
                    [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(thirdpartyWarehouses, ignoredWhs, item_id, item_pricing, True)
5944 mandeep.dh 605
 
606
    warehouse = warehouses[warehouse_retid]
607
    billingWarehouseId = warehouse.billingWarehouseId
608
 
609
    # Fetching billing warehouse of a Good billable warehouse corresponding to the virtual one
610
    if not warehouse.billingWarehouseId:
16030 amit.gupta 611
        for w in Warehouse.query.filter_by(vendor_id = warehouse.vendor_id, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD], logisticsLocation=warehouse.logisticsLocation).all():
5944 mandeep.dh 612
            if w.billingWarehouseId:
613
                billingWarehouseId = w.billingWarehouseId
614
                break
615
 
616
    expectedDelay = item.expectedDelay 
617
    if expectedDelay is None:
618
        print 'expectedDelay field for this item was Null. Resetting it to 0'
619
        expectedDelay = 0
620
    else:
621
        expectedDelay = int(item.expectedDelay)
622
 
623
    if total_availability <= 0:
8026 amar.kumar 624
        if item.preferredVendor in [1, 5]:
6562 rajveer 625
            expectedDelay = expectedDelay + 3
626
        else:
627
            expectedDelay = expectedDelay + 2
6643 rajveer 628
    else:
629
        if warehouse.transferDelayInHours:
630
            expectedDelay = expectedDelay + warehouse.transferDelayInHours / 24
5944 mandeep.dh 631
 
18022 manish.sha 632
    if WarehouseType._NAMES_TO_VALUES[warehouse.warehouseType] == WarehouseType.THIRD_PARTY:
8491 rajveer 633
        expectedDelay = expectedDelay + __get_vendor_holiday_delay(warehouse.vendor_id, expectedDelay) 
634
 
5963 mandeep.dh 635
    total_availability = 0
16029 amit.gupta 636
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
6545 rajveer 637
        if entry.warehouse_id not in ignoredWhs:
16029 amit.gupta 638
            if entry.warehouse_id not in ourGoodWarehouses and entry.warehouse_id not in thirdpartyWarehouses:
16015 amit.gupta 639
                continue
640
            if entry.warehouse_id in ourGoodWarehouses and ourGoodWarehouses[entry.warehouse_id].billingWarehouseId == billingWarehouseId:
641
                total_availability += entry.availability - entry.reserved - entry.held
642
            elif entry.warehouse_id in thirdpartyWarehouses:
643
                vendorId = thirdpartyWarehouses[entry.warehouse_id].vendor_id
644
                for goodWarehouse in ourGoodWarehouses.values():
16029 amit.gupta 645
                    if goodWarehouse.vendor_id==vendorId and goodWarehouse.billingWarehouseId == billingWarehouseId and warehouse.logisticsLocation==goodWarehouse.logisticsLocation:
16015 amit.gupta 646
                        total_availability += entry.availability - entry.reserved - entry.held
647
                        break
5963 mandeep.dh 648
 
5978 rajveer 649
    item_availability_cache = ItemAvailabilityCache.get_by(itemId=item_id, sourceId=source_id)
5944 mandeep.dh 650
    if item_availability_cache is None:
651
        item_availability_cache = ItemAvailabilityCache()
652
        item_availability_cache.itemId = item_id
5978 rajveer 653
        item_availability_cache.sourceId = source_id
5944 mandeep.dh 654
    item_availability_cache.warehouseId = int(warehouse_retid)
655
    item_availability_cache.expectedDelay = expectedDelay
656
    item_availability_cache.billingWarehouseId = billingWarehouseId
657
    item_availability_cache.sellingPrice = item.sellingPrice
658
    item_availability_cache.totalAvailability = total_availability
16029 amit.gupta 659
    #item_availability_cache.location = warehouse.logisticsLocation 
7589 rajveer 660
    item_availability_cache.weight = 1000*item.weight if item.weight else 300
5944 mandeep.dh 661
    session.commit()
662
 
6540 rajveer 663
def __get_warehouse_with_min_transfer_price(warehouses, ignoredWhs, item_id, item_pricing, ignoreAvailability):
5944 mandeep.dh 664
    warehouse_retid = -1
665
    minTransferPrice = None
666
    total_availability = 0
6013 amar.kumar 667
    availabilityForBillingWarehouses = {}
668
    warehousesAvailability = {}
669
    availability = 0
670
    billing_warehouse_retid = None
5944 mandeep.dh 671
 
672
    if not ignoreAvailability:
673
        for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
7242 amar.kumar 674
            entry.reserved = max(entry.reserved, 0)
8524 amar.kumar 675
            entry.held = max(entry.held, 0)
6013 amar.kumar 676
            #if entry.availability > entry.reserved:
8182 amar.kumar 677
            warehousesAvailability[entry.warehouse_id] = [entry.availability, entry.reserved, entry.held] 
5944 mandeep.dh 678
 
6540 rajveer 679
    if len(ignoredWhs) > 0:
680
        for whid in ignoredWhs:
681
            if warehousesAvailability.has_key(whid):
6542 rajveer 682
                warehousesAvailability[whid][0] = 0
6683 rajveer 683
                warehousesAvailability[whid][1] = 0
8182 amar.kumar 684
                warehousesAvailability[whid][2] = 0
6540 rajveer 685
 
5944 mandeep.dh 686
    for warehouse in warehouses.values():
687
        if not ignoreAvailability:
6013 amar.kumar 688
            #TODO Mistake no entry for this warehouse.id in warehouseswithAvailab
689
            if warehouse.id not in warehousesAvailability:
690
                continue
691
            entry = warehousesAvailability[warehouse.id]
692
            if warehouse.billingWarehouseId in availabilityForBillingWarehouses:
693
                if warehouse.billingWarehouseId is not None or warehouse.billingWarehouseId != 0: 
8182 amar.kumar 694
                    availabilityForBillingWarehouses[warehouse.billingWarehouseId] = availabilityForBillingWarehouses[warehouse.billingWarehouseId] + entry[0] - entry[1] - entry[2]  
5944 mandeep.dh 695
            else:
6013 amar.kumar 696
                if warehouse.billingWarehouseId is not None or warehouse.billingWarehouseId != 0: 
8182 amar.kumar 697
                    availabilityForBillingWarehouses[warehouse.billingWarehouseId] = entry[0] - entry[1] - entry[2]
698
            if entry[0] <= (entry[1] + entry[2]):
5944 mandeep.dh 699
                continue
8182 amar.kumar 700
            total_availability += entry[0] - entry[1] - entry[2]
5944 mandeep.dh 701
 
702
        # Missing transfer price cases should not impact warehouse assignment
703
        transferPrice = None
704
        if item_pricing.has_key(warehouse.vendor_id):
6778 rajveer 705
            transferPrice = item_pricing[warehouse.vendor_id].nlc
5944 mandeep.dh 706
        if minTransferPrice is None or (transferPrice and minTransferPrice > transferPrice):
707
            warehouse_retid = warehouse.id
6013 amar.kumar 708
            billing_warehouse_retid = warehouse.billingWarehouseId
5944 mandeep.dh 709
            minTransferPrice = transferPrice
6013 amar.kumar 710
 
711
 
712
    if billing_warehouse_retid in availabilityForBillingWarehouses: 
713
        availability = availabilityForBillingWarehouses[billing_warehouse_retid]
714
    else:
715
        availability = total_availability
716
 
717
    return [warehouse_retid, availability]
5944 mandeep.dh 718
 
6540 rajveer 719
def __get_warehouse_with_min_transfer_delay(warehouses, ignoredWhs, item_id, item_pricing):
5944 mandeep.dh 720
    minTransferDelay = None
721
    minTransferDelayWarehouses = {}
722
    total_availability = 0
723
 
724
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
7242 amar.kumar 725
        entry.reserved = max(entry.reserved, 0)
8524 amar.kumar 726
        entry.held = max(entry.held, 0)
5944 mandeep.dh 727
        if warehouses.has_key(entry.warehouse_id):
728
            warehouse = warehouses[entry.warehouse_id]
6013 amar.kumar 729
            #if entry.availability > entry.reserved:
6683 rajveer 730
            if entry.warehouse_id not in ignoredWhs:
8182 amar.kumar 731
                total_availability += entry.availability - entry.reserved - entry.held
732
            if entry.availability - entry.reserved - entry.held <= 0:
6780 amar.kumar 733
                continue
6013 amar.kumar 734
            transferDelay = warehouse.transferDelayInHours
735
            if minTransferDelay is None or minTransferDelay >= transferDelay:
736
                if minTransferDelay != transferDelay:
737
                    minTransferDelayWarehouses = {}
738
                minTransferDelayWarehouses[warehouse.id] = warehouse
739
                minTransferDelay = transferDelay
5944 mandeep.dh 740
 
6540 rajveer 741
    return [__get_warehouse_with_min_transfer_price(minTransferDelayWarehouses, ignoredWhs, item_id, item_pricing, False)[0], total_availability]
5944 mandeep.dh 742
 
743
def __get_warehouse_with_max_availability(warehouse_ids, item_id):
744
    warehouse_retid = -1
745
    max_availability = 0
746
    total_availability = 0
747
 
748
    for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
7242 amar.kumar 749
        entry.reserved = max(entry.reserved, 0)
8524 amar.kumar 750
        entry.held = max(entry.held, 0)
5944 mandeep.dh 751
        if entry.warehouse_id in warehouse_ids:
752
            availability = entry.availability - entry.reserved
753
            if availability > max_availability:
754
                warehouse_retid = entry.warehouse_id
755
                max_availability = availability
756
            total_availability += availability
757
 
758
    return [warehouse_retid, total_availability]
759
 
8491 rajveer 760
def __get_vendor_holiday_delay(vendor_id, expectedDelay):
761
    ## If vendor is closed two days continuously
5944 mandeep.dh 762
    holidayDelay = 0
8491 rajveer 763
    currentDate = datetime.date.today()
764
    expectedDate = currentDate + datetime.timedelta(days = expectedDelay)
765
    holidays = VendorHolidays.query.filter(VendorHolidays.vendor_id == vendor_id).filter(VendorHolidays.date.between(currentDate, expectedDate)).all()
766
    if holidays:
767
        holidayDelay = holidayDelay + len(holidays)
5944 mandeep.dh 768
    return holidayDelay 
769
 
770
def get_item_pricing(item_id, vendorId):
771
    '''
772
    if vendor id is -1 then we calculate an average transfer price to be populated
773
    at the time of order creation. This will be later updated with actual transfer price
774
    at the time of billing.
775
    '''
776
    if(vendorId == -1):
6778 rajveer 777
        tp_total = 0
778
        nlc_total = 0
5944 mandeep.dh 779
        try:
780
            item_pricings = []
781
            item = __get_item_from_master(item_id)
782
            if item.preferredVendor is not None:
783
                item_pricing = VendorItemPricing.query.filter_by(item_id=item_id, vendor_id=item.preferredVendor).first()
784
                if item_pricing:
785
                    item_pricings.append(item_pricing)                    
786
            else :
787
                item_pricings = VendorItemPricing.query.filter_by(item_id=item_id).all()
788
            if item_pricings:
789
                for item_pricing in item_pricings:
6778 rajveer 790
                    tp_total += item_pricing.transfer_price
791
                    nlc_total += item_pricing.nlc
792
                tp_avg = tp_total / len(item_pricings)
793
                nlc_avg = nlc_total / len(item_pricings)
794
                item_pricing.transfer_price = tp_avg
795
                item_pricing.nlc = nlc_avg
5944 mandeep.dh 796
            else:
797
                item_pricing = VendorItemPricing()
798
                item_pricing.transfer_price = item.sellingPrice
6778 rajveer 799
                item_pricing.nlc = item.sellingPrice
5944 mandeep.dh 800
                vendor = Vendor()
801
                vendor.id = vendorId
802
                item_pricing.vendor = vendor
803
                item_pricing.item_id = item_id
804
 
805
            return item_pricing
806
        except:
807
            raise InventoryServiceException(101, "Item pricing not found ")
808
    vendor = Vendor.get_by(id=vendorId)    
809
    try:
810
        item_pricing = VendorItemPricing.query.filter_by(vendor=vendor, item_id=item_id).one()
811
        return item_pricing
812
    except MultipleResultsFound:
813
        raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
814
    except NoResultFound:
815
        raise InventoryServiceException(111, "Missing pricing information for Vendor: " + vendor.name + " and Item: " + str(item_id))
816
 
817
def get_all_item_pricing(item_id):
818
    item_pricing = VendorItemPricing.query.filter_by(item_id=item_id).all()
819
    return item_pricing
10126 amar.kumar 820
def get_all_vendor_item_pricing(item_id, vendor_id):
821
    query = VendorItemPricing.query
822
    if item_id:
823
        query = query.filter_by(item_id = item_id)
824
    if item_id:
825
        query = query.filter_by(vendor_id = vendor_id)
826
    item_pricing = query.all()
827
    return item_pricing
828
 
5944 mandeep.dh 829
def get_item_mappings(item_id):
830
    item_mappings = VendorItemMapping.query.filter_by(item_id=item_id).all()
831
    return item_mappings
832
 
833
def add_vendor_pricing(vendorItemPricing):
834
    if not vendorItemPricing:
835
        raise InventoryServiceException(108, "Bad vendorItemPricing in request")
836
    vendorId = vendorItemPricing.vendorId
837
    itemId = vendorItemPricing.itemId
838
 
839
    try:
840
        vendor = Vendor.query.filter_by(id=vendorId).one()
841
    except:
842
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
843
 
844
    try:
845
        item = __get_item_from_master(itemId)
846
    except:
847
        raise InventoryServiceException(101, "Item not found for itemId " + str(itemId))
848
 
849
    validate_vendor_prices(item, vendorItemPricing)
850
 
851
    try:
852
        ds_vendorItemPricing = VendorItemPricing.query.filter(and_(VendorItemPricing.vendor==vendor, VendorItemPricing.item_id==itemId)).one()
853
    except:
854
        ds_vendorItemPricing = VendorItemPricing()
855
        ds_vendorItemPricing.vendor = vendor
856
        ds_vendorItemPricing.item_id = itemId
857
 
858
    subject = ""
859
    message = ""
860
    if vendorItemPricing.mop:
861
        ds_vendorItemPricing.mop = vendorItemPricing.mop
862
    if vendorItemPricing.dealerPrice:
863
        ds_vendorItemPricing.dealerPrice = vendorItemPricing.dealerPrice
864
    if vendorItemPricing.transferPrice:
865
        if vendorItemPricing.transferPrice != ds_vendorItemPricing.transfer_price:
6617 amar.kumar 866
            client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
867
            item = client.getItem(itemId)
868
            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 869
            subject = "Alert:Change in Transfer Price {0} {1} {2} {3} {4}".format(item.brand, item.modelName, item.modelNumber, item.color, itemId)
5944 mandeep.dh 870
        ds_vendorItemPricing.transfer_price = vendorItemPricing.transferPrice
6751 amar.kumar 871
    if vendorItemPricing.nlc:
872
        if vendorItemPricing.nlc != ds_vendorItemPricing.nlc:
873
            client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
874
            item = client.getItem(itemId)
7315 amit.gupta 875
            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 876
            subject = "Alert:Change in NLC {0} {1} {2} {3} {4}".format(item.brand, item.modelName, item.modelNumber, item.color, itemId)
877
        ds_vendorItemPricing.nlc = vendorItemPricing.nlc
9895 vikram.rag 878
    session.commit()    
879
    client = CatalogClient("catalog_service_server_host_staging", "catalog_service_server_port").get_client()
880
    client.updateNlcAtMarketplaces(itemId,vendorId,ds_vendorItemPricing.nlc)
5944 mandeep.dh 881
    if subject:
882
        __send_mail(subject, message)
883
    return
884
 
885
def add_vendor_item_mapping(key, vendorItemMapping):
886
    if not vendorItemMapping:
887
        raise InventoryServiceException(108, "Bad vendorItemMapping in request")
888
    vendorId = vendorItemMapping.vendorId
889
    itemId = vendorItemMapping.itemId
890
 
891
    try:
892
        vendor = Vendor.query.filter_by(id=vendorId).one()
893
    except:
894
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
895
 
896
    try:
897
        ds_vendorItemMapping = VendorItemMapping.query.filter(and_(VendorItemMapping.vendor==vendor, VendorItemMapping.item_id==itemId, VendorItemMapping.item_key==key)).one()
898
    except:
899
        ds_vendorItemMapping = VendorItemMapping()
900
        ds_vendorItemMapping.vendor = vendor
901
        ds_vendorItemMapping.item_id = itemId
902
    ds_vendorItemMapping.item_key = vendorItemMapping.itemKey
903
 
904
    session.commit()
905
 
906
    # Marking the missed inventory as not ignored as the catalog dashboard user has updated their key
907
    for missedInventoryUpdate in MissedInventoryUpdate.query.filter_by(itemKey = vendorItemMapping.itemKey).all():
908
        missedInventoryUpdate.isIgnored = 0
909
    session.commit()
910
 
911
    return
912
 
913
def validate_vendor_prices(item, vendorPrices):
914
    if item.mrp != None and item.mrp != "" and vendorPrices.mop != "" and item.mrp <  vendorPrices.mop:
915
        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))
916
        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 917
    return
18459 kshitij.so 918
    #if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
18460 kshitij.so 919
#         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))
920
#         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)))
921
    #return 
5944 mandeep.dh 922
 
923
def get_all_vendors():
924
    return Vendor.query.all()
925
 
926
def get_pending_orders_inventory(vendor_id=1):
927
    """
928
    Returns a list of inventory stock for items for which there are pending orders.
929
    """
930
 
931
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter_by(vendor_id = vendor_id)]
932
    pending_items_inventory = []
933
    if warehouse_ids:
934
        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()
935
    return pending_items_inventory
936
 
7149 amar.kumar 937
def get_billable_inventory_and_pending_orders():
938
    """
939
    Returns a list of inventory Availability and Reserved Count for items which either have real inventory
940
    or have pending orders.
941
    """
942
 
943
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter(Warehouse.isAvailabilityMonitored == 1).filter(or_(Warehouse.inventoryType == 'GOOD', Warehouse.warehouseType == 'OURS'))]
944
    items_inventory = []
945
    reserved_items_inventory = []
946
    available_items_inventory = []
947
    if warehouse_ids:
948
        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()
949
        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()
950
 
951
    items_inventory.extend(reserved_items_inventory)
952
    items_inventory.extend(available_items_inventory)
953
    return items_inventory
954
 
955
 
5944 mandeep.dh 956
def close_session():
957
    if session.is_active:
958
        print "session is active. closing it."
959
        session.close()
960
 
961
def is_alive():
962
    try:
963
        session.query(Vendor.id).limit(1).one()
964
        return True
965
    except:
966
        return False
967
 
968
def add_vendor(vendor):
969
    if not vendor:
970
        raise InventoryServiceException(108, "Bad vendor")
971
    if get_vendor(vendor.id):
972
        #vendor is already present.
973
        raise InventoryServiceException(101, "Vendor already present")
974
 
975
    ds_vendor = Vendor()
976
    ds_vendor.id = vendor.id
977
    ds_vendor.name = vendor.name
978
    session.commit()
979
    return ds_vendor.id
980
 
981
def add_warehouse_vendor_mapping(warehouse_id, VendorId):
982
    return True
983
 
984
def mark_missed_inventory_updates_as_processed(itemKey, warehouseId):
985
    MissedInventoryUpdate.query.filter_by(itemKey = itemKey, warehouseId = warehouseId).delete()
986
    session.commit()
987
 
988
def get_item_keys_to_be_processed(warehouseId):
989
    return [i.itemKey for i in MissedInventoryUpdate.query.filter_by(warehouseId = warehouseId, isIgnored = 0)]
990
 
991
def reset_availability(itemKey, vendorId, quantity, warehouseId):
992
    vendorItemMapping = VendorItemMapping.get_by(vendor_id = vendorId, item_key = itemKey)
993
    if vendorItemMapping:
994
        itemId = vendorItemMapping.item_id
995
 
996
        if skippedItems.has_key(warehouseId) and itemId in skippedItems[warehouseId]:
997
            quantity = 0
998
 
999
        currentInventorySnapshot = CurrentInventorySnapshot.get_by(item_id = itemId, warehouse_id = warehouseId)
1000
        if currentInventorySnapshot:
1001
            currentInventorySnapshot.availability = quantity
5978 rajveer 1002
            clear_item_availability_cache(itemId) 
5944 mandeep.dh 1003
        else:
1004
            add_inventory(itemId, warehouseId, quantity)
1005
 
1006
    else:
1007
        raise InventoryServiceException(101, 'VendorMapping not found for: ' + itemKey)
1008
    session.commit()
1009
 
1010
def reset_availability_for_warehouse(warehouseId):
13149 manish.sha 1011
    itemIds = []
5944 mandeep.dh 1012
    for currentInventorySnapshot in CurrentInventorySnapshot.query.filter_by(warehouse_id=warehouseId).all():
1013
        currentInventorySnapshot.availability = 0
13149 manish.sha 1014
        itemIds.append(currentInventorySnapshot.item_id)
1015
    clear_item_availability_cache(itemIds) 
5944 mandeep.dh 1016
    session.commit()
1017
 
7718 amar.kumar 1018
def get_our_warehouse_id_for_vendor(vendor_id, billing_warehouse_id):
6467 amar.kumar 1019
    try:
7718 amar.kumar 1020
        warehouse = Warehouse.query.filter_by(vendor_id = vendor_id, warehouseType = 'OURS', inventoryType = 'GOOD', billingWarehouseId = billing_warehouse_id).first()
6467 amar.kumar 1021
        return warehouse.id
1022
    except Exception as e:
1023
        print e;
7755 amar.kumar 1024
        raise InventoryServiceException(101, 'No our warehouse found for vendorId: ' + str(vendor_id))
5944 mandeep.dh 1025
 
1026
def __send_mail(subject, message):
1027
    try:
6029 rajveer 1028
        thread = threading.Thread(target=partial(mail, mail_user, mail_password, to_addresses, subject, message))
5944 mandeep.dh 1029
        thread.start()
1030
    except Exception as ex:
1031
        print ex    
1032
 
1033
def get_shipping_locations():
1034
    shippingLocationIds = {}
1035
    warehouses = Warehouse.query.all()
1036
    for warehouse in warehouses:
1037
        if warehouse.shippingWarehouseId:
1038
            shippingLocationIds[warehouse.shippingWarehouseId] = 1
1039
 
1040
    shippingLocations = []
1041
    for shippingLocationId in shippingLocationIds:
1042
        shippingLocations.append(get_Warehouse(shippingLocationId))
1043
 
1044
    return shippingLocations
1045
 
1046
def get_inventory_snapshot(warehouseId):
1047
    query = CurrentInventorySnapshot.query
1048
 
1049
    if warehouseId:
1050
        query = query.filter_by(warehouse_id = warehouseId)
1051
 
1052
    itemInventoryMap = {}
1053
    for row in query.all():
1054
        if not itemInventoryMap.has_key(row.item_id):
1055
            itemInventoryMap[row.item_id] = []
1056
 
1057
        itemInventoryMap[row.item_id].append(row)
1058
 
1059
    return itemInventoryMap
1060
 
1061
def update_vendor_string(warehouseId, vendorString):
1062
    warehouse = get_Warehouse(warehouseId)
1063
    warehouse.vendorString = vendorString
1064
    session.commit()
1065
 
1066
def __get_item_from_master(item_id):
1067
    client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
5978 rajveer 1068
    return client.getItem(item_id)
1069
 
1070
def __check_risky_item(item_id, source_id):
1071
    ## We should get the list of strings which will identify to the catalog servers
1072
    if source_id == 1:
1073
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
1074
        client.validateRiskyStatus(item_id)
1075
    if source_id == 2:
1076
        client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
1077
        client.validateRiskyStatus(item_id)
1078
 
1079
def __get_item_from_source(item_id, source_id):
1080
    if source_id == 1:
1081
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
1082
        return client.getItem(item_id)
1083
    if source_id == 2:
1084
        client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
6531 vikram.rag 1085
        return client.getItem(item_id)
1086
 
1087
def get_monitored_warehouses_for_vendors(vendorIds):
1088
    w = []
1089
    for wh in Warehouse.query.filter_by(isAvailabilityMonitored = 1).all():
1090
        if wh.vendor.id in (vendorIds):
1091
            w.append(to_t_warehouse(wh).id)
1092
    return w
1093
def get_ignored_warehouseids_and_itemids():
1094
    iw = []
1095
    for i in IgnoredInventoryUpdateItems.query.all():
1096
        iw.append(to_t_itemidwarehouseid(i)) 
1097
    return iw
1098
def insert_item_to_ignore_inventory_update_list(item_id,warehouse_id):
1099
    try:
1100
        ds_warehouse=IgnoredInventoryUpdateItems()
1101
        ds_warehouse.item_id=item_id
1102
        ds_warehouse.warehouse_id=warehouse_id
6532 amit.gupta 1103
        clear_item_availability_cache(item_id)
6531 vikram.rag 1104
        session.commit()
1105
        return True
1106
    except:
1107
        return False       
1108
def delete_item_from_ignore_inventory_update_list(item_id,warehouse_id):
1109
    try:
1110
        session.query(IgnoredInventoryUpdateItems).filter_by(item_id=item_id,warehouse_id=warehouse_id).delete()
6532 amit.gupta 1111
        clear_item_availability_cache(item_id)
6531 vikram.rag 1112
        session.commit()
1113
        return True
1114
    except:
1115
        return False           
1116
 
1117
def get_all_ignored_inventoryupdate_items_count():
1118
    return  session.query(func.count(distinct(IgnoredInventoryUpdateItems.item_id))).scalar()
1119
 
1120
def get_ignored_inventoryupdate_itemids(offset=0,limit=None):
1121
    itemIds = session.query(distinct(IgnoredInventoryUpdateItems.item_id))
1122
    '''if limit is not None:
1123
        itemIds = itemIds.limit(limit)'''
1124
    print itemIds.all()
1125
    return [id for (id, ) in itemIds.all()]
6821 amar.kumar 1126
 
1127
def update_item_stock_purchase_params(item_id, numOfDaysStock, minStockLevel):
1128
    if numOfDaysStock is None or minStockLevel is None:
1129
        raise InventoryServiceException(108, "Bad params : numOfDaysStock = " + str(numOfDaysStock) + "minStockLevel = " + str(minStockLevel))
1130
    itemStockPurchaseParams = ItemStockPurchaseParams.query.filter_by(item_id = item_id).first()
1131
    if itemStockPurchaseParams is None:
1132
        itemStockPurchaseParams = ItemStockPurchaseParams()
1133
    itemStockPurchaseParams.item_id = item_id
1134
    itemStockPurchaseParams.numOfDaysStock = numOfDaysStock
1135
    itemStockPurchaseParams.minStockLevel = minStockLevel
1136
    session.commit()
1137
 
1138
def get_item_stock_purchase_params(item_id):
1139
    return ItemStockPurchaseParams.query.filter_by(item_id = item_id).first()
1140
 
1141
def add_oos_status_for_item(oosStatusMap, date):
1142
 
1143
    oosDate = to_py_date(date)
1144
    oosDate.replace(second=0, microsecond=0)
1145
 
1146
    cartAdditionStartDate = oosDate - datetime.timedelta(days = 1)
1147
 
1148
    client = TransactionClient().get_client()
1149
 
1150
    #Gets physical orders in the last day
1151
    orders = client.getPhysicalOrders(to_java_date(cartAdditionStartDate), to_java_date(oosDate))
8019 amar.kumar 1152
    rtoOrders = client.getAllOrders([20], 0, 0, 0)
9665 rajveer 1153
    orderCountByItemIdSourceId = {}
1154
    rtoOrderCountByItemIdSourceId = {}
1155
 
6821 amar.kumar 1156
    for order in orders:
9665 rajveer 1157
        if not orderCountByItemIdSourceId.has_key(order.lineitems[0].item_id):
1158
            orderCountByItemIdSourceId[order.lineitems[0].item_id] = {}
1159
 
1160
        if orderCountByItemIdSourceId[order.lineitems[0].item_id].has_key(order.source):
18430 manish.sha 1161
            orderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = orderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] + order.lineitems[0].quantity
6821 amar.kumar 1162
        else:
18430 manish.sha 1163
            orderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = order.lineitems[0].quantity
9665 rajveer 1164
 
8019 amar.kumar 1165
 
1166
    for order in rtoOrders:
9665 rajveer 1167
        if not rtoOrderCountByItemIdSourceId.has_key(order.lineitems[0].item_id):
1168
            rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id] = {}
1169
 
1170
        if rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id].has_key(order.source):
18430 manish.sha 1171
            rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] + order.lineitems[0].quantity 
8019 amar.kumar 1172
        else:
18430 manish.sha 1173
            rtoOrderCountByItemIdSourceId[order.lineitems[0].item_id][order.source] = order.lineitems[0].quantity
9665 rajveer 1174
 
1175
 
6821 amar.kumar 1176
    for itemId, status in oosStatusMap.iteritems():
9665 rajveer 1177
        total_order_count = 0 
9791 rajveer 1178
        total_rto_count = 0
13726 manish.sha 1179
        for sid in (1,3,4,6,7,8):
6821 amar.kumar 1180
            oosStatus = OOSStatus()
1181
            oosStatus.item_id = itemId
1182
            oosStatus.date = oosDate
9791 rajveer 1183
            oosStatus.sourceId  = sid
1184
            order_count = 0
1185
            rto_count = 0
1186
            if orderCountByItemIdSourceId.has_key(itemId) and orderCountByItemIdSourceId[itemId].has_key(sid):
1187
                order_count = orderCountByItemIdSourceId[itemId][sid]
1188
            if rtoOrderCountByItemIdSourceId.has_key(itemId) and rtoOrderCountByItemIdSourceId[itemId].has_key(sid):
18430 manish.sha 1189
                rto_count = rtoOrderCountByItemIdSourceId[itemId][sid]
9791 rajveer 1190
            oosStatus.num_orders = order_count
1191
            oosStatus.rto_orders = rto_count
9666 rajveer 1192
            oosStatus.is_oos = status
9791 rajveer 1193
            if oosStatus.is_oos and order_count > 0:
1194
                oosStatus.is_oos = False
1195
            total_order_count = total_order_count + order_count
1196
            total_rto_count = total_rto_count + rto_count
1197
        oosStatus = OOSStatus()
1198
        oosStatus.item_id = itemId
1199
        oosStatus.date = oosDate
1200
        oosStatus.sourceId  = 0
1201
        oosStatus.num_orders = total_order_count
1202
        oosStatus.rto_orders = total_rto_count
9804 rajveer 1203
        if itemId in orderCountByItemIdSourceId and 1 in orderCountByItemIdSourceId[itemId]:
1204
            order_count = orderCountByItemIdSourceId[itemId][1]
9791 rajveer 1205
        oosStatus.is_oos = status
1206
        if oosStatus.is_oos and order_count > 0:
1207
            oosStatus.is_oos = False
6821 amar.kumar 1208
 
9791 rajveer 1209
        session.commit()
1210
 
9861 rajveer 1211
 
1212
    itemCountMap = {}
1213
    oosDate = oosDate - datetime.timedelta(days = 1) - datetime.timedelta(hours = 1)
1214
    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()
1215
    for line in lines:
1216
        item_id = line[0]
9896 rajveer 1217
        quantity = int(math.ceil(max(1,2*line[1])))
9861 rajveer 1218
        itemCountMap[item_id] = quantity
9862 rajveer 1219
    cl = CatalogClient('catalog_service_server_host_prod','catalog_service_server_port').get_client()
9861 rajveer 1220
    cl.updateItemHoldInventory(itemCountMap)
9791 rajveer 1221
 
9665 rajveer 1222
def get_oos_statuses_for_x_days_for_item(itemId, sourceId, days):
6832 amar.kumar 1223
    timestamp = datetime.datetime.now()
9640 amar.kumar 1224
    timestamp = timestamp - datetime.timedelta(days = days)
9665 rajveer 1225
    return OOSStatus.query.filter_by(item_id = itemId).filter_by(sourceId = sourceId).filter(OOSStatus.date > timestamp).all()
6857 amar.kumar 1226
 
10126 amar.kumar 1227
def get_oos_statuses_for_x_days(sourceId, days):
1228
    timestamp = datetime.datetime.now()
1229
    timestamp = timestamp - datetime.timedelta(days = days)
1230
    if sourceId == -1:
1231
        return OOSStatus.query.filter(OOSStatus.date > timestamp).all()
1232
    else:
1233
        return OOSStatus.query.filter_by(sourceId = sourceId).filter(OOSStatus.date > timestamp).all()
1234
 
6857 amar.kumar 1235
def get_non_zero_item_stock_purchase_params():
7281 kshitij.so 1236
    return ItemStockPurchaseParams.query.filter(or_("numOfDaysStock!=0","minStockLevel!=0"))
1237
 
7972 amar.kumar 1238
def get_last_n_day_sale_for_item(itemId, numberOfDays):
1239
    lastNdaySale = ""
9685 rajveer 1240
    oosStatuses = get_oos_statuses_for_x_days_for_item(itemId, 0, numberOfDays)
7972 amar.kumar 1241
    for oosStatus in oosStatuses:
1242
        if oosStatus.is_oos == True:
1243
            lastNdaySale +="X-"
1244
        else:
1245
            lastNdaySale +=str(oosStatus.num_orders) + "-"
1246
    return lastNdaySale[:-1] 
1247
 
7281 kshitij.so 1248
def get_warehouse_name(warehouseId):
1249
    row = Warehouse.get_by(id = warehouseId)
1250
    return row.displayName
1251
 
1252
def get_amazon_inventory_for_item(amazonItemId):
1253
    inventory = AmazonInventorySnapshot.get_by(item_id=amazonItemId)
1254
    return inventory
1255
 
1256
def get_all_amazon_inventory():
1257
    return session.query(AmazonInventorySnapshot).all()
1258
 
10450 vikram.rag 1259
def add_or_update_amazon_inventory_for_item(amazoninventorysnapshot,time):
7281 kshitij.so 1260
    inventory = AmazonInventorySnapshot.get_by(item_id = amazoninventorysnapshot.item_id)
1261
    if inventory is None:
1262
        amazon_inventory = AmazonInventorySnapshot()
1263
        amazon_inventory.item_id = amazoninventorysnapshot.item_id
1264
        amazon_inventory.availability = amazoninventorysnapshot.availability
1265
        amazon_inventory.reserved = amazoninventorysnapshot.reserved
10450 vikram.rag 1266
        amazon_inventory.is_oos = amazoninventorysnapshot.is_oos
1267
        if time != 0:
1268
            amazon_inventory.lastUpdatedOnAmazon = to_py_date(time)
1269
    else: 
7281 kshitij.so 1270
        inventory.availability = amazoninventorysnapshot.availability
1271
        inventory.reserved = amazoninventorysnapshot.reserved
10450 vikram.rag 1272
        if not inventory.is_oos and (to_py_date(time) - inventory.lastUpdatedOnAmazon).days == 0:
1273
            pass
1274
        else:
1275
            inventory.is_oos = amazoninventorysnapshot.is_oos
1276
        if time != 0:    
1277
            inventory.lastUpdatedOnAmazon = to_py_date(time)      
7281 kshitij.so 1278
    session.commit()
1279
 
8182 amar.kumar 1280
def add_update_hold_inventory(itemId, warehouseId, holdQuantity, source):
9762 amar.kumar 1281
    if holdQuantity <0:
1282
        print "Negative holdQuantity : " + str(holdQuantity) + " is not allowed"
1283
        raise InventoryServiceException(108, "Negative heldQuantity is not allowed")
8197 amar.kumar 1284
    hold_inventory_detail = HoldInventoryDetail.get_by(item_id = itemId, warehouse_id=warehouseId, source = source)
1285
    if  hold_inventory_detail is None:
8182 amar.kumar 1286
        diffTobeAddedInCIS = holdQuantity
1287
        hold_inventory_detail = HoldInventoryDetail()
1288
        hold_inventory_detail.item_id = itemId 
1289
        hold_inventory_detail.warehouse_id = warehouseId 
1290
        hold_inventory_detail.held = holdQuantity 
1291
        hold_inventory_detail.source = source
1292
    else:
8497 amar.kumar 1293
        diffTobeAddedInCIS = holdQuantity - hold_inventory_detail.held
8182 amar.kumar 1294
        hold_inventory_detail.held = holdQuantity
1295
 
1296
    current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
1297
    if not current_inventory_snapshot:
1298
        current_inventory_snapshot = CurrentInventorySnapshot()
1299
        current_inventory_snapshot.item_id = itemId
1300
        current_inventory_snapshot.warehouse_id = warehouseId
1301
        current_inventory_snapshot.availability = 0
1302
        current_inventory_snapshot.reserved = 0
1303
        current_inventory_snapshot.held = 0
1304
    current_inventory_snapshot.held = current_inventory_snapshot.held + diffTobeAddedInCIS
1305
    session.commit()
1306
    #**Update item availability cache**#
1307
    clear_item_availability_cache(itemId)
8282 kshitij.so 1308
 
1309
def add_or_update_amazon_fba_inventory(amazonfbainventorysnapshot):
11173 vikram.rag 1310
    inventory = AmazonFbaInventorySnapshot.query.filter_by(item_id = amazonfbainventorysnapshot.item_id,location=amazonfbainventorysnapshot.location).first()
8282 kshitij.so 1311
    if inventory is None:
1312
        amazon_fba_inventory = AmazonFbaInventorySnapshot()
1313
        amazon_fba_inventory.item_id = amazonfbainventorysnapshot.item_id
1314
        amazon_fba_inventory.availability = amazonfbainventorysnapshot.availability
11173 vikram.rag 1315
        amazon_fba_inventory.location = amazonfbainventorysnapshot.location
1316
        amazon_fba_inventory.reserved = amazonfbainventorysnapshot.reserved
1317
        amazon_fba_inventory.inbound = amazonfbainventorysnapshot.inbound
1318
        amazon_fba_inventory.unfulfillable = amazonfbainventorysnapshot.unfulfillable
1319
 
8282 kshitij.so 1320
    else:
11173 vikram.rag 1321
        print 'updating'
8282 kshitij.so 1322
        inventory.availability = amazonfbainventorysnapshot.availability
11173 vikram.rag 1323
        inventory.location = amazonfbainventorysnapshot.location
1324
        inventory.reserved = amazonfbainventorysnapshot.reserved
1325
        inventory.inbound = amazonfbainventorysnapshot.inbound
1326
        inventory.unfulfillable = amazonfbainventorysnapshot.unfulfillable
8282 kshitij.so 1327
 
1328
 
1329
def get_amazon_fba_inventory(itemId):
11173 vikram.rag 1330
    return AmazonFbaInventorySnapshot.query.filter_by(item_id = itemId)
8282 kshitij.so 1331
 
8363 vikram.rag 1332
def get_all_amazon_fba_inventory():
1333
    return AmazonFbaInventorySnapshot.query.all() 
1334
 
12799 manish.sha 1335
def get_oursgood_warehouseids_for_location(stateId):
8363 vikram.rag 1336
    warehouseId=[]
12799 manish.sha 1337
    x= session.query(Warehouse.id).filter(Warehouse.id==Warehouse.billingWarehouseId).filter(Warehouse.warehouseType=='OURS').filter(Warehouse.state_id==stateId).all()
8363 vikram.rag 1338
    for id in x:
1339
        warehouseId.append(id[0])
1340
    return session.query(Warehouse.id).filter(Warehouse.inventoryType=='GOOD').filter(Warehouse.warehouseType=='OURS').filter(Warehouse.billingWarehouseId.in_(warehouseId)).all()
8954 vikram.rag 1341
 
1342
def get_holdinventorydetail_forItem_forWarehouseId_exceptsource(item_id,warehouse_id,source):
1343
    holddetails = HoldInventoryDetail.query.filter(HoldInventoryDetail.item_id == item_id).all()
1344
    print holddetails
1345
    hold = 0
1346
    for holddetail in holddetails:
1347
        if holddetail.source !=source and holddetail.warehouse_id == warehouse_id:
1348
            hold = hold + holddetail.held
9404 vikram.rag 1349
    return hold
1350
 
1351
def get_snapdeal_inventory_for_item(id):
1352
    print SnapdealInventorySnapshot.get_by(item_id = id)
1353
    return SnapdealInventorySnapshot.get_by(item_id = id)
1354
 
1355
def add_or_update_snapdeal_inventor_for_item(snapdealinventoryitem):
1356
    snapdeal_inventory_item = SnapdealInventorySnapshot.get_by(item_id = snapdealinventoryitem.item_id)
1357
    if snapdeal_inventory_item is None:
1358
        snapdeal_inventory_item = SnapdealInventorySnapshot()
1359
        snapdeal_inventory_item.item_id = snapdealinventoryitem.item_id
1360
        snapdeal_inventory_item.availability = snapdealinventoryitem.availability
9495 vikram.rag 1361
        snapdeal_inventory_item.pendingOrders = snapdealinventoryitem.pendingOrders
9404 vikram.rag 1362
        snapdeal_inventory_item.lastUpdatedOnSnapdeal = to_py_date(snapdealinventoryitem.lastUpdatedOnSnapdeal)
10450 vikram.rag 1363
        snapdeal_inventory_item.is_oos = snapdealinventoryitem.is_oos
9404 vikram.rag 1364
    else:
1365
        snapdeal_inventory_item.availability = snapdealinventoryitem.availability
9495 vikram.rag 1366
        snapdeal_inventory_item.pendingOrders = snapdealinventoryitem.pendingOrders
10450 vikram.rag 1367
        if not snapdeal_inventory_item.is_oos and (to_py_date(snapdealinventoryitem.lastUpdatedOnSnapdeal) - snapdeal_inventory_item.lastUpdatedOnSnapdeal).days == 0:
1368
            pass
1369
        else:
1370
            snapdeal_inventory_item.is_oos = snapdealinventoryitem.is_oos
9404 vikram.rag 1371
        snapdeal_inventory_item.lastUpdatedOnSnapdeal = to_py_date(snapdealinventoryitem.lastUpdatedOnSnapdeal)
1372
    session.commit()
8954 vikram.rag 1373
 
9404 vikram.rag 1374
def get_nlc_for_warehouse(warehouse_id,itemid):
1375
    warehouse = Warehouse.get_by(id=warehouse_id)
1376
    if warehouse is None:
1377
        return 0
1378
    vendoritempricing = VendorItemPricing.query.filter_by(item_id=itemid, vendor_id=warehouse.vendor_id).first()
1379
    '''vendoritempricing = VendorItemPricing.get_by(id=warehouse.vendor_id,item_id=itemid)'''
1380
    if vendoritempricing is None:
1381
        return 0
9456 vikram.rag 1382
    return vendoritempricing.nlc
1383
 
9495 vikram.rag 1384
def get_snapdeal_inventory_snapshot():
9640 amar.kumar 1385
    return SnapdealInventorySnapshot.query.all()
10050 vikram.rag 1386
 
9640 amar.kumar 1387
def get_held_inventory_map_for_item(itemId, warehouseId):
1388
    heldInventoryMap = {}
1389
    holdInventories = HoldInventoryDetail.query.filter_by(item_id= itemId, warehouse_id = warehouseId).all()
1390
    for holdInventory in holdInventories:
1391
        heldInventoryMap[holdInventory.source] = holdInventory.held
1392
    return heldInventoryMap 
10050 vikram.rag 1393
 
9761 amar.kumar 1394
def get_hold_inventory_details(itemId, warehouseId, source):
1395
    heldInventoryQuery = HoldInventoryDetail.query
1396
    if itemId:
1397
        heldInventoryQuery = heldInventoryQuery.filter_by(item_id = itemId)
1398
    if warehouseId:
1399
        heldInventoryQuery = heldInventoryQuery.filter_by(warehouse_id = warehouseId)
1400
    if source:
1401
        heldInventoryQuery = heldInventoryQuery.filter_by(source = source)
1402
    holdInventoryDetails = heldInventoryQuery.all()
1403
    return holdInventoryDetails
9896 rajveer 1404
 
10450 vikram.rag 1405
def add_or_update_flipkart_inventory_snapshot(flipkartInventorySnapshot,time):
10050 vikram.rag 1406
    for snapshot in flipkartInventorySnapshot:
1407
        flipkart_inventory = FlipkartInventorySnapshot.get_by(item_id = snapshot.item_id)
1408
        if flipkart_inventory is None:
1409
            flipkart_inventory = FlipkartInventorySnapshot()
1410
            flipkart_inventory.item_id = snapshot.item_id
1411
            flipkart_inventory.availability = snapshot.availability
1412
            flipkart_inventory.createdOrders = snapshot.createdOrders
1413
            flipkart_inventory.heldOrders = snapshot.heldOrders
10450 vikram.rag 1414
            flipkart_inventory.is_oos = snapshot.is_oos
1415
            flipkart_inventory.lastUpdatedOnFlipkart = to_py_date(time) 
10050 vikram.rag 1416
        else:
1417
            flipkart_inventory.availability = snapshot.availability
1418
            flipkart_inventory.createdOrders = snapshot.createdOrders
1419
            flipkart_inventory.heldOrders = snapshot.heldOrders
10450 vikram.rag 1420
            if not flipkart_inventory.is_oos and (to_py_date(time) - flipkart_inventory.lastUpdatedOnFlipkart).days == 0:
1421
                pass
1422
            else:
1423
                flipkart_inventory.is_oos = snapshot.is_oos
1424
            flipkart_inventory.lastUpdatedOnFlipkart = to_py_date(time) 
10050 vikram.rag 1425
    session.commit()
1426
 
1427
def get_flipkart_inventory_snapshot():
1428
    return FlipkartInventorySnapshot.query.all()     
1429
 
10097 kshitij.so 1430
def get_flipkart_inventory_for_Item(itemId):
10485 vikram.rag 1431
    return FlipkartInventorySnapshot.get_by(item_id = itemId)
1432
 
1433
def get_state_master():
1434
    stateIdNameMap = {} 
1435
    statemaster = StateMaster.query.all()
1436
    for state in statemaster:
12280 amit.gupta 1437
        stateIdNameMap[state.id] = to_t_state(state)
10544 vikram.rag 1438
    return stateIdNameMap    
1439
 
1440
def update_snapdeal_stock_at_eod(allsnapdealstock):
1441
    for stockitem in allsnapdealstock:
1442
        snapdealstockateod = SnapdealStockAtEOD()
1443
        snapdealstockateod.item_id = stockitem.item_id
1444
        snapdealstockateod.availability = stockitem.availability
1445
        snapdealstockateod.date =  to_py_date(stockitem.date)
1446
    session.commit()
1447
 
1448
def update_flipkart_stock_at_eod(allflipkartstock):
1449
    for stockitem in allflipkartstock:
1450
        snapdealstockateod = FlipkartStockAtEOD()
1451
        snapdealstockateod.item_id = stockitem.item_id
1452
        snapdealstockateod.availability = stockitem.availability
1453
        snapdealstockateod.date =  to_py_date(stockitem.date)
1454
    session.commit()
10687 rajveer 1455
 
12363 kshitij.so 1456
def get_wanlc_for_source(item_id,sourceId):
1457
    stockWanlc = StockWeightedNlcInfo.query.filter(StockWeightedNlcInfo.itemId==item_id).filter(StockWeightedNlcInfo.source==sourceId).order_by(desc(StockWeightedNlcInfo.updatedTimestamp)).limit(1).all()
1458
    if stockWanlc is None or len(stockWanlc)==0:
1459
        return 0.0
1460
    else:
1461
        return stockWanlc[0].avgWeightedNlc
1462
 
1463
def get_all_available_amazon_inventory():
1464
    return AmazonFbaInventorySnapshot.query.filter(AmazonFbaInventorySnapshot.availability>0).all() 
1465