Subversion Repositories SmartDukaan

Rev

Rev 6805 | Rev 6826 | 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
5944 mandeep.dh 8
from shop2020.clients.CatalogClient import CatalogClient
4748 mandeep.dh 9
from shop2020.clients.HelperClient import HelperClient
5944 mandeep.dh 10
from shop2020.clients.InventoryClient import InventoryClient
4748 mandeep.dh 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
5944 mandeep.dh 15
from shop2020.model.v1.catalog.impl.DataService import Item, ItemChangeLog, \
16
    Category, EntityIDGenerator, SimilarItems, ProductNotification, Source, \
6531 vikram.rag 17
    SourceItemPricing, AuthorizationLog, VoucherItemMapping, CategoryVatMaster, \
6805 anupam.sin 18
    OOSTracker,EntityTag, ItemInsurerMapping, Insurer
5944 mandeep.dh 19
from shop2020.thriftpy.model.v1.catalog.ttypes import status, ItemShippingInfo, \
6805 anupam.sin 20
    ItemType, PremiumType
5944 mandeep.dh 21
from shop2020.thriftpy.model.v1.inventory.ttypes import \
6531 vikram.rag 22
    InventoryServiceException, IgnoredInventoryUpdateItems
4873 mandeep.dh 23
from shop2020.utils import EmailAttachmentSender
4748 mandeep.dh 24
from shop2020.utils.EmailAttachmentSender import mail
5318 rajveer 25
from shop2020.utils.Utils import to_py_date, log_risky_flag
621 chandransh 26
from sqlalchemy import desc, asc
6039 amit.gupta 27
from sqlalchemy.sql.expression import or_, distinct, func, and_
3086 rajveer 28
from string import Template
4748 mandeep.dh 29
import datetime
30
import sys
5393 mandeep.dh 31
import threading
3924 rajveer 32
import urllib2
94 ashish 33
 
5978 rajveer 34
sourceId = int(ConfigClient().get_property("sourceid"))
6550 rajveer 35
to_addresses = ["khushal.bhatia@shop2020.in", "chandan.kumar@shop2020.in",  "chaitnaya.vats@shop2020.in"]
6029 rajveer 36
mail_user = "cnc.center@shop2020.in"
37
mail_password = "5h0p2o2o"
38
source_name = "Saholic"
39
source_url = "www.saholic.com"
5885 mandeep.dh 40
skippedItems = { 175 : [27, 2160, 2175, 2163, 2158, 7128, 26, 2154],
41
                 193 : [5839] }
5047 amit.gupta 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
 
6821 amar.kumar 56
def get_all_alive_items():
57
    query = Item.query
58
    query = query.filter(Item.status!=status.DELETED).filter(Item.status!=status.PHASED_OUT)
59
    items = query.all()
60
    return items
61
 
62
 
3849 chandransh 63
def get_all_items(is_active, offset=0, limit=None):
103 ashish 64
    if is_active:
3849 chandransh 65
        items = get_all_items_by_status(status.ACTIVE, offset, limit)
103 ashish 66
    else:
3849 chandransh 67
        items = get_all_items_by_status(None, offset, limit)
766 rajveer 68
    return items
69
 
3849 chandransh 70
def get_item_count_by_status(use_status, status):
71
    if use_status:
72
        return Item.query.filter_by(status=status).count()
103 ashish 73
    else:
3849 chandransh 74
        return Item.query.count()
103 ashish 75
 
635 rajveer 76
def get_item(item_id):
766 rajveer 77
    item = Item.get_by(id=item_id)
78
    return item
94 ashish 79
 
635 rajveer 80
def get_items_by_catalog_id(catalog_id):
447 rajveer 81
    query = Item.query.filter_by(catalog_item_id=catalog_id)
437 rajveer 82
    try:
635 rajveer 83
        items = query.all()
4934 amit.gupta 84
        return items
1399 rajveer 85
    except Exception as ex:
86
        print ex
437 rajveer 87
        raise InventoryServiceException(109, "Item not found")
5586 phani.kuma 88
 
89
def is_valid_catalog_id(catalog_id):
90
    item = Item.query.filter_by(catalog_item_id=catalog_id).first()
91
    if item is not None:
92
        return True
93
    else:
94
        return False
95
 
576 chandransh 96
def is_active(item_id):
2983 chandransh 97
    t_item_shipping_info = ItemShippingInfo()
576 chandransh 98
    try:
635 rajveer 99
        item = get_item(item_id)
3281 chandransh 100
        t_item_shipping_info.isRisky = item.risky
5944 mandeep.dh 101
        client = InventoryClient().get_client()
5978 rajveer 102
        itemInfo = client.getItemAvailabilityAtLocation(item.id, sourceId)
5944 mandeep.dh 103
        warehouse_id = itemInfo[0]
5393 mandeep.dh 104
        if item.risky and item.status == status.ACTIVE:
5944 mandeep.dh 105
            availability = client.getItemAvailibilityAtWarehouse(warehouse_id, item_id)
106
            if availability <= 0:
5393 mandeep.dh 107
                add_status_change_log(item, status.PAUSED_BY_RISK)
108
                item.status = status.PAUSED_BY_RISK
109
                item.status_description = "This item is currently out of stock"
110
                session.commit()
111
                __send_mail_for_oos_item(item)
112
                #This will clear cache from tomcat
113
                __clear_homepage_cache()
114
        else:
5944 mandeep.dh 115
            availability = itemInfo[4]
2983 chandransh 116
        t_item_shipping_info.isActive = (item.status == status.ACTIVE)
3281 chandransh 117
        t_item_shipping_info.quantity = availability
576 chandransh 118
    except InventoryServiceException:
2983 chandransh 119
        print "[ERROR] Unexpected error:", sys.exc_info()[0]
120
    return t_item_shipping_info
121
 
2035 rajveer 122
def get_item_status_description(itemId):
123
    item = get_item(itemId)
124
    return item.status_description
94 ashish 125
 
122 ashish 126
def update_item(item):
127
    if not item:
128
        raise InventoryServiceException(108, "Bad item in request")
129
 
130
    if not item.id:
609 chandransh 131
        raise InventoryServiceException(101, "Missing id for update")
122 ashish 132
 
2120 ankur.sing 133
    validate_item_prices(item)
2065 ankur.sing 134
 
635 rajveer 135
    ds_item = get_item(item.id)
5047 amit.gupta 136
    message = ""
122 ashish 137
    if not ds_item:
609 chandransh 138
        raise InventoryServiceException(101, "Item missing in our database")
122 ashish 139
 
963 chandransh 140
    if item.productGroup:
141
        ds_item.product_group = item.productGroup 
142
    if item.brand:
143
        ds_item.brand = item.brand
511 rajveer 144
    if item.modelNumber:
145
        ds_item.model_number = item.modelNumber
2497 ankur.sing 146
    ds_item.color = item.color
147
    ds_item.model_name = item.modelName
148
    ds_item.category = item.category
149
    ds_item.comments = item.comments
511 rajveer 150
 
2497 ankur.sing 151
    ds_item.catalog_item_id = item.catalogItemId
483 rajveer 152
 
2129 ankur.sing 153
    ds_item.mrp = item.mrp
5047 amit.gupta 154
    if ds_item.sellingPrice or item.sellingPrice:
155
        if ds_item.sellingPrice != item.sellingPrice:
156
            message += "Selling Price is changed from {0} to {1}.\n".format(ds_item.sellingPrice, item.sellingPrice)
157
 
2129 ankur.sing 158
    ds_item.sellingPrice = item.sellingPrice
2497 ankur.sing 159
 
2174 ankur.sing 160
    ds_item.weight = item.weight
6241 amit.gupta 161
    ds_item.showSellingPrice = item.showSellingPrice
2129 ankur.sing 162
 
2358 ankur.sing 163
    if ds_item.status != item.itemStatus:
2402 rajveer 164
        add_status_change_log(ds_item, item.itemStatus)
5047 amit.gupta 165
        if item.itemStatus == status.PHASED_OUT:
166
            message += "Item is phased out."
2358 ankur.sing 167
        ds_item.status = item.itemStatus
2035 rajveer 168
    if item.status_description:
169
        ds_item.status_description = item.status_description
122 ashish 170
 
511 rajveer 171
    if item.startDate:
2116 ankur.sing 172
        ds_item.startDate = to_py_date(item.startDate)
6696 rajveer 173
        ds_item.startDate = ds_item.startDate.replace(hour=0,second=0,minute=0)
2497 ankur.sing 174
    else:
175
        ds_item.startDate = None
511 rajveer 176
    if item.retireDate:
2116 ankur.sing 177
        ds_item.retireDate = to_py_date(item.retireDate)
2497 ankur.sing 178
    else:
179
        ds_item.retireDate = None
5217 amit.gupta 180
 
181
    if item.expectedArrivalDate:
182
        ds_item.expectedArrivalDate = to_py_date(item.expectedArrivalDate)
183
    else:
184
        ds_item.expectedArrivalDate = None
511 rajveer 185
 
5217 amit.gupta 186
    if item.comingSoonStartDate:
187
        ds_item.comingSoonStartDate = to_py_date(item.comingSoonStartDate)
6696 rajveer 188
        ds_item.comingSoonStartDate = ds_item.comingSoonStartDate.replace(hour=0,second=0,minute=0)
5217 amit.gupta 189
    else:
190
        ds_item.comingSoonStartDate = None
191
 
192
 
2497 ankur.sing 193
    ds_item.feature_id = item.featureId
194
    ds_item.feature_description = item.featureDescription
122 ashish 195
 
5047 amit.gupta 196
    if ds_item.bestDealText or item.bestDealText:
197
        if item.bestDealText != ds_item.bestDealText:
5080 amit.gupta 198
            message += "Promotion text is changed from '{0}' to '{1}'.\n".format(ds_item.bestDealText, item.bestDealText)
2129 ankur.sing 199
    ds_item.bestDealText = item.bestDealText
200
    ds_item.bestDealValue = item.bestDealValue
2065 ankur.sing 201
    ds_item.bestSellingRank = item.bestSellingRank
2497 ankur.sing 202
 
6777 vikram.rag 203
    if ds_item.bestDealsDetailsText or item.bestDealsDetailsText:
204
        if item.bestDealsDetailsText != ds_item.bestDealsDetailsText:
205
            message += "Best deals details text is changed from '{0}' to '{1}'.\n".format(ds_item.bestDealsDetailsText, item.bestDealsDetailsText)
206
    ds_item.bestDealsDetailsText = item.bestDealsDetailsText
207
 
208
    if ds_item.bestDealsDetailsLink or item.bestDealsDetailsLink:
209
        if item.bestDealsDetailsLink != ds_item.bestDealsDetailsLink:
210
            message += "Best deals details link is changed from '{0}' to '{1}'.\n".format(ds_item.bestDealsDetailsLink, item.bestDealsDetailsLink)
211
    ds_item.bestDealsDetailsLink = item.bestDealsDetailsLink
212
 
213
 
2065 ankur.sing 214
    ds_item.defaultForEntity = item.defaultForEntity
5047 amit.gupta 215
 
216
    if ds_item.risky or item.risky:
217
        if ds_item.risky != item.risky:
5080 amit.gupta 218
            message += "Risky flag is changed to '{0}'.\n".format(set)
5047 amit.gupta 219
 
2251 ankur.sing 220
    ds_item.risky = item.risky
3359 chandransh 221
 
5385 phani.kuma 222
    ds_item.type = ItemType._VALUES_TO_NAMES[item.type]
223
    ds_item.hasItemNo = item.hasItemNo
5460 phani.kuma 224
    ds_item.clearance = item.clearance
5385 phani.kuma 225
 
3459 chandransh 226
    if item.expectedDelay is not None:
3359 chandransh 227
        ds_item.expectedDelay = item.expectedDelay
4506 phani.kuma 228
 
229
    if item.preferredVendor:
5080 amit.gupta 230
        if item.preferredVendor != ds_item.preferredVendor:
5944 mandeep.dh 231
            inventoryClient = InventoryClient().get_client()
232
            newPreferredVendorName = inventoryClient.getVendor(item.preferredVendor).name
5080 amit.gupta 233
            oldPreferredVendorName = 'None'
234
            if ds_item.preferredVendor:
5944 mandeep.dh 235
                oldPreferredVendorName = inventoryClient.getVendor(ds_item.preferredVendor).name
5408 amit.gupta 236
            message += "Preferred vendor is changed from '{0}' to '{1}'.\n".format(oldPreferredVendorName, newPreferredVendorName)        
4506 phani.kuma 237
        ds_item.preferredVendor = item.preferredVendor
5080 amit.gupta 238
 
239
    if item.isWarehousePreferenceSticky != ds_item.isWarehousePreferenceSticky:
240
        flag = "ON" if item.isWarehousePreferenceSticky else "OFF"
241
        message += "Warehouse preference sticky is {0}.\n".format(flag)
242
 
4413 anupam.sin 243
    ds_item.isWarehousePreferenceSticky = item.isWarehousePreferenceSticky
3359 chandransh 244
 
2347 ankur.sing 245
    ds_item.updatedOn = datetime.datetime.now()
2065 ankur.sing 246
 
122 ashish 247
    session.commit();
5047 amit.gupta 248
    subject = "Item '{0}' is updated in Catalog. Id is {1}".format(__get_product_name(ds_item),ds_item.id)
249
    if message:
250
        __send_mail(subject, message)
122 ashish 251
    return ds_item.id
94 ashish 252
 
103 ashish 253
def add_item(item):
254
    if not item:
122 ashish 255
        raise InventoryServiceException(108, "Bad item in request")
635 rajveer 256
    if get_item(item.id):
122 ashish 257
        raise InventoryServiceException(101, "Item already exists")
2120 ankur.sing 258
 
259
    validate_item_prices(item)
260
 
103 ashish 261
    ds_item = Item()
963 chandransh 262
    if item.productGroup:
263
        ds_item.product_group = item.productGroup
264
    if item.brand:
265
        ds_item.brand = item.brand
515 rajveer 266
    if item.modelName:
267
        ds_item.model_name = item.modelName
268
    if item.modelNumber:
269
        ds_item.model_number = item.modelNumber
609 chandransh 270
    if item.color:
271
        ds_item.color = item.color
483 rajveer 272
    if item.category:
273
        ds_item.category = item.category
274
    if item.comments:
275
        ds_item.comments = item.comments
276
 
103 ashish 277
    ds_item.addedOn = datetime.datetime.now()
609 chandransh 278
    ds_item.updatedOn = datetime.datetime.now()
2116 ankur.sing 279
    if item.startDate:
280
        ds_item.startDate = to_py_date(item.startDate)
6696 rajveer 281
        ds_item.startDate = ds_item.startDate.replace(hour=0,second=0,minute=0)
2116 ankur.sing 282
    if item.retireDate:
283
        ds_item.retireDate = to_py_date(item.retireDate)
5217 amit.gupta 284
    if item.comingSoonStartDate:
285
        ds_item.comingSoonStartDate = to_py_date(item.comingSoonStartDate)
286
    if item.expectedArrivalDate:
287
        ds_item.expectedArrivalDate = to_py_date(item.expectedArrivalDate)    
483 rajveer 288
    if item.mrp:
289
        ds_item.mrp = item.mrp
290
    if item.sellingPrice:
291
        ds_item.sellingPrice = item.sellingPrice
122 ashish 292
    if item.weight:
293
        ds_item.weight = item.weight
294
 
295
    if item.featureId:
296
        ds_item.feature_id = item.featureId
297
    if item.featureDescription:
298
        ds_item.feature_description = item.featureDescription
299
 
2116 ankur.sing 300
 
103 ashish 301
    #check if categories present. If yes, add them to system
122 ashish 302
 
609 chandransh 303
    if item.bestDealValue:
304
        ds_item.bestDealValue = item.bestDealValue
305
    if item.bestDealText:
306
        ds_item.bestDealText = item.bestDealText
6777 vikram.rag 307
    if item.bestDealsDetailsText:
308
        ds_item.bestDealsDetailsText = item.bestDealsDetailsText
309
    if item.bestDealsDetailsLink:
310
        ds_item.bestDealsDetailsLink = item.bestDealsDetailsLink    
2116 ankur.sing 311
    if item.bestSellingRank:
312
        ds_item.bestSellingRank = item.bestSellingRank
313
    ds_item.defaultForEntity = item.defaultForEntity
2251 ankur.sing 314
    ds_item.risky = item.risky
609 chandransh 315
 
5385 phani.kuma 316
    ds_item.type = ItemType._VALUES_TO_NAMES[item.type]
317
    ds_item.hasItemNo = item.hasItemNo
5460 phani.kuma 318
    ds_item.clearance = item.clearance
5385 phani.kuma 319
 
3467 chandransh 320
    if item.expectedDelay is not None:
3359 chandransh 321
        ds_item.expectedDelay = item.expectedDelay
3467 chandransh 322
    else:
323
        ds_item.expectedDelay = 0
3359 chandransh 324
 
5408 amit.gupta 325
    preferredVendorName = "None"
4881 phani.kuma 326
    if item.preferredVendor:
327
        ds_item.preferredVendor = item.preferredVendor
5944 mandeep.dh 328
        inventoryClient = InventoryClient().get_client()
329
        preferredVendorName = inventoryClient.getVendor(item.preferredVendor).name        
4881 phani.kuma 330
 
5586 phani.kuma 331
    if item.catalogItemId:
332
        catalog_client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
333
        master_items = catalog_client.getItemsByCatalogId(item.catalogItemId)
334
        itemStatus = status.IN_PROCESS
335
        for masterItem in master_items:
336
            if masterItem.itemStatus in [status.CONTENT_COMPLETE, status.COMING_SOON, status.ACTIVE, status.PAUSED]:
337
                itemStatus = status.CONTENT_COMPLETE
338
                ds_item.category = masterItem.category
339
                break
340
        ds_item.catalog_item_id = item.catalogItemId
341
        ds_item.status = itemStatus
2116 ankur.sing 342
        ds_item.status_description = "This item is in process."
343
    else:
5586 phani.kuma 344
        # Check if a similar item already exists in our database
345
        similar_item = Item.query.filter_by(brand=item.brand, model_number=item.modelNumber, model_name=item.modelName).first()
346
        print "[SIMILAR ITEM FOUND:] FOR {0} {1} {2}".format(item.brand, item.modelNumber, item.modelName)
347
 
348
        if similar_item is None or similar_item.catalog_item_id is None:
349
            # If there is no similar item in the database from before,
350
            # use the entity_id_generator
351
            entity_id = EntityIDGenerator.query.first()
352
            ds_item.catalog_item_id = entity_id.id + 1
353
            ds_item.status = status.IN_PROCESS
354
            ds_item.status_description = "This item is in process."
355
            entity_id.id = entity_id.id  + 1
356
            if similar_item is not None and similar_item.catalog_item_id is None:
357
                similar_item.catalog_item_id = entity_id.id
358
        else:
359
            #If a similar item already exists for a product group, brand and model_number, set it as same.
360
            ds_item.catalog_item_id = similar_item.catalog_item_id
361
            ds_item.category = similar_item.category
362
            ds_item.product_group = similar_item.product_group
363
            ds_item.status = similar_item.status
364
            ds_item.status_description = similar_item.status_description
2116 ankur.sing 365
 
103 ashish 366
    session.commit();
5052 amit.gupta 367
    subject = "New item is added. Id is {0}".format(str(ds_item.id))
6777 vikram.rag 368
    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,item.bestDealsDetailsText,item.bestDealsDetailsLink, preferredVendorName)
5047 amit.gupta 369
    __send_mail(subject, message)
3325 chandransh 370
    return ds_item.id
371
 
103 ashish 372
def retire_item(item_id):
373
    if not item_id:
122 ashish 374
        raise InventoryServiceException(101, "bad item id")
635 rajveer 375
    item = get_item(item_id)
103 ashish 376
    if not item:
122 ashish 377
        raise InventoryServiceException(108, "item id not present")
378
    item.status = status.PHASED_OUT
379
    item.retireDate = datetime.datetime.now()
103 ashish 380
    session.commit()
122 ashish 381
 
382
#need to implement threads based solution here
103 ashish 383
def start_item_on(item_id, timestamp):
384
    if not item_id:
122 ashish 385
        raise InventoryServiceException(101, "bad item id")
635 rajveer 386
    item = get_item(item_id)
103 ashish 387
    if not item:
122 ashish 388
        raise InventoryServiceException(108, "item id not present")
103 ashish 389
 
122 ashish 390
    item.status = status.ACTIVE
391
    item.startDate = datetime.datetime.fromtimestamp(to_py_date(timestamp))
392
    add_status_change_log(item, status.ACTIVE)
103 ashish 393
    session.commit()
394
 
122 ashish 395
#need to implement threads here
103 ashish 396
def retire_item_on(item_id, timestamp):
397
    if not item_id:
122 ashish 398
        raise InventoryServiceException(101, "bad item id")
635 rajveer 399
    item = get_item(item_id)
103 ashish 400
    if not item:
122 ashish 401
        raise InventoryServiceException(108, "item id not present")
103 ashish 402
 
122 ashish 403
    item.status = status.PHASED_OUT
404
    item.retireDate = datetime.datetime.fromtimestamp(to_py_date(timestamp))
405
    add_status_change_log(item, status.PHASED_OUT)
103 ashish 406
    session.commit()
407
 
408
def add_status_change_log(item, new_status):
409
    item_change_log = ItemChangeLog()
410
    item_change_log.new_status = new_status
411
    item_change_log.old_status = item.status
412
    item_change_log.timestamp = datetime.datetime.now()
413
    item_change_log.item = item
414
    session.commit()
415
 
416
def change_item_status(item_id, new_status):
417
    if not item_id:
122 ashish 418
        raise InventoryServiceException(101, "bad item id")
635 rajveer 419
    item = get_item(item_id)
103 ashish 420
    if not item:
122 ashish 421
        raise InventoryServiceException(108, "item id not present")
2116 ankur.sing 422
    add_status_change_log(item, new_status)
122 ashish 423
    item.status = new_status
2251 ankur.sing 424
    if item.status == status.PHASED_OUT:
425
        item.status_description = "This item has been phased out"
5047 amit.gupta 426
        __send_mail("Item '{0}' is Phased-Out. Item id is {1}".format(__get_product_name(item), item_id), "")
2251 ankur.sing 427
    elif item.status == status.DELETED:
428
        item.status_description = "This item has been deleted"
3924 rajveer 429
    elif item.status == status.PAUSED:
430
        item.status_description = "This item is currently out of stock"      
431
    elif item.status == status.PAUSED_BY_RISK:
432
        item.status_description = "This item is currently out of stock"
433
        #This will clear cache from tomcat
434
        __clear_homepage_cache()  
2251 ankur.sing 435
    elif item.status == status.ACTIVE:
436
        item.status_description = "This item is active"
437
    elif item.status == status.IN_PROCESS:
438
        item.status_description = "This item is in process"
439
    elif item.status == status.CONTENT_COMPLETE:
440
        item.status_description = "This item is in process"
103 ashish 441
    session.commit()
442
 
5944 mandeep.dh 443
def check_risky_item(item_id):
635 rajveer 444
    item = get_item(item_id)
2251 ankur.sing 445
    if not item.risky:
446
        return
5944 mandeep.dh 447
    client = InventoryClient().get_client()
5978 rajveer 448
    itemInfo = client.getItemAvailabilityAtLocation(item.id, sourceId)    
5944 mandeep.dh 449
    warehouse_id = itemInfo[0]
450
    availability = client.getItemAvailibilityAtWarehouse(warehouse_id, item.id)
451
    if availability <= 0:
2251 ankur.sing 452
        if item.status == status.ACTIVE:
2984 rajveer 453
            change_item_status(item.id, status.PAUSED_BY_RISK)
4797 rajveer 454
            __send_mail_for_oos_item(item)
2251 ankur.sing 455
    else:
2984 rajveer 456
        if item.status == status.PAUSED_BY_RISK:
2251 ankur.sing 457
            change_item_status(item.id, status.ACTIVE)
6255 rajveer 458
            __send_mail_for_active_item(item.id, "Item '{0}' is Active. Item id is {1}".format(__get_product_name(item), item_id), "")
2368 ankur.sing 459
    session.commit()
2983 chandransh 460
 
2075 rajveer 461
def mark_item_as_content_complete(entity_id, category, brand, modelName, modelNumber):
2828 rajveer 462
    '''
463
    Get all the items for this entityID and update category, brand, modelName and modelNumber for all.
464
    Update Status for only IN_PROCESS items to CONTENT_COMPLETE
465
    '''
723 chandransh 466
    content_complete_status = status.CONTENT_COMPLETE
2828 rajveer 467
    items = Item.query.filter_by(catalog_item_id=entity_id).all()
723 chandransh 468
    current_timestamp = datetime.datetime.now()
469
    for item in items:
2828 rajveer 470
        if item.status == status.IN_PROCESS:
471
            item.status = content_complete_status
472
            item_change_log = ItemChangeLog()
473
            item_change_log.old_status = item.status
474
            item_change_log.new_status = content_complete_status
475
            item_change_log.timestamp = current_timestamp
476
            item_change_log.item = item
723 chandransh 477
 
4762 phani.kuma 478
        category_object = get_category(category)
479
        if category_object is not None:
480
            item.category = category
481
            item.product_group = category_object.display_name
2075 rajveer 482
        item.brand = brand
2081 rajveer 483
        item.model_name = modelName
484
        item.model_number = modelNumber
723 chandransh 485
        item.updatedOn = current_timestamp
486
    session.commit()
487
    return True
1294 chandransh 488
 
2404 chandransh 489
def get_child_categories(category):
490
    cm = CategoryManager()
2621 varun.gupt 491
    cat = cm.getCategory(category)
492
    return cat.children_category_ids if cat else None
2404 chandransh 493
 
626 chandransh 494
def get_best_sellers(start_index, stop_index, category=-1):
2404 chandransh 495
    '''
496
    Returns the Best Sellers between the start and the stop index in the given category
497
    '''
1926 rajveer 498
    query = get_best_sellers_query(category, None)
1098 chandransh 499
    best_sellers = query.all()[start_index:stop_index]
621 chandransh 500
    return get_thrift_item_list(best_sellers)
501
 
2093 chandransh 502
def get_best_sellers_count(category=-1):
2404 chandransh 503
    '''
504
    Returns the number of best sellers in the given category
505
    '''
1926 rajveer 506
    count = get_best_sellers_query(category, None).count()
1120 rajveer 507
    if count is None:
508
        count = 0
766 rajveer 509
    return count
621 chandransh 510
 
1926 rajveer 511
def get_best_sellers_catalog_ids(start_index, stop_index, brand, category=-1):
2404 chandransh 512
    '''
513
    Returns the Best sellers for the given brand and category between the start and the stop index.
514
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
515
    '''
1926 rajveer 516
    query = get_best_sellers_query(category, brand)
1098 chandransh 517
    best_sellers = query.all()[start_index:stop_index]
621 chandransh 518
    return [item.catalog_item_id for item in best_sellers]
1970 rajveer 519
 
1926 rajveer 520
def get_best_sellers_query(category, brand):
2404 chandransh 521
    '''
522
    Returns the query to be used for getting Best Sellers.
523
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
524
    '''
1098 chandransh 525
    query = Item.query.filter_by(status=status.ACTIVE).filter(Item.bestSellingRank != None)
626 chandransh 526
    if category != -1:
1970 rajveer 527
        all_categories = [category]
528
        child_categories = get_child_categories(category)
529
        if child_categories is not None:
530
            all_categories = all_categories + child_categories 
531
        query = query.filter(Item.category.in_(all_categories))
1926 rajveer 532
    if brand is not None:
533
        query = query.filter_by(brand=brand)
1098 chandransh 534
    query = query.order_by(asc(Item.bestSellingRank))
621 chandransh 535
    return query
609 chandransh 536
 
1098 chandransh 537
def get_best_deals(category=-1):
2404 chandransh 538
    '''
539
    Returns the Best deals in the given category. Ignores the category if it's passed as -1.
540
    '''
541
    query = get_best_deals_query(Item, category, None)
1098 chandransh 542
    items = query.all()
609 chandransh 543
    return get_thrift_item_list(items)
544
 
1098 chandransh 545
def get_best_deals_count(category=-1):
2404 chandransh 546
    '''
547
    Returns the count of best deals in the given category.
548
    Ignores the category if it's -1.
549
    '''
550
    count = get_best_deals_counting_query(func.count(distinct(Item.catalog_item_id)), category, None).scalar()
1120 rajveer 551
    if count is None:
552
        count = 0
766 rajveer 553
    return count
501 rajveer 554
 
1926 rajveer 555
def get_best_deals_catalog_ids(start_index, stop_index, brand, category=-1):
2404 chandransh 556
    '''
557
    Returns the catalog_item_ids of best deal items for the given brand and category.
558
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
559
    '''
560
    query = get_best_deals_query(Item, category, brand)
1098 chandransh 561
    best_deal_items = query.all()[start_index:stop_index]
562
    return [item.catalog_item_id for item in best_deal_items]
563
 
2404 chandransh 564
def get_best_deals_counting_query(obj, category, brand):
565
    '''
566
    Returns the query to be used to select the best deals in the given brand and category.
567
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
568
    '''
569
    query = session.query(obj).filter_by(status=status.ACTIVE).filter(Item.bestDealValue != None)
626 chandransh 570
    if category != -1:
1970 rajveer 571
        all_categories = [category]
572
        child_categories = get_child_categories(category)
573
        if child_categories is not None:
574
            all_categories = all_categories + child_categories 
575
        query = query.filter(Item.category.in_(all_categories))
1926 rajveer 576
    if brand is not None:
577
        query = query.filter_by(brand=brand)
2404 chandransh 578
    return query
579
 
580
def get_best_deals_query(obj, category, brand):
581
    '''
582
    Returns the query to be used to get the best deals in the given category and brand.
583
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
584
    '''
585
    query = get_best_deals_counting_query(obj, category, brand)
1098 chandransh 586
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.bestDealValue))
587
    return query
609 chandransh 588
 
5217 amit.gupta 589
def get_coming_soon(category=-1):
590
    '''
591
    Returns the Coming Soon items in the given category. Ignores the category if it's passed as -1.
592
    '''
593
    query = get_coming_soon_query(Item, category, None)
594
    items = query.all()
595
    return get_thrift_item_list(items)
596
 
597
def get_coming_soon_count(category=-1):
598
    '''
599
    Returns the count of coming in the given category.
600
    Ignores the category if it's -1.
601
    '''
602
    count = get_coming_soon_counting_query(func.count(distinct(Item.catalog_item_id)), category, None).scalar()
603
    if count is None:
604
        count = 0
605
    return count
606
 
607
def get_coming_soon_catalog_ids(start_index, stop_index, brand, category=-1):
608
    '''
609
    Returns the catalog_item_ids of coming soon items for the given brand and category.
610
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
611
    '''
612
    query = get_coming_soon_query(Item, category, brand)
613
    coming_soon_items = query.all()[start_index:stop_index]
614
    return [item.catalog_item_id for item in coming_soon_items]
615
 
616
def get_coming_soon_counting_query(obj, category, brand):
617
    '''
618
    Returns the query to be used to select the coming soon product in the given brand and category.
619
    Ignores the category if it's passed as -1 and the brand if it's passed as None. 
620
    '''
621
    query = session.query(obj).filter_by(status=status.COMING_SOON)
622
    if category != -1:
623
        all_categories = [category]
624
        child_categories = get_child_categories(category)
625
        if child_categories is not None:
626
            all_categories = all_categories + child_categories 
627
        query = query.filter(Item.category.in_(all_categories))
628
    if brand is not None:
629
        query = query.filter_by(brand=brand)
630
    return query
631
 
632
def get_coming_soon_query(obj, category, brand):
633
    '''
634
    Returns the query to be used to get the coming soon products in the given category and brand.
635
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
636
    '''
637
    query = get_coming_soon_counting_query(obj, category, brand)
638
    query = query.group_by(Item.catalog_item_id).order_by(asc(Item.comingSoonStartDate))
639
    return query
640
 
1098 chandransh 641
def get_latest_arrivals(limit, category=-1):
2404 chandransh 642
    '''
643
    Returns up to limit number of Latest Arrivals in the given category.
644
    '''
2975 chandransh 645
    categories = []
646
    if category != -1:
647
        categories = [category]
648
    query = get_latest_arrivals_query(Item, categories, None)
1098 chandransh 649
    items = query.all()[0:limit]
609 chandransh 650
    return get_thrift_item_list(items)
598 chandransh 651
 
1098 chandransh 652
def get_latest_arrivals_count(limit, category=-1):
2404 chandransh 653
    '''
654
    Returns the number of latest arrivals which will be displayed on the website.
3016 chandransh 655
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 656
    '''
2975 chandransh 657
    categories = []
658
    if category != -1:
659
        categories = [category]
660
    count = get_latest_arrivals_counting_query(func.count(distinct(Item.catalog_item_id)), categories, None).scalar()
1120 rajveer 661
    if count is None:
662
        count = 0
663
    count = min(count, limit)
766 rajveer 664
    return count
602 chandransh 665
 
2975 chandransh 666
def get_latest_arrivals_catalog_ids(start_index, stop_index, brand, categories=[]):
2404 chandransh 667
    '''
668
    Returns the catalog_item_ids of the latest arrivals between the start and the stop index
3016 chandransh 669
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 670
    '''
2975 chandransh 671
    query = get_latest_arrivals_query(Item, categories, brand)
1098 chandransh 672
    latest_arrivals = query.all()[start_index:stop_index]
673
    return [item.catalog_item_id for item in latest_arrivals]
674
 
2975 chandransh 675
def get_latest_arrivals_counting_query(obj, categories, brand):
2404 chandransh 676
    '''
677
    Returns the query to be used to count Latest arrivals.
3016 chandransh 678
    To ignore the categories, pass the list as empty. To ignore brand, pass it as null.
2404 chandransh 679
    '''
680
    query = session.query(obj).filter_by(status=status.ACTIVE)
2975 chandransh 681
 
682
    all_categories = []
683
    for category in categories:
684
        all_categories.append(category)
1970 rajveer 685
        child_categories = get_child_categories(category)
2975 chandransh 686
        if child_categories:
687
            all_categories = all_categories + child_categories
688
    if all_categories: 
1970 rajveer 689
        query = query.filter(Item.category.in_(all_categories))
2975 chandransh 690
 
1926 rajveer 691
    if brand is not None:
692
        query = query.filter_by(brand=brand)
2404 chandransh 693
    return query
694
 
2975 chandransh 695
def get_latest_arrivals_query(obj, categories, brand):
2404 chandransh 696
    '''
697
    Returns the query to be used to retrieve Latest Arrivals.
698
    Ignores the category if it's passed as -1 and the brand if it's passed as None.
699
    '''
2975 chandransh 700
    query = get_latest_arrivals_counting_query(obj, categories, brand)
5167 rajveer 701
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.startDate)).order_by(Item.catalog_item_id)
1098 chandransh 702
    return query
609 chandransh 703
 
704
def get_thrift_item_list(items):
1098 chandransh 705
    return [to_t_item(item) for item in items if item != None]
635 rajveer 706
 
1155 rajveer 707
def generate_new_entity_id():
708
    generator =  EntityIDGenerator.query.one()
709
    id = generator.id + 1
710
    generator.id = id
711
    session.commit()
712
    return id
713
 
635 rajveer 714
def put_category_object(object):
715
    category = Category.get_by(id=1)
716
    if category is None:
717
        category = Category()
718
    category.object = object    
719
    session.commit()
720
    return True
721
 
722
def get_category_object():
766 rajveer 723
    object = Category.get_by(id=1).object
724
    return object
725
 
1970 rajveer 726
def add_category(t_category):
727
    category = Category.get_by(id=t_category.id)
728
    if category is None:
729
        category = Category()
730
    category.id = t_category.id 
731
    category.label = t_category.label
732
    category.description = t_category.description
4762 phani.kuma 733
    category.display_name = t_category.display_name
1970 rajveer 734
    category.parent_category_id = t_category.parent_category_id 
735
    session.commit()
736
    return True
737
 
738
def get_category(id):
739
    return Category.query.filter_by(id=id).first()
740
 
741
def get_all_categories():
742
    return Category.query.all()
743
 
2120 ankur.sing 744
def validate_item_prices(item):
2129 ankur.sing 745
    if item.mrp == None or item.sellingPrice == None or item.mrp == "" or item.sellingPrice == "":
746
        return
747
    if item.mrp < item.sellingPrice:
2120 ankur.sing 748
        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))
749
        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 750
    return
2120 ankur.sing 751
 
752
def validate_vendor_prices(item, vendorPrices):
2129 ankur.sing 753
    if item.mrp != None and item.mrp != "" and vendorPrices.mop != "" and item.mrp <  vendorPrices.mop:
2120 ankur.sing 754
        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))
755
        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)))
756
    if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
757
        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))
758
        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)))
759
    return
2065 ankur.sing 760
 
4725 phani.kuma 761
def check_color_valid(color):
762
    if color is not None:
763
        color = color.strip().lower()
764
        if color != '' and color != 'na' and color != 'blank' and color != '(blank)':
765
            return True
766
    return False
767
 
768
def check_similar_item(brand, model_number, model_name, color):
2129 ankur.sing 769
    query = Item.query
2428 ankur.sing 770
    query = query.filter_by(brand=brand)
771
    query = query.filter_by(model_number=model_number)
4725 phani.kuma 772
    query = query.filter_by(model_name=model_name)
773
    similar_items = query.all()
774
    item = None
775
    # Check if a similar item already exists in our database
776
    for old_item in similar_items:
777
        if old_item.color != None and old_item.color.strip().lower() == color.strip().lower():
778
            item = old_item
779
            break
780
 
781
    # 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 782
    if item is None:
4725 phani.kuma 783
        for old_item in similar_items:
784
            if not check_color_valid(old_item.color):
785
                item = old_item
786
                break
787
    i = 0
788
    color_of_similar_item = None
789
    # Check if a similar item already exists in our database to be used to get catalog_item_id
790
    for old_item in similar_items:
791
        # get a similar item already existing in our database with valid color
792
        if check_color_valid(old_item.color):
793
            similar_item = old_item
794
            color_of_similar_item = similar_item.color
795
            break
796
        i = i + 1
797
        # get a similar item already existing in our database if similar item with valid color is not found
798
        if i == len(similar_items):
799
            similar_item = old_item
800
            color_of_similar_item = similar_item.color
801
 
802
    # Check if a similar item that is obtained above is having a valid color
803
    if check_color_valid(color_of_similar_item):
804
        # 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.
805
        # 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.
806
        if item is None and not check_color_valid(color):
807
            return similar_item.id
808
 
809
    if item is None:
2116 ankur.sing 810
        return 0
811
    else:
812
        return item.id
2286 ankur.sing 813
 
814
def change_risky_flag(item_id, risky):
815
    item = get_item(item_id)
816
    if not item:
817
        raise InventoryServiceException(101, "Item missing in our database")
818
    try:
819
        log_risky_flag(item_id, risky)
820
    except:
821
        print "Not able to log risky flag change"
822
    item.risky = risky
4295 varun.gupt 823
    if not risky and item.status == status.PAUSED_BY_RISK:
2368 ankur.sing 824
        change_item_status(item.id, status.ACTIVE)
6255 rajveer 825
        __send_mail_for_active_item(item.id, "Item '{0}' is Active. Item id is {1}".format(__get_product_name(item), item_id), "")
2286 ankur.sing 826
    session.commit()
5047 amit.gupta 827
    flag = "ON" if risky else "OFF"
828
    subject = "Risky flag is {0} for Item {1}.".format(flag, __get_product_name(item))
829
    __send_mail(subject,"")
2286 ankur.sing 830
 
4957 phani.kuma 831
def get_items_for_mastersheet(categoryName, brand):
832
    if not categoryName or not brand:
833
        raise InventoryServiceException(101, "Invalid category or brand in request")
834
 
4762 phani.kuma 835
    categories = ["Handsets", "Tablets", "Laptops"]
4957 phani.kuma 836
    query = Item.query.filter(Item.status != status.PHASED_OUT)
837
    if categoryName == "ALL":
838
        pass
839
    elif categoryName == "ALL Accessories":
840
        query = query.filter(~Item.product_group.in_(categories))
841
    elif categoryName == "ALL Handsets":
842
        query = query.filter(Item.product_group.in_(categories))
843
    elif categoryName == "Mobile Accessories":
844
        child_categories = get_child_categories(10011)
845
        if child_categories is not None:
846
            child_categories.append(0)
847
            query = query.filter(Item.category.in_(child_categories))
848
    elif categoryName == "Laptop Accessories":
849
        child_categories = get_child_categories(10070)
850
        if child_categories is not None:
851
            child_categories.append(0)
852
            query = query.filter(Item.category.in_(child_categories))
853
    else:
854
        query = query.filter(Item.product_group == categoryName)
855
 
856
    if brand == "ALL":
857
        pass
858
    else:
859
        query = query.filter(Item.brand == brand)
2358 ankur.sing 860
    items = query.all()
861
    return items
2116 ankur.sing 862
 
2358 ankur.sing 863
def get_risky_items():
864
    items = Item.query.filter_by(risky=True).all()
865
    return items
3008 rajveer 866
 
2809 rajveer 867
def get_similar_items_catalog_ids(start_index, stop_index, itemId):
3008 rajveer 868
    query = SimilarItems.query.filter_by(item_id=itemId).limit(stop_index-start_index)
869
    similar_items = query.all()
3289 rajveer 870
    return_list = []
871
    for similar_item in similar_items:
872
        isActive = False
873
        try:
874
            all_items = Item.query.filter_by(catalog_item_id=similar_item.catalog_item_id).all()
875
        except:
876
            continue
877
        for item in all_items:
878
            isActive = isActive or item.status == status.ACTIVE
879
        if isActive:
880
            return_list.append(similar_item.catalog_item_id)
881
    return return_list
4423 phani.kuma 882
 
883
def get_all_similar_items_catalog_ids(itemId):
884
    query = SimilarItems.query.filter_by(item_id=itemId)
885
    similar_items = query.all()
886
    return_list = []
887
    for similar_item in similar_items:
888
        item_query = Item.query.filter_by(catalog_item_id=similar_item.catalog_item_id).limit(1)
889
        item = item_query.one()
890
        return_list.append(item)
2809 rajveer 891
 
4423 phani.kuma 892
    return get_thrift_item_list(return_list)
893
 
894
def add_similar_item_catalog_id(itemId, catalog_item_id):
895
    if not itemId or not catalog_item_id:
896
        raise InventoryServiceException(101, "Bad itemId or catalogItemId in request")
897
    items_for_entity = get_items_by_catalog_id(catalog_item_id)
898
    if not len(items_for_entity):
899
        raise InventoryServiceException(101, "catalogItemId does not exists in database")
900
 
901
    s_items = SimilarItems.query.filter_by(item_id=itemId, catalog_item_id=catalog_item_id).all()
902
    if not len(s_items):
903
        s_item = SimilarItems()
904
        s_item.item_id=itemId
905
        s_item.catalog_item_id=catalog_item_id
906
        session.commit()
907
        return items_for_entity[0]
908
    else:
909
        raise InventoryServiceException(101, "Already exists")
910
 
911
def delete_similar_item_catalog_id(itemId, catalog_item_id):
912
    if not itemId or not catalog_item_id:
913
        raise InventoryServiceException(101, "Bad itemId or catalogItemId in request")
914
 
915
    similar_item = SimilarItems.query.filter_by(item_id=itemId, catalog_item_id=catalog_item_id).all()
916
    if len(similar_item):
917
        similar_item[0].delete()
918
    session.commit()
919
    return True
5504 phani.kuma 920
 
921
def get_all_vouchers_for_item(itemId):
922
    vouchers = VoucherItemMapping.query.filter_by(item_id=itemId).all()
923
    return vouchers
924
 
925
def get_voucher_amount(itemId, voucher_type):
926
    voucher = VoucherItemMapping.query.filter_by(item_id=itemId, voucherType=voucher_type).all()
927
    if len(voucher):
928
        return voucher[0].amount
929
    else:
5518 rajveer 930
        return 0
5504 phani.kuma 931
 
932
def add_update_voucher_for_item(catalog_item_id, voucher_type, voucher_amount):
933
    if not catalog_item_id or not voucher_type or not voucher_amount:
934
        raise InventoryServiceException(101, "Bad catalogItemId or voucherType or voucherAmount in request")
935
 
936
    items_for_entity = get_items_by_catalog_id(catalog_item_id)
937
    if not len(items_for_entity):
938
        raise InventoryServiceException(101, "catalogItemId does not exists in database")
939
 
940
    for item in items_for_entity:
941
        itemId = item.id
942
        voucher = VoucherItemMapping.query.filter_by(item_id=itemId, voucherType=voucher_type).all()
943
        if not len(voucher):
944
            voucher = VoucherItemMapping()
945
            voucher.item_id=itemId
946
            voucher.voucherType=voucher_type
947
            voucher.amount=voucher_amount
948
        else:
949
            voucher[0].amount=voucher_amount
950
    session.commit()
951
    return True
4423 phani.kuma 952
 
5504 phani.kuma 953
def delete_voucher_for_item(catalog_item_id, voucher_type):
954
    if not catalog_item_id or not voucher_type:
955
        raise InventoryServiceException(101, "Bad catalogItemId or voucherType in request")
956
 
957
    items_for_entity = get_items_by_catalog_id(catalog_item_id)
958
    if not len(items_for_entity):
959
        raise InventoryServiceException(101, "catalogItemId does not exists in database")
960
 
961
    for item in items_for_entity:
962
        itemId = item.id
963
        voucher = VoucherItemMapping.query.filter_by(item_id=itemId, voucherType=voucher_type).all()
964
        if len(voucher):
965
            voucher[0].delete()
966
    session.commit()
967
    return True
968
 
3079 rajveer 969
def add_product_notification(itemId, email):
970
    try:
3470 rajveer 971
        try:
972
            product_notification = ProductNotification.query.filter_by(item_id=itemId, email=email).one()
973
        except:
974
            product_notification = ProductNotification()
975
            product_notification.email = email
976
            product_notification.item_id = itemId
3079 rajveer 977
        product_notification.addedOn = datetime.datetime.now()
978
        session.commit()
979
        return True
980
    except:
981
        return False
3086 rajveer 982
 
983
 
984
def send_product_notifications():
985
    product_notifications = ProductNotification.query.all()
986
    for product_notification in product_notifications:
987
        item = product_notification.item
5944 mandeep.dh 988
        client = InventoryClient().get_client()
5978 rajveer 989
        availability = client.getItemAvailabilityAtLocation(item.id, sourceId)[4]
5125 mandeep.dh 990
        if item.status == status.ACTIVE and (not item.risky or availability > 0):
3086 rajveer 991
            __enque_product_notification_email(product_notification.email, __get_product_name(item) , product_notification.addedOn, __get_product_url(item), item.id)
992
            product_notification.delete()
993
    session.commit()
994
    return True
995
 
996
def __get_product_name(item):
997
    product_name = item.brand + " " + item.model_name + " " + item.model_number
998
    color = item.color
999
    if color is not None and color != 'NA':
1000
        product_name = product_name + " (" + color + ")"
3201 rajveer 1001
    product_name = product_name.replace("  "," ")
3086 rajveer 1002
    return product_name
1003
 
1004
 
1005
def __get_product_url(item):
6029 rajveer 1006
    product_url = "http://" + source_url + "/mobile-phones/" + item.brand + "-" + item.model_name + "-" + item.model_number + "-" + str(item.catalog_item_id)
3086 rajveer 1007
    product_url = product_url.replace("--","-")
1008
    product_url = product_url.replace(" ","")
1009
    return product_url
1010
 
3348 varun.gupt 1011
def get_all_brands_by_category(category_id):
1012
    catm = CategoryManager()
1013
    child_categories = catm.getCategory(category_id).children_category_ids
1014
    brands = session.query(distinct(Item.brand)).filter(Item.category.in_(child_categories)).all()
1015
 
1016
    return [brand[0] for brand in brands]
3086 rajveer 1017
 
4957 phani.kuma 1018
def get_all_brands():
1019
    brands = session.query(distinct(Item.brand)).order_by(Item.brand).all()
1020
 
1021
    return [brand[0] for brand in brands]
1022
 
3086 rajveer 1023
def __enque_product_notification_email(email, product, date, url, itemId):
1024
 
1025
    html = """
1026
        <html>
1027
        <body>
1028
        <div>
1029
        <p>
1030
            Hi,<br /><br />
6029 rajveer 1031
            The product requested by you on $date is now available on $source_url.
3086 rajveer 1032
        </p>
1033
 
1034
        <p>    
1035
        <strong>Product: $product </strong>
1036
        </p>
1037
 
1038
        <p>
1039
        Click the link below to visit the product: 
1040
        <br/>
1041
        $url
1042
        </p>
1043
        <p>
1044
        Regards,<br/>
6029 rajveer 1045
        $source_name Customer Support Team<br/>
1046
        $source_url<br/>
3086 rajveer 1047
        Email: help@saholic.com<br/>
1048
        </p>
1049
        </div>
1050
        </body>
1051
        </html>
1052
        """
1053
 
6029 rajveer 1054
    html = Template(html).substitute(dict(product=product,date=date,url=url,source_url=source_url,source_name=source_name))
3079 rajveer 1055
 
3086 rajveer 1056
    try:
1057
        helper_client = HelperClient().get_client()
5866 rajveer 1058
        helper_client.saveUserEmailForSending([email], "", "Product requested by you is available now.", html, str(itemId), "ProductNotification", [], [])
3086 rajveer 1059
    except Exception as e:
1060
        print e
1061
 
3557 rajveer 1062
def get_all_sources():
1063
    sources = Source.query.all()
1064
    return [to_t_source(source) for source in sources]
3086 rajveer 1065
 
3557 rajveer 1066
def get_item_pricing_by_source(itemId, sourceId):
1067
    item = Item.query.filter_by(id=itemId).first()
1068
    if item is None:
1069
        raise InventoryServiceException(101, "Bad Item")
1070
 
1071
    source = Source.query.filter_by(id=sourceId).first()
1072
    if source is None:
1073
        raise InventoryServiceException(101, "Source not found for sourceId " + str(sourceId))
1074
 
1075
    item_pricing = SourceItemPricing.query.filter_by(source=source, item=item).first()
1076
    if item_pricing is None:
1077
        raise InventoryServiceException(101, "Pricing information not found for sourceId " + str(sourceId))
1078
    return item_pricing
1079
 
1080
def add_source_item_pricing(sourceItemPricing):
1081
    if not sourceItemPricing:
1082
        raise InventoryServiceException(108, "Bad sourceItemPricing in request")
1083
 
1084
    if not sourceItemPricing.sellingPrice:
4326 mandeep.dh 1085
        raise InventoryServiceException(101, "Selling Price is not defined for sourceId " + str(sourceItemPricing.sourceId))
3557 rajveer 1086
 
1087
    sourceId = sourceItemPricing.sourceId
1088
    itemId = sourceItemPricing.itemId
1089
 
1090
    item = Item.query.filter_by(id=itemId).first()
1091
    if item is None:
1092
        raise InventoryServiceException(101, "Bad Item")
1093
 
1094
    source = Source.query.filter_by(id=sourceId).first()
1095
    if source is None:
1096
        raise InventoryServiceException(101, "Source not found for sourceId " + str(sourceId))
1097
 
3564 rajveer 1098
    ds_sourceItemPricing = SourceItemPricing.get_by(source=source, item=item)
3557 rajveer 1099
    if ds_sourceItemPricing is None:
1100
        ds_sourceItemPricing = SourceItemPricing()
1101
        ds_sourceItemPricing.source = source
1102
        ds_sourceItemPricing.item = item
1103
 
1104
    if sourceItemPricing.mrp:
1105
        ds_sourceItemPricing.mrp = sourceItemPricing.mrp
1106
    ds_sourceItemPricing.sellingPrice = sourceItemPricing.sellingPrice
1107
 
1108
    session.commit()
1109
    return
1110
 
1111
def get_all_source_pricing(itemId):
1112
    item = Item.query.filter_by(id=itemId).first()
1113
    if item is None:
1114
        raise InventoryServiceException(101, "Bad Item")
1115
    source_pricing = SourceItemPricing.query.filter_by(item=item).all()
1116
    return source_pricing
1117
 
1118
 
1119
def get_item_for_source(item_id, sourceId):
1120
    item = get_item(item_id)
1121
    if sourceId == -1:
1122
        return item
1123
    try:
1124
        sip = get_item_pricing_by_source(item_id, sourceId)
1125
        item.sellingPrice = sip.sellingPrice
1126
        if sip.mrp:
1127
            item.mrp = sip.mrp
1128
    except:
1129
        print "No source pricing"
1130
    return item
1131
 
3872 chandransh 1132
def search_items(search_terms, offset, limit):
1133
    query = Item.query
1134
 
1135
    search_terms = ['%' + search_term + '%' for search_term in search_terms]
1136
 
1137
    for search_term in search_terms:
6661 rajveer 1138
        query_clause = []
3872 chandransh 1139
        query_clause.append(Item.brand.like(search_term))
1140
        query_clause.append(Item.model_number.like(search_term))
1141
        query_clause.append(Item.model_name.like(search_term))
6661 rajveer 1142
        query = query.filter(or_(*query_clause))
3872 chandransh 1143
 
1144
    query = query.order_by(Item.product_group, Item.brand, Item.model_number, Item.model_name).offset(offset)
1145
    if limit:
1146
        query = query.limit(limit)
1147
    items = query.all()
1148
    return items
1149
 
1150
def get_search_result_count(search_terms):
1151
    query = Item.query
1152
 
1153
    search_terms = ['%' + search_term + '%' for search_term in search_terms]
1154
 
1155
    for search_term in search_terms:
6661 rajveer 1156
        query_clause = []
3872 chandransh 1157
        query_clause.append(Item.brand.like(search_term))
1158
        query_clause.append(Item.model_number.like(search_term))
1159
        query_clause.append(Item.model_name.like(search_term))
6661 rajveer 1160
        query = query.filter(or_(*query_clause))
3872 chandransh 1161
 
1162
    return query.count()
1163
 
3924 rajveer 1164
def __clear_homepage_cache():
1165
    try:
1166
        # create a password manager
1167
        password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
1168
        # Add the username and password.
1169
        configclient = ConfigClient()
4310 rajveer 1170
        ips = configclient.get_property("production_servers_private_ips");
3924 rajveer 1171
        ips = ips.split(" ")
1172
 
1173
        for ip in ips:
4310 rajveer 1174
            try:
1175
                top_level_url = "http://" + ip + ":8080/"
1176
                password_mgr.add_password(None, top_level_url, "saholic", "shop2020")
1177
                handler = urllib2.HTTPBasicAuthHandler(password_mgr)
3924 rajveer 1178
 
4310 rajveer 1179
                opener = urllib2.build_opener(handler)
3924 rajveer 1180
 
4310 rajveer 1181
                # use the opener to fetch a URL
1182
                res = opener.open(top_level_url + "cache-admin/HomePageSnippets?_method=delete")
1183
                print "Successfully cleared home page cache" + res.read()
1184
            except:
1185
                print "Unable to clear home page cache" + res.read()
3924 rajveer 1186
    except:
1187
        print "Unable to clear cache, still should continue with other operations"
4024 chandransh 1188
 
4295 varun.gupt 1189
def get_product_notifications(start_datetime):
1190
    '''
1191
    Returns a list of Product Notification objects each representing user requests for notification
1192
    '''
1193
    query = ProductNotification.query
3924 rajveer 1194
 
4295 varun.gupt 1195
    if start_datetime:
1196
        query = query.filter(ProductNotification.addedOn > start_datetime)
1197
 
1198
    notifications = query.order_by(desc('addedOn')).all()
1199
    return notifications
1200
 
1201
def get_product_notification_request_count(start_datetime):
1202
    '''
1203
    Returns list of items and the counts of product notification requests
1204
    '''
1205
    print start_datetime
1206
    query = session.query(ProductNotification, func.count(ProductNotification.email).label('count'))
1207
 
1208
    if start_datetime:
1209
        query = query.filter(ProductNotification.addedOn > start_datetime)
1210
 
1211
    counts = query.group_by(ProductNotification.item_id).order_by(desc('count')).all()
1212
    return counts
1213
 
766 rajveer 1214
def close_session():
1215
    if session.is_active:
1216
        print "session is active. closing it."
1399 rajveer 1217
        session.close()
3376 rajveer 1218
 
1219
def is_alive():
1220
    try:
1221
        session.query(Item.id).limit(1).one()
1222
        return True
1223
    except:
1224
        return False
4332 anupam.sin 1225
 
4649 phani.kuma 1226
def add_authorization_log_for_item(itemId, username, reason):
1227
    if not itemId or not username:
1228
        raise InventoryServiceException(101, "Bad itemId or Invalid username in request")
1229
    authorize_log = AuthorizationLog()
1230
    authorize_log.item_id = itemId
1231
    authorize_log.username = username
1232
    authorize_log.reason = reason
1233
    session.commit()
4797 rajveer 1234
    return True
1235
 
6255 rajveer 1236
def __send_mail_for_oos_item(item):
1237
    oos = OOSTracker.get_by(itemId = item.id)
1238
    if oos is None:
1239
        oos = OOSTracker()
1240
        oos.itemId = item.id
1241
        session.commit()
1242
        try:
1243
            EmailAttachmentSender.mail(mail_user, mail_password, to_addresses + ["abhishek.mathur@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)
1244
        except Exception as e:
1245
            print e
4985 mandeep.dh 1246
 
6255 rajveer 1247
def __send_mail_for_active_item(itemId, subject, message):
1248
    oos = OOSTracker.get_by(itemId = itemId)
1249
    if oos is not None:
1250
        oos.delete()
1251
        session.commit()
1252
    __send_mail(subject, message)
1253
 
5047 amit.gupta 1254
def __send_mail(subject, message):
5080 amit.gupta 1255
    try:
6029 rajveer 1256
        thread = threading.Thread(target=partial(mail, mail_user, mail_password, to_addresses, subject, message))
5080 amit.gupta 1257
        thread.start()
1258
    except Exception as ex:
1259
        print ex    
5185 mandeep.dh 1260
 
5460 phani.kuma 1261
def get_clearance_sale_catalog_ids():
1262
    all_status = [status.ACTIVE, status.PAUSED, status.PAUSED_BY_RISK]
1263
    query = Item.query.filter_by(clearance=True)
1264
    query = query.filter(Item.status.in_(all_status))
1265
    query = query.group_by(Item.catalog_item_id).order_by(desc(Item.startDate)).order_by(Item.catalog_item_id)
1266
    clearance_sales = query.all()
1267
    return [item.catalog_item_id for item in clearance_sales]
6039 amit.gupta 1268
 
1269
def get_vat_amount_for_item(itemId, price):
1270
    item = Item.query.filter_by(id=itemId).first()
1271
    vatPercentage = item.vatPercentage
1272
    if vatPercentage is None:
1273
        vatMaster = CategoryVatMaster.query.filter(and_(CategoryVatMaster.categoryId==item.category, CategoryVatMaster.minVal<=price,  CategoryVatMaster.maxVal>=price)).first()
1274
        vatPercentage = vatMaster.vatPercent
1275
        if  vatPercentage is None:
1276
            vatPercentage = 0
1277
    return (price*vatPercentage)/100
1278
 
1279
def get_vat_percentage_for_item(itemId, price):
1280
    item = Item.query.filter_by(id=itemId).first()
1281
    vatPercentage = item.vatPercentage
1282
    if vatPercentage is None:
1283
        vatMaster = CategoryVatMaster.query.filter(and_(CategoryVatMaster.categoryId==item.category, CategoryVatMaster.minVal<=price,  CategoryVatMaster.maxVal>=price)).first()
1284
        vatPercentage = vatMaster.vatPercent
1285
        if  vatPercentage is None:
1286
            vatPercentage = 0
1287
    return vatPercentage
6511 kshitij.so 1288
 
6531 vikram.rag 1289
def get_all_ignored_inventoryupdate_items_list(offset,limit):
1290
    client = InventoryClient().get_client()
1291
    itemids = client.getIgnoredInventoryUpdateItemids(offset,limit)
6532 amit.gupta 1292
    result = []
1293
    if itemids is not None and len(itemids)>0:
1294
        query = Item.query.filter(Item.id.in_(itemids))
1295
        query = query.order_by(Item.product_group, Item.brand, Item.model_number, Item.model_name)
1296
        result = [to_t_item(item) for item in query.all()]
1297
    return result
6531 vikram.rag 1298
 
1299
 
6511 kshitij.so 1300
def add_tag (displayName, catalogId):
1301
    ent_tag = None
1302
    if catalogId is None or (not is_valid_catalog_id(catalogId)):            
1303
        raise InventoryServiceException(id, "Invalid CatalogId")
1304
    else:
1305
        ent_tag = EntityTag()
1306
        ent_tag.entityId = catalogId
1307
    if displayName is None:
1308
        raise InventoryServiceException(id, "Tag should not be empty")
1309
    else: 
1310
        ent_tag.tag = displayName
1311
    session.commit()
1312
    return True
1313
 
1314
def get_all_tags ():
1315
    return [tuple[0] for tuple in session.query(EntityTag.tag).distinct().all()]
1316
 
1317
def get_all_entities_by_tag_name(displayName):
1318
    return [tuple[0] for tuple in session.query(EntityTag.entityId).filter_by(tag=displayName).all()]
1319
 
1320
def delete_tag(displayName):
1321
    session.query(EntityTag.entityId).filter_by(tag=displayName).delete()
1322
    session.commit()
1323
    return True
6518 kshitij.so 1324
 
1325
def delete_entity_tag(displayName, catalogId):
1326
    session.query(EntityTag.tag).filter_by(tag=displayName,entityId=catalogId).delete()
1327
    session.commit()
6805 anupam.sin 1328
    return True
1329
 
1330
def get_insurance_amount(itemId, insurerId, quantity):
1331
    itemInsurerMapping = ItemInsurerMapping.query.filter(ItemInsurerMapping.itemId == itemId).filter(ItemInsurerMapping.insurerId == insurerId).first()
1332
    if not itemInsurerMapping:
1333
        return 0
1334
    insuranceAmount = 0.0
1335
    if itemInsurerMapping.premiumType == PremiumType._NAMES_TO_VALUES.get("PERCENT"):
1336
        item = Item.get_by(id = itemId)
1337
        insuranceAmount = item.sellingPrice * (itemInsurerMapping.premiumAmount/100) * quantity
1338
    else :
1339
        insuranceAmount = itemInsurerMapping.premiumAmount * quantity
1340
 
1341
    return insuranceAmount
1342
 
1343
def get_insurer(insurerId):
1344
    return Insurer.get_by(id = insurerId)