Commit 3a79775e authored by Xiaowu Zhang's avatar Xiaowu Zhang Committed by Titouan Soulard

builder: add security stock management

use  "stock definition supply" which overwrite default parameter in
purchase supply for the date included in "valid from" et "valid until"
if the value is not defined in "stock defintion supply", the default
parameter is used
parent 00f9d57b
...@@ -300,62 +300,73 @@ class BuilderMixin(XMLObject, Amount, Predicate): ...@@ -300,62 +300,73 @@ class BuilderMixin(XMLObject, Amount, Predicate):
portal = self.getPortalObject() portal = self.getPortalObject()
if from_date is None: if from_date is None:
from_date = DateTime().earliestTime() from_date = DateTime().earliestTime()
#resource related variable
# Initiate Conditions taken from Yusei T. Original Script
# XXX to be cleaned
min_inventory = supply.getMinStock()
resource_value = supply.getResourceValue() resource_value = supply.getResourceValue()
default_quantity_unit_value = resource_value.getDefaultQuantityUnitValue() default_quantity_unit_value = resource_value.getDefaultQuantityUnitValue()
order_quantity_unit_value = supply.getOrderQuantityUnitValue()
flow_quantity_unit_value = supply.getFlowQuantityUnitValue()
time_quantity_unit_value = supply.getTimeQuantityUnitValue()
time_second_ratio = resource_value.getQuantityUnitDefinitionRatio(portal.portal_categories.quantity_unit.time.second) time_second_ratio = resource_value.getQuantityUnitDefinitionRatio(portal.portal_categories.quantity_unit.time.second)
min_delay = supply.getMinDelay()
max_delay = supply.getMaxDelay()
min_order_delay = supply.getMinOrderDelay()
max_order_delay = supply.getMaxOrderDelay()
min_order = supply.getMinOrderQuantity()
max_order = supply.getMaxOrderQuantity()
# Initiate conversions
# XXX To be cleaned
min_delay_second = 0
max_delay_second = 0
min_order_delay_second = 0
max_order_delay_second = 0
min_order_in_default_quantity_unit = 0
max_order_in_default_quantity_unit = float('inf')
default_quantity_unit_relative_url = default_quantity_unit_value.getCategoryRelativeUrl() default_quantity_unit_relative_url = default_quantity_unit_value.getCategoryRelativeUrl()
if time_quantity_unit_value is not None: def getCorrectSupplyParameter(selected_supply, default_supply, method_id):
time_second_conversion_ratio = resource_value.getQuantityUnitDefinitionRatio(time_quantity_unit_value) / time_second_ratio if selected_supply == default_supply:
return getattr(default_supply, method_id)()
if min_delay: selected_supply_method = getattr(selected_supply, method_id)
min_delay_second = min_delay * time_second_conversion_ratio default_supply_method = getattr(default_supply, method_id)
if max_delay: return selected_supply_method() or default_supply_method()
max_delay_second = max_delay * time_second_conversion_ratio
if min_order_delay: def getMinMaxDelayAndOrderDelay(selected_supply, default_supply):
min_order_delay_second = min_order_delay * time_second_conversion_ratio time_quantity_unit_value = getCorrectSupplyParameter(selected_supply, default_supply, 'getTimeQuantityUnitValue')
if max_delay: min_delay_second = 0
max_order_delay_second = max_order_delay * time_second_conversion_ratio max_delay_second = 0
min_order_delay_second = 0
if order_quantity_unit_value is not None: max_order_delay_second = 0
order_quantity_unit_relative_url = order_quantity_unit_value.getCategoryRelativeUrl() if time_quantity_unit_value is not None:
order_quantity_unit_default_quantity_unit_conversion_ratio = resource_value.convertQuantity(1, order_quantity_unit_relative_url, default_quantity_unit_relative_url) min_delay = getCorrectSupplyParameter(selected_supply, default_supply, 'getMinDelay')
if min_order: max_delay = getCorrectSupplyParameter(selected_supply, default_supply, 'getMaxDelay')
min_order_in_default_quantity_unit = min_order * order_quantity_unit_default_quantity_unit_conversion_ratio min_order_delay = getCorrectSupplyParameter(selected_supply, default_supply, 'getMinOrderDelay')
if max_order: max_order_delay = getCorrectSupplyParameter(selected_supply, default_supply, 'getMaxOrderDelay')
max_order_in_default_quantity_unit = max_order * order_quantity_unit_default_quantity_unit_conversion_ratio time_second_conversion_ratio = resource_value.getQuantityUnitDefinitionRatio(time_quantity_unit_value) / time_second_ratio
else: if min_delay:
min_delay_second = min_delay * time_second_conversion_ratio
if max_delay:
max_delay_second = max_delay * time_second_conversion_ratio
if min_order_delay:
min_order_delay_second = min_order_delay * time_second_conversion_ratio
if max_delay:
max_order_delay_second = max_order_delay * time_second_conversion_ratio
return min_delay_second, max_delay_second, min_order_delay_second, max_order_delay_second
min_delay_second, max_delay_second, min_order_delay_second, max_order_delay_second = getMinMaxDelayAndOrderDelay(supply, supply)
def getOrderQuantityUnitDefaultQuantityUnitConversionRatio(selected_supply, default_supply):
order_quantity_unit_value = getCorrectSupplyParameter(selected_supply, default_supply, 'getOrderQuantityUnitValue')
order_quantity_unit_default_quantity_unit_conversion_ratio = 1 order_quantity_unit_default_quantity_unit_conversion_ratio = 1
#min_order_in_default_quantity_unit = 0
if flow_quantity_unit_value is not None: #max_order_in_default_quantity_unit = float('inf')
flow_quantity_unit_relative_url = flow_quantity_unit_value.getCategoryRelativeUrl() if order_quantity_unit_value is not None:
flow_quantity_unit_default_quantity_unit_conversion_ratio = resource_value.convertQuantity(1, flow_quantity_unit_relative_url, default_quantity_unit_relative_url) order_quantity_unit_relative_url = order_quantity_unit_value.getCategoryRelativeUrl()
default_quantity_unit_flow_quantity_unit_conversion_ratio = 1 / flow_quantity_unit_default_quantity_unit_conversion_ratio order_quantity_unit_default_quantity_unit_conversion_ratio = resource_value.convertQuantity(1, order_quantity_unit_relative_url, default_quantity_unit_relative_url)
else: """
those are not used yet
min_order = supply.getMinOrderQuantity()
max_order = supply.getMaxOrderQuantity()
if min_order:
min_order_in_default_quantity_unit = min_order * order_quantity_unit_default_quantity_unit_conversion_ratio
if max_order:
max_order_in_default_quantity_unit = max_order * order_quantity_unit_default_quantity_unit_conversion_ratio
"""
return order_quantity_unit_default_quantity_unit_conversion_ratio
order_quantity_unit_default_quantity_unit_conversion_ratio = getOrderQuantityUnitDefaultQuantityUnitConversionRatio(supply, supply)
def getDefaultQuantityUnitFlowQuantityUnitConversionRatio(selected_supply, default_supply):
flow_quantity_unit_value = getCorrectSupplyParameter(selected_supply, default_supply, 'getFlowQuantityUnitValue')
default_quantity_unit_flow_quantity_unit_conversion_ratio = 1 default_quantity_unit_flow_quantity_unit_conversion_ratio = 1
if flow_quantity_unit_value is not None:
flow_quantity_unit_relative_url = flow_quantity_unit_value.getCategoryRelativeUrl()
flow_quantity_unit_default_quantity_unit_conversion_ratio = resource_value.convertQuantity(1, flow_quantity_unit_relative_url, default_quantity_unit_relative_url)
default_quantity_unit_flow_quantity_unit_conversion_ratio = 1 / flow_quantity_unit_default_quantity_unit_conversion_ratio
return default_quantity_unit_flow_quantity_unit_conversion_ratio
default_quantity_unit_flow_quantity_unit_conversion_ratio = getDefaultQuantityUnitFlowQuantityUnitConversionRatio(supply, supply)
def getPreviousValidDate(date): def getPreviousValidDate(date):
# We suppose the system has not been configured to handled per hour commands # We suppose the system has not been configured to handled per hour commands
...@@ -366,23 +377,29 @@ class BuilderMixin(XMLObject, Amount, Predicate): ...@@ -366,23 +377,29 @@ class BuilderMixin(XMLObject, Amount, Predicate):
factor=-1)).earliestTime() factor=-1)).earliestTime()
# Function to define the minimal quantity to be ordered # Function to define the minimal quantity to be ordered
def minimalQuantity(quantity, date): def minimalQuantity(selected_supply,default_supply, quantity, date):
# Initiate variables to match original script from Yusei T. # Initiate variables to match original script from Yusei T.
# XXX To be cleaned # XXX To be cleaned
if selected_supply != default_supply:
delay_second = max_delay_second or min_delay_second or 0 local_min_delay_second, local_max_delay_second, local_min_order_delay_second, local_max_order_delay_second = getMinMaxDelayAndOrderDelay(selected_supply, default_supply)
local_order_quantity_unit_default_quantity_unit_conversion_ratio = getOrderQuantityUnitDefaultQuantityUnitConversionRatio(selected_supply, default_supply)
local_order_quantity_unit_value = getCorrectSupplyParameter(selected_supply, default_supply, 'getOrderQuantityUnitValue')
else:
local_min_delay_second, local_max_delay_second, local_min_order_delay_second, local_max_order_delay_second = min_delay_second, max_delay_second, min_order_delay_second, max_order_delay_second
local_order_quantity_unit_default_quantity_unit_conversion_ratio = order_quantity_unit_default_quantity_unit_conversion_ratio
local_order_quantity_unit_value = original_order_quantity_unit_value
delay_second = local_max_delay_second or local_min_delay_second or 0
limit_date = getPreviousValidDate(date) limit_date = getPreviousValidDate(date)
start_date = getPreviousValidDate( start_date = getPreviousValidDate(
addToDate(limit_date, second=-delay_second) addToDate(limit_date, second=-delay_second)
) )
stop_date = addToDate(start_date, second=delay_second).earliestTime() stop_date = addToDate(start_date, second=delay_second).earliestTime()
order_delay_second = max_order_delay_second or min_order_delay_second or 0 order_delay_second = local_max_order_delay_second or local_min_order_delay_second or 0
effective_date = addToDate(start_date, second=-order_delay_second) effective_date = addToDate(start_date, second=-order_delay_second)
order_quantity = ceil(quantity / local_order_quantity_unit_default_quantity_unit_conversion_ratio)
order_quantity = ceil(quantity / order_quantity_unit_default_quantity_unit_conversion_ratio) quantity = order_quantity * local_order_quantity_unit_default_quantity_unit_conversion_ratio
quantity = order_quantity * order_quantity_unit_default_quantity_unit_conversion_ratio return order_quantity, local_order_quantity_unit_value, effective_date, start_date, stop_date, quantity
return order_quantity, order_quantity_unit_value, effective_date, start_date, stop_date, quantity
resource_portal_type = resource_value.getPortalType() resource_portal_type = resource_value.getPortalType()
def newMovement(effective_date, start_date, stop_date, quantity, quantity_unit): def newMovement(effective_date, start_date, stop_date, quantity, quantity_unit):
...@@ -486,17 +503,42 @@ class BuilderMixin(XMLObject, Amount, Predicate): ...@@ -486,17 +503,42 @@ class BuilderMixin(XMLObject, Amount, Predicate):
node_uid=supply.getDestinationUid() node_uid=supply.getDestinationUid()
) + history_list ) + history_list
min_stock_value = supply.getMinOrderQuantity() / default_quantity_unit_flow_quantity_unit_conversion_ratio
factor = supply.getMinFlow()
next_period_history_list = [] next_period_history_list = []
#self.log(limit_date_list)
def chooseCorrectSupply(default_supply,start_date_range_min,start_date_range_max):
search_dict = {
'predicate.start_date_range_min':{'query':start_date_range_min, 'range':'ngt'},
'predicate.start_date_range_max':{'query':start_date_range_max, 'range':'nlt'},
}
stock_definition_supply_list = portal.portal_catalog(
portal_type=('Purchase Supply Cell', 'Purchase Supply Line'),
strict_resource_uid=resource_value.getUid(),
default_ledger_uid=portal.portal_categories.ledger.stock.definition.getUid(),
validation_state='validated',
**search_dict
)
if len(stock_definition_supply_list):
return stock_definition_supply_list[0]
return default_supply
original_min_stock_value = supply.getMinOrderQuantity() / default_quantity_unit_flow_quantity_unit_conversion_ratio
original_factor = supply.getMinFlow()
original_order_quantity_unit_value = supply.getOrderQuantityUnitValue()
# Create a movement per period # Create a movement per period
for period_start_date in limit_date_list: for period_start_date in limit_date_list:
# Prepare history list of the current period # Prepare history list of the current period
next_period_start_date = DateTime(supply.getNextPeriodicalDate( next_period_start_date = DateTime(supply.getNextPeriodicalDate(
period_start_date, period_start_date,
next_start_date=period_start_date)).earliestTime() next_start_date=period_start_date)).earliestTime()
selected_supply = chooseCorrectSupply(default_supply = supply, start_date_range_min = period_start_date, start_date_range_max = next_period_start_date)
#we found a stock definition supply
if selected_supply != supply:
min_stock_value = getCorrectSupplyParameter(selected_supply, supply, 'getMinOrderQuantity') / getDefaultQuantityUnitFlowQuantityUnitConversionRatio(selected_supply, supply)
factor = getCorrectSupplyParameter(selected_supply, supply, 'getMinFlow')
else:
min_stock_value = original_min_stock_value
factor = original_factor
period_history_list = [] period_history_list = []
if next_period_history_list and\ if next_period_history_list and\
...@@ -548,7 +590,7 @@ class BuilderMixin(XMLObject, Amount, Predicate): ...@@ -548,7 +590,7 @@ class BuilderMixin(XMLObject, Amount, Predicate):
if (week_consumption!= 0 or factor) and future_inventory_to_date < min_inventory: if (week_consumption!= 0 or factor) and future_inventory_to_date < min_inventory:
quantity = min_inventory - future_inventory_to_date quantity = min_inventory - future_inventory_to_date
ordered_quantity, ordered_unit, effective_date, start_date, delivery_date, quantity = minimalQuantity(quantity, period_start_date) ordered_quantity, ordered_unit, effective_date, start_date, delivery_date, quantity = minimalQuantity(selected_supply, supply, quantity, period_start_date)
# XXX CLN This is very naive, it has to be optimized # XXX CLN This is very naive, it has to be optimized
if start_date > supply.getStartDateRangeMax(): if start_date > supply.getStartDateRangeMax():
break break
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment