Subversion Repositories SmartDukaan

Rev

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