Subversion Repositories SmartDukaan

Rev

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