本文目录导读:

我来给你一个完整的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'