Subversion Repositories SmartDukaan

Rev

Rev 5731 | Rev 5866 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
94 ashish 1
'''
2
Created on 23-Mar-2010
3
 
4
@author: ashish
5
'''
6
from elixir import *
5393 mandeep.dh 7
from functools import partial
4748 mandeep.dh 8
from pydoc import Helper
9
from shop2020.clients.HelperClient import HelperClient
10
from shop2020.clients.TransactionClient import TransactionClient
11
from shop2020.config.client.ConfigClient import ConfigClient
94 ashish 12
from shop2020.model.v1.catalog.impl import DataService
4748 mandeep.dh 13
from shop2020.model.v1.catalog.impl.CategoryManager import CategoryManager
5318 rajveer 14
from shop2020.model.v1.catalog.impl.Convertors import to_t_item, to_t_source
4748 mandeep.dh 15
from shop2020.model.v1.catalog.impl.DataService import Item, Warehouse, \
5393 mandeep.dh 16
    ItemInventoryHistory, CurrentInventorySnapshot, ItemChangeLog, Category, \
17
    EntityIDGenerator, VendorItemPricing, VendorItemMapping, Vendor, SimilarItems, \
18
    ProductNotification, Source, SourceItemPricing, AuthorizationLog, \
5110 mandeep.dh 19
    MissedInventoryUpdate, BadInventorySnapshot, VendorItemProcurementDelay, \
5504 phani.kuma 20
    VendorHolidays, ItemAvailabilityCache, VoucherItemMapping
4748 mandeep.dh 21
from shop2020.thriftpy.model.v1.catalog.ttypes import InventoryServiceException, \
5393 mandeep.dh 22
    status, ItemShippingInfo, HolidayType, InventoryType, WarehouseType, ItemType
4748 mandeep.dh 23
from shop2020.thriftpy.model.v1.order.ttypes import AlertType
4873 mandeep.dh 24
from shop2020.utils import EmailAttachmentSender
4748 mandeep.dh 25
from shop2020.utils.EmailAttachmentSender import mail
5318 rajveer 26
from shop2020.utils.Utils import to_py_date, log_risky_flag
621 chandransh 27
from sqlalchemy import desc, asc
3244 chandransh 28
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
3872 chandransh 29
from sqlalchemy.sql.expression import and_, or_, distinct, func
3086 rajveer 30
from string import Template
4748 mandeep.dh 31
from urllib2 import HTTPBasicAuthHandler
5110 mandeep.dh 32
import calendar
4748 mandeep.dh 33
import datetime
34
import sys
5393 mandeep.dh 35
import threading
3924 rajveer 36
import urllib2
5586 phani.kuma 37
from shop2020.clients.CatalogClient import CatalogClient
94 ashish 38
 
5047 amit.gupta 39
to_addresses = ["cnc.center@shop2020.in", "ashutosh.saxena@shop2020.in"]
40
from_user = "cnc.center@shop2020.in"
41
from_pwd = "5h0p2o2o"
42
 
5295 rajveer 43
def initialize(dbname='catalog', db_hostname="localhost"):
44
    DataService.initialize(dbname, db_hostname)
5336 rajveer 45
 
3849 chandransh 46
def get_all_items_by_status(status, offset=0, limit=None):
47
    query = Item.query
4539 rajveer 48
    if status is not None:
3849 chandransh 49
        query = query.filter_by(status=status)
50
    query = query.order_by(Item.product_group, Item.brand, Item.model_number, Item.model_name).offset(offset)
51
    if limit:
52
        query = query.limit(limit)
53
    items = query.all()
54
    return items
55
 
56
def get_all_items(is_active, offset=0, limit=None):
103 ashish 57
    if is_active:
3849 chandransh 58
        items = get_all_items_by_status(status.ACTIVE, offset, limit)
103 ashish 59
    else:
3849 chandransh 60
        items = get_all_items_by_status(None, offset, limit)
766 rajveer 61
    return items
62
 
3849 chandransh 63
def get_item_count_by_status(use_status, status):
64
    if use_status:
65
        return Item.query.filter_by(status=status).count()
103 ashish 66
    else:
3849 chandransh 67
        return Item.query.count()
103 ashish 68
 
635 rajveer 69
def get_item(item_id):
766 rajveer 70
    item = Item.get_by(id=item_id)
71
    return item
94 ashish 72
 
635 rajveer 73
def get_items_by_catalog_id(catalog_id):
447 rajveer 74
    query = Item.query.filter_by(catalog_item_id=catalog_id)
437 rajveer 75
    try:
635 rajveer 76
        items = query.all()
4934 amit.gupta 77
        return items
1399 rajveer 78
    except Exception as ex:
79
        print ex
437 rajveer 80
        raise InventoryServiceException(109, "Item not found")
5586 phani.kuma 81
 
82
def is_valid_catalog_id(catalog_id):
83
    item = Item.query.filter_by(catalog_item_id=catalog_id).first()
84
    if item is not None:
85
        return True
86
    else:
87
        return False
88
 
576 chandransh 89
def is_active(item_id):
2983 chandransh 90
    t_item_shipping_info = ItemShippingInfo()
576 chandransh 91
    try:
635 rajveer 92
        item = get_item(item_id)
3281 chandransh 93
        t_item_shipping_info.isRisky = item.risky
5393 mandeep.dh 94
        warehouse_id = get_item_availability_for_location(item.id)[0]
95
        if item.risky and item.status == status.ACTIVE:
96
            availability = 0
97
            currentInventorySnapshot = CurrentInventorySnapshot.query.filter_by(item_id = item.id, warehouse_id = warehouse_id).all()
5424 rajveer 98
            if not currentInventorySnapshot or currentInventorySnapshot[0].availability <= currentInventorySnapshot[0].reserved:
5393 mandeep.dh 99
                add_status_change_log(item, status.PAUSED_BY_RISK)
100
                item.status = status.PAUSED_BY_RISK
101
                item.status_description = "This item is currently out of stock"
102
                session.commit()
103
                __send_mail_for_oos_item(item)
104
                #This will clear cache from tomcat
105
                __clear_homepage_cache()
106
            else:
5513 mandeep.dh 107
                availability = currentInventorySnapshot[0].availability - currentInventorySnapshot[0].reserved
5393 mandeep.dh 108
        else:
109
            availability = item.get_total_inventory
2983 chandransh 110
        t_item_shipping_info.isActive = (item.status == status.ACTIVE)
3281 chandransh 111
        t_item_shipping_info.quantity = availability
576 chandransh 112
    except InventoryServiceException:
2983 chandransh 113
        print "[ERROR] Unexpected error:", sys.exc_info()[0]
114
    return t_item_shipping_info
115
 
2035 rajveer 116
def get_item_status_description(itemId):
117
    item = get_item(itemId)
118
    return item.status_description
563 chandransh 119
 
94 ashish 120
def get_Warehouse(warehouse_id):
121
    return Warehouse.get_by(id=warehouse_id)
122
 
4332 anupam.sin 123
def get_Vendor(vendorId):
124
    return Vendor.get_by(id=vendorId)
125
 
122 ashish 126
def get_all_warehouses_by_status(status):
5114 mandeep.dh 127
    return Warehouse.query.all()
122 ashish 128
 
94 ashish 129
def get_all_warehouses_for_item(item_id):
635 rajveer 130
    item = get_item(item_id)
94 ashish 131
    if not item:
122 ashish 132
        raise InventoryServiceException(108, "Some unforeseen error while obtaining item")
133
    return item.get_all_warehouses
94 ashish 134
 
122 ashish 135
def get_all_items_for_warehouse(warehouse_id):
136
    warehouse = get_Warehouse(warehouse_id)
137
    if not warehouse:
138
        raise InventoryServiceException(108, "bad warehouse")
139
    return warehouse.all_items
140
 
94 ashish 141
def add_warehouse(warehouse):
103 ashish 142
    if not warehouse:
122 ashish 143
        raise InventoryServiceException(108, "Bad warehouse")
103 ashish 144
    if get_Warehouse(warehouse.id):
145
        #warehouse is already present.
122 ashish 146
        raise InventoryServiceException(101, "Warehouse already present")
103 ashish 147
 
94 ashish 148
    ds_warehouse = Warehouse()
149
    ds_warehouse.location = warehouse.location
122 ashish 150
    ds_warehouse.status = status.ACTIVE
103 ashish 151
    ds_warehouse.addedOn = datetime.datetime.now()
483 rajveer 152
    ds_warehouse.lastCheckedOn = datetime.datetime.now()
153
    ds_warehouse.tinNumber = warehouse.tinNumber
154
    ds_warehouse.pincode = warehouse.pincode
5591 mandeep.dh 155
    ds_warehouse.billingType = warehouse.billingType
156
    ds_warehouse.billingWarehouseId = warehouse.billingWarehouseId
157
    ds_warehouse.displayName = warehouse.displayName
158
    ds_warehouse.inventoryType = InventoryType._VALUES_TO_NAMES[warehouse.inventoryType]
159
    ds_warehouse.isAvailabilityMonitored = warehouse.isAvailabilityMonitored
160
    ds_warehouse.logisticsLocation = warehouse.logisticsLocation
161
    ds_warehouse.shippingWarehouseId = warehouse.shippingWarehouseId
162
    ds_warehouse.transferDelayInHours = warehouse.transferDelayInHours
163
    ds_warehouse.vendor = get_Vendor(warehouse.vendor.id)
164
    ds_warehouse.warehouseType = WarehouseType._VALUES_TO_NAMES[warehouse.warehouseType]    
483 rajveer 165
    if warehouse.vendorString:
166
        ds_warehouse.vendorString = warehouse.vendorString
94 ashish 167
    session.commit()
103 ashish 168
    return ds_warehouse.id
94 ashish 169
 
122 ashish 170
def update_item(item):
171
    if not item:
172
        raise InventoryServiceException(108, "Bad item in request")
173
 
174
    if not item.id:
609 chandransh 175
        raise InventoryServiceException(101, "Missing id for update")
122 ashish 176
 
2120 ankur.sing 177
    validate_item_prices(item)
2065 ankur.sing 178
 
635 rajveer 179
    ds_item = get_item(item.id)
5047 amit.gupta 180
    message = ""
122 ashish 181
    if not ds_item:
609 chandransh 182
        raise InventoryServiceException(101, "Item missing in our database")
122 ashish 183
 
963 chandransh 184
    if item.productGroup:
185
        ds_item.product_group = item.productGroup 
186
    if item.brand:
187
        ds_item.brand = item.brand
511 rajveer 188
    if item.modelNumber:
189
        ds_item.model_number = item.modelNumber
2497 ankur.sing 190
    ds_item.color = item.color
191
    ds_item.model_name = item.modelName
192
    ds_item.category = item.category
193
    ds_item.comments = item.comments
511 rajveer 194
 
2497 ankur.sing 195
    ds_item.catalog_item_id = item.catalogItemId
483 rajveer 196
 
2129 ankur.sing 197
    ds_item.mrp = item.mrp
5047 amit.gupta 198
    if ds_item.sellingPrice or item.sellingPrice:
199
        if ds_item.sellingPrice != item.sellingPrice:
200
            message += "Selling Price is changed from {0} to {1}.\n".format(ds_item.sellingPrice, item.sellingPrice)
201
 
2129 ankur.sing 202
    ds_item.sellingPrice = item.sellingPrice
2497 ankur.sing 203
 
2174 ankur.sing 204
    ds_item.weight = item.weight
2129 ankur.sing 205
 
2358 ankur.sing 206
    if ds_item.status != item.itemStatus:
2402 rajveer 207
        add_status_change_log(ds_item, item.itemStatus)
5047 amit.gupta 208
        if item.itemStatus == status.PHASED_OUT:
209
            message += "Item is phased out."
2358 ankur.sing 210
        ds_item.status = item.itemStatus
2035 rajveer 211
    if item.status_description:
212
        ds_item.status_description = item.status_description
122 ashish 213
 
511 rajveer 214
    if item.startDate:
2116 ankur.sing 215
        ds_item.startDate = to_py_date(item.startDate)
2497 ankur.sing 216
    else:
217
        ds_item.startDate = None
511 rajveer 218
    if item.retireDate:
2116 ankur.sing 219
        ds_item.retireDate = to_py_date(item.retireDate)
2497 ankur.sing 220
    else:
221
        ds_item.retireDate = None
5217 amit.gupta 222
 
223
    if item.expectedArrivalDate:
224
        ds_item.expectedArrivalDate = to_py_date(item.expectedArrivalDate)
225
    else:
226
        ds_item.expectedArrivalDate = None
511 rajveer 227
 
5217 amit.gupta 228
    if item.comingSoonStartDate:
229
        ds_item.comingSoonStartDate = to_py_date(item.comingSoonStartDate)
230
    else:
231
        ds_item.comingSoonStartDate = None
232
 
233
 
2497 ankur.sing 234
    ds_item.feature_id = item.featureId
235
    ds_item.feature_description = item.featureDescription
122 ashish 236
 
5047 amit.gupta 237
    if ds_item.bestDealText or item.bestDealText:
238
        if item.bestDealText != ds_item.bestDealText:
5080 amit.gupta 239
            message += "Promotion text is changed from '{0}' to '{1}'.\n".format(ds_item.bestDealText, item.bestDealText)
2129 ankur.sing 240
    ds_item.bestDealText = item.bestDealText
241
    ds_item.bestDealValue = item.bestDealValue
2065 ankur.sing 242
    ds_item.bestSellingRank = item.bestSellingRank
2497 ankur.sing 243
 
2065 ankur.sing 244
    ds_item.defaultForEntity = item.defaultForEntity
5047 amit.gupta 245
 
246
    if ds_item.risky or item.risky:
247
        if ds_item.risky != item.risky:
5080 amit.gupta 248
            message += "Risky flag is changed to '{0}'.\n".format(set)
5047 amit.gupta 249
 
2251 ankur.sing 250
    ds_item.risky = item.risky
3359 chandransh 251
 
5385 phani.kuma 252
    ds_item.type = ItemType._VALUES_TO_NAMES[item.type]
253
    ds_item.hasItemNo = item.hasItemNo
5460 phani.kuma 254
    ds_item.clearance = item.clearance
5385 phani.kuma 255
 
3459 chandransh 256
    if item.expectedDelay is not None:
3359 chandransh 257
        ds_item.expectedDelay = item.expectedDelay
4506 phani.kuma 258
 
259
    if item.preferredVendor:
5080 amit.gupta 260
        if item.preferredVendor != ds_item.preferredVendor:
261
            newPreferredVendorName = get_Vendor(item.preferredVendor).name
262
            oldPreferredVendorName = 'None'
263
            if ds_item.preferredVendor:
264
                oldPreferredVendorName = get_Vendor(ds_item.preferredVendor).name
5408 amit.gupta 265
            message += "Preferred vendor is changed from '{0}' to '{1}'.\n".format(oldPreferredVendorName, newPreferredVendorName)        
4506 phani.kuma 266
        ds_item.preferredVendor = item.preferredVendor
5080 amit.gupta 267
 
268
    if item.isWarehousePreferenceSticky != ds_item.isWarehousePreferenceSticky:
269
        flag = "ON" if item.isWarehousePreferenceSticky else "OFF"
270
        message += "Warehouse preference sticky is {0}.\n".format(flag)
271
 
4413 anupam.sin 272
    ds_item.isWarehousePreferenceSticky = item.isWarehousePreferenceSticky
3359 chandransh 273
 
2347 ankur.sing 274
    ds_item.updatedOn = datetime.datetime.now()
2065 ankur.sing 275
 
122 ashish 276
    session.commit();
5047 amit.gupta 277
    subject = "Item '{0}' is updated in Catalog. Id is {1}".format(__get_product_name(ds_item),ds_item.id)
278
    if message:
279
        __send_mail(subject, message)
122 ashish 280
    return ds_item.id
94 ashish 281
 
103 ashish 282
def add_item(item):
283
    if not item:
122 ashish 284
        raise InventoryServiceException(108, "Bad item in request")
635 rajveer 285
    if get_item(item.id):
122 ashish 286
        raise InventoryServiceException(101, "Item already exists")
2120 ankur.sing 287
 
288
    validate_item_prices(item)
289
 
103 ashish 290
    ds_item = Item()
963 chandransh 291
    if item.productGroup:
292
        ds_item.product_group = item.productGroup
293
    if item.brand:
294
        ds_item.brand = item.brand
515 rajveer 295
    if item.modelName:
296
        ds_item.model_name = item.modelName
297
    if item.modelNumber:
298
        ds_item.model_number = item.modelNumber
609 chandransh 299
    if item.color:
300
        ds_item.color = item.color
483 rajveer 301
    if item.category:
302
        ds_item.category = item.category
303
    if item.comments:
304
        ds_item.comments = item.comments
305
 
103 ashish 306
    ds_item.addedOn = datetime.datetime.now()
609 chandransh 307
    ds_item.updatedOn = datetime.datetime.now()
2116 ankur.sing 308
    if item.startDate:
309
        ds_item.startDate = to_py_date(item.startDate)
310
    if item.retireDate:
311
        ds_item.retireDate = to_py_date(item.retireDate)
5217 amit.gupta 312
    if item.comingSoonStartDate:
313
        ds_item.comingSoonStartDate = to_py_date(item.comingSoonStartDate)
314
    if item.expectedArrivalDate:
315
        ds_item.expectedArrivalDate = to_py_date(item.expectedArrivalDate)    
483 rajveer 316
    if item.mrp:
317
        ds_item.mrp = item.mrp
318
    if item.sellingPrice:
319
        ds_item.sellingPrice = item.sellingPrice
122 ashish 320
    if item.weight:
321
        ds_item.weight = item.weight
322
 
323
    if item.featureId:
324
        ds_item.feature_id = item.featureId
325
    if item.featureDescription:
326
        ds_item.feature_description = item.featureDescription
327
 
2116 ankur.sing 328
 
103 ashish 329
    #check if categories present. If yes, add them to system
122 ashish 330
 
609 chandransh 331
    if item.bestDealValue:
332
        ds_item.bestDealValue = item.bestDealValue
333
    if item.bestDealText:
334
        ds_item.bestDealText = item.bestDealText
2116 ankur.sing 335
    if item.bestSellingRank:
336
        ds_item.bestSellingRank = item.bestSellingRank
337
    ds_item.defaultForEntity = item.defaultForEntity
2251 ankur.sing 338
    ds_item.risky = item.risky
609 chandransh 339
 
5385 phani.kuma 340
    ds_item.type = ItemType._VALUES_TO_NAMES[item.type]
341
    ds_item.hasItemNo = item.hasItemNo
5460 phani.kuma 342
    ds_item.clearance = item.clearance
5385 phani.kuma 343
 
3467 chandransh 344
    if item.expectedDelay is not None:
3359 chandransh 345
        ds_item.expectedDelay = item.expectedDelay
3467 chandransh 346
    else:
347
        ds_item.expectedDelay = 0
3359 chandransh 348
 
5408 amit.gupta 349
    preferredVendorName = "None"
4881 phani.kuma 350
    if item.preferredVendor:
351
        ds_item.preferredVendor = item.preferredVendor
5408 amit.gupta 352
        preferredVendorName = get_Vendor(item.preferredVendor).name
4881 phani.kuma 353
 
5586 phani.kuma 354
    if item.catalogItemId:
355
        catalog_client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
356
        master_items = catalog_client.getItemsByCatalogId(item.catalogItemId)
357
        itemStatus = status.IN_PROCESS
358
        for masterItem in master_items:
359
            if masterItem.itemStatus in [status.CONTENT_COMPLETE, status.COMING_SOON, status.ACTIVE, status.PAUSED]:
360
                itemStatus = status.CONTENT_COMPLETE
361
                ds_item.category = masterItem.category
362
                break
363
        ds_item.catalog_item_id = item.catalogItemId
364
        ds_item.status = itemStatus
2116 ankur.sing 365
        ds_item.status_description = "This item is in process."
366
    else:
5586 phani.kuma 367
        # Check if a similar item already exists in our database
368
        similar_item = Item.query.filter_by(brand=item.brand, model_number=item.modelNumber, model_name=item.modelName).first()
369
        print "[SIMILAR ITEM FOUND:] FOR {0} {1} {2}".format(item.brand, item.modelNumber, item.modelName)
370
 
371
        if similar_item is None or similar_item.catalog_item_id is None:
372
            # If there is no similar item in the database from before,
373
            # use the entity_id_generator
374
            entity_id = EntityIDGenerator.query.first()
375
            ds_item.catalog_item_id = entity_id.id + 1
376
            ds_item.status = status.IN_PROCESS
377
            ds_item.status_description = "This item is in process."
378
            entity_id.id = entity_id.id  + 1
379
            if similar_item is not None and similar_item.catalog_item_id is None:
380
                similar_item.catalog_item_id = entity_id.id
381
        else:
382
            #If a similar item already exists for a product group, brand and model_number, set it as same.
383
            ds_item.catalog_item_id = similar_item.catalog_item_id
384
            ds_item.category = similar_item.category
385
            ds_item.product_group = similar_item.product_group
386
            ds_item.status = similar_item.status
387
            ds_item.status_description = similar_item.status_description
2116 ankur.sing 388
 
103 ashish 389
    session.commit();
5052 amit.gupta 390
    subject = "New item is added. Id is {0}".format(str(ds_item.id))
5408 amit.gupta 391
    message = "Category : {6}, Brand : {0}, Model : {1}, Model Number : {2}\nColor : {3}, Selling Price : {4}, Mrp : {5}, \nPromotion Text : {7}, Preferred Vendor: {8}".format(item.brand, item.modelNumber, item.modelName, item.color, item.sellingPrice, item.mrp, item.category, item.bestDealText, preferredVendorName)
5047 amit.gupta 392
    __send_mail(subject, message)
3325 chandransh 393
    return ds_item.id
394
 
395
def update_inventory_history(warehouse_id, timestamp, availability):
396
    warehouse = get_Warehouse(warehouse_id)
397
    if not warehouse:
398
        raise InventoryServiceException(107, "Warehouse? Where?")
5124 mandeep.dh 399
    vendor = warehouse.vendor
3325 chandransh 400
    time = datetime.datetime.now()
401
    for item_key, quantity in availability.iteritems():
402
        try:
403
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
404
            item = vendor_item_mapping.item
405
        except:
406
            continue  
407
        try:
408
            item_inventory_history = ItemInventoryHistory()
409
            item_inventory_history.warehouse = warehouse
410
            item_inventory_history.item = item
411
            item_inventory_history.timestamp = time
5424 rajveer 412
            item_inventory_history.availability = quantity
3325 chandransh 413
        except:
414
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
415
    session.commit()
103 ashish 416
 
483 rajveer 417
def update_inventory(warehouse_id, timestamp, availability):
418
    warehouse = get_Warehouse(warehouse_id)
419
    if not warehouse:
420
        raise InventoryServiceException(107, "Warehouse? Where?")
421
 
422
    time = datetime.datetime.now()
423
    warehouse.lastCheckedOn = time
424
    warehouse.vendorString = timestamp
5116 mandeep.dh 425
    vendor = warehouse.vendor
2368 ankur.sing 426
    session.commit()
5457 rajveer 427
    items = []
1368 chandransh 428
    for item_key, quantity in availability.iteritems():
483 rajveer 429
        try:
1368 chandransh 430
            vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
431
            item = vendor_item_mapping.item
5457 rajveer 432
            items.append(item)
494 rajveer 433
        except:
4873 mandeep.dh 434
            print 'Skipping update for ' + item_key + ' quantity ' + str(quantity) + ' warehouse id: ' + str(warehouse_id)
435
            __send_mail_for_missing_key(item_key, quantity, warehouse_id)
4748 mandeep.dh 436
            continue
494 rajveer 437
        try:
483 rajveer 438
            current_inventory_snapshot = CurrentInventorySnapshot.get_by(item=item, warehouse=warehouse)
439
            if not current_inventory_snapshot:
440
                current_inventory_snapshot = CurrentInventorySnapshot()
441
                current_inventory_snapshot.item = item
442
                current_inventory_snapshot.warehouse = warehouse
5424 rajveer 443
                current_inventory_snapshot.availability = 0
871 chandransh 444
                current_inventory_snapshot.reserved = 0
483 rajveer 445
            # added the difference in the current inventory    
5424 rajveer 446
            current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
4400 rajveer 447
            try:
448
                if quantity > 0 and __get_item_reserved(item) > 0:
449
                    cl = TransactionClient().get_client()
4448 rajveer 450
                    #FIXME hardcoding for warehouse id 
451
                    cl.addAlert(AlertType.NEW_INVENTORY_ALERT, 5, "Inventory received for item " + item.brand + " " + item.model_name + " " + item.model_number + " " +  item.color)
4400 rajveer 452
            except:
453
                print "Not able to raise alert for incoming inventory" 
5424 rajveer 454
            if current_inventory_snapshot.availability < 0:
455
                __send_alert_for_negative_availability(item, current_inventory_snapshot.availability, warehouse)
483 rajveer 456
        except:
457
            raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
2368 ankur.sing 458
        session.commit() 
5295 rajveer 459
        #**Update item availability cache**#
5457 rajveer 460
        for item in items:
461
            __update_item_availability_cache(item.id)
462
            check_risky_item(item)
483 rajveer 463
 
4822 mandeep.dh 464
def __send_alert_for_negative_reserved(item, reserved, warehouse):
4873 mandeep.dh 465
    itemName = " ".join([str(item.id), str(item.brand), str(item.model_name), str(item.model_number), str(item.color)])
466
    EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', 'mandeep.dhir@shop2020.in', 'Negative reserved: ' + str(reserved) + ' for Item Id: ' + itemName + ' warehouse id: ' + str(warehouse.id), None)
4822 mandeep.dh 467
 
468
def __send_alert_for_negative_availability(item, availability, warehouse):
4873 mandeep.dh 469
    itemName = " ".join([str(item.id), str(item.brand), str(item.model_name), str(item.model_number), str(item.color)])
5213 mandeep.dh 470
    # EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', 'mandeep.dhir@shop2020.in', 'Negative availability ' + str(availability) + ' for Item id: ' + itemName + ' warehouse id: ' + str(warehouse.id), None)
4822 mandeep.dh 471
 
4873 mandeep.dh 472
def __send_mail_for_missing_key(item_key, quantity, warehouse_id):
4985 mandeep.dh 473
    missedInventoryUpdate = MissedInventoryUpdate.get_by(itemKey = item_key, warehouseId = warehouse_id)
474
    # One email per product key mismatch
475
    if not missedInventoryUpdate:
5110 mandeep.dh 476
        EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', ['mandeep.dhir@shop2020.in', 'chaitnaya.vats@shop2020.in', 'asghar.bilgrami@shop2020.in'], 'Skipped inventory update for ' + item_key + ' quantity ' + str(quantity) + ' warehouse id: ' + str(warehouse_id), None)
4873 mandeep.dh 477
        missedInventoryUpdate = MissedInventoryUpdate()
478
        missedInventoryUpdate.itemKey = item_key
479
        missedInventoryUpdate.quantity = quantity
4985 mandeep.dh 480
        missedInventoryUpdate.isIgnored = 1
4873 mandeep.dh 481
        missedInventoryUpdate.timestamp = datetime.datetime.now()
482
        missedInventoryUpdate.warehouseId = warehouse_id
4748 mandeep.dh 483
        session.commit()
4985 mandeep.dh 484
    else:
485
        missedInventoryUpdate.quantity += quantity
486
        session.commit()
4748 mandeep.dh 487
 
4320 rajveer 488
def add_inventory(itemId, warehouseId, quantity):
489
    current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
490
    if not current_inventory_snapshot:
491
        current_inventory_snapshot = CurrentInventorySnapshot()
492
        current_inventory_snapshot.item_id = itemId
493
        current_inventory_snapshot.warehouse_id = warehouseId
5424 rajveer 494
        current_inventory_snapshot.availability = 0
4320 rajveer 495
        current_inventory_snapshot.reserved = 0
496
    # added the difference in the current inventory    
5424 rajveer 497
    current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
4813 rajveer 498
    session.commit()
5295 rajveer 499
    #**Update item availability cache**#
500
    __update_item_availability_cache(itemId)
5424 rajveer 501
    if current_inventory_snapshot.availability < 0:
502
        __send_alert_for_negative_availability(get_item(itemId), current_inventory_snapshot.availability, get_Warehouse(warehouseId))
4813 rajveer 503
    check_risky_item(get_item(itemId)) 
94 ashish 504
 
5110 mandeep.dh 505
def add_bad_inventory(itemId, warehouseId, quantity):
506
    bad_inventory_snapshot = BadInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
507
    if not bad_inventory_snapshot:
508
        bad_inventory_snapshot = BadInventorySnapshot()
509
        bad_inventory_snapshot.item_id = itemId
510
        bad_inventory_snapshot.warehouse_id = warehouseId
511
        bad_inventory_snapshot.availability = 0
512
    # added the difference in the current inventory    
513
    bad_inventory_snapshot.availability += quantity
514
    session.commit()
515
    if bad_inventory_snapshot.availability < 0:
516
        __send_alert_for_negative_availability(get_item(itemId), bad_inventory_snapshot.availability, get_Warehouse(warehouseId))
517
 
635 rajveer 518
def get_item_inventory_by_item_id(item_id):
5381 rajveer 519
    return Item.get_by(id=item_id).currentInventory
103 ashish 520
 
521
def retire_warehouse(warehouse_id):
522
    if not warehouse_id:
122 ashish 523
        raise InventoryServiceException(101, "Bad warehouse id")
103 ashish 524
    warehouse = get_Warehouse(warehouse_id)
525
    if not warehouse:
122 ashish 526
        raise InventoryServiceException(108, "warehouse id not present")
527
    warehouse.status = status.DELETED;
103 ashish 528
    session.commit()
529
 
530
def retire_item(item_id):
531
    if not item_id:
122 ashish 532
        raise InventoryServiceException(101, "bad item id")
635 rajveer 533
    item = get_item(item_id)
103 ashish 534
    if not item:
122 ashish 535
        raise InventoryServiceException(108, "item id not present")
536
    item.status = status.PHASED_OUT
537
    item.retireDate = datetime.datetime.now()
103 ashish 538
    session.commit()
122 ashish 539
 
540
#need to implement threads based solution here
103 ashish 541
def start_item_on(item_id, timestamp):
542
    if not item_id:
122 ashish 543
        raise InventoryServiceException(101, "bad item id")
635 rajveer 544
    item = get_item(item_id)
103 ashish 545
    if not item:
122 ashish 546
        raise InventoryServiceException(108, "item id not present")
103 ashish 547
 
122 ashish 548
    item.status = status.ACTIVE
549
    item.startDate = datetime.datetime.fromtimestamp(to_py_date(timestamp))
550
    add_status_change_log(item, status.ACTIVE)
103 ashish 551
    session.commit()
552
 
122 ashish 553
#need to implement threads here
103 ashish 554
def retire_item_on(item_id, timestamp):
555
    if not item_id:
122 ashish 556
        raise InventoryServiceException(101, "bad item id")
635 rajveer 557
    item = get_item(item_id)
103 ashish 558
    if not item:
122 ashish 559
        raise InventoryServiceException(108, "item id not present")
103 ashish 560
 
122 ashish 561
    item.status = status.PHASED_OUT
562
    item.retireDate = datetime.datetime.fromtimestamp(to_py_date(timestamp))
563
    add_status_change_log(item, status.PHASED_OUT)
103 ashish 564
    session.commit()
565
 
566
def add_status_change_log(item, new_status):
567
    item_change_log = ItemChangeLog()
568
    item_change_log.new_status = new_status
569
    item_change_log.old_status = item.status
570
    item_change_log.timestamp = datetime.datetime.now()
571
    item_change_log.item = item
572
    session.commit()
573
 
574
def change_item_status(item_id, new_status):
575
    if not item_id:
122 ashish 576
        raise InventoryServiceException(101, "bad item id")
635 rajveer 577
    item = get_item(item_id)
103 ashish 578
    if not item:
122 ashish 579
        raise InventoryServiceException(108, "item id not present")
2116 ankur.sing 580
    add_status_change_log(item, new_status)
122 ashish 581
    item.status = new_status
2251 ankur.sing 582
    if item.status == status.PHASED_OUT:
583
        item.status_description = "This item has been phased out"
5047 amit.gupta 584
        __send_mail("Item '{0}' is Phased-Out. Item id is {1}".format(__get_product_name(item), item_id), "")
2251 ankur.sing 585
    elif item.status == status.DELETED:
586
        item.status_description = "This item has been deleted"
3924 rajveer 587
    elif item.status == status.PAUSED:
588
        item.status_description = "This item is currently out of stock"      
589
    elif item.status == status.PAUSED_BY_RISK:
590
        item.status_description = "This item is currently out of stock"
591
        #This will clear cache from tomcat
592
        __clear_homepage_cache()  
2251 ankur.sing 593
    elif item.status == status.ACTIVE:
594
        item.status_description = "This item is active"
5047 amit.gupta 595
        __send_mail("Item '{0}' is Active. Item id is {1}".format(__get_product_name(item), item_id), "")
2251 ankur.sing 596
    elif item.status == status.IN_PROCESS:
597
        item.status_description = "This item is in process"
598
    elif item.status == status.CONTENT_COMPLETE:
599
        item.status_description = "This item is in process"
103 ashish 600
    session.commit()
601
 
602
def get_item_availability_for_warehouse(warehouse_id, item_id):
603
    if not warehouse_id:
122 ashish 604
        raise InventoryServiceException(101, "bad warehouse_id")
103 ashish 605
    if not item_id:
122 ashish 606
        raise InventoryServiceException(101, "bad item_id")
103 ashish 607
 
608
    warehouse = get_Warehouse(warehouse_id)
609
    if not warehouse:
122 ashish 610
        raise InventoryServiceException(108, "warehouse does not exist")
635 rajveer 611
    item = get_item(item_id)
504 rajveer 612
 
103 ashish 613
    if not item:
766 rajveer 614
        raise InventoryServiceException(108, "item does not exist")
122 ashish 615
 
494 rajveer 616
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id)
504 rajveer 617
    query = query.filter_by(item_id = item.id)
494 rajveer 618
    try:
619
        current_inventory_snapshot = query.one()
5424 rajveer 620
        return current_inventory_snapshot.availability - current_inventory_snapshot.reserved
494 rajveer 621
    except:
622
        return 0
623
    """
624
    current_inventory_snapshot = CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id == warehouse_id, CurrentInventorySnapshot.item_id == item_id).one()
103 ashish 625
    if not current_inventory_snapshot:
626
        return 0
627
    else:
5424 rajveer 628
        return current_inventory_snapshot.availability
494 rajveer 629
    """
643 chandransh 630
 
2368 ankur.sing 631
def check_risky_item(item):
2251 ankur.sing 632
    if not item.risky:
633
        return
5393 mandeep.dh 634
    warehouse_id = get_item_availability_for_location(item.id)[0]
635
    currentInventorySnapshot = CurrentInventorySnapshot.query.filter_by(item_id = item.id, warehouse_id = warehouse_id).all()
5424 rajveer 636
    if not currentInventorySnapshot or currentInventorySnapshot[0].availability <= currentInventorySnapshot[0].reserved:
2251 ankur.sing 637
        if item.status == status.ACTIVE:
2984 rajveer 638
            change_item_status(item.id, status.PAUSED_BY_RISK)
4797 rajveer 639
            __send_mail_for_oos_item(item)
2251 ankur.sing 640
    else:
2984 rajveer 641
        if item.status == status.PAUSED_BY_RISK:
2251 ankur.sing 642
            change_item_status(item.id, status.ACTIVE)
2368 ankur.sing 643
    session.commit()
2251 ankur.sing 644
 
4406 anupam.sin 645
'''
646
This method returns quantity of a particular item across all warehouses whose ids is provided
647
if warehouse_ids is null it checks for inventory in all warehouses.
648
'''
649
def __get_item_availability(item, warehouse_ids):
650
    if warehouse_ids is None:
651
        all_inventory = CurrentInventorySnapshot.query.filter_by(item = item).all()
652
        availability = 0
653
        reserved = 0
654
        for currInv in all_inventory:
5424 rajveer 655
            availability = availability + currInv.availability
4406 anupam.sin 656
            reserved = reserved + currInv.reserved
657
        return availability - reserved
658
    else:
659
        total_availability = 0
5333 mandeep.dh 660
        for current_inventory_snapshot in CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).filter_by(item_id = item.id).all():
5424 rajveer 661
            total_availability += current_inventory_snapshot.availability - current_inventory_snapshot.reserved
4406 anupam.sin 662
        return total_availability 
4400 rajveer 663
 
664
def __get_item_reserved(item):
665
    all_inventory = CurrentInventorySnapshot.query.filter_by(item = item).all()
666
    reserved = 0
667
    for currInv in all_inventory:
668
        reserved = reserved + currInv.reserved
669
    return reserved
2983 chandransh 670
 
871 chandransh 671
def reserve_item_in_warehouse(item_id, warehouse_id, quantity):    
672
    if not warehouse_id:
673
        raise InventoryServiceException(101, "bad warehouse_id")
2251 ankur.sing 674
    item = get_item(item_id)
675
    if not item:
871 chandransh 676
        raise InventoryServiceException(101, "bad item_id")
677
 
678
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
679
    try:
680
        current_inventory_snapshot = query.one()
681
    except:
4103 chandransh 682
        current_inventory_snapshot = CurrentInventorySnapshot()
683
        current_inventory_snapshot.warehouse_id = warehouse_id
684
        current_inventory_snapshot.item_id = item_id
5424 rajveer 685
        current_inventory_snapshot.availability = 0
4103 chandransh 686
        current_inventory_snapshot.reserved = 0
687
 
688
    current_inventory_snapshot.reserved = current_inventory_snapshot.reserved + quantity
689
    session.commit()
5295 rajveer 690
    #**Update item availability cache**#
691
    __update_item_availability_cache(item_id)
4103 chandransh 692
    check_risky_item(item)
693
    return True
871 chandransh 694
 
695
def reduce_reservation_count(item_id, warehouse_id, quantity):
696
    if not warehouse_id:
697
        raise InventoryServiceException(101, "bad warehouse_id")
2251 ankur.sing 698
    item = get_item(item_id)
699
    if not item:
871 chandransh 700
        raise InventoryServiceException(101, "bad item_id")
701
 
702
    query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
703
    try:
704
        current_inventory_snapshot = query.one()
705
        current_inventory_snapshot.reserved = current_inventory_snapshot.reserved - quantity
706
        session.commit()
5295 rajveer 707
        #**Update item availability cache**#
708
        __update_item_availability_cache(item_id)
2368 ankur.sing 709
        check_risky_item(item)
4822 mandeep.dh 710
        if current_inventory_snapshot.reserved < 0:
711
            __send_alert_for_negative_reserved(get_item(item_id), current_inventory_snapshot.reserved, get_Warehouse(warehouse_id))
871 chandransh 712
        return True
713
    except:
714
        print "Unexpected error:", sys.exc_info()[0]
715
        return False
716
 
2075 rajveer 717
def mark_item_as_content_complete(entity_id, category, brand, modelName, modelNumber):
2828 rajveer 718
    '''
719
    Get all the items for this entityID and update category, brand, modelName and modelNumber for all.
720
    Update Status for only IN_PROCESS items to CONTENT_COMPLETE
721
    '''
723 chandransh 722
    content_complete_status = status.CONTENT_COMPLETE
2828 rajveer 723
    items = Item.query.filter_by(catalog_item_id=entity_id).all()
723 chandransh 724
    current_timestamp = datetime.datetime.now()
725
    for item in items:
2828 rajveer 726
        if item.status == status.IN_PROCESS:
727
            item.status = content_complete_status
728
            item_change_log = ItemChangeLog()
729
            item_change_log.old_status = item.status
730
            item_change_log.new_status = content_complete_status
731
            item_change_log.timestamp = current_timestamp
732
            item_change_log.item = item
723 chandransh 733
 
4762 phani.kuma 734
        category_object = get_category(category)
735
        if category_object is not None:
736
            item.category = category
737
            item.product_group = category_object.display_name
2075 rajveer 738
        item.brand = brand
2081 rajveer 739
        item.model_name = modelName
740
        item.model_number = modelNumber
723 chandransh 741
        item.updatedOn = current_timestamp
742
    session.commit()
743
    return True
1294 chandransh 744
 
5295 rajveer 745
def get_item_availability_for_location(item_id):
5318 rajveer 746
    item_availability = ItemAvailabilityCache.get_by(itemId=item_id)
747
    if item_availability:
748
        return [item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice]
749
    else:
750
        __update_item_availability_cache(item_id)
751
        return get_item_availability_for_location(item_id)
5295 rajveer 752
 
5336 rajveer 753
def clear_item_availability_cache():
5318 rajveer 754
    ItemAvailabilityCache.query.delete()
755
    session.commit()
5295 rajveer 756
 
757
def __update_item_availability_cache(item_id):
3355 chandransh 758
    """
759
    Determines the warehouse that should be used to fulfil an order for the given item.
5110 mandeep.dh 760
    Algorithm explained at https://sites.google.com/a/shop2020.in/virtual-w-h-and-inventory/technical-details
761
 
5393 mandeep.dh 762
    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.
763
    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.
764
 
765
    if item available at any OUR-GOOD warehouse
766
        // OUR-GOOD warehouses have inventory risk; So, we empty them first! 
767
        // We can start with minimum transfer price criterion but down the line we can also bring in Inventory age 
768
        assign OUR-GOOD warehouse with minimum transfer price
5110 mandeep.dh 769
    else
5393 mandeep.dh 770
        if Preferred vendor is specified and marked Sticky
771
            // Always purchase from Preferred if its marked sticky
772
            assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
773
        else 
774
            if item available in a THIRDPARTY GOOD/VIRTUAL warehouse
775
                assign THIRDPARTY GOOD/VIRTUAL warehouse where item is available with minimal transfer delay followed by minimum transfer price
776
            else 
777
                // Item not available at any warehouse, OURS or THIRDPARTY
778
                If Preferred vendor is specified
779
                    assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
780
                else
781
                    assign THIRDPARTY GOOD/VIRTUAL warehouse with minimum transfer price
782
 
3355 chandransh 783
    Returns an ordered list of size 4 with following elements in the given order:
784
    1. Logistics location of the warehouse which was finally picked up to ship the order.
5295 rajveer 785
    2. Expected delay added by the category manager.
786
    3. Id of the warehouse which was finally picked up.
5110 mandeep.dh 787
 
3355 chandransh 788
    Parameters:
5295 rajveer 789
     - itemId
3355 chandransh 790
    """
1416 chandransh 791
    item = Item.get_by(id=item_id)
5393 mandeep.dh 792
    item_pricing = {}
793
    for vendorItemPricing in VendorItemPricing.query.filter_by(item=item).all():
794
        item_pricing[vendorItemPricing.vendor_id] = vendorItemPricing
795
 
796
    warehouses = {}
797
    ourGoodWarehouses = {}
798
    thirdpartyWarehouses = {}
799
    preferredThirdpartyWarehouses = {}
5110 mandeep.dh 800
    for warehouse in Warehouse.query.all():
801
        if (warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.BAD]):
802
            continue
5393 mandeep.dh 803
        warehouses[warehouse.id] = warehouse
804
        if warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.OURS]:
805
            if warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
806
                ourGoodWarehouses[warehouse.id] = warehouse
807
        else:
808
            thirdpartyWarehouses[warehouse.id] = warehouse
809
            if item.preferredVendor == warehouse.vendor_id and warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
810
                preferredThirdpartyWarehouses[warehouse.id] = warehouse
5110 mandeep.dh 811
 
643 chandransh 812
    warehouse_retid = -1
3503 chandransh 813
    total_availability = 0
5110 mandeep.dh 814
 
5393 mandeep.dh 815
    [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(ourGoodWarehouses, item, item_pricing, False)
5110 mandeep.dh 816
    if warehouse_retid == -1:
5393 mandeep.dh 817
        if item.preferredVendor and item.isWarehousePreferenceSticky:
5731 mandeep.dh 818
            [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(preferredThirdpartyWarehouses, item, item_pricing)
819
            if warehouse_retid == -1:
820
                warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
5110 mandeep.dh 821
        else:
5393 mandeep.dh 822
            [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(thirdpartyWarehouses, item, item_pricing)
5110 mandeep.dh 823
            if warehouse_retid == -1:
5393 mandeep.dh 824
                if item.preferredVendor:
825
                    warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
826
                else:
827
                    [warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(thirdpartyWarehouses, item, item_pricing, True)
5110 mandeep.dh 828
 
5393 mandeep.dh 829
    warehouse = warehouses[warehouse_retid]
5110 mandeep.dh 830
    billingWarehouseId = warehouse.billingWarehouseId
5393 mandeep.dh 831
 
5110 mandeep.dh 832
    # Fetching billing warehouse of a Good billable warehouse corresponding to the virtual one
5663 mandeep.dh 833
    if not warehouse.billingWarehouseId:
5513 mandeep.dh 834
        for w in Warehouse.query.filter_by(vendor_id = warehouse.vendor_id, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]).all():
835
            if w.billingWarehouseId:
836
                billingWarehouseId = w.billingWarehouseId
5110 mandeep.dh 837
                break
4897 rajveer 838
 
839
    expectedDelay = item.expectedDelay 
840
    if expectedDelay is None:
841
        print 'expectedDelay field for this item was Null. Resetting it to 0'
842
        expectedDelay = 0
843
    else:
844
        expectedDelay = int(item.expectedDelay)
5393 mandeep.dh 845
 
4897 rajveer 846
    if total_availability <= 0:
847
        expectedDelay = expectedDelay + __get_expected_procurement_delay(item)
4979 rajveer 848
        expectedDelay = expectedDelay + __get_vendor_holiday_delay(item, expectedDelay)
5437 mandeep.dh 849
    else:
850
        if warehouse.transferDelayInHours:
851
            expectedDelay = expectedDelay + warehouse.transferDelayInHours / 24
5393 mandeep.dh 852
 
5318 rajveer 853
    item_availability_cache = ItemAvailabilityCache.get_by(itemId=item_id)
854
    if item_availability_cache is None:
855
        item_availability_cache = ItemAvailabilityCache()
856
        item_availability_cache.itemId = item_id
857
    item_availability_cache.warehouseId = int(warehouse_retid)
858
    item_availability_cache.expectedDelay = expectedDelay
859
    item_availability_cache.billingWarehouseId = billingWarehouseId
860
    item_availability_cache.sellingPrice = item.sellingPrice
861
    session.commit()
5393 mandeep.dh 862
 
863
def __get_warehouse_with_min_transfer_price(warehouses, item, item_pricing, ignoreAvailability):
864
    warehouse_retid = -1
865
    minTransferPrice = None
866
    total_availability = 0
867
    warehousesWithAvailability = {}
5318 rajveer 868
 
5393 mandeep.dh 869
    if not ignoreAvailability:
870
        if item.currentInventory:
871
            for entry in item.currentInventory:
5424 rajveer 872
                if entry.availability > entry.reserved:
5393 mandeep.dh 873
                    warehousesWithAvailability[entry.warehouse_id] = entry
874
 
875
    for warehouse in warehouses.values():
876
        if not ignoreAvailability:
877
            if warehousesWithAvailability.has_key(warehouse.id):
878
                entry = warehousesWithAvailability[warehouse.id]
5424 rajveer 879
                total_availability += entry.availability - entry.reserved
5393 mandeep.dh 880
            else:
881
                continue
882
 
883
        # Missing transfer price cases should not impact warehouse assignment
884
        transferPrice = None
885
        if item_pricing.has_key(warehouse.vendor_id):
886
            transferPrice = item_pricing[warehouse.vendor_id].transfer_price
887
        if minTransferPrice is None or (transferPrice and minTransferPrice > transferPrice):
888
            warehouse_retid = warehouse.id
889
            minTransferPrice = transferPrice
890
 
891
    return [warehouse_retid, total_availability]
892
 
893
def __get_warehouse_with_min_transfer_delay(warehouses, item, item_pricing):
894
    minTransferDelay = None
895
    minTransferDelayWarehouses = {}
896
    total_availability = 0
897
 
898
    if item.currentInventory:
899
        for entry in item.currentInventory:
900
            if warehouses.has_key(entry.warehouse_id):
901
                warehouse = warehouses[entry.warehouse_id]
5424 rajveer 902
                if entry.availability > entry.reserved:
903
                    total_availability += entry.availability - entry.reserved
5393 mandeep.dh 904
                    transferDelay = warehouse.transferDelayInHours
905
                    if minTransferDelay is None or minTransferDelay >= transferDelay:
906
                        if minTransferDelay != transferDelay:
907
                            minTransferDelayWarehouses = {}
908
                        minTransferDelayWarehouses[warehouse.id] = warehouse
909
                        minTransferDelay = transferDelay
910
 
911
    return [__get_warehouse_with_min_transfer_price(minTransferDelayWarehouses, item, item_pricing, False)[0], total_availability]
912
 
5110 mandeep.dh 913
def __get_warehouse_with_max_availability(warehouse_ids, item):
4406 anupam.sin 914
    warehouse_retid = -1
915
    max_availability = 0
916
    total_availability = 0
917
 
5110 mandeep.dh 918
    if item.currentInventory:
919
        for entry in item.currentInventory:
920
            if entry.warehouse_id in warehouse_ids:
5424 rajveer 921
                availability = entry.availability - entry.reserved
5110 mandeep.dh 922
                if availability > max_availability:
923
                    warehouse_retid = entry.warehouse_id
924
                    max_availability = availability
925
                total_availability += availability
643 chandransh 926
 
5110 mandeep.dh 927
    return [warehouse_retid, total_availability]
2341 chandransh 928
 
4897 rajveer 929
def __get_expected_procurement_delay(item):
4979 rajveer 930
    procurementDelay = 2
4897 rajveer 931
    try:
932
        if item.preferredVendor:
933
            delays = VendorItemProcurementDelay.query.filter_by(vendor_id = item.preferredVendor, item_id = item.id).all()
934
        else:
935
            delays = VendorItemProcurementDelay.query.filter_by(item_id = item.id).all()
936
 
937
        procurementDelay= min([delay.procurementDelay for delay in delays])
938
    except Exception as e:
939
        print e
940
    return procurementDelay
941
 
4979 rajveer 942
def __get_vendor_holiday_delay(item, expectedDelay):
943
    holidayDelay = 0
944
    try:
945
        if item.preferredVendor:
946
            holidays = VendorHolidays.query.filter_by(vendor_id = item.preferredVendor).all()
947
            currentDate = datetime.date.today()
948
            expectedDate = currentDate + datetime.timedelta(days = expectedDelay)
949
            for holiday in holidays:
950
                if holiday.holidayType == HolidayType.WEEKLY and holiday.holidayValue != calendar.SUNDAY:
951
                    if currentDate.weekday() > holiday.holidayValue:
952
                        holidayDate = currentDate + datetime.timedelta(days=holiday.holidayValue-currentDate.weekday(), weeks=1)
953
                    else:
954
                        holidayDate = currentDate + datetime.timedelta(days=holiday.holidayValue-currentDate.weekday())
955
                    if holidayDate >=  currentDate and holidayDate <= expectedDate:
956
                        holidayDelay = holidayDelay + 1
957
                elif holiday.holidayType == HolidayType.MONTHLY:
958
                    holidayDate = datetime.date(currentDate.year, currentDate.month, holiday.holidayValue)
959
                    if holidayDate >=  currentDate and holidayDate <= expectedDate:
960
                        holidayDelay = holidayDelay + 1    
961
                elif holiday.holidayType == HolidayType.SPECIFIC:
5005 rajveer 962
                    holidayValue = str(holiday.holidayValue)
963
                    holidayDate = datetime.date(int(holidayValue[:4]), int(holidayValue[4:6]), int(holidayValue[6:8]))
4979 rajveer 964
                    if holidayDate >=  currentDate and holidayDate <= expectedDate:
965
                        holidayDelay = holidayDelay + 1                
966
    except Exception as e:
967
        print e
968
    return holidayDelay 
5393 mandeep.dh 969
 
122 ashish 970
def get_warehouses_for_item(item_id):
643 chandransh 971
 
122 ashish 972
    if not item_id:
973
        raise InventoryServiceException(101, "bad item_id")
635 rajveer 974
    item = get_item(item_id)
122 ashish 975
 
976
    if not item:
977
        raise InventoryServiceException(101, "bad item")
978
 
483 rajveer 979
    warehouses = item.currentInventory.warehouse
501 rajveer 980
    return warehouses
981
 
2404 chandransh 982
def get_child_categories(category):
983
    cm = CategoryManager()
2621 varun.gupt 984
    cat = cm.getCategory(category)
985
    return cat.children_category_ids if cat else None
2404 chandransh 986
 
626 chandransh 987
def get_best_sellers(start_index, stop_index, category=-1):
2404 chandransh 988
    '''
989
    Returns the Best Sellers between the start and the stop index in the given category
990
    '''
1926 rajveer 991
    query = get_best_sellers_query(category, None)
1098 chandransh 992
    best_sellers = query.all()[start_index:stop_index]
621 chandransh 993
    return get_thrift_item_list(best_sellers)
994
 
2093 chandransh 995
def get_best_sellers_count(category=-1):
2404 chandransh 996
    '''
997
    Returns the number of best sellers in the given category
998
    '''
1926 rajveer 999
    count = get_best_sellers_query(category, None).count()
1120 rajveer 1000
    if count is None:
1001
        count = 0
766 rajveer 1002
    return count
621 chandransh 1003
 
1926 rajveer 1004
def get_best_sellers_catalog_ids(start_index, stop_index, brand, category=-1):
2404 chandransh 1005
    '''
1006
    Returns the Best sellers for the given brand and category between the start and the stop index.
1007
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
1008
    '''
1926 rajveer 1009
    query = get_best_sellers_query(category, brand)
1098 chandransh 1010
    best_sellers = query.all()[start_index:stop_index]
621 chandransh 1011
    return [item.catalog_item_id for item in best_sellers]
1970 rajveer 1012
 
1926 rajveer 1013
def get_best_sellers_query(category, brand):
2404 chandransh 1014
    '''
1015
    Returns the query to be used for getting Best Sellers.
1016
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
1017
    '''
1098 chandransh 1018
    query = Item.query.filter_by(status=status.ACTIVE).filter(Item.bestSellingRank != None)
626 chandransh 1019
    if category != -1:
1970 rajveer 1020
        all_categories = [category]
1021
        child_categories = get_child_categories(category)
1022
        if child_categories is not None:
1023
            all_categories = all_categories + child_categories 
1024
        query = query.filter(Item.category.in_(all_categories))
1926 rajveer 1025
    if brand is not None:
1026
        query = query.filter_by(brand=brand)
1098 chandransh 1027
    query = query.order_by(asc(Item.bestSellingRank))
621 chandransh 1028
    return query
609 chandransh 1029
 
1098 chandransh 1030
def get_best_deals(category=-1):
2404 chandransh 1031
    '''
1032
    Returns the Best deals in the given category. Ignores the category if it's passed as -1.
1033
    '''
1034
    query = get_best_deals_query(Item, category, None)
1098 chandransh 1035
    items = query.all()
609 chandransh 1036
    return get_thrift_item_list(items)
1037
 
1098 chandransh 1038
def get_best_deals_count(category=-1):
2404 chandransh 1039
    '''
1040
    Returns the count of best deals in the given category.
1041
    Ignores the category if it's -1.
1042
    '''
1043
    count = get_best_deals_counting_query(func.count(distinct(Item.catalog_item_id)), category, None).scalar()
1120 rajveer 1044
    if count is None:
1045
        count = 0
766 rajveer 1046
    return count
501 rajveer 1047
 
1926 rajveer 1048
def get_best_deals_catalog_ids(start_index, stop_index, brand, category=-1):
2404 chandransh 1049
    '''
1050
    Returns the catalog_item_ids of best deal items for the given brand and category.
1051
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
1052
    '''
1053
    query = get_best_deals_query(Item, category, brand)
1098 chandransh 1054
    best_deal_items = query.all()[start_index:stop_index]
1055
    return [item.catalog_item_id for item in best_deal_items]
1056
 
2404 chandransh 1057
def get_best_deals_counting_query(obj, category, brand):
1058
    '''
1059
    Returns the query to be used to select the best deals in the given brand and category.
1060
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
1061
    '''
1062
    query = session.query(obj).filter_by(status=status.ACTIVE).filter(Item.bestDealValue != None)
626 chandransh 1063
    if category != -1:
1970 rajveer 1064
        all_categories = [category]
1065
        child_categories = get_child_categories(category)
1066
        if child_categories is not None:
1067
            all_categories = all_categories + child_categories 
1068
        query = query.filter(Item.category.in_(all_categories))
1926 rajveer 1069
    if brand is not None:
1070
        query = query.filter_by(brand=brand)
2404 chandransh 1071
    return query
1072
 
1073
def get_best_deals_query(obj, category, brand):
1074
    '''
1075
    Returns the query to be used to get the best deals in the given category and brand.
1076
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
1077
    '''
1078
    query = get_best_deals_counting_query(obj, category, brand)
1098 chandransh 1079
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.bestDealValue))
1080
    return query
609 chandransh 1081
 
5217 amit.gupta 1082
def get_coming_soon(category=-1):
1083
    '''
1084
    Returns the Coming Soon items in the given category. Ignores the category if it's passed as -1.
1085
    '''
1086
    query = get_coming_soon_query(Item, category, None)
1087
    items = query.all()
1088
    return get_thrift_item_list(items)
1089
 
1090
def get_coming_soon_count(category=-1):
1091
    '''
1092
    Returns the count of coming in the given category.
1093
    Ignores the category if it's -1.
1094
    '''
1095
    count = get_coming_soon_counting_query(func.count(distinct(Item.catalog_item_id)), category, None).scalar()
1096
    if count is None:
1097
        count = 0
1098
    return count
1099
 
1100
def get_coming_soon_catalog_ids(start_index, stop_index, brand, category=-1):
1101
    '''
1102
    Returns the catalog_item_ids of coming soon items for the given brand and category.
1103
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
1104
    '''
1105
    query = get_coming_soon_query(Item, category, brand)
1106
    coming_soon_items = query.all()[start_index:stop_index]
1107
    return [item.catalog_item_id for item in coming_soon_items]
1108
 
1109
def get_coming_soon_counting_query(obj, category, brand):
1110
    '''
1111
    Returns the query to be used to select the coming soon product in the given brand and category.
1112
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
1113
    '''
1114
    query = session.query(obj).filter_by(status=status.COMING_SOON)
1115
    if category != -1:
1116
        all_categories = [category]
1117
        child_categories = get_child_categories(category)
1118
        if child_categories is not None:
1119
            all_categories = all_categories + child_categories 
1120
        query = query.filter(Item.category.in_(all_categories))
1121
    if brand is not None:
1122
        query = query.filter_by(brand=brand)
1123
    return query
1124
 
1125
def get_coming_soon_query(obj, category, brand):
1126
    '''
1127
    Returns the query to be used to get the coming soon products in the given category and brand.
1128
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
1129
    '''
1130
    query = get_coming_soon_counting_query(obj, category, brand)
1131
    query = query.group_by(Item.catalog_item_id).order_by(asc(Item.comingSoonStartDate))
1132
    return query
1133
 
1098 chandransh 1134
def get_latest_arrivals(limit, category=-1):
2404 chandransh 1135
    '''
1136
    Returns up to limit number of Latest Arrivals in the given category.
1137
    '''
2975 chandransh 1138
    categories = []
1139
    if category != -1:
1140
        categories = [category]
1141
    query = get_latest_arrivals_query(Item, categories, None)
1098 chandransh 1142
    items = query.all()[0:limit]
609 chandransh 1143
    return get_thrift_item_list(items)
598 chandransh 1144
 
1098 chandransh 1145
def get_latest_arrivals_count(limit, category=-1):
2404 chandransh 1146
    '''
1147
    Returns the number of latest arrivals which will be displayed on the website.
3016 chandransh 1148
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 1149
    '''
2975 chandransh 1150
    categories = []
1151
    if category != -1:
1152
        categories = [category]
1153
    count = get_latest_arrivals_counting_query(func.count(distinct(Item.catalog_item_id)), categories, None).scalar()
1120 rajveer 1154
    if count is None:
1155
        count = 0
1156
    count = min(count, limit)
766 rajveer 1157
    return count
602 chandransh 1158
 
2975 chandransh 1159
def get_latest_arrivals_catalog_ids(start_index, stop_index, brand, categories=[]):
2404 chandransh 1160
    '''
1161
    Returns the catalog_item_ids of the latest arrivals between the start and the stop index
3016 chandransh 1162
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 1163
    '''
2975 chandransh 1164
    query = get_latest_arrivals_query(Item, categories, brand)
1098 chandransh 1165
    latest_arrivals = query.all()[start_index:stop_index]
1166
    return [item.catalog_item_id for item in latest_arrivals]
1167
 
2975 chandransh 1168
def get_latest_arrivals_counting_query(obj, categories, brand):
2404 chandransh 1169
    '''
1170
    Returns the query to be used to count Latest arrivals.
3016 chandransh 1171
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 1172
    '''
1173
    query = session.query(obj).filter_by(status=status.ACTIVE)
2975 chandransh 1174
 
1175
    all_categories = []
1176
    for category in categories:
1177
        all_categories.append(category)
1970 rajveer 1178
        child_categories = get_child_categories(category)
2975 chandransh 1179
        if child_categories:
1180
            all_categories = all_categories + child_categories
1181
    if all_categories: 
1970 rajveer 1182
        query = query.filter(Item.category.in_(all_categories))
2975 chandransh 1183
 
1926 rajveer 1184
    if brand is not None:
1185
        query = query.filter_by(brand=brand)
2404 chandransh 1186
    return query
1187
 
2975 chandransh 1188
def get_latest_arrivals_query(obj, categories, brand):
2404 chandransh 1189
    '''
1190
    Returns the query to be used to retrieve Latest Arrivals.
1191
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
1192
    '''
2975 chandransh 1193
    query = get_latest_arrivals_counting_query(obj, categories, brand)
5167 rajveer 1194
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.startDate)).order_by(Item.catalog_item_id)
1098 chandransh 1195
    return query
609 chandransh 1196
 
1197
def get_thrift_item_list(items):
1098 chandransh 1198
    return [to_t_item(item) for item in items if item != None]
635 rajveer 1199
 
1155 rajveer 1200
def generate_new_entity_id():
1201
    generator =  EntityIDGenerator.query.one()
1202
    id = generator.id + 1
1203
    generator.id = id
1204
    session.commit()
1205
    return id
1206
 
635 rajveer 1207
def put_category_object(object):
1208
    category = Category.get_by(id=1)
1209
    if category is None:
1210
        category = Category()
1211
    category.object = object    
1212
    session.commit()
1213
    return True
1214
 
1215
def get_category_object():
766 rajveer 1216
    object = Category.get_by(id=1).object
1217
    return object
1218
 
4283 anupam.sin 1219
def get_item_pricing(item_id, vendorId):
1341 chandransh 1220
    item = Item.query.filter_by(id=item_id).first()
1221
    if item is None:
1222
        raise InventoryServiceException(101, "Bad Item")
4307 anupam.sin 1223
    '''
1224
    if vendor id is -1 then we calculate an average transfer price to be populated
1225
    at the time of order creation. This will be later updated with actual transfer price
1226
    at the time of billing.
1227
    '''
1228
    if(vendorId == -1):
4543 anupam.sin 1229
        total = 0
4307 anupam.sin 1230
        try:
5133 mandeep.dh 1231
            item_pricings = []
5393 mandeep.dh 1232
            if item.preferredVendor is not None:
1233
                item_pricing = VendorItemPricing.query.filter_by(item=item, vendor_id=item.preferredVendor).first()
5133 mandeep.dh 1234
                if item_pricing:
1235
                    item_pricings.append(item_pricing)                    
4858 anupam.sin 1236
            else :
1237
                item_pricings = VendorItemPricing.query.filter_by(item=item).all()
4315 anupam.sin 1238
            if item_pricings:
4307 anupam.sin 1239
                for item_pricing in item_pricings:
4543 anupam.sin 1240
                    total += item_pricing.transfer_price
4315 anupam.sin 1241
                avg = total / len(item_pricings)
1242
                item_pricing.transfer_price = avg
4543 anupam.sin 1243
            else:
1244
                item_pricing = VendorItemPricing()
1245
                item_pricing.transfer_price = item.sellingPrice
1246
                vendor = Vendor()
1247
                vendor.id = vendorId
1248
                item_pricing.vendor = vendor
1249
                item_pricing.item = item
1250
 
1251
            return item_pricing
4307 anupam.sin 1252
        except:
1253
            raise InventoryServiceException(101, "Item pricing not found ")
4283 anupam.sin 1254
    vendor = Vendor.get_by(id=vendorId)    
1341 chandransh 1255
    try:
1256
        item_pricing = VendorItemPricing.query.filter_by(vendor=vendor, item=item).one()
1347 chandransh 1257
        return item_pricing
3244 chandransh 1258
    except MultipleResultsFound:
1341 chandransh 1259
        raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
3244 chandransh 1260
    except NoResultFound:
1341 chandransh 1261
        raise InventoryServiceException(111, "Missing pricing information for Vendor: " + vendor.name + " and Item: " + str(item_id))
1262
 
1970 rajveer 1263
def add_category(t_category):
1264
    category = Category.get_by(id=t_category.id)
1265
    if category is None:
1266
        category = Category()
1267
    category.id = t_category.id 
1268
    category.label = t_category.label
1269
    category.description = t_category.description
4762 phani.kuma 1270
    category.display_name = t_category.display_name
1970 rajveer 1271
    category.parent_category_id = t_category.parent_category_id 
1272
    session.commit()
1273
    return True
1274
 
1275
def get_category(id):
1276
    return Category.query.filter_by(id=id).first()
1277
 
1278
def get_all_categories():
1279
    return Category.query.all()
1280
 
1991 ankur.sing 1281
 
1282
def get_all_item_pricing(item_id):
1283
    item = Item.query.filter_by(id=item_id).first()
1284
    if item is None:
1285
        raise InventoryServiceException(101, "Bad Item")
1286
    item_pricing = VendorItemPricing.query.filter_by(item=item).all()
1287
    return item_pricing
1288
 
2116 ankur.sing 1289
def get_item_mappings(item_id):
1290
    item = Item.query.filter_by(id=item_id).first()
1291
    if item is None:
1292
        raise InventoryServiceException(101, "Bad Item")
1293
    item_mappings = VendorItemMapping.query.filter_by(item=item).all()
1294
    return item_mappings
1295
 
1296
def add_vendor_pricing(vendorItemPricing):
1991 ankur.sing 1297
    if not vendorItemPricing:
1298
        raise InventoryServiceException(108, "Bad vendorItemPricing in request")
1299
    vendorId = vendorItemPricing.vendorId
1300
    itemId = vendorItemPricing.itemId
1301
 
1302
    try:
1303
        vendor = Vendor.query.filter_by(id=vendorId).one()
1304
    except:
1305
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
1306
 
1307
    try:
1308
        item = Item.query.filter_by(id=itemId).one()
1309
    except:
5047 amit.gupta 1310
        raise InventoryServiceException(101, "Item not found for itemId " + str(itemId))
1991 ankur.sing 1311
 
2120 ankur.sing 1312
    validate_vendor_prices(to_t_item(item), vendorItemPricing)
2065 ankur.sing 1313
 
1991 ankur.sing 1314
    try:
1315
        ds_vendorItemPricing = VendorItemPricing.query.filter(and_(VendorItemPricing.vendor==vendor, VendorItemPricing.item==item)).one()
1316
    except:
2116 ankur.sing 1317
        ds_vendorItemPricing = VendorItemPricing()
1318
        ds_vendorItemPricing.vendor = vendor
1319
        ds_vendorItemPricing.item = item
1991 ankur.sing 1320
 
5047 amit.gupta 1321
    subject = ""
1322
    message = ""
1991 ankur.sing 1323
    if vendorItemPricing.mop:
1324
        ds_vendorItemPricing.mop = vendorItemPricing.mop
1325
    if vendorItemPricing.dealerPrice:
1326
        ds_vendorItemPricing.dealerPrice = vendorItemPricing.dealerPrice
1327
    if vendorItemPricing.transferPrice:
5047 amit.gupta 1328
        if vendorItemPricing.transferPrice != ds_vendorItemPricing.transfer_price:
1329
            message = "Transfer price for Item '{0}' \nand Vendor:{1} is changed from {2} to {3}.".format(__get_product_name(item), vendor.name, ds_vendorItemPricing.transfer_price, vendorItemPricing.transferPrice)
1330
            subject = "Alert:Change in Transfer Price"
2065 ankur.sing 1331
        ds_vendorItemPricing.transfer_price = vendorItemPricing.transferPrice
1991 ankur.sing 1332
 
1333
    session.commit()
5047 amit.gupta 1334
    if subject:
1335
        __send_mail(subject, message)
1991 ankur.sing 1336
    return
1337
 
2358 ankur.sing 1338
def add_vendor_item_mapping(key, vendorItemMapping):
2116 ankur.sing 1339
    if not vendorItemMapping:
1340
        raise InventoryServiceException(108, "Bad vendorItemMapping in request")
1341
    vendorId = vendorItemMapping.vendorId
1342
    itemId = vendorItemMapping.itemId
1343
 
1344
    try:
1345
        vendor = Vendor.query.filter_by(id=vendorId).one()
1346
    except:
1347
        raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
1348
 
1349
    try:
1350
        item = Item.query.filter_by(id=itemId).one()
1351
    except:
1352
        raise InventoryServiceException(101, "Item not found for vendorId " + str(itemId))
1353
 
1354
    try:
2358 ankur.sing 1355
        ds_vendorItemMapping = VendorItemMapping.query.filter(and_(VendorItemMapping.vendor==vendor, VendorItemMapping.item==item, VendorItemMapping.item_key==key)).one()
2116 ankur.sing 1356
    except:
1357
        ds_vendorItemMapping = VendorItemMapping()
1358
        ds_vendorItemMapping.vendor = vendor
1359
        ds_vendorItemMapping.item = item
1360
    ds_vendorItemMapping.item_key = vendorItemMapping.itemKey
4985 mandeep.dh 1361
 
2116 ankur.sing 1362
    session.commit()
4985 mandeep.dh 1363
 
1364
    # Marking the missed inventory as not ignored as the catalog dashboard user has updated their key
1365
    for missedInventoryUpdate in MissedInventoryUpdate.query.filter_by(itemKey = vendorItemMapping.itemKey).all():
1366
        missedInventoryUpdate.isIgnored = 0
1367
    session.commit()
1368
 
2116 ankur.sing 1369
    return
1370
 
2120 ankur.sing 1371
def validate_item_prices(item):
2129 ankur.sing 1372
    if item.mrp == None or item.sellingPrice == None or item.mrp == "" or item.sellingPrice == "":
1373
        return
1374
    if item.mrp < item.sellingPrice:
2120 ankur.sing 1375
        print "[BAD MRP and SP:] for {0} {1} {2} {3}. MRP={4}, SP={5}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(item.mrp), str(item.sellingPrice))
1376
        raise InventoryServiceException(101, "[BAD MRP and SP:] for {0} {1} {2} {3}. MRP={4}, SP={5}".format(item.productGroup, item.brand, item.modelNumber, item.color, str(item.mrp), str(item.sellingPrice)))
2065 ankur.sing 1377
    return
2120 ankur.sing 1378
 
1379
def validate_vendor_prices(item, vendorPrices):
2129 ankur.sing 1380
    if item.mrp != None and item.mrp != "" and vendorPrices.mop != "" and item.mrp <  vendorPrices.mop:
2120 ankur.sing 1381
        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))
1382
        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)))
1383
    if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
1384
        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))
1385
        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)))
1386
    return
2065 ankur.sing 1387
 
1388
def get_all_vendors():
1389
    return Vendor.query.all()
1390
 
4725 phani.kuma 1391
def check_color_valid(color):
1392
    if color is not None:
1393
        color = color.strip().lower()
1394
        if color != '' and color != 'na' and color != 'blank' and color != '(blank)':
1395
            return True
1396
    return False
1397
 
1398
def check_similar_item(brand, model_number, model_name, color):
2129 ankur.sing 1399
    query = Item.query
2428 ankur.sing 1400
    query = query.filter_by(brand=brand)
1401
    query = query.filter_by(model_number=model_number)
4725 phani.kuma 1402
    query = query.filter_by(model_name=model_name)
1403
    similar_items = query.all()
1404
    item = None
1405
    # Check if a similar item already exists in our database
1406
    for old_item in similar_items:
1407
        if old_item.color != None and old_item.color.strip().lower() == color.strip().lower():
1408
            item = old_item
1409
            break
1410
 
1411
    # Check if a similar item already exists in our database with out valid color if similar item with same color is not found
2116 ankur.sing 1412
    if item is None:
4725 phani.kuma 1413
        for old_item in similar_items:
1414
            if not check_color_valid(old_item.color):
1415
                item = old_item
1416
                break
1417
    i = 0
1418
    color_of_similar_item = None
1419
    # Check if a similar item already exists in our database to be used to get catalog_item_id
1420
    for old_item in similar_items:
1421
        # get a similar item already existing in our database with valid color
1422
        if check_color_valid(old_item.color):
1423
            similar_item = old_item
1424
            color_of_similar_item = similar_item.color
1425
            break
1426
        i = i + 1
1427
        # get a similar item already existing in our database if similar item with valid color is not found
1428
        if i == len(similar_items):
1429
            similar_item = old_item
1430
            color_of_similar_item = similar_item.color
1431
 
1432
    # Check if a similar item that is obtained above is having a valid color
1433
    if check_color_valid(color_of_similar_item):
1434
        # if a similar item that is obtained above is having a valid color and new item is about to be created with out valid color it is not done.
1435
        # since for example if their is a item with red color in our database and we are creating a new item with no color for the same product which is wrong.
1436
        if item is None and not check_color_valid(color):
1437
            return similar_item.id
1438
 
1439
    if item is None:
2116 ankur.sing 1440
        return 0
1441
    else:
1442
        return item.id
2286 ankur.sing 1443
 
1444
def change_risky_flag(item_id, risky):
1445
    item = get_item(item_id)
1446
    if not item:
1447
        raise InventoryServiceException(101, "Item missing in our database")
1448
    try:
1449
        log_risky_flag(item_id, risky)
1450
    except:
1451
        print "Not able to log risky flag change"
1452
    item.risky = risky
4295 varun.gupt 1453
    if not risky and item.status == status.PAUSED_BY_RISK:
2368 ankur.sing 1454
        change_item_status(item.id, status.ACTIVE)
2286 ankur.sing 1455
    session.commit()
5047 amit.gupta 1456
    flag = "ON" if risky else "OFF"
1457
    subject = "Risky flag is {0} for Item {1}.".format(flag, __get_product_name(item))
1458
    __send_mail(subject,"")
2286 ankur.sing 1459
 
4957 phani.kuma 1460
def get_items_for_mastersheet(categoryName, brand):
1461
    if not categoryName or not brand:
1462
        raise InventoryServiceException(101, "Invalid category or brand in request")
1463
 
4762 phani.kuma 1464
    categories = ["Handsets", "Tablets", "Laptops"]
4957 phani.kuma 1465
    query = Item.query.filter(Item.status != status.PHASED_OUT)
1466
    if categoryName == "ALL":
1467
        pass
1468
    elif categoryName == "ALL Accessories":
1469
        query = query.filter(~Item.product_group.in_(categories))
1470
    elif categoryName == "ALL Handsets":
1471
        query = query.filter(Item.product_group.in_(categories))
1472
    elif categoryName == "Mobile Accessories":
1473
        child_categories = get_child_categories(10011)
1474
        if child_categories is not None:
1475
            child_categories.append(0)
1476
            query = query.filter(Item.category.in_(child_categories))
1477
    elif categoryName == "Laptop Accessories":
1478
        child_categories = get_child_categories(10070)
1479
        if child_categories is not None:
1480
            child_categories.append(0)
1481
            query = query.filter(Item.category.in_(child_categories))
1482
    else:
1483
        query = query.filter(Item.product_group == categoryName)
1484
 
1485
    if brand == "ALL":
1486
        pass
1487
    else:
1488
        query = query.filter(Item.brand == brand)
2358 ankur.sing 1489
    items = query.all()
1490
    return items
2116 ankur.sing 1491
 
2358 ankur.sing 1492
def get_risky_items():
1493
    items = Item.query.filter_by(risky=True).all()
1494
    return items
3008 rajveer 1495
 
2809 rajveer 1496
def get_similar_items_catalog_ids(start_index, stop_index, itemId):
3008 rajveer 1497
    query = SimilarItems.query.filter_by(item_id=itemId).limit(stop_index-start_index)
1498
    similar_items = query.all()
3289 rajveer 1499
    return_list = []
1500
    for similar_item in similar_items:
1501
        isActive = False
1502
        try:
1503
            all_items = Item.query.filter_by(catalog_item_id=similar_item.catalog_item_id).all()
1504
        except:
1505
            continue
1506
        for item in all_items:
1507
            isActive = isActive or item.status == status.ACTIVE
1508
        if isActive:
1509
            return_list.append(similar_item.catalog_item_id)
1510
    return return_list
4423 phani.kuma 1511
 
1512
def get_all_similar_items_catalog_ids(itemId):
1513
    query = SimilarItems.query.filter_by(item_id=itemId)
1514
    similar_items = query.all()
1515
    return_list = []
1516
    for similar_item in similar_items:
1517
        item_query = Item.query.filter_by(catalog_item_id=similar_item.catalog_item_id).limit(1)
1518
        item = item_query.one()
1519
        return_list.append(item)
2809 rajveer 1520
 
4423 phani.kuma 1521
    return get_thrift_item_list(return_list)
1522
 
1523
def add_similar_item_catalog_id(itemId, catalog_item_id):
1524
    if not itemId or not catalog_item_id:
1525
        raise InventoryServiceException(101, "Bad itemId or catalogItemId in request")
1526
    items_for_entity = get_items_by_catalog_id(catalog_item_id)
1527
    if not len(items_for_entity):
1528
        raise InventoryServiceException(101, "catalogItemId does not exists in database")
1529
 
1530
    s_items = SimilarItems.query.filter_by(item_id=itemId, catalog_item_id=catalog_item_id).all()
1531
    if not len(s_items):
1532
        s_item = SimilarItems()
1533
        s_item.item_id=itemId
1534
        s_item.catalog_item_id=catalog_item_id
1535
        session.commit()
1536
        return items_for_entity[0]
1537
    else:
1538
        raise InventoryServiceException(101, "Already exists")
1539
 
1540
def delete_similar_item_catalog_id(itemId, catalog_item_id):
1541
    if not itemId or not catalog_item_id:
1542
        raise InventoryServiceException(101, "Bad itemId or catalogItemId in request")
1543
 
1544
    similar_item = SimilarItems.query.filter_by(item_id=itemId, catalog_item_id=catalog_item_id).all()
1545
    if len(similar_item):
1546
        similar_item[0].delete()
1547
    session.commit()
1548
    return True
5504 phani.kuma 1549
 
1550
def get_all_vouchers_for_item(itemId):
1551
    vouchers = VoucherItemMapping.query.filter_by(item_id=itemId).all()
1552
    return vouchers
1553
 
1554
def get_voucher_amount(itemId, voucher_type):
1555
    voucher = VoucherItemMapping.query.filter_by(item_id=itemId, voucherType=voucher_type).all()
1556
    if len(voucher):
1557
        return voucher[0].amount
1558
    else:
5518 rajveer 1559
        return 0
5504 phani.kuma 1560
 
1561
def add_update_voucher_for_item(catalog_item_id, voucher_type, voucher_amount):
1562
    if not catalog_item_id or not voucher_type or not voucher_amount:
1563
        raise InventoryServiceException(101, "Bad catalogItemId or voucherType or voucherAmount in request")
1564
 
1565
    items_for_entity = get_items_by_catalog_id(catalog_item_id)
1566
    if not len(items_for_entity):
1567
        raise InventoryServiceException(101, "catalogItemId does not exists in database")
1568
 
1569
    for item in items_for_entity:
1570
        itemId = item.id
1571
        voucher = VoucherItemMapping.query.filter_by(item_id=itemId, voucherType=voucher_type).all()
1572
        if not len(voucher):
1573
            voucher = VoucherItemMapping()
1574
            voucher.item_id=itemId
1575
            voucher.voucherType=voucher_type
1576
            voucher.amount=voucher_amount
1577
        else:
1578
            voucher[0].amount=voucher_amount
1579
    session.commit()
1580
    return True
4423 phani.kuma 1581
 
5504 phani.kuma 1582
def delete_voucher_for_item(catalog_item_id, voucher_type):
1583
    if not catalog_item_id or not voucher_type:
1584
        raise InventoryServiceException(101, "Bad catalogItemId or voucherType in request")
1585
 
1586
    items_for_entity = get_items_by_catalog_id(catalog_item_id)
1587
    if not len(items_for_entity):
1588
        raise InventoryServiceException(101, "catalogItemId does not exists in database")
1589
 
1590
    for item in items_for_entity:
1591
        itemId = item.id
1592
        voucher = VoucherItemMapping.query.filter_by(item_id=itemId, voucherType=voucher_type).all()
1593
        if len(voucher):
1594
            voucher[0].delete()
1595
    session.commit()
1596
    return True
1597
 
3079 rajveer 1598
def add_product_notification(itemId, email):
1599
    try:
3470 rajveer 1600
        try:
1601
            product_notification = ProductNotification.query.filter_by(item_id=itemId, email=email).one()
1602
        except:
1603
            product_notification = ProductNotification()
1604
            product_notification.email = email
1605
            product_notification.item_id = itemId
3079 rajveer 1606
        product_notification.addedOn = datetime.datetime.now()
1607
        session.commit()
1608
        return True
1609
    except:
1610
        return False
3086 rajveer 1611
 
1612
 
1613
def send_product_notifications():
1614
    product_notifications = ProductNotification.query.all()
1615
    for product_notification in product_notifications:
1616
        item = product_notification.item
5125 mandeep.dh 1617
        availability = __get_item_availability(item, None)
1618
        if item.status == status.ACTIVE and (not item.risky or availability > 0):
3086 rajveer 1619
            __enque_product_notification_email(product_notification.email, __get_product_name(item) , product_notification.addedOn, __get_product_url(item), item.id)
1620
            product_notification.delete()
1621
    session.commit()
1622
    return True
1623
 
1624
def __get_product_name(item):
1625
    product_name = item.brand + " " + item.model_name + " " + item.model_number
1626
    color = item.color
1627
    if color is not None and color != 'NA':
1628
        product_name = product_name + " (" + color + ")"
3201 rajveer 1629
    product_name = product_name.replace("  "," ")
3086 rajveer 1630
    return product_name
1631
 
1632
 
1633
def __get_product_url(item):
1634
    product_url = "http://www.saholic.com/mobile-phones/" + item.brand + "-" + item.model_name + "-" + item.model_number + "-" + str(item.catalog_item_id)
1635
    product_url = product_url.replace("--","-")
1636
    product_url = product_url.replace(" ","")
1637
    return product_url
1638
 
3348 varun.gupt 1639
def get_all_brands_by_category(category_id):
1640
    catm = CategoryManager()
1641
    child_categories = catm.getCategory(category_id).children_category_ids
1642
    brands = session.query(distinct(Item.brand)).filter(Item.category.in_(child_categories)).all()
1643
 
1644
    return [brand[0] for brand in brands]
3086 rajveer 1645
 
4957 phani.kuma 1646
def get_all_brands():
1647
    brands = session.query(distinct(Item.brand)).order_by(Item.brand).all()
1648
 
1649
    return [brand[0] for brand in brands]
1650
 
3086 rajveer 1651
def __enque_product_notification_email(email, product, date, url, itemId):
1652
 
1653
    html = """
1654
        <html>
1655
        <body>
1656
        <div>
1657
        <p>
1658
            Hi,<br /><br />
1659
            The product requested by you on $date is now available on saholic.com.
1660
        </p>
1661
 
1662
        <p>    
1663
        <strong>Product: $product </strong>
1664
        </p>
1665
 
1666
        <p>
1667
        Click the link below to visit the product: 
1668
        <br/>
1669
        $url
1670
        </p>
1671
        <p>
1672
        Regards,<br/>
1673
        Saholic Customer Support Team<br/>
1674
        www.saholic.com<br/>
1675
        Email: help@saholic.com<br/>
1676
        </p>
1677
        </div>
1678
        </body>
1679
        </html>
1680
        """
1681
 
1682
    html = Template(html).substitute(dict(product=product,date=date,url=url))
3079 rajveer 1683
 
3086 rajveer 1684
    try:
1685
        helper_client = HelperClient().get_client()
1686
        helper_client.saveUserEmailForSending(email, "", "Product requested by you is available now.", html, str(itemId), "ProductNotification")
1687
    except Exception as e:
1688
        print e
1689
 
3557 rajveer 1690
def get_all_sources():
1691
    sources = Source.query.all()
1692
    return [to_t_source(source) for source in sources]
3086 rajveer 1693
 
3557 rajveer 1694
def get_item_pricing_by_source(itemId, sourceId):
1695
    item = Item.query.filter_by(id=itemId).first()
1696
    if item is None:
1697
        raise InventoryServiceException(101, "Bad Item")
1698
 
1699
    source = Source.query.filter_by(id=sourceId).first()
1700
    if source is None:
1701
        raise InventoryServiceException(101, "Source not found for sourceId " + str(sourceId))
1702
 
1703
    item_pricing = SourceItemPricing.query.filter_by(source=source, item=item).first()
1704
    if item_pricing is None:
1705
        raise InventoryServiceException(101, "Pricing information not found for sourceId " + str(sourceId))
1706
    return item_pricing
1707
 
1708
def add_source_item_pricing(sourceItemPricing):
1709
    if not sourceItemPricing:
1710
        raise InventoryServiceException(108, "Bad sourceItemPricing in request")
1711
 
1712
    if not sourceItemPricing.sellingPrice:
4326 mandeep.dh 1713
        raise InventoryServiceException(101, "Selling Price is not defined for sourceId " + str(sourceItemPricing.sourceId))
3557 rajveer 1714
 
1715
    sourceId = sourceItemPricing.sourceId
1716
    itemId = sourceItemPricing.itemId
1717
 
1718
    item = Item.query.filter_by(id=itemId).first()
1719
    if item is None:
1720
        raise InventoryServiceException(101, "Bad Item")
1721
 
1722
    source = Source.query.filter_by(id=sourceId).first()
1723
    if source is None:
1724
        raise InventoryServiceException(101, "Source not found for sourceId " + str(sourceId))
1725
 
3564 rajveer 1726
    ds_sourceItemPricing = SourceItemPricing.get_by(source=source, item=item)
3557 rajveer 1727
    if ds_sourceItemPricing is None:
1728
        ds_sourceItemPricing = SourceItemPricing()
1729
        ds_sourceItemPricing.source = source
1730
        ds_sourceItemPricing.item = item
1731
 
1732
    if sourceItemPricing.mrp:
1733
        ds_sourceItemPricing.mrp = sourceItemPricing.mrp
1734
    ds_sourceItemPricing.sellingPrice = sourceItemPricing.sellingPrice
1735
 
1736
    session.commit()
1737
    return
1738
 
1739
def get_all_source_pricing(itemId):
1740
    item = Item.query.filter_by(id=itemId).first()
1741
    if item is None:
1742
        raise InventoryServiceException(101, "Bad Item")
1743
    source_pricing = SourceItemPricing.query.filter_by(item=item).all()
1744
    return source_pricing
1745
 
1746
 
1747
def get_item_for_source(item_id, sourceId):
1748
    item = get_item(item_id)
1749
    if sourceId == -1:
1750
        return item
1751
    try:
1752
        sip = get_item_pricing_by_source(item_id, sourceId)
1753
        item.sellingPrice = sip.sellingPrice
1754
        if sip.mrp:
1755
            item.mrp = sip.mrp
1756
    except:
1757
        print "No source pricing"
1758
    return item
1759
 
3872 chandransh 1760
def search_items(search_terms, offset, limit):
1761
    query = Item.query
1762
 
1763
    query_clause = []
1764
 
1765
    search_terms = ['%' + search_term + '%' for search_term in search_terms]
1766
 
1767
    for search_term in search_terms:
1768
        query_clause.append(Item.brand.like(search_term))
1769
        query_clause.append(Item.model_number.like(search_term))
1770
        query_clause.append(Item.model_name.like(search_term))
1771
 
1772
    query = query.filter(or_(*query_clause))
1773
 
1774
    query = query.order_by(Item.product_group, Item.brand, Item.model_number, Item.model_name).offset(offset)
1775
    if limit:
1776
        query = query.limit(limit)
1777
    items = query.all()
1778
    return items
1779
 
1780
def get_search_result_count(search_terms):
1781
    query = Item.query
1782
 
1783
    query_clause = []
1784
 
1785
    search_terms = ['%' + search_term + '%' for search_term in search_terms]
1786
 
1787
    for search_term in search_terms:
1788
        query_clause.append(Item.brand.like(search_term))
1789
        query_clause.append(Item.model_number.like(search_term))
1790
        query_clause.append(Item.model_name.like(search_term))
1791
 
1792
    query = query.filter(or_(*query_clause))
1793
 
1794
    return query.count()
1795
 
3924 rajveer 1796
def __clear_homepage_cache():
1797
    try:
1798
        # create a password manager
1799
        password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
1800
        # Add the username and password.
1801
        configclient = ConfigClient()
4310 rajveer 1802
        ips = configclient.get_property("production_servers_private_ips");
3924 rajveer 1803
        ips = ips.split(" ")
1804
 
1805
        for ip in ips:
4310 rajveer 1806
            try:
1807
                top_level_url = "http://" + ip + ":8080/"
1808
                password_mgr.add_password(None, top_level_url, "saholic", "shop2020")
1809
                handler = urllib2.HTTPBasicAuthHandler(password_mgr)
3924 rajveer 1810
 
4310 rajveer 1811
                opener = urllib2.build_opener(handler)
3924 rajveer 1812
 
4310 rajveer 1813
                # use the opener to fetch a URL
1814
                res = opener.open(top_level_url + "cache-admin/HomePageSnippets?_method=delete")
1815
                print "Successfully cleared home page cache" + res.read()
1816
            except:
1817
                print "Unable to clear home page cache" + res.read()
3924 rajveer 1818
    except:
1819
        print "Unable to clear cache, still should continue with other operations"
4024 chandransh 1820
 
4062 chandransh 1821
def get_pending_orders_inventory(vendor_id=1):
4024 chandransh 1822
    """
1823
    Returns a list of inventory stock for items for which there are pending orders.
1824
    """
4341 rajveer 1825
 
5110 mandeep.dh 1826
    warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter_by(vendor_id = vendor_id)]
4064 chandransh 1827
    pending_items_inventory = []
1828
    if warehouse_ids:
5424 rajveer 1829
        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()
4024 chandransh 1830
    return pending_items_inventory
4295 varun.gupt 1831
 
1832
def get_product_notifications(start_datetime):
1833
    '''
1834
    Returns a list of Product Notification objects each representing user requests for notification
1835
    '''
1836
    query = ProductNotification.query
3924 rajveer 1837
 
4295 varun.gupt 1838
    if start_datetime:
1839
        query = query.filter(ProductNotification.addedOn > start_datetime)
1840
 
1841
    notifications = query.order_by(desc('addedOn')).all()
1842
    return notifications
1843
 
1844
def get_product_notification_request_count(start_datetime):
1845
    '''
1846
    Returns list of items and the counts of product notification requests
1847
    '''
1848
    print start_datetime
1849
    query = session.query(ProductNotification, func.count(ProductNotification.email).label('count'))
1850
 
1851
    if start_datetime:
1852
        query = query.filter(ProductNotification.addedOn > start_datetime)
1853
 
1854
    counts = query.group_by(ProductNotification.item_id).order_by(desc('count')).all()
1855
    return counts
1856
 
766 rajveer 1857
def close_session():
1858
    if session.is_active:
1859
        print "session is active. closing it."
1399 rajveer 1860
        session.close()
3376 rajveer 1861
 
1862
def is_alive():
1863
    try:
1864
        session.query(Item.id).limit(1).one()
1865
        return True
1866
    except:
1867
        return False
4332 anupam.sin 1868
 
1869
def add_vendor(vendor):
1870
    if not vendor:
1871
        raise InventoryServiceException(108, "Bad vendor")
1872
    if get_Vendor(vendor.id):
1873
        #vendor is already present.
1874
        raise InventoryServiceException(101, "Vendor already present")
1875
 
1876
    ds_vendor = Vendor()
1877
    ds_vendor.id = vendor.id
1878
    ds_vendor.name = vendor.name
1879
    session.commit()
1880
    return ds_vendor.id
1881
 
1882
def add_warehouse_vendor_mapping(warehouse_id, VendorId):
1883
    return True
1884
 
4649 phani.kuma 1885
def add_authorization_log_for_item(itemId, username, reason):
1886
    if not itemId or not username:
1887
        raise InventoryServiceException(101, "Bad itemId or Invalid username in request")
1888
    authorize_log = AuthorizationLog()
1889
    authorize_log.item_id = itemId
1890
    authorize_log.username = username
1891
    authorize_log.reason = reason
1892
    session.commit()
4797 rajveer 1893
    return True
1894
 
1895
def __send_mail_for_oos_item(item): 
1896
    try:
4930 rajveer 1897
        EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', ['abhishek.mathur@shop2020.in', 'chaitnaya.vats@shop2020.in'], "Item is out of stock. ID: " + str(item.id)  + " " + str(item.brand) +  " " + str(item.model_name) + " " + str(item.model_number)+ " " + str(item.color), None)
4797 rajveer 1898
    except Exception as e:
1899
        print e
4985 mandeep.dh 1900
 
1901
def mark_missed_inventory_updates_as_processed(itemKey, warehouseId):
1902
    MissedInventoryUpdate.query.filter_by(itemKey = itemKey, warehouseId = warehouseId).delete()
1903
    session.commit()
1904
 
1905
def get_item_keys_to_be_processed(warehouseId):
1906
    return [i.itemKey for i in MissedInventoryUpdate.query.filter_by(warehouseId = warehouseId, isIgnored = 0)]
1907
 
1908
def reset_availability(itemKey, vendorId, quantity, warehouseId):
1909
    vendorItemMapping = VendorItemMapping.get_by(vendor_id = vendorId, item_key = itemKey)
1910
    if vendorItemMapping:
1911
        itemId = vendorItemMapping.item_id
1912
        currentInventorySnapshot = CurrentInventorySnapshot.get_by(item_id = itemId, warehouse_id = warehouseId)
1913
        if currentInventorySnapshot:
5424 rajveer 1914
            currentInventorySnapshot.availability = quantity
5768 mandeep.dh 1915
            __update_item_availability_cache(itemId) 
1916
            check_risky_item(currentInventorySnapshot.item)
4985 mandeep.dh 1917
        else:
1918
            add_inventory(itemId, warehouseId, quantity)
5768 mandeep.dh 1919
 
4985 mandeep.dh 1920
    else:
1921
        raise InventoryServiceException(101, 'VendorMapping not found for: ' + itemKey)
1922
    session.commit()
5047 amit.gupta 1923
 
5437 mandeep.dh 1924
def reset_availability_for_warehouse(warehouseId):
5474 mandeep.dh 1925
    for currentInventorySnapshot in CurrentInventorySnapshot.query.filter_by(warehouse_id=warehouseId).all():
1926
        currentInventorySnapshot.availability = 0
5557 mandeep.dh 1927
        __update_item_availability_cache(currentInventorySnapshot.item_id)
1928
        check_risky_item(currentInventorySnapshot.item) 
5437 mandeep.dh 1929
    session.commit()
1930
 
5047 amit.gupta 1931
def __send_mail(subject, message):
5080 amit.gupta 1932
    try:
1933
        thread = threading.Thread(target=partial(mail, from_user, from_pwd, to_addresses, subject, message))
1934
        thread.start()
1935
    except Exception as ex:
1936
        print ex    
5185 mandeep.dh 1937
 
1938
def get_shipping_locations():
1939
    shippingLocationIds = {}
1940
    warehouses = Warehouse.query.all()
1941
    for warehouse in warehouses:
1942
        if warehouse.shippingWarehouseId:
1943
            shippingLocationIds[warehouse.shippingWarehouseId] = 1
1944
 
1945
    shippingLocations = []
1946
    for shippingLocationId in shippingLocationIds:
1947
        shippingLocations.append(get_Warehouse(shippingLocationId))
1948
 
5313 mandeep.dh 1949
    return shippingLocations
1950
 
1951
def get_inventory_snapshot(warehouseId):
1952
    query = CurrentInventorySnapshot.query
1953
 
1954
    if warehouseId:
1955
        query = query.filter_by(warehouse_id = warehouseId)
1956
 
1957
    itemInventoryMap = {}
1958
    for row in query.all():
1959
        if not itemInventoryMap.has_key(row.item_id):
1960
            itemInventoryMap[row.item_id] = []
1961
 
1962
        itemInventoryMap[row.item_id].append(row)
1963
 
1964
    return itemInventoryMap
5460 phani.kuma 1965
 
1966
def get_clearance_sale_catalog_ids():
1967
    all_status = [status.ACTIVE, status.PAUSED, status.PAUSED_BY_RISK]
1968
    query = Item.query.filter_by(clearance=True)
1969
    query = query.filter(Item.status.in_(all_status))
1970
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.startDate)).order_by(Item.catalog_item_id)
1971
    clearance_sales = query.all()
1972
    return [item.catalog_item_id for item in clearance_sales]
5712 mandeep.dh 1973
 
1974
def update_vendor_string(warehouseId, vendorString):
1975
    warehouse = get_Warehouse(warehouseId)
1976
    warehouse.vendorString = vendorString
1977
    session.commit()