Subversion Repositories SmartDukaan

Rev

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