| Line 2... |
Line 2... |
| 2 |
Created on 23-Mar-2010
|
2 |
Created on 23-Mar-2010
|
| 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 pydoc import Helper
|
8 |
from pydoc import Helper
|
| 8 |
from shop2020.clients.HelperClient import HelperClient
|
9 |
from shop2020.clients.HelperClient import HelperClient
|
| 9 |
from shop2020.clients.TransactionClient import TransactionClient
|
10 |
from shop2020.clients.TransactionClient import TransactionClient
|
| 10 |
from shop2020.config.client.ConfigClient import ConfigClient
|
11 |
from shop2020.config.client.ConfigClient import ConfigClient
|
| 11 |
from shop2020.model.v1.catalog.impl import DataService
|
12 |
from shop2020.model.v1.catalog.impl import DataService
|
| 12 |
from shop2020.model.v1.catalog.impl.CategoryManager import CategoryManager
|
13 |
from shop2020.model.v1.catalog.impl.CategoryManager import CategoryManager
|
| 13 |
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
|
| 14 |
from shop2020.model.v1.catalog.impl.DataService import Item, Warehouse, \
|
15 |
from shop2020.model.v1.catalog.impl.DataService import Item, Warehouse, \
|
| 15 |
ItemInventoryHistory, CurrentInventorySnapshot, ItemChangeLog, \
|
16 |
ItemInventoryHistory, CurrentInventorySnapshot, ItemChangeLog, Category, \
|
| 16 |
Category, EntityIDGenerator, VendorItemPricing, VendorItemMapping, Vendor, \
|
17 |
EntityIDGenerator, VendorItemPricing, VendorItemMapping, Vendor, SimilarItems, \
|
| 17 |
SimilarItems, ProductNotification, Source, SourceItemPricing, AuthorizationLog, \
|
18 |
ProductNotification, Source, SourceItemPricing, AuthorizationLog, \
|
| 18 |
MissedInventoryUpdate, BadInventorySnapshot, VendorItemProcurementDelay, \
|
19 |
MissedInventoryUpdate, BadInventorySnapshot, VendorItemProcurementDelay, \
|
| 19 |
VendorHolidays, ItemAvailabilityCache
|
20 |
VendorHolidays, ItemAvailabilityCache
|
| 20 |
from shop2020.thriftpy.model.v1.catalog.ttypes import InventoryServiceException, \
|
21 |
from shop2020.thriftpy.model.v1.catalog.ttypes import InventoryServiceException, \
|
| 21 |
status, ItemShippingInfo, HolidayType, InventoryType, ItemType
|
22 |
status, ItemShippingInfo, HolidayType, InventoryType, WarehouseType, ItemType
|
| 22 |
from shop2020.thriftpy.model.v1.order.ttypes import AlertType
|
23 |
from shop2020.thriftpy.model.v1.order.ttypes import AlertType
|
| 23 |
from shop2020.utils import EmailAttachmentSender
|
24 |
from shop2020.utils import EmailAttachmentSender
|
| 24 |
from shop2020.utils.EmailAttachmentSender import mail
|
25 |
from shop2020.utils.EmailAttachmentSender import mail
|
| 25 |
from shop2020.utils.Utils import to_py_date, log_risky_flag
|
26 |
from shop2020.utils.Utils import to_py_date, log_risky_flag
|
| 26 |
from sqlalchemy import desc, asc
|
27 |
from sqlalchemy import desc, asc
|
| Line 29... |
Line 30... |
| 29 |
from string import Template
|
30 |
from string import Template
|
| 30 |
from urllib2 import HTTPBasicAuthHandler
|
31 |
from urllib2 import HTTPBasicAuthHandler
|
| 31 |
import calendar
|
32 |
import calendar
|
| 32 |
import datetime
|
33 |
import datetime
|
| 33 |
import sys
|
34 |
import sys
|
| - |
|
35 |
import threading
|
| 34 |
import urllib2
|
36 |
import urllib2
|
| 35 |
from functools import partial
|
- |
|
| 36 |
|
37 |
|
| 37 |
import threading
|
- |
|
| 38 |
|
38 |
|
| 39 |
to_addresses = ["cnc.center@shop2020.in", "ashutosh.saxena@shop2020.in"]
|
39 |
to_addresses = ["cnc.center@shop2020.in", "ashutosh.saxena@shop2020.in"]
|
| 40 |
from_user = "cnc.center@shop2020.in"
|
40 |
from_user = "cnc.center@shop2020.in"
|
| 41 |
from_pwd = "5h0p2o2o"
|
41 |
from_pwd = "5h0p2o2o"
|
| 42 |
|
42 |
|
| Line 82... |
Line 82... |
| 82 |
def is_active(item_id):
|
82 |
def is_active(item_id):
|
| 83 |
t_item_shipping_info = ItemShippingInfo()
|
83 |
t_item_shipping_info = ItemShippingInfo()
|
| 84 |
try:
|
84 |
try:
|
| 85 |
item = get_item(item_id)
|
85 |
item = get_item(item_id)
|
| 86 |
t_item_shipping_info.isRisky = item.risky
|
86 |
t_item_shipping_info.isRisky = item.risky
|
| 87 |
warehouse_ids = None
|
87 |
warehouse_id = get_item_availability_for_location(item.id)[0]
|
| 88 |
if item.isWarehousePreferenceSticky:
|
88 |
if item.risky and item.status == status.ACTIVE:
|
| 89 |
warehouse_ids = [w.id for w in Warehouse.query.filter_by(shippingWarehouseId = item.preferredWarehouse, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]).all()]
|
89 |
availability = 0
|
| 90 |
availability = __get_item_availability(item, warehouse_ids)
|
90 |
currentInventorySnapshot = CurrentInventorySnapshot.query.filter_by(item_id = item.id, warehouse_id = warehouse_id).all()
|
| 91 |
if item.risky and availability <= 0 and item.status == status.ACTIVE:
|
91 |
if not currentInventorySnapshot or currentInventorySnapshot[0].availibility <= currentInventorySnapshot[0].reserved:
|
| 92 |
add_status_change_log(item, status.PAUSED_BY_RISK)
|
92 |
add_status_change_log(item, status.PAUSED_BY_RISK)
|
| 93 |
item.status = status.PAUSED_BY_RISK
|
93 |
item.status = status.PAUSED_BY_RISK
|
| 94 |
item.status_description = "This item is currently out of stock"
|
94 |
item.status_description = "This item is currently out of stock"
|
| 95 |
session.commit()
|
95 |
session.commit()
|
| 96 |
__send_mail_for_oos_item(item)
|
96 |
__send_mail_for_oos_item(item)
|
| 97 |
#This will clear cache from tomcat
|
97 |
#This will clear cache from tomcat
|
| 98 |
__clear_homepage_cache()
|
98 |
__clear_homepage_cache()
|
| - |
|
99 |
else:
|
| - |
|
100 |
availability = currentInventorySnapshot[0].availibility
|
| - |
|
101 |
else:
|
| - |
|
102 |
availability = item.get_total_inventory
|
| 99 |
t_item_shipping_info.isActive = (item.status == status.ACTIVE)
|
103 |
t_item_shipping_info.isActive = (item.status == status.ACTIVE)
|
| 100 |
t_item_shipping_info.quantity = availability
|
104 |
t_item_shipping_info.quantity = availability
|
| 101 |
except InventoryServiceException:
|
105 |
except InventoryServiceException:
|
| 102 |
print "[ERROR] Unexpected error:", sys.exc_info()[0]
|
106 |
print "[ERROR] Unexpected error:", sys.exc_info()[0]
|
| 103 |
return t_item_shipping_info
|
107 |
return t_item_shipping_info
|
| Line 232... |
Line 236... |
| 232 |
ds_item.type = ItemType._VALUES_TO_NAMES[item.type]
|
236 |
ds_item.type = ItemType._VALUES_TO_NAMES[item.type]
|
| 233 |
ds_item.hasItemNo = item.hasItemNo
|
237 |
ds_item.hasItemNo = item.hasItemNo
|
| 234 |
|
238 |
|
| 235 |
if item.expectedDelay is not None:
|
239 |
if item.expectedDelay is not None:
|
| 236 |
ds_item.expectedDelay = item.expectedDelay
|
240 |
ds_item.expectedDelay = item.expectedDelay
|
| 237 |
|
- |
|
| 238 |
if item.preferredWarehouse:
|
- |
|
| 239 |
if item.preferredWarehouse != ds_item.preferredWarehouse:
|
- |
|
| 240 |
newPreferredWareHouseName = get_Warehouse(item.preferredWarehouse).displayName
|
- |
|
| 241 |
oldPreferredWareHouseName = 'None'
|
- |
|
| 242 |
if ds_item.preferredWarehouse:
|
- |
|
| 243 |
oldPreferredWareHouseName = get_Warehouse(ds_item.preferredWarehouse).displayName
|
- |
|
| 244 |
message += "Preferred warehouse is changed from '{0}' to '{1}'.\n".format(oldPreferredWareHouseName, newPreferredWareHouseName)
|
- |
|
| 245 |
ds_item.preferredWarehouse = item.preferredWarehouse
|
- |
|
| 246 |
|
- |
|
| 247 |
if item.defaultWarehouse:
|
- |
|
| 248 |
ds_item.defaultWarehouse = item.defaultWarehouse
|
- |
|
| 249 |
|
241 |
|
| 250 |
if item.preferredVendor:
|
242 |
if item.preferredVendor:
|
| 251 |
if item.preferredVendor != ds_item.preferredVendor:
|
243 |
if item.preferredVendor != ds_item.preferredVendor:
|
| 252 |
newPreferredVendorName = get_Vendor(item.preferredVendor).name
|
244 |
newPreferredVendorName = get_Vendor(item.preferredVendor).name
|
| 253 |
oldPreferredVendorName = 'None'
|
245 |
oldPreferredVendorName = 'None'
|
| Line 333... |
Line 325... |
| 333 |
|
325 |
|
| 334 |
if item.expectedDelay is not None:
|
326 |
if item.expectedDelay is not None:
|
| 335 |
ds_item.expectedDelay = item.expectedDelay
|
327 |
ds_item.expectedDelay = item.expectedDelay
|
| 336 |
else:
|
328 |
else:
|
| 337 |
ds_item.expectedDelay = 0
|
329 |
ds_item.expectedDelay = 0
|
| 338 |
|
- |
|
| 339 |
if item.preferredWarehouse:
|
- |
|
| 340 |
ds_item.preferredWarehouse = item.preferredWarehouse
|
- |
|
| 341 |
|
- |
|
| 342 |
if item.defaultWarehouse:
|
- |
|
| 343 |
ds_item.defaultWarehouse = item.defaultWarehouse
|
- |
|
| 344 |
|
330 |
|
| 345 |
if item.preferredVendor:
|
331 |
if item.preferredVendor:
|
| 346 |
ds_item.preferredVendor = item.preferredVendor
|
332 |
ds_item.preferredVendor = item.preferredVendor
|
| 347 |
|
333 |
|
| 348 |
# Check if a similar item already exists in our database
|
334 |
# Check if a similar item already exists in our database
|
| Line 607... |
Line 593... |
| 607 |
"""
|
593 |
"""
|
| 608 |
|
594 |
|
| 609 |
def check_risky_item(item):
|
595 |
def check_risky_item(item):
|
| 610 |
if not item.risky:
|
596 |
if not item.risky:
|
| 611 |
return
|
597 |
return
|
| 612 |
warehouse_ids = None
|
- |
|
| 613 |
if item.isWarehousePreferenceSticky :
|
598 |
warehouse_id = get_item_availability_for_location(item.id)[0]
|
| 614 |
warehouse_ids = [w.id for w in Warehouse.query.filter_by(shippingWarehouseId = item.preferredWarehouse, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]).all()]
|
599 |
currentInventorySnapshot = CurrentInventorySnapshot.query.filter_by(item_id = item.id, warehouse_id = warehouse_id).all()
|
| 615 |
availability = __get_item_availability(item, warehouse_ids)
|
600 |
if not currentInventorySnapshot or currentInventorySnapshot[0].availability <= currentInventorySnapshot[0].reserved:
|
| 616 |
if availability <= 0:
|
- |
|
| 617 |
if item.status == status.ACTIVE:
|
601 |
if item.status == status.ACTIVE:
|
| 618 |
change_item_status(item.id, status.PAUSED_BY_RISK)
|
602 |
change_item_status(item.id, status.PAUSED_BY_RISK)
|
| 619 |
__send_mail_for_oos_item(item)
|
603 |
__send_mail_for_oos_item(item)
|
| 620 |
else:
|
604 |
else:
|
| 621 |
if item.status == status.PAUSED_BY_RISK:
|
605 |
if item.status == status.PAUSED_BY_RISK:
|
| Line 737... |
Line 721... |
| 737 |
def __update_item_availability_cache(item_id):
|
721 |
def __update_item_availability_cache(item_id):
|
| 738 |
"""
|
722 |
"""
|
| 739 |
Determines the warehouse that should be used to fulfil an order for the given item.
|
723 |
Determines the warehouse that should be used to fulfil an order for the given item.
|
| 740 |
Algorithm explained at https://sites.google.com/a/shop2020.in/virtual-w-h-and-inventory/technical-details
|
724 |
Algorithm explained at https://sites.google.com/a/shop2020.in/virtual-w-h-and-inventory/technical-details
|
| 741 |
|
725 |
|
| 742 |
If item's Preferred warehouse is present
|
- |
|
| 743 |
If item marked sticky
|
- |
|
| 744 |
use GOOD type warehouse at preferred warehouse with maximum availability.
|
726 |
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.
|
| 745 |
If not available at any, then use THIRD_PARTY warehouse without billing support
|
- |
|
| 746 |
corresponding to preferred warehouse where available.
|
- |
|
| 747 |
If still not available, then use any GOOD type warehouse with billing support.
|
727 |
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.
|
| 748 |
else
|
728 |
|
| 749 |
if availability > 0 at least one of GOOD type warehouses in preferred warehouse
|
729 |
if item available at any OUR-GOOD warehouse
|
| 750 |
use GOOD type warehouse at preferred warehouse with maximum availability
|
730 |
// OUR-GOOD warehouses have inventory risk; So, we empty them first!
|
| 751 |
|
- |
|
| 752 |
If available at no warehouse
|
731 |
// We can start with minimum transfer price criterion but down the line we can also bring in Inventory age
|
| 753 |
use any GOOD type warehouse at default warehouse
|
732 |
assign OUR-GOOD warehouse with minimum transfer price
|
| 754 |
else
|
733 |
else
|
| 755 |
if available at any warehouse of type GOOD with billing support
|
734 |
if Preferred vendor is specified and marked Sticky
|
| 756 |
use warehouse of type GOOD with billing support with maximum availability
|
735 |
// Always purchase from Preferred if its marked sticky
|
| - |
|
736 |
assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
|
| 757 |
else
|
737 |
else
|
| 758 |
if preferred warehouse is present and availability at preferred warehouse's corresponding ThirdPartyWarehouse without billing support > 0
|
738 |
if item available in a THIRDPARTY GOOD/VIRTUAL warehouse
|
| 759 |
preferred warehouse's corresponding ThirdPartyWarehouse without billing support with maximum availability
|
739 |
assign THIRDPARTY GOOD/VIRTUAL warehouse where item is available with minimal transfer delay followed by minimum transfer price
|
| 760 |
else
|
740 |
else
|
| - |
|
741 |
// Item not available at any warehouse, OURS or THIRDPARTY
|
| - |
|
742 |
If Preferred vendor is specified
|
| 761 |
use ThirdPartyWarehouse without billing support with maximum availability
|
743 |
assign preferred vendor's THIRDPARTY GOOD/VIRTUAL warehouse
|
| 762 |
|
744 |
else
|
| - |
|
745 |
assign THIRDPARTY GOOD/VIRTUAL warehouse with minimum transfer price
|
| - |
|
746 |
|
| 763 |
Returns an ordered list of size 4 with following elements in the given order:
|
747 |
Returns an ordered list of size 4 with following elements in the given order:
|
| 764 |
1. Logistics location of the warehouse which was finally picked up to ship the order.
|
748 |
1. Logistics location of the warehouse which was finally picked up to ship the order.
|
| 765 |
2. Expected delay added by the category manager.
|
749 |
2. Expected delay added by the category manager.
|
| 766 |
3. Id of the warehouse which was finally picked up.
|
750 |
3. Id of the warehouse which was finally picked up.
|
| 767 |
|
- |
|
| 768 |
|
751 |
|
| 769 |
Parameters:
|
752 |
Parameters:
|
| 770 |
- itemId
|
753 |
- itemId
|
| 771 |
"""
|
754 |
"""
|
| 772 |
|
- |
|
| 773 |
item = Item.get_by(id=item_id)
|
755 |
item = Item.get_by(id=item_id)
|
| 774 |
warehouse_ids = []
|
756 |
item_pricing = {}
|
| 775 |
goodBillableWarehouses = []
|
757 |
for vendorItemPricing in VendorItemPricing.query.filter_by(item=item).all():
|
| 776 |
goodBillableWarehousesAtPreferredShippingLocation = []
|
758 |
item_pricing[vendorItemPricing.vendor_id] = vendorItemPricing
|
| - |
|
759 |
|
| - |
|
760 |
warehouses = {}
|
| 777 |
goodBillableWarehousesAtDefaultShippingLocation = []
|
761 |
ourGoodWarehouses = {}
|
| 778 |
nonBillableWarehouses = []
|
762 |
thirdpartyWarehouses = {}
|
| 779 |
nonBillableWarehousesCorrespondingToPreferredShippingLocation = []
|
763 |
preferredThirdpartyWarehouses = {}
|
| 780 |
for warehouse in Warehouse.query.all():
|
764 |
for warehouse in Warehouse.query.all():
|
| 781 |
if (warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.BAD]):
|
765 |
if (warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.BAD]):
|
| 782 |
continue
|
766 |
continue
|
| 783 |
if warehouse.shippingWarehouseId == item.defaultWarehouse and warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD] and warehouse.billingWarehouseId:
|
767 |
warehouses[warehouse.id] = warehouse
|
| 784 |
goodBillableWarehousesAtDefaultShippingLocation.append(warehouse.id)
|
768 |
if warehouse.warehouseType == WarehouseType._VALUES_TO_NAMES[WarehouseType.OURS]:
|
| 785 |
if warehouse.billingWarehouseId is None:
|
769 |
if warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
|
| 786 |
nonBillableWarehouses.append(warehouse.id)
|
770 |
ourGoodWarehouses[warehouse.id] = warehouse
|
| 787 |
|
771 |
else:
|
| 788 |
warehouse_ids.append(warehouse.id)
|
772 |
thirdpartyWarehouses[warehouse.id] = warehouse
|
| 789 |
if warehouse.billingWarehouseId and warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
|
773 |
if item.preferredVendor == warehouse.vendor_id and warehouse.inventoryType == InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]:
|
| 790 |
goodBillableWarehouses.append(warehouse.id)
|
- |
|
| 791 |
if item.preferredWarehouse and item.preferredWarehouse == warehouse.shippingWarehouseId:
|
774 |
preferredThirdpartyWarehouses[warehouse.id] = warehouse
|
| 792 |
goodBillableWarehousesAtPreferredShippingLocation.append(warehouse.id)
|
- |
|
| 793 |
nonBillableWarehousesCorrespondingToPreferredShippingLocation.extend([w.id for w in Warehouse.query.filter_by(vendor_id = warehouse.vendor_id, billingWarehouseId = None).all()])
|
- |
|
| 794 |
|
775 |
|
| 795 |
warehouse_retid = -1
|
776 |
warehouse_retid = -1
|
| 796 |
total_availability = 0
|
777 |
total_availability = 0
|
| 797 |
|
778 |
|
| 798 |
'''
|
- |
|
| 799 |
If warehouse preference is set and it is sticky then we should fulfil this order from this warehouse only.
|
- |
|
| 800 |
But we still need to calculate total availability across warehouses.
|
- |
|
| 801 |
'''
|
- |
|
| 802 |
if (item.isWarehousePreferenceSticky and item.preferredWarehouse):
|
- |
|
| 803 |
[warehouse_retid, total_availability] = __get_warehouse_with_max_availability(goodBillableWarehousesAtPreferredShippingLocation, item)
|
- |
|
| 804 |
if warehouse_retid == -1:
|
- |
|
| 805 |
[warehouse_retid, total_availability] = __get_warehouse_with_max_availability(nonBillableWarehousesCorrespondingToPreferredShippingLocation, item)
|
- |
|
| 806 |
if warehouse_retid == -1:
|
- |
|
| 807 |
warehouse_retid = goodBillableWarehousesAtPreferredShippingLocation[0]
|
- |
|
| 808 |
if item.preferredVendor:
|
- |
|
| 809 |
warehousesWithPreferredVendorAtPreferredShippingLocation = Warehouse.query.filter_by(shippingWarehouseId = item.preferredWarehouse, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD], vendor_id = item.preferredVendor).all()
|
779 |
[warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(ourGoodWarehouses, item, item_pricing, False)
|
| 810 |
if warehousesWithPreferredVendorAtPreferredShippingLocation:
|
- |
|
| 811 |
warehouse_retid = warehousesWithPreferredVendorAtPreferredShippingLocation[0].id
|
- |
|
| 812 |
elif (not item.isWarehousePreferenceSticky and item.preferredWarehouse):
|
- |
|
| 813 |
[warehouse_retid, total_availability] = __get_warehouse_with_max_availability(goodBillableWarehousesAtPreferredShippingLocation, item)
|
- |
|
| 814 |
|
- |
|
| 815 |
if warehouse_retid == -1:
|
780 |
if warehouse_retid == -1:
|
| 816 |
[warehouse_retid, total_availability] = __get_warehouse_with_max_availability(warehouse_ids, item)
|
- |
|
| 817 |
if warehouse_retid == -1:
|
- |
|
| 818 |
warehouse_retid = goodBillableWarehousesAtDefaultShippingLocation[0]
|
781 |
if item.preferredVendor and item.isWarehousePreferenceSticky:
|
| 819 |
if item.preferredVendor:
|
- |
|
| 820 |
warehousesWithPreferredVendorAtDefaultShippingLocation = Warehouse.query.filter_by(shippingWarehouseId = item.defaultWarehouse, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD], vendor_id = item.preferredVendor).all()
|
- |
|
| 821 |
if warehousesWithPreferredVendorAtDefaultShippingLocation:
|
782 |
warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
|
| 822 |
warehouse_retid = warehousesWithPreferredVendorAtDefaultShippingLocation[0].id
|
- |
|
| 823 |
else:
|
783 |
else:
|
| 824 |
[warehouse_retid, total_availability] = __get_warehouse_with_max_availability(goodBillableWarehouses, item)
|
784 |
[warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_delay(thirdpartyWarehouses, item, item_pricing)
|
| 825 |
if warehouse_retid == -1:
|
785 |
if warehouse_retid == -1:
|
| 826 |
if item.preferredWarehouse:
|
786 |
if item.preferredVendor:
|
| 827 |
[warehouse_retid, total_availability] = __get_warehouse_with_max_availability(nonBillableWarehousesCorrespondingToPreferredShippingLocation, item)
|
787 |
warehouse_retid = preferredThirdpartyWarehouses.keys()[0]
|
| 828 |
if warehouse_retid == -1:
|
788 |
else:
|
| 829 |
# Availability at Good Billable warehouses is Zero, so can safely use all warehouse_ids to capture the thirdparty virtual/good one
|
- |
|
| 830 |
[warehouse_retid, total_availability] = __get_warehouse_with_max_availability(warehouse_ids, item)
|
789 |
[warehouse_retid, total_availability] = __get_warehouse_with_min_transfer_price(thirdpartyWarehouses, item, item_pricing, True)
|
| 831 |
|
790 |
|
| 832 |
warehouse = Warehouse.get_by(id=warehouse_retid)
|
791 |
warehouse = warehouses[warehouse_retid]
|
| 833 |
billingWarehouseId = warehouse.billingWarehouseId
|
792 |
billingWarehouseId = warehouse.billingWarehouseId
|
| 834 |
|
793 |
|
| 835 |
# Fetching billing warehouse of a Good billable warehouse corresponding to the virtual one
|
794 |
# Fetching billing warehouse of a Good billable warehouse corresponding to the virtual one
|
| 836 |
if warehouse.billingWarehouseId is None:
|
795 |
if warehouse.billingWarehouseId is None:
|
| 837 |
for warehouse in Warehouse.query.filter_by(vendor_id = warehouse.vendor_id, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]).all():
|
796 |
for warehouse in Warehouse.query.filter_by(vendor_id = warehouse.vendor_id, inventoryType = InventoryType._VALUES_TO_NAMES[InventoryType.GOOD]).all():
|
| 838 |
if warehouse.billingWarehouseId:
|
797 |
if warehouse.billingWarehouseId:
|
| 839 |
billingWarehouseId = warehouse.billingWarehouseId
|
798 |
billingWarehouseId = warehouse.billingWarehouseId
|
| Line 843... |
Line 802... |
| 843 |
if expectedDelay is None:
|
802 |
if expectedDelay is None:
|
| 844 |
print 'expectedDelay field for this item was Null. Resetting it to 0'
|
803 |
print 'expectedDelay field for this item was Null. Resetting it to 0'
|
| 845 |
expectedDelay = 0
|
804 |
expectedDelay = 0
|
| 846 |
else:
|
805 |
else:
|
| 847 |
expectedDelay = int(item.expectedDelay)
|
806 |
expectedDelay = int(item.expectedDelay)
|
| 848 |
|
807 |
|
| 849 |
if total_availability <= 0:
|
808 |
if total_availability <= 0:
|
| 850 |
expectedDelay = expectedDelay + __get_expected_procurement_delay(item)
|
809 |
expectedDelay = expectedDelay + __get_expected_procurement_delay(item)
|
| 851 |
expectedDelay = expectedDelay + __get_vendor_holiday_delay(item, expectedDelay)
|
810 |
expectedDelay = expectedDelay + __get_vendor_holiday_delay(item, expectedDelay)
|
| - |
|
811 |
|
| - |
|
812 |
if warehouse.transferDelayInHours:
|
| - |
|
813 |
expectedDelay += warehouse.transferDelayInHours / 24
|
| 852 |
|
814 |
|
| 853 |
item_availability_cache = ItemAvailabilityCache.get_by(itemId=item_id)
|
815 |
item_availability_cache = ItemAvailabilityCache.get_by(itemId=item_id)
|
| 854 |
if item_availability_cache is None:
|
816 |
if item_availability_cache is None:
|
| 855 |
item_availability_cache = ItemAvailabilityCache()
|
817 |
item_availability_cache = ItemAvailabilityCache()
|
| 856 |
item_availability_cache.itemId = item_id
|
818 |
item_availability_cache.itemId = item_id
|
| 857 |
item_availability_cache.warehouseId = int(warehouse_retid)
|
819 |
item_availability_cache.warehouseId = int(warehouse_retid)
|
| 858 |
item_availability_cache.expectedDelay = expectedDelay
|
820 |
item_availability_cache.expectedDelay = expectedDelay
|
| 859 |
item_availability_cache.billingWarehouseId = billingWarehouseId
|
821 |
item_availability_cache.billingWarehouseId = billingWarehouseId
|
| 860 |
item_availability_cache.sellingPrice = item.sellingPrice
|
822 |
item_availability_cache.sellingPrice = item.sellingPrice
|
| 861 |
session.commit()
|
823 |
session.commit()
|
| - |
|
824 |
|
| - |
|
825 |
def __get_warehouse_with_min_transfer_price(warehouses, item, item_pricing, ignoreAvailability):
|
| - |
|
826 |
warehouse_retid = -1
|
| - |
|
827 |
minTransferPrice = None
|
| - |
|
828 |
total_availability = 0
|
| - |
|
829 |
warehousesWithAvailability = {}
|
| 862 |
|
830 |
|
| - |
|
831 |
if not ignoreAvailability:
|
| - |
|
832 |
if item.currentInventory:
|
| - |
|
833 |
for entry in item.currentInventory:
|
| - |
|
834 |
if entry.availibility > entry.reserved:
|
| - |
|
835 |
warehousesWithAvailability[entry.warehouse_id] = entry
|
| - |
|
836 |
|
| - |
|
837 |
for warehouse in warehouses.values():
|
| - |
|
838 |
if not ignoreAvailability:
|
| - |
|
839 |
if warehousesWithAvailability.has_key(warehouse.id):
|
| - |
|
840 |
entry = warehousesWithAvailability[warehouse.id]
|
| - |
|
841 |
total_availability += entry.availibility - entry.reserved
|
| - |
|
842 |
else:
|
| - |
|
843 |
continue
|
| - |
|
844 |
|
| - |
|
845 |
# Missing transfer price cases should not impact warehouse assignment
|
| - |
|
846 |
transferPrice = None
|
| - |
|
847 |
if item_pricing.has_key(warehouse.vendor_id):
|
| - |
|
848 |
transferPrice = item_pricing[warehouse.vendor_id].transfer_price
|
| - |
|
849 |
if minTransferPrice is None or (transferPrice and minTransferPrice > transferPrice):
|
| - |
|
850 |
warehouse_retid = warehouse.id
|
| - |
|
851 |
minTransferPrice = transferPrice
|
| - |
|
852 |
|
| - |
|
853 |
return [warehouse_retid, total_availability]
|
| - |
|
854 |
|
| - |
|
855 |
def __get_warehouse_with_min_transfer_delay(warehouses, item, item_pricing):
|
| - |
|
856 |
minTransferDelay = None
|
| - |
|
857 |
minTransferDelayWarehouses = {}
|
| - |
|
858 |
total_availability = 0
|
| - |
|
859 |
|
| - |
|
860 |
if item.currentInventory:
|
| - |
|
861 |
for entry in item.currentInventory:
|
| - |
|
862 |
if warehouses.has_key(entry.warehouse_id):
|
| - |
|
863 |
warehouse = warehouses[entry.warehouse_id]
|
| - |
|
864 |
if entry.availibility > entry.reserved:
|
| - |
|
865 |
total_availability += entry.availibility - entry.reserved
|
| - |
|
866 |
transferDelay = warehouse.transferDelayInHours
|
| - |
|
867 |
if minTransferDelay is None or minTransferDelay >= transferDelay:
|
| - |
|
868 |
if minTransferDelay != transferDelay:
|
| - |
|
869 |
minTransferDelayWarehouses = {}
|
| - |
|
870 |
minTransferDelayWarehouses[warehouse.id] = warehouse
|
| - |
|
871 |
minTransferDelay = transferDelay
|
| - |
|
872 |
|
| - |
|
873 |
return [__get_warehouse_with_min_transfer_price(minTransferDelayWarehouses, item, item_pricing, False)[0], total_availability]
|
| - |
|
874 |
|
| 863 |
def __get_warehouse_with_max_availability(warehouse_ids, item):
|
875 |
def __get_warehouse_with_max_availability(warehouse_ids, item):
|
| 864 |
warehouse_retid = -1
|
876 |
warehouse_retid = -1
|
| 865 |
max_availability = 0
|
877 |
max_availability = 0
|
| 866 |
total_availability = 0
|
878 |
total_availability = 0
|
| 867 |
|
879 |
|
| Line 914... |
Line 926... |
| 914 |
if holidayDate >= currentDate and holidayDate <= expectedDate:
|
926 |
if holidayDate >= currentDate and holidayDate <= expectedDate:
|
| 915 |
holidayDelay = holidayDelay + 1
|
927 |
holidayDelay = holidayDelay + 1
|
| 916 |
except Exception as e:
|
928 |
except Exception as e:
|
| 917 |
print e
|
929 |
print e
|
| 918 |
return holidayDelay
|
930 |
return holidayDelay
|
| - |
|
931 |
|
| 919 |
def get_warehouses_for_item(item_id):
|
932 |
def get_warehouses_for_item(item_id):
|
| 920 |
|
933 |
|
| 921 |
if not item_id:
|
934 |
if not item_id:
|
| 922 |
raise InventoryServiceException(101, "bad item_id")
|
935 |
raise InventoryServiceException(101, "bad item_id")
|
| 923 |
item = get_item(item_id)
|
936 |
item = get_item(item_id)
|
| Line 1176... |
Line 1189... |
| 1176 |
'''
|
1189 |
'''
|
| 1177 |
if(vendorId == -1):
|
1190 |
if(vendorId == -1):
|
| 1178 |
total = 0
|
1191 |
total = 0
|
| 1179 |
try:
|
1192 |
try:
|
| 1180 |
item_pricings = []
|
1193 |
item_pricings = []
|
| 1181 |
if item.preferredWarehouse is not None:
|
1194 |
if item.preferredVendor is not None:
|
| 1182 |
warehouse = Warehouse.query.filter_by(id=item.preferredWarehouse).first()
|
- |
|
| 1183 |
item_pricing = VendorItemPricing.query.filter_by(item=item, vendor=warehouse.vendor).first()
|
1195 |
item_pricing = VendorItemPricing.query.filter_by(item=item, vendor_id=item.preferredVendor).first()
|
| 1184 |
if item_pricing:
|
1196 |
if item_pricing:
|
| 1185 |
item_pricings.append(item_pricing)
|
1197 |
item_pricings.append(item_pricing)
|
| 1186 |
else :
|
1198 |
else :
|
| 1187 |
item_pricings = VendorItemPricing.query.filter_by(item=item).all()
|
1199 |
item_pricings = VendorItemPricing.query.filter_by(item=item).all()
|
| 1188 |
if item_pricings:
|
1200 |
if item_pricings:
|