Subversion Repositories SmartDukaan

Rev

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