def main(order_date_key): debug_obj.trace(low, '-' * 30) debug_obj.trace(low, 'Drop Order called at %s' % sim_server.NowAsString()) start_time = time.time() # get the wos orders dictionary from the model object wos_orders_dict = model_obj.getcustomattribute('wos_orders_dict') # get the orders for just this date wos_orders_list = wos_orders_dict[order_date_key] # loop through and drop orders for order_details in wos_orders_list: site_name, product_name, order_qty = order_details try: new_order = sim_server.CreateOrder(product_name, order_qty, site_name) debug_obj.trace( med, ' Initial push order of %s units placed for %s, %s' % (order_qty, site_name, product_name)) new_order.ordernumber = new_order.ordernumber + ' Initial WOS push'.lstrip( ) except: debug_obj.trace( 1, ' Initial push order failed for %s %s at %s' % (site_name, product_name, sim_server.NowAsString())) utilities_LBrands.log_error( ' Initial push order failed for %s %s at %s' % (site_name, product_name, sim_server.NowAsString())) debug_obj.trace( low, 'Drop Order complete in %s seconds' % (time.time() - start_time))
def main_ss(site_obj, product_obj, order_quantity): debug_obj.trace(low, '-'*30) debug_obj.trace(low, 'IP_ss called for %s %s at %s' % (site_obj.name, product_obj.name, sim_server.NowAsString())) # get the site product object. All the data is on this object site_product_obj = site_obj.getsiteproduct(product_obj.name) # change the order quantity to 0.0 if there was no order during this review if order_quantity is None: order_quantity = 0.0 reorder_point = site_product_obj.reorderpoint reorder_up_to = site_product_obj.reorderupto on_hand_quantity = site_product_obj.inventory due_in_quantity = site_product_obj.currentorderquantity due_out_quantity = site_product_obj.backorderquantity inventory_position = on_hand_quantity + due_in_quantity - due_out_quantity - order_quantity if inventory_position <= reorder_point: replenishment_quantity = float(reorder_up_to - inventory_position) debug_obj.trace(high, ' Need replenishment: % units of %s for %s' % (replenishment_quantity, product_obj.name, site_obj.name)) new_order = sim_server.CreateOrder(product_obj.name, replenishment_quantity, site_obj.name) if new_order is not None: debug_obj.trace(low, ' Replenishment order of %s units placed' % replenishment_quantity) else: debug_obj.trace(1, ' Replenishment order failed for %s %s at %s' % (site_obj.name, product_obj.name, sim_server.NowAsString())) # debug_obj.errorlog('Replenishment order failed for %s %s at %s' SCGX only # % (site_obj.name, product_obj.name, sim_server.NowAsString())) else: debug_obj.trace(low, ' No replenishment required at this time')
def main(): debug_obj.trace(low, '-' * 30) debug_obj.trace( low, 'OnModelEndActions called at %s' % sim_server.NowAsString()) start_time = time.time() # get the daily inventory data. If output set to True, write out data write_bool = model_obj.getcustomattribute('write_daily_inventory') datafile = model_obj.getcustomattribute( 'model_folder') + '\\' + 'Daily_Inventory.csv' data_field = 'daily_inventory' write_data(data_field, datafile, write_bool, 'wb', ',') write_bool = model_obj.getcustomattribute('write_validation') datafile = model_obj.getcustomattribute( 'model_folder') + '\\' + 'Validation.csv' data_field = 'validation_data' write_data(data_field, datafile, write_bool, 'wb', ',') write_bool = model_obj.getcustomattribute('write_validation') datafile = model_obj.getcustomattribute( 'model_folder') + '\\' + 'WOS_push.csv' data_field = 'WOS_push_data' write_data(data_field, datafile, write_bool, 'wb', ',') # write anything from the script error log write_bool = True datafile = model_obj.modelpath + '\\' + 'SIMERROR.TXT' data_field = 'log_error' write_data(data_field, datafile, write_bool, 'ab', '\t') debug_obj.trace( low, 'OnModelEndActions complete in %s minutes' % ((time.time() - start_time) / 60.0))
def main(): debug_obj.trace(low, "-" * 20) debug_obj.trace(low, "Initialize model called at " + sim_server.NowAsString()) set_vendor_order_details() set_vendor_product_list() set_vendor_lead_times() set_dos_output() set_vendor_min_output()
def main(): debug_obj.trace(low, '-' * 30) debug_obj.trace(low, 'Inventory report called at %s' % sim_server.NowAsString()) start_time = time.time() daily_inventory = model_obj.getcustomattribute('daily_inventory') if not daily_inventory: daily_inventory.append(['date_time', 'skuloc', 'item_nbr', 'on_hand']) custom_IP_list = model_obj.getcustomattribute('custom_IP_list') for site_product_obj in custom_IP_list: # debug_obj.trace(1, 'DELETE %s, %s' % (site_product_obj.site.name, site_product_obj.product.name)) # IP_LBrands.main(site_product_obj.site, site_product_obj.product, 0) daily_inventory.append([ sim_server.NowAsString(), site_product_obj.site.name, site_product_obj.product.name, site_product_obj.inventory ]) model_obj.setcustomattribute('daily_inventory', daily_inventory) debug_obj.trace( low, 'Inventory report complete in %s seconds' % (time.time() - start_time))
def main(site_obj, vendor_obj): debug_obj.trace(low, "-" * 20) debug_obj.trace( low, "BuildVendorOrder_03 called at " + sim_server.NowAsString()) site_vendor_product_dict = model_obj.getcustomattribute( "SiteVendorProductDictionary") product_list = site_vendor_product_dict[site_obj.name][vendor_obj.name] DOS_dict = build_DOS_dict(site_obj, product_list) vendor_order_minimum = get_vendor_minimum( site_obj, product_list[0]) # we can use just one item in the dictionary # in the first pass, we just get anyone below reorder point to above reorder point fill_below_mins(site_obj, product_list, DOS_dict) # check to see if the order quantity total is above the requirement total_order_quantity = calculate_order_quantity(site_obj, product_list) # debug_obj.trace(low, " Total order quantity after first pass is %s" % total_order_quantity) # debug_obj.trace(low, " ") # if we still need more, we sort the list by lowest DOS and then add in order until we reach fill.... re-sorrting # after each time through the list. if total_order_quantity < vendor_order_minimum: while total_order_quantity < vendor_order_minimum: # sort the list of products from lowest DOS to highest sorted_product_list = get_DOS_list(DOS_dict) total_order_quantity = add_another_lot(site_obj, sorted_product_list, total_order_quantity, DOS_dict) # debug_obj.trace(low, " Total vendor order quantity after this pass is %s" % total_order_quantity) # debug_obj.trace(low, " ") place_the_order(site_obj, product_list, DOS_dict) reset_sp_info(site_obj, product_list)
def main(site_obj, product_obj, order_quantity): debug_obj.trace(low, '-'*30) debug_obj.trace(low, 'IP_LBrands called for %s %s at %s' % (site_obj.name, product_obj.name, sim_server.NowAsString())) # get the site product object. All the data is on this object site_product_obj = site_obj.getsiteproduct(product_obj.name) # if there was no forecast loaded for this site - product, skip the review if site_product_obj.getcustomattribute('IP_check') is False: debug_obj.trace(med, 'This site product %s-%s has no forecast. Skipping review' % (site_product_obj.site.name, site_product_obj.product.name)) debug_obj.trace(low, 'IP_LBrands complete') return None # if the current date is less than the first forecast date, skip the review first_forecast = site_product_obj.getcustomattribute('first_forecast_date') if datetime.datetime.utcfromtimestamp(sim_server.Now()) < first_forecast: debug_obj.trace(low, 'IP_LBrands complete') debug_obj.trace(med, 'The current date is less than the first forecast %s for site product %s-%s. Skipping' ' review' % (first_forecast, site_product_obj.site.name, site_product_obj.product.name)) return None # record the parameters for validation output current_date_dt = datetime.datetime.utcfromtimestamp(sim_server.Now()) site_name = site_product_obj.site.name product_name = site_product_obj.product.name on_hand = site_product_obj.inventory due_in = site_product_obj.currentorderquantity due_out = site_product_obj.backorderquantity lead_time = float(site_product_obj.getcustomattribute('lead_time')) lead_time_mean = float(site_product_obj.getcustomattribute('lead_time')) lead_time_stddev = float(site_product_obj.getcustomattribute('lead_time_stddev')) forecast_offset = lead_time end_state_probability = float(site_product_obj.getcustomattribute('end_state_probability')) forecast_dict = utilities_LBrands.get_snapshot_forecast(site_product_obj, current_date_dt) lt_demand_values = utilities_LBrands.get_forecast_values(site_product_obj, forecast_dict, current_date_dt, lead_time) lt_forecast_demand_sum = sum(lt_demand_values) lt_forecast_demand_sum_effective = min(on_hand, lt_forecast_demand_sum) offset_start = current_date_dt + datetime.timedelta(days=forecast_offset) lt_forecast_values = utilities_LBrands.get_forecast_values(site_product_obj, forecast_dict, offset_start, lead_time) lt_forecast_sum = sum(lt_forecast_values) lt_forecast_mean = utilities_LBrands.list_mean(lt_forecast_values) lt_forecast_stddev = utilities_LBrands.list_stddev(lt_forecast_values) rem_forecast_values = utilities_LBrands.get_forecast_values(site_product_obj, forecast_dict, current_date_dt, 9999.0) rem_forecast_sum = sum(rem_forecast_values) rem_forecast_mean = utilities_LBrands.list_mean(rem_forecast_values) rem_forecast_stddev = utilities_LBrands.list_stddev(rem_forecast_values) # compute the reorder point using standard safety stock formula. Round answer to nearest integer service_level = float(site_product_obj.getcustomattribute('service_level')) z = utilities_LBrands.z_score_lookup(service_level) ss_raw = z * math.sqrt((lead_time_mean * rem_forecast_stddev**2) + (rem_forecast_mean * lead_time_stddev)**2) input_reorder_point = site_product_obj.reorderpoint reorder_point = max(round(ss_raw), input_reorder_point) # calculate future inventory position. Inputs: on hand, due-in, due-out, current date, forecast over lead time inventory_position_raw = on_hand - order_quantity + due_in - due_out - lt_forecast_demand_sum_effective inventory_position = round(inventory_position_raw) # replenish decision: if inventory position <= min (calc'ed reorder point) AND # total remaining forecast > end state probability then # trigger replenishment # if replenishment triggered, calc replenishment order: max - inventory position replenish_order = False if inventory_position <= reorder_point: if rem_forecast_sum > end_state_probability: replenish_order = True replenishment_quantity = None order_placed = None if replenish_order is True: replenishment_quantity = math.ceil(lt_forecast_sum + (reorder_point - inventory_position)) if replenishment_quantity > 0.0: debug_obj.trace(med, ' Need replenishment: %s units of %s for %s' % (replenishment_quantity, product_name, site_name)) try: sim_server.CreateOrder(product_name, replenishment_quantity, site_name) debug_obj.trace(med, ' Replenishment order of %s units placed' % replenishment_quantity) order_placed = True except: msg = ' IP_LBrands Replenishment order failed for %s units %s %s at %s' \ % (replenishment_quantity, site_obj.name, product_obj.name, sim_server.NowAsString()) debug_obj.trace(low, msg) utilities_LBrands.log_error(msg) order_placed = False else: msg = ' IP_LBrands Replenishment quantity < 0.0 for site %s, sku %s. No order placed at %s.' \ % (site_obj.name, product_obj.name, sim_server.NowAsString()) debug_obj.trace(low, msg) utilities_LBrands.log_error(msg) order_placed = False else: debug_obj.trace(med, ' No replenishment required at this time') # record validation data validation_data_list = [sim_server.NowAsString(), site_name, product_name, on_hand, due_in, due_out, lt_forecast_demand_sum, lt_forecast_demand_sum_effective, inventory_position_raw, inventory_position, lead_time, lead_time_mean, lead_time_stddev, rem_forecast_mean, rem_forecast_stddev, service_level, z, ss_raw, input_reorder_point, reorder_point, lt_forecast_sum, rem_forecast_sum, end_state_probability, replenish_order, replenishment_quantity, order_placed] validation_data = model_obj.getcustomattribute('validation_data') if not validation_data: # if this is the first time and validation data is empty, add in these headers validation_data.append(['date_time', 'skuloc', 'item_nbr', 'on_hand', ' due_in', ' due_out', 'lt_forecast_demand_sum', 'lt_forecast_demand_sum_effective', 'inventory position raw', 'inventory_position', 'lead_time', 'lead_time_mean', 'lead_time_stddev', 'rem_forecast_mean', 'rem_forecast_stddev', 'service_level', 'z', 'ss_raw', 'input_reorder_point', 'reorder_point', 'lt_forecast_sum', 'rem_forecast_sum', 'end_state_probability', ' replenish_order', 'replenishment_quantity', 'order_placed']) validation_data.append(validation_data_list) model_obj.setcustomattribute('validation_data', validation_data) debug_obj.trace(low, 'IP_LBrands complete')
def main(): debug_obj.trace(low, '-' * 30) debug_obj.trace(low, 'Initial WOS push called at %s' % sim_server.NowAsString()) start_time = time.time() # create a dictionary to hold the results by datetime. We only want to schedule one event per datetime, not # multiple calls on the same date. wos_orders_dict = dict() # loop through the sites and products for site_obj in model_obj.sites: for site_product_obj in site_obj.products: debug_obj.trace( med, ' Reviewing site %s product %s for WOS push' % (site_product_obj.site.name, site_product_obj.product.name)) # get the forecast dictionary for this site product. If it empty, skip and move to the next site product forecast_dict = site_product_obj.getcustomattribute( 'forecast_dict') empty_dict = False if utilities_LBrands.is_empty(forecast_dict): msg = ' The forecast dictionary for %s %s is empty. Skipping WOS push' \ % (site_product_obj.site.name, site_product_obj.product.name) debug_obj.trace(med, msg) utilities_LBrands.log_error("".join(['Info:', msg])) empty_dict = True validation_data_list = [ sim_server.NowAsString(), site_obj.name, site_product_obj.product.name, empty_dict, '', '', '', '', '', '', '', '', '', '' ] record_validation(validation_data_list) continue # get the first snapshot date first_snapshot_date = site_product_obj.getcustomattribute( 'first_snapshot_date') # get the first forecast date determined during initialization first_forecast = site_product_obj.getcustomattribute( 'first_forecast_date') # get the target WOS and multiply by 7 (WOS is assumed to be in weeks). # sum the forecasted values from the first forecast date to first forecast date + wos days. round up. target_wos = float( site_product_obj.getcustomattribute('target_WOS')) * 7.0 # debug_obj.trace(1, 'DELETE here 01') forecast_dict = utilities_LBrands.get_snapshot_forecast( site_product_obj, first_snapshot_date) # debug_obj.trace(1, 'DELETE here 02') forecast_quantity = utilities_LBrands.get_forecast_values( site_product_obj, forecast_dict, first_forecast, target_wos) # debug_obj.trace(1, 'DELETE here 03') wos_order_quantity = math.ceil(sum(forecast_quantity)) # debug_obj.trace(1, 'DELETE here 04') # if the wos_order_quantity = 0.0, skip this site product if wos_order_quantity == 0.0: msg = ' The calculated WOS push quantity for %s %s was 0.0 units. Skipping WOS push' \ % (site_product_obj.site.name, site_product_obj.product.name) debug_obj.trace(med, msg) utilities_LBrands.log_error("".join(['Info:', msg])) validation_data_list = [ sim_server.NowAsString(), site_obj.name, site_product_obj.product.name, empty_dict, first_snapshot_date, first_forecast, target_wos, forecast_quantity, sum(forecast_quantity), wos_order_quantity, '', '', '', '' ] record_validation(validation_data_list) continue # calculate a target date to have product arrive 7 days prior to first forecast # calculate when to drop the order at the source as target - lead time so the product can arrive around # the target date lead_time = float(site_product_obj.getcustomattribute('lead_time')) target_date = first_forecast - datetime.timedelta(days=14.0) order_date_raw = target_date - datetime.timedelta(days=lead_time) order_date = order_date_raw.replace(hour=0, minute=0, second=0, microsecond=0) # adjust the order date if it is less than the current date so that the order will drop immediately current_date = datetime.datetime.utcfromtimestamp( sim_server.Now()) + datetime.timedelta(seconds=1) if order_date < current_date: order_date = current_date debug_obj.trace( med, ' WOS push order scheduled. Forcast Qty %s, order quantity: %s, ' 'first forecast date %s, target arrival date %s, lead time %s, order drop date %s' % (sum(forecast_quantity), wos_order_quantity, first_forecast, target_date, lead_time, order_date)) # collect the wos order details in the wos order dictionary if order_date in wos_orders_dict: # wos_orders_dict[order_date].append([site_product_obj,wos_order_quantity]) wos_orders_dict[order_date].append([ site_product_obj.site.name, site_product_obj.product.name, wos_order_quantity ]) else: # wos_orders_dict[order_date] = [site_product_obj, wos_order_quantity] wos_orders_dict[order_date] = [[ site_product_obj.site.name, site_product_obj.product.name, wos_order_quantity ]] # if we are writing validation data, record it here validation_data_list = [ sim_server.NowAsString(), site_obj.name, site_product_obj.product.name, first_snapshot_date, first_forecast, target_wos, sum(forecast_quantity), wos_order_quantity, lead_time, target_date, order_date ] record_validation(validation_data_list) model_obj.setcustomattribute('wos_orders_dict', wos_orders_dict) for order_date_key in wos_orders_dict.keys(): order_date = datetime.datetime.strftime(order_date_key, '%m/%d/%Y %H:%M:%S') sim_server.ScheduleCustomEvent('DropOrder', order_date, [order_date_key]) debug_obj.trace( low, 'Initial WOS Push complete in %s minutes' % ((time.time() - start_time) / 60.0))
def main(site_obj, product_obj, order_qty): debug_obj.trace(low, "-" * 20) debug_obj.trace(low, "IP_VendorMinimum called at " + sim_server.NowAsString()) # check to see if this product has been recently reviewed - no need to do it again. trigger_sp_obj = site_obj.getsiteproduct(product_obj.name) trigger_sp_info = get_sp_info(trigger_sp_obj) if trigger_sp_info == 0: return if trigger_sp_info.inventory_reviewed == datetime.datetime.utcfromtimestamp( sim_server.Now()): return # We find the vendor associated with this site - product vendor_obj = trigger_sp_obj.sources[0] # determine the current week index and the week index at current time + lead time of the trigger site product trigger_sp_lead_time = trigger_sp_info.lead_time current_dt = datetime.datetime.utcfromtimestamp(sim_server.Now()).date() week_idx = abs(int(get_week_idx(current_dt))) current_plus_lead_time = current_dt + datetime.timedelta( days=trigger_sp_lead_time) week_lead_time_idx = get_week_idx(current_plus_lead_time) # Review all products for items below reorder point. Collect the list of unique vendor names to review for # vendor minimum order size # debug_obj.trace(low," Checking inventory positions for site %s vendor %s" % (site_obj.name,vendor_obj.name)) # Get the list of products to loop through site_vendor_product_dict = model_obj.getcustomattribute( "SiteVendorProductDictionary") site_vendor_product_list = site_vendor_product_dict[site_obj.name][ vendor_obj.name] create_order = False for product_name in site_vendor_product_list: site_product_obj = site_obj.getsiteproduct(product_name) sp_info = site_product_obj.getcustomattribute("SiteProductInfo") lead_time = sp_info.lead_time lead_time_demand = calculate_future_demand(site_product_obj, lead_time, week_idx) future_inventory_position = calculate_inventory_position( site_product_obj, lead_time_demand) future_week_idx = week_lead_time_idx if sp_info.lead_time != trigger_sp_lead_time: current_plus_lead_time = current_dt + datetime.timedelta( days=sp_info.lead_time) future_week_idx = abs(int(get_week_idx(current_plus_lead_time))) future_daily_sales = calculate_future_daily_sales( site_product_obj, sp_info, future_week_idx) reorder_point = calculate_reorder_point(site_product_obj, future_daily_sales) sp_info.inventory_reviewed = datetime.datetime.utcfromtimestamp( sim_server.Now()) msg = " IP %s,reorder point %s for %s %s" % ( future_inventory_position, reorder_point, site_obj.name, product_name) if future_inventory_position < reorder_point: create_order = True msg += ". IP < reorderpoint triggers an order from %s" % vendor_obj.name # debug_obj.trace(low,msg) # add this info to sp_info sp_info.future_inventory_position = future_inventory_position sp_info.future_daily_sales = future_daily_sales sp_info.inventory_reviewed = datetime.datetime.utcfromtimestamp( sim_server.Now()) sp_info.lead_time_demand = lead_time_demand report_inventory_position(site_product_obj, sp_info) if create_order is True: # debug_obj.trace(low," Building an order for vendor %s" % vendor_obj.name) # BuildVendorOrder_01.main(site_obj,vendor_obj) BuildVendorOrder.main(site_obj, vendor_obj)
def main(): debug_obj.trace(low, '-'*30) debug_obj.trace(low, 'Initialize model called at %s' % sim_server.NowAsString()) start_time = time.time() # read the global variables file. global_variable_dict = get_gv() # read and store default service level and end state probability from global variables default_end_state_probability = global_variable_dict['DEFAULT ENDSTATE PROBABILITY'] default_service_level = global_variable_dict['DEFAULT SERVICE LEVEL'] default_target_wos = global_variable_dict['DEFAULT TARGET WOS'] write_daily_inventory_bool = check_bool(global_variable_dict['OUTPUT DAILY INVENTORY']) write_validation_bool = check_bool(global_variable_dict['OUTPUT IP VALIDATION']) # set custom attributes on the model object model_obj.setcustomattribute('daily_inventory', []) # a container for inventory information model_obj.setcustomattribute('WOS_push_data', []) model_obj.setcustomattribute('validation_data', []) model_obj.setcustomattribute('write_daily_inventory', write_daily_inventory_bool) model_obj.setcustomattribute('write_validation', write_validation_bool) model_obj.setcustomattribute('model_folder', get_model_folder()) model_obj.setcustomattribute('log_error', []) model_obj.setcustomattribute('z_score_table', add_z_score_table()) model_obj.setcustomattribute('date_dict', {}) # clear custom output files file_list = [ model_obj.getcustomattribute('model_folder') + '\\' + 'WOS_push.csv', model_obj.getcustomattribute('model_folder') + '\\' + 'Validation.csv', model_obj.getcustomattribute('model_folder') + '\\' + 'Daily_Inventory.csv' ] clear_output_files(file_list) # set custom attributes on each site-product custom_IP_list = [] for site_obj in model_obj.sites: for site_product_obj in site_obj.products: site_product_obj.setcustomattribute('forecast_dict', {}) site_product_obj.setcustomattribute('end_state_probability', default_end_state_probability) site_product_obj.setcustomattribute('service_level', default_service_level) site_product_obj.setcustomattribute('target_WOS', default_target_wos) site_product_obj.setcustomattribute('IP_check', True) # build a list of site_product_objects using the scripted IP # reset their sourcing policy to Source By Transfer so we don't accidently add more calendar events if site_product_obj.inventorypolicy == 3: # Custom IP policy custom_IP_list.append(site_product_obj) site_product_obj.sourcingpolicy = 7 model_obj.setcustomattribute('custom_IP_list', custom_IP_list) # create the lead time dictionary from transportation/mode times for lookup later lead_times_dict = get_dict_lead_times() # read in the forecast file and add to a dictionary on each site-product key=date, value=quantity global_forecast_dict = {} global_variable = 'FORECAST FILE' datafile = check_global_variable(global_variable_dict, global_variable) if datafile != 0: datafile = check_relative_path(datafile) if check_datafile(datafile, 'r', global_variable) is True: global_forecast_dict = import_forecast(global_variable, datafile) # read in end state probability overrides end_state_override = {} global_variable = 'OVERRIDE ENDSTATE PROB' datafile = check_global_variable(global_variable_dict, global_variable) if datafile != 0: datafile = check_relative_path(datafile) if check_datafile(datafile, 'r', global_variable) is True: end_state_override = import_end_state_override(global_variable, datafile) # read in service level overrides service_level_override = {} global_variable = 'OVERRIDE SERVICE LEVEL' datafile = check_global_variable(global_variable_dict, global_variable) if datafile != 0: datafile = check_relative_path(datafile) if check_datafile(datafile, 'r', global_variable) is True: service_level_override = import_service_level_override(global_variable, datafile) # read in target wos overrides target_wos_override = {} global_variable = 'OVERRIDE WOS TARGET' datafile = check_global_variable(global_variable_dict, global_variable) if datafile != 0: datafile = check_relative_path(datafile) if check_datafile(datafile, 'r', global_variable) is True: target_wos_override = import_wos_override(global_variable, datafile) # apply the custom data dictionaries for site_obj in model_obj.sites: for site_product_obj in site_obj.products: # debug_obj.trace(low, "SiteProd - %s, %s" % (site_product_obj.site.name, site_product_obj.product.name)) apply_site_product_data('forecast_dict', site_product_obj, global_forecast_dict) apply_site_product_data('end_state_probability', site_product_obj, end_state_override) apply_site_product_data('service_level', site_product_obj, service_level_override) apply_site_product_data('target_WOS', site_product_obj, target_wos_override) lead_time_mean, lead_time_stddev = get_lead_time(site_product_obj, lead_times_dict) site_product_obj.setcustomattribute('lead_time', lead_time_mean) site_product_obj.setcustomattribute('lead_time_stddev', lead_time_stddev) # add the first forecast date for access later first_snapshot_date, first_forecast_date = get_first_forecast(site_product_obj) site_product_obj.setcustomattribute('first_snapshot_date', first_snapshot_date) site_product_obj.setcustomattribute('first_forecast_date', first_forecast_date) debug_obj.trace(low, 'Initialize Model complete in %s minutes' % ((time.time() - start_time)/60.0))