文章目录[隐藏]
WordPress柔性供应链软件的多维度数据分析看板开发教程
概述:柔性供应链数据分析的重要性
在当今快速变化的市场环境中,柔性供应链管理已成为企业保持竞争力的关键。WordPress作为全球最流行的内容管理系统,通过定制化开发可以转变为强大的业务管理平台。本文将详细介绍如何为WordPress开发一个柔性供应链软件的多维度数据分析看板,帮助企业实时监控供应链状态、预测趋势并优化决策。
环境准备与基础配置
WordPress环境搭建
首先确保您已安装WordPress 5.0以上版本,并具备以下条件:
- PHP 7.4或更高版本
- MySQL 5.6或更高版本
- 至少256MB内存限制
- 已安装必要的PHP扩展(json、mysqli、gd等)
创建自定义插件框架
在wp-content/plugins目录下创建新文件夹"flexible-supply-chain-dashboard",并创建主插件文件:
<?php
/**
* Plugin Name: 柔性供应链数据分析看板
* Plugin URI: https://yourwebsite.com/
* Description: WordPress柔性供应链多维度数据分析看板
* Version: 1.0.0
* Author: Your Name
* License: GPL v2 or later
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('FSCD_VERSION', '1.0.0');
define('FSCD_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('FSCD_PLUGIN_URL', plugin_dir_url(__FILE__));
// 初始化插件
add_action('init', 'fscd_init_plugin');
function fscd_init_plugin() {
// 检查用户权限
if (current_user_can('manage_options')) {
// 注册管理菜单
add_action('admin_menu', 'fscd_register_admin_menu');
// 加载必要脚本和样式
add_action('admin_enqueue_scripts', 'fscd_load_admin_assets');
}
}
数据库设计与数据模型
创建供应链数据表
我们需要创建几个核心数据表来存储供应链信息:
// 在插件激活时创建数据表
register_activation_hook(__FILE__, 'fscd_create_tables');
function fscd_create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// 供应商表
$suppliers_table = $wpdb->prefix . 'fscd_suppliers';
$suppliers_sql = "CREATE TABLE IF NOT EXISTS $suppliers_table (
id INT(11) NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
category VARCHAR(100) NOT NULL,
reliability_score DECIMAL(5,2) DEFAULT 0.00,
lead_time_days INT(5) DEFAULT 0,
location VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
// 库存表
$inventory_table = $wpdb->prefix . 'fscd_inventory';
$inventory_sql = "CREATE TABLE IF NOT EXISTS $inventory_table (
id INT(11) NOT NULL AUTO_INCREMENT,
product_id INT(11) NOT NULL,
product_name VARCHAR(255) NOT NULL,
current_stock INT(11) DEFAULT 0,
reorder_level INT(11) DEFAULT 10,
warehouse_location VARCHAR(255),
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
// 订单与物流表
$orders_table = $wpdb->prefix . 'fscd_orders';
$orders_sql = "CREATE TABLE IF NOT EXISTS $orders_table (
id INT(11) NOT NULL AUTO_INCREMENT,
order_number VARCHAR(50) NOT NULL,
supplier_id INT(11) NOT NULL,
product_id INT(11) NOT NULL,
quantity INT(11) NOT NULL,
order_date DATE NOT NULL,
estimated_delivery DATE,
actual_delivery DATE,
status ENUM('pending', 'shipped', 'delivered', 'delayed') DEFAULT 'pending',
shipping_cost DECIMAL(10,2),
PRIMARY KEY (id),
KEY supplier_id (supplier_id),
KEY status (status)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($suppliers_sql);
dbDelta($inventory_sql);
dbDelta($orders_sql);
}
多维度数据分析模块开发
核心数据分析类
创建一个核心类来处理数据分析逻辑:
class FSCD_Analytics {
private $wpdb;
public function __construct() {
global $wpdb;
$this->wpdb = $wpdb;
}
/**
* 计算供应商可靠性指标
* @param int $supplier_id 供应商ID
* @return array 可靠性指标数据
*/
public function calculate_supplier_reliability($supplier_id = null) {
$table_name = $this->wpdb->prefix . 'fscd_orders';
$suppliers_table = $this->wpdb->prefix . 'fscd_suppliers';
$query = "SELECT
s.id,
s.name,
COUNT(o.id) as total_orders,
SUM(CASE WHEN o.status = 'delivered' AND o.actual_delivery <= o.estimated_delivery THEN 1 ELSE 0 END) as on_time_deliveries,
AVG(DATEDIFF(o.actual_delivery, o.order_date)) as avg_delivery_time,
AVG(o.shipping_cost) as avg_shipping_cost
FROM $suppliers_table s
LEFT JOIN $table_name o ON s.id = o.supplier_id";
if ($supplier_id) {
$query .= $this->wpdb->prepare(" WHERE s.id = %d", $supplier_id);
}
$query .= " GROUP BY s.id ORDER BY on_time_deliveries DESC";
$results = $this->wpdb->get_results($query, ARRAY_A);
// 计算可靠性分数
foreach ($results as &$result) {
if ($result['total_orders'] > 0) {
$on_time_rate = ($result['on_time_deliveries'] / $result['total_orders']) * 100;
$result['reliability_score'] = round($on_time_rate, 2);
} else {
$result['reliability_score'] = 0;
}
}
return $results;
}
/**
* 库存周转率分析
* @param string $time_period 时间周期(monthly, quarterly, yearly)
* @return array 库存周转数据
*/
public function inventory_turnover_analysis($time_period = 'monthly') {
$orders_table = $this->wpdb->prefix . 'fscd_orders';
$inventory_table = $this->wpdb->prefix . 'fscd_inventory';
// 根据时间周期设置日期格式
switch ($time_period) {
case 'yearly':
$date_format = '%Y';
break;
case 'quarterly':
$date_format = '%Y-Q%q';
break;
default:
$date_format = '%Y-%m';
}
$query = $this->wpdb->prepare(
"SELECT
DATE_FORMAT(o.order_date, %s) as period,
i.product_name,
SUM(o.quantity) as total_sold,
AVG(i.current_stock) as avg_inventory,
CASE
WHEN AVG(i.current_stock) > 0
THEN ROUND(SUM(o.quantity) / AVG(i.current_stock), 2)
ELSE 0
END as turnover_rate
FROM $orders_table o
JOIN $inventory_table i ON o.product_id = i.id
WHERE o.status = 'delivered'
GROUP BY period, i.product_name
ORDER BY period DESC, turnover_rate DESC",
$date_format
);
return $this->wpdb->get_results($query, ARRAY_A);
}
/**
* 供应链风险预测
* @return array 风险指标数据
*/
public function predict_supply_chain_risks() {
$results = array(
'low_stock_alerts' => $this->get_low_stock_alerts(),
'delayed_shipments' => $this->get_delayed_shipments(),
'supplier_reliability_issues' => $this->get_supplier_reliability_issues()
);
// 计算总体风险分数
$total_risk_score = 0;
$weight_factors = array(
'low_stock' => 0.4,
'delayed_shipments' => 0.3,
'supplier_issues' => 0.3
);
if (count($results['low_stock_alerts']) > 5) {
$total_risk_score += 40 * $weight_factors['low_stock'];
} elseif (count($results['low_stock_alerts']) > 2) {
$total_risk_score += 20 * $weight_factors['low_stock'];
}
if (count($results['delayed_shipments']) > 3) {
$total_risk_score += 30 * $weight_factors['delayed_shipments'];
}
if (count($results['supplier_reliability_issues']) > 2) {
$total_risk_score += 30 * $weight_factors['supplier_issues'];
}
$results['total_risk_score'] = round($total_risk_score, 2);
$results['risk_level'] = $this->determine_risk_level($total_risk_score);
return $results;
}
private function get_low_stock_alerts() {
$table_name = $this->wpdb->prefix . 'fscd_inventory';
$query = "SELECT * FROM $table_name WHERE current_stock <= reorder_level";
return $this->wpdb->get_results($query, ARRAY_A);
}
private function get_delayed_shipments() {
$table_name = $this->wpdb->prefix . 'fscd_orders';
$query = "SELECT * FROM $table_name WHERE status = 'delayed' OR (estimated_delivery < CURDATE() AND status != 'delivered')";
return $this->wpdb->get_results($query, ARRAY_A);
}
private function get_supplier_reliability_issues() {
$reliability_data = $this->calculate_supplier_reliability();
$issues = array();
foreach ($reliability_data as $supplier) {
if ($supplier['reliability_score'] < 70 && $supplier['total_orders'] > 5) {
$issues[] = $supplier;
}
}
return $issues;
}
private function determine_risk_level($score) {
if ($score >= 70) return 'high';
if ($score >= 40) return 'medium';
return 'low';
}
}
可视化看板界面开发
管理页面与图表展示
创建数据分析看板的管理页面:
function fscd_register_admin_menu() {
add_menu_page(
'供应链数据分析看板',
'供应链看板',
'manage_options',
'fscd-dashboard',
'fscd_display_dashboard',
'dashicons-analytics',
30
);
// 添加子菜单
add_submenu_page(
'fscd-dashboard',
'供应商分析',
'供应商分析',
'manage_options',
'fscd-suppliers',
'fscd_display_suppliers'
);
add_submenu_page(
'fscd-dashboard',
'库存分析',
'库存分析',
'manage_options',
'fscd-inventory',
'fscd_display_inventory'
);
}
function fscd_display_dashboard() {
$analytics = new FSCD_Analytics();
// 获取各种分析数据
$supplier_reliability = $analytics->calculate_supplier_reliability();
$inventory_turnover = $analytics->inventory_turnover_analysis('monthly');
$risk_analysis = $analytics->predict_supply_chain_risks();
?>
<div class="wrap fscd-dashboard">
<h1>柔性供应链数据分析看板</h1>
<div class="fscd-stats-container">
<!-- 风险概览卡片 -->
<div class="fscd-stat-card risk-card risk-<?php echo esc_attr($risk_analysis['risk_level']); ?>">
<h3>供应链风险指数</h3>
<div class="risk-score"><?php echo esc_html($risk_analysis['total_risk_score']); ?>/100</div>
<div class="risk-level">风险等级: <?php echo esc_html(strtoupper($risk_analysis['risk_level'])); ?></div>
<div class="risk-details">
<p>低库存预警: <?php echo count($risk_analysis['low_stock_alerts']); ?> 个产品</p>
<p>延迟发货: <?php echo count($risk_analysis['delayed_shipments']); ?> 个订单</p>
<p>供应商问题: <?php echo count($risk_analysis['supplier_reliability_issues']); ?> 个供应商</p>
</div>
</div>
<!-- 供应商可靠性卡片 -->
<div class="fscd-stat-card">
<h3>供应商可靠性排名</h3>
<div class="supplier-list">
<?php
$top_suppliers = array_slice($supplier_reliability, 0, 5);
foreach ($top_suppliers as $supplier):
?>
<div class="supplier-item">
<span class="supplier-name"><?php echo esc_html($supplier['name']); ?></span>
<span class="supplier-score"><?php echo esc_html($supplier['reliability_score']); ?>%</span>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<!-- 库存周转率图表区域 -->
<div class="fscd-chart-container">
<h2>月度库存周转率</h2>
<div id="inventory-turnover-chart" style="height: 400px;"></div>
</div>
<!-- 数据表格展示 -->
<div class="fscd-table-container">
<h2>详细数据分析</h2>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>产品名称</th>
<th>当前库存</th>
<th>再订货水平</th>
<th>周转率</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<?php
$inventory_data = $analytics->get_low_stock_alerts();
foreach ($inventory_data as $item):
$status_class = $item['current_stock'] <= $item['reorder_level'] ? 'status-alert' : 'status-ok';
?>
<tr>
<td><?php echo esc_html($item['product_name']); ?></td>
<td><?php echo esc_html($item['current_stock']); ?></td>
<td><?php echo esc_html($item['reorder_level']); ?></td>
<td><?php echo esc_html($item['turnover_rate'] ?? 'N/A'); ?></td>
<td class="<?php echo esc_attr($status_class); ?>">
<?php echo $item['current_stock'] <= $item['reorder_level'] ? '需要补货' : '正常'; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<script>
// 使用Chart.js或ECharts初始化图表
jQuery(document).ready(function($) {
// 这里可以添加JavaScript图表初始化代码
// 实际项目中建议使用Chart.js或ECharts库
console.log('Dashboard loaded. Chart data:', <?php echo json_encode($inventory_turnover); ?>);
});
</script>
<?php
}
// 加载管理界面资源
function fscd_load_admin_assets($hook) {
if (strpos($hook, 'fscd-') === false) {
return;
}
wp_enqueue_style(
'fscd-admin-style',
FSCD_PLUGIN_URL . 'assets/css/admin-style.css',
array(),
FSCD_VERSION
);
wp_enqueue_script(
'fscd-admin-script',
FSCD_PLUGIN_URL . 'assets/js/admin-script.js',
array('jquery'),
FSCD_VERSION,
true
);
// 如果需要图表库,可以在这里加载Chart.js或ECharts
// wp_enqueue_script('chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', array(), '3.7.0');
}
数据导入与API集成
外部数据导入功能
为方便从外部系统导入数据,创建数据导入功能:
class FSCD_Data_Importer {
/**
* 从CSV文件导入供应链数据
* @param string $file_path CSV文件路径
* @param string $data_type 数据类型(suppliers, inventory, orders)
* @return array 导入结果
*/
public function import_from_csv($file_path, $data_type) {
global $wpdb;
if (!file_exists($file_path)) {
return array(
'success' => false,
'message' => '文件不存在'
);
}
$handle = fopen($file_path, 'r');
if (!$handle) {
return array(
'success' => false,
'message' => '无法打开文件'
);
}
$imported_count = 0;
$skipped_count = 0;
$errors = array();
// 读取CSV标题行
$headers = fgetcsv($handle);
while (($row = fgetcsv($handle)) !== false) {
$data = array_combine($headers, $row);
switch ($data_type) {
case 'suppliers':
$result = $this->import_supplier_data($data);
break;
case 'inventory':
$result = $this->import_inventory_data($data);
break;
case 'orders':
$result = $this->import_order_data($data);
break;
default:
$result = array('success' => false, 'message' => '未知数据类型');
}
if ($result['success']) {
$imported_count++;
} else {
$skipped_count++;
$errors[] = $result['message'];
}
}
fclose($handle);
return array(
'success' => true,
'imported' => $imported_count,
'skipped' => $skipped_count,
'errors' => array_slice($errors, 0, 10) // 只返回前10个错误
);
}
private function import_supplier_data($data) {
global $wpdb;
$table_name = $wpdb->prefix . 'fscd_suppliers';
// 数据验证
if (empty($data['name'])) {
return array('success' => false, 'message' => '供应商名称不能为空');
}
// 检查是否已存在
$existing = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM $table_name WHERE name = %s",
sanitize_text_field($data['name'])
));
if ($existing > 0) {
// 更新现有记录
$result = $wpdb->update(
$table_name,
array(
'category' => sanitize_text_field($data['category'] ?? ''),
'reliability_score' => floatval($data['reliability_score'] ?? 0),
'lead_time_days' => intval($data['lead_time_days'] ?? 0),
'location' => sanitize_text_field($data['location'] ?? '')
),
array('name' => sanitize_text_field($data['name']))
);
} else {
// 插入新记录
$result = $wpdb->insert(
$table_name,
array(
'name' => sanitize_text_field($data['name']),
'category' => sanitize_text_field($data['category'] ?? ''),
'reliability_score' => floatval($data['reliability_score'] ?? 0),
'lead_time_days' => intval($data['lead_time_days'] ?? 0),
'location' => sanitize_text_field($data['location'] ?? '')
)
);
}
return array(
'success' => $result !== false,
'message' => $result !== false ? '导入成功' : $wpdb->last_error
);
}
// 其他导入方法类似,限于篇幅省略...
}
/**
* REST API端点创建
* 用于与其他系统集成
*/
add_action('rest_api_init', 'fscd_register_rest_routes');
function fscd_register_rest_routes() {
// 获取供应链概览数据
register_rest_route('fscd/v1', '/dashboard/overview', array(
'methods' => 'GET',
'callback' => 'fscd_api_get_dashboard_overview',
'permission_callback' => 'fscd_api_permission_check'
));
// 获取供应商数据
register_rest_route('fscd/v1', '/suppliers', array(
'methods' => 'GET',
'callback' => 'fscd_api_get_suppliers',
'permission_callback' => 'fscd_api_permission_check'
));
// 提交新订单数据
register_rest_route('fscd/v1', '/orders', array(
'methods' => 'POST',
'callback' => 'fscd_api_create_order',
'permission_callback' => 'fscd_api_permission_check'
));
}
function fscd_api_permission_check($request) {
// 实际项目中应使用更严格的权限验证
return current_user_can('manage_options');
}
function fscd_api_get_dashboard_overview($request) {
$analytics = new FSCD_Analytics();
return array(
'supplier_reliability' => $analytics->calculate_supplier_reliability(),
'inventory_turnover' => $analytics->inventory_turnover_analysis('monthly'),
'risk_analysis' => $analytics->predict_supply_chain_risks(),
'timestamp' => current_time('mysql')
);
}
高级功能:预测分析与预警系统
机器学习趋势预测(简化示例)
class FSCD_Predictive_Analytics {
/**
* 基于历史数据的简单线性预测
* @param array $historical_data 历史数据数组
* @param int $future_periods 预测未来周期数
* @return array 预测结果
*/
public function predict_trend($historical_data, $future_periods = 3) {
if (count($historical_data) < 2) {
return array('error' => '需要至少2个数据点进行预测');
}
$n = count($historical_data);
$sum_x = 0;
$sum_y = 0;
$sum_xy = 0;
$sum_xx = 0;
// 计算线性回归参数
foreach ($historical_data as $i => $value) {
$x = $i + 1;
$y = floatval($value);
$sum_x += $x;
$sum_y += $y;
$sum_xy += $x * $y;
$sum_xx += $x * $x;
}
// 计算斜率和截距
$slope = ($n * $sum_xy - $sum_x * $sum_y) / ($n * $sum_xx - $sum_x * $sum_x);
$intercept = ($sum_y - $slope * $sum_x) / $n;
// 生成预测
$predictions = array();
for ($i = 1; $i <= $future_periods; $i++) {
$predictions[] = array(
'period' => '未来周期 ' . $i,
'predicted_value' => round($intercept + $slope * ($n + $i), 2),
'confidence' => $this->calculate_confidence($historical_data, $slope)
);
}
return array(
'historical_data' => $historical_data,
'predictions' => $predictions,
'trend_slope' => $slope,
'r_squared' => $this->calculate_r_squared($historical_data, $slope, $intercept)
);
}
/**
* 库存需求预测
* @param int $product_id 产品ID
* @return array 预测结果
*/
public function predict_inventory_demand($product_id) {
global $wpdb;
$orders_table = $wpdb->prefix . 'fscd_orders';
// 获取过去12个月的销售数据
$query = $wpdb->prepare(
"SELECT
DATE_FORMAT(order_date, '%%Y-%%m') as month,
SUM(quantity) as total_sold
FROM $orders_table
WHERE product_id = %d
AND order_date >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
AND status = 'delivered'
GROUP BY month
ORDER BY month",
$product_id
);
$historical_sales = $wpdb->get_results($query, ARRAY_A);
if (empty($historical_sales)) {
return array('error' => '没有足够的历史数据');
}
// 提取销售数据数组
$sales_data = array_column($historical_sales, 'total_sold');
// 使用移动平均法预测
$predictions = $this->moving_average_forecast($sales_data, 3);
return array(
'historical' => $historical_sales,
'predictions' => $predictions,
'recommended_stock' => $this->calculate_recommended_stock($predictions)
);
}
private function moving_average_forecast($data, $window_size = 3) {
$n = count($data);
if ($n < $window_size) {
return array();
}
$predictions = array();
for ($i = $window_size; $i < $n; $i++) {
$window = array_slice($data, $i - $window_size, $window_size);
$predictions[] = array_sum($window) / $window_size;
}
// 预测未来3个周期
$last_window = array_slice($data, -$window_size);
$last_ma = array_sum($last_window) / $window_size;
$future_predictions = array();
for ($i = 1; $i <= 3; $i++) {
$future_predictions[] = array(
'period' => '未来' . $i . '个月',
'predicted_demand' => round($last_ma * (1 + 0.05 * $i), 2), // 假设5%的增长率
'confidence_interval' => array(
'lower' => round($last_ma * 0.8, 2),
'upper' => round($last_ma * 1.2, 2)
)
);
}
return $future_predictions;
}
private function calculate_recommended_stock($predictions) {
if (empty($predictions)) {
return 0;
}
$avg_demand = array_sum(array_column($predictions, 'predicted_demand')) / count($predictions);
// 安全库存 = 平均需求 * 1.5(可根据实际情况调整)
$safety_stock = $avg_demand * 1.5;
// 推荐库存 = 未来3个月预测需求 + 安全库存
$future_demand = array_sum(array_column($predictions, 'predicted_demand'));
return round($future_demand + $safety_stock);
}
private function calculate_confidence($data, $slope) {
$n = count($data);
if ($n <= 2) return 0.5;
// 简单的置信度计算(实际项目应使用更复杂的统计方法)
$variance = 0;
$mean = array_sum($data) / $n;
foreach ($data as $value) {
$variance += pow($value - $mean, 2);
}
$variance /= $n;
$std_dev = sqrt($variance);
$cv = $std_dev / abs($mean);
// 变异系数越小,置信度越高
$confidence = 1 - min($cv, 1);
return round($confidence, 2);
}
private function calculate_r_squared($data, $slope, $intercept) {
$n = count($data);
$mean = array_sum($data) / $n;
$ss_total = 0;
$ss_residual = 0;
foreach ($data as $i => $value) {
$x = $i + 1;
$y = floatval($value);
$y_pred = $intercept + $slope * $x;
$ss_total += pow($y - $mean, 2);
$ss_residual += pow($y - $y_pred, 2);
}
if ($ss_total == 0) return 1;
return round(1 - ($ss_residual / $ss_total), 4);
}
}
实时预警系统
class FSCD_Alert_System {
/**
* 检查并发送预警
*/
public function check_and_send_alerts() {
$alerts = array();
// 检查低库存预警
$alerts['low_stock'] = $this->check_low_stock_alerts();
// 检查延迟发货预警
$alerts['delayed_shipments'] = $this->check_delayed_shipments();
// 检查供应商可靠性预警
$alerts['supplier_issues'] = $this->check_supplier_reliability();
// 发送预警
if (!empty(array_filter($alerts))) {
$this->send_alerts($alerts);
}
return $alerts;
}
private function check_low_stock_alerts() {
global $wpdb;
$table_name = $wpdb->prefix . 'fscd_inventory';
$query = "SELECT * FROM $table_name
WHERE current_stock <= reorder_level
OR current_stock <= (reorder_level * 1.2)"; // 预警阈值
$results = $wpdb->get_results($query, ARRAY_A);
$alerts = array();
foreach ($results as $item) {
$severity = $item['current_stock'] <= $item['reorder_level'] ? 'high' : 'medium';
$alerts[] = array(
'type' => 'low_stock',
'severity' => $severity,
'product_id' => $item['id'],
'product_name' => $item['product_name'],
'current_stock' => $item['current_stock'],
'reorder_level' => $item['reorder_level'],
'message' => sprintf(
'产品"%s"库存不足。当前库存:%d,再订货点:%d',
$item['product_name'],
$item['current_stock'],
$item['reorder_level']
),
'timestamp' => current_time('mysql')
);
}
return $alerts;
}
private function check_delayed_shipments() {
global $wpdb;
$table_name = $wpdb->prefix . 'fscd_orders';
$query = "SELECT o.*, s.name as supplier_name
FROM $table_name o
LEFT JOIN {$wpdb->prefix}fscd_suppliers s ON o.supplier_id = s.id
WHERE (o.status = 'delayed'
OR (o.estimated_delivery < CURDATE() AND o.status != 'delivered'))
AND o.order_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)";
$results = $wpdb->get_results($query, ARRAY_A);
$alerts = array();
foreach ($results as $order) {
$delay_days = $this->calculate_delay_days($order);
$alerts[] = array(
'type' => 'delayed_shipment',
'severity' => $delay_days > 7 ? 'high' : ($delay_days > 3 ? 'medium' : 'low'),
'order_id' => $order['id'],
'order_number' => $order['order_number'],
'supplier_name' => $order['supplier_name'],
'delay_days' => $delay_days,
'message' => sprintf(
'订单%s已延迟%d天。供应商:%s',
$order['order_number'],
$delay_days,
$order['supplier_name']
),
'timestamp' => current_time('mysql')
);
}
return $alerts;
}
private function calculate_delay_days($order) {
if ($order['status'] == 'delayed') {
$expected = $order['estimated_delivery'] ?: $order['order_date'];
return max(0, floor((time() - strtotime($expected)) / (60 * 60 * 24)));
}
return 0;
}
private function send_alerts($alerts) {
// 发送邮件通知
$this->send_email_alerts($alerts);
// 发送系统通知
$this->create_admin_notices($alerts);
// 记录到日志
$this->log_alerts($alerts);
}
private function send_email_alerts($alerts) {
$to = get_option('admin_email');
$subject = '供应链预警通知 - ' . get_bloginfo('name');
$message = "供应链系统检测到以下预警:nn";
foreach ($alerts as $type => $type_alerts) {
if (!empty($type_alerts)) {
$message .= strtoupper(str_replace('_', ' ', $type)) . ":n";
foreach ($type_alerts as $alert) {
$message .= "- " . $alert['message'] . "n";
}
$message .= "n";
}
}
$message .= "n请登录管理后台查看详细信息。n";
$message .= "链接:" . admin_url('admin.php?page=fscd-dashboard');
wp_mail($to, $subject, $message);
}
private function create_admin_notices($alerts) {
$total_alerts = 0;
foreach ($alerts as $type_alerts) {
