进销存技术分享

JXC - 专注于进销存软件开发

进销存系统智能补货策略与算法实现

智能补货概述

智能补货是进销存系统的核心功能之一,通过算法分析历史销售数据、库存状态、采购周期等信息,自动生成科学的补货建议。本文详细介绍进销存系统中智能补货策略的设计与算法实现。

补货策略模型

策略类型 适用场景 核心算法
安全库存补货 常规商品常规补货 (日均销量 × 补货周期) + 安全库存
智能预测补货 季节性商品波动较大 时间序列预测 + ARIMA
促销活动补货 大促期间备货 活动因子 × 历史峰值 × 增长系数
最小起订量补货 物流成本优化 凑整计算 + 经济订货量

安全库存计算算法

基于的服务水平和需求波动计算安全库存:

// 安全库存计算服务
class SafetyStockCalculator {
  constructor(salesHistoryModel, productModel) {
    this.SalesHistory = salesHistoryModel;
    this.Product = productModel;
  }

  // 计算安全库存
  async calculateSafetyStock(productId, options = {}) {
    const {
      serviceLevel = 0.95,  // 默认95%服务水平
      leadTime = 7,          // 默认补货周期7天
      useSeasonal = true     // 是否考虑季节性
    } = options;

    const product = await this.Product.findById(productId);

    // 获取历史销量数据
    const salesData = await this.getSalesData(productId);

    // 计算日均销量
    const avgDailySales = this.calculateAverageSales(salesData);

    // 计算销量标准差
    const salesStd = this.calculateStdDev(salesData);

    // 计算季节性因子
    const seasonalFactor = useSeasonal
      ? await this.calculateSeasonalFactor(productId)
      : 1;

    // 计算安全库存
    // 安全库存 = Z值 × 销量标准差 × sqrt(补货周期)
    const zValue = this.getZValue(serviceLevel);
    const safetyStock = zValue * salesStd * Math.sqrt(leadTime) * seasonalFactor;

    // 计算再订货点
    const reorderPoint = avgDailySales * leadTime + safetyStock;

    return {
      safetyStock: Math.ceil(safetyStock),
      reorderPoint: Math.ceil(reorderPoint),
      avgDailySales: avgDailySales.toFixed(2),
      seasonalFactor: seasonalFactor.toFixed(2)
    };
  }

  // 获取销量数据
  async getSalesData(productId, days = 90) {
    const startDate = new Date();
    startDate.setDate(startDate.getDate() - days);

    return this.SalesHistory.aggregate([
      {
        $match: {
          productId,
          saleDate: { $gte: startDate }
        }
      },
      {
        $group: {
          _id: { $dateToString: { format: '%Y-%m-%d', date: '$saleDate' } },
          quantity: { $sum: '$quantity' }
        }
      },
      { $sort: { _id: 1 } }
    ]);
  }

  // 计算日均销量
  calculateAverageSales(salesData) {
    if (salesData.length === 0) return 0;
    const totalSales = salesData.reduce((sum, day) => sum + day.quantity, 0);
    return totalSales / salesData.length;
  }

  // 计算标准差
  calculateStdDev(salesData) {
    if (salesData.length === 0) return 0;
    const avg = this.calculateAverageSales(salesData);
    const squaredDiffs = salesData.map(day =>
      Math.pow(day.quantity - avg, 2)
    );
    const avgSquaredDiff = squaredDiffs.reduce((a, b) => a + b, 0) / salesData.length;
    return Math.sqrt(avgSquaredDiff);
  }

  // 获取Z值(正态分布)
  getZValue(serviceLevel) {
    const zTable = {
      0.90: 1.28,
      0.95: 1.65,
      0.975: 1.96,
      0.99: 2.33,
      0.999: 3.09
    };
    return zTable[serviceLevel] || 1.65;
  }

  // 计算季节性因子
  async calculateSeasonalFactor(productId) {
    const currentMonth = new Date().getMonth() + 1;

    // 获取去年同月销量
    const lastYearData = await this.getMonthlySales(productId, currentMonth);
    const lastYearTotal = lastYearData.reduce((sum, d) => sum + d.quantity, 0);

    // 获取去年全年销量
    const lastYearAllData = await this.getYearlySales(productId);
    const lastYearAllTotal = lastYearAllData.reduce((sum, d) => sum + d.quantity, 0);

    // 计算季节性因子
    const avgMonthlySales = lastYearAllTotal / 12;
    return avgMonthlySales > 0 ? (lastYearTotal / 12) / avgMonthlySales : 1;
  }
}

智能预测补货算法

基于时间序列的销量预测:

// 智能预测补货服务
class SmartReplenishmentService {
  constructor(salesModel, productModel, supplierModel) {
    this.Sales = salesModel;
    this.Product = productModel;
    this.Supplier = supplierModel;
  }

  // 智能补货推荐
  async getReplenishmentRecommendation(productId, options = {}) {
    const product = await this.Product.findById(productId);

    // 获取各种预测数据
    const forecast = await this.forecastSales(productId, options);
    const safetyStockInfo = await this.calculateSafetyStock(productId);
    const supplierInfo = await this.getSupplierInfo(product.supplierId);

    // 计算建议补货量
    const recommendedQty = this.calculateRecommendQty({
      forecast,
      currentStock: product.stock,
      safetyStock: safetyStockInfo.safetyStock,
      minOrderQty: supplierInfo.minOrderQty,
      leadTime: supplierInfo.leadTime
    });

    return {
      productId,
      productName: product.name,
      currentStock: product.stock,
      safetyStock: safetyStockInfo.safetyStock,
      forecastSales: forecast.total,
      recommendedQty,
      urgency: this.getUrgencyLevel(product.stock, safetyStockInfo.reorderPoint),
      supplier: supplierInfo,
      reasons: this.generateReasons(forecast, product.stock, safetyStockInfo)
    };
  }

  // 预测未来销量(使用移动平均 + 趋势调整)
  async forecastSales(productId, options = {}) {
    const { days = 30, method = 'weighted' } = options;

    // 获取历史销量
    const historyData = await this.getSalesHistory(productId, 180);

    // 基础预测:加权移动平均
    const baseForecast = this.weightedMovingAverage(historyData, days);

    // 趋势调整
    const trend = this.calculateTrend(historyData);

    // 季节性调整
    const seasonalFactor = this.getSeasonalFactor(new Date().getMonth() + 1);

    // 综合预测
    const prediction = baseForecast * (1 + trend) * seasonalFactor;

    return {
      daily: prediction,
      total: Math.ceil(prediction * days),
      trend: trend.toFixed(2),
      seasonalFactor: seasonalFactor.toFixed(2),
      confidence: this.calculateConfidence(historyData)
    };
  }

  // 加权移动平均
  weightedMovingAverage(data, period) {
    const recentData = data.slice(-period);
    if (recentData.length === 0) return 0;

    // 越近期的数据权重越大
    const weights = recentData.map((_, i) => i + 1);
    const totalWeight = weights.reduce((a, b) => a + b, 0);

    const weightedSum = recentData.reduce((sum, day, i) =>
      sum + day.quantity * weights[i], 0
    );

    return weightedSum / totalWeight;
  }

  // 计算趋势
  calculateTrend(data) {
    if (data.length < 30) return 0;

    // 比较近30天与之前30天的平均值
    const recent = data.slice(-30);
    const previous = data.slice(-60, -30);

    const recentAvg = recent.reduce((s, d) => s + d.quantity, 0) / recent.length;
    const previousAvg = previous.reduce((s, d) => s + d.quantity, 0) / previous.length;

    return previousAvg > 0 ? (recentAvg - previousAvg) / previousAvg : 0;
  }

  // 获取季节性因子
  getSeasonalFactor(month) {
    const seasonalFactors = {
      1: 0.8,   // 春节前备货
      2: 0.6,   // 春节淡季
      3: 1.0,
      4: 1.0,
      5: 1.1,   // 五一促销
      6: 1.2,   # 6.18电商大促
      7: 1.0,
      8: 0.9,
      9: 1.0,
      10: 1.1,  // 国庆促销
      11: 1.3,  # 双11大促
      12: 1.4   // 年底旺季
    };
    return seasonalFactors[month] || 1.0;
  }

  // 计算建议补货量
  calculateRecommendQty({ forecast, currentStock, safetyStock, minOrderQty, leadTime }) {
    // 基础补货量 = 预测销量 - 当前库存 + 安全库存
    let recommended = forecast.total - currentStock + safetyStock;

    // 如果结果为负数,说明库存充足
    if (recommended <= 0) return 0;

    // 考虑最小起订量
    if (recommended < minOrderQty && currentStock < safetyStock) {
      recommended = minOrderQty;
    }

    // 凑整到最小包装
    recommended = Math.ceil(recommended / minOrderQty) * minOrderQty;

    return Math.ceil(recommended);
  }

  // 生成推荐原因
  generateReasons(forecast, currentStock, safetyStock) {
    const reasons = [];

    if (currentStock <= safetyStock.reorderPoint) {
      reasons.push('库存已达到再订货点,需要及时补货');
    }

    if (forecast.trend > 0.1) {
      reasons.push(`预测销量上涨 ${(forecast.trend * 100).toFixed(0)}%,建议增加备货`);
    }

    if (forecast.seasonalFactor > 1.2) {
      reasons.push(`当前为销售旺季,季节性因子 ${forecast.seasonalFactor}`);
    }

    return reasons;
  }
}

自动订货单生成

根据补货建议自动生成采购订单:

// 自动生成采购订单
class AutoPurchaseOrderService {
  constructor(recommendationService, purchaseOrderModel) {
    this.Recommendation = recommendationService;
    this.PurchaseOrder = purchaseOrderModel;
  }

  // 批量生成补货建议
  async batchReplenishment(warehouseId, filters = {}) {
    const products = await this.getProductsByWarehouse(warehouseId, filters);

    const recommendations = [];
    for (const product of products) {
      const rec = await this.Recommendation.getReplenishmentRecommendation(product._id);
      if (rec.recommendedQty > 0) {
        recommendations.push(rec);
      }
    }

    // 按紧急程度排序
    return recommendations.sort((a, b) => {
      const urgencyOrder = { critical: 0, high: 1, medium: 2, low: 3 };
      return urgencyOrder[a.urgency] - urgencyOrder[b.urgency];
    });
  }

  // 生成采购订单
  async generatePurchaseOrder(supplierId, items, options = {}) {
    const { priority = 'normal', expectedDate, remark } = options;

    // 按供应商分组
    const orderItems = items.map(item => ({
      productId: item.productId,
      productName: item.productName,
      quantity: item.recommendedQty,
      unit: item.unit || '个',
      price: item.price || 0,
      amount: item.recommendedQty * (item.price || 0)
    }));

    const totalAmount = orderItems.reduce((sum, item) => sum + item.amount, 0);

    const order = await this.PurchaseOrder.create({
      orderNo: this.generateOrderNo(supplierId),
      supplierId,
      items: orderItems,
      totalAmount,
      status: 'draft',
      priority,
      expectedDate,
      remark,
      creator: 'system',
      createdAt: new Date()
    });

    return order;
  }

  // 生成订单号
  generateOrderNo(supplierId) {
    const prefix = 'PO';
    const date = new Date().toISOString().slice(0, 10).replace(/-/g, '');
    const random = Math.random().toString(36).substr(2, 6).toUpperCase();
    return `${prefix}${date}${random}`;
  }

  // 自动提交审核
  async autoSubmitForApproval(orderId, thresholds = {}) {
    const order = await this.PurchaseOrder.findById(orderId);

    // 大额订单需要审批
    if (order.totalAmount > thresholds.largeOrderAmount) {
      order.status = 'pending_approval';
      order.approvalLevel = 1;
    } else {
      order.status = 'approved';
      order.approvedAt = new Date();
      order.approver = 'system_auto';
    }

    await order.save();
    return order;
  }
}

总结

智能补货系统可以显著提升进销存管理效率,核心价值包括:

通过智能补货系统的实施,企业可以实现库存的最优化管理。

← 下一篇:进销存系统供应商管理与采购优化