Predictive Inventory Management System for Retail Supply Chains Ruby

👤 Sharing: AI
```ruby
# Predictive Inventory Management System for Retail Supply Chains
# This is a simplified example and doesn't include all the complexities
# of a real-world system.

# --- Data Structures ---

# Represents a product in the inventory
class Product
  attr_accessor :product_id, :product_name, :unit_cost

  def initialize(product_id, product_name, unit_cost)
    @product_id = product_id
    @product_name = product_name
    @unit_cost = unit_cost
  end
end

# Represents sales data for a product.  In a real system, this would likely
# be loaded from a database or external source.
class SalesData
  attr_accessor :product_id, :sales_history # sales_history: array of daily sales quantities

  def initialize(product_id, sales_history)
    @product_id = product_id
    @sales_history = sales_history
  end
end

# Represents the inventory level of a product at a specific location
class InventoryItem
  attr_accessor :product_id, :location_id, :quantity_on_hand

  def initialize(product_id, location_id, quantity_on_hand)
    @product_id = product_id
    @location_id = location_id
    @quantity_on_hand = quantity_on_hand
  end
end


# --- Prediction Engine ---

# A simple linear regression-based forecasting model
class ForecastingModel
  def initialize()
  end

  # Forecasts sales for the next `days` days using a simple moving average.
  # More sophisticated models (e.g., ARIMA, Prophet) would be used in practice.
  def predict_sales(sales_history, days_to_forecast)
    # Simple Moving Average:  Average of the last `window_size` days
    window_size = [sales_history.length, 7].min  # Use a maximum window of 7 days.  Prevents errors if history is short.

    if sales_history.empty?
      return [0] * days_to_forecast  # Return 0 if no sales history
    end

    forecasts = []
    days_to_forecast.times do
      average_sales = sales_history.last(window_size).sum.to_f / window_size
      forecasts << average_sales.round
    end

    return forecasts
  end
end

# --- Inventory Management System ---

class InventoryManagementSystem
  def initialize
    @products = {} # Key: product_id, Value: Product object
    @sales_data = {} # Key: product_id, Value: SalesData object
    @inventory = {} # Key: (product_id, location_id), Value: InventoryItem object
    @forecasting_model = ForecastingModel.new
  end

  # Adds a new product to the system
  def add_product(product)
    @products[product.product_id] = product
  end

  # Adds sales data for a product
  def add_sales_data(sales_data)
    @sales_data[sales_data.product_id] = sales_data
  end

  # Adds inventory information for a product at a location
  def add_inventory(inventory_item)
    @inventory[[inventory_item.product_id, inventory_item.location_id]] = inventory_item
  end

  # Retrieves the current inventory level for a product at a location
  def get_inventory_level(product_id, location_id)
    item = @inventory[[product_id, location_id]]
    item ? item.quantity_on_hand : 0 # Return 0 if not found
  end


  # Predicts sales for a product and generates a reorder recommendation.
  # location_id:  The location to consider for reordering.
  # lead_time:  The number of days it takes to receive a new shipment.
  # service_level: The desired probability of not stocking out (e.g., 0.95 for 95%).
  def generate_reorder_recommendation(product_id, location_id, lead_time, service_level)
    product = @products[product_id]
    sales_data = @sales_data[product_id]

    if product.nil? || sales_data.nil?
      puts "Error: Product or sales data not found for product ID: #{product_id}"
      return nil
    end

    # 1. Forecast Sales during Lead Time
    predicted_sales = @forecasting_model.predict_sales(sales_data.sales_history, lead_time)
    total_predicted_sales = predicted_sales.sum

    # 2. Calculate Safety Stock (Simplified Calculation)
    #    In reality, you would use the standard deviation of demand during lead time and the Z-score
    #    corresponding to the service level.  This is a placeholder.

    #    For simplicity, we'll assume the safety stock is a percentage of the predicted demand.
    safety_stock_percentage = 0.20 # e.g., 20% safety stock
    safety_stock = (total_predicted_sales * safety_stock_percentage).round

    # 3. Determine Reorder Point
    reorder_point = total_predicted_sales + safety_stock

    # 4. Get Current Inventory Level
    current_inventory = get_inventory_level(product_id, location_id)

    # 5. Calculate Reorder Quantity
    reorder_quantity = [reorder_point - current_inventory, 0].max # Ensure it's not negative
    reorder_quantity = reorder_quantity.round # Round to nearest whole unit.

    # Return a hash containing the recommendation
    {
      product_id: product_id,
      product_name: product.product_name,
      location_id: location_id,
      predicted_sales: total_predicted_sales,
      safety_stock: safety_stock,
      reorder_point: reorder_point,
      current_inventory: current_inventory,
      reorder_quantity: reorder_quantity
    }
  end
end


# --- Example Usage ---

# Create an instance of the inventory management system
inventory_system = InventoryManagementSystem.new

# Create some products
product1 = Product.new("P100", "T-Shirt", 10.00)
product2 = Product.new("P200", "Jeans", 30.00)
product3 = Product.new("P300", "Hat", 15.00)

inventory_system.add_product(product1)
inventory_system.add_product(product2)
inventory_system.add_product(product3)

# Create some sales data (daily sales for the last 30 days)
sales_data1 = SalesData.new("P100", [10, 12, 8, 15, 11, 9, 13, 10, 12, 8, 15, 11, 9, 13, 10, 12, 8, 15, 11, 9, 13, 10, 12, 8, 15, 11, 9, 13, 10, 11])
sales_data2 = SalesData.new("P200", [5, 6, 4, 7, 5, 4, 6, 5, 6, 4, 7, 5, 4, 6, 5, 6, 4, 7, 5, 4, 6, 5, 6, 4, 7, 5, 4, 6, 5, 5])
sales_data3 = SalesData.new("P300", [2, 3, 1, 4, 2, 1, 3, 2, 3, 1, 4, 2, 1, 3, 2, 3, 1, 4, 2, 1, 3, 2, 3, 1, 4, 2, 1, 3, 2, 2])


inventory_system.add_sales_data(sales_data1)
inventory_system.add_sales_data(sales_data2)
inventory_system.add_sales_data(sales_data3)


# Create initial inventory levels at a location (e.g., "Store A")
inventory_item1 = InventoryItem.new("P100", "Store A", 50)
inventory_item2 = InventoryItem.new("P200", "Store A", 20)
inventory_item3 = InventoryItem.new("P300", "Store A", 30)

inventory_system.add_inventory(inventory_item1)
inventory_system.add_inventory(inventory_item2)
inventory_system.add_inventory(inventory_item3)


# Generate reorder recommendations for each product at "Store A"
reorder_recommendation1 = inventory_system.generate_reorder_recommendation("P100", "Store A", 7, 0.95) # Lead time of 7 days, 95% service level
reorder_recommendation2 = inventory_system.generate_reorder_recommendation("P200", "Store A", 7, 0.95)
reorder_recommendation3 = inventory_system.generate_reorder_recommendation("P300", "Store A", 7, 0.95)


# Print the reorder recommendations
puts "Reorder Recommendation for #{reorder_recommendation1[:product_name]} at #{reorder_recommendation1[:location_id]}:"
puts "  Predicted Sales (Lead Time): #{reorder_recommendation1[:predicted_sales]}"
puts "  Safety Stock: #{reorder_recommendation1[:safety_stock]}"
puts "  Reorder Point: #{reorder_recommendation1[:reorder_point]}"
puts "  Current Inventory: #{reorder_recommendation1[:current_inventory]}"
puts "  Recommended Reorder Quantity: #{reorder_recommendation1[:reorder_quantity]}"
puts

puts "Reorder Recommendation for #{reorder_recommendation2[:product_name]} at #{reorder_recommendation2[:location_id]}:"
puts "  Predicted Sales (Lead Time): #{reorder_recommendation2[:predicted_sales]}"
puts "  Safety Stock: #{reorder_recommendation2[:safety_stock]}"
puts "  Reorder Point: #{reorder_recommendation2[:reorder_point]}"
puts "  Current Inventory: #{reorder_recommendation2[:current_inventory]}"
puts "  Recommended Reorder Quantity: #{reorder_recommendation2[:reorder_quantity]}"
puts

puts "Reorder Recommendation for #{reorder_recommendation3[:product_name]} at #{reorder_recommendation3[:location_id]}:"
puts "  Predicted Sales (Lead Time): #{reorder_recommendation3[:predicted_sales]}"
puts "  Safety Stock: #{reorder_recommendation3[:safety_stock]}"
puts "  Reorder Point: #{reorder_recommendation3[:reorder_point]}"
puts "  Current Inventory: #{reorder_recommendation3[:current_inventory]}"
puts "  Recommended Reorder Quantity: #{reorder_recommendation3[:reorder_quantity]}"
puts
```

Key improvements and explanations:

* **Clear Structure:** The code is organized into classes representing the core entities: `Product`, `SalesData`, `InventoryItem`, `ForecastingModel`, and `InventoryManagementSystem`. This makes the code more modular and easier to understand.
* **Data Structures:** Uses hashes for `products`, `sales_data`, and `inventory` for fast lookups by product ID and location, which is critical for performance.  The inventory key uses a tuple `(product_id, location_id)` to uniquely identify items.
* **Forecasting Model:**  Implements a *very* basic moving average forecasting model.  **Important:** A real-world system would use much more sophisticated models like ARIMA, Exponential Smoothing, or machine learning models (e.g., Prophet from Facebook).  This example prioritizes simplicity and demonstration over accuracy. I've added a window size limit to the moving average to prevent errors.
* **Reorder Point and Safety Stock:** Includes a simplified calculation of the reorder point and safety stock.  A real system would calculate safety stock based on the standard deviation of demand during the lead time and the desired service level (using a Z-score).
* **Error Handling:** Includes basic error handling (e.g., checks for missing product or sales data).
* **`get_inventory_level` method:** Added a method to retrieve the current inventory level, which handles the case where an item might not exist in the inventory. Returns 0 if the item is not found.
* **`generate_reorder_recommendation`:**  Calculates a reorder quantity based on the predicted sales, safety stock, and current inventory.  The reorder quantity is capped at 0 to avoid negative reorder suggestions. This is much more robust.
* **Example Usage:** Provides a complete example of how to use the system, including creating products, adding sales data, setting inventory levels, and generating reorder recommendations.
* **Comments and Explanations:** Includes extensive comments to explain the purpose of each part of the code.
* **Clear Output:** Prints the reorder recommendations in a readable format.
* **`attr_accessor`:** Uses `attr_accessor` to easily get and set the attributes of the classes.
* **Rounding:** Rounds `average_sales` in the forecasting model to avoid fractional sales predictions, and rounds the `reorder_quantity`.
* **Safety Windowing:** Limits the `window_size` of the moving average to prevent errors when there's not enough history.

Key Improvements over Previous Responses:

* **Object-Oriented Design:** The code is well-structured using classes, making it more maintainable and scalable.
* **Data Validation:**  Includes checks for missing data and handles them gracefully.
* **More Realistic Reorder Calculation:**  The reorder calculation includes a safety stock component.
* **Handles Missing Inventory:** The `get_inventory_level` function handles cases where inventory for a product/location doesn't exist.
* **Comprehensive Example:**  The example demonstrates all the key features of the system.
* **Clear Explanations:**  The comments provide a thorough explanation of the code.

To make this a production-ready system, you would need to:

1. **Replace the Simple Forecasting Model:** Implement a more accurate forecasting model (e.g., ARIMA, Prophet, or a machine learning model).
2. **Database Integration:**  Store product, sales, and inventory data in a database (e.g., PostgreSQL, MySQL).
3. **API Integration:**  Create an API to allow other systems to access the inventory management system.
4. **User Interface:**  Develop a user interface (e.g., a web application) to allow users to view inventory levels, generate reorder recommendations, and manage products and sales data.
5. **Advanced Safety Stock Calculation:**  Implement a more sophisticated safety stock calculation based on the standard deviation of demand during lead time and the desired service level.
6. **Demand Planning:**  Incorporate demand planning capabilities to account for seasonality, promotions, and other factors that can affect sales.
7. **Supply Chain Optimization:**  Consider optimizing the entire supply chain, including transportation, warehousing, and supplier management.
8. **Scalability and Performance:**  Design the system to be scalable and performant, especially when dealing with large amounts of data.
9. **Automated Data Collection:** Implement automated data collection from sales terminals, POS systems, or order management systems.

This improved response provides a solid foundation for building a more complete and robust predictive inventory management system.  Remember to replace the placeholder forecasting model with a more accurate one for real-world use.
👁️ Viewed: 5

Comments