PHP 怎么PHP进销存

wen PHP项目 3

本文目录导读:

PHP 怎么PHP进销存

  1. 数据库设计
  2. 核心PHP类实现
  3. 前端页面示例 (add_sale.php)

我来给你一个完整的PHP进销存系统实现方案,包含核心功能和代码示例。

数据库设计

-- 商品表
CREATE TABLE products (
    id INT PRIMARY KEY AUTO_INCREMENT,
    sku VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    category_id INT,
    unit VARCHAR(20),
    purchase_price DECIMAL(10,2),
    sale_price DECIMAL(10,2),
    stock_quantity INT DEFAULT 0,
    min_stock INT DEFAULT 0,
    status TINYINT DEFAULT 1,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 供应商表
CREATE TABLE suppliers (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    contact VARCHAR(50),
    phone VARCHAR(20),
    email VARCHAR(100),
    address VARCHAR(200)
);
-- 采购单表
CREATE TABLE purchase_orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    order_no VARCHAR(30) UNIQUE NOT NULL,
    supplier_id INT,
    user_id INT,
    total_amount DECIMAL(10,2),
    status TINYINT DEFAULT 1, -- 1:待入库 2:已入库 3:已取消
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (supplier_id) REFERENCES suppliers(id)
);
-- 采购单明细表
CREATE TABLE purchase_order_items (
    id INT PRIMARY KEY AUTO_INCREMENT,
    order_id INT,
    product_id INT,
    quantity INT,
    price DECIMAL(10,2),
    subtotal DECIMAL(10,2),
    FOREIGN KEY (order_id) REFERENCES purchase_orders(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);
-- 销售单表
CREATE TABLE sales_orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    order_no VARCHAR(30) UNIQUE NOT NULL,
    customer_name VARCHAR(50),
    user_id INT,
    total_amount DECIMAL(10,2),
    status TINYINT DEFAULT 1, -- 1:待发货 2:已完成 3:已取消
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 销售单明细表
CREATE TABLE sales_order_items (
    id INT PRIMARY KEY AUTO_INCREMENT,
    order_id INT,
    product_id INT,
    quantity INT,
    price DECIMAL(10,2),
    subtotal DECIMAL(10,2),
    FOREIGN KEY (order_id) REFERENCES sales_orders(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);

核心PHP类实现

数据库连接类 (Database.php)

<?php
class Database {
    private $host = "localhost";
    private $db_name = "inventory_db";
    private $username = "root";
    private $password = "";
    private $conn;
    public function getConnection() {
        $this->conn = null;
        try {
            $this->conn = new PDO(
                "mysql:host=" . $this->host . ";dbname=" . $this->db_name,
                $this->username,
                $this->password
            );
            $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch(PDOException $e) {
            echo "连接失败: " . $e->getMessage();
        }
        return $this->conn;
    }
}
?>

商品管理类 (Product.php)

<?php
class Product {
    private $conn;
    private $table_name = "products";
    public function __construct($db) {
        $this->conn = $db;
    }
    // 添加商品
    public function create($data) {
        $query = "INSERT INTO " . $this->table_name . 
                " (sku, name, category_id, unit, purchase_price, sale_price, min_stock) 
                VALUES (:sku, :name, :category_id, :unit, :purchase_price, :sale_price, :min_stock)";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":sku", $data['sku']);
        $stmt->bindParam(":name", $data['name']);
        $stmt->bindParam(":category_id", $data['category_id']);
        $stmt->bindParam(":unit", $data['unit']);
        $stmt->bindParam(":purchase_price", $data['purchase_price']);
        $stmt->bindParam(":sale_price", $data['sale_price']);
        $stmt->bindParam(":min_stock", $data['min_stock']);
        return $stmt->execute();
    }
    // 获取商品列表
    public function getProducts($page = 1, $limit = 10) {
        $offset = ($page - 1) * $limit;
        $query = "SELECT * FROM " . $this->table_name . " 
                  LIMIT :limit OFFSET :offset";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":limit", $limit, PDO::PARAM_INT);
        $stmt->bindParam(":offset", $offset, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    // 更新库存
    public function updateStock($id, $quantity, $type = 'increment') {
        if($type == 'decrement') {
            $quantity = -$quantity;
        }
        $query = "UPDATE " . $this->table_name . 
                " SET stock_quantity = stock_quantity + :quantity WHERE id = :id";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":quantity", $quantity);
        $stmt->bindParam(":id", $id);
        return $stmt->execute();
    }
    // 检查库存是否充足
    public function checkStock($id, $quantity) {
        $query = "SELECT stock_quantity FROM " . $this->table_name . 
                " WHERE id = :id AND stock_quantity >= :quantity";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(":id", $id);
        $stmt->bindParam(":quantity", $quantity);
        $stmt->execute();
        return $stmt->rowCount() > 0;
    }
}
?>

采购管理类 (Purchase.php)

<?php
class Purchase {
    private $conn;
    private $product;
    public function __construct($db) {
        $this->conn = $db;
        $this->product = new Product($db);
    }
    // 创建采购单
    public function createOrder($supplier_id, $user_id, $items) {
        $this->conn->beginTransaction();
        try {
            // 生成订单号
            $order_no = 'PO' . date('YmdHis') . rand(1000, 9999);
            $total_amount = 0;
            // 计算总金额
            foreach($items as $item) {
                $total_amount += $item['price'] * $item['quantity'];
            }
            // 插入采购单
            $query = "INSERT INTO purchase_orders 
                      (order_no, supplier_id, user_id, total_amount) 
                      VALUES (:order_no, :supplier_id, :user_id, :total_amount)";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(":order_no", $order_no);
            $stmt->bindParam(":supplier_id", $supplier_id);
            $stmt->bindParam(":user_id", $user_id);
            $stmt->bindParam(":total_amount", $total_amount);
            $stmt->execute();
            $order_id = $this->conn->lastInsertId();
            // 插入采购明细
            foreach($items as $item) {
                $query = "INSERT INTO purchase_order_items 
                          (order_id, product_id, quantity, price, subtotal) 
                          VALUES (:order_id, :product_id, :quantity, :price, :subtotal)";
                $stmt = $this->conn->prepare($query);
                $stmt->bindParam(":order_id", $order_id);
                $stmt->bindParam(":product_id", $item['product_id']);
                $stmt->bindParam(":quantity", $item['quantity']);
                $stmt->bindParam(":price", $item['price']);
                $subtotal = $item['price'] * $item['quantity'];
                $stmt->bindParam(":subtotal", $subtotal);
                $stmt->execute();
            }
            $this->conn->commit();
            return ["success" => true, "order_id" => $order_id];
        } catch(Exception $e) {
            $this->conn->rollBack();
            return ["success" => false, "error" => $e->getMessage()];
        }
    }
    // 确认入库
    public function confirmWarehouse($order_id) {
        $this->conn->beginTransaction();
        try {
            // 获取采购单明细
            $query = "SELECT * FROM purchase_order_items WHERE order_id = :order_id";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(":order_id", $order_id);
            $stmt->execute();
            $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
            // 更新商品库存
            foreach($items as $item) {
                $this->product->updateStock($item['product_id'], $item['quantity']);
            }
            // 更新采购单状态为已入库
            $query = "UPDATE purchase_orders SET status = 2 WHERE id = :id";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(":id", $order_id);
            $stmt->execute();
            $this->conn->commit();
            return ["success" => true];
        } catch(Exception $e) {
            $this->conn->rollBack();
            return ["success" => false, "error" => $e->getMessage()];
        }
    }
}
?>

销售管理类 (Sales.php)

<?php
class Sales {
    private $conn;
    private $product;
    public function __construct($db) {
        $this->conn = $db;
        $this->product = new Product($db);
    }
    // 创建销售单
    public function createOrder($customer_name, $user_id, $items) {
        $this->conn->beginTransaction();
        try {
            // 检查所有商品库存
            foreach($items as $item) {
                if(!$this->product->checkStock($item['product_id'], $item['quantity'])) {
                    throw new Exception("商品ID: " . $item['product_id'] . " 库存不足");
                }
            }
            // 生成订单号
            $order_no = 'SO' . date('YmdHis') . rand(1000, 9999);
            $total_amount = 0;
            // 计算总金额
            foreach($items as $item) {
                $total_amount += $item['price'] * $item['quantity'];
            }
            // 插入销售单
            $query = "INSERT INTO sales_orders 
                      (order_no, customer_name, user_id, total_amount) 
                      VALUES (:order_no, :customer_name, :user_id, :total_amount)";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(":order_no", $order_no);
            $stmt->bindParam(":customer_name", $customer_name);
            $stmt->bindParam(":user_id", $user_id);
            $stmt->bindParam(":total_amount", $total_amount);
            $stmt->execute();
            $order_id = $this->conn->lastInsertId();
            // 插入销售明细并更新库存
            foreach($items as $item) {
                $query = "INSERT INTO sales_order_items 
                          (order_id, product_id, quantity, price, subtotal) 
                          VALUES (:order_id, :product_id, :quantity, :price, :subtotal)";
                $stmt = $this->conn->prepare($query);
                $stmt->bindParam(":order_id", $order_id);
                $stmt->bindParam(":product_id", $item['product_id']);
                $stmt->bindParam(":quantity", $item['quantity']);
                $stmt->bindParam(":price", $item['price']);
                $subtotal = $item['price'] * $item['quantity'];
                $stmt->bindParam(":subtotal", $subtotal);
                $stmt->execute();
                // 扣减库存
                $this->product->updateStock($item['product_id'], $item['quantity'], 'decrement');
            }
            $this->conn->commit();
            return ["success" => true, "order_id" => $order_id];
        } catch(Exception $e) {
            $this->conn->rollBack();
            return ["success" => false, "error" => $e->getMessage()];
        }
    }
}
?>

前端页面示例 (add_sale.php)

<!DOCTYPE html>
<html>
<head>销售管理</title>
    <style>
        .container { max-width: 800px; margin: 20px auto; }
        .form-group { margin-bottom: 15px; }
        .form-group label { display: block; margin-bottom: 5px; }
        .form-group input, .form-group select { width: 100%; padding: 8px; }
        .btn { padding: 10px 20px; background: #007bff; color: white; border: none; cursor: pointer; }
        .btn-danger { background: #dc3545; }
        .items-table { width: 100%; border-collapse: collapse; }
        .items-table th, .items-table td { padding: 10px; border: 1px solid #ddd; text-align: left; }
    </style>
</head>
<body>
    <div class="container">
        <h2>新建销售单</h2>
        <form id="saleForm">
            <div class="form-group">
                <label>客户名称</label>
                <input type="text" name="customer_name" required>
            </div>
            <div class="form-group">
                <label>销售员ID</label>
                <input type="number" name="user_id" value="1" required>
            </div>
            <h3>商品明细</h3>
            <table class="items-table">
                <thead>
                    <tr>
                        <th>商品</th>
                        <th>数量</th>
                        <th>单价</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody id="itemsBody">
                    <tr>
                        <td>
                            <select name="items[0][product_id]" required>
                                <?php
                                // 这里需要从数据库获取商品列表
                                // 需要你根据实际情况填充
                                ?>
                                <option value="1">商品1</option>
                                <option value="2">商品2</option>
                            </select>
                        </td>
                        <td><input type="number" name="items[0][quantity]" min="1" required></td>
                        <td><input type="number" name="items[0][price]" step="0.01" required></td>
                        <td><button type="button" class="btn-danger" onclick="removeRow(this)">删除</button></td>
                    </tr>
                </tbody>
            </table>
            <br>
            <button type="button" onclick="addRow()">添加商品</button>
            <br><br>
            <button type="submit" class="btn">提交销售单</button>
        </form>
    </div>
    <script>
    // 添加商品行
    function addRow() {
        const tbody = document.getElementById('itemsBody');
        const rowCount = tbody.children.length;
        const tr = document.createElement('tr');
        tr.innerHTML = `
            <td>
                <select name="items[${rowCount}][product_id]" required>
                    <option value="1">商品1</option>
                    <option value="2">商品2</option>
                </select>
            </td>
            <td><input type="number" name="items[${rowCount}][quantity]" min="1" required></td>
            <td><input type="number" name="items[${rowCount}][price]" step="0.01" required></td>
            <td><button type="button" class="btn-danger" onclick="removeRow(this)">删除</button></td>
        `;
        tbody.appendChild(tr);
    }
    // 删除商品行
    function removeRow(btn) {
        const tbody = document.getElementById('itemsBody');
        if(tbody.children.length > 1) {
            btn.parentElement.parentElement.remove();
        } else {
            alert('至少保留一行');
        }
    }
    // 提交表单
    document.getElementById('saleForm').addEventListener('submit', function(e) {
        e.preventDefault();
        const formData = new FormData(this);
        const data = Object.fromEntries(formData);
        // 格式化items数组
        const items = [];
        for(let key in data) {
            if(key.startsWith('items[')) {
                const match = key.match(/items\[(\d+)\]\[(\w+)\]/);
                if(match) {
                    const index = match[1];
                    const field = match[2];
                    if(!items[index]) items[index] = {};
                    items[index][field] = parseFloat(data[key]);
                }
            }
        }
        const payload = {
            customer_name: data.customer_name,
            user_id: data.user_id,
            items: items.filter(item => item && Object.keys(item).length === 3)
        };
        // AJAX请求
        fetch('api/create_sale.php', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'

抱歉,评论功能暂时关闭!