首页 / 教程文章 / WordPress柔性供应链软件开发中的容器化部署教程

WordPress柔性供应链软件开发中的容器化部署教程

WordPress柔性供应链软件开发中的容器化部署教程

引言:为什么需要容器化部署

在当今快速发展的电商环境中,柔性供应链系统需要具备高度可扩展性和弹性。WordPress作为广泛使用的内容管理系统,结合定制化的供应链插件,可以构建强大的电商解决方案。然而,传统的部署方式在面对流量波动、快速迭代和跨环境一致性时面临挑战。

容器化技术通过将应用程序及其依赖项打包到标准化单元中,实现了环境一致性、快速部署和弹性扩展。本教程将详细介绍如何将WordPress柔性供应链软件进行容器化部署。

环境准备与Docker安装

Docker环境配置

首先,我们需要在服务器上安装Docker和Docker Compose。以下是在Ubuntu系统上的安装步骤:

#!/bin/bash
# 更新系统包列表
sudo apt-get update

# 安装必要的依赖包
sudo apt-get install -y 
    apt-transport-https 
    ca-certificates 
    curl 
    gnupg 
    lsb-release

# 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 设置稳定版仓库
echo 
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu 
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装Docker引擎
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io

# 安装Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-$(uname -s)-$(uname -m)" 
    -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# 验证安装
docker --version
docker-compose --version

项目结构规划

创建以下项目目录结构:

wordpress-supply-chain/
├── docker-compose.yml
├── nginx/
│   ├── Dockerfile
│   └── nginx.conf
├── wordpress/
│   └── Dockerfile
├── mysql/
│   └── init.sql
├── php/
│   └── custom.ini
└── plugins/
    └── supply-chain-manager/
        └── (供应链插件文件)

Docker容器配置详解

MySQL数据库配置

创建MySQL初始化脚本,用于设置供应链数据库:

-- mysql/init.sql
-- 创建供应链专用数据库
CREATE DATABASE IF NOT EXISTS supply_chain_db;
USE supply_chain_db;

-- 创建供应商表
CREATE TABLE IF NOT EXISTS suppliers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    contact_email VARCHAR(255),
    phone VARCHAR(50),
    address TEXT,
    reliability_score DECIMAL(3,2) DEFAULT 0.00,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 创建库存表
CREATE TABLE IF NOT EXISTS inventory (
    id INT AUTO_INCREMENT PRIMARY KEY,
    product_id INT NOT NULL,
    supplier_id INT,
    quantity INT DEFAULT 0,
    reorder_level INT DEFAULT 10,
    last_restocked DATE,
    location VARCHAR(100),
    FOREIGN KEY (supplier_id) REFERENCES suppliers(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 创建订单跟踪表
CREATE TABLE IF NOT EXISTS order_tracking (
    id INT AUTO_INCREMENT PRIMARY KEY,
    order_id VARCHAR(50) NOT NULL,
    status ENUM('pending', 'processing', 'shipped', 'delivered', 'cancelled') DEFAULT 'pending',
    supplier_id INT,
    estimated_delivery DATE,
    actual_delivery DATE,
    tracking_number VARCHAR(100),
    notes TEXT,
    FOREIGN KEY (supplier_id) REFERENCES suppliers(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 插入示例数据
INSERT INTO suppliers (name, contact_email, reliability_score) VALUES
('优质供应商A', 'supplierA@example.com', 4.8),
('快速配送B', 'supplierB@example.com', 4.5),
('经济优选C', 'supplierC@example.com', 4.2);

WordPress Dockerfile配置

创建WordPress容器的Dockerfile,集成供应链插件:

# wordpress/Dockerfile
# 使用官方WordPress镜像作为基础
FROM wordpress:6.2-php8.1-apache

# 设置维护者信息
LABEL maintainer="supply-chain-dev@example.com"

# 安装必要的PHP扩展
RUN apt-get update && apt-get install -y 
    libzip-dev 
    libpng-dev 
    libjpeg-dev 
    libfreetype6-dev 
    && docker-php-ext-configure gd --with-freetype --with-jpeg 
    && docker-php-ext-install -j$(nproc) gd zip pdo_mysql

# 复制自定义PHP配置
COPY ../php/custom.ini /usr/local/etc/php/conf.d/custom.ini

# 复制供应链插件到WordPress插件目录
COPY ../plugins/supply-chain-manager /var/www/html/wp-content/plugins/supply-chain-manager

# 设置插件目录权限
RUN chown -R www-data:www-data /var/www/html/wp-content/plugins/supply-chain-manager 
    && chmod -R 755 /var/www/html/wp-content/plugins/supply-chain-manager

# 创建供应链数据目录
RUN mkdir -p /var/www/html/wp-content/uploads/supply-chain 
    && chown -R www-data:www-data /var/www/html/wp-content/uploads/supply-chain

# 暴露Apache端口
EXPOSE 80

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 
    CMD curl -f http://localhost/ || exit 1

Nginx反向代理配置

创建Nginx配置文件,优化WordPress性能:

# nginx/nginx.conf
events {
    worker_connections 1024;
}

http {
    # 基础配置
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    
    # MIME类型
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # 日志配置
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    
    # Gzip压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
    
    # WordPress上游服务器
    upstream wordpress {
        server wordpress:80;
    }
    
    # 主服务器配置
    server {
        listen 80;
        server_name supplychain.example.com;
        
        # 根目录
        root /var/www/html;
        index index.php index.html index.htm;
        
        # WordPress重写规则
        location / {
            try_files $uri $uri/ /index.php?$args;
        }
        
        # PHP处理
        location ~ .php$ {
            fastcgi_pass wordpress:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
            
            # 增加超时时间用于供应链数据处理
            fastcgi_read_timeout 300;
        }
        
        # 静态文件缓存
        location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
        
        # 供应链API端点
        location ~ ^/wp-json/supply-chain/ {
            # 增加API超时时间
            fastcgi_read_timeout 60;
            
            # 允许跨域请求(开发环境)
            add_header 'Access-Control-Allow-Origin' '*' always;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
        }
        
        # 安全设置
        location ~ /.ht {
            deny all;
        }
    }
}

Docker Compose编排配置

创建完整的docker-compose.yml文件,编排所有服务:

# docker-compose.yml
version: '3.8'

services:
  # MySQL数据库服务
  mysql:
    image: mysql:8.0
    container_name: supply-chain-mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-secure_root_password}
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: ${DB_PASSWORD:-secure_password}
    volumes:
      - mysql_data:/var/lib/mysql
      - ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - supply-chain-network
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

  # WordPress应用服务
  wordpress:
    build: ./wordpress
    container_name: supply-chain-wordpress
    restart: unless-stopped
    depends_on:
      mysql:
        condition: service_healthy
    environment:
      WORDPRESS_DB_HOST: mysql:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD:-secure_password}
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_CONFIG_EXTRA: |
        define('WP_DEBUG', ${WP_DEBUG:-false});
        define('WP_DEBUG_LOG', ${WP_DEBUG_LOG:-false});
        define('SUPPLY_CHAIN_API_KEY', ${SUPPLY_CHAIN_API_KEY:-default_key});
    volumes:
      - wordpress_data:/var/www/html/wp-content
      - ./plugins/supply-chain-manager:/var/www/html/wp-content/plugins/supply-chain-manager
    networks:
      - supply-chain-network
    expose:
      - "80"

  # Nginx反向代理
  nginx:
    build: ./nginx
    container_name: supply-chain-nginx
    restart: unless-stopped
    depends_on:
      - wordpress
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - wordpress_data:/var/www/html/wp-content
    networks:
      - supply-chain-network

  # 供应链监控服务(可选)
  monitor:
    image: redis:7-alpine
    container_name: supply-chain-monitor
    restart: unless-stopped
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    networks:
      - supply-chain-network
    ports:
      - "6379:6379"

  # 备份服务
  backup:
    image: alpine:latest
    container_name: supply-chain-backup
    restart: on-failure
    depends_on:
      - mysql
      - wordpress
    volumes:
      - backup_data:/backup
      - mysql_data:/var/lib/mysql:ro
      - wordpress_data:/var/www/html/wp-content:ro
    networks:
      - supply-chain-network
    command: >
      sh -c '
      echo "备份服务启动..."
      while true; do
        # 每天凌晨3点执行备份
        if [ $$(date +%H) -eq 03 ]; then
          echo "开始备份: $$(date)"
          # 备份MySQL数据库
          mysqldump -h mysql -u wordpress -p$${DB_PASSWORD:-secure_password} wordpress > /backup/mysql-backup-$$(date +%Y%m%d).sql
          # 备份WordPress内容
          tar -czf /backup/wordpress-backup-$$(date +%Y%m%d).tar.gz /var/www/html/wp-content
          echo "备份完成: $$(date)"
          # 删除7天前的备份
          find /backup -name "*.sql" -mtime +7 -delete
          find /backup -name "*.tar.gz" -mtime +7 -delete
        fi
        sleep 3600
      done
      '

# 数据卷定义
volumes:
  mysql_data:
    name: supply-chain-mysql-data
  wordpress_data:
    name: supply-chain-wordpress-data
  redis_data:
    name: supply-chain-redis-data
  backup_data:
    name: supply-chain-backup-data

# 网络定义
networks:
  supply-chain-network:
    driver: bridge
    name: supply-chain-network

部署与运维脚本

部署脚本

创建自动化部署脚本:

#!/bin/bash
# deploy.sh - WordPress供应链系统容器化部署脚本

set -e  # 遇到错误时退出

# 颜色定义
RED='33[0;31m'
GREEN='33[0;32m'
YELLOW='33[1;33m'
NC='33[0m' # No Color

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 检查Docker是否安装
check_docker() {
    if ! command -v docker &> /dev/null; then
        log_error "Docker未安装,请先安装Docker"
        exit 1
    fi
    
    if ! command -v docker-compose &> /dev/null; then
        log_error "Docker Compose未安装,请先安装Docker Compose"
        exit 1
    fi
    
    log_info "Docker和Docker Compose已安装"
}

# 创建环境变量文件
setup_env() {
    if [ ! -f .env ]; then
        log_info "创建环境变量文件..."
        cat > .env << EOF
# WordPress数据库配置
DB_ROOT_PASSWORD=$(openssl rand -base64 32)
DB_PASSWORD=$(openssl rand -base64 32)

# WordPress调试设置
WP_DEBUG=false
WP_DEBUG_LOG=false

# 供应链API密钥
SUPPLY_CHAIN_API_KEY=$(openssl rand -base64 32)

# 时区设置
TZ=Asia/Shanghai
EOF
        log_info "环境变量文件已创建"
    else
        log_warn "环境变量文件已存在,跳过创建"
    fi
}

# 构建并启动容器
start_containers() {
    log_info "开始构建Docker镜像..."
    docker-compose build --no-cache
    
    log_info "启动容器..."
    docker-compose up -d
    
    # 等待服务启动
    log_info "等待服务启动..."
    sleep 30
    
    # 检查服务状态
    if docker-compose ps | grep -q "Up"; then
        log_info "所有服务已成功启动!"
        
        # 显示访问信息
        echo "========================================"
        echo "WordPress供应链系统已部署完成!"
        echo "访问地址: http://localhost"
        echo "MySQL端口: 3306"
        echo "Redis监控: localhost:6379"
        echo "========================================"
    else
        log_error "部分服务启动失败,请检查日志"
        docker-compose logs
        exit 1
    fi
}

# 执行健康检查
health_check() {
    log_info "执行健康检查..."
    
    # 检查WordPress
    if curl -f http://localhost > /dev/null 2>&1; then
        log_info "WordPress服务正常"
    else
        log_error "WordPress服务异常"
    fi
    
    # 检查MySQL
    if docker-compose exec -T mysql mysqladmin ping -h localhost > /dev/null 2>&1; then
        log_info "MySQL服务正常"
    else
        log_error "MySQL服务异常"
    fi
}

# 主函数
main() {
    log_info "开始部署WordPress供应链系统..."
    
    # 检查依赖
    check_docker
    
    # 设置环境变量
    setup_env
    
    # 启动容器
    start_containers
    
    # 健康检查
    health_check
    
    log_info "部署完成!"
}

# 执行主函数
main "$@"

供应链插件示例代码

创建供应链管理插件的核心功能文件:

<?php
/**
 * WordPress供应链管理插件
 * 文件名: supply-chain-manager.php
 * 描述: 柔性供应链核心管理功能
 */

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

/**
 * 供应链管理器主类
 */
class SupplyChainManager {
    
    private $db;
    private $api_key;
    
    /**
     * 构造函数
     */
    public function __construct() {
        global $wpdb;
        $this->db = $wpdb;
        $this->api_key = defined('SUPPLY_CHAIN_API_KEY') ? SUPPLY_CHAIN_API_KEY : '';
        
        // 初始化钩子
        $this->init_hooks();
    }
    
    /**
     * 初始化WordPress钩子
     */
    private function init_hooks() {
        // 添加管理菜单
        add_action('admin_menu', array($this, 'add_admin_menu'));
        
        // 注册REST API端点
        add_action('rest_api_init', array($this, 'register_rest_routes'));
        

// 注册供应链数据表

    register_activation_hook(__FILE__, array($this, 'create_tables'));
    
    // 添加库存检查钩子
    add_action('woocommerce_checkout_order_processed', array($this, 'check_inventory'), 10, 3);
    
    // 添加供应商选择短代码
    add_shortcode('supplier_selection', array($this, 'supplier_selection_shortcode'));
}

/**
 * 创建供应链数据表
 */
public function create_tables() {
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    
    $charset_collate = $this->db->get_charset_collate();
    
    // 供应商表
    $suppliers_table = $this->db->prefix . 'supply_chain_suppliers';
    $sql = "CREATE TABLE IF NOT EXISTS $suppliers_table (
        id mediumint(9) 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,
        reliability_score decimal(3,2) DEFAULT 0.00,
        lead_time_days int DEFAULT 7,
        minimum_order decimal(10,2),
        payment_terms text,
        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),
        INDEX idx_reliability (reliability_score),
        INDEX idx_active (is_active)
    ) $charset_collate;";
    dbDelta($sql);
    
    // 库存表
    $inventory_table = $this->db->prefix . 'supply_chain_inventory';
    $sql = "CREATE TABLE IF NOT EXISTS $inventory_table (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        product_id bigint(20) NOT NULL,
        supplier_id mediumint(9),
        sku varchar(100),
        current_stock int DEFAULT 0,
        reserved_stock int DEFAULT 0,
        available_stock int GENERATED ALWAYS AS (current_stock - reserved_stock) STORED,
        reorder_point int DEFAULT 10,
        safety_stock int DEFAULT 5,
        unit_cost decimal(10,2),
        location varchar(100),
        batch_number varchar(50),
        expiry_date date,
        last_updated datetime DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        FOREIGN KEY (supplier_id) REFERENCES $suppliers_table(id) ON DELETE SET NULL,
        INDEX idx_product (product_id),
        INDEX idx_available (available_stock),
        INDEX idx_reorder (reorder_point),
        UNIQUE KEY unique_product_supplier (product_id, supplier_id)
    ) $charset_collate;";
    dbDelta($sql);
    
    // 采购订单表
    $orders_table = $this->db->prefix . 'supply_chain_orders';
    $sql = "CREATE TABLE IF NOT EXISTS $orders_table (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        order_number varchar(50) NOT NULL UNIQUE,
        supplier_id mediumint(9) NOT NULL,
        status enum('draft','pending','confirmed','shipped','delivered','cancelled') DEFAULT 'draft',
        total_amount decimal(10,2) DEFAULT 0.00,
        currency varchar(3) DEFAULT 'USD',
        order_date datetime DEFAULT CURRENT_TIMESTAMP,
        expected_delivery date,
        actual_delivery date,
        notes text,
        created_by bigint(20),
        PRIMARY KEY (id),
        FOREIGN KEY (supplier_id) REFERENCES $suppliers_table(id),
        INDEX idx_status (status),
        INDEX idx_delivery (expected_delivery),
        INDEX idx_supplier (supplier_id)
    ) $charset_collate;";
    dbDelta($sql);
    
    // 订单项表
    $order_items_table = $this->db->prefix . 'supply_chain_order_items';
    $sql = "CREATE TABLE IF NOT EXISTS $order_items_table (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        order_id mediumint(9) NOT NULL,
        product_id bigint(20) NOT NULL,
        quantity int NOT NULL,
        unit_price decimal(10,2) NOT NULL,
        total_price decimal(10,2) GENERATED ALWAYS AS (quantity * unit_price) STORED,
        received_quantity int DEFAULT 0,
        status enum('pending','partial','completed') DEFAULT 'pending',
        PRIMARY KEY (id),
        FOREIGN KEY (order_id) REFERENCES $orders_table(id) ON DELETE CASCADE,
        INDEX idx_order (order_id),
        INDEX idx_product (product_id)
    ) $charset_collate;";
    dbDelta($sql);
}

/**
 * 添加管理菜单
 */
public function add_admin_menu() {
    add_menu_page(
        '供应链管理',
        '供应链',
        'manage_options',
        'supply-chain',
        array($this, 'render_dashboard'),
        'dashicons-networking',
        30
    );
    
    add_submenu_page(
        'supply-chain',
        '供应商管理',
        '供应商',
        'manage_options',
        'supply-chain-suppliers',
        array($this, 'render_suppliers_page')
    );
    
    add_submenu_page(
        'supply-chain',
        '库存管理',
        '库存',
        'manage_options',
        'supply-chain-inventory',
        array($this, 'render_inventory_page')
    );
    
    add_submenu_page(
        'supply-chain',
        '采购订单',
        '采购订单',
        'manage_options',
        'supply-chain-orders',
        array($this, 'render_orders_page')
    );
    
    add_submenu_page(
        'supply-chain',
        '报表分析',
        '报表',
        'manage_options',
        'supply-chain-reports',
        array($this, 'render_reports_page')
    );
}

/**
 * 注册REST API端点
 */
public function register_rest_routes() {
    // 供应商API
    register_rest_route('supply-chain/v1', '/suppliers', array(
        'methods' => 'GET',
        'callback' => array($this, 'get_suppliers_api'),
        'permission_callback' => array($this, 'check_api_permission')
    ));
    
    register_rest_route('supply-chain/v1', '/suppliers/(?P<id>d+)', array(
        'methods' => 'GET',
        'callback' => array($this, 'get_supplier_api'),
        'permission_callback' => array($this, 'check_api_permission')
    ));
    
    // 库存API
    register_rest_route('supply-chain/v1', '/inventory', array(
        'methods' => 'GET',
        'callback' => array($this, 'get_inventory_api'),
        'permission_callback' => array($this, 'check_api_permission')
    ));
    
    register_rest_route('supply-chain/v1', '/inventory/low-stock', array(
        'methods' => 'GET',
        'callback' => array($this, 'get_low_stock_api'),
        'permission_callback' => array($this, 'check_api_permission')
    ));
    
    // 订单API
    register_rest_route('supply-chain/v1', '/orders', array(
        'methods' => 'POST',
        'callback' => array($this, 'create_order_api'),
        'permission_callback' => array($this, 'check_api_permission')
    ));
}

/**
 * API权限检查
 */
public function check_api_permission($request) {
    $api_key = $request->get_header('X-API-Key');
    
    // 验证API密钥
    if ($api_key === $this->api_key) {
        return true;
    }
    
    // 检查用户权限
    if (current_user_can('manage_options')) {
        return true;
    }
    
    return new WP_Error('rest_forbidden', '无权访问', array('status' => 403));
}

/**
 * 获取供应商列表API
 */
public function get_suppliers_api($request) {
    $table_name = $this->db->prefix . 'supply_chain_suppliers';
    
    $page = $request->get_param('page') ? intval($request->get_param('page')) : 1;
    $per_page = $request->get_param('per_page') ? intval($request->get_param('per_page')) : 20;
    $offset = ($page - 1) * $per_page;
    
    // 构建查询
    $sql = "SELECT * FROM $table_name WHERE is_active = 1";
    
    // 添加筛选条件
    if ($request->get_param('min_reliability')) {
        $min_reliability = floatval($request->get_param('min_reliability'));
        $sql .= $this->db->prepare(" AND reliability_score >= %f", $min_reliability);
    }
    
    // 添加排序
    $orderby = $request->get_param('orderby') ?: 'reliability_score';
    $order = $request->get_param('order') ?: 'DESC';
    $sql .= " ORDER BY $orderby $order";
    
    // 添加分页
    $sql .= $this->db->prepare(" LIMIT %d OFFSET %d", $per_page, $offset);
    
    $suppliers = $this->db->get_results($sql);
    
    // 获取总数
    $count_sql = "SELECT COUNT(*) FROM $table_name WHERE is_active = 1";
    $total = $this->db->get_var($count_sql);
    
    return rest_ensure_response(array(
        'data' => $suppliers,
        'pagination' => array(
            'page' => $page,
            'per_page' => $per_page,
            'total' => intval($total),
            'total_pages' => ceil($total / $per_page)
        )
    ));
}

/**
 * 检查库存
 */
public function check_inventory($order_id, $posted_data, $order) {
    $items = $order->get_items();
    
    foreach ($items as $item) {
        $product_id = $item->get_product_id();
        $quantity = $item->get_quantity();
        
        // 检查库存
        $inventory_table = $this->db->prefix . 'supply_chain_inventory';
        $sql = $this->db->prepare(
            "SELECT available_stock FROM $inventory_table WHERE product_id = %d",
            $product_id
        );
        
        $available_stock = $this->db->get_var($sql);
        
        if ($available_stock < $quantity) {
            // 库存不足,触发补货逻辑
            $this->trigger_reorder($product_id, $quantity - $available_stock);
            
            // 记录库存预留
            $this->reserve_stock($product_id, $available_stock);
            
            // 发送通知
            $this->send_low_stock_notification($product_id, $available_stock, $quantity);
        } else {
            // 预留库存
            $this->reserve_stock($product_id, $quantity);
        }
    }
}

/**
 * 触发补货逻辑
 */
private function trigger_reorder($product_id, $required_quantity) {
    // 获取最佳供应商
    $best_supplier = $this->get_best_supplier($product_id);
    
    if ($best_supplier) {
        // 创建采购订单
        $order_data = array(
            'supplier_id' => $best_supplier->id,
            'product_id' => $product_id,
            'quantity' => max($required_quantity * 2, 50), // 最少补货50件或需求量的2倍
            'unit_price' => $this->get_supplier_price($best_supplier->id, $product_id)
        );
        
        $this->create_purchase_order($order_data);
    }
}

/**
 * 获取最佳供应商
 */
private function get_best_supplier($product_id) {
    $suppliers_table = $this->db->prefix . 'supply_chain_suppliers';
    $inventory_table = $this->db->prefix . 'supply_chain_inventory';
    
    $sql = $this->db->prepare(
        "SELECT s.*, i.unit_price 
         FROM $suppliers_table s
         INNER JOIN $inventory_table i ON s.id = i.supplier_id
         WHERE i.product_id = %d 
         AND s.is_active = 1
         ORDER BY s.reliability_score DESC, i.unit_price ASC
         LIMIT 1",
        $product_id
    );
    
    return $this->db->get_row($sql);
}

/**
 * 供应商选择短代码
 */
public function supplier_selection_shortcode($atts) {
    $atts = shortcode_atts(array(
        'product_id' => 0,
        'show_prices' => true
    ), $atts);
    
    if (!$atts['product_id']) {
        return '<p>请指定产品ID</p>';
    }
    
    ob_start();
    ?>
    <div class="supplier-selection-widget">
        <h3>选择供应商</h3>
        <div class="supplier-options">
            <?php
            $suppliers = $this->get_product_suppliers($atts['product_id']);
            foreach ($suppliers as $supplier) {
                ?>
                <div class="supplier-option">
                    <input type="radio" 
                           name="supplier_<?php echo $atts['product_id']; ?>" 
                           value="<?php echo $supplier->id; ?>"
                           data-price="<?php echo $supplier->unit_price; ?>"
                           data-lead-time="<?php echo $supplier->lead_time_days; ?>">
                    <label>
                        <strong><?php echo esc_html($supplier->name); ?></strong>
                        <?php if ($atts['show_prices']): ?>
                            <span class="price">$<?php echo number_format($supplier->unit_price, 2); ?></span>
                        <?php endif; ?>
                        <span class="lead-time">交货期: <?php echo $supplier->lead_time_days; ?>天</span>
                        <span class="reliability">可靠度: <?php echo $supplier->reliability_score; ?>/5</span>
                    </label>
                </div>
                <?php
            }
            ?>
        </div>
    </div>
    <style>
        .supplier-selection-widget {
            border: 1px solid #ddd;
            padding: 20px;
            margin: 20px 0;
            border-radius: 5px;
        }
        .supplier-option {
            margin: 10px 0;
            padding: 10px;
            border: 1px solid #eee;
            border-radius: 3px;
        }
        .supplier-option:hover {
            background-color: #f9f9f9;
        }
        .supplier-option label {
            display: block;
            margin-left: 25px;
            cursor: pointer;
        }
        .supplier-option .price {
            color: #0073aa;
            font-weight: bold;
            margin-left: 15px;
        }
        .supplier-option .lead-time {
            color: #666;
            margin-left: 15px;
            font-size: 0.9em;
        }
        .supplier-option .reliability {
            color: #46b450;
            margin-left: 15px;
            font-size: 0.9em;
        }
    </style>
    <script>
        jQuery(document).ready(function($) {
            $('.supplier-option input').on('change', function() {
                var price = $(this).data('price');
                var leadTime = $(this).data('lead-time');
                
                // 更新产品价格和交货时间显示
                $('.product-price').text('$' + price.toFixed(2));
                $('.delivery-time').text('预计' + leadTime + '天内发货');
                
                // 发送AJAX请求更新购物车
                $.ajax({
                    url: '<?php echo rest_url('supply-chain/v1/update-cart'); ?>',
                    method: 'POST',
                    data: {
                        product_id: <?php echo $atts['product_id']; ?>,
                        supplier_id: $(this).val(),
                        price: price
                    }
                });
            });
        });
    </script>
    <?php
    return ob_get_clean();
}

/**
 * 获取产品供应商
 */
private function get_product_suppliers($product_id) {
    $suppliers_table = $this->db->prefix . 'supply_chain_suppliers';
    $inventory_table = $this->db->prefix . 'supply_chain_inventory';
    
    $sql = $this->db->prepare(
        "SELECT s.*, i.unit_price 
         FROM $suppliers_table s
         INNER JOIN $inventory_table i ON s.id = i.supplier_id
         WHERE i.product_id = %d 
         AND s.is_active = 1
         AND i.available_stock > 0
         ORDER BY s.reliability_score DESC, i.unit_price ASC",
        $product_id
    );
    
    return $this->db->get_results($sql);
}

/**
 * 渲染仪表板
 */
public function render_dashboard() {
    ?>
    <div class="wrap supply-chain-dashboard">
        <h1>供应链仪表板</h1>
        
        <div class="dashboard-stats">
            <div class="stat-card">
                <h3>活跃供应商</h3>
                <p class="stat-number"><?php echo $this->get_supplier_count(); ?></p>
            </div>
            
            <div class="stat-card">
                <h3>低库存产品</h3>
                <p class="stat-number"><?php echo $this->get_low_stock_count(); ?></p>
            </div
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5911.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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