首页 / 教程文章 / WordPress小批量定制插件实现物料需求计划(MRP)的教程

WordPress小批量定制插件实现物料需求计划(MRP)的教程

WordPress小批量定制插件实现物料需求计划(MRP)的教程

概述:为什么在WordPress中实现MRP?

物料需求计划(MRP)是制造业中用于管理生产物料的核心系统。对于中小型企业来说,完整的ERP系统可能过于庞大且昂贵。本教程将展示如何在WordPress中创建一个轻量级MRP插件,特别适合小批量定制生产环境。

通过这个插件,您可以在熟悉的WordPress环境中管理物料清单、库存、生产订单和采购需求,实现基本的MRP功能。

环境准备与插件基础结构

首先,我们需要创建插件的基本结构。在WordPress的wp-content/plugins/目录下创建一个新文件夹mrp-manager

<?php
/**
 * Plugin Name: MRP Manager
 * Plugin URI: https://yourwebsite.com/
 * Description: 小批量定制生产的物料需求计划管理系统
 * Version: 1.0.0
 * Author: 您的名称
 * License: GPL v2 or later
 */

// 防止直接访问
if (!defined('ABSPATH')) {
    exit;
}

// 定义插件常量
define('MRP_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('MRP_PLUGIN_URL', plugin_dir_url(__FILE__));

// 初始化插件
class MRP_Manager {
    
    public 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('admin_menu', array($this, 'add_admin_menu'));
        
        // 加载脚本和样式
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
    }
    
    public function activate() {
        $this->create_tables();
        $this->insert_initial_data();
    }
    
    public function deactivate() {
        // 清理临时数据
    }
    
    public function add_admin_menu() {
        add_menu_page(
            'MRP管理系统',
            'MRP管理',
            'manage_options',
            'mrp-manager',
            array($this, 'display_dashboard'),
            'dashicons-clipboard',
            30
        );
        
        // 添加子菜单
        add_submenu_page(
            'mrp-manager',
            '物料管理',
            '物料管理',
            'manage_options',
            'mrp-materials',
            array($this, 'display_materials_page')
        );
        
        add_submenu_page(
            'mrp-manager',
            'BOM管理',
            'BOM管理',
            'manage_options',
            'mrp-bom',
            array($this, 'display_bom_page')
        );
    }
    
    public function enqueue_admin_assets($hook) {
        if (strpos($hook, 'mrp-') !== false) {
            wp_enqueue_style('mrp-admin-style', MRP_PLUGIN_URL . 'assets/css/admin.css');
            wp_enqueue_script('mrp-admin-script', MRP_PLUGIN_URL . 'assets/js/admin.js', array('jquery'), '1.0', true);
        }
    }
    
    public function display_dashboard() {
        include MRP_PLUGIN_PATH . 'templates/dashboard.php';
    }
    
    public function display_materials_page() {
        include MRP_PLUGIN_PATH . 'templates/materials.php';
    }
    
    public function display_bom_page() {
        include MRP_PLUGIN_PATH . 'templates/bom.php';
    }
    
    private function create_tables() {
        global $wpdb;
        
        $charset_collate = $wpdb->get_charset_collate();
        
        // 物料表
        $materials_table = $wpdb->prefix . 'mrp_materials';
        $sql_materials = "CREATE TABLE IF NOT EXISTS $materials_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            material_code varchar(50) NOT NULL,
            material_name varchar(200) NOT NULL,
            category varchar(100) DEFAULT '',
            unit varchar(20) DEFAULT '',
            current_stock decimal(10,2) DEFAULT 0,
            safety_stock decimal(10,2) DEFAULT 0,
            lead_time int DEFAULT 0,
            supplier_info text,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            UNIQUE KEY material_code (material_code)
        ) $charset_collate;";
        
        // BOM表
        $bom_table = $wpdb->prefix . 'mrp_bom';
        $sql_bom = "CREATE TABLE IF NOT EXISTS $bom_table (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            product_code varchar(50) NOT NULL,
            product_name varchar(200) NOT NULL,
            material_id mediumint(9) NOT NULL,
            quantity decimal(10,2) NOT NULL,
            waste_rate decimal(5,2) DEFAULT 0,
            operation_sequence int DEFAULT 0,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY product_code (product_code),
            KEY material_id (material_id)
        ) $charset_collate;";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql_materials);
        dbDelta($sql_bom);
    }
    
    private function insert_initial_data() {
        // 可以插入一些初始数据
    }
}

// 初始化插件
$mrp_manager = new MRP_Manager();
?>

物料管理模块实现

物料管理是MRP的基础。下面我们创建一个物料管理类,用于处理物料的CRUD操作。

<?php
// 文件路径: includes/class-material-manager.php

class Material_Manager {
    
    private $table_name;
    
    public function __construct() {
        global $wpdb;
        $this->table_name = $wpdb->prefix . 'mrp_materials';
    }
    
    /**
     * 添加新物料
     * @param array $data 物料数据
     * @return int|false 插入ID或false
     */
    public function add_material($data) {
        global $wpdb;
        
        $defaults = array(
            'material_code' => '',
            'material_name' => '',
            'category' => '',
            'unit' => '个',
            'current_stock' => 0,
            'safety_stock' => 0,
            'lead_time' => 0,
            'supplier_info' => ''
        );
        
        $data = wp_parse_args($data, $defaults);
        
        // 验证必要字段
        if (empty($data['material_code']) || empty($data['material_name'])) {
            return false;
        }
        
        $result = $wpdb->insert(
            $this->table_name,
            $data,
            array('%s', '%s', '%s', '%s', '%f', '%f', '%d', '%s')
        );
        
        return $result ? $wpdb->insert_id : false;
    }
    
    /**
     * 更新物料信息
     * @param int $id 物料ID
     * @param array $data 更新数据
     * @return bool 是否成功
     */
    public function update_material($id, $data) {
        global $wpdb;
        
        $result = $wpdb->update(
            $this->table_name,
            $data,
            array('id' => $id),
            array('%s', '%s', '%s', '%s', '%f', '%f', '%d', '%s'),
            array('%d')
        );
        
        return $result !== false;
    }
    
    /**
     * 获取所有物料
     * @param array $args 查询参数
     * @return array 物料列表
     */
    public function get_materials($args = array()) {
        global $wpdb;
        
        $defaults = array(
            'per_page' => 20,
            'page' => 1,
            'search' => '',
            'category' => ''
        );
        
        $args = wp_parse_args($args, $defaults);
        
        $offset = ($args['page'] - 1) * $args['per_page'];
        
        $where = 'WHERE 1=1';
        $params = array();
        
        if (!empty($args['search'])) {
            $where .= " AND (material_code LIKE %s OR material_name LIKE %s)";
            $search_term = '%' . $wpdb->esc_like($args['search']) . '%';
            $params[] = $search_term;
            $params[] = $search_term;
        }
        
        if (!empty($args['category'])) {
            $where .= " AND category = %s";
            $params[] = $args['category'];
        }
        
        $query = "SELECT * FROM {$this->table_name} {$where} 
                  ORDER BY material_code LIMIT %d OFFSET %d";
        
        $params[] = $args['per_page'];
        $params[] = $offset;
        
        if (!empty($params)) {
            $query = $wpdb->prepare($query, $params);
        }
        
        return $wpdb->get_results($query);
    }
    
    /**
     * 根据ID获取物料
     * @param int $id 物料ID
     * @return object|null 物料对象
     */
    public function get_material($id) {
        global $wpdb;
        
        $query = $wpdb->prepare(
            "SELECT * FROM {$this->table_name} WHERE id = %d",
            $id
        );
        
        return $wpdb->get_row($query);
    }
    
    /**
     * 检查库存是否充足
     * @param int $material_id 物料ID
     * @param float $required_qty 需求数量
     * @return array 检查结果
     */
    public function check_stock($material_id, $required_qty) {
        $material = $this->get_material($material_id);
        
        if (!$material) {
            return array(
                'success' => false,
                'message' => '物料不存在'
            );
        }
        
        $available = $material->current_stock - $material->safety_stock;
        
        if ($available >= $required_qty) {
            return array(
                'success' => true,
                'available' => $available,
                'shortage' => 0
            );
        } else {
            return array(
                'success' => false,
                'available' => $available,
                'shortage' => $required_qty - $available,
                'message' => sprintf('库存不足,缺料 %.2f %s', 
                    $required_qty - $available, 
                    $material->unit)
            );
        }
    }
}
?>

BOM(物料清单)管理

BOM是MRP的核心,定义了产品与物料的关系。

<?php
// 文件路径: includes/class-bom-manager.php

class BOM_Manager {
    
    private $table_name;
    
    public function __construct() {
        global $wpdb;
        $this->table_name = $wpdb->prefix . 'mrp_bom';
    }
    
    /**
     * 创建或更新BOM
     * @param string $product_code 产品代码
     * @param string $product_name 产品名称
     * @param array $materials 物料数组
     * @return bool 是否成功
     */
    public function save_bom($product_code, $product_name, $materials) {
        global $wpdb;
        
        // 删除旧的BOM记录
        $this->delete_bom($product_code);
        
        // 插入新的BOM记录
        foreach ($materials as $index => $material) {
            $data = array(
                'product_code' => $product_code,
                'product_name' => $product_name,
                'material_id' => $material['id'],
                'quantity' => $material['quantity'],
                'waste_rate' => isset($material['waste_rate']) ? $material['waste_rate'] : 0,
                'operation_sequence' => $index + 1
            );
            
            $wpdb->insert(
                $this->table_name,
                $data,
                array('%s', '%s', '%d', '%f', '%f', '%d')
            );
        }
        
        return true;
    }
    
    /**
     * 获取产品的BOM
     * @param string $product_code 产品代码
     * @return array BOM列表
     */
    public function get_bom($product_code) {
        global $wpdb;
        
        $query = $wpdb->prepare(
            "SELECT b.*, m.material_code, m.material_name, m.unit 
             FROM {$this->table_name} b
             LEFT JOIN {$wpdb->prefix}mrp_materials m ON b.material_id = m.id
             WHERE b.product_code = %s
             ORDER BY b.operation_sequence",
            $product_code
        );
        
        return $wpdb->get_results($query);
    }
    
    /**
     * 计算物料需求
     * @param string $product_code 产品代码
     * @param float $quantity 生产数量
     * @return array 物料需求列表
     */
    public function calculate_material_requirements($product_code, $quantity) {
        $bom_items = $this->get_bom($product_code);
        $requirements = array();
        
        foreach ($bom_items as $item) {
            // 考虑损耗率
            $required_qty = $item->quantity * $quantity * (1 + $item->waste_rate / 100);
            
            $requirements[] = array(
                'material_id' => $item->material_id,
                'material_code' => $item->material_code,
                'material_name' => $item->material_name,
                'unit' => $item->unit,
                'required_qty' => round($required_qty, 2),
                'base_qty' => $item->quantity,
                'waste_rate' => $item->waste_rate
            );
        }
        
        return $requirements;
    }
    
    /**
     * 删除BOM
     * @param string $product_code 产品代码
     * @return bool 是否成功
     */
    private function delete_bom($product_code) {
        global $wpdb;
        
        return $wpdb->delete(
            $this->table_name,
            array('product_code' => $product_code),
            array('%s')
        );
    }
}
?>

MRP计算引擎实现

这是MRP系统的核心计算逻辑。

<?php
// 文件路径: includes/class-mrp-calculator.php

class MRP_Calculator {
    
    private $material_manager;
    private $bom_manager;
    
    public function __construct() {
        $this->material_manager = new Material_Manager();
        $this->bom_manager = new BOM_Manager();
    }
    
    /**
     * 执行MRP计算
     * @param array $production_orders 生产订单数组
     * @return array MRP计算结果
     */
    public function run_mrp_calculation($production_orders) {
        $results = array(
            'material_requirements' => array(),
            'stock_shortages' => array(),
            'purchase_suggestions' => array(),
            'summary' => array()
        );
        
        // 汇总所有物料需求
        $total_requirements = array();
        
        foreach ($production_orders as $order) {
            $requirements = $this->bom_manager->calculate_material_requirements(
                $order['product_code'],
                $order['quantity']
            );
            
            foreach ($requirements as $req) {
                $material_id = $req['material_id'];
                
                if (!isset($total_requirements[$material_id])) {
                    $total_requirements[$material_id] = array(
                        'material_id' => $material_id,
                        'material_code' => $req['material_code'],
                        'material_name' => $req['material_name'],
                        'unit' => $req['unit'],
                        'total_required' => 0,
                        'orders' => array()
                    );
                }
                
                $total_requirements[$material_id]['total_required'] += $req['required_qty'];
                $total_requirements[$material_id]['orders'][] = array(
                    'product_code' => $order['product_code'],
                    'quantity' => $order['quantity'],
                    'required_qty' => $req['required_qty']
                );
            }
        }
        
        // 检查库存并生成采购建议
        foreach ($total_requirements as $material_id => $requirement) {
            $stock_check = $this->material_manager->check_stock(
                $material_id,
                $requirement['total_required']
            );
            
            $results['material_requirements'][] = array_merge(
                $requirement,
                array('stock_check' => $stock_check)
            );
            
            if (!$stock_check['success']) {
                $material = $this->material_manager->get_material($material_id);
                
                $results['stock_shortages'][] = array(
                    'material_id' => $material_id,
                    'material_code' => $requirement['material_code'],
                    'material_name' => $requirement['material_name'],
                    'required_qty' => $requirement['total_required'],
                    'available_qty' => $stock_check['available'],
                    'shortage_qty' => $stock_check['shortage'],
                    'unit' => $requirement['unit'],
                    'lead_time' => $material->lead_time
                );
                
                // 生成采购建议(考虑安全库存)
                $purchase_qty = max(
                    $stock_check['shortage'],
                    $material->safety_stock * 0.5 // 至少采购安全库存的50%
                );
                
                $results['purchase_suggestions'][] = array(
                    'material_id' => $material_id,
                    'material_code' => $requirement['material_code'],
                    'material_name' => $requirement['material_name'],
                    'purchase_qty' => ceil($purchase_qty), // 向上取整
                    'unit' => $requirement['unit'],
                    'lead_time' => $material->lead_time,
                    'suggested_order_date' => date('Y-m-d'),
                    'suggested_delivery_date' => date('Y-m-d', strtotime("+{$material->lead_time} days"))
                );
            }
        }
        
        // 生成摘要信息
        $results['summary'] = array(
            'total_materials' => count($total_requirements),
            'total_requirements' => array_sum(array_column($results['material_requirements'], 'total_required')),
            'shortages_count' => count($results['stock_shortages']),
            'purchase_suggestions_count' => count($results['purchase_suggestions']),
            'calculation_time' => current_time('mysql')
        );
        
        return $results;
    }
    
    /**
     * 生成MRP报告
     * @param array $mrp_results MRP计算结果
     * @return string HTML格式的报告
     */
    public function generate_mrp_report($mrp_results) {
        ob_start();
        ?>
        <div class="mrp-report">
            <h2>MRP计算报告</h2>
            <p>生成时间: <?php echo $mrp_results['summary']['calculation_time']; ?></p>
            
            <div class="summary">
                <h3>摘要</h3>
                <ul>
                    <li>涉及物料种类: <?php echo $mrp_results['summary']['total_materials']; ?></li>
                    <li>总需求数量: <?php echo $mrp_results['summary']['total_requirements']; ?></li>
                    <li>缺料数量: <?php echo $mrp_results['summary']['shortages_count']; ?></li>
                    <li>采购建议: <?php echo $mrp_results['summary']['purchase_suggestions_count']; ?> 项</li>
                </ul>
            </div>
            
            <?php if (!empty($mrp_results['stock_shortages'])): ?>
            <div class="shortages">
                <h3>库存短缺明细</h3>
                <table class="wp-list-table widefat fixed striped">
                    <thead>
                        <tr>
                            <th>物料编码</th>
                            <th>物料名称</th>
                            <th>需求数量</th>
                            <th>可用库存</th>
                            <th>短缺数量</th>
                            <th>单位</th>
                            <th>采购提前期</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ($mrp_results['stock_shortages'] as $shortage): ?>
                        <tr>
                            <td><?php echo esc_html($shortage['material_code']); ?></td>
                            <td><?php echo esc_html($shortage['material_name']); ?></td>
                            <td class="number"><?php echo number_format($shortage['required_qty'], 2); ?></td>
                            <td class="number"><?php echo number_format($shortage['available_qty'], 2); ?></td>
                            <td class="number highlight"><?php echo number_format($shortage['shortage_qty'], 2); ?></td>
                            <td><?php echo esc_html($shortage['unit']); ?></td>
                            <td><?php echo $shortage['lead_time']; ?> 天</td>
                        </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
            <?php endif; ?>
            
            <?php if (!empty($mrp_results['purchase_suggestions'])): ?>
            <div class="purchase-suggestions">
                <h3>采购建议</h3>
                <table class="wp-list-table widefat fixed striped">
                    <thead>
                        <tr>
                            <th>物料编码</th>
                            <th>物料名称</th>
                            <th>建议采购量</th>
                            <th>单位</th>
                            <th>建议下单日期</th>
                            <th>期望到货日期</th>
                            <th>操作</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ($mrp_results['purchase_suggestions'] as $suggestion): ?>
                        <tr>
                            <td><?php echo esc_html($suggestion['material_code']); ?></td>
                            <td><?php echo esc_html($suggestion['material_name']); ?></td>
                            <td class="number"><?php echo number_format($suggestion['purchase_qty'], 2); ?></td>
                            <td><?php echo esc_html($suggestion['unit']); ?></td>
                            <td><?php echo $suggestion['suggested_order_date']; ?></td>
                            <td><?php echo $suggestion['suggested_delivery_date']; ?></td>
                            <td>
                                <button class="button button-small create-po" 
                                        data-material-id="<?php echo $suggestion['material_id']; ?>"
                                        data-quantity="<?php echo $suggestion['purchase_qty']; ?>">
                                    创建采购单
                                </button>
                            </td>
                        </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
            <?php endif; ?>
        </div>
        <?php
        return ob_get_clean();
    }
}
?>

前端界面与用户交互

创建用户友好的管理界面是插件成功的关键。

<?php
// 文件路径: templates/mrp-calculator.php

/**
 * MRP计算器界面
 */

// 检查权限
if (!current_user_can('manage_options')) {
    wp_die('权限不足');
}

// 处理表单提交
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['mrp_calculate'])) {
    $production_orders = array();
    
    if (!empty($_POST['production_orders'])) {
        foreach ($_POST['production_orders'] as $order) {
            if (!empty($order['product_code']) && !empty($order['quantity'])) {
                $production_orders[] = array(
                    'product_code' => sanitize_text_field($order['product_code']),
                    'quantity' => floatval($order['quantity'])
                );
            }
        }
    }
    
    if (!empty($production_orders)) {
        $mrp_calculator = new MRP_Calculator();
        $mrp_results = $mrp_calculator->run_mrp_calculation($production_orders);
        $report = $mrp_calculator->generate_mrp_report($mrp_results);
    }
}

// 获取产品列表
global $wpdb;
$products = $wpdb->get_results(
    "SELECT DISTINCT product_code, product_name 
     FROM {$wpdb->prefix}mrp_bom 
     ORDER BY product_code"
);
?>

<div class="wrap">
    <h1>MRP计算器</h1>
    
    <div class="mrp-container">
        <div class="mrp-left">
            <form method="post" action="">
                <?php wp_nonce_field('mrp_calculate_action', 'mrp_nonce'); ?>
                
                <div class="production-orders">
                    <h3>生产订单输入</h3>
                    
                    <div id="order-list">
                        <div class="order-item">
                            <div class="order-row">
                                <div class="order-field">
                                    <label>产品代码:</label>
                                    <select name="production_orders[0][product_code]" class="product-select">
                                        <option value="">选择产品</option>
                                        <?php foreach ($products as $product): ?>
                                        <option value="<?php echo esc_attr($product->product_code); ?>">
                                            <?php echo esc_html($product->product_code . ' - ' . $product->product_name); ?>
                                        </option>
                                        <?php endforeach; ?>
                                    </select>
                                </div>
                                
                                <div class="order-field">
                                    <label>生产数量:</label>
                                    <input type="number" 
                                           name="production_orders[0][quantity]" 
                                           step="0.01" 
                                           min="0" 
                                           value="1"
                                           class="small-text">
                                </div>
                                
                                <div class="order-field">
                                    <button type="button" class="button remove-order" style="display:none;">
                                        删除
                                    </button>
                                </div>
                            </div>
                            
                            <div class="product-details" style="display:none;">
                                <!-- 产品详情将通过AJAX加载 -->
                            </div>
                        </div>
                    </div>
                    
                    <button type="button" id="add-order" class="button">
                        + 添加生产订单
                    </button>
                </div>
                
                <div class="mrp-actions">
                    <button type="submit" 
                            name="mrp_calculate" 
                            class="button button-primary button-large">
                        执行MRP计算
                    </button>
                    
                    <button type="button" id="clear-orders" class="button">
                        清空所有
                    </button>
                </div>
            </form>
        </div>
        
        <div class="mrp-right">
            <?php if (isset($report)): ?>
                <?php echo $report; ?>
                
                <div class="export-options">
                    <h4>导出选项</h4>
                    <button type="button" id="export-pdf" class="button">
                        导出为PDF
                    </button>
                    <button type="button" id="export-excel" class="button">
                        导出为Excel
                    </button>
                    <button type="button" id="print-report" class="button">
                        打印报告
                    </button>
                </div>
            <?php else: ?>
                <div class="mrp-instructions">
                    <h3>使用说明</h3>
                    <ol>
                        <li>在左侧添加生产订单</li>
                        <li>选择产品代码和输入生产数量</li>
                        <li>点击"执行MRP计算"按钮</li>
                        <li>系统将自动计算物料需求并识别短缺</li>
                        <li>根据采购建议创建采购订单</li>
                    </ol>
                    
                    <div class="tips">
                        <h4>小批量定制生产提示:</h4>
                        <ul>
                            <li>对于定制产品,建议先创建BOM再运行MRP</li>
                            <li>考虑设置较高的安全库存以应对紧急订单</li>
                            <li>定期更新物料库存信息</li>
                            <li>及时调整采购提前期数据</li>
                        </ul>
                    </div>
                </div>
            <?php endif; ?>
        </div>
    </div>
</div>

<script type="text/javascript">
jQuery(document).ready(function($) {
    let orderCount = 1;
    
    // 添加生产订单
    $('#add-order').on('click', function() {
        const orderItem = `
            <div class="order-item">
                <div class="order-row">
                    <div class="order-field">
                        <label>产品代码:</label>
                        <select name="production_orders[${orderCount}][product_code]" class="product-select">
                            <option value="">选择产品</option>
                            <?php foreach ($products as $product): ?>
                            <option value="<?php echo esc_attr($product->product_code); ?>">
                                <?php echo esc_html($product->product_code . ' - ' . $product->product_name); ?>
                            </option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    
                    <div class="order-field">
                        <label>生产数量:</label>
                        <input type="number" 
                               name="production_orders[${orderCount}][quantity]" 
                               step="0.01" 
                               min="0" 
                               value="1"
                               class="small-text">
                    </div>
                    
                    <div class="order-field">
                        <button type="button" class="button remove-order">
                            删除
                        </button>
                    </div>
                </div>
                
                <div class="product-details" style="display:none;"></div>
            </div>
        `;
        
        $('#order-list').append(orderItem);
        orderCount++;
        
        // 显示所有删除按钮(除了第一个)
        $('.remove-order').show();
        $('#order-list .order-item:first-child .remove-order').hide();
    });
    
    // 删除生产订单
    $(document).on('click', '.remove-order', function() {
        if ($('.order-item').length > 1) {
            $(this).closest('.order-item').remove();
        }
    });
    
    // 产品选择变化时加载BOM详情
    $(document).on('change', '.product-select', function() {
        const productCode = $(this).val();
        const detailsDiv = $(this).closest('.order-item').find('.product-details');
        
        if (productCode) {
            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: {
                    action: 'get_bom_details',
                    product_code: productCode,
                    nonce: '<?php echo wp_create_nonce('mrp_ajax_nonce'); ?>'
                },
                beforeSend: function() {
                    detailsDiv.html('<p>加载中...</p>').show();
                },
                success: function(response) {
                    if (response.success) {
                        detailsDiv.html(response.data);
                    } else {
                        detailsDiv.html('<p class="error">加载失败</p>');
                    }
                }
            });
        } else {
            detailsDiv.hide();
        }
    });
    
    // 创建采购单
    $(document).on('click', '.create-po', function() {
        const materialId = $(this).data('material-id');
        const quantity = $(this).data('quantity');
        
        if (confirm('确定要创建采购单吗?')) {
            $.ajax({
                url: ajaxurl,
                type: 'POST',
                data: {
                    action: 'create_purchase_order',
                    material_id: materialId,
                    quantity: quantity,
                    nonce: '<?php echo wp_create_nonce('mrp_ajax_nonce'); ?>'
                },
                success: function(response) {
                    if (response.success) {
                        alert('采购单创建成功!');
                        $(this).replaceWith('<span class="dashicons dashicons-yes-alt"></span> 已创建');
                    } else {
                        alert('创建失败: ' + response.data);
                    }
                }
            });
        }
    });
    
    // 清空所有订单
    $('#clear-orders').on('click', function() {
        if (confirm('确定要清空所有生产订单吗?')) {
            $('#order-list').html(`
                <div class="order-item">
                    <div class="order-row">
                        <div class="order-field">
                            <label>产品代码:</label>
                            <select name="production_orders[0][product_code]" class="product-select">
                                <option value="">选择产品</option>
                                <?php foreach ($products as $product): ?>
                                <option value="<?php echo esc_attr($product->product_code); ?>">
                                    <?php echo esc_html($product->product_code . ' - ' . $product->product_name); ?>
                                </option>
                                <?php endforeach; ?>
                            </select>
                        </div>
                        
                        <div class="order-field">
                            <label>生产数量:</label>
                            <input type="number" 
                                   name="production_orders[0][quantity]" 
                                   step="0.01" 
                                   min="0" 
                                   value="1"
                                   class="small-text">
                        </div>
                        
                        <div class="order-field">
                            <button type="button" class="button remove-order" style="display:none;">
                                删除
                            </button>
                        </div>
                    </div>
                    
                    <div class="product-details" style="display:none;"></div>
                </div>
            `);
            orderCount = 1;
        }
    });
});
</script>

<style type="text/css">
.mrp-container {
    display: flex;
    gap: 30px;
    margin-top: 20px;
}

.mrp-left {
    flex: 1;
    min-width: 400px;
}

.mrp-right {
    flex: 2;
    min-width: 500px;
}

.production-orders {
    background: #fff;
    padding: 20px;
    border: 1px solid #ccd0d4;
    box-shadow: 0 1px 1px rgba(0,0,0,.04);
}

.order-item {
    margin-bottom: 15px;
    padding: 15px;
    background: #f9f9f9;
    border: 1px solid #e5e5e5;
}

.order-row {
    display: flex;
    gap: 10px;
    align-items: flex-end;
}

.order-field {
    flex: 1;
}

.order-field label {
    display: block;
    margin-bottom: 5px;
    font-weight: 600;
}

.product-details {
    margin-top: 10px;
    padding: 10px;
    background: #fff;
    border: 1px dashed #ddd;
}

.mrp-actions {
    margin-top: 20px;
    padding-top: 20px;
    border-top: 1px solid #ddd;
}

.mrp-report .summary,
.mrp-report .shortages,
.mrp-report .purchase-suggestions {
    margin-bottom: 30px;
}

.mrp-report table {
    margin-top: 10px;
}

.mrp-report .number {
    text-align: right;
}

.mrp-report .highlight {
    color: #d63638;
    font-weight: bold;
}

.export-options {
    margin-top: 20px;
    padding: 15px;
    background: #f0f6fc;
    border: 1px solid #c3c4c7;
}

.mrp-instructions {
    background: #fff;
    padding: 20px;
    border: 1px solid #ccd0d4;
}

.mrp-instructions ol,
.mrp-instructions ul {
    margin-left: 20px;
}

.tips {
    margin-top: 20px;
    padding: 15px;
    background: #f0f6fc;
    border-left: 4px solid #72aee6;
}
</style>

AJAX处理与数据交互

<?php
// 文件路径: includes/class-ajax-handler.php

class MRP_Ajax_Handler {
    
    public function __construct() {
        add_action('wp_ajax_get_bom_details', array($this, 'get_bom_details'));
        add_action('wp_ajax_create_purchase_order', array($this, 'create_purchase_order'));
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5955.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部