文章目录
-
- 在当今电商竞争激烈的环境中,传统的单一供应链系统已无法满足企业的多样化需求。特别是对于使用WordPress搭建电商网站的中小企业来说,一个能够灵活调配多个供应商、仓库和物流节点的系统至关重要。本文将带您一步步开发一个WordPress多节点柔性供应链插件,实现库存智能分配、供应商自动选择和物流优化等功能。
- 首先,我们需要创建插件的基础结构。在WordPress的wp-content/plugins/目录下创建新文件夹flexible-supply-chain。 <?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('FSC_VERSION', '1.0.0'); define('FSC_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('FSC_PLUGIN_URL', plugin_dir_url(__FILE__)); // 初始化插件 class FlexibleSupplyChain { private static $instance = null; public static function get_instance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } private function __construct() { $this->init_hooks(); } private function init_hooks() { // 激活/停用钩子 register_activation_hook(__FILE__, array($this, 'activate')); register_deactivation_hook(__FILE__, array($this, 'deactivate')); // 初始化 add_action('init', array($this, 'init')); // 管理菜单 add_action('admin_menu', array($this, 'add_admin_menu')); // 加载脚本和样式 add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts')); } public function activate() { $this->create_tables(); $this->create_default_settings(); } public function deactivate() { // 清理临时数据 } public function init() { // 初始化代码 } // 其他方法将在后续实现 } // 启动插件 FlexibleSupplyChain::get_instance(); ?>
- 柔性供应链系统需要存储供应商、仓库、库存和订单分配等信息。我们创建以下数据库表: <?php /** * 创建数据库表 */ private function create_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); // 供应商表 $suppliers_table = $wpdb->prefix . 'fsc_suppliers'; $sql1 = "CREATE TABLE IF NOT EXISTS $suppliers_table ( id INT(11) NOT NULL AUTO_INCREMENT, name VARCHAR(255) NOT NULL, code VARCHAR(50) NOT NULL UNIQUE, contact_person VARCHAR(100), email VARCHAR(100), phone VARCHAR(50), address TEXT, priority INT(11) DEFAULT 0, is_active TINYINT(1) DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id) ) $charset_collate;"; // 仓库节点表 $warehouses_table = $wpdb->prefix . 'fsc_warehouses'; $sql2 = "CREATE TABLE IF NOT EXISTS $warehouses_table ( id INT(11) NOT NULL AUTO_INCREMENT, name VARCHAR(255) NOT NULL, code VARCHAR(50) NOT NULL UNIQUE, supplier_id INT(11), location VARCHAR(255), latitude DECIMAL(10, 8), longitude DECIMAL(11, 8), capacity INT(11) DEFAULT 0, current_load INT(11) DEFAULT 0, lead_time INT(11) DEFAULT 1 COMMENT '交货时间(天)', shipping_cost DECIMAL(10, 2) DEFAULT 0, is_active TINYINT(1) DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), FOREIGN KEY (supplier_id) REFERENCES $suppliers_table(id) ON DELETE SET NULL ) $charset_collate;"; // 库存表 $inventory_table = $wpdb->prefix . 'fsc_inventory'; $sql3 = "CREATE TABLE IF NOT EXISTS $inventory_table ( id INT(11) NOT NULL AUTO_INCREMENT, product_id INT(11) NOT NULL COMMENT '关联WooCommerce产品ID', warehouse_id INT(11) NOT NULL, sku VARCHAR(100), quantity INT(11) DEFAULT 0, reserved_quantity INT(11) DEFAULT 0 COMMENT '已预订数量', safety_stock INT(11) DEFAULT 10 COMMENT '安全库存', reorder_point INT(11) DEFAULT 20 COMMENT '补货点', status ENUM('in_stock', 'low_stock', 'out_of_stock') DEFAULT 'in_stock', last_updated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY product_warehouse (product_id, warehouse_id), FOREIGN KEY (warehouse_id) REFERENCES $warehouses_table(id) ON DELETE CASCADE ) $charset_collate;"; // 订单分配表 $allocations_table = $wpdb->prefix . 'fsc_allocations'; $sql4 = "CREATE TABLE IF NOT EXISTS $allocations_table ( id INT(11) NOT NULL AUTO_INCREMENT, order_id INT(11) NOT NULL COMMENT 'WooCommerce订单ID', order_item_id INT(11) NOT NULL, product_id INT(11) NOT NULL, warehouse_id INT(11) NOT NULL, quantity INT(11) NOT NULL, allocation_type ENUM('auto', 'manual') DEFAULT 'auto', status ENUM('pending', 'confirmed', 'shipped', 'delivered') DEFAULT 'pending', estimated_ship_date DATE, actual_ship_date DATE, tracking_number VARCHAR(100), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), FOREIGN KEY (warehouse_id) REFERENCES $warehouses_table(id) ON DELETE CASCADE ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql1); dbDelta($sql2); dbDelta($sql3); dbDelta($sql4); // 添加版本号到选项表,便于后续升级 add_option('fsc_db_version', FSC_VERSION); } ?>
- 柔性供应链的核心是智能分配算法。以下是一个基于多因素决策的库存分配算法: <?php /** * 智能库存分配算法 * @param int $product_id 产品ID * @param int $required_quantity 需求数量 * @param array $customer_location 客户位置 [latitude, longitude] * @return array 分配结果 */ public function allocate_inventory($product_id, $required_quantity, $customer_location = null) { global $wpdb; $allocations = array(); $remaining_quantity = $required_quantity; // 获取所有有库存的仓库 $inventory_table = $wpdb->prefix . 'fsc_inventory'; $warehouses_table = $wpdb->prefix . 'fsc_warehouses'; $query = $wpdb->prepare( "SELECT i.*, w.*, (i.quantity - i.reserved_quantity) as available_quantity, w.shipping_cost, w.lead_time FROM $inventory_table i JOIN $warehouses_table w ON i.warehouse_id = w.id WHERE i.product_id = %d AND (i.quantity - i.reserved_quantity) > 0 AND w.is_active = 1 ORDER BY w.priority DESC, (i.quantity - i.reserved_quantity) DESC", $product_id ); $available_stock = $wpdb->get_results($query); // 如果没有库存,返回空数组 if (empty($available_stock)) { return $allocations; } // 计算每个仓库的得分(多因素决策) $scored_warehouses = array(); foreach ($available_stock as $stock) { $score = 0; // 因素1:库存充足度(30%权重) $availability_score = min(100, ($stock->available_quantity / $required_quantity) * 100); $score += $availability_score * 0.3; // 因素2:交货时间(25%权重) $lead_time_score = max(0, 100 - ($stock->lead_time * 10)); $score += $lead_time_score * 0.25; // 因素3:运输成本(20%权重) $cost_score = max(0, 100 - ($stock->shipping_cost * 5)); $score += $cost_score * 0.2; // 因素4:仓库负载率(15%权重) $load_ratio = $stock->current_load / max(1, $stock->capacity); $load_score = (1 - $load_ratio) * 100; $score += $load_score * 0.15; // 因素5:距离(如果提供了客户位置,10%权重) if ($customer_location && $stock->latitude && $stock->longitude) { $distance = $this->calculate_distance( $customer_location['latitude'], $customer_location['longitude'], $stock->latitude, $stock->longitude ); $distance_score = max(0, 100 - ($distance * 0.1)); $score += $distance_score * 0.1; } $scored_warehouses[] = array( 'warehouse' => $stock, 'score' => $score, 'available_quantity' => $stock->available_quantity ); } // 按得分排序 usort($scored_warehouses, function($a, $b) { return $b['score'] <=> $a['score']; }); // 分配库存 foreach ($scored_warehouses as $scored) { if ($remaining_quantity <= 0) break; $warehouse = $scored['warehouse']; $allocate_quantity = min($scored['available_quantity'], $remaining_quantity); $allocations[] = array( 'warehouse_id' => $warehouse->id, 'warehouse_name' => $warehouse->name, 'quantity' => $allocate_quantity, 'lead_time' => $warehouse->lead_time, 'shipping_cost' => $warehouse->shipping_cost, 'score' => $scored['score'] ); $remaining_quantity -= $allocate_quantity; } // 如果还有剩余需求,尝试从低优先级仓库分配 if ($remaining_quantity > 0) { // 这里可以添加备选分配逻辑 error_log("库存不足: 产品{$product_id} 还需要{$remaining_quantity}件"); } return $allocations; } /** * 计算两个坐标之间的距离(公里) * 使用Haversine公式 */ private function calculate_distance($lat1, $lon1, $lat2, $lon2) { $earth_radius = 6371; // 地球半径,单位公里 $lat1_rad = deg2rad($lat1); $lon1_rad = deg2rad($lon1); $lat2_rad = deg2rad($lat2); $lon2_rad = deg2rad($lon2); $delta_lat = $lat2_rad - $lat1_rad; $delta_lon = $lon2_rad - $lon1_rad; $a = sin($delta_lat/2) * sin($delta_lat/2) + cos($lat1_rad) * cos($lat2_rad) * sin($delta_lon/2) * sin($delta_lon/2); $c = 2 * atan2(sqrt($a), sqrt(1-$a)); return $earth_radius * $c; } ?>
- 将我们的供应链系统与WooCommerce订单系统集成: <?php /** * WooCommerce订单集成 */ class FSC_WooCommerce_Integration { public function __construct() { // 订单状态变更钩子 add_action('woocommerce_order_status_processing', array($this, 'process_order_allocation'), 10, 1); add_action('woocommerce_order_status_completed', array($this, 'update_inventory_after_shipment'), 10, 1); // 添加订单详情页的供应链信息 add_action('woocommerce_order_details_after_order_table', array($this, 'display_supply_chain_info'), 10, 1); // 后台订单详情添加分配信息 add_action('add_meta_boxes', array($this, 'add_order_meta_box')); } /** * 处理订单分配 */ public function process_order_allocation($order_id) { $order = wc_get_order($order_id); if (!$order) { return; } // 获取客户位置(如果有) $customer_location = $this->get_customer_location($order); // 遍历订单中的每个商品 foreach ($order->get_items() as $item_id => $item) { $product_id = $item->get_product_id(); $quantity = $item->get_quantity(); // 调用智能分配算法 $allocations = $this->allocate_inventory($product_id, $quantity, $customer_location); if (!empty($allocations)) { $this->save_allocations($order_id, $item_id, $product_id, $allocations); $this->reserve_inventory($allocations); // 更新订单备注 $allocation_note = "库存已分配: "; foreach ($allocations as $alloc) { $allocation_note .= "{$alloc['warehouse_name']}({$alloc['quantity']}件) "; } $order->add_order_note($allocation_note); } else { // 库存不足处理 $order->add_order_note("库存不足,产品ID: {$product_id}"); $order->update_status('on-hold', '等待库存补充'); } } } /** * 保存分配记录到数据库 */ private function save_allocations($order_id, $item_id, $product_id, $allocations) { global $wpdb; $table = $wpdb->prefix . 'fsc_allocations'; foreach ($allocations as $alloc) { $wpdb->insert( $table, array( 'order_id' => $order_id, 'order_item_id' => $item_id, 'product_id' => $product_id, 'warehouse_id' => $alloc['warehouse_id'], 'quantity' => $alloc['quantity'], 'allocation_type' => 'auto', 'status' => 'confirmed', 'estimated_ship_date' => date('Y-m-d', strtotime("+{$alloc['lead_time']} days")) ), array('%d', '%d', '%d', '%d', '%d', '%s', '%s', '%s') ); } } /** * 预留库存 */ private function reserve_inventory($allocations) { global $wpdb; $table = $wpdb->prefix . 'fsc_inventory'; foreach ($allocations as $alloc) { $wpdb->query( $wpdb->prepare( "UPDATE $table SET reserved_quantity = reserved_quantity + %d WHERE warehouse_id = %d", $alloc['quantity'], $alloc['warehouse_id'] ) ); } } /** * 添加订单详情元框 */ public function add_order_meta_box() { add_meta_box( 'fsc_order_allocation', '供应链分配信息', array($this, 'render_order_meta_box'), 'shop_order', 'side', 'high' ); } /** * 渲染订单元框内容 */ public function render_order_meta_box($post) { global $wpdb; $order_id = $post->ID; $allocations_table = $wpdb->prefix . 'fsc_allocations'; $warehouses_table = $wpdb->prefix . 'fsc_warehouses'; $allocations = $wpdb->get_results( $wpdb->prepare( "SELECT a.*, w.name as warehouse_name FROM $allocations_table a JOIN $warehouses_table w ON a.warehouse_id = w.id WHERE a.order_id = %d", $order_id ) ); if ($allocations) { echo '<div class="fsc-allocation-info">'; echo '<h4>库存分配详情:</h4>'; echo '<ul>'; foreach ($allocations as $alloc) { echo '<li>'; echo "仓库: {$alloc->warehouse_name}<br>"; echo "产品ID: {$alloc->product_id}<br>"; echo "数量: {$alloc->quantity}<br>"; echo "状态: {$alloc->status}<br>"; echo "预计发货: " . ($alloc->estimated_ship_date ?: '未设置') . "<br>"; if ($alloc->tracking_number) { echo "物流单号: {$alloc->tracking_number}"; } echo '</li>'; } echo '</ul>'; // 添加手动重新分配按钮 echo '<button type="button" class="button button-secondary" id="reallocate-inventory">重新分配库存</button>'; echo '</div>'; // 添加JavaScript处理重新分配 echo '<script> jQuery(document).ready(function($) { $("#reallocate-inventory").click(function() { if (confirm("确定要重新分配库存吗?这将取消当前的分配并尝试新的分配策略。")) { $.post(ajaxurl, { action: "fsc_reallocate_order", order_id: ' . $order_id . ', nonce: "' . wp_create_nonce('fsc_reallocate') . '" }, function(response) { if (response.success) { location.reload(); } else { alert("重新分配失败: " + response.data); } }); } }); }); </script>'; } else { echo '<p>暂无分配信息</p>'; echo '<button type="button" class="button button-primary" id="allocate-inventory">分配库存</button>'; } } } ?>
- 创建直观的管理界面,让用户可以轻松管理供应链节点: <?php /** * 供应链管理仪表板 */ class FSC_Admin_Dashboard { public function __construct() { add_action('admin_menu', array($this, 'register_admin_pages')); add_action('admin_init', array($this, 'register_settings')); add_action('wp_ajax_fsc_get_dashboard_data', array($this, 'ajax_get_dashboard_data')); } /** * 注册管理页面 */ public function register_admin_pages() { // 主菜单 add_menu_page( '柔性供应链', '供应链管理', 'manage_options', 'fsc-dashboard', array($this, 'render_dashboard'), 'dashicons-networking', 30 ); // 子菜单 add_submenu_page( 'fsc-dashboard', '仓库管理', '仓库节点', 'manage_options', 'fsc-warehouses', array($this, 'render_warehouses_page') ); add_submenu_page( 'fsc-dashboard', '供应商管理', '供应商', 'manage_options', 'fsc-suppliers', array($this, 'render_suppliers_page') ); add_submenu_page( 'fsc-dashboard', '库存监控', '库存监控', 'manage_options', 'fsc-inventory', array($this, 'render_inventory_page') ); add_submenu_page( 'fsc-dashboard', '分配记录', '分配记录', 'manage_options', 'fsc-allocations', array($this, 'render_allocations_page') ); add_submenu_page( 'fsc-dashboard', '系统设置', '系统设置', 'manage_options', 'fsc-settings', array($this, 'render_settings_page') ); } /** * 渲染仪表板 */ public function render_dashboard() { ?> <div class="wrap fsc-dashboard"> <h1>柔性供应链管理系统</h1> <div class="fsc-stats-row"> <div class="fsc-stat-box"> <h3>活跃仓库</h3> <div class="stat-number" id="active-warehouses">0</div> </div> <div class="fsc-stat-box"> <h3>总库存量</h3> <div class="stat-number" id="total-inventory">0</div> </div> <div class="fsc-stat-box"> <h3>今日分配</h3> <div class="stat-number" id="today-allocations">0</div> </div> <div class="fsc-stat-box"> <h3>低库存预警</h3> <div class="stat-number warning" id="low-stock-alerts">0</div> </div> </div> <div class="fsc-charts-row"> <div class="fsc-chart-container"> <h3>仓库负载率</h3> <canvas id="warehouse-load-chart" width="400" height="200"></canvas> </div> <div class="fsc-chart-container"> <h3>库存分布</h3> <canvas id="inventory-distribution-chart" width="400" height="200"></canvas> </div> </div> <div class="fsc-recent-activity"> <h3>最近活动</h3> <table class="wp-list-table widefat fixed striped"> <thead> <tr> <th>时间</th> <th>订单号</th> <th>产品</th> <th>仓库</th> <th>数量</th> <th>状态</th> </tr> </thead> <tbody id="recent-activities"> <!-- 通过AJAX加载 --> </tbody> </table> </div> </div> <style> .fsc-dashboard { padding: 20px; } .fsc-stats-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin: 20px 0; } .fsc-stat-box { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); text-align: center; } .fsc-stat-box h3 { margin: 0 0 10px 0; color: #666; font-size: 14px; text-transform: uppercase; } .stat-number { font-size: 32px; font-weight: bold; color: #2271b1; } .stat-number.warning { color: #d63638; } .fsc-charts-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 20px; margin: 30px 0; } .fsc-chart-container { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .fsc-recent-activity { margin-top: 30px; } </style> <script> jQuery(document).ready(function($) { // 加载仪表板数据 function loadDashboardData() { $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'fsc_get_dashboard_data' }, success: function(response) { if (response.success) { var data = response.data; // 更新统计数据 $('#active-warehouses').text(data.stats.active_warehouses); $('#total-inventory').text(data.stats.total_inventory); $('#today-allocations').text(data.stats.today_allocations); $('#low-stock-alerts').text(data.stats.low_stock_alerts); // 更新最近活动 var activitiesHtml = ''; data.recent_activities.forEach(function(activity) { activitiesHtml += '<tr>' + '<td>' + activity.time + '</td>' + '<td>#' + activity.order_id + '</td>' + '<td>' + activity.product_name + '</td>' + '<td>' + activity.warehouse_name + '</td>' + '<td>' + activity.quantity + '</td>' + '<td><span class="status-' + activity.status + '">' + activity.status_text + '</span></td>' + '</tr>'; }); $('#recent-activities').html(activitiesHtml); // 渲染图表 renderCharts(data.charts); } } }); } // 渲染图表 function renderCharts(chartData) { // 仓库负载图表 var loadCtx = document.getElementById('warehouse-load-chart').getContext('2d'); new Chart(loadCtx, { type: 'bar', data: { labels: chartData.warehouse_load.labels, datasets: [{ label: '负载率 (%)', data: chartData.warehouse_load.data, backgroundColor: 'rgba(54, 162, 235, 0.5)', borderColor: 'rgba(54, 162, 235, 1)', borderWidth: 1 }] }, options: { responsive: true, scales: { y: { beginAtZero: true, max: 100 } } } }); // 库存分布图表 var distCtx = document.getElementById('inventory-distribution-chart').getContext('2d'); new Chart(distCtx, { type: 'doughnut', data: { labels: chartData.inventory_distribution.labels, datasets: [{ data: chartData.inventory_distribution.data, backgroundColor: [ '#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40' ] }] } }); } // 初始加载 loadDashboardData(); // 每5分钟刷新一次 setInterval(loadDashboardData, 300000); }); </script> <?php } /** * AJAX获取仪表板数据 */ public function ajax_get_dashboard_data() { global $wpdb; // 验证权限 if (!current_user_can('manage_options')) { wp_die('权限不足'); } $data = array( 'stats' => $this->get_dashboard_stats(), 'recent_activities' => $this->get_recent_activities(), 'charts' => $this->get_chart_data() ); wp_send_json_success($data); } /** * 获取仪表板统计数据 */ private function get_dashboard_stats() { global $wpdb; $warehouses_table = $wpdb->prefix . 'fsc_warehouses'; $inventory_table = $wpdb->prefix . 'fsc_inventory'; $allocations_table = $wpdb->prefix . 'fsc_allocations'; $stats = array( 'active_warehouses' => $wpdb->get_var("SELECT COUNT(*) FROM $warehouses_table WHERE is_active = 1"), 'total_inventory' => $wpdb->get_var("SELECT SUM(quantity) FROM $inventory_table"), 'today_allocations' => $wpdb->get_var($wpdb->prepare( "SELECT COUNT(*) FROM $allocations_table WHERE DATE(created_at) = %s", date('Y-m-d') )), 'low_stock_alerts' => $wpdb->get_var("SELECT COUNT(*) FROM $inventory_table WHERE status = 'low_stock'") ); return $stats; } } ?>
- 创建REST API接口,实现与外部系统的集成: <?php /** * REST API接口 */ class FSC_REST_API { public function __construct() { add_action('rest_api_init', array($this, 'register_routes')); } /** * 注册REST API路由 */ public function register_routes() { // 库存查询接口 register_rest_route('fsc/v1', '/inventory/(?P<product_id>d+)', array( 'methods' => 'GET', 'callback' => array($this, 'get_inventory'), 'permission_callback' => array($this, 'check_api_permission'), 'args' => array( 'product_id' => array( 'validate_callback' => function($param) { return is_numeric($param); } ) ) )); // 库存更新接口 register_rest_route('fsc/v1', '/inventory', array( 'methods' => 'POST', 'callback' => array($this, 'update_inventory'), 'permission_callback' => array($this, 'check_api_permission') )); // 订单分配接口 register_rest_route('fsc/v1', '/allocate', array( 'methods' => 'POST', 'callback' => array($this, 'allocate_order'), 'permission_callback' => array($this, 'check_api_permission') )); // 仓库状态接口 register_rest_route('fsc/v1', '/warehouses', array( 'methods' => 'GET', 'callback' => array($this, 'get_warehouses'), 'permission_callback' => array($this, 'check_api_permission') )); } /** * API权限检查 */ public function check_api_permission($request) { // 检查API密钥 $api_key = $request->get_header('X-FSC-API-Key'); if (!$api_key) { return new WP_Error('rest_forbidden', '缺少API密钥', array('status' => 401)); } // 验证API密钥(这里应该从数据库或设置中获取) $valid_key = get_option('fsc_api_key', ''); if ($api_key !== $valid_key) { return new WP_Error('rest_forbidden', '无效的API密钥', array('status' => 403)); } return true; } /** * 获取库存信息 */ public function get_inventory($request) { global $wpdb; $product_id = $request['product_id']; $inventory_table = $wpdb->prefix . 'fsc_inventory'; $warehouses_table = $wpdb->prefix . 'fsc_warehouses'; $results = $wpdb->get_results($wpdb->prepare( "SELECT i.*, w.name as warehouse_name, w.location, (i.quantity - i.reserved_quantity) as available_quantity FROM $inventory_table i JOIN $warehouses_table w ON i.warehouse_id = w.id WHERE i.product_id = %d AND w.is_active = 1", $product_id )); $inventory_data = array(); $total_available = 0; foreach ($results as $row) { $inventory_data[] = array( 'warehouse_id' => $row->warehouse_id, 'warehouse_name' => $row->warehouse_name, 'location' => $row->location, 'quantity' => $row->quantity, 'reserved_quantity' => $row->reserved_quantity, 'available_quantity' => $row->available_quantity, 'safety_stock' => $row->safety_stock, 'status' => $row->status, 'last_updated' => $row->last_updated ); $total_available += $row->available_quantity; } return array( 'product_id' => $product_id, 'total_available' => $total_available, 'inventory' => $inventory_data, 'timestamp' => current_time('mysql') ); } /** * 更新库存 */ public function update_inventory($request) { global $wpdb; $params = $request->get_json_params(); // 验证必要参数 if (empty($params['warehouse_id']) || empty($params['product_id']) || !isset($params['quantity'])) { return new WP_Error('invalid_params', '缺少必要参数', array('status' => 400)); } $inventory_table = $wpdb->prefix . 'fsc_inventory'; // 检查记录是否存在 $existing = $wpdb->get_row($wpdb->prepare( "SELECT * FROM $inventory_table WHERE warehouse_id = %d AND product_id = %d", $params['warehouse_id'], $params['product_id'] )); if ($existing) { // 更新现有记录 $wpdb->update( $inventory_table, array( 'quantity' => $params['quantity'], 'last_updated' => current_time('mysql') ), array( 'warehouse_id' => $params['warehouse_id'], 'product_id' => $params['product_id'] ) ); } else { // 插入新记录 $wpdb->insert( $inventory_table, array( 'warehouse_id' => $params['warehouse_id'], 'product_id' => $params['product_id'], 'quantity' => $params['quantity'], 'sku' => $params['sku'] ?? '', 'safety_stock' => $params['safety_stock'] ?? 10, 'reorder_point' => $params['reorder_point'] ?? 20 ) ); } // 更新库存状态 $this->update_inventory_status($params['warehouse_id'], $params['product_id']); return array( 'success' => true, 'message' => '库存更新成功',
在当今电商竞争激烈的环境中,传统的单一供应链系统已无法满足企业的多样化需求。特别是对于使用WordPress搭建电商网站的中小企业来说,一个能够灵活调配多个供应商、仓库和物流节点的系统至关重要。本文将带您一步步开发一个WordPress多节点柔性供应链插件,实现库存智能分配、供应商自动选择和物流优化等功能。
首先,我们需要创建插件的基础结构。在WordPress的wp-content/plugins/目录下创建新文件夹flexible-supply-chain。
<?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('FSC_VERSION', '1.0.0');
define('FSC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('FSC_PLUGIN_URL', plugin_dir_url(__FILE__));
// 初始化插件
class FlexibleSupplyChain {
private static $instance = null;
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->init_hooks();
}
private function init_hooks() {
// 激活/停用钩子
register_activation_hook(__FILE__, array($this, 'activate'));
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
// 初始化
add_action('init', array($this, 'init'));
// 管理菜单
add_action('admin_menu', array($this, 'add_admin_menu'));
// 加载脚本和样式
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
}
public function activate() {
$this->create_tables();
$this->create_default_settings();
}
public function deactivate() {
// 清理临时数据
}
public function init() {
// 初始化代码
}
// 其他方法将在后续实现
}
// 启动插件
FlexibleSupplyChain::get_instance();
?>
柔性供应链系统需要存储供应商、仓库、库存和订单分配等信息。我们创建以下数据库表:
<?php
/**
* 创建数据库表
*/
private function create_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// 供应商表
$suppliers_table = $wpdb->prefix . 'fsc_suppliers';
$sql1 = "CREATE TABLE IF NOT EXISTS $suppliers_table (
id INT(11) NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
code VARCHAR(50) NOT NULL UNIQUE,
contact_person VARCHAR(100),
email VARCHAR(100),
phone VARCHAR(50),
address TEXT,
priority INT(11) DEFAULT 0,
is_active TINYINT(1) DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
// 仓库节点表
$warehouses_table = $wpdb->prefix . 'fsc_warehouses';
$sql2 = "CREATE TABLE IF NOT EXISTS $warehouses_table (
id INT(11) NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
code VARCHAR(50) NOT NULL UNIQUE,
supplier_id INT(11),
location VARCHAR(255),
latitude DECIMAL(10, 8),
longitude DECIMAL(11, 8),
capacity INT(11) DEFAULT 0,
current_load INT(11) DEFAULT 0,
lead_time INT(11) DEFAULT 1 COMMENT '交货时间(天)',
shipping_cost DECIMAL(10, 2) DEFAULT 0,
is_active TINYINT(1) DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
FOREIGN KEY (supplier_id) REFERENCES $suppliers_table(id) ON DELETE SET NULL
) $charset_collate;";
// 库存表
$inventory_table = $wpdb->prefix . 'fsc_inventory';
$sql3 = "CREATE TABLE IF NOT EXISTS $inventory_table (
id INT(11) NOT NULL AUTO_INCREMENT,
product_id INT(11) NOT NULL COMMENT '关联WooCommerce产品ID',
warehouse_id INT(11) NOT NULL,
sku VARCHAR(100),
quantity INT(11) DEFAULT 0,
reserved_quantity INT(11) DEFAULT 0 COMMENT '已预订数量',
safety_stock INT(11) DEFAULT 10 COMMENT '安全库存',
reorder_point INT(11) DEFAULT 20 COMMENT '补货点',
status ENUM('in_stock', 'low_stock', 'out_of_stock') DEFAULT 'in_stock',
last_updated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY product_warehouse (product_id, warehouse_id),
FOREIGN KEY (warehouse_id) REFERENCES $warehouses_table(id) ON DELETE CASCADE
) $charset_collate;";
// 订单分配表
$allocations_table = $wpdb->prefix . 'fsc_allocations';
$sql4 = "CREATE TABLE IF NOT EXISTS $allocations_table (
id INT(11) NOT NULL AUTO_INCREMENT,
order_id INT(11) NOT NULL COMMENT 'WooCommerce订单ID',
order_item_id INT(11) NOT NULL,
product_id INT(11) NOT NULL,
warehouse_id INT(11) NOT NULL,
quantity INT(11) NOT NULL,
allocation_type ENUM('auto', 'manual') DEFAULT 'auto',
status ENUM('pending', 'confirmed', 'shipped', 'delivered') DEFAULT 'pending',
estimated_ship_date DATE,
actual_ship_date DATE,
tracking_number VARCHAR(100),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
FOREIGN KEY (warehouse_id) REFERENCES $warehouses_table(id) ON DELETE CASCADE
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql1);
dbDelta($sql2);
dbDelta($sql3);
dbDelta($sql4);
// 添加版本号到选项表,便于后续升级
add_option('fsc_db_version', FSC_VERSION);
}
?>
柔性供应链的核心是智能分配算法。以下是一个基于多因素决策的库存分配算法:
<?php
/**
* 智能库存分配算法
* @param int $product_id 产品ID
* @param int $required_quantity 需求数量
* @param array $customer_location 客户位置 [latitude, longitude]
* @return array 分配结果
*/
public function allocate_inventory($product_id, $required_quantity, $customer_location = null) {
global $wpdb;
$allocations = array();
$remaining_quantity = $required_quantity;
// 获取所有有库存的仓库
$inventory_table = $wpdb->prefix . 'fsc_inventory';
$warehouses_table = $wpdb->prefix . 'fsc_warehouses';
$query = $wpdb->prepare(
"SELECT i.*, w.*,
(i.quantity - i.reserved_quantity) as available_quantity,
w.shipping_cost,
w.lead_time
FROM $inventory_table i
JOIN $warehouses_table w ON i.warehouse_id = w.id
WHERE i.product_id = %d
AND (i.quantity - i.reserved_quantity) > 0
AND w.is_active = 1
ORDER BY w.priority DESC,
(i.quantity - i.reserved_quantity) DESC",
$product_id
);
$available_stock = $wpdb->get_results($query);
// 如果没有库存,返回空数组
if (empty($available_stock)) {
return $allocations;
}
// 计算每个仓库的得分(多因素决策)
$scored_warehouses = array();
foreach ($available_stock as $stock) {
$score = 0;
// 因素1:库存充足度(30%权重)
$availability_score = min(100, ($stock->available_quantity / $required_quantity) * 100);
$score += $availability_score * 0.3;
// 因素2:交货时间(25%权重)
$lead_time_score = max(0, 100 - ($stock->lead_time * 10));
$score += $lead_time_score * 0.25;
// 因素3:运输成本(20%权重)
$cost_score = max(0, 100 - ($stock->shipping_cost * 5));
$score += $cost_score * 0.2;
// 因素4:仓库负载率(15%权重)
$load_ratio = $stock->current_load / max(1, $stock->capacity);
$load_score = (1 - $load_ratio) * 100;
$score += $load_score * 0.15;
// 因素5:距离(如果提供了客户位置,10%权重)
if ($customer_location && $stock->latitude && $stock->longitude) {
$distance = $this->calculate_distance(
$customer_location['latitude'],
$customer_location['longitude'],
$stock->latitude,
$stock->longitude
);
$distance_score = max(0, 100 - ($distance * 0.1));
$score += $distance_score * 0.1;
}
$scored_warehouses[] = array(
'warehouse' => $stock,
'score' => $score,
'available_quantity' => $stock->available_quantity
);
}
// 按得分排序
usort($scored_warehouses, function($a, $b) {
return $b['score'] <=> $a['score'];
});
// 分配库存
foreach ($scored_warehouses as $scored) {
if ($remaining_quantity <= 0) break;
$warehouse = $scored['warehouse'];
$allocate_quantity = min($scored['available_quantity'], $remaining_quantity);
$allocations[] = array(
'warehouse_id' => $warehouse->id,
'warehouse_name' => $warehouse->name,
'quantity' => $allocate_quantity,
'lead_time' => $warehouse->lead_time,
'shipping_cost' => $warehouse->shipping_cost,
'score' => $scored['score']
);
$remaining_quantity -= $allocate_quantity;
}
// 如果还有剩余需求,尝试从低优先级仓库分配
if ($remaining_quantity > 0) {
// 这里可以添加备选分配逻辑
error_log("库存不足: 产品{$product_id} 还需要{$remaining_quantity}件");
}
return $allocations;
}
/**
* 计算两个坐标之间的距离(公里)
* 使用Haversine公式
*/
private function calculate_distance($lat1, $lon1, $lat2, $lon2) {
$earth_radius = 6371; // 地球半径,单位公里
$lat1_rad = deg2rad($lat1);
$lon1_rad = deg2rad($lon1);
$lat2_rad = deg2rad($lat2);
$lon2_rad = deg2rad($lon2);
$delta_lat = $lat2_rad - $lat1_rad;
$delta_lon = $lon2_rad - $lon1_rad;
$a = sin($delta_lat/2) * sin($delta_lat/2) +
cos($lat1_rad) * cos($lat2_rad) *
sin($delta_lon/2) * sin($delta_lon/2);
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
return $earth_radius * $c;
}
?>
将我们的供应链系统与WooCommerce订单系统集成:
<?php
/**
* WooCommerce订单集成
*/
class FSC_WooCommerce_Integration {
public function __construct() {
// 订单状态变更钩子
add_action('woocommerce_order_status_processing', array($this, 'process_order_allocation'), 10, 1);
add_action('woocommerce_order_status_completed', array($this, 'update_inventory_after_shipment'), 10, 1);
// 添加订单详情页的供应链信息
add_action('woocommerce_order_details_after_order_table', array($this, 'display_supply_chain_info'), 10, 1);
// 后台订单详情添加分配信息
add_action('add_meta_boxes', array($this, 'add_order_meta_box'));
}
/**
* 处理订单分配
*/
public function process_order_allocation($order_id) {
$order = wc_get_order($order_id);
if (!$order) {
return;
}
// 获取客户位置(如果有)
$customer_location = $this->get_customer_location($order);
// 遍历订单中的每个商品
foreach ($order->get_items() as $item_id => $item) {
$product_id = $item->get_product_id();
$quantity = $item->get_quantity();
// 调用智能分配算法
$allocations = $this->allocate_inventory($product_id, $quantity, $customer_location);
if (!empty($allocations)) {
$this->save_allocations($order_id, $item_id, $product_id, $allocations);
$this->reserve_inventory($allocations);
// 更新订单备注
$allocation_note = "库存已分配: ";
foreach ($allocations as $alloc) {
$allocation_note .= "{$alloc['warehouse_name']}({$alloc['quantity']}件) ";
}
$order->add_order_note($allocation_note);
} else {
// 库存不足处理
$order->add_order_note("库存不足,产品ID: {$product_id}");
$order->update_status('on-hold', '等待库存补充');
}
}
}
/**
* 保存分配记录到数据库
*/
private function save_allocations($order_id, $item_id, $product_id, $allocations) {
global $wpdb;
$table = $wpdb->prefix . 'fsc_allocations';
foreach ($allocations as $alloc) {
$wpdb->insert(
$table,
array(
'order_id' => $order_id,
'order_item_id' => $item_id,
'product_id' => $product_id,
'warehouse_id' => $alloc['warehouse_id'],
'quantity' => $alloc['quantity'],
'allocation_type' => 'auto',
'status' => 'confirmed',
'estimated_ship_date' => date('Y-m-d', strtotime("+{$alloc['lead_time']} days"))
),
array('%d', '%d', '%d', '%d', '%d', '%s', '%s', '%s')
);
}
}
/**
* 预留库存
*/
private function reserve_inventory($allocations) {
global $wpdb;
$table = $wpdb->prefix . 'fsc_inventory';
foreach ($allocations as $alloc) {
$wpdb->query(
$wpdb->prepare(
"UPDATE $table
SET reserved_quantity = reserved_quantity + %d
WHERE warehouse_id = %d",
$alloc['quantity'],
$alloc['warehouse_id']
)
);
}
}
/**
* 添加订单详情元框
*/
public function add_order_meta_box() {
add_meta_box(
'fsc_order_allocation',
'供应链分配信息',
array($this, 'render_order_meta_box'),
'shop_order',
'side',
'high'
);
}
/**
* 渲染订单元框内容
*/
public function render_order_meta_box($post) {
global $wpdb;
$order_id = $post->ID;
$allocations_table = $wpdb->prefix . 'fsc_allocations';
$warehouses_table = $wpdb->prefix . 'fsc_warehouses';
$allocations = $wpdb->get_results(
$wpdb->prepare(
"SELECT a.*, w.name as warehouse_name
FROM $allocations_table a
JOIN $warehouses_table w ON a.warehouse_id = w.id
WHERE a.order_id = %d",
$order_id
)
);
if ($allocations) {
echo '<div class="fsc-allocation-info">';
echo '<h4>库存分配详情:</h4>';
echo '<ul>';
foreach ($allocations as $alloc) {
echo '<li>';
echo "仓库: {$alloc->warehouse_name}<br>";
echo "产品ID: {$alloc->product_id}<br>";
echo "数量: {$alloc->quantity}<br>";
echo "状态: {$alloc->status}<br>";
echo "预计发货: " . ($alloc->estimated_ship_date ?: '未设置') . "<br>";
if ($alloc->tracking_number) {
echo "物流单号: {$alloc->tracking_number}";
}
echo '</li>';
}
echo '</ul>';
// 添加手动重新分配按钮
echo '<button type="button" class="button button-secondary" id="reallocate-inventory">重新分配库存</button>';
echo '</div>';
// 添加JavaScript处理重新分配
echo '<script>
jQuery(document).ready(function($) {
$("#reallocate-inventory").click(function() {
if (confirm("确定要重新分配库存吗?这将取消当前的分配并尝试新的分配策略。")) {
$.post(ajaxurl, {
action: "fsc_reallocate_order",
order_id: ' . $order_id . ',
nonce: "' . wp_create_nonce('fsc_reallocate') . '"
}, function(response) {
if (response.success) {
location.reload();
} else {
alert("重新分配失败: " + response.data);
}
});
}
});
});
</script>';
} else {
echo '<p>暂无分配信息</p>';
echo '<button type="button" class="button button-primary" id="allocate-inventory">分配库存</button>';
}
}
}
?>
创建直观的管理界面,让用户可以轻松管理供应链节点:
<?php
/**
* 供应链管理仪表板
*/
class FSC_Admin_Dashboard {
public function __construct() {
add_action('admin_menu', array($this, 'register_admin_pages'));
add_action('admin_init', array($this, 'register_settings'));
add_action('wp_ajax_fsc_get_dashboard_data', array($this, 'ajax_get_dashboard_data'));
}
/**
* 注册管理页面
*/
public function register_admin_pages() {
// 主菜单
add_menu_page(
'柔性供应链',
'供应链管理',
'manage_options',
'fsc-dashboard',
array($this, 'render_dashboard'),
'dashicons-networking',
30
);
// 子菜单
add_submenu_page(
'fsc-dashboard',
'仓库管理',
'仓库节点',
'manage_options',
'fsc-warehouses',
array($this, 'render_warehouses_page')
);
add_submenu_page(
'fsc-dashboard',
'供应商管理',
'供应商',
'manage_options',
'fsc-suppliers',
array($this, 'render_suppliers_page')
);
add_submenu_page(
'fsc-dashboard',
'库存监控',
'库存监控',
'manage_options',
'fsc-inventory',
array($this, 'render_inventory_page')
);
add_submenu_page(
'fsc-dashboard',
'分配记录',
'分配记录',
'manage_options',
'fsc-allocations',
array($this, 'render_allocations_page')
);
add_submenu_page(
'fsc-dashboard',
'系统设置',
'系统设置',
'manage_options',
'fsc-settings',
array($this, 'render_settings_page')
);
}
/**
* 渲染仪表板
*/
public function render_dashboard() {
?>
<div class="wrap fsc-dashboard">
<h1>柔性供应链管理系统</h1>
<div class="fsc-stats-row">
<div class="fsc-stat-box">
<h3>活跃仓库</h3>
<div class="stat-number" id="active-warehouses">0</div>
</div>
<div class="fsc-stat-box">
<h3>总库存量</h3>
<div class="stat-number" id="total-inventory">0</div>
</div>
<div class="fsc-stat-box">
<h3>今日分配</h3>
<div class="stat-number" id="today-allocations">0</div>
</div>
<div class="fsc-stat-box">
<h3>低库存预警</h3>
<div class="stat-number warning" id="low-stock-alerts">0</div>
</div>
</div>
<div class="fsc-charts-row">
<div class="fsc-chart-container">
<h3>仓库负载率</h3>
<canvas id="warehouse-load-chart" width="400" height="200"></canvas>
</div>
<div class="fsc-chart-container">
<h3>库存分布</h3>
<canvas id="inventory-distribution-chart" width="400" height="200"></canvas>
</div>
</div>
<div class="fsc-recent-activity">
<h3>最近活动</h3>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th>时间</th>
<th>订单号</th>
<th>产品</th>
<th>仓库</th>
<th>数量</th>
<th>状态</th>
</tr>
</thead>
<tbody id="recent-activities">
<!-- 通过AJAX加载 -->
</tbody>
</table>
</div>
</div>
<style>
.fsc-dashboard {
padding: 20px;
}
.fsc-stats-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin: 20px 0;
}
.fsc-stat-box {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
text-align: center;
}
.fsc-stat-box h3 {
margin: 0 0 10px 0;
color: #666;
font-size: 14px;
text-transform: uppercase;
}
.stat-number {
font-size: 32px;
font-weight: bold;
color: #2271b1;
}
.stat-number.warning {
color: #d63638;
}
.fsc-charts-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 20px;
margin: 30px 0;
}
.fsc-chart-container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.fsc-recent-activity {
margin-top: 30px;
}
</style>
<script>
jQuery(document).ready(function($) {
// 加载仪表板数据
function loadDashboardData() {
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'fsc_get_dashboard_data'
},
success: function(response) {
if (response.success) {
var data = response.data;
// 更新统计数据
$('#active-warehouses').text(data.stats.active_warehouses);
$('#total-inventory').text(data.stats.total_inventory);
$('#today-allocations').text(data.stats.today_allocations);
$('#low-stock-alerts').text(data.stats.low_stock_alerts);
// 更新最近活动
var activitiesHtml = '';
data.recent_activities.forEach(function(activity) {
activitiesHtml += '<tr>' +
'<td>' + activity.time + '</td>' +
'<td>#' + activity.order_id + '</td>' +
'<td>' + activity.product_name + '</td>' +
'<td>' + activity.warehouse_name + '</td>' +
'<td>' + activity.quantity + '</td>' +
'<td><span class="status-' + activity.status + '">' + activity.status_text + '</span></td>' +
'</tr>';
});
$('#recent-activities').html(activitiesHtml);
// 渲染图表
renderCharts(data.charts);
}
}
});
}
// 渲染图表
function renderCharts(chartData) {
// 仓库负载图表
var loadCtx = document.getElementById('warehouse-load-chart').getContext('2d');
new Chart(loadCtx, {
type: 'bar',
data: {
labels: chartData.warehouse_load.labels,
datasets: [{
label: '负载率 (%)',
data: chartData.warehouse_load.data,
backgroundColor: 'rgba(54, 162, 235, 0.5)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true,
max: 100
}
}
}
});
// 库存分布图表
var distCtx = document.getElementById('inventory-distribution-chart').getContext('2d');
new Chart(distCtx, {
type: 'doughnut',
data: {
labels: chartData.inventory_distribution.labels,
datasets: [{
data: chartData.inventory_distribution.data,
backgroundColor: [
'#FF6384',
'#36A2EB',
'#FFCE56',
'#4BC0C0',
'#9966FF',
'#FF9F40'
]
}]
}
});
}
// 初始加载
loadDashboardData();
// 每5分钟刷新一次
setInterval(loadDashboardData, 300000);
});
</script>
<?php
}
/**
* AJAX获取仪表板数据
*/
public function ajax_get_dashboard_data() {
global $wpdb;
// 验证权限
if (!current_user_can('manage_options')) {
wp_die('权限不足');
}
$data = array(
'stats' => $this->get_dashboard_stats(),
'recent_activities' => $this->get_recent_activities(),
'charts' => $this->get_chart_data()
);
wp_send_json_success($data);
}
/**
* 获取仪表板统计数据
*/
private function get_dashboard_stats() {
global $wpdb;
$warehouses_table = $wpdb->prefix . 'fsc_warehouses';
$inventory_table = $wpdb->prefix . 'fsc_inventory';
$allocations_table = $wpdb->prefix . 'fsc_allocations';
$stats = array(
'active_warehouses' => $wpdb->get_var("SELECT COUNT(*) FROM $warehouses_table WHERE is_active = 1"),
'total_inventory' => $wpdb->get_var("SELECT SUM(quantity) FROM $inventory_table"),
'today_allocations' => $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM $allocations_table WHERE DATE(created_at) = %s",
date('Y-m-d')
)),
'low_stock_alerts' => $wpdb->get_var("SELECT COUNT(*) FROM $inventory_table WHERE status = 'low_stock'")
);
return $stats;
}
}
?>
创建REST API接口,实现与外部系统的集成:
<?php
/**
* REST API接口
*/
class FSC_REST_API {
public function __construct() {
add_action('rest_api_init', array($this, 'register_routes'));
}
/**
* 注册REST API路由
*/
public function register_routes() {
// 库存查询接口
register_rest_route('fsc/v1', '/inventory/(?P<product_id>d+)', array(
'methods' => 'GET',
'callback' => array($this, 'get_inventory'),
'permission_callback' => array($this, 'check_api_permission'),
'args' => array(
'product_id' => array(
'validate_callback' => function($param) {
return is_numeric($param);
}
)
)
));
// 库存更新接口
register_rest_route('fsc/v1', '/inventory', array(
'methods' => 'POST',
'callback' => array($this, 'update_inventory'),
'permission_callback' => array($this, 'check_api_permission')
));
// 订单分配接口
register_rest_route('fsc/v1', '/allocate', array(
'methods' => 'POST',
'callback' => array($this, 'allocate_order'),
'permission_callback' => array($this, 'check_api_permission')
));
// 仓库状态接口
register_rest_route('fsc/v1', '/warehouses', array(
'methods' => 'GET',
'callback' => array($this, 'get_warehouses'),
'permission_callback' => array($this, 'check_api_permission')
));
}
/**
* API权限检查
*/
public function check_api_permission($request) {
// 检查API密钥
$api_key = $request->get_header('X-FSC-API-Key');
if (!$api_key) {
return new WP_Error('rest_forbidden', '缺少API密钥', array('status' => 401));
}
// 验证API密钥(这里应该从数据库或设置中获取)
$valid_key = get_option('fsc_api_key', '');
if ($api_key !== $valid_key) {
return new WP_Error('rest_forbidden', '无效的API密钥', array('status' => 403));
}
return true;
}
/**
* 获取库存信息
*/
public function get_inventory($request) {
global $wpdb;
$product_id = $request['product_id'];
$inventory_table = $wpdb->prefix . 'fsc_inventory';
$warehouses_table = $wpdb->prefix . 'fsc_warehouses';
$results = $wpdb->get_results($wpdb->prepare(
"SELECT i.*, w.name as warehouse_name, w.location,
(i.quantity - i.reserved_quantity) as available_quantity
FROM $inventory_table i
JOIN $warehouses_table w ON i.warehouse_id = w.id
WHERE i.product_id = %d AND w.is_active = 1",
$product_id
));
$inventory_data = array();
$total_available = 0;
foreach ($results as $row) {
$inventory_data[] = array(
'warehouse_id' => $row->warehouse_id,
'warehouse_name' => $row->warehouse_name,
'location' => $row->location,
'quantity' => $row->quantity,
'reserved_quantity' => $row->reserved_quantity,
'available_quantity' => $row->available_quantity,
'safety_stock' => $row->safety_stock,
'status' => $row->status,
'last_updated' => $row->last_updated
);
$total_available += $row->available_quantity;
}
return array(
'product_id' => $product_id,
'total_available' => $total_available,
'inventory' => $inventory_data,
'timestamp' => current_time('mysql')
);
}
/**
* 更新库存
*/
public function update_inventory($request) {
global $wpdb;
$params = $request->get_json_params();
// 验证必要参数
if (empty($params['warehouse_id']) || empty($params['product_id']) || !isset($params['quantity'])) {
return new WP_Error('invalid_params', '缺少必要参数', array('status' => 400));
}
$inventory_table = $wpdb->prefix . 'fsc_inventory';
// 检查记录是否存在
$existing = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $inventory_table
WHERE warehouse_id = %d AND product_id = %d",
$params['warehouse_id'], $params['product_id']
));
if ($existing) {
// 更新现有记录
$wpdb->update(
$inventory_table,
array(
'quantity' => $params['quantity'],
'last_updated' => current_time('mysql')
),
array(
'warehouse_id' => $params['warehouse_id'],
'product_id' => $params['product_id']
)
);
} else {
// 插入新记录
$wpdb->insert(
$inventory_table,
array(
'warehouse_id' => $params['warehouse_id'],
'product_id' => $params['product_id'],
'quantity' => $params['quantity'],
'sku' => $params['sku'] ?? '',
'safety_stock' => $params['safety_stock'] ?? 10,
'reorder_point' => $params['reorder_point'] ?? 20
)
);
}
// 更新库存状态
$this->update_inventory_status($params['warehouse_id'], $params['product_id']);
return array(
'success' => true,
'message' => '库存更新成功',


