All checks were successful
Dev Build / build-test (pull_request) Successful in 2m12s
95 lines
3.7 KiB
C#
95 lines
3.7 KiB
C#
using Extrudex.Domain.Interfaces;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace Extrudex.Infrastructure.Services;
|
|
|
|
/// <summary>
|
|
/// Detects low-stock filament spools by comparing the remaining weight percentage
|
|
/// against a configurable threshold. The threshold can be set via:
|
|
/// 1. EXTRUDEX_LOW_STOCK_THRESHOLD env var (highest priority, e.g. "25")
|
|
/// 2. FilamentAlerts:LowStockThresholdPercent in appsettings.json
|
|
/// 3. Default: 20% (a standard spool is "low" when ≤20% remains)
|
|
/// </summary>
|
|
public class LowStockDetector : ILowStockDetector
|
|
{
|
|
private readonly ILogger<LowStockDetector> _logger;
|
|
|
|
/// <summary>
|
|
/// The percentage threshold below which a spool is considered low stock.
|
|
/// For example, 20 means a spool is "low" when ≤20% of its filament remains.
|
|
/// </summary>
|
|
public decimal LowStockThresholdPercent { get; }
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="LowStockDetector"/> class.
|
|
/// Reads the low-stock threshold from configuration with env var override support.
|
|
/// </summary>
|
|
/// <param name="configuration">Application configuration for threshold settings.</param>
|
|
/// <param name="logger">Logger for diagnostic output.</param>
|
|
public LowStockDetector(IConfiguration configuration, ILogger<LowStockDetector> logger)
|
|
{
|
|
_logger = logger;
|
|
|
|
// Priority: env var > appsettings > default (20%)
|
|
var envThreshold = Environment.GetEnvironmentVariable("EXTRUDEX_LOW_STOCK_THRESHOLD");
|
|
var configThreshold = configuration.GetValue<decimal?>("FilamentAlerts:LowStockThresholdPercent");
|
|
|
|
if (!string.IsNullOrEmpty(envThreshold) && decimal.TryParse(envThreshold, out var parsedEnv))
|
|
{
|
|
LowStockThresholdPercent = Math.Clamp(parsedEnv, 0m, 100m);
|
|
_logger.LogInformation(
|
|
"Low-stock threshold set from env var EXTRUDEX_LOW_STOCK_THRESHOLD: {Threshold}%",
|
|
LowStockThresholdPercent);
|
|
}
|
|
else if (configThreshold.HasValue)
|
|
{
|
|
LowStockThresholdPercent = Math.Clamp(configThreshold.Value, 0m, 100m);
|
|
_logger.LogInformation(
|
|
"Low-stock threshold set from config FilamentAlerts:LowStockThresholdPercent: {Threshold}%",
|
|
LowStockThresholdPercent);
|
|
}
|
|
else
|
|
{
|
|
LowStockThresholdPercent = 20m;
|
|
_logger.LogInformation(
|
|
"Low-stock threshold using default: {Threshold}%", LowStockThresholdPercent);
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public bool IsLowStock(decimal weightRemainingGrams, decimal weightTotalGrams)
|
|
{
|
|
if (weightTotalGrams <= 0m)
|
|
{
|
|
_logger.LogDebug(
|
|
"Spool with total weight {Total}g cannot be evaluated for low stock — treating as not low",
|
|
weightTotalGrams);
|
|
return false;
|
|
}
|
|
|
|
var remainingPercent = GetRemainingWeightPercent(weightRemainingGrams, weightTotalGrams);
|
|
var isLow = remainingPercent <= LowStockThresholdPercent;
|
|
|
|
if (isLow)
|
|
{
|
|
_logger.LogDebug(
|
|
"Spool is LOW STOCK: {Remaining}g / {Total}g = {Percent:F1}% (threshold: {Threshold}%)",
|
|
weightRemainingGrams, weightTotalGrams, remainingPercent, LowStockThresholdPercent);
|
|
}
|
|
|
|
return isLow;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public decimal GetRemainingWeightPercent(decimal weightRemainingGrams, decimal weightTotalGrams)
|
|
{
|
|
if (weightTotalGrams <= 0m)
|
|
return 0m;
|
|
|
|
return Math.Round(
|
|
(weightRemainingGrams / weightTotalGrams) * 100m,
|
|
1,
|
|
MidpointRounding.AwayFromZero);
|
|
}
|
|
} |