Skip to content

Unconstrained Forecast ​

Introduction ​

Et labore labore et laudantium quidem et molestiae sint est repudiandae rerum est ipsa autem ea unde voluptatum! Est eaque cumque aut amet voluptatem est architecto fugit.

Pre-Conditions ​

  • Masters that should be uploaded
    1. SKU Master
    2. Location Master
    3. Budget Master
    4. BOM Master
  • Global Configurations

Course of Events ​

  1. Retrieve Global Configurations:

    • Fetches the global configurations for the company to determine the time level (time_level_value).
  2. Delete Previous Data:

    • Deletes previous forecast data for the specified scenario and level.
  3. Update Master Data:

    • Updates master data from SKU, BOM, and location masters.
  4. Generate Constrained Forecast If True:

    • If constrained_forecast is True, generates a Level 0 forecast and updates the scenario name accordingly.
  5. Fetch Company Configurations:

    • Retrieves company-specific configurations including base level.
  6. Store Forecast Scenario:

    • Stores the forecast scenario in the database if it's not a constrained forecast.
    • Collection: forecast_scenario
  7. Generate Forecast:

    • Depending on the level parameter, generates the forecast:
      • For a list of levels: Iterates through the levels and generates the forecast for each.
      • For None: Runs forecast from ROS.
      • For a single level: Generates the forecast for the specified level.
    • Sends email notifications if necessary.

Function: run_flexi_forecast ​

Function Steps: ​

1. Notification Initialization: ​

  • Initializes notification and task IDs if the calling function is not norm_generate_func or forecastForInterDC.
  • Initiates a notification for generating the forecast from ROS.
  • Updates the status and user information for the task.

2. Data Retrieval: ​

  • Fetches SKU master data and active SKUs for the company.
  • Retrieves distinct ROS levels and collates them based on the channel collate dictionary.
  • Constructs the match query and group query for sales master data.

3. Data Partitioning: ​

  • Calculates the number of documents in the database and partitions them into multiple parts for parallel processing.

4. Parallel Processing: ​

  • Determines the number of processes to be used based on available cores.
  • Divides the data into arrays for multiprocessing and starts the forecast generation process using the forecast_store function.

5. Stage Completion: ​

  • Completes the stages of data retrieval and forecast generation, and updates the notifications and task statuses.

Helper Function: forecast_store ​

Function Steps: ​

  1. Data Parsing:

    • Parses and processes MongoDB objects.
    • Extracts sales data and constructs dictionaries for ROS values and SKU mappings.
  2. Forecast Calculation:

    • Fetches global configurations for the company.
    • Calls the calcForecastBasedOnBudget function to calculate the forecast based on budget and ROS values.
  3. Forecast Storage:

    • Stores the calculated forecast quantities and updates the forecast data.

Helper Function: calcForecastBasedOnBudget ​

The calcForecastBasedOnBudget function calculates the forecast based on the budget, ROS values, and other parameters.

Function Steps: ​

  1. Retrieve Global Configurations:

    • Fetches the global configurations for the company to determine the time level (time_level_value).
  2. Set Budget Parameters:

    • Sets parameters for budget calculation based on the time level and forecast duration.
  3. SKU Mapping

    • Maps SKU's to various category columns
    • skuCatgMap = getSkuCatgMap(companyId, categoryColumn='category', keyToBe=keyToBe, varcore=varcore)
    • Collection: sku_master
  4. Fetch Budget Data:

    • Fetches all budget data for the company and filters attributes based on budget removal settings.
    • Collection: budget_map
  5. Calculate Forecast:

    • Iterates through store SKUs and calculates the forecast quantity based on ROS values, budget factors, and various configurations.

      1. For a specific SKU-Location-Channel, consider a set of sales history values for N time buckets called group, ordered in descending order of time buckets.
      2. If outlier-correction is true, we compute the range of valid sales history values as,
      py
      min_sales_quantity = mean(group) - (std(group) * outlier_correction_value)
      
      max_sales_quantity = mean(group) + (std(group) * outlier_correction_value)

      Using these range values, we discard values from group that are not included in the range min_sales_quantity, max_sales_quantity (both inclusive)

      py
      group_filtered = [x for x in group if min_sales_quantity <= x <= max_sales_quantity]
      1. Now the latest history_horizon number of values are selected.
      python
      group_filtered_history_horizon = group_filtered[:history_horizon]
      1. Then the forecast is calculated
      py
      forecast_qty=round(float(ROS per day) * float(no of days) * float(budget factor), 5)
      1. Finally, the ROS for the SKU-Location-Channel is saved to the dict as
      py
       sku_store_ros['ros_list'] = sku_store_ros['ros'].str[1]
       sku_store_ros['sale_date_list'] = sku_store_ros['ros'].str[2]
       sku_store_ros['tb_start_date_list'] = sku_store_ros['ros'].str[3]
       sku_store_ros['ros'] = sku_store_ros['ros'].str[0].astype(float)
  6. Store Forecast Data:

    • Stores the calculated forecast data and handles bifurcation store data if provided.
      • ros_list, sale_date_list, tb_start_date_list are exploded using pd.DataFrame.explode() and written to ROS Bifurcated .csv file that is made available for download.
    • Collection: sales_master
  7. Create Forecast Bifurcated File:

  • Exports debug information and no-budget details to CSV files.
  • ROS Bifurcated data is not stored in database.

Exception Handling ​

  • Captures and logs exceptions, ensuring that the notification of the task status is updated to Failed in case of errors.

Validation Checks ​

Post Conditions ​

Exceptions ​

To Find ​

@execute.route('/generate/forecast', methods = ['POST'])

Improvements ​

  • budget_scenario_name=requestJson.get('budget_scenario_name', None) None should not be written