文章目录[隐藏]
WordPress柔性供应链软件开发中实现智能补货策略的详细教程
引言:柔性供应链与智能补货的重要性
在当今快速变化的电商环境中,WordPress作为全球最流行的内容管理系统,已成为许多企业搭建在线商店的首选平台。然而,随着业务规模扩大,传统的库存管理方式已无法满足需求。柔性供应链系统能够根据市场需求动态调整,而智能补货策略则是其核心组成部分,它通过数据分析和算法预测,实现库存优化,降低缺货风险,同时减少资金占用。
本文将详细介绍如何在WordPress环境中开发柔性供应链软件,并实现智能补货功能。我们将从系统设计、数据采集、算法实现到界面集成,提供完整的解决方案。
系统架构设计
整体架构概述
我们的柔性供应链系统将采用模块化设计,与WooCommerce深度集成,同时保持足够的灵活性以便未来扩展。
<?php
/**
* WordPress柔性供应链系统 - 主架构类
*
* @package FlexibleSupplyChain
*/
class FlexibleSupplyChainSystem {
private $inventory_manager;
private $demand_forecaster;
private $replenishment_engine;
private $data_collector;
/**
* 初始化系统组件
*/
public function __construct() {
$this->inventory_manager = new InventoryManager();
$this->demand_forecaster = new DemandForecaster();
$this->replenishment_engine = new ReplenishmentEngine();
$this->data_collector = new DataCollector();
$this->init_hooks();
}
/**
* 初始化WordPress钩子
*/
private function init_hooks() {
// 每日执行库存检查和补货计算
add_action('fsc_daily_replenishment_check', array($this, 'daily_replenishment_process'));
// 订单完成后更新库存数据
add_action('woocommerce_order_status_completed', array($this->inventory_manager, 'update_inventory_after_order'));
// 添加管理页面
add_action('admin_menu', array($this, 'add_admin_pages'));
}
/**
* 每日补货处理流程
*/
public function daily_replenishment_process() {
// 1. 收集销售和库存数据
$sales_data = $this->data_collector->get_recent_sales_data(30); // 最近30天数据
$inventory_data = $this->data_collector->get_current_inventory();
// 2. 预测需求
$demand_forecast = $this->demand_forecaster->calculate_forecast($sales_data);
// 3. 计算补货建议
$replenishment_suggestions = $this->replenishment_engine->calculate_replenishment(
$inventory_data,
$demand_forecast
);
// 4. 应用补货策略
$this->apply_replenishment_decisions($replenishment_suggestions);
// 5. 记录日志
$this->log_replenishment_actions($replenishment_suggestions);
}
// ... 其他方法
}
?>
数据采集与处理模块
销售数据收集
智能补货的基础是准确的历史销售数据。我们需要从WooCommerce中提取相关数据并进行预处理。
<?php
/**
* 数据收集器类
* 负责从WooCommerce和其他来源收集数据
*/
class DataCollector {
/**
* 获取最近N天的销售数据
*
* @param int $days 天数
* @return array 销售数据数组
*/
public function get_recent_sales_data($days = 30) {
global $wpdb;
$start_date = date('Y-m-d', strtotime("-{$days} days"));
$query = $wpdb->prepare("
SELECT
product_id,
SUM(product_qty) as total_sold,
DATE(post_date) as sale_date
FROM {$wpdb->prefix}woocommerce_order_items as items
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta as meta
ON items.order_item_id = meta.order_item_id
INNER JOIN {$wpdb->posts} as orders
ON items.order_id = orders.ID
WHERE
meta.meta_key = '_product_id' AND
orders.post_status = 'wc-completed' AND
orders.post_date >= %s
GROUP BY product_id, DATE(post_date)
ORDER BY sale_date DESC
", $start_date);
$results = $wpdb->get_results($query, ARRAY_A);
// 处理数据,按产品ID组织
$processed_data = array();
foreach ($results as $row) {
$product_id = $row['product_id'];
if (!isset($processed_data[$product_id])) {
$processed_data[$product_id] = array();
}
$processed_data[$product_id][] = array(
'date' => $row['sale_date'],
'quantity' => $row['total_sold']
);
}
return $processed_data;
}
/**
* 获取当前库存数据
*
* @return array 库存数据
*/
public function get_current_inventory() {
$inventory_data = array();
// 获取所有可管理库存的产品
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'meta_key' => '_manage_stock',
'meta_value' => 'yes'
);
$products = get_posts($args);
foreach ($products as $product) {
$product_id = $product->ID;
$product_obj = wc_get_product($product_id);
$inventory_data[$product_id] = array(
'current_stock' => $product_obj->get_stock_quantity(),
'backorders_allowed' => $product_obj->backorders_allowed(),
'low_stock_amount' => get_post_meta($product_id, '_low_stock_amount', true) ?: 2,
'reorder_level' => get_post_meta($product_id, '_reorder_level', true),
'lead_time' => get_post_meta($product_id, '_lead_time_days', true) ?: 7,
'supplier_id' => get_post_meta($product_id, '_supplier_id', true)
);
}
return $inventory_data;
}
}
?>
需求预测算法实现
移动平均法实现
需求预测是智能补货的核心。我们首先实现一个简单的移动平均法,然后扩展为更复杂的指数平滑法。
<?php
/**
* 需求预测器类
* 实现多种需求预测算法
*/
class DemandForecaster {
/**
* 计算需求预测
*
* @param array $sales_data 销售数据
* @param string $method 预测方法 (moving_average, exponential_smoothing)
* @return array 预测结果
*/
public function calculate_forecast($sales_data, $method = 'exponential_smoothing') {
$forecasts = array();
foreach ($sales_data as $product_id => $product_sales) {
switch ($method) {
case 'moving_average':
$forecasts[$product_id] = $this->moving_average_forecast($product_sales);
break;
case 'exponential_smoothing':
$forecasts[$product_id] = $this->exponential_smoothing_forecast($product_sales);
break;
default:
$forecasts[$product_id] = $this->exponential_smoothing_forecast($product_sales);
}
}
return $forecasts;
}
/**
* 简单移动平均法预测
*
* @param array $sales_data 产品销售数据
* @param int $period 移动平均期数,默认7天
* @return array 包含预测值和置信区间的数组
*/
private function moving_average_forecast($sales_data, $period = 7) {
if (count($sales_data) < $period) {
// 数据不足时使用所有可用数据
$period = count($sales_data);
}
// 提取销售量
$quantities = array_column($sales_data, 'quantity');
// 计算最近period天的平均值
$recent_data = array_slice($quantities, 0, $period);
$average = array_sum($recent_data) / $period;
// 计算标准差用于置信区间
$variance = 0;
foreach ($recent_data as $qty) {
$variance += pow($qty - $average, 2);
}
$std_dev = sqrt($variance / $period);
// 95%置信区间
$confidence_interval = 1.96 * $std_dev / sqrt($period);
return array(
'forecast' => round($average, 2),
'lower_bound' => round(max(0, $average - $confidence_interval), 2),
'upper_bound' => round($average + $confidence_interval, 2),
'method' => 'moving_average',
'period' => $period
);
}
/**
* 指数平滑法预测 (Holt-Winters方法,考虑趋势和季节性)
*
* @param array $sales_data 产品销售数据
* @param float $alpha 水平平滑系数 (0-1)
* @param float $beta 趋势平滑系数 (0-1)
* @param int $season_period 季节性周期 (如7表示周季节性)
* @return array 预测结果
*/
private function exponential_smoothing_forecast($sales_data, $alpha = 0.3, $beta = 0.1, $season_period = 7) {
$quantities = array_column($sales_data, 'quantity');
$n = count($quantities);
if ($n < $season_period * 2) {
// 数据不足以进行季节性分析,退回到简单指数平滑
return $this->simple_exponential_smoothing($quantities, $alpha);
}
// 初始化水平、趋势和季节性成分
$level = array();
$trend = array();
$seasonal = array();
// 初始季节性因子计算
$season_averages = array();
for ($i = 0; $i < $season_period; $i++) {
$sum = 0;
$count = 0;
for ($j = $i; $j < $n; $j += $season_period) {
$sum += $quantities[$j];
$count++;
}
$season_averages[$i] = $sum / $count;
}
$overall_average = array_sum($season_averages) / $season_period;
// 初始化季节性因子
for ($i = 0; $i < $season_period; $i++) {
$seasonal[$i] = $season_averages[$i] / $overall_average;
}
// 初始水平和趋势
$level[0] = $quantities[0] / $seasonal[0];
$trend[0] = 0;
// 应用Holt-Winters公式
for ($i = 1; $i < $n; $i++) {
$season_index = $i % $season_period;
// 更新水平
$level[$i] = $alpha * ($quantities[$i] / $seasonal[$season_index]) +
(1 - $alpha) * ($level[$i-1] + $trend[$i-1]);
// 更新趋势
$trend[$i] = $beta * ($level[$i] - $level[$i-1]) +
(1 - $beta) * $trend[$i-1];
// 更新季节性因子
$seasonal[$season_index] = 0.2 * ($quantities[$i] / $level[$i]) +
0.8 * $seasonal[$season_index];
}
// 生成预测
$last_level = $level[$n-1];
$last_trend = $trend[$n-1];
$last_season_index = ($n-1) % $season_period;
// 预测未来7天
$forecast_days = 7;
$forecast_values = array();
for ($i = 1; $i <= $forecast_days; $i++) {
$season_index = ($last_season_index + $i) % $season_period;
$forecast = ($last_level + $i * $last_trend) * $seasonal[$season_index];
$forecast_values[] = max(0, round($forecast, 2));
}
// 计算平均预测值作为补货依据
$average_forecast = array_sum($forecast_values) / count($forecast_values);
return array(
'forecast' => round($average_forecast, 2),
'daily_forecasts' => $forecast_values,
'method' => 'holt_winters',
'parameters' => array(
'alpha' => $alpha,
'beta' => $beta,
'season_period' => $season_period
)
);
}
}
?>
智能补货引擎
补货策略实现
基于需求预测和当前库存,我们可以实现多种补货策略。
<?php
/**
* 补货引擎类
* 实现智能补货决策逻辑
*/
class ReplenishmentEngine {
/**
* 计算补货建议
*
* @param array $inventory_data 当前库存数据
* @param array $demand_forecasts 需求预测
* @return array 补货建议
*/
public function calculate_replenishment($inventory_data, $demand_forecasts) {
$suggestions = array();
foreach ($inventory_data as $product_id => $inventory) {
if (!isset($demand_forecasts[$product_id])) {
continue; // 没有预测数据的产品跳过
}
$forecast = $demand_forecasts[$product_id];
$daily_demand = $forecast['forecast'];
// 计算安全库存
$lead_time = $inventory['lead_time'] ?: 7;
$service_level = 0.95; // 95%的服务水平
$z_score = 1.65; // 95%对应的Z值
// 假设需求标准差为预测值的20%
$demand_std_dev = $daily_demand * 0.2;
$safety_stock = $z_score * sqrt($lead_time) * $demand_std_dev;
// 计算再订货点
$reorder_point = ($daily_demand * $lead_time) + $safety_stock;
// 计算经济订货批量 (EOQ)
$ordering_cost = 50; // 每次订货成本
$holding_cost_rate = 0.2; // 持有成本率
$product_price = $this->get_product_price($product_id);
$annual_demand = $daily_demand * 365;
$eoq = sqrt((2 * $annual_demand * $ordering_cost) / ($holding_cost_rate * $product_price));
// 当前库存水平
$current_stock = $inventory['current_stock'];
// 判断是否需要补货
$needs_reorder = false;
$reorder_quantity = 0;
if ($current_stock <= $reorder_point) {
$needs_reorder = true;
$reorder_quantity = max($eoq, $reorder_point - $current_stock + $safety_stock);
// 考虑供应商最小订单量
$min_order_qty = $this->get_supplier_min_order($inventory['supplier_id']);
if ($min_order_qty > 0 && $reorder_quantity < $min_order_qty) {
$reorder_quantity = $min_order_qty;
}
// 考虑包装规格
$pack_size = $this->get_product_pack_size($product_id);
if ($pack_size > 1) {
$reorder_quantity = ceil($reorder_quantity / $pack_size) * $pack_size;
}
}
$suggestions[$product_id] = array(
'product_id' => $product_id,
'product_name' => get_the_title($product_id),
'current_stock' => $current_stock,
'daily_demand_forecast' => $daily_demand,
'safety_stock' => round($safety_stock, 2),
'reorder_point' => round($reorder_point, 2),
'eoq' => round($eoq, 2),
'needs_reorder' => $needs_reorder,
'suggested_quantity' => $needs_reorder ? round($reorder_quantity) : 0,
'lead_time_days' => $lead_time,
'stock_out_risk' => $this->calculate_stockout_risk($current_stock, $daily_demand, $lead_time),
'forecast_method' => $forecast['method']
);
}
// 按缺货风险排序
usort($suggestions, function($a, $b) {
return $b['stock_out_risk'] <=> $a['stock_out_risk'];
});
return $suggestions;
}
/**
* 计算缺货风险
*/
private function calculate_stockout_risk($current_stock, $daily_demand, $lead_time) {
if ($daily_demand <= 0) return 0;
$days_of_supply = $current_stock / $daily_demand;
$risk = 0;
if ($days_of_supply < $lead_time) {
$risk = 1 - ($days_of_supply / $lead_time);
}
return round($risk * 100, 2); // 返回百分比
}
/**
* 获取产品价格
*/
private function get_product_price($product_id) {
$product = wc_get_product($product_id);
return $product ? $product->get_price() : 0;
}
/**
* 获取供应商最小订单量
*/
private function get_supplier_min_order($supplier_id) {
if (!$supplier_id) return 0;
return get_post_meta($supplier_id, '_min_order_quantity', true) ?: 0;
}
/**
* 获取产品包装规格
*/
private function get_product_pack_size($product_id) {
return get_post_meta($product_id, '_pack_size', true) ?: 1;
}
/**
* 应用补货决策 - 创建采购订单
*/
public function create_purchase_order($product_id, $quantity, $supplier_id) {
// 创建采购订单自定义帖子类型
$purchase_order_data = array(
'post_title' => '采购订单 - ' . date('Y-m-d H:i:s'),
'post_content' => '',
'post_status' => 'publish',
'post_type' => 'purchase_order',
'meta_input' => array(
'_supplier_id' => $supplier_id,
'_product_id' => $product_id,
'_quantity' => $quantity,
'_order_date' => current_time('mysql'),
'_expected_date' => date('Y-m-d', strtotime('+' . get_post_meta($product_id, '_lead_time_days', true) . ' days')),
'_status' => 'pending',
'_auto_generated' => true
)
);
$order_id = wp_insert_post($purchase_order_data);
if ($order_id) {
// 发送通知
$this->send_replenishment_notification($order_id, $product_id, $quantity);
// 更新产品元数据
update_post_meta($product_id, '_last_auto_reorder_date', current_time('mysql'));
update_post_meta($product_id, '_last_auto_reorder_qty', $quantity);
return $order_id;
}
return false;
}
/**
* 发送补货通知
*/
private function send_replenishment_notification($order_id, $product_id, $quantity) {
$product_name = get_the_title($product_id);
$admin_email = get_option('admin_email');
$subject = '自动补货通知: ' . $product_name;
$message = "系统已自动生成采购订单 #{$order_id}nn";
$message .= "产品: {$product_name}n";
$message .= "数量: {$quantity}n";
$message .= "时间: " . date('Y-m-d H:i:s') . "nn";
$message .= "请登录管理后台查看详情。";
wp_mail($admin_email, $subject, $message);
}
}
?>
库存管理模块
实时库存监控与预警
<?php
/**
* 库存管理器类
* 负责库存的实时监控和预警
*/
class InventoryManager {
/**
* 订单完成后更新库存
*/
public function update_inventory_after_order($order_id) {
$order = wc_get_order($order_id);
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
$quantity = $item->get_quantity();
// 获取当前库存
$product = wc_get_product($product_id);
if ($product && $product->managing_stock()) {
$current_stock = $product->get_stock_quantity();
$new_stock = $current_stock - $quantity;
// 更新库存
wc_update_product_stock($product_id, $new_stock);
// 检查是否需要预警
$this->check_stock_alert($product_id, $new_stock);
}
}
}
/**
* 检查库存预警
*/
private function check_stock_alert($product_id, $current_stock) {
$low_stock_amount = get_post_meta($product_id, '_low_stock_amount', true);
$reorder_level = get_post_meta($product_id, '_reorder_level', true);
if (!$low_stock_amount) {
$low_stock_amount = 2; // 默认值
}
// 触发低库存预警
if ($current_stock <= $low_stock_amount && $current_stock > 0) {
$this->send_low_stock_alert($product_id, $current_stock, 'low_stock');
}
// 触发缺货预警
if ($current_stock <= 0) {
$this->send_low_stock_alert($product_id, $current_stock, 'out_of_stock');
}
// 触发再订货点预警
if ($reorder_level && $current_stock <= $reorder_level) {
$this->send_low_stock_alert($product_id, $current_stock, 'reorder_point');
}
}
/**
* 发送库存预警
*/
private function send_low_stock_alert($product_id, $current_stock, $alert_type) {
$product_name = get_the_title($product_id);
$admin_email = get_option('admin_email');
$alert_types = array(
'low_stock' => '低库存预警',
'out_of_stock' => '缺货预警',
'reorder_point' => '再订货点预警'
);
$subject = $alert_types[$alert_type] . ': ' . $product_name;
$message = "产品: {$product_name}n";
$message .= "当前库存: {$current_stock}n";
$message .= "预警类型: " . $alert_types[$alert_type] . "n";
$message .= "时间: " . date('Y-m-d H:i:s') . "nn";
if ($alert_type == 'reorder_point') {
$message .= "建议立即检查补货建议。n";
}
wp_mail($admin_email, $subject, $message);
// 记录预警日志
$this->log_alert($product_id, $alert_type, $current_stock);
}
/**
* 记录预警日志
*/
private function log_alert($product_id, $alert_type, $current_stock) {
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'fsc_stock_alerts',
array(
'product_id' => $product_id,
'alert_type' => $alert_type,
'stock_level' => $current_stock,
'alert_date' => current_time('mysql')
)
);
}
/**
* 获取库存周转率
*/
public function calculate_inventory_turnover($product_id, $period_days = 30) {
global $wpdb;
$start_date = date('Y-m-d', strtotime("-{$period_days} days"));
// 计算期间销售成本
$sales_query = $wpdb->prepare("
SELECT SUM(meta.meta_value * items.product_qty) as total_cost
FROM {$wpdb->prefix}woocommerce_order_items as items
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta as meta
ON items.order_item_id = meta.order_item_id
INNER JOIN {$wpdb->posts} as orders
ON items.order_id = orders.ID
WHERE
meta.meta_key = '_product_id' AND
meta.meta_value = %d AND
orders.post_status = 'wc-completed' AND
orders.post_date >= %s
", $product_id, $start_date);
$sales_cost = $wpdb->get_var($sales_query);
// 计算平均库存价值
$product = wc_get_product($product_id);
$product_cost = get_post_meta($product_id, '_cost_price', true) ?: $product->get_price();
$current_stock = $product->get_stock_quantity();
// 假设期初库存与当前库存相同(简化计算)
$average_inventory_value = ($current_stock * $product_cost) / 2;
if ($average_inventory_value > 0) {
$turnover = $sales_cost / $average_inventory_value;
return round($turnover, 2);
}
return 0;
}
}
?>
管理界面与可视化
WordPress后台管理页面
<?php
/**
* 管理界面类
* 创建WordPress后台管理页面
*/
class AdminInterface {
/**
* 添加管理菜单
*/
public function add_admin_menus() {
// 主菜单
add_menu_page(
'柔性供应链管理',
'供应链管理',
'manage_options',
'fsc-dashboard',
array($this, 'render_dashboard_page'),
'dashicons-networking',
56
);
// 子菜单
add_submenu_page(
'fsc-dashboard',
'智能补货建议',
'补货建议',
'manage_options',
'fsc-replenishment',
array($this, 'render_replenishment_page')
);
add_submenu_page(
'fsc-dashboard',
'库存监控',
'库存监控',
'manage_options',
'fsc-inventory',
array($this, 'render_inventory_page')
);
add_submenu_page(
'fsc-dashboard',
'需求预测分析',
'需求预测',
'manage_options',
'fsc-forecast',
array($this, 'render_forecast_page')
);
add_submenu_page(
'fsc-dashboard',
'系统设置',
'设置',
'manage_options',
'fsc-settings',
array($this, 'render_settings_page')
);
}
/**
* 渲染仪表板页面
*/
public function render_dashboard_page() {
?>
<div class="wrap fsc-dashboard">
<h1>柔性供应链管理系统</h1>
<div class="fsc-stats-container">
<div class="fsc-stat-box">
<h3>库存状态</h3>
<div class="stat-number" id="total-inventory-value">加载中...</div>
<p>总库存价值</p>
</div>
<div class="fsc-stat-box">
<h3>需要补货</h3>
<div class="stat-number" id="products-needing-reorder">0</div>
<p>个产品</p>
</div>
<div class="fsc-stat-box">
<h3>缺货风险</h3>
<div class="stat-number" id="high-risk-products">0</div>
<p>高风险产品</p>
</div>
<div class="fsc-stat-box">
<h3>平均周转率</h3>
<div class="stat-number" id="avg-turnover-rate">0</div>
<p>次/月</p>
</div>
</div>
<div class="fsc-charts-container">
<div class="fsc-chart-box">
<h3>库存水平分布</h3>
<canvas id="inventory-level-chart" width="400" height="200"></canvas>
</div>
<div class="fsc-chart-box">
<h3>补货建议趋势</h3>
<canvas id="replenishment-trend-chart" width="400" height="200"></canvas>
</div>
</div>
<div class="fsc-recent-alerts">
<h3>最近预警</h3>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>产品</th>
<th>预警类型</th>
<th>库存水平</th>
<th>时间</th>
<th>操作</th>
</tr>
</thead>
<tbody id="recent-alerts-list">
<!-- 通过AJAX加载 -->
</tbody>
</table>
</div>
</div>
<script>
jQuery(document).ready(function($) {
// 加载仪表板数据
loadDashboardData();
function loadDashboardData() {
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'fsc_get_dashboard_data'
},
success: function(response) {
if (response.success) {
updateDashboard(response.data);
}
}
});
}
function updateDashboard(data) {
$('#total-inventory-value').text(data.total_inventory_value);
$('#products-needing-reorder').text(data.products_needing_reorder);
$('#high-risk-products').text(data.high_risk_products);
$('#avg-turnover-rate').text(data.avg_turnover_rate);
// 更新图表
updateCharts(data.charts);
// 更新预警列表
updateAlertsList(data.recent_alerts);
}
});
</script>
<?php
}
/**
* 渲染补货建议页面
*/
public function render_replenishment_page() {
$replenishment_engine = new ReplenishmentEngine();
$data_collector = new DataCollector();
$inventory_data = $data_collector->get_current_inventory();
$sales_data = $data_collector->get_recent_sales_data(30);
$demand_forecaster = new DemandForecaster();
$forecasts = $demand_forecaster->calculate_forecast($sales_data);
$suggestions = $replenishment_engine->calculate_replenishment($inventory_data, $forecasts);
?>
<div class="wrap">
<h1>智能补货建议</h1>
<div class="fsc-filters">
<select id="filter-supplier">
<option value="">所有供应商</option>
<?php
$suppliers = get_posts(array(
'post_type' => 'supplier',
'posts_per_page' => -1
));
foreach ($suppliers as $supplier) {
echo '<option value="' . $supplier->ID . '">' . $supplier->post_title . '</option>';
}
?>
</select>
<select id="filter-risk">
<option value="">所有风险等级</option>
<option value="high">高风险 (>70%)</option>
<option value="medium">中风险 (30-70%)</option>
<option value="low">低风险 (<30%)</option>
</select>
<button class="button button-primary" onclick="applyFilters()">筛选</button>
<button class="button" onclick="exportSuggestions()">导出建议</button>
<button class="button button-secondary" onclick="runReplenishmentCheck()">立即运行补货检查</button>
</div>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>产品</th>
<th>当前库存</th>
<th>日均需求</th>
<th>安全库存</th>
<th>再订货点</th>
<th>经济订货量</th>
<th>建议补货量</th>
<th>缺货风险</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($suggestions as $suggestion): ?>
<tr class="risk-level-<?php echo $this->get_risk_level($suggestion['stock_out_risk']); ?>">
<td>
<strong><?php echo esc_html($suggestion['product_name']); ?></strong><br>
<small>ID: <?php echo $suggestion['product_id']; ?></small>
</td>
<td><?php echo $suggestion['current_stock']; ?></td>
<td><?php echo $suggestion['daily_demand_forecast']; ?></td>
<td><?php echo $suggestion['safety_stock']; ?></td>
<td><?php echo $suggestion['reorder_point']; ?></td>
<td><?php echo $suggestion['eoq']; ?></td>
<td>
<?php if ($suggestion['needs_reorder']): ?>
<span class="reorder-needed"><?php echo $suggestion['suggested_quantity']; ?></span>
<?php else: ?>
<span class="no-reorder">-</span>
<?php endif; ?>
</td>
<td>
<div class="risk-indicator">
<div class="risk-bar" style="width: <?php echo min(100, $suggestion['stock_out_risk']); ?>%"></div>
<span><?php echo $suggestion['stock_out_risk']; ?>%</span>
</div>
</td>
<td>
<?php if ($suggestion['needs_reorder']): ?>
<button class="button button-small button-primary"
onclick="createPurchaseOrder(<?php echo $suggestion['product_id']; ?>, <?php echo $suggestion['suggested_quantity']; ?>)">
创建采购单
</button>
<?php endif; ?>
<button class="button button-small"
onclick="viewProductDetails(<?php echo $suggestion['product_id']; ?>)">
详情
</button>


