Subversion Repositories SmartDukaan

Rev

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