Subversion Repositories SmartDukaan

Rev

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

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