| Line 3... |
Line 3... |
| 3 |
|
3 |
|
| 4 |
@author: ashish
|
4 |
@author: ashish
|
| 5 |
'''
|
5 |
'''
|
| 6 |
from elixir import *
|
6 |
from elixir import *
|
| 7 |
from functools import partial
|
7 |
from functools import partial
|
| 8 |
from pydoc import Helper
|
8 |
from shop2020.clients.CatalogClient import CatalogClient
|
| 9 |
from shop2020.clients.HelperClient import HelperClient
|
9 |
from shop2020.clients.HelperClient import HelperClient
|
| 10 |
from shop2020.clients.TransactionClient import TransactionClient
|
10 |
from shop2020.clients.InventoryClient import InventoryClient
|
| 11 |
from shop2020.config.client.ConfigClient import ConfigClient
|
11 |
from shop2020.config.client.ConfigClient import ConfigClient
|
| 12 |
from shop2020.model.v1.catalog.impl import DataService
|
12 |
from shop2020.model.v1.catalog.impl import DataService
|
| 13 |
from shop2020.model.v1.catalog.impl.CategoryManager import CategoryManager
|
13 |
from shop2020.model.v1.catalog.impl.CategoryManager import CategoryManager
|
| 14 |
from shop2020.model.v1.catalog.impl.Convertors import to_t_item, to_t_source
|
14 |
from shop2020.model.v1.catalog.impl.Convertors import to_t_item, to_t_source
|
| 15 |
from shop2020.model.v1.catalog.impl.DataService import Item, Warehouse, \
|
15 |
from shop2020.model.v1.catalog.impl.DataService import Item, ItemChangeLog, \
|
| 16 |
ItemInventoryHistory, CurrentInventorySnapshot, ItemChangeLog, Category, \
|
- |
|
| 17 |
EntityIDGenerator, VendorItemPricing, VendorItemMapping, Vendor, SimilarItems, \
|
16 |
Category, EntityIDGenerator, SimilarItems, ProductNotification, Source, \
|
| 18 |
ProductNotification, Source, SourceItemPricing, AuthorizationLog, \
|
- |
|
| 19 |
MissedInventoryUpdate, BadInventorySnapshot, VendorItemProcurementDelay, \
|
- |
|
| 20 |
VendorHolidays, ItemAvailabilityCache, VoucherItemMapping
|
17 |
SourceItemPricing, AuthorizationLog, VoucherItemMapping
|
| 21 |
from shop2020.thriftpy.model.v1.catalog.ttypes import InventoryServiceException, \
|
18 |
from shop2020.thriftpy.model.v1.catalog.ttypes import status, ItemShippingInfo, \
|
| 22 |
status, ItemShippingInfo, HolidayType, InventoryType, WarehouseType, ItemType
|
19 |
ItemType
|
| 23 |
from shop2020.thriftpy.model.v1.order.ttypes import AlertType
|
20 |
from shop2020.thriftpy.model.v1.inventory.ttypes import \
|
| - |
|
21 |
InventoryServiceException
|
| 24 |
from shop2020.utils import EmailAttachmentSender
|
22 |
from shop2020.utils import EmailAttachmentSender
|
| 25 |
from shop2020.utils.EmailAttachmentSender import mail
|
23 |
from shop2020.utils.EmailAttachmentSender import mail
|
| 26 |
from shop2020.utils.Utils import to_py_date, log_risky_flag
|
24 |
from shop2020.utils.Utils import to_py_date, log_risky_flag
|
| 27 |
from sqlalchemy import desc, asc
|
25 |
from sqlalchemy import desc, asc
|
| 28 |
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
|
- |
|
| 29 |
from sqlalchemy.sql.expression import and_, or_, distinct, func
|
26 |
from sqlalchemy.sql.expression import or_, distinct, func
|
| 30 |
from string import Template
|
27 |
from string import Template
|
| 31 |
from urllib2 import HTTPBasicAuthHandler
|
- |
|
| 32 |
import calendar
|
- |
|
| 33 |
import datetime
|
28 |
import datetime
|
| 34 |
import sys
|
29 |
import sys
|
| 35 |
import threading
|
30 |
import threading
|
| 36 |
import urllib2
|
31 |
import urllib2
|
| 37 |
from shop2020.clients.CatalogClient import CatalogClient
|
- |
|
| 38 |
|
32 |
|
| 39 |
to_addresses = ["cnc.center@shop2020.in", "ashutosh.saxena@shop2020.in"]
|
33 |
to_addresses = ["cnc.center@shop2020.in", "ashutosh.saxena@shop2020.in"]
|
| 40 |
from_user = "cnc.center@shop2020.in"
|
34 |
from_user = "cnc.center@shop2020.in"
|
| 41 |
from_pwd = "5h0p2o2o"
|
35 |
from_pwd = "5h0p2o2o"
|
| 42 |
skippedItems = { 175 : [27, 2160, 2175, 2163, 2158, 7128, 26, 2154],
|
36 |
skippedItems = { 175 : [27, 2160, 2175, 2163, 2158, 7128, 26, 2154],
|
| Line 91... |
Line 85... |
| 91 |
def is_active(item_id):
|
85 |
def is_active(item_id):
|
| 92 |
t_item_shipping_info = ItemShippingInfo()
|
86 |
t_item_shipping_info = ItemShippingInfo()
|
| 93 |
try:
|
87 |
try:
|
| 94 |
item = get_item(item_id)
|
88 |
item = get_item(item_id)
|
| 95 |
t_item_shipping_info.isRisky = item.risky
|
89 |
t_item_shipping_info.isRisky = item.risky
|
| - |
|
90 |
client = InventoryClient().get_client()
|
| 96 |
warehouse_id = get_item_availability_for_location(item.id)[0]
|
91 |
itemInfo = client.getItemAvailabilityAtLocation(item.id)
|
| - |
|
92 |
warehouse_id = itemInfo[0]
|
| 97 |
if item.risky and item.status == status.ACTIVE:
|
93 |
if item.risky and item.status == status.ACTIVE:
|
| - |
|
94 |
availability = client.getItemAvailibilityAtWarehouse(warehouse_id, item_id)
|
| 98 |
availability = 0
|
95 |
if availability <= 0:
|
| 99 |
currentInventorySnapshot = CurrentInventorySnapshot.query.filter_by(item_id = item.id, warehouse_id = warehouse_id).all()
|
- |
|
| 100 |
if not currentInventorySnapshot or currentInventorySnapshot[0].availability <= currentInventorySnapshot[0].reserved:
|
- |
|
| 101 |
add_status_change_log(item, status.PAUSED_BY_RISK)
|
96 |
add_status_change_log(item, status.PAUSED_BY_RISK)
|
| 102 |
item.status = status.PAUSED_BY_RISK
|
97 |
item.status = status.PAUSED_BY_RISK
|
| 103 |
item.status_description = "This item is currently out of stock"
|
98 |
item.status_description = "This item is currently out of stock"
|
| 104 |
session.commit()
|
99 |
session.commit()
|
| 105 |
__send_mail_for_oos_item(item)
|
100 |
__send_mail_for_oos_item(item)
|
| 106 |
#This will clear cache from tomcat
|
101 |
#This will clear cache from tomcat
|
| 107 |
__clear_homepage_cache()
|
102 |
__clear_homepage_cache()
|
| 108 |
else:
|
- |
|
| 109 |
availability = currentInventorySnapshot[0].availability - currentInventorySnapshot[0].reserved
|
- |
|
| 110 |
else:
|
103 |
else:
|
| 111 |
availability = item.get_total_inventory
|
104 |
availability = itemInfo[4]
|
| 112 |
t_item_shipping_info.isActive = (item.status == status.ACTIVE)
|
105 |
t_item_shipping_info.isActive = (item.status == status.ACTIVE)
|
| 113 |
t_item_shipping_info.quantity = availability
|
106 |
t_item_shipping_info.quantity = availability
|
| 114 |
except InventoryServiceException:
|
107 |
except InventoryServiceException:
|
| 115 |
print "[ERROR] Unexpected error:", sys.exc_info()[0]
|
108 |
print "[ERROR] Unexpected error:", sys.exc_info()[0]
|
| 116 |
return t_item_shipping_info
|
109 |
return t_item_shipping_info
|
| 117 |
|
110 |
|
| 118 |
def get_item_status_description(itemId):
|
111 |
def get_item_status_description(itemId):
|
| 119 |
item = get_item(itemId)
|
112 |
item = get_item(itemId)
|
| 120 |
return item.status_description
|
113 |
return item.status_description
|
| 121 |
|
- |
|
| 122 |
def get_Warehouse(warehouse_id):
|
- |
|
| 123 |
return Warehouse.get_by(id=warehouse_id)
|
- |
|
| 124 |
|
- |
|
| 125 |
def get_Vendor(vendorId):
|
- |
|
| 126 |
return Vendor.get_by(id=vendorId)
|
- |
|
| 127 |
|
- |
|
| 128 |
def get_all_warehouses_by_status(status):
|
- |
|
| 129 |
return Warehouse.query.all()
|
- |
|
| 130 |
|
- |
|
| 131 |
def get_all_warehouses_for_item(item_id):
|
- |
|
| 132 |
item = get_item(item_id)
|
- |
|
| 133 |
if not item:
|
- |
|
| 134 |
raise InventoryServiceException(108, "Some unforeseen error while obtaining item")
|
- |
|
| 135 |
return item.get_all_warehouses
|
- |
|
| 136 |
|
- |
|
| 137 |
def get_all_items_for_warehouse(warehouse_id):
|
- |
|
| 138 |
warehouse = get_Warehouse(warehouse_id)
|
- |
|
| 139 |
if not warehouse:
|
- |
|
| 140 |
raise InventoryServiceException(108, "bad warehouse")
|
- |
|
| 141 |
return warehouse.all_items
|
- |
|
| 142 |
|
- |
|
| 143 |
def add_warehouse(warehouse):
|
- |
|
| 144 |
if not warehouse:
|
- |
|
| 145 |
raise InventoryServiceException(108, "Bad warehouse")
|
- |
|
| 146 |
if get_Warehouse(warehouse.id):
|
- |
|
| 147 |
#warehouse is already present.
|
- |
|
| 148 |
raise InventoryServiceException(101, "Warehouse already present")
|
- |
|
| 149 |
|
- |
|
| 150 |
ds_warehouse = Warehouse()
|
- |
|
| 151 |
ds_warehouse.location = warehouse.location
|
- |
|
| 152 |
ds_warehouse.status = status.ACTIVE
|
- |
|
| 153 |
ds_warehouse.addedOn = datetime.datetime.now()
|
- |
|
| 154 |
ds_warehouse.lastCheckedOn = datetime.datetime.now()
|
- |
|
| 155 |
ds_warehouse.tinNumber = warehouse.tinNumber
|
- |
|
| 156 |
ds_warehouse.pincode = warehouse.pincode
|
- |
|
| 157 |
ds_warehouse.billingType = warehouse.billingType
|
- |
|
| 158 |
ds_warehouse.billingWarehouseId = warehouse.billingWarehouseId
|
- |
|
| 159 |
ds_warehouse.displayName = warehouse.displayName
|
- |
|
| 160 |
ds_warehouse.inventoryType = InventoryType._VALUES_TO_NAMES[warehouse.inventoryType]
|
- |
|
| 161 |
ds_warehouse.isAvailabilityMonitored = warehouse.isAvailabilityMonitored
|
- |
|
| 162 |
ds_warehouse.logisticsLocation = warehouse.logisticsLocation
|
- |
|
| 163 |
ds_warehouse.shippingWarehouseId = warehouse.shippingWarehouseId
|
- |
|
| 164 |
ds_warehouse.transferDelayInHours = warehouse.transferDelayInHours
|
- |
|
| 165 |
ds_warehouse.vendor = get_Vendor(warehouse.vendor.id)
|
- |
|
| 166 |
ds_warehouse.warehouseType = WarehouseType._VALUES_TO_NAMES[warehouse.warehouseType]
|
- |
|
| 167 |
if warehouse.vendorString:
|
- |
|
| 168 |
ds_warehouse.vendorString = warehouse.vendorString
|
- |
|
| 169 |
session.commit()
|
- |
|
| 170 |
return ds_warehouse.id
|
- |
|
| 171 |
|
114 |
|
| 172 |
def update_item(item):
|
115 |
def update_item(item):
|
| 173 |
if not item:
|
116 |
if not item:
|
| 174 |
raise InventoryServiceException(108, "Bad item in request")
|
117 |
raise InventoryServiceException(108, "Bad item in request")
|
| 175 |
|
118 |
|
| Line 258... |
Line 201... |
| 258 |
if item.expectedDelay is not None:
|
201 |
if item.expectedDelay is not None:
|
| 259 |
ds_item.expectedDelay = item.expectedDelay
|
202 |
ds_item.expectedDelay = item.expectedDelay
|
| 260 |
|
203 |
|
| 261 |
if item.preferredVendor:
|
204 |
if item.preferredVendor:
|
| 262 |
if item.preferredVendor != ds_item.preferredVendor:
|
205 |
if item.preferredVendor != ds_item.preferredVendor:
|
| - |
|
206 |
inventoryClient = InventoryClient().get_client()
|
| 263 |
newPreferredVendorName = get_Vendor(item.preferredVendor).name
|
207 |
newPreferredVendorName = inventoryClient.getVendor(item.preferredVendor).name
|
| 264 |
oldPreferredVendorName = 'None'
|
208 |
oldPreferredVendorName = 'None'
|
| 265 |
if ds_item.preferredVendor:
|
209 |
if ds_item.preferredVendor:
|
| 266 |
oldPreferredVendorName = get_Vendor(ds_item.preferredVendor).name
|
210 |
oldPreferredVendorName = inventoryClient.getVendor(ds_item.preferredVendor).name
|
| 267 |
message += "Preferred vendor is changed from '{0}' to '{1}'.\n".format(oldPreferredVendorName, newPreferredVendorName)
|
211 |
message += "Preferred vendor is changed from '{0}' to '{1}'.\n".format(oldPreferredVendorName, newPreferredVendorName)
|
| 268 |
ds_item.preferredVendor = item.preferredVendor
|
212 |
ds_item.preferredVendor = item.preferredVendor
|
| 269 |
|
213 |
|
| 270 |
if item.isWarehousePreferenceSticky != ds_item.isWarehousePreferenceSticky:
|
214 |
if item.isWarehousePreferenceSticky != ds_item.isWarehousePreferenceSticky:
|
| 271 |
flag = "ON" if item.isWarehousePreferenceSticky else "OFF"
|
215 |
flag = "ON" if item.isWarehousePreferenceSticky else "OFF"
|
| Line 349... |
Line 293... |
| 349 |
ds_item.expectedDelay = 0
|
293 |
ds_item.expectedDelay = 0
|
| 350 |
|
294 |
|
| 351 |
preferredVendorName = "None"
|
295 |
preferredVendorName = "None"
|
| 352 |
if item.preferredVendor:
|
296 |
if item.preferredVendor:
|
| 353 |
ds_item.preferredVendor = item.preferredVendor
|
297 |
ds_item.preferredVendor = item.preferredVendor
|
| - |
|
298 |
inventoryClient = InventoryClient().get_client()
|
| 354 |
preferredVendorName = get_Vendor(item.preferredVendor).name
|
299 |
preferredVendorName = inventoryClient.getVendor(item.preferredVendor).name
|
| 355 |
|
300 |
|
| 356 |
if item.catalogItemId:
|
301 |
if item.catalogItemId:
|
| 357 |
catalog_client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
|
302 |
catalog_client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
|
| 358 |
master_items = catalog_client.getItemsByCatalogId(item.catalogItemId)
|
303 |
master_items = catalog_client.getItemsByCatalogId(item.catalogItemId)
|
| 359 |
itemStatus = status.IN_PROCESS
|
304 |
itemStatus = status.IN_PROCESS
|
| Line 392... |
Line 337... |
| 392 |
subject = "New item is added. Id is {0}".format(str(ds_item.id))
|
337 |
subject = "New item is added. Id is {0}".format(str(ds_item.id))
|
| 393 |
message = "Category : {6}, Brand : {0}, Model : {1}, Model Number : {2}\nColor : {3}, Selling Price : {4}, Mrp : {5}, \nPromotion Text : {7}, Preferred Vendor: {8}".format(item.brand, item.modelNumber, item.modelName, item.color, item.sellingPrice, item.mrp, item.category, item.bestDealText, preferredVendorName)
|
338 |
message = "Category : {6}, Brand : {0}, Model : {1}, Model Number : {2}\nColor : {3}, Selling Price : {4}, Mrp : {5}, \nPromotion Text : {7}, Preferred Vendor: {8}".format(item.brand, item.modelNumber, item.modelName, item.color, item.sellingPrice, item.mrp, item.category, item.bestDealText, preferredVendorName)
|
| 394 |
__send_mail(subject, message)
|
339 |
__send_mail(subject, message)
|
| 395 |
return ds_item.id
|
340 |
return ds_item.id
|
| 396 |
|
341 |
|
| 397 |
def update_inventory_history(warehouse_id, timestamp, availability):
|
- |
|
| 398 |
warehouse = get_Warehouse(warehouse_id)
|
- |
|
| 399 |
if not warehouse:
|
- |
|
| 400 |
raise InventoryServiceException(107, "Warehouse? Where?")
|
- |
|
| 401 |
vendor = warehouse.vendor
|
- |
|
| 402 |
time = datetime.datetime.now()
|
- |
|
| 403 |
for item_key, quantity in availability.iteritems():
|
- |
|
| 404 |
try:
|
- |
|
| 405 |
vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
|
- |
|
| 406 |
item = vendor_item_mapping.item
|
- |
|
| 407 |
except:
|
- |
|
| 408 |
continue
|
- |
|
| 409 |
try:
|
- |
|
| 410 |
item_inventory_history = ItemInventoryHistory()
|
- |
|
| 411 |
item_inventory_history.warehouse = warehouse
|
- |
|
| 412 |
item_inventory_history.item = item
|
- |
|
| 413 |
item_inventory_history.timestamp = time
|
- |
|
| 414 |
item_inventory_history.availability = quantity
|
- |
|
| 415 |
except:
|
- |
|
| 416 |
raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
|
- |
|
| 417 |
session.commit()
|
- |
|
| 418 |
|
- |
|
| 419 |
def update_inventory(warehouse_id, timestamp, availability):
|
- |
|
| 420 |
warehouse = get_Warehouse(warehouse_id)
|
- |
|
| 421 |
if not warehouse:
|
- |
|
| 422 |
raise InventoryServiceException(107, "Warehouse? Where?")
|
- |
|
| 423 |
|
- |
|
| 424 |
time = datetime.datetime.now()
|
- |
|
| 425 |
warehouse.lastCheckedOn = time
|
- |
|
| 426 |
warehouse.vendorString = timestamp
|
- |
|
| 427 |
vendor = warehouse.vendor
|
- |
|
| 428 |
session.commit()
|
- |
|
| 429 |
items = []
|
- |
|
| 430 |
for item_key, quantity in availability.iteritems():
|
- |
|
| 431 |
try:
|
- |
|
| 432 |
vendor_item_mapping = VendorItemMapping.query.filter_by(vendor=vendor, item_key=item_key).one();
|
- |
|
| 433 |
item = vendor_item_mapping.item
|
- |
|
| 434 |
items.append(item)
|
- |
|
| 435 |
except:
|
- |
|
| 436 |
print 'Skipping update for ' + item_key + ' quantity ' + str(quantity) + ' warehouse id: ' + str(warehouse_id)
|
- |
|
| 437 |
__send_mail_for_missing_key(item_key, quantity, warehouse_id)
|
- |
|
| 438 |
continue
|
- |
|
| 439 |
try:
|
- |
|
| 440 |
current_inventory_snapshot = CurrentInventorySnapshot.get_by(item=item, warehouse=warehouse)
|
- |
|
| 441 |
if not current_inventory_snapshot:
|
- |
|
| 442 |
current_inventory_snapshot = CurrentInventorySnapshot()
|
- |
|
| 443 |
current_inventory_snapshot.item = item
|
- |
|
| 444 |
current_inventory_snapshot.warehouse = warehouse
|
- |
|
| 445 |
current_inventory_snapshot.availability = 0
|
- |
|
| 446 |
current_inventory_snapshot.reserved = 0
|
- |
|
| 447 |
# added the difference in the current inventory
|
- |
|
| 448 |
current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
|
- |
|
| 449 |
try:
|
- |
|
| 450 |
if quantity > 0 and __get_item_reserved(item) > 0:
|
- |
|
| 451 |
cl = TransactionClient().get_client()
|
- |
|
| 452 |
#FIXME hardcoding for warehouse id
|
- |
|
| 453 |
cl.addAlert(AlertType.NEW_INVENTORY_ALERT, 5, "Inventory received for item " + item.brand + " " + item.model_name + " " + item.model_number + " " + item.color)
|
- |
|
| 454 |
except:
|
- |
|
| 455 |
print "Not able to raise alert for incoming inventory"
|
- |
|
| 456 |
if current_inventory_snapshot.availability < 0:
|
- |
|
| 457 |
__send_alert_for_negative_availability(item, current_inventory_snapshot.availability, warehouse)
|
- |
|
| 458 |
except:
|
- |
|
| 459 |
raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
|
- |
|
| 460 |
session.commit()
|
- |
|
| 461 |
#**Update item availability cache**#
|
- |
|
| 462 |
for item in items:
|
- |
|
| 463 |
__update_item_availability_cache(item.id)
|
- |
|
| 464 |
check_risky_item(item)
|
- |
|
| 465 |
|
- |
|
| 466 |
def __send_alert_for_negative_reserved(item, reserved, warehouse):
|
- |
|
| 467 |
itemName = " ".join([str(item.id), str(item.brand), str(item.model_name), str(item.model_number), str(item.color)])
|
- |
|
| 468 |
EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', 'mandeep.dhir@shop2020.in', 'Negative reserved: ' + str(reserved) + ' for Item Id: ' + itemName + ' warehouse id: ' + str(warehouse.id), None)
|
- |
|
| 469 |
|
- |
|
| 470 |
def __send_alert_for_negative_availability(item, availability, warehouse):
|
- |
|
| 471 |
itemName = " ".join([str(item.id), str(item.brand), str(item.model_name), str(item.model_number), str(item.color)])
|
- |
|
| 472 |
# EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', 'mandeep.dhir@shop2020.in', 'Negative availability ' + str(availability) + ' for Item id: ' + itemName + ' warehouse id: ' + str(warehouse.id), None)
|
- |
|
| 473 |
|
- |
|
| 474 |
def __send_mail_for_missing_key(item_key, quantity, warehouse_id):
|
- |
|
| 475 |
missedInventoryUpdate = MissedInventoryUpdate.get_by(itemKey = item_key, warehouseId = warehouse_id)
|
- |
|
| 476 |
# One email per product key mismatch
|
- |
|
| 477 |
if not missedInventoryUpdate:
|
- |
|
| 478 |
EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', ['mandeep.dhir@shop2020.in', 'chaitnaya.vats@shop2020.in', 'asghar.bilgrami@shop2020.in'], 'Skipped inventory update for ' + item_key + ' quantity ' + str(quantity) + ' warehouse id: ' + str(warehouse_id), None)
|
- |
|
| 479 |
missedInventoryUpdate = MissedInventoryUpdate()
|
- |
|
| 480 |
missedInventoryUpdate.itemKey = item_key
|
- |
|
| 481 |
missedInventoryUpdate.quantity = quantity
|
- |
|
| 482 |
missedInventoryUpdate.isIgnored = 1
|
- |
|
| 483 |
missedInventoryUpdate.timestamp = datetime.datetime.now()
|
- |
|
| 484 |
missedInventoryUpdate.warehouseId = warehouse_id
|
- |
|
| 485 |
session.commit()
|
- |
|
| 486 |
else:
|
- |
|
| 487 |
missedInventoryUpdate.quantity += quantity
|
- |
|
| 488 |
session.commit()
|
- |
|
| 489 |
|
- |
|
| 490 |
def add_inventory(itemId, warehouseId, quantity):
|
- |
|
| 491 |
current_inventory_snapshot = CurrentInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
|
- |
|
| 492 |
if not current_inventory_snapshot:
|
- |
|
| 493 |
current_inventory_snapshot = CurrentInventorySnapshot()
|
- |
|
| 494 |
current_inventory_snapshot.item_id = itemId
|
- |
|
| 495 |
current_inventory_snapshot.warehouse_id = warehouseId
|
- |
|
| 496 |
current_inventory_snapshot.availability = 0
|
- |
|
| 497 |
current_inventory_snapshot.reserved = 0
|
- |
|
| 498 |
# added the difference in the current inventory
|
- |
|
| 499 |
current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
|
- |
|
| 500 |
session.commit()
|
- |
|
| 501 |
#**Update item availability cache**#
|
- |
|
| 502 |
__update_item_availability_cache(itemId)
|
- |
|
| 503 |
if current_inventory_snapshot.availability < 0:
|
- |
|
| 504 |
__send_alert_for_negative_availability(get_item(itemId), current_inventory_snapshot.availability, get_Warehouse(warehouseId))
|
- |
|
| 505 |
check_risky_item(get_item(itemId))
|
- |
|
| 506 |
|
- |
|
| 507 |
def add_bad_inventory(itemId, warehouseId, quantity):
|
- |
|
| 508 |
bad_inventory_snapshot = BadInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
|
- |
|
| 509 |
if not bad_inventory_snapshot:
|
- |
|
| 510 |
bad_inventory_snapshot = BadInventorySnapshot()
|
- |
|
| 511 |
bad_inventory_snapshot.item_id = itemId
|
- |
|
| 512 |
bad_inventory_snapshot.warehouse_id = warehouseId
|
- |
|
| 513 |
bad_inventory_snapshot.availability = 0
|
- |
|
| 514 |
# added the difference in the current inventory
|
- |
|
| 515 |
bad_inventory_snapshot.availability += quantity
|
- |
|
| 516 |
session.commit()
|
- |
|
| 517 |
if bad_inventory_snapshot.availability < 0:
|
- |
|
| 518 |
__send_alert_for_negative_availability(get_item(itemId), bad_inventory_snapshot.availability, get_Warehouse(warehouseId))
|
- |
|
| 519 |
|
- |
|
| 520 |
def get_item_inventory_by_item_id(item_id):
|
- |
|
| 521 |
return Item.get_by(id=item_id).currentInventory
|
- |
|
| 522 |
|
- |
|
| 523 |
def retire_warehouse(warehouse_id):
|
- |
|
| 524 |
if not warehouse_id:
|
- |
|
| 525 |
raise InventoryServiceException(101, "Bad warehouse id")
|
- |
|
| 526 |
warehouse = get_Warehouse(warehouse_id)
|
- |
|
| 527 |
if not warehouse:
|
- |
|
| 528 |
raise InventoryServiceException(108, "warehouse id not present")
|
- |
|
| 529 |
warehouse.status = status.DELETED;
|
- |
|
| 530 |
session.commit()
|
- |
|
| 531 |
|
- |
|
| 532 |
def retire_item(item_id):
|
342 |
def retire_item(item_id):
|
| 533 |
if not item_id:
|
343 |
if not item_id:
|
| 534 |
raise InventoryServiceException(101, "bad item id")
|
344 |
raise InventoryServiceException(101, "bad item id")
|
| 535 |
item = get_item(item_id)
|
345 |
item = get_item(item_id)
|
| 536 |
if not item:
|
346 |
if not item:
|
| Line 599... |
Line 409... |
| 599 |
item.status_description = "This item is in process"
|
409 |
item.status_description = "This item is in process"
|
| 600 |
elif item.status == status.CONTENT_COMPLETE:
|
410 |
elif item.status == status.CONTENT_COMPLETE:
|
| 601 |
item.status_description = "This item is in process"
|
411 |
item.status_description = "This item is in process"
|
| 602 |
session.commit()
|
412 |
session.commit()
|
| 603 |
|
413 |
|
| 604 |
def get_item_availability_for_warehouse(warehouse_id, item_id):
|
- |
|
| 605 |
if not warehouse_id:
|
- |
|
| 606 |
raise InventoryServiceException(101, "bad warehouse_id")
|
- |
|
| 607 |
if not item_id:
|
414 |
def check_risky_item(item_id):
|
| 608 |
raise InventoryServiceException(101, "bad item_id")
|
- |
|
| 609 |
|
- |
|
| 610 |
warehouse = get_Warehouse(warehouse_id)
|
- |
|
| 611 |
if not warehouse:
|
- |
|
| 612 |
raise InventoryServiceException(108, "warehouse does not exist")
|
- |
|
| 613 |
item = get_item(item_id)
|
415 |
item = get_item(item_id)
|
| 614 |
|
- |
|
| 615 |
if not item:
|
- |
|
| 616 |
raise InventoryServiceException(108, "item does not exist")
|
- |
|
| 617 |
|
- |
|
| 618 |
query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id)
|
- |
|
| 619 |
query = query.filter_by(item_id = item.id)
|
- |
|
| 620 |
try:
|
- |
|
| 621 |
current_inventory_snapshot = query.one()
|
- |
|
| 622 |
return current_inventory_snapshot.availability - current_inventory_snapshot.reserved
|
- |
|
| 623 |
except:
|
- |
|
| 624 |
return 0
|
- |
|
| 625 |
"""
|
- |
|
| 626 |
current_inventory_snapshot = CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id == warehouse_id, CurrentInventorySnapshot.item_id == item_id).one()
|
- |
|
| 627 |
if not current_inventory_snapshot:
|
- |
|
| 628 |
return 0
|
- |
|
| 629 |
else:
|
- |
|
| 630 |
return current_inventory_snapshot.availability
|
- |
|
| 631 |
"""
|
- |
|
| 632 |
|
- |
|
| 633 |
def check_risky_item(item):
|
- |
|
| 634 |
if not item.risky:
|
416 |
if not item.risky:
|
| 635 |
return
|
417 |
return
|
| - |
|
418 |
client = InventoryClient().get_client()
|
| 636 |
warehouse_id = get_item_availability_for_location(item.id)[0]
|
419 |
itemInfo = client.getItemAvailabilityAtLocation(item.id)
|
| - |
|
420 |
warehouse_id = itemInfo[0]
|
| 637 |
currentInventorySnapshot = CurrentInventorySnapshot.query.filter_by(item_id = item.id, warehouse_id = warehouse_id).all()
|
421 |
availability = client.getItemAvailibilityAtWarehouse(warehouse_id, item.id)
|
| 638 |
if not currentInventorySnapshot or currentInventorySnapshot[0].availability <= currentInventorySnapshot[0].reserved:
|
422 |
if availability <= 0:
|
| 639 |
if item.status == status.ACTIVE:
|
423 |
if item.status == status.ACTIVE:
|
| 640 |
change_item_status(item.id, status.PAUSED_BY_RISK)
|
424 |
change_item_status(item.id, status.PAUSED_BY_RISK)
|
| 641 |
__send_mail_for_oos_item(item)
|
425 |
__send_mail_for_oos_item(item)
|
| 642 |
else:
|
426 |
else:
|
| 643 |
if item.status == status.PAUSED_BY_RISK:
|
427 |
if item.status == status.PAUSED_BY_RISK:
|
| 644 |
change_item_status(item.id, status.ACTIVE)
|
428 |
change_item_status(item.id, status.ACTIVE)
|
| 645 |
session.commit()
|
429 |
session.commit()
|
| 646 |
|
- |
|
| 647 |
'''
|
- |
|
| 648 |
This method returns quantity of a particular item across all warehouses whose ids is provided
|
- |
|
| 649 |
if warehouse_ids is null it checks for inventory in all warehouses.
|
- |
|
| 650 |
'''
|
- |
|
| 651 |
def __get_item_availability(item, warehouse_ids):
|
- |
|
| 652 |
if warehouse_ids is None:
|
- |
|
| 653 |
all_inventory = CurrentInventorySnapshot.query.filter_by(item = item).all()
|
- |
|
| 654 |
availability = 0
|
- |
|
| 655 |
reserved = 0
|
- |
|
| 656 |
for currInv in all_inventory:
|
- |
|
| 657 |
availability = availability + currInv.availability
|
- |
|
| 658 |
reserved = reserved + currInv.reserved
|
- |
|
| 659 |
return availability - reserved
|
- |
|
| 660 |
else:
|
- |
|
| 661 |
total_availability = 0
|
- |
|
| 662 |
for current_inventory_snapshot in CurrentInventorySnapshot.query.filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).filter_by(item_id = item.id).all():
|
- |
|
| 663 |
total_availability += current_inventory_snapshot.availability - current_inventory_snapshot.reserved
|
- |
|
| 664 |
return total_availability
|
- |
|
| 665 |
|
- |
|
| 666 |
def __get_item_reserved(item):
|
- |
|
| 667 |
all_inventory = CurrentInventorySnapshot.query.filter_by(item = item).all()
|
- |
|
| 668 |
reserved = 0
|
- |
|
| 669 |
for currInv in all_inventory:
|
- |
|
| 670 |
reserved = reserved + currInv.reserved
|
- |
|
| 671 |
return reserved
|
- |
|
| 672 |
|
- |
|
| 673 |
def reserve_item_in_warehouse(item_id, warehouse_id, quantity):
|
- |
|
| 674 |
if not warehouse_id:
|
- |
|
| 675 |
raise InventoryServiceException(101, "bad warehouse_id")
|
- |
|
| 676 |
item = get_item(item_id)
|
- |
|
| 677 |
if not item:
|
- |
|
| 678 |
raise InventoryServiceException(101, "bad item_id")
|
- |
|
| 679 |
|
- |
|
| 680 |
query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
|
- |
|
| 681 |
try:
|
- |
|
| 682 |
current_inventory_snapshot = query.one()
|
- |
|
| 683 |
except:
|
- |
|
| 684 |
current_inventory_snapshot = CurrentInventorySnapshot()
|
- |
|
| 685 |
current_inventory_snapshot.warehouse_id = warehouse_id
|
- |
|
| 686 |
current_inventory_snapshot.item_id = item_id
|
- |
|
| 687 |
current_inventory_snapshot.availability = 0
|
- |
|
| 688 |
current_inventory_snapshot.reserved = 0
|
- |
|
| 689 |
|
- |
|
| 690 |
current_inventory_snapshot.reserved = current_inventory_snapshot.reserved + quantity
|
- |
|
| 691 |
session.commit()
|
- |
|
| 692 |
#**Update item availability cache**#
|
- |
|
| 693 |
__update_item_availability_cache(item_id)
|
- |
|
| 694 |
check_risky_item(item)
|
- |
|
| 695 |
return True
|
- |
|
| 696 |
|
- |
|
| 697 |
def reduce_reservation_count(item_id, warehouse_id, quantity):
|
- |
|
| 698 |
if not warehouse_id:
|
- |
|
| 699 |
raise InventoryServiceException(101, "bad warehouse_id")
|
- |
|
| 700 |
item = get_item(item_id)
|
- |
|
| 701 |
if not item:
|
- |
|
| 702 |
raise InventoryServiceException(101, "bad item_id")
|
- |
|
| 703 |
|
- |
|
| 704 |
query = CurrentInventorySnapshot.query.filter_by(warehouse_id = warehouse_id, item_id = item_id)
|
- |
|
| 705 |
try:
|
- |
|
| 706 |
current_inventory_snapshot = query.one()
|
- |
|
| 707 |
current_inventory_snapshot.reserved = current_inventory_snapshot.reserved - quantity
|
- |
|
| 708 |
session.commit()
|
- |
|
| 709 |
#**Update item availability cache**#
|
- |
|
| 710 |
__update_item_availability_cache(item_id)
|
- |
|
| 711 |
check_risky_item(item)
|
- |
|
| 712 |
if current_inventory_snapshot.reserved < 0:
|
- |
|
| 713 |
__send_alert_for_negative_reserved(get_item(item_id), current_inventory_snapshot.reserved, get_Warehouse(warehouse_id))
|
- |
|
| 714 |
return True
|
- |
|
| 715 |
except:
|
- |
|
| 716 |
print "Unexpected error:", sys.exc_info()[0]
|
- |
|
| 717 |
return False
|
- |
|
| 718 |
|
430 |
|
| 719 |
def mark_item_as_content_complete(entity_id, category, brand, modelName, modelNumber):
|
431 |
def mark_item_as_content_complete(entity_id, category, brand, modelName, modelNumber):
|
| 720 |
'''
|
432 |
'''
|
| 721 |
Get all the items for this entityID and update category, brand, modelName and modelNumber for all.
|
433 |
Get all the items for this entityID and update category, brand, modelName and modelNumber for all.
|
| 722 |
Update Status for only IN_PROCESS items to CONTENT_COMPLETE
|
434 |
Update Status for only IN_PROCESS items to CONTENT_COMPLETE
|
| Line 742... |
Line 454... |
| 742 |
item.model_number = modelNumber
|
454 |
item.model_number = modelNumber
|
| 743 |
item.updatedOn = current_timestamp
|
455 |
item.updatedOn = current_timestamp
|
| 744 |
session.commit()
|
456 |
session.commit()
|
| 745 |
return True
|
457 |
return True
|
| 746 |
|
458 |
|
| 747 |
def get_item_availability_for_location(item_id):
|
- |
|
| 748 |
item_availability = ItemAvailabilityCache.get_by(itemId=item_id)
|
- |
|
| 749 |
if item_availability:
|
- |
|
| 750 |
return [item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice]
|
- |
|
| 751 |
else:
|
- |
|
| 752 |
__update_item_availability_cache(item_id)
|
- |
|
| 753 |
return get_item_availability_for_location(item_id)
|
- |
|
| 754 |
|
- |
|
| 755 |
def clear_item_availability_cache():
|
- |
|
| 756 |
ItemAvailabilityCache.query.delete()
|
- |
|
| 757 |
session.commit()
|
- |
|
| 758 |
|
- |
|
| 759 |
def __update_item_availability_cache(item_id):
|
- |
|
| 760 |
"""
|
- |
|
| 761 |
Determines the warehouse that should be used to fulfil an order for the given item.
|
- |
|
| 762 |
Algorithm explained at https://sites.google.com/a/shop2020.in/virtual-w-h-and-inventory/technical-details
|
- |
|
| 763 |
|
- |
|
| 764 |
It will be ensured that every item has either a preferred vendor specified or at least for one vendor its transfer price should be defined.
|
- |
|
| 765 |
This is needed to associate an item with at least one vendor so that in default case when its available no where, we know from where to procure it.
|
- |
|
| 766 |
|
- |
|
| 767 |
if item available at any OUR-GOOD warehouse
|
- |
|
| 768 |
// OUR-GOOD warehouses have inventory risk; So, we empty them first!
|
- |
|
| 769 |
// We can start with minimum transfer price criterion but down the line we can also bring in Inventory age
|
- |
|
| 770 |
assign OUR-GOOD warehouse with minimum transfer price
|
- |
|
| 771 |
else
|
- |
|
| 772 |
if Preferred vendor is specified and marked Sticky
|
- |
|
| 773 |
// Always purchase from Preferred if its marked sticky
|
- |
|
| 774 |
assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
|
- |
|
| 775 |
else
|
- |
|
| 776 |
if item available in a THIRDPARTY GOOD/VIRTUAL warehouse
|
- |
|
| 777 |
assign THIRDPARTY GOOD/VIRTUAL warehouse where item is available with minimal transfer delay followed by minimum transfer price
|
- |
|
| 778 |
else
|
- |
|
| 779 |
// Item not available at any warehouse, OURS or THIRDPARTY
|
- |
|
| 780 |
If Preferred vendor is specified
|
- |
|
| 781 |
assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
|
- |
|
| 782 |
else
|
- |
|
| 783 |
assign THIRDPARTY GOOD/VIRTUAL warehouse with minimum transfer price
|
- |
|
| 784 |
|
- |
|
| 785 |
Returns an ordered list of size 4 with following elements in the given order:
|
- |
|
| 786 |
1. Logistics location of the warehouse which was finally picked up to ship the order.
|
- |
|
| 787 |
2. Expected delay added by the category manager.
|
- |
|
| 788 |
3. Id of the warehouse which was finally picked up.
|
- |
|
| 789 |
|
- |
|
| 790 |
Parameters:
|
- |
|
| 791 |
- itemId
|
- |
|
| 792 |
"""
|
- |
|
| 793 |
item = Item.get_by(id=item_id)
|
- |
|
| 794 |
item_pricing = {}
|
- |
|
| 795 |
for vendorItemPricing in VendorItemPricing.query.filter_by(item=item).all():
|
- |
|
| 796 |
item_pricing[vendorItemPricing.vendor_id] = vendorItemPricing
|
- |
|
| 797 |
|
- |
|
| 798 |
warehouses = {}
|
- |
|
| 799 |
ourGoodWarehouses = {}
|
- |
|
| 800 |
thirdpartyWarehouses = {}
|
- |
|
| 801 |
preferredThirdpartyWarehouses = {}
|
- |
|
| 802 |
for warehouse in Warehouse.query.all():
|
- |
|
| 803 |
if (warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.BAD]):
|
- |
|
| 804 |
continue
|
- |
|
| 805 |
warehouses[warehouse.id] = warehouse
|
- |
|
| 806 |
if warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.OURS]:
|
- |
|
| 807 |
if warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
|
- |
|
| 808 |
ourGoodWarehouses[warehouse.id] = warehouse
|
- |
|
| 809 |
else:
|
- |
|
| 810 |
thirdpartyWarehouses[warehouse.id] = warehouse
|
- |
|
| 811 |
if item.preferredVendor == warehouse.vendor_id and warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
|
- |
|
| 812 |
preferredThirdpartyWarehouses[warehouse.id] = warehouse
|
- |
|
| 813 |
|
- |
|
| 814 |
warehouse_retid = -1
|
- |
|
| 815 |
total_availability = 0
|
- |
|
| 816 |
|
- |
|
| 817 |
[warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(ourGoodWarehouses, item, item_pricing, False)
|
- |
|
| 818 |
if warehouse_retid == -1:
|
- |
|
| 819 |
if item.preferredVendor and item.isWarehousePreferenceSticky:
|
- |
|
| 820 |
[warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(preferredThirdpartyWarehouses, item, item_pricing)
|
- |
|
| 821 |
if warehouse_retid == -1:
|
- |
|
| 822 |
warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
|
- |
|
| 823 |
else:
|
- |
|
| 824 |
[warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(thirdpartyWarehouses, item, item_pricing)
|
- |
|
| 825 |
if warehouse_retid == -1:
|
- |
|
| 826 |
if item.preferredVendor:
|
- |
|
| 827 |
warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
|
- |
|
| 828 |
else:
|
- |
|
| 829 |
[warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(thirdpartyWarehouses, item, item_pricing, True)
|
- |
|
| 830 |
|
- |
|
| 831 |
warehouse = warehouses[warehouse_retid]
|
- |
|
| 832 |
billingWarehouseId = warehouse.billingWarehouseId
|
- |
|
| 833 |
|
- |
|
| 834 |
# Fetching billing warehouse of a Good billable warehouse corresponding to the virtual one
|
- |
|
| 835 |
if not warehouse.billingWarehouseId:
|
- |
|
| 836 |
for w in Warehouse.query.filter_by(vendor_id = warehouse.vendor_id, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]).all():
|
- |
|
| 837 |
if w.billingWarehouseId:
|
- |
|
| 838 |
billingWarehouseId = w.billingWarehouseId
|
- |
|
| 839 |
break
|
- |
|
| 840 |
|
- |
|
| 841 |
expectedDelay = item.expectedDelay
|
- |
|
| 842 |
if expectedDelay is None:
|
- |
|
| 843 |
print 'expectedDelay field for this item was Null. Resetting it to 0'
|
- |
|
| 844 |
expectedDelay = 0
|
- |
|
| 845 |
else:
|
- |
|
| 846 |
expectedDelay = int(item.expectedDelay)
|
- |
|
| 847 |
|
- |
|
| 848 |
if total_availability <= 0:
|
- |
|
| 849 |
expectedDelay = expectedDelay + __get_expected_procurement_delay(item)
|
- |
|
| 850 |
expectedDelay = expectedDelay + __get_vendor_holiday_delay(item, expectedDelay)
|
- |
|
| 851 |
else:
|
- |
|
| 852 |
if warehouse.transferDelayInHours:
|
- |
|
| 853 |
expectedDelay = expectedDelay + warehouse.transferDelayInHours / 24
|
- |
|
| 854 |
|
- |
|
| 855 |
item_availability_cache = ItemAvailabilityCache.get_by(itemId=item_id)
|
- |
|
| 856 |
if item_availability_cache is None:
|
- |
|
| 857 |
item_availability_cache = ItemAvailabilityCache()
|
- |
|
| 858 |
item_availability_cache.itemId = item_id
|
- |
|
| 859 |
item_availability_cache.warehouseId = int(warehouse_retid)
|
- |
|
| 860 |
item_availability_cache.expectedDelay = expectedDelay
|
- |
|
| 861 |
item_availability_cache.billingWarehouseId = billingWarehouseId
|
- |
|
| 862 |
item_availability_cache.sellingPrice = item.sellingPrice
|
- |
|
| 863 |
session.commit()
|
- |
|
| 864 |
|
- |
|
| 865 |
def __get_warehouse_with_min_transfer_price(warehouses, item, item_pricing, ignoreAvailability):
|
- |
|
| 866 |
warehouse_retid = -1
|
- |
|
| 867 |
minTransferPrice = None
|
- |
|
| 868 |
total_availability = 0
|
- |
|
| 869 |
warehousesWithAvailability = {}
|
- |
|
| 870 |
|
- |
|
| 871 |
if not ignoreAvailability:
|
- |
|
| 872 |
if item.currentInventory:
|
- |
|
| 873 |
for entry in item.currentInventory:
|
- |
|
| 874 |
if entry.availability > entry.reserved:
|
- |
|
| 875 |
warehousesWithAvailability[entry.warehouse_id] = entry
|
- |
|
| 876 |
|
- |
|
| 877 |
for warehouse in warehouses.values():
|
- |
|
| 878 |
if not ignoreAvailability:
|
- |
|
| 879 |
if warehousesWithAvailability.has_key(warehouse.id):
|
- |
|
| 880 |
entry = warehousesWithAvailability[warehouse.id]
|
- |
|
| 881 |
total_availability += entry.availability - entry.reserved
|
- |
|
| 882 |
else:
|
- |
|
| 883 |
continue
|
- |
|
| 884 |
|
- |
|
| 885 |
# Missing transfer price cases should not impact warehouse assignment
|
- |
|
| 886 |
transferPrice = None
|
- |
|
| 887 |
if item_pricing.has_key(warehouse.vendor_id):
|
- |
|
| 888 |
transferPrice = item_pricing[warehouse.vendor_id].transfer_price
|
- |
|
| 889 |
if minTransferPrice is None or (transferPrice and minTransferPrice > transferPrice):
|
- |
|
| 890 |
warehouse_retid = warehouse.id
|
- |
|
| 891 |
minTransferPrice = transferPrice
|
- |
|
| 892 |
|
- |
|
| 893 |
return [warehouse_retid, total_availability]
|
- |
|
| 894 |
|
- |
|
| 895 |
def __get_warehouse_with_min_transfer_delay(warehouses, item, item_pricing):
|
- |
|
| 896 |
minTransferDelay = None
|
- |
|
| 897 |
minTransferDelayWarehouses = {}
|
- |
|
| 898 |
total_availability = 0
|
- |
|
| 899 |
|
- |
|
| 900 |
if item.currentInventory:
|
- |
|
| 901 |
for entry in item.currentInventory:
|
- |
|
| 902 |
if warehouses.has_key(entry.warehouse_id):
|
- |
|
| 903 |
warehouse = warehouses[entry.warehouse_id]
|
- |
|
| 904 |
if entry.availability > entry.reserved:
|
- |
|
| 905 |
total_availability += entry.availability - entry.reserved
|
- |
|
| 906 |
transferDelay = warehouse.transferDelayInHours
|
- |
|
| 907 |
if minTransferDelay is None or minTransferDelay >= transferDelay:
|
- |
|
| 908 |
if minTransferDelay != transferDelay:
|
- |
|
| 909 |
minTransferDelayWarehouses = {}
|
- |
|
| 910 |
minTransferDelayWarehouses[warehouse.id] = warehouse
|
- |
|
| 911 |
minTransferDelay = transferDelay
|
- |
|
| 912 |
|
- |
|
| 913 |
return [__get_warehouse_with_min_transfer_price(minTransferDelayWarehouses, item, item_pricing, False)[0], total_availability]
|
- |
|
| 914 |
|
- |
|
| 915 |
def __get_warehouse_with_max_availability(warehouse_ids, item):
|
- |
|
| 916 |
warehouse_retid = -1
|
- |
|
| 917 |
max_availability = 0
|
- |
|
| 918 |
total_availability = 0
|
- |
|
| 919 |
|
- |
|
| 920 |
if item.currentInventory:
|
- |
|
| 921 |
for entry in item.currentInventory:
|
- |
|
| 922 |
if entry.warehouse_id in warehouse_ids:
|
- |
|
| 923 |
availability = entry.availability - entry.reserved
|
- |
|
| 924 |
if availability > max_availability:
|
- |
|
| 925 |
warehouse_retid = entry.warehouse_id
|
- |
|
| 926 |
max_availability = availability
|
- |
|
| 927 |
total_availability += availability
|
- |
|
| 928 |
|
- |
|
| 929 |
return [warehouse_retid, total_availability]
|
- |
|
| 930 |
|
- |
|
| 931 |
def __get_expected_procurement_delay(item):
|
- |
|
| 932 |
procurementDelay = 2
|
- |
|
| 933 |
try:
|
- |
|
| 934 |
if item.preferredVendor:
|
- |
|
| 935 |
delays = VendorItemProcurementDelay.query.filter_by(vendor_id = item.preferredVendor, item_id = item.id).all()
|
- |
|
| 936 |
else:
|
- |
|
| 937 |
delays = VendorItemProcurementDelay.query.filter_by(item_id = item.id).all()
|
- |
|
| 938 |
|
- |
|
| 939 |
procurementDelay= min([delay.procurementDelay for delay in delays])
|
- |
|
| 940 |
except Exception as e:
|
- |
|
| 941 |
print e
|
- |
|
| 942 |
return procurementDelay
|
- |
|
| 943 |
|
- |
|
| 944 |
def __get_vendor_holiday_delay(item, expectedDelay):
|
- |
|
| 945 |
holidayDelay = 0
|
- |
|
| 946 |
try:
|
- |
|
| 947 |
if item.preferredVendor:
|
- |
|
| 948 |
holidays = VendorHolidays.query.filter_by(vendor_id = item.preferredVendor).all()
|
- |
|
| 949 |
currentDate = datetime.date.today()
|
- |
|
| 950 |
expectedDate = currentDate + datetime.timedelta(days = expectedDelay)
|
- |
|
| 951 |
for holiday in holidays:
|
- |
|
| 952 |
if holiday.holidayType == HolidayType.WEEKLY and holiday.holidayValue != calendar.SUNDAY:
|
- |
|
| 953 |
if currentDate.weekday() > holiday.holidayValue:
|
- |
|
| 954 |
holidayDate = currentDate + datetime.timedelta(days=holiday.holidayValue-currentDate.weekday(), weeks=1)
|
- |
|
| 955 |
else:
|
- |
|
| 956 |
holidayDate = currentDate + datetime.timedelta(days=holiday.holidayValue-currentDate.weekday())
|
- |
|
| 957 |
if holidayDate >= currentDate and holidayDate <= expectedDate:
|
- |
|
| 958 |
holidayDelay = holidayDelay + 1
|
- |
|
| 959 |
elif holiday.holidayType == HolidayType.MONTHLY:
|
- |
|
| 960 |
holidayDate = datetime.date(currentDate.year, currentDate.month, holiday.holidayValue)
|
- |
|
| 961 |
if holidayDate >= currentDate and holidayDate <= expectedDate:
|
- |
|
| 962 |
holidayDelay = holidayDelay + 1
|
- |
|
| 963 |
elif holiday.holidayType == HolidayType.SPECIFIC:
|
- |
|
| 964 |
holidayValue = str(holiday.holidayValue)
|
- |
|
| 965 |
holidayDate = datetime.date(int(holidayValue[:4]), int(holidayValue[4:6]), int(holidayValue[6:8]))
|
- |
|
| 966 |
if holidayDate >= currentDate and holidayDate <= expectedDate:
|
- |
|
| 967 |
holidayDelay = holidayDelay + 1
|
- |
|
| 968 |
except Exception as e:
|
- |
|
| 969 |
print e
|
- |
|
| 970 |
return holidayDelay
|
- |
|
| 971 |
|
- |
|
| 972 |
def get_warehouses_for_item(item_id):
|
- |
|
| 973 |
|
- |
|
| 974 |
if not item_id:
|
- |
|
| 975 |
raise InventoryServiceException(101, "bad item_id")
|
- |
|
| 976 |
item = get_item(item_id)
|
- |
|
| 977 |
|
- |
|
| 978 |
if not item:
|
- |
|
| 979 |
raise InventoryServiceException(101, "bad item")
|
- |
|
| 980 |
|
- |
|
| 981 |
warehouses = item.currentInventory.warehouse
|
- |
|
| 982 |
return warehouses
|
- |
|
| 983 |
|
- |
|
| 984 |
def get_child_categories(category):
|
459 |
def get_child_categories(category):
|
| 985 |
cm = CategoryManager()
|
460 |
cm = CategoryManager()
|
| 986 |
cat = cm.getCategory(category)
|
461 |
cat = cm.getCategory(category)
|
| 987 |
return cat.children_category_ids if cat else None
|
462 |
return cat.children_category_ids if cat else None
|
| 988 |
|
463 |
|
| Line 1216... |
Line 691... |
| 1216 |
|
691 |
|
| 1217 |
def get_category_object():
|
692 |
def get_category_object():
|
| 1218 |
object = Category.get_by(id=1).object
|
693 |
object = Category.get_by(id=1).object
|
| 1219 |
return object
|
694 |
return object
|
| 1220 |
|
695 |
|
| 1221 |
def get_item_pricing(item_id, vendorId):
|
- |
|
| 1222 |
item = Item.query.filter_by(id=item_id).first()
|
- |
|
| 1223 |
if item is None:
|
- |
|
| 1224 |
raise InventoryServiceException(101, "Bad Item")
|
- |
|
| 1225 |
'''
|
- |
|
| 1226 |
if vendor id is -1 then we calculate an average transfer price to be populated
|
- |
|
| 1227 |
at the time of order creation. This will be later updated with actual transfer price
|
- |
|
| 1228 |
at the time of billing.
|
- |
|
| 1229 |
'''
|
- |
|
| 1230 |
if(vendorId == -1):
|
- |
|
| 1231 |
total = 0
|
- |
|
| 1232 |
try:
|
- |
|
| 1233 |
item_pricings = []
|
- |
|
| 1234 |
if item.preferredVendor is not None:
|
- |
|
| 1235 |
item_pricing = VendorItemPricing.query.filter_by(item=item, vendor_id=item.preferredVendor).first()
|
- |
|
| 1236 |
if item_pricing:
|
- |
|
| 1237 |
item_pricings.append(item_pricing)
|
- |
|
| 1238 |
else :
|
- |
|
| 1239 |
item_pricings = VendorItemPricing.query.filter_by(item=item).all()
|
- |
|
| 1240 |
if item_pricings:
|
- |
|
| 1241 |
for item_pricing in item_pricings:
|
- |
|
| 1242 |
total += item_pricing.transfer_price
|
- |
|
| 1243 |
avg = total / len(item_pricings)
|
- |
|
| 1244 |
item_pricing.transfer_price = avg
|
- |
|
| 1245 |
else:
|
- |
|
| 1246 |
item_pricing = VendorItemPricing()
|
- |
|
| 1247 |
item_pricing.transfer_price = item.sellingPrice
|
- |
|
| 1248 |
vendor = Vendor()
|
- |
|
| 1249 |
vendor.id = vendorId
|
- |
|
| 1250 |
item_pricing.vendor = vendor
|
- |
|
| 1251 |
item_pricing.item = item
|
- |
|
| 1252 |
|
- |
|
| 1253 |
return item_pricing
|
- |
|
| 1254 |
except:
|
- |
|
| 1255 |
raise InventoryServiceException(101, "Item pricing not found ")
|
- |
|
| 1256 |
vendor = Vendor.get_by(id=vendorId)
|
- |
|
| 1257 |
try:
|
- |
|
| 1258 |
item_pricing = VendorItemPricing.query.filter_by(vendor=vendor, item=item).one()
|
- |
|
| 1259 |
return item_pricing
|
- |
|
| 1260 |
except MultipleResultsFound:
|
- |
|
| 1261 |
raise InventoryServiceException(110, "Multiple pricing information present for Vendor: " + vendor.name + " and Item: " + str(item_id))
|
- |
|
| 1262 |
except NoResultFound:
|
- |
|
| 1263 |
raise InventoryServiceException(111, "Missing pricing information for Vendor: " + vendor.name + " and Item: " + str(item_id))
|
- |
|
| 1264 |
|
- |
|
| 1265 |
def add_category(t_category):
|
696 |
def add_category(t_category):
|
| 1266 |
category = Category.get_by(id=t_category.id)
|
697 |
category = Category.get_by(id=t_category.id)
|
| 1267 |
if category is None:
|
698 |
if category is None:
|
| 1268 |
category = Category()
|
699 |
category = Category()
|
| 1269 |
category.id = t_category.id
|
700 |
category.id = t_category.id
|
| Line 1278... |
Line 709... |
| 1278 |
return Category.query.filter_by(id=id).first()
|
709 |
return Category.query.filter_by(id=id).first()
|
| 1279 |
|
710 |
|
| 1280 |
def get_all_categories():
|
711 |
def get_all_categories():
|
| 1281 |
return Category.query.all()
|
712 |
return Category.query.all()
|
| 1282 |
|
713 |
|
| 1283 |
|
- |
|
| 1284 |
def get_all_item_pricing(item_id):
|
- |
|
| 1285 |
item = Item.query.filter_by(id=item_id).first()
|
- |
|
| 1286 |
if item is None:
|
- |
|
| 1287 |
raise InventoryServiceException(101, "Bad Item")
|
- |
|
| 1288 |
item_pricing = VendorItemPricing.query.filter_by(item=item).all()
|
- |
|
| 1289 |
return item_pricing
|
- |
|
| 1290 |
|
- |
|
| 1291 |
def get_item_mappings(item_id):
|
- |
|
| 1292 |
item = Item.query.filter_by(id=item_id).first()
|
- |
|
| 1293 |
if item is None:
|
- |
|
| 1294 |
raise InventoryServiceException(101, "Bad Item")
|
- |
|
| 1295 |
item_mappings = VendorItemMapping.query.filter_by(item=item).all()
|
- |
|
| 1296 |
return item_mappings
|
- |
|
| 1297 |
|
- |
|
| 1298 |
def add_vendor_pricing(vendorItemPricing):
|
- |
|
| 1299 |
if not vendorItemPricing:
|
- |
|
| 1300 |
raise InventoryServiceException(108, "Bad vendorItemPricing in request")
|
- |
|
| 1301 |
vendorId = vendorItemPricing.vendorId
|
- |
|
| 1302 |
itemId = vendorItemPricing.itemId
|
- |
|
| 1303 |
|
- |
|
| 1304 |
try:
|
- |
|
| 1305 |
vendor = Vendor.query.filter_by(id=vendorId).one()
|
- |
|
| 1306 |
except:
|
- |
|
| 1307 |
raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
|
- |
|
| 1308 |
|
- |
|
| 1309 |
try:
|
- |
|
| 1310 |
item = Item.query.filter_by(id=itemId).one()
|
- |
|
| 1311 |
except:
|
- |
|
| 1312 |
raise InventoryServiceException(101, "Item not found for itemId " + str(itemId))
|
- |
|
| 1313 |
|
- |
|
| 1314 |
validate_vendor_prices(to_t_item(item), vendorItemPricing)
|
- |
|
| 1315 |
|
- |
|
| 1316 |
try:
|
- |
|
| 1317 |
ds_vendorItemPricing = VendorItemPricing.query.filter(and_(VendorItemPricing.vendor==vendor, VendorItemPricing.item==item)).one()
|
- |
|
| 1318 |
except:
|
- |
|
| 1319 |
ds_vendorItemPricing = VendorItemPricing()
|
- |
|
| 1320 |
ds_vendorItemPricing.vendor = vendor
|
- |
|
| 1321 |
ds_vendorItemPricing.item = item
|
- |
|
| 1322 |
|
- |
|
| 1323 |
subject = ""
|
- |
|
| 1324 |
message = ""
|
- |
|
| 1325 |
if vendorItemPricing.mop:
|
- |
|
| 1326 |
ds_vendorItemPricing.mop = vendorItemPricing.mop
|
- |
|
| 1327 |
if vendorItemPricing.dealerPrice:
|
- |
|
| 1328 |
ds_vendorItemPricing.dealerPrice = vendorItemPricing.dealerPrice
|
- |
|
| 1329 |
if vendorItemPricing.transferPrice:
|
- |
|
| 1330 |
if vendorItemPricing.transferPrice != ds_vendorItemPricing.transfer_price:
|
- |
|
| 1331 |
message = "Transfer price for Item '{0}' \nand Vendor:{1} is changed from {2} to {3}.".format(__get_product_name(item), vendor.name, ds_vendorItemPricing.transfer_price, vendorItemPricing.transferPrice)
|
- |
|
| 1332 |
subject = "Alert:Change in Transfer Price"
|
- |
|
| 1333 |
ds_vendorItemPricing.transfer_price = vendorItemPricing.transferPrice
|
- |
|
| 1334 |
|
- |
|
| 1335 |
session.commit()
|
- |
|
| 1336 |
if subject:
|
- |
|
| 1337 |
__send_mail(subject, message)
|
- |
|
| 1338 |
return
|
- |
|
| 1339 |
|
- |
|
| 1340 |
def add_vendor_item_mapping(key, vendorItemMapping):
|
- |
|
| 1341 |
if not vendorItemMapping:
|
- |
|
| 1342 |
raise InventoryServiceException(108, "Bad vendorItemMapping in request")
|
- |
|
| 1343 |
vendorId = vendorItemMapping.vendorId
|
- |
|
| 1344 |
itemId = vendorItemMapping.itemId
|
- |
|
| 1345 |
|
- |
|
| 1346 |
try:
|
- |
|
| 1347 |
vendor = Vendor.query.filter_by(id=vendorId).one()
|
- |
|
| 1348 |
except:
|
- |
|
| 1349 |
raise InventoryServiceException(101, "Vendor not found for vendorId " + str(vendorId))
|
- |
|
| 1350 |
|
- |
|
| 1351 |
try:
|
- |
|
| 1352 |
item = Item.query.filter_by(id=itemId).one()
|
- |
|
| 1353 |
except:
|
- |
|
| 1354 |
raise InventoryServiceException(101, "Item not found for vendorId " + str(itemId))
|
- |
|
| 1355 |
|
- |
|
| 1356 |
try:
|
- |
|
| 1357 |
ds_vendorItemMapping = VendorItemMapping.query.filter(and_(VendorItemMapping.vendor==vendor, VendorItemMapping.item==item, VendorItemMapping.item_key==key)).one()
|
- |
|
| 1358 |
except:
|
- |
|
| 1359 |
ds_vendorItemMapping = VendorItemMapping()
|
- |
|
| 1360 |
ds_vendorItemMapping.vendor = vendor
|
- |
|
| 1361 |
ds_vendorItemMapping.item = item
|
- |
|
| 1362 |
ds_vendorItemMapping.item_key = vendorItemMapping.itemKey
|
- |
|
| 1363 |
|
- |
|
| 1364 |
session.commit()
|
- |
|
| 1365 |
|
- |
|
| 1366 |
# Marking the missed inventory as not ignored as the catalog dashboard user has updated their key
|
- |
|
| 1367 |
for missedInventoryUpdate in MissedInventoryUpdate.query.filter_by(itemKey = vendorItemMapping.itemKey).all():
|
- |
|
| 1368 |
missedInventoryUpdate.isIgnored = 0
|
- |
|
| 1369 |
session.commit()
|
- |
|
| 1370 |
|
- |
|
| 1371 |
return
|
- |
|
| 1372 |
|
- |
|
| 1373 |
def validate_item_prices(item):
|
714 |
def validate_item_prices(item):
|
| 1374 |
if item.mrp == None or item.sellingPrice == None or item.mrp == "" or item.sellingPrice == "":
|
715 |
if item.mrp == None or item.sellingPrice == None or item.mrp == "" or item.sellingPrice == "":
|
| 1375 |
return
|
716 |
return
|
| 1376 |
if item.mrp < item.sellingPrice:
|
717 |
if item.mrp < item.sellingPrice:
|
| 1377 |
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))
|
718 |
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))
|
| Line 1385... |
Line 726... |
| 1385 |
if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
|
726 |
if vendorPrices.mop != "" and vendorPrices.transferPrice != "" and vendorPrices.transferPrice > vendorPrices.mop:
|
| 1386 |
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))
|
727 |
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))
|
| 1387 |
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)))
|
728 |
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)))
|
| 1388 |
return
|
729 |
return
|
| 1389 |
|
730 |
|
| 1390 |
def get_all_vendors():
|
- |
|
| 1391 |
return Vendor.query.all()
|
- |
|
| 1392 |
|
- |
|
| 1393 |
def check_color_valid(color):
|
731 |
def check_color_valid(color):
|
| 1394 |
if color is not None:
|
732 |
if color is not None:
|
| 1395 |
color = color.strip().lower()
|
733 |
color = color.strip().lower()
|
| 1396 |
if color != '' and color != 'na' and color != 'blank' and color != '(blank)':
|
734 |
if color != '' and color != 'na' and color != 'blank' and color != '(blank)':
|
| 1397 |
return True
|
735 |
return True
|
| Line 1614... |
Line 952... |
| 1614 |
|
952 |
|
| 1615 |
def send_product_notifications():
|
953 |
def send_product_notifications():
|
| 1616 |
product_notifications = ProductNotification.query.all()
|
954 |
product_notifications = ProductNotification.query.all()
|
| 1617 |
for product_notification in product_notifications:
|
955 |
for product_notification in product_notifications:
|
| 1618 |
item = product_notification.item
|
956 |
item = product_notification.item
|
| - |
|
957 |
client = InventoryClient().get_client()
|
| 1619 |
availability = __get_item_availability(item, None)
|
958 |
availability = client.getItemAvailabilityAtLocation(item.id)[4]
|
| 1620 |
if item.status == status.ACTIVE and (not item.risky or availability > 0):
|
959 |
if item.status == status.ACTIVE and (not item.risky or availability > 0):
|
| 1621 |
__enque_product_notification_email(product_notification.email, __get_product_name(item) , product_notification.addedOn, __get_product_url(item), item.id)
|
960 |
__enque_product_notification_email(product_notification.email, __get_product_name(item) , product_notification.addedOn, __get_product_url(item), item.id)
|
| 1622 |
product_notification.delete()
|
961 |
product_notification.delete()
|
| 1623 |
session.commit()
|
962 |
session.commit()
|
| 1624 |
return True
|
963 |
return True
|
| Line 1818... |
Line 1157... |
| 1818 |
except:
|
1157 |
except:
|
| 1819 |
print "Unable to clear home page cache" + res.read()
|
1158 |
print "Unable to clear home page cache" + res.read()
|
| 1820 |
except:
|
1159 |
except:
|
| 1821 |
print "Unable to clear cache, still should continue with other operations"
|
1160 |
print "Unable to clear cache, still should continue with other operations"
|
| 1822 |
|
1161 |
|
| 1823 |
def get_pending_orders_inventory(vendor_id=1):
|
- |
|
| 1824 |
"""
|
- |
|
| 1825 |
Returns a list of inventory stock for items for which there are pending orders.
|
- |
|
| 1826 |
"""
|
- |
|
| 1827 |
|
- |
|
| 1828 |
warehouse_ids = [warehouse.id for warehouse in Warehouse.query.filter_by(vendor_id = vendor_id)]
|
- |
|
| 1829 |
pending_items_inventory = []
|
- |
|
| 1830 |
if warehouse_ids:
|
- |
|
| 1831 |
pending_items_inventory = session.query(CurrentInventorySnapshot.item_id, func.sum(CurrentInventorySnapshot.availability), func.sum(CurrentInventorySnapshot.reserved)).filter(CurrentInventorySnapshot.warehouse_id.in_(warehouse_ids)).group_by(CurrentInventorySnapshot.item_id).having(func.sum(CurrentInventorySnapshot.reserved) > 0).all()
|
- |
|
| 1832 |
return pending_items_inventory
|
- |
|
| 1833 |
|
- |
|
| 1834 |
def get_product_notifications(start_datetime):
|
1162 |
def get_product_notifications(start_datetime):
|
| 1835 |
'''
|
1163 |
'''
|
| 1836 |
Returns a list of Product Notification objects each representing user requests for notification
|
1164 |
Returns a list of Product Notification objects each representing user requests for notification
|
| 1837 |
'''
|
1165 |
'''
|
| 1838 |
query = ProductNotification.query
|
1166 |
query = ProductNotification.query
|
| Line 1866... |
Line 1194... |
| 1866 |
session.query(Item.id).limit(1).one()
|
1194 |
session.query(Item.id).limit(1).one()
|
| 1867 |
return True
|
1195 |
return True
|
| 1868 |
except:
|
1196 |
except:
|
| 1869 |
return False
|
1197 |
return False
|
| 1870 |
|
1198 |
|
| 1871 |
def add_vendor(vendor):
|
- |
|
| 1872 |
if not vendor:
|
- |
|
| 1873 |
raise InventoryServiceException(108, "Bad vendor")
|
- |
|
| 1874 |
if get_Vendor(vendor.id):
|
- |
|
| 1875 |
#vendor is already present.
|
- |
|
| 1876 |
raise InventoryServiceException(101, "Vendor already present")
|
- |
|
| 1877 |
|
- |
|
| 1878 |
ds_vendor = Vendor()
|
- |
|
| 1879 |
ds_vendor.id = vendor.id
|
- |
|
| 1880 |
ds_vendor.name = vendor.name
|
- |
|
| 1881 |
session.commit()
|
- |
|
| 1882 |
return ds_vendor.id
|
- |
|
| 1883 |
|
- |
|
| 1884 |
def add_warehouse_vendor_mapping(warehouse_id, VendorId):
|
- |
|
| 1885 |
return True
|
- |
|
| 1886 |
|
- |
|
| 1887 |
def add_authorization_log_for_item(itemId, username, reason):
|
1199 |
def add_authorization_log_for_item(itemId, username, reason):
|
| 1888 |
if not itemId or not username:
|
1200 |
if not itemId or not username:
|
| 1889 |
raise InventoryServiceException(101, "Bad itemId or Invalid username in request")
|
1201 |
raise InventoryServiceException(101, "Bad itemId or Invalid username in request")
|
| 1890 |
authorize_log = AuthorizationLog()
|
1202 |
authorize_log = AuthorizationLog()
|
| 1891 |
authorize_log.item_id = itemId
|
1203 |
authorize_log.item_id = itemId
|
| Line 1898... |
Line 1210... |
| 1898 |
try:
|
1210 |
try:
|
| 1899 |
EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', ['abhishek.mathur@shop2020.in', 'chaitnaya.vats@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)
|
1211 |
EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', ['abhishek.mathur@shop2020.in', 'chaitnaya.vats@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)
|
| 1900 |
except Exception as e:
|
1212 |
except Exception as e:
|
| 1901 |
print e
|
1213 |
print e
|
| 1902 |
|
1214 |
|
| 1903 |
def mark_missed_inventory_updates_as_processed(itemKey, warehouseId):
|
- |
|
| 1904 |
MissedInventoryUpdate.query.filter_by(itemKey = itemKey, warehouseId = warehouseId).delete()
|
- |
|
| 1905 |
session.commit()
|
- |
|
| 1906 |
|
- |
|
| 1907 |
def get_item_keys_to_be_processed(warehouseId):
|
- |
|
| 1908 |
return [i.itemKey for i in MissedInventoryUpdate.query.filter_by(warehouseId = warehouseId, isIgnored = 0)]
|
- |
|
| 1909 |
|
- |
|
| 1910 |
def reset_availability(itemKey, vendorId, quantity, warehouseId):
|
- |
|
| 1911 |
vendorItemMapping = VendorItemMapping.get_by(vendor_id = vendorId, item_key = itemKey)
|
- |
|
| 1912 |
if vendorItemMapping:
|
- |
|
| 1913 |
itemId = vendorItemMapping.item_id
|
- |
|
| 1914 |
|
- |
|
| 1915 |
if skippedItems.has_key(warehouseId) and itemId in skippedItems[warehouseId]:
|
- |
|
| 1916 |
quantity = 0
|
- |
|
| 1917 |
|
- |
|
| 1918 |
currentInventorySnapshot = CurrentInventorySnapshot.get_by(item_id = itemId, warehouse_id = warehouseId)
|
- |
|
| 1919 |
if currentInventorySnapshot:
|
- |
|
| 1920 |
currentInventorySnapshot.availability = quantity
|
- |
|
| 1921 |
__update_item_availability_cache(itemId)
|
- |
|
| 1922 |
check_risky_item(currentInventorySnapshot.item)
|
- |
|
| 1923 |
else:
|
- |
|
| 1924 |
add_inventory(itemId, warehouseId, quantity)
|
- |
|
| 1925 |
|
- |
|
| 1926 |
else:
|
- |
|
| 1927 |
raise InventoryServiceException(101, 'VendorMapping not found for: ' + itemKey)
|
- |
|
| 1928 |
session.commit()
|
- |
|
| 1929 |
|
- |
|
| 1930 |
def reset_availability_for_warehouse(warehouseId):
|
- |
|
| 1931 |
for currentInventorySnapshot in CurrentInventorySnapshot.query.filter_by(warehouse_id=warehouseId).all():
|
- |
|
| 1932 |
currentInventorySnapshot.availability = 0
|
- |
|
| 1933 |
__update_item_availability_cache(currentInventorySnapshot.item_id)
|
- |
|
| 1934 |
check_risky_item(currentInventorySnapshot.item)
|
- |
|
| 1935 |
session.commit()
|
- |
|
| 1936 |
|
- |
|
| 1937 |
def __send_mail(subject, message):
|
1215 |
def __send_mail(subject, message):
|
| 1938 |
try:
|
1216 |
try:
|
| 1939 |
thread = threading.Thread(target=partial(mail, from_user, from_pwd, to_addresses, subject, message))
|
1217 |
thread = threading.Thread(target=partial(mail, from_user, from_pwd, to_addresses, subject, message))
|
| 1940 |
thread.start()
|
1218 |
thread.start()
|
| 1941 |
except Exception as ex:
|
1219 |
except Exception as ex:
|
| 1942 |
print ex
|
1220 |
print ex
|
| 1943 |
|
1221 |
|
| 1944 |
def get_shipping_locations():
|
- |
|
| 1945 |
shippingLocationIds = {}
|
- |
|
| 1946 |
warehouses = Warehouse.query.all()
|
- |
|
| 1947 |
for warehouse in warehouses:
|
- |
|
| 1948 |
if warehouse.shippingWarehouseId:
|
- |
|
| 1949 |
shippingLocationIds[warehouse.shippingWarehouseId] = 1
|
- |
|
| 1950 |
|
- |
|
| 1951 |
shippingLocations = []
|
- |
|
| 1952 |
for shippingLocationId in shippingLocationIds:
|
- |
|
| 1953 |
shippingLocations.append(get_Warehouse(shippingLocationId))
|
- |
|
| 1954 |
|
- |
|
| 1955 |
return shippingLocations
|
- |
|
| 1956 |
|
- |
|
| 1957 |
def get_inventory_snapshot(warehouseId):
|
- |
|
| 1958 |
query = CurrentInventorySnapshot.query
|
- |
|
| 1959 |
|
- |
|
| 1960 |
if warehouseId:
|
- |
|
| 1961 |
query = query.filter_by(warehouse_id = warehouseId)
|
- |
|
| 1962 |
|
- |
|
| 1963 |
itemInventoryMap = {}
|
- |
|
| 1964 |
for row in query.all():
|
- |
|
| 1965 |
if not itemInventoryMap.has_key(row.item_id):
|
- |
|
| 1966 |
itemInventoryMap[row.item_id] = []
|
- |
|
| 1967 |
|
- |
|
| 1968 |
itemInventoryMap[row.item_id].append(row)
|
- |
|
| 1969 |
|
- |
|
| 1970 |
return itemInventoryMap
|
- |
|
| 1971 |
|
- |
|
| 1972 |
def get_clearance_sale_catalog_ids():
|
1222 |
def get_clearance_sale_catalog_ids():
|
| 1973 |
all_status = [status.ACTIVE, status.PAUSED, status.PAUSED_BY_RISK]
|
1223 |
all_status = [status.ACTIVE, status.PAUSED, status.PAUSED_BY_RISK]
|
| 1974 |
query = Item.query.filter_by(clearance=True)
|
1224 |
query = Item.query.filter_by(clearance=True)
|
| 1975 |
query = query.filter(Item.status.in_(all_status))
|
1225 |
query = query.filter(Item.status.in_(all_status))
|
| 1976 |
query = query.group_by(Item.catalog_item_id).order_by(desc(Item.startDate)).order_by(Item.catalog_item_id)
|
1226 |
query = query.group_by(Item.catalog_item_id).order_by(desc(Item.startDate)).order_by(Item.catalog_item_id)
|
| 1977 |
clearance_sales = query.all()
|
1227 |
clearance_sales = query.all()
|
| 1978 |
return [item.catalog_item_id for item in clearance_sales]
|
1228 |
return [item.catalog_item_id for item in clearance_sales]
|
| 1979 |
|
- |
|
| 1980 |
def update_vendor_string(warehouseId, vendorString):
|
- |
|
| 1981 |
warehouse = get_Warehouse(warehouseId)
|
- |
|
| 1982 |
warehouse.vendorString = vendorString
|
- |
|
| 1983 |
session.commit()
|
- |
|