文章目录
-
- 在当今电商竞争激烈的环境中,高效的库存管理是企业成功的关键因素之一。对于拥有多个仓库的企业来说,如何实现库存的智能分配和调拨,直接影响到订单履行效率、运输成本和客户满意度。传统的库存管理方式往往依赖人工判断,容易出现库存分配不均、调拨不及时等问题。 WordPress作为全球最流行的内容管理系统,通过灵活的插件和自定义开发,可以构建强大的供应链管理解决方案。本文将详细介绍如何在WordPress平台上实现一个柔性供应链软件,重点讲解多仓库智能调拨功能的开发与实现。
-
- 首先,我们需要设计合理的数据库结构来支持多仓库库存管理。以下是核心数据表的SQL创建语句: -- 仓库信息表 CREATE TABLE wp_warehouses ( warehouse_id INT AUTO_INCREMENT PRIMARY KEY, warehouse_name VARCHAR(100) NOT NULL, location VARCHAR(255), capacity INT, current_inventory INT DEFAULT 0, contact_person VARCHAR(100), contact_phone VARCHAR(20), is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 商品库存表(记录每个仓库中每个商品的库存) CREATE TABLE wp_product_inventory ( inventory_id INT AUTO_INCREMENT PRIMARY KEY, product_id INT NOT NULL, warehouse_id INT NOT NULL, quantity INT DEFAULT 0, safety_stock INT DEFAULT 10, -- 安全库存 reorder_point INT DEFAULT 20, -- 再订货点 last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (warehouse_id) REFERENCES wp_warehouses(warehouse_id) ); -- 调拨记录表 CREATE TABLE wp_inventory_transfers ( transfer_id INT AUTO_INCREMENT PRIMARY KEY, product_id INT NOT NULL, from_warehouse_id INT NOT NULL, to_warehouse_id INT NOT NULL, quantity INT NOT NULL, transfer_reason VARCHAR(255), status ENUM('pending', 'in_transit', 'completed', 'cancelled') DEFAULT 'pending', requested_by INT, -- 请求用户ID approved_by INT, -- 批准用户ID created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, completed_at TIMESTAMP NULL, FOREIGN KEY (from_warehouse_id) REFERENCES wp_warehouses(warehouse_id), FOREIGN KEY (to_warehouse_id) REFERENCES wp_warehouses(warehouse_id) );
- 仓库管理模块:管理仓库基本信息 库存管理模块:实时监控各仓库库存水平 智能调拨引擎:核心算法模块,自动决定调拨策略 订单路由模块:根据库存情况自动分配订单到最优仓库 报表分析模块:提供库存和调拨数据分析
-
- 智能调拨是系统的核心功能,它需要综合考虑多个因素来决定是否需要调拨以及如何调拨。以下是PHP实现的核心算法: <?php /** * 智能调拨决策引擎 * * @param int $product_id 商品ID * @param int $required_quantity 需求数量 * @param int $destination_warehouse_id 目标仓库ID(订单所在仓库) * @return array 调拨决策结果 */ function intelligent_transfer_decision($product_id, $required_quantity, $destination_warehouse_id) { global $wpdb; $decision = [ 'need_transfer' => false, 'transfer_from' => null, 'transfer_quantity' => 0, 'reason' => '' ]; // 1. 检查目标仓库库存是否充足 $destination_stock = get_warehouse_stock($product_id, $destination_warehouse_id); if ($destination_stock >= $required_quantity) { $decision['reason'] = '目标仓库库存充足,无需调拨'; return $decision; } // 2. 获取所有仓库的库存情况 $warehouses_stock = $wpdb->get_results($wpdb->prepare( "SELECT w.warehouse_id, w.warehouse_name, w.location, pi.quantity, pi.safety_stock, pi.reorder_point FROM wp_warehouses w JOIN wp_product_inventory pi ON w.warehouse_id = pi.warehouse_id WHERE pi.product_id = %d AND w.is_active = 1 ORDER BY w.location ASC", $product_id ), ARRAY_A); // 3. 寻找最优调拨源仓库 $best_source = null; $max_score = 0; foreach ($warehouses_stock as $warehouse) { // 跳过目标仓库 if ($warehouse['warehouse_id'] == $destination_warehouse_id) { continue; } // 计算该仓库作为调拨源的得分 $score = calculate_warehouse_score( $warehouse, $destination_warehouse_id, $required_quantity ); if ($score > $max_score && $warehouse['quantity'] > $warehouse['safety_stock']) { $max_score = $score; $best_source = $warehouse; } } // 4. 做出调拨决策 if ($best_source) { // 计算可调拨数量(不能低于安全库存) $available_quantity = $best_source['quantity'] - $best_source['safety_stock']; $transfer_quantity = min($available_quantity, $required_quantity - $destination_stock); if ($transfer_quantity > 0) { $decision['need_transfer'] = true; $decision['transfer_from'] = $best_source['warehouse_id']; $decision['transfer_quantity'] = $transfer_quantity; $decision['reason'] = sprintf( '从%s调拨%d件商品到目标仓库,基于库存充足度和距离最优原则', $best_source['warehouse_name'], $transfer_quantity ); } } else { $decision['reason'] = '未找到合适的调拨源仓库,所有仓库库存均接近安全库存'; } return $decision; } /** * 计算仓库作为调拨源的得分 * 考虑因素:库存充足度、距离、运输成本等 */ function calculate_warehouse_score($warehouse, $destination_id, $required_quantity) { $score = 0; // 1. 库存充足度得分(40%权重) $excess_stock = $warehouse['quantity'] - $warehouse['safety_stock']; $inventory_score = ($excess_stock / ($required_quantity + 1)) * 40; $score += min($inventory_score, 40); // 2. 距离得分(30%权重)- 这里简化处理,实际应集成地图API $distance = calculate_distance($warehouse['warehouse_id'], $destination_id); $distance_score = (1 / ($distance + 1)) * 30; $score += $distance_score; // 3. 历史调拨效率得分(30%权重) $efficiency_score = get_transfer_efficiency_score($warehouse['warehouse_id'], $destination_id); $score += $efficiency_score * 30; return $score; } ?>
- 当智能调拨引擎做出调拨决策后,需要执行具体的调拨流程: <?php /** * 执行库存调拨 * * @param int $product_id 商品ID * @param int $from_warehouse_id 源仓库ID * @param int $to_warehouse_id 目标仓库ID * @param int $quantity 调拨数量 * @param string $reason 调拨原因 * @return int|false 调拨记录ID或false(失败时) */ function execute_inventory_transfer($product_id, $from_warehouse_id, $to_warehouse_id, $quantity, $reason = '') { global $wpdb; // 验证源仓库库存是否充足 $source_stock = get_warehouse_stock($product_id, $from_warehouse_id); if ($source_stock < $quantity) { return false; } // 开始数据库事务 $wpdb->query('START TRANSACTION'); try { // 1. 创建调拨记录 $transfer_data = [ 'product_id' => $product_id, 'from_warehouse_id' => $from_warehouse_id, 'to_warehouse_id' => $to_warehouse_id, 'quantity' => $quantity, 'transfer_reason' => $reason, 'status' => 'pending', 'requested_by' => get_current_user_id(), 'created_at' => current_time('mysql') ]; $result = $wpdb->insert('wp_inventory_transfers', $transfer_data); if (!$result) { throw new Exception('创建调拨记录失败'); } $transfer_id = $wpdb->insert_id; // 2. 减少源仓库库存(预扣) $update_source = $wpdb->query($wpdb->prepare( "UPDATE wp_product_inventory SET quantity = quantity - %d WHERE product_id = %d AND warehouse_id = %d", $quantity, $product_id, $from_warehouse_id )); if (!$update_source) { throw new Exception('更新源仓库库存失败'); } // 3. 增加目标仓库在途库存(可选,根据业务需求) // 这里可以根据实际业务决定是否立即增加目标仓库库存 // 或者等待调拨完成后再更新 // 4. 记录库存变更日志 log_inventory_change( $product_id, $from_warehouse_id, -$quantity, 'transfer_out', "调拨出库至仓库{$to_warehouse_id},调拨单号:{$transfer_id}" ); // 提交事务 $wpdb->query('COMMIT'); // 5. 发送调拨通知(给相关仓库管理员) send_transfer_notification($transfer_id); return $transfer_id; } catch (Exception $e) { // 回滚事务 $wpdb->query('ROLLBACK'); error_log('调拨执行失败: ' . $e->getMessage()); return false; } } /** * 完成调拨流程(当货物实际到达目标仓库时调用) */ function complete_inventory_transfer($transfer_id) { global $wpdb; // 获取调拨信息 $transfer = $wpdb->get_row($wpdb->prepare( "SELECT * FROM wp_inventory_transfers WHERE transfer_id = %d", $transfer_id ), ARRAY_A); if (!$transfer || $transfer['status'] != 'in_transit') { return false; } $wpdb->query('START TRANSACTION'); try { // 1. 增加目标仓库实际库存 $update_target = $wpdb->query($wpdb->prepare( "UPDATE wp_product_inventory SET quantity = quantity + %d WHERE product_id = %d AND warehouse_id = %d", $transfer['quantity'], $transfer['product_id'], $transfer['to_warehouse_id'] )); if (!$update_target) { // 如果目标仓库还没有该商品的库存记录,则创建一条 $wpdb->insert('wp_product_inventory', [ 'product_id' => $transfer['product_id'], 'warehouse_id' => $transfer['to_warehouse_id'], 'quantity' => $transfer['quantity'] ]); } // 2. 更新调拨状态为已完成 $wpdb->update('wp_inventory_transfers', [ 'status' => 'completed', 'completed_at' => current_time('mysql'), 'approved_by' => get_current_user_id() ], ['transfer_id' => $transfer_id] ); // 3. 记录库存变更日志 log_inventory_change( $transfer['product_id'], $transfer['to_warehouse_id'], $transfer['quantity'], 'transfer_in', "调拨入库自仓库{$transfer['from_warehouse_id']},调拨单号:{$transfer_id}" ); $wpdb->query('COMMIT'); // 4. 触发相关事件(如更新订单状态等) do_action('inventory_transfer_completed', $transfer_id); return true; } catch (Exception $e) { $wpdb->query('ROLLBACK'); error_log('调拨完成失败: ' . $e->getMessage()); return false; } } ?>
-
- <?php /** * 添加供应链管理菜单到WordPress后台 */ add_action('admin_menu', 'register_supply_chain_menu'); function register_supply_chain_menu() { // 主菜单 add_menu_page( '供应链管理', // 页面标题 '供应链管理', // 菜单标题 'manage_options', // 权限 'supply-chain', // 菜单slug 'supply_chain_dashboard', // 回调函数 'dashicons-store', // 图标 30 // 位置 ); // 子菜单:仓库管理 add_submenu_page( 'supply-chain', '仓库管理', '仓库管理', 'manage_options', 'warehouse-management', 'warehouse_management_page' ); // 子菜单:库存调拨 add_submenu_page( 'supply-chain', '库存调拨', '库存调拨', 'manage_options', 'inventory-transfer', 'inventory_transfer_page' ); // 子菜单:调拨记录 add_submenu_page( 'supply-chain', '调拨记录', '调拨记录', 'manage_options', 'transfer-records', 'transfer_records_page' ); } /** * 库存调拨管理页面 */ function inventory_transfer_page() { ?> <div class="wrap"> <h1>智能库存调拨</h1> <div class="card"> <h2>自动调拨决策</h2> <form method="post" action=""> <?php wp_nonce_field('auto_transfer_action', 'transfer_nonce'); ?> <table class="form-table"> <tr> <th scope="row"><label for="product_id">商品</label></th> <td> <select name="product_id" id="product_id" required> <option value="">选择商品...</option> <?php $products = wc_get_products(['limit' => -1]); foreach ($products as $product) { echo '<option value="' . $product->get_id() . '">' . $product->get_name() . '</option>'; } ?> </select> </td> </tr> <tr> <th scope="row"><label for="destination_warehouse">目标仓库</label></th> <td> <select name="destination_warehouse" id="destination_warehouse" required> <option value="">选择目标仓库...</option> <?php $warehouses = get_all_warehouses(); foreach ($warehouses as $warehouse) { echo '<option value="' . $warehouse['warehouse_id'] . '">' . $warehouse['warehouse_name'] . '</option>'; } ?> </select> </td> </tr> <tr> <th scope="row"><label for="required_quantity">需求数量</label></th> <td> <input type="number" name="required_quantity" id="required_quantity" min="1" required> </td> </tr> </table> <p class="submit"> <input type="submit" name="analyze_transfer" class="button button-primary" value="分析调拨需求"> </p> </form> <?php // 处理表单提交 if (isset($_POST['analyze_transfer']) && wp_verify_nonce($_POST['transfer_nonce'], 'auto_transfer_action')) { $product_id = intval($_POST['product_id']); $destination_id = intval($_POST['destination_warehouse']); $required_quantity = intval($_POST['required_quantity']); $decision = intelligent_transfer_decision( $product_id, $required_quantity, $destination_id ); echo '<div class="notice notice-info">'; echo '<h3>调拨分析结果</h3>'; echo '<p><strong>结论:</strong>' . esc_html($decision['reason']) . '</p>'; if ($decision['need_transfer']) { echo '<p><strong>建议调拨:</strong>从仓库#' . $decision['transfer_from'] . ' 调拨 ' . $decision['transfer_quantity'] . ' 件商品</p>'; // 显示执行调拨按钮 echo '<form method="post" action="">'; wp_nonce_field('execute_transfer_action', 'execute_nonce'); echo '<input type="hidden" name="product_id" value="' . $product_id . '">'; echo '<input type="hidden" name="from_warehouse" value="' . $decision['transfer_from'] . '">'; echo '<input type="hidden" name="to_warehouse" value="' . $destination_id . '">'; echo '<input type="hidden" name="quantity" value="' . $decision['transfer_quantity'] . '">'; echo '<input type="submit" name="execute_transfer" class="button button-primary" echo '<input type="submit" name="execute_transfer" class="button button-primary" value="执行调拨">'; echo '</form>'; } echo '</div>'; // 处理执行调拨请求 if (isset($_POST['execute_transfer']) && wp_verify_nonce($_POST['execute_nonce'], 'execute_transfer_action')) { $transfer_id = execute_inventory_transfer( intval($_POST['product_id']), intval($_POST['from_warehouse']), intval($_POST['to_warehouse']), intval($_POST['quantity']), '系统智能调拨' ); if ($transfer_id) { echo '<div class="notice notice-success">'; echo '<p>调拨单创建成功!调拨单号:' . $transfer_id . '</p>'; echo '</div>'; } else { echo '<div class="notice notice-error">'; echo '<p>调拨执行失败,请检查库存情况</p>'; echo '</div>'; } } } ?> </div> <div class="card"> <h2>手动调拨</h2> <form method="post" action=""> <?php wp_nonce_field('manual_transfer_action', 'manual_nonce'); ?> <table class="form-table"> <tr> <th scope="row"><label for="manual_product_id">商品</label></th> <td> <select name="manual_product_id" id="manual_product_id" required> <option value="">选择商品...</option> <?php $products = wc_get_products(['limit' => -1]); foreach ($products as $product) { echo '<option value="' . $product->get_id() . '">' . $product->get_name() . '</option>'; } ?> </select> </td> </tr> <tr> <th scope="row"><label for="from_warehouse">源仓库</label></th> <td> <select name="from_warehouse" id="from_warehouse" required> <option value="">选择源仓库...</option> <?php foreach ($warehouses as $warehouse) { echo '<option value="' . $warehouse['warehouse_id'] . '">' . $warehouse['warehouse_name'] . '</option>'; } ?> </select> </td> </tr> <tr> <th scope="row"><label for="to_warehouse">目标仓库</label></th> <td> <select name="to_warehouse" id="to_warehouse" required> <option value="">选择目标仓库...</option> <?php foreach ($warehouses as $warehouse) { echo '<option value="' . $warehouse['warehouse_id'] . '">' . $warehouse['warehouse_name'] . '</option>'; } ?> </select> </td> </tr> <tr> <th scope="row"><label for="manual_quantity">调拨数量</label></th> <td> <input type="number" name="manual_quantity" id="manual_quantity" min="1" required> </td> </tr> <tr> <th scope="row"><label for="transfer_reason">调拨原因</label></th> <td> <textarea name="transfer_reason" id="transfer_reason" rows="3" cols="50"></textarea> </td> </tr> </table> <p class="submit"> <input type="submit" name="submit_manual_transfer" class="button button-primary" value="提交调拨申请"> </p> </form> </div> </div> <style> .card { background: #fff; border: 1px solid #ccd0d4; box-shadow: 0 1px 1px rgba(0,0,0,.04); margin: 20px 0; padding: 20px; } .form-table th { width: 200px; } </style> <?php } ?>
- <?php /** * 供应链管理仪表板 */ function supply_chain_dashboard() { ?> <div class="wrap"> <h1>供应链管理仪表板</h1> <div class="dashboard-container"> <!-- 库存概览 --> <div class="dashboard-card"> <h3>库存概览</h3> <div class="inventory-summary"> <?php $total_inventory = get_total_inventory_value(); $low_stock_items = get_low_stock_items_count(); $out_of_stock_items = get_out_of_stock_items_count(); ?> <div class="metric"> <span class="metric-value"><?php echo wc_price($total_inventory); ?></span> <span class="metric-label">库存总值</span> </div> <div class="metric"> <span class="metric-value warning"><?php echo $low_stock_items; ?></span> <span class="metric-label">低库存商品</span> </div> <div class="metric"> <span class="metric-value danger"><?php echo $out_of_stock_items; ?></span> <span class="metric-label">缺货商品</span> </div> </div> </div> <!-- 仓库库存分布 --> <div class="dashboard-card wide"> <h3>各仓库库存分布</h3> <div class="warehouse-distribution"> <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> <?php $warehouses = get_all_warehouses_with_inventory(); foreach ($warehouses as $warehouse) { $usage_rate = ($warehouse['current_inventory'] / $warehouse['capacity']) * 100; $usage_class = $usage_rate > 90 ? 'danger' : ($usage_rate > 70 ? 'warning' : ''); ?> <tr> <td><?php echo esc_html($warehouse['warehouse_name']); ?></td> <td><?php echo $warehouse['product_count']; ?></td> <td><?php echo $warehouse['total_quantity']; ?></td> <td><?php echo wc_price($warehouse['inventory_value']); ?></td> <td> <div class="usage-bar"> <div class="usage-fill <?php echo $usage_class; ?>" style="width: <?php echo $usage_rate; ?>%"> <?php echo round($usage_rate, 1); ?>% </div> </div> </td> <td> <a href="<?php echo admin_url('admin.php?page=warehouse-management&id=' . $warehouse['warehouse_id']); ?>" class="button button-small">详情</a> </td> </tr> <?php } ?> </tbody> </table> </div> </div> <!-- 近期调拨活动 --> <div class="dashboard-card"> <h3>近期调拨活动</h3> <div class="recent-transfers"> <?php $recent_transfers = get_recent_transfers(5); if (empty($recent_transfers)) { echo '<p>暂无调拨记录</p>'; } else { echo '<ul>'; foreach ($recent_transfers as $transfer) { $status_class = ''; switch ($transfer['status']) { case 'completed': $status_class = 'success'; break; case 'in_transit': $status_class = 'warning'; break; case 'pending': $status_class = 'info'; break; case 'cancelled': $status_class = 'danger'; break; } ?> <li> <span class="transfer-status <?php echo $status_class; ?>"> <?php echo $transfer['status']; ?> </span> <strong><?php echo get_product_name($transfer['product_id']); ?></strong> (<?php echo $transfer['quantity']; ?>件) <br> <small> 从 <?php echo get_warehouse_name($transfer['from_warehouse_id']); ?> 到 <?php echo get_warehouse_name($transfer['to_warehouse_id']); ?> · <?php echo human_time_diff(strtotime($transfer['created_at']), current_time('timestamp')); ?>前 </small> </li> <?php } echo '</ul>'; } ?> <a href="<?php echo admin_url('admin.php?page=transfer-records'); ?>" class="button">查看所有调拨记录</a> </div> </div> <!-- 智能调拨建议 --> <div class="dashboard-card"> <h3>智能调拨建议</h3> <div class="transfer-suggestions"> <?php $suggestions = get_transfer_suggestions(); if (empty($suggestions)) { echo '<p>暂无调拨建议,库存分布均衡</p>'; } else { echo '<ul>'; foreach ($suggestions as $suggestion) { ?> <li> <strong><?php echo $suggestion['product_name']; ?></strong> <br> 建议从 <em><?php echo $suggestion['from_warehouse']; ?></em> 调拨 <em><?php echo $suggestion['quantity']; ?>件</em> 到 <em><?php echo $suggestion['to_warehouse']; ?></em> <br> <small>原因:<?php echo $suggestion['reason']; ?></small> <br> <button class="button button-small execute-suggestion" data-product="<?php echo $suggestion['product_id']; ?>" data-from="<?php echo $suggestion['from_warehouse_id']; ?>" data-to="<?php echo $suggestion['to_warehouse_id']; ?>" data-quantity="<?php echo $suggestion['quantity']; ?>"> 执行调拨 </button> </li> <?php } echo '</ul>'; } ?> </div> </div> </div> </div> <style> .dashboard-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-top: 20px; } .dashboard-card { background: #fff; border: 1px solid #ccd0d4; border-radius: 4px; padding: 20px; } .dashboard-card.wide { grid-column: span 2; } .inventory-summary { display: flex; justify-content: space-around; text-align: center; } .metric { display: flex; flex-direction: column; } .metric-value { font-size: 24px; font-weight: bold; color: #0073aa; } .metric-value.warning { color: #ffb900; } .metric-value.danger { color: #dc3232; } .metric-label { font-size: 12px; color: #666; margin-top: 5px; } .usage-bar { width: 100%; height: 20px; background: #f0f0f0; border-radius: 10px; overflow: hidden; } .usage-fill { height: 100%; background: #46b450; text-align: center; color: white; font-size: 12px; line-height: 20px; } .usage-fill.warning { background: #ffb900; } .usage-fill.danger { background: #dc3232; } .transfer-status { display: inline-block; padding: 2px 8px; border-radius: 3px; font-size: 11px; text-transform: uppercase; } .transfer-status.success { background: #d4edda; color: #155724; } .transfer-status.warning { background: #fff3cd; color: #856404; } .transfer-status.info { background: #d1ecf1; color: #0c5460; } .transfer-status.danger { background: #f8d7da; color: #721c24; } </style> <script> jQuery(document).ready(function($) { // 执行调拨建议 $('.execute-suggestion').on('click', function() { var button = $(this); var data = { action: 'execute_transfer_suggestion', product_id: button.data('product'), from_warehouse: button.data('from'), to_warehouse: button.data('to'), quantity: button.data('quantity'), nonce: '<?php echo wp_create_nonce('execute_suggestion_nonce'); ?>' }; button.prop('disabled', true).text('处理中...'); $.post(ajaxurl, data, function(response) { if (response.success) { alert('调拨单创建成功!单号:' + response.data.transfer_id); button.closest('li').fadeOut(); } else { alert('操作失败:' + response.data.message); button.prop('disabled', false).text('执行调拨'); } }); }); // 自动刷新仪表板数据(每60秒) setInterval(function() { $.post(ajaxurl, { action: 'refresh_dashboard_data', nonce: '<?php echo wp_create_nonce('refresh_dashboard_nonce'); ?>' }, function(response) { if (response.success) { // 更新相关数据 // 这里可以根据返回的数据更新页面元素 } }); }, 60000); }); </script> <?php } // AJAX处理函数 add_action('wp_ajax_execute_transfer_suggestion', 'ajax_execute_transfer_suggestion'); function ajax_execute_transfer_suggestion() { check_ajax_referer('execute_suggestion_nonce', 'nonce'); $transfer_id = execute_inventory_transfer( intval($_POST['product_id']), intval($_POST['from_warehouse']), intval($_POST['to_warehouse']), intval($_POST['quantity']), '仪表板智能建议调拨' ); if ($transfer_id) { wp_send_json_success(['transfer_id' => $transfer_id]); } else { wp_send_json_error(['message' => '调拨执行失败']); } } ?>
在当今电商竞争激烈的环境中,高效的库存管理是企业成功的关键因素之一。对于拥有多个仓库的企业来说,如何实现库存的智能分配和调拨,直接影响到订单履行效率、运输成本和客户满意度。传统的库存管理方式往往依赖人工判断,容易出现库存分配不均、调拨不及时等问题。
WordPress作为全球最流行的内容管理系统,通过灵活的插件和自定义开发,可以构建强大的供应链管理解决方案。本文将详细介绍如何在WordPress平台上实现一个柔性供应链软件,重点讲解多仓库智能调拨功能的开发与实现。
首先,我们需要设计合理的数据库结构来支持多仓库库存管理。以下是核心数据表的SQL创建语句:
-- 仓库信息表
CREATE TABLE wp_warehouses (
warehouse_id INT AUTO_INCREMENT PRIMARY KEY,
warehouse_name VARCHAR(100) NOT NULL,
location VARCHAR(255),
capacity INT,
current_inventory INT DEFAULT 0,
contact_person VARCHAR(100),
contact_phone VARCHAR(20),
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 商品库存表(记录每个仓库中每个商品的库存)
CREATE TABLE wp_product_inventory (
inventory_id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
warehouse_id INT NOT NULL,
quantity INT DEFAULT 0,
safety_stock INT DEFAULT 10, -- 安全库存
reorder_point INT DEFAULT 20, -- 再订货点
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (warehouse_id) REFERENCES wp_warehouses(warehouse_id)
);
-- 调拨记录表
CREATE TABLE wp_inventory_transfers (
transfer_id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
from_warehouse_id INT NOT NULL,
to_warehouse_id INT NOT NULL,
quantity INT NOT NULL,
transfer_reason VARCHAR(255),
status ENUM('pending', 'in_transit', 'completed', 'cancelled') DEFAULT 'pending',
requested_by INT, -- 请求用户ID
approved_by INT, -- 批准用户ID
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP NULL,
FOREIGN KEY (from_warehouse_id) REFERENCES wp_warehouses(warehouse_id),
FOREIGN KEY (to_warehouse_id) REFERENCES wp_warehouses(warehouse_id)
);
- 仓库管理模块:管理仓库基本信息
- 库存管理模块:实时监控各仓库库存水平
- 智能调拨引擎:核心算法模块,自动决定调拨策略
- 订单路由模块:根据库存情况自动分配订单到最优仓库
- 报表分析模块:提供库存和调拨数据分析
智能调拨是系统的核心功能,它需要综合考虑多个因素来决定是否需要调拨以及如何调拨。以下是PHP实现的核心算法:
<?php
/**
* 智能调拨决策引擎
*
* @param int $product_id 商品ID
* @param int $required_quantity 需求数量
* @param int $destination_warehouse_id 目标仓库ID(订单所在仓库)
* @return array 调拨决策结果
*/
function intelligent_transfer_decision($product_id, $required_quantity, $destination_warehouse_id) {
global $wpdb;
$decision = [
'need_transfer' => false,
'transfer_from' => null,
'transfer_quantity' => 0,
'reason' => ''
];
// 1. 检查目标仓库库存是否充足
$destination_stock = get_warehouse_stock($product_id, $destination_warehouse_id);
if ($destination_stock >= $required_quantity) {
$decision['reason'] = '目标仓库库存充足,无需调拨';
return $decision;
}
// 2. 获取所有仓库的库存情况
$warehouses_stock = $wpdb->get_results($wpdb->prepare(
"SELECT w.warehouse_id, w.warehouse_name, w.location,
pi.quantity, pi.safety_stock, pi.reorder_point
FROM wp_warehouses w
JOIN wp_product_inventory pi ON w.warehouse_id = pi.warehouse_id
WHERE pi.product_id = %d AND w.is_active = 1
ORDER BY w.location ASC",
$product_id
), ARRAY_A);
// 3. 寻找最优调拨源仓库
$best_source = null;
$max_score = 0;
foreach ($warehouses_stock as $warehouse) {
// 跳过目标仓库
if ($warehouse['warehouse_id'] == $destination_warehouse_id) {
continue;
}
// 计算该仓库作为调拨源的得分
$score = calculate_warehouse_score(
$warehouse,
$destination_warehouse_id,
$required_quantity
);
if ($score > $max_score && $warehouse['quantity'] > $warehouse['safety_stock']) {
$max_score = $score;
$best_source = $warehouse;
}
}
// 4. 做出调拨决策
if ($best_source) {
// 计算可调拨数量(不能低于安全库存)
$available_quantity = $best_source['quantity'] - $best_source['safety_stock'];
$transfer_quantity = min($available_quantity, $required_quantity - $destination_stock);
if ($transfer_quantity > 0) {
$decision['need_transfer'] = true;
$decision['transfer_from'] = $best_source['warehouse_id'];
$decision['transfer_quantity'] = $transfer_quantity;
$decision['reason'] = sprintf(
'从%s调拨%d件商品到目标仓库,基于库存充足度和距离最优原则',
$best_source['warehouse_name'],
$transfer_quantity
);
}
} else {
$decision['reason'] = '未找到合适的调拨源仓库,所有仓库库存均接近安全库存';
}
return $decision;
}
/**
* 计算仓库作为调拨源的得分
* 考虑因素:库存充足度、距离、运输成本等
*/
function calculate_warehouse_score($warehouse, $destination_id, $required_quantity) {
$score = 0;
// 1. 库存充足度得分(40%权重)
$excess_stock = $warehouse['quantity'] - $warehouse['safety_stock'];
$inventory_score = ($excess_stock / ($required_quantity + 1)) * 40;
$score += min($inventory_score, 40);
// 2. 距离得分(30%权重)- 这里简化处理,实际应集成地图API
$distance = calculate_distance($warehouse['warehouse_id'], $destination_id);
$distance_score = (1 / ($distance + 1)) * 30;
$score += $distance_score;
// 3. 历史调拨效率得分(30%权重)
$efficiency_score = get_transfer_efficiency_score($warehouse['warehouse_id'], $destination_id);
$score += $efficiency_score * 30;
return $score;
}
?>
当智能调拨引擎做出调拨决策后,需要执行具体的调拨流程:
<?php
/**
* 执行库存调拨
*
* @param int $product_id 商品ID
* @param int $from_warehouse_id 源仓库ID
* @param int $to_warehouse_id 目标仓库ID
* @param int $quantity 调拨数量
* @param string $reason 调拨原因
* @return int|false 调拨记录ID或false(失败时)
*/
function execute_inventory_transfer($product_id, $from_warehouse_id, $to_warehouse_id, $quantity, $reason = '') {
global $wpdb;
// 验证源仓库库存是否充足
$source_stock = get_warehouse_stock($product_id, $from_warehouse_id);
if ($source_stock < $quantity) {
return false;
}
// 开始数据库事务
$wpdb->query('START TRANSACTION');
try {
// 1. 创建调拨记录
$transfer_data = [
'product_id' => $product_id,
'from_warehouse_id' => $from_warehouse_id,
'to_warehouse_id' => $to_warehouse_id,
'quantity' => $quantity,
'transfer_reason' => $reason,
'status' => 'pending',
'requested_by' => get_current_user_id(),
'created_at' => current_time('mysql')
];
$result = $wpdb->insert('wp_inventory_transfers', $transfer_data);
if (!$result) {
throw new Exception('创建调拨记录失败');
}
$transfer_id = $wpdb->insert_id;
// 2. 减少源仓库库存(预扣)
$update_source = $wpdb->query($wpdb->prepare(
"UPDATE wp_product_inventory
SET quantity = quantity - %d
WHERE product_id = %d AND warehouse_id = %d",
$quantity, $product_id, $from_warehouse_id
));
if (!$update_source) {
throw new Exception('更新源仓库库存失败');
}
// 3. 增加目标仓库在途库存(可选,根据业务需求)
// 这里可以根据实际业务决定是否立即增加目标仓库库存
// 或者等待调拨完成后再更新
// 4. 记录库存变更日志
log_inventory_change(
$product_id,
$from_warehouse_id,
-$quantity,
'transfer_out',
"调拨出库至仓库{$to_warehouse_id},调拨单号:{$transfer_id}"
);
// 提交事务
$wpdb->query('COMMIT');
// 5. 发送调拨通知(给相关仓库管理员)
send_transfer_notification($transfer_id);
return $transfer_id;
} catch (Exception $e) {
// 回滚事务
$wpdb->query('ROLLBACK');
error_log('调拨执行失败: ' . $e->getMessage());
return false;
}
}
/**
* 完成调拨流程(当货物实际到达目标仓库时调用)
*/
function complete_inventory_transfer($transfer_id) {
global $wpdb;
// 获取调拨信息
$transfer = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM wp_inventory_transfers WHERE transfer_id = %d",
$transfer_id
), ARRAY_A);
if (!$transfer || $transfer['status'] != 'in_transit') {
return false;
}
$wpdb->query('START TRANSACTION');
try {
// 1. 增加目标仓库实际库存
$update_target = $wpdb->query($wpdb->prepare(
"UPDATE wp_product_inventory
SET quantity = quantity + %d
WHERE product_id = %d AND warehouse_id = %d",
$transfer['quantity'], $transfer['product_id'], $transfer['to_warehouse_id']
));
if (!$update_target) {
// 如果目标仓库还没有该商品的库存记录,则创建一条
$wpdb->insert('wp_product_inventory', [
'product_id' => $transfer['product_id'],
'warehouse_id' => $transfer['to_warehouse_id'],
'quantity' => $transfer['quantity']
]);
}
// 2. 更新调拨状态为已完成
$wpdb->update('wp_inventory_transfers',
[
'status' => 'completed',
'completed_at' => current_time('mysql'),
'approved_by' => get_current_user_id()
],
['transfer_id' => $transfer_id]
);
// 3. 记录库存变更日志
log_inventory_change(
$transfer['product_id'],
$transfer['to_warehouse_id'],
$transfer['quantity'],
'transfer_in',
"调拨入库自仓库{$transfer['from_warehouse_id']},调拨单号:{$transfer_id}"
);
$wpdb->query('COMMIT');
// 4. 触发相关事件(如更新订单状态等)
do_action('inventory_transfer_completed', $transfer_id);
return true;
} catch (Exception $e) {
$wpdb->query('ROLLBACK');
error_log('调拨完成失败: ' . $e->getMessage());
return false;
}
}
?>
<?php
/**
* 添加供应链管理菜单到WordPress后台
*/
add_action('admin_menu', 'register_supply_chain_menu');
function register_supply_chain_menu() {
// 主菜单
add_menu_page(
'供应链管理', // 页面标题
'供应链管理', // 菜单标题
'manage_options', // 权限
'supply-chain', // 菜单slug
'supply_chain_dashboard', // 回调函数
'dashicons-store', // 图标
30 // 位置
);
// 子菜单:仓库管理
add_submenu_page(
'supply-chain',
'仓库管理',
'仓库管理',
'manage_options',
'warehouse-management',
'warehouse_management_page'
);
// 子菜单:库存调拨
add_submenu_page(
'supply-chain',
'库存调拨',
'库存调拨',
'manage_options',
'inventory-transfer',
'inventory_transfer_page'
);
// 子菜单:调拨记录
add_submenu_page(
'supply-chain',
'调拨记录',
'调拨记录',
'manage_options',
'transfer-records',
'transfer_records_page'
);
}
/**
* 库存调拨管理页面
*/
function inventory_transfer_page() {
?>
<div class="wrap">
<h1>智能库存调拨</h1>
<div class="card">
<h2>自动调拨决策</h2>
<form method="post" action="">
<?php wp_nonce_field('auto_transfer_action', 'transfer_nonce'); ?>
<table class="form-table">
<tr>
<th scope="row"><label for="product_id">商品</label></th>
<td>
<select name="product_id" id="product_id" required>
<option value="">选择商品...</option>
<?php
$products = wc_get_products(['limit' => -1]);
foreach ($products as $product) {
echo '<option value="' . $product->get_id() . '">' .
$product->get_name() . '</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="destination_warehouse">目标仓库</label></th>
<td>
<select name="destination_warehouse" id="destination_warehouse" required>
<option value="">选择目标仓库...</option>
<?php
$warehouses = get_all_warehouses();
foreach ($warehouses as $warehouse) {
echo '<option value="' . $warehouse['warehouse_id'] . '">' .
$warehouse['warehouse_name'] . '</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="required_quantity">需求数量</label></th>
<td>
<input type="number" name="required_quantity" id="required_quantity"
min="1" required>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="analyze_transfer" class="button button-primary"
value="分析调拨需求">
</p>
</form>
<?php
// 处理表单提交
if (isset($_POST['analyze_transfer']) &&
wp_verify_nonce($_POST['transfer_nonce'], 'auto_transfer_action')) {
$product_id = intval($_POST['product_id']);
$destination_id = intval($_POST['destination_warehouse']);
$required_quantity = intval($_POST['required_quantity']);
$decision = intelligent_transfer_decision(
$product_id,
$required_quantity,
$destination_id
);
echo '<div class="notice notice-info">';
echo '<h3>调拨分析结果</h3>';
echo '<p><strong>结论:</strong>' . esc_html($decision['reason']) . '</p>';
if ($decision['need_transfer']) {
echo '<p><strong>建议调拨:</strong>从仓库#' . $decision['transfer_from'] .
' 调拨 ' . $decision['transfer_quantity'] . ' 件商品</p>';
// 显示执行调拨按钮
echo '<form method="post" action="">';
wp_nonce_field('execute_transfer_action', 'execute_nonce');
echo '<input type="hidden" name="product_id" value="' . $product_id . '">';
echo '<input type="hidden" name="from_warehouse" value="' . $decision['transfer_from'] . '">';
echo '<input type="hidden" name="to_warehouse" value="' . $destination_id . '">';
echo '<input type="hidden" name="quantity" value="' . $decision['transfer_quantity'] . '">';
echo '<input type="submit" name="execute_transfer" class="button button-primary"
echo '<input type="submit" name="execute_transfer" class="button button-primary"
value="执行调拨">';
echo '</form>';
}
echo '</div>';
// 处理执行调拨请求
if (isset($_POST['execute_transfer']) &&
wp_verify_nonce($_POST['execute_nonce'], 'execute_transfer_action')) {
$transfer_id = execute_inventory_transfer(
intval($_POST['product_id']),
intval($_POST['from_warehouse']),
intval($_POST['to_warehouse']),
intval($_POST['quantity']),
'系统智能调拨'
);
if ($transfer_id) {
echo '<div class="notice notice-success">';
echo '<p>调拨单创建成功!调拨单号:' . $transfer_id . '</p>';
echo '</div>';
} else {
echo '<div class="notice notice-error">';
echo '<p>调拨执行失败,请检查库存情况</p>';
echo '</div>';
}
}
}
?>
</div>
<div class="card">
<h2>手动调拨</h2>
<form method="post" action="">
<?php wp_nonce_field('manual_transfer_action', 'manual_nonce'); ?>
<table class="form-table">
<tr>
<th scope="row"><label for="manual_product_id">商品</label></th>
<td>
<select name="manual_product_id" id="manual_product_id" required>
<option value="">选择商品...</option>
<?php
$products = wc_get_products(['limit' => -1]);
foreach ($products as $product) {
echo '<option value="' . $product->get_id() . '">' .
$product->get_name() . '</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="from_warehouse">源仓库</label></th>
<td>
<select name="from_warehouse" id="from_warehouse" required>
<option value="">选择源仓库...</option>
<?php
foreach ($warehouses as $warehouse) {
echo '<option value="' . $warehouse['warehouse_id'] . '">' .
$warehouse['warehouse_name'] . '</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="to_warehouse">目标仓库</label></th>
<td>
<select name="to_warehouse" id="to_warehouse" required>
<option value="">选择目标仓库...</option>
<?php
foreach ($warehouses as $warehouse) {
echo '<option value="' . $warehouse['warehouse_id'] . '">' .
$warehouse['warehouse_name'] . '</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="manual_quantity">调拨数量</label></th>
<td>
<input type="number" name="manual_quantity" id="manual_quantity"
min="1" required>
</td>
</tr>
<tr>
<th scope="row"><label for="transfer_reason">调拨原因</label></th>
<td>
<textarea name="transfer_reason" id="transfer_reason"
rows="3" cols="50"></textarea>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="submit_manual_transfer"
class="button button-primary" value="提交调拨申请">
</p>
</form>
</div>
</div>
<style>
.card {
background: #fff;
border: 1px solid #ccd0d4;
box-shadow: 0 1px 1px rgba(0,0,0,.04);
margin: 20px 0;
padding: 20px;
}
.form-table th {
width: 200px;
}
</style>
<?php
}
?>
<?php
/**
* 添加供应链管理菜单到WordPress后台
*/
add_action('admin_menu', 'register_supply_chain_menu');
function register_supply_chain_menu() {
// 主菜单
add_menu_page(
'供应链管理', // 页面标题
'供应链管理', // 菜单标题
'manage_options', // 权限
'supply-chain', // 菜单slug
'supply_chain_dashboard', // 回调函数
'dashicons-store', // 图标
30 // 位置
);
// 子菜单:仓库管理
add_submenu_page(
'supply-chain',
'仓库管理',
'仓库管理',
'manage_options',
'warehouse-management',
'warehouse_management_page'
);
// 子菜单:库存调拨
add_submenu_page(
'supply-chain',
'库存调拨',
'库存调拨',
'manage_options',
'inventory-transfer',
'inventory_transfer_page'
);
// 子菜单:调拨记录
add_submenu_page(
'supply-chain',
'调拨记录',
'调拨记录',
'manage_options',
'transfer-records',
'transfer_records_page'
);
}
/**
* 库存调拨管理页面
*/
function inventory_transfer_page() {
?>
<div class="wrap">
<h1>智能库存调拨</h1>
<div class="card">
<h2>自动调拨决策</h2>
<form method="post" action="">
<?php wp_nonce_field('auto_transfer_action', 'transfer_nonce'); ?>
<table class="form-table">
<tr>
<th scope="row"><label for="product_id">商品</label></th>
<td>
<select name="product_id" id="product_id" required>
<option value="">选择商品...</option>
<?php
$products = wc_get_products(['limit' => -1]);
foreach ($products as $product) {
echo '<option value="' . $product->get_id() . '">' .
$product->get_name() . '</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="destination_warehouse">目标仓库</label></th>
<td>
<select name="destination_warehouse" id="destination_warehouse" required>
<option value="">选择目标仓库...</option>
<?php
$warehouses = get_all_warehouses();
foreach ($warehouses as $warehouse) {
echo '<option value="' . $warehouse['warehouse_id'] . '">' .
$warehouse['warehouse_name'] . '</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="required_quantity">需求数量</label></th>
<td>
<input type="number" name="required_quantity" id="required_quantity"
min="1" required>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="analyze_transfer" class="button button-primary"
value="分析调拨需求">
</p>
</form>
<?php
// 处理表单提交
if (isset($_POST['analyze_transfer']) &&
wp_verify_nonce($_POST['transfer_nonce'], 'auto_transfer_action')) {
$product_id = intval($_POST['product_id']);
$destination_id = intval($_POST['destination_warehouse']);
$required_quantity = intval($_POST['required_quantity']);
$decision = intelligent_transfer_decision(
$product_id,
$required_quantity,
$destination_id
);
echo '<div class="notice notice-info">';
echo '<h3>调拨分析结果</h3>';
echo '<p><strong>结论:</strong>' . esc_html($decision['reason']) . '</p>';
if ($decision['need_transfer']) {
echo '<p><strong>建议调拨:</strong>从仓库#' . $decision['transfer_from'] .
' 调拨 ' . $decision['transfer_quantity'] . ' 件商品</p>';
// 显示执行调拨按钮
echo '<form method="post" action="">';
wp_nonce_field('execute_transfer_action', 'execute_nonce');
echo '<input type="hidden" name="product_id" value="' . $product_id . '">';
echo '<input type="hidden" name="from_warehouse" value="' . $decision['transfer_from'] . '">';
echo '<input type="hidden" name="to_warehouse" value="' . $destination_id . '">';
echo '<input type="hidden" name="quantity" value="' . $decision['transfer_quantity'] . '">';
echo '<input type="submit" name="execute_transfer" class="button button-primary"
echo '<input type="submit" name="execute_transfer" class="button button-primary"
value="执行调拨">';
echo '</form>';
}
echo '</div>';
// 处理执行调拨请求
if (isset($_POST['execute_transfer']) &&
wp_verify_nonce($_POST['execute_nonce'], 'execute_transfer_action')) {
$transfer_id = execute_inventory_transfer(
intval($_POST['product_id']),
intval($_POST['from_warehouse']),
intval($_POST['to_warehouse']),
intval($_POST['quantity']),
'系统智能调拨'
);
if ($transfer_id) {
echo '<div class="notice notice-success">';
echo '<p>调拨单创建成功!调拨单号:' . $transfer_id . '</p>';
echo '</div>';
} else {
echo '<div class="notice notice-error">';
echo '<p>调拨执行失败,请检查库存情况</p>';
echo '</div>';
}
}
}
?>
</div>
<div class="card">
<h2>手动调拨</h2>
<form method="post" action="">
<?php wp_nonce_field('manual_transfer_action', 'manual_nonce'); ?>
<table class="form-table">
<tr>
<th scope="row"><label for="manual_product_id">商品</label></th>
<td>
<select name="manual_product_id" id="manual_product_id" required>
<option value="">选择商品...</option>
<?php
$products = wc_get_products(['limit' => -1]);
foreach ($products as $product) {
echo '<option value="' . $product->get_id() . '">' .
$product->get_name() . '</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="from_warehouse">源仓库</label></th>
<td>
<select name="from_warehouse" id="from_warehouse" required>
<option value="">选择源仓库...</option>
<?php
foreach ($warehouses as $warehouse) {
echo '<option value="' . $warehouse['warehouse_id'] . '">' .
$warehouse['warehouse_name'] . '</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="to_warehouse">目标仓库</label></th>
<td>
<select name="to_warehouse" id="to_warehouse" required>
<option value="">选择目标仓库...</option>
<?php
foreach ($warehouses as $warehouse) {
echo '<option value="' . $warehouse['warehouse_id'] . '">' .
$warehouse['warehouse_name'] . '</option>';
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row"><label for="manual_quantity">调拨数量</label></th>
<td>
<input type="number" name="manual_quantity" id="manual_quantity"
min="1" required>
</td>
</tr>
<tr>
<th scope="row"><label for="transfer_reason">调拨原因</label></th>
<td>
<textarea name="transfer_reason" id="transfer_reason"
rows="3" cols="50"></textarea>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="submit_manual_transfer"
class="button button-primary" value="提交调拨申请">
</p>
</form>
</div>
</div>
<style>
.card {
background: #fff;
border: 1px solid #ccd0d4;
box-shadow: 0 1px 1px rgba(0,0,0,.04);
margin: 20px 0;
padding: 20px;
}
.form-table th {
width: 200px;
}
</style>
<?php
}
?>
<?php
/**
* 供应链管理仪表板
*/
function supply_chain_dashboard() {
?>
<div class="wrap">
<h1>供应链管理仪表板</h1>
<div class="dashboard-container">
<!-- 库存概览 -->
<div class="dashboard-card">
<h3>库存概览</h3>
<div class="inventory-summary">
<?php
$total_inventory = get_total_inventory_value();
$low_stock_items = get_low_stock_items_count();
$out_of_stock_items = get_out_of_stock_items_count();
?>
<div class="metric">
<span class="metric-value"><?php echo wc_price($total_inventory); ?></span>
<span class="metric-label">库存总值</span>
</div>
<div class="metric">
<span class="metric-value warning"><?php echo $low_stock_items; ?></span>
<span class="metric-label">低库存商品</span>
</div>
<div class="metric">
<span class="metric-value danger"><?php echo $out_of_stock_items; ?></span>
<span class="metric-label">缺货商品</span>
</div>
</div>
</div>
<!-- 仓库库存分布 -->
<div class="dashboard-card wide">
<h3>各仓库库存分布</h3>
<div class="warehouse-distribution">
<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>
<?php
$warehouses = get_all_warehouses_with_inventory();
foreach ($warehouses as $warehouse) {
$usage_rate = ($warehouse['current_inventory'] / $warehouse['capacity']) * 100;
$usage_class = $usage_rate > 90 ? 'danger' : ($usage_rate > 70 ? 'warning' : '');
?>
<tr>
<td><?php echo esc_html($warehouse['warehouse_name']); ?></td>
<td><?php echo $warehouse['product_count']; ?></td>
<td><?php echo $warehouse['total_quantity']; ?></td>
<td><?php echo wc_price($warehouse['inventory_value']); ?></td>
<td>
<div class="usage-bar">
<div class="usage-fill <?php echo $usage_class; ?>"
style="width: <?php echo $usage_rate; ?>%">
<?php echo round($usage_rate, 1); ?>%
</div>
</div>
</td>
<td>
<a href="<?php echo admin_url('admin.php?page=warehouse-management&id=' . $warehouse['warehouse_id']); ?>"
class="button button-small">详情</a>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</div>
<!-- 近期调拨活动 -->
<div class="dashboard-card">
<h3>近期调拨活动</h3>
<div class="recent-transfers">
<?php
$recent_transfers = get_recent_transfers(5);
if (empty($recent_transfers)) {
echo '<p>暂无调拨记录</p>';
} else {
echo '<ul>';
foreach ($recent_transfers as $transfer) {
$status_class = '';
switch ($transfer['status']) {
case 'completed': $status_class = 'success'; break;
case 'in_transit': $status_class = 'warning'; break;
case 'pending': $status_class = 'info'; break;
case 'cancelled': $status_class = 'danger'; break;
}
?>
<li>
<span class="transfer-status <?php echo $status_class; ?>">
<?php echo $transfer['status']; ?>
</span>
<strong><?php echo get_product_name($transfer['product_id']); ?></strong>
(<?php echo $transfer['quantity']; ?>件)
<br>
<small>
从 <?php echo get_warehouse_name($transfer['from_warehouse_id']); ?>
到 <?php echo get_warehouse_name($transfer['to_warehouse_id']); ?>
· <?php echo human_time_diff(strtotime($transfer['created_at']), current_time('timestamp')); ?>前
</small>
</li>
<?php
}
echo '</ul>';
}
?>
<a href="<?php echo admin_url('admin.php?page=transfer-records'); ?>"
class="button">查看所有调拨记录</a>
</div>
</div>
<!-- 智能调拨建议 -->
<div class="dashboard-card">
<h3>智能调拨建议</h3>
<div class="transfer-suggestions">
<?php
$suggestions = get_transfer_suggestions();
if (empty($suggestions)) {
echo '<p>暂无调拨建议,库存分布均衡</p>';
} else {
echo '<ul>';
foreach ($suggestions as $suggestion) {
?>
<li>
<strong><?php echo $suggestion['product_name']; ?></strong>
<br>
建议从 <em><?php echo $suggestion['from_warehouse']; ?></em>
调拨 <em><?php echo $suggestion['quantity']; ?>件</em>
到 <em><?php echo $suggestion['to_warehouse']; ?></em>
<br>
<small>原因:<?php echo $suggestion['reason']; ?></small>
<br>
<button class="button button-small execute-suggestion"
data-product="<?php echo $suggestion['product_id']; ?>"
data-from="<?php echo $suggestion['from_warehouse_id']; ?>"
data-to="<?php echo $suggestion['to_warehouse_id']; ?>"
data-quantity="<?php echo $suggestion['quantity']; ?>">
执行调拨
</button>
</li>
<?php
}
echo '</ul>';
}
?>
</div>
</div>
</div>
</div>
<style>
.dashboard-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-top: 20px;
}
.dashboard-card {
background: #fff;
border: 1px solid #ccd0d4;
border-radius: 4px;
padding: 20px;
}
.dashboard-card.wide {
grid-column: span 2;
}
.inventory-summary {
display: flex;
justify-content: space-around;
text-align: center;
}
.metric {
display: flex;
flex-direction: column;
}
.metric-value {
font-size: 24px;
font-weight: bold;
color: #0073aa;
}
.metric-value.warning {
color: #ffb900;
}
.metric-value.danger {
color: #dc3232;
}
.metric-label {
font-size: 12px;
color: #666;
margin-top: 5px;
}
.usage-bar {
width: 100%;
height: 20px;
background: #f0f0f0;
border-radius: 10px;
overflow: hidden;
}
.usage-fill {
height: 100%;
background: #46b450;
text-align: center;
color: white;
font-size: 12px;
line-height: 20px;
}
.usage-fill.warning {
background: #ffb900;
}
.usage-fill.danger {
background: #dc3232;
}
.transfer-status {
display: inline-block;
padding: 2px 8px;
border-radius: 3px;
font-size: 11px;
text-transform: uppercase;
}
.transfer-status.success { background: #d4edda; color: #155724; }
.transfer-status.warning { background: #fff3cd; color: #856404; }
.transfer-status.info { background: #d1ecf1; color: #0c5460; }
.transfer-status.danger { background: #f8d7da; color: #721c24; }
</style>
<script>
jQuery(document).ready(function($) {
// 执行调拨建议
$('.execute-suggestion').on('click', function() {
var button = $(this);
var data = {
action: 'execute_transfer_suggestion',
product_id: button.data('product'),
from_warehouse: button.data('from'),
to_warehouse: button.data('to'),
quantity: button.data('quantity'),
nonce: '<?php echo wp_create_nonce('execute_suggestion_nonce'); ?>'
};
button.prop('disabled', true).text('处理中...');
$.post(ajaxurl, data, function(response) {
if (response.success) {
alert('调拨单创建成功!单号:' + response.data.transfer_id);
button.closest('li').fadeOut();
} else {
alert('操作失败:' + response.data.message);
button.prop('disabled', false).text('执行调拨');
}
});
});
// 自动刷新仪表板数据(每60秒)
setInterval(function() {
$.post(ajaxurl, {
action: 'refresh_dashboard_data',
nonce: '<?php echo wp_create_nonce('refresh_dashboard_nonce'); ?>'
}, function(response) {
if (response.success) {
// 更新相关数据
// 这里可以根据返回的数据更新页面元素
}
});
}, 60000);
});
</script>
<?php
}
// AJAX处理函数
add_action('wp_ajax_execute_transfer_suggestion', 'ajax_execute_transfer_suggestion');
function ajax_execute_transfer_suggestion() {
check_ajax_referer('execute_suggestion_nonce', 'nonce');
$transfer_id = execute_inventory_transfer(
intval($_POST['product_id']),
intval($_POST['from_warehouse']),
intval($_POST['to_warehouse']),
intval($_POST['quantity']),
'仪表板智能建议调拨'
);
if ($transfer_id) {
wp_send_json_success(['transfer_id' => $transfer_id]);
} else {
wp_send_json_error(['message' => '调拨执行失败']);
}
}
?>
<?php
/**
* 供应链管理仪表板
*/
function supply_chain_dashboard() {
?>
<div class="wrap">
<h1>供应链管理仪表板</h1>
<div class="dashboard-container">
<!-- 库存概览 -->
<div class="dashboard-card">
<h3>库存概览</h3>
<div class="inventory-summary">
<?php
$total_inventory = get_total_inventory_value();
$low_stock_items = get_low_stock_items_count();
$out_of_stock_items = get_out_of_stock_items_count();
?>
<div class="metric">
<span class="metric-value"><?php echo wc_price($total_inventory); ?></span>
<span class="metric-label">库存总值</span>
</div>
<div class="metric">
<span class="metric-value warning"><?php echo $low_stock_items; ?></span>
<span class="metric-label">低库存商品</span>
</div>
<div class="metric">
<span class="metric-value danger"><?php echo $out_of_stock_items; ?></span>
<span class="metric-label">缺货商品</span>
</div>
</div>
</div>
<!-- 仓库库存分布 -->
<div class="dashboard-card wide">
<h3>各仓库库存分布</h3>
<div class="warehouse-distribution">
<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>
<?php
$warehouses = get_all_warehouses_with_inventory();
foreach ($warehouses as $warehouse) {
$usage_rate = ($warehouse['current_inventory'] / $warehouse['capacity']) * 100;
$usage_class = $usage_rate > 90 ? 'danger' : ($usage_rate > 70 ? 'warning' : '');
?>
<tr>
<td><?php echo esc_html($warehouse['warehouse_name']); ?></td>
<td><?php echo $warehouse['product_count']; ?></td>
<td><?php echo $warehouse['total_quantity']; ?></td>
<td><?php echo wc_price($warehouse['inventory_value']); ?></td>
<td>
<div class="usage-bar">
<div class="usage-fill <?php echo $usage_class; ?>"
style="width: <?php echo $usage_rate; ?>%">
<?php echo round($usage_rate, 1); ?>%
</div>
</div>
</td>
<td>
<a href="<?php echo admin_url('admin.php?page=warehouse-management&id=' . $warehouse['warehouse_id']); ?>"
class="button button-small">详情</a>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</div>
<!-- 近期调拨活动 -->
<div class="dashboard-card">
<h3>近期调拨活动</h3>
<div class="recent-transfers">
<?php
$recent_transfers = get_recent_transfers(5);
if (empty($recent_transfers)) {
echo '<p>暂无调拨记录</p>';
} else {
echo '<ul>';
foreach ($recent_transfers as $transfer) {
$status_class = '';
switch ($transfer['status']) {
case 'completed': $status_class = 'success'; break;
case 'in_transit': $status_class = 'warning'; break;
case 'pending': $status_class = 'info'; break;
case 'cancelled': $status_class = 'danger'; break;
}
?>
<li>
<span class="transfer-status <?php echo $status_class; ?>">
<?php echo $transfer['status']; ?>
</span>
<strong><?php echo get_product_name($transfer['product_id']); ?></strong>
(<?php echo $transfer['quantity']; ?>件)
<br>
<small>
从 <?php echo get_warehouse_name($transfer['from_warehouse_id']); ?>
到 <?php echo get_warehouse_name($transfer['to_warehouse_id']); ?>
· <?php echo human_time_diff(strtotime($transfer['created_at']), current_time('timestamp')); ?>前
</small>
</li>
<?php
}
echo '</ul>';
}
?>
<a href="<?php echo admin_url('admin.php?page=transfer-records'); ?>"
class="button">查看所有调拨记录</a>
</div>
</div>
<!-- 智能调拨建议 -->
<div class="dashboard-card">
<h3>智能调拨建议</h3>
<div class="transfer-suggestions">
<?php
$suggestions = get_transfer_suggestions();
if (empty($suggestions)) {
echo '<p>暂无调拨建议,库存分布均衡</p>';
} else {
echo '<ul>';
foreach ($suggestions as $suggestion) {
?>
<li>
<strong><?php echo $suggestion['product_name']; ?></strong>
<br>
建议从 <em><?php echo $suggestion['from_warehouse']; ?></em>
调拨 <em><?php echo $suggestion['quantity']; ?>件</em>
到 <em><?php echo $suggestion['to_warehouse']; ?></em>
<br>
<small>原因:<?php echo $suggestion['reason']; ?></small>
<br>
<button class="button button-small execute-suggestion"
data-product="<?php echo $suggestion['product_id']; ?>"
data-from="<?php echo $suggestion['from_warehouse_id']; ?>"
data-to="<?php echo $suggestion['to_warehouse_id']; ?>"
data-quantity="<?php echo $suggestion['quantity']; ?>">
执行调拨
</button>
</li>
<?php
}
echo '</ul>';
}
?>
</div>
</div>
</div>
</div>
<style>
.dashboard-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-top: 20px;
}
.dashboard-card {
background: #fff;
border: 1px solid #ccd0d4;
border-radius: 4px;
padding: 20px;
}
.dashboard-card.wide {
grid-column: span 2;
}
.inventory-summary {
display: flex;
justify-content: space-around;
text-align: center;
}
.metric {
display: flex;
flex-direction: column;
}
.metric-value {
font-size: 24px;
font-weight: bold;
color: #0073aa;
}
.metric-value.warning {
color: #ffb900;
}
.metric-value.danger {
color: #dc3232;
}
.metric-label {
font-size: 12px;
color: #666;
margin-top: 5px;
}
.usage-bar {
width: 100%;
height: 20px;
background: #f0f0f0;
border-radius: 10px;
overflow: hidden;
}
.usage-fill {
height: 100%;
background: #46b450;
text-align: center;
color: white;
font-size: 12px;
line-height: 20px;
}
.usage-fill.warning {
background: #ffb900;
}
.usage-fill.danger {
background: #dc3232;
}
.transfer-status {
display: inline-block;
padding: 2px 8px;
border-radius: 3px;
font-size: 11px;
text-transform: uppercase;
}
.transfer-status.success { background: #d4edda; color: #155724; }
.transfer-status.warning { background: #fff3cd; color: #856404; }
.transfer-status.info { background: #d1ecf1; color: #0c5460; }
.transfer-status.danger { background: #f8d7da; color: #721c24; }
</style>
<script>
jQuery(document).ready(function($) {
// 执行调拨建议
$('.execute-suggestion').on('click', function() {
var button = $(this);
var data = {
action: 'execute_transfer_suggestion',
product_id: button.data('product'),
from_warehouse: button.data('from'),
to_warehouse: button.data('to'),
quantity: button.data('quantity'),
nonce: '<?php echo wp_create_nonce('execute_suggestion_nonce'); ?>'
};
button.prop('disabled', true).text('处理中...');
$.post(ajaxurl, data, function(response) {
if (response.success) {
alert('调拨单创建成功!单号:' + response.data.transfer_id);
button.closest('li').fadeOut();
} else {
alert('操作失败:' + response.data.message);
button.prop('disabled', false).text('执行调拨');
}
});
});
// 自动刷新仪表板数据(每60秒)
setInterval(function() {
$.post(ajaxurl, {
action: 'refresh_dashboard_data',
nonce: '<?php echo wp_create_nonce('refresh_dashboard_nonce'); ?>'
}, function(response) {
if (response.success) {
// 更新相关数据
// 这里可以根据返回的数据更新页面元素
}
});
}, 60000);
});
</script>
<?php
}
// AJAX处理函数
add_action('wp_ajax_execute_transfer_suggestion', 'ajax_execute_transfer_suggestion');
function ajax_execute_transfer_suggestion() {
check_ajax_referer('execute_suggestion_nonce', 'nonce');
$transfer_id = execute_inventory_transfer(
intval($_POST['product_id']),
intval($_POST['from_warehouse']),
intval($_POST['to_warehouse']),
intval($_POST['quantity']),
'仪表板智能建议调拨'
);
if ($transfer_id) {
wp_send_json_success(['transfer_id' => $transfer_id]);
} else {
wp_send_json_error(['message' => '调拨执行失败']);
}
}
?>
<?php
/**
* 基于机器学习的库存预测和调拨优化
* 注:这是一个简化示例,实际应用中需要更复杂的算法和更多数据
*/
class MLInventoryPredictor {
private $model_data = [];
public function __construct() {
$this->load_training_data();
}
/**
* 加载历史数据用于训练
*/
private function load_training_data() {
global $wpdb;
// 加载历史销售数据
$this->model_data['sales_history'] = $wpdb->get_results("
SELECT product_id, DATE(created_at) as date, SUM(quantity) as daily_sales
FROM wp_order_items
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 90 DAY)
GROUP BY product_id, DATE(created_at)
ORDER BY date DESC
", ARRAY_A);
// 加载季节性因素
$this->model_data['seasonality'] = $this->calculate_seasonality_factors();
// 加载促销活动数据
$this->model_data['promotions'] = $this->get_promotion_data();
}
/**
* 预测未来需求
*/
public function predict_demand($product_id, $warehouse_id, $days_ahead = 7) {
$predictions = [];
// 1. 基于历史销售趋势
$historical_trend = $this->calculate_historical_trend($product_id, $warehouse_id);
// 2. 考虑季节性因素
$seasonality_factor = $this->get_seasonality_factor(date('m'), $product_id);
// 3. 考虑促销活动影响
$promotion_impact = $this->get_promotion_impact($product_id);
// 4. 生成预测
for ($day = 1; $day <= $days_ahead; $day++) {
$date = date('Y-m-d', strtotime("+{$day} days"));
// 基础预测 = 历史平均 * 趋势系数
$base_prediction = $historical_trend['average'] * $historical_trend['trend_factor'];
// 应用季节性调整
$seasonal_adjusted = $base_prediction * $seasonality_factor;
// 应用促销影响
$final_prediction = $seasonal_adjusted * (1 + $promotion_impact);
// 添加随机波动(模拟现实不确定性)
$random_variation = 1 + (mt_rand(-20, 20) / 100);
$final_prediction *= $random_variation;
$predictions[$date] = round($final_prediction);
}
return $predictions;
}
/**
* 生成优化调拨计划
<?php
/**
* 基于机器学习的库存预测和调拨优化
* 注:这是一个简化示例,实际应用中需要更复杂的算法和更多数据
*/
class MLInventoryPredictor {
private $model_data = [];
public function __construct() {
$this->load_training_data();
}
/**
* 加载历史数据用于训练
*/
private function load_training_data() {
global $wpdb;
// 加载历史销售数据
$this->model_data['sales_history'] = $wpdb->get_results("
SELECT product_id, DATE(created_at) as date, SUM(quantity) as daily_sales
FROM wp_order_items
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 90 DAY)
GROUP BY product_id, DATE(created_at)
ORDER BY date DESC
", ARRAY_A);
// 加载季节性因素
$this->model_data['seasonality'] = $this->calculate_seasonality_factors();
// 加载促销活动数据
$this->model_data['promotions'] = $this->get_promotion_data();
}
/**
* 预测未来需求
*/
public function predict_demand($product_id, $warehouse_id, $days_ahead = 7) {
$predictions = [];
// 1. 基于历史销售趋势
$historical_trend = $this->calculate_historical_trend($product_id, $warehouse_id);
// 2. 考虑季节性因素
$seasonality_factor = $this->get_seasonality_factor(date('m'), $product_id);
// 3. 考虑促销活动影响
$promotion_impact = $this->get_promotion_impact($product_id);
// 4. 生成预测
for ($day = 1; $day <= $days_ahead; $day++) {
$date = date('Y-m-d', strtotime("+{$day} days"));
// 基础预测 = 历史平均 * 趋势系数
$base_prediction = $historical_trend['average'] * $historical_trend['trend_factor'];
// 应用季节性调整
$seasonal_adjusted = $base_prediction * $seasonality_factor;
// 应用促销影响
$final_prediction = $seasonal_adjusted * (1 + $promotion_impact);
// 添加随机波动(模拟现实不确定性)
$random_variation = 1 + (mt_rand(-20, 20) / 100);
$final_prediction *= $random_variation;
$predictions[$date] = round($final_prediction);
}
return $predictions;
}
/**
* 生成优化调拨计划


