如何用PHP项目实现采购计划?

wen java案例 12

本文目录导读:

如何用PHP项目实现采购计划?

  1. 核心功能与业务流程
  2. 数据库设计 (MySQL)
  3. PHP 后端核心代码示例 (面向过程 / Laravel风格思路)
  4. 前端界面 (HTML + JavaScript/jQuery)
  5. 注意事项与进阶优化

使用PHP实现采购计划(采购申请与审批)通常需要一个完整的Web应用,包含数据库、后端逻辑和前端界面。

下面是一个从零开始的标准化实现方案,涵盖了需求分析、数据库设计、核心代码示例和业务流程,你可以根据这个框架来构建自己的项目。

核心功能与业务流程

一个简单的采购计划系统通常包含以下流程:

  1. 需求发起:各部门提交采购申请单。
  2. 审批流转:部门主管 -> 财务 -> 总经理(或多级审批)。
  3. 计划汇总:审批通过的申请汇总成“采购计划”。
  4. 采购执行:计划单转为采购订单(可选,本方案聚焦于计划生成)。

数据库设计 (MySQL)

这是最关键的部分,至少需要三张核心表。

采购申请表 (purchase_requests)

CREATE TABLE `purchase_requests` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `pr_number` varchar(50) NOT NULL COMMENT '申请单号,如 PR-20231027-001',
  `applicant_id` int(11) NOT NULL COMMENT '申请人(关联用户表)',
  `department_id` int(11) DEFAULT NULL COMMENT '部门ID', varchar(200) NOT NULL COMMENT '采购事由/标题',
  `total_amount` decimal(12,2) DEFAULT '0.00' COMMENT '预估总金额',
  `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态: 0-草稿, 1-待主管审批, 2-待财务审批, 3-已批准, 4-已拒绝',
  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
  `updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `pr_number` (`pr_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

申请明细表 (purchase_request_items)

CREATE TABLE `purchase_request_items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `request_id` int(11) NOT NULL COMMENT '关联申请单ID',
  `material_name` varchar(100) NOT NULL COMMENT '物料/服务名称',
  `specification` varchar(255) DEFAULT NULL COMMENT '规格型号',
  `quantity` int(11) NOT NULL COMMENT '数量',
  `unit` varchar(20) DEFAULT NULL COMMENT '单位',
  `estimated_price` decimal(10,2) DEFAULT NULL COMMENT '预估单价',
  `remark` text COMMENT '备注/用途说明',
  PRIMARY KEY (`id`),
  KEY `request_id` (`request_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

审批记录表 (approval_logs)

CREATE TABLE `approval_logs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `request_id` int(11) NOT NULL COMMENT '申请单ID',
  `approver_id` int(11) NOT NULL COMMENT '审批人ID',
  `action` enum('approve','reject','return') NOT NULL COMMENT '动作',
  `comment` text COMMENT '审批意见',
  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

提示:如果系统复杂,建议将“状态”独立成一张 workflow_steps(工作流步骤)表,方便配置多级审批。

PHP 后端核心代码示例 (面向过程 / Laravel风格思路)

假设你使用 原生PHPThinkPHP/Laravel 框架。

创建采购申请 (Controller - create 方法)

// 接收 POST 数据
$title = $_POST['title'];
$items = $_POST['items']; // 这是一个数组,包含多个物料的 json
// 1. 生成唯一的申请单号
$pr_number = 'PR-' . date('Ymd') . '-' . str_pad($this->getNextSequence(), 4, '0', STR_PAD_LEFT);
// 2. 开启事务
$this->db->beginTransaction();
try {
    // 3. 插入主表
    $sql = "INSERT INTO purchase_requests (pr_number, applicant_id, title, total_amount, status) VALUES (?, ?, ?, ?, 0)";
    $this->db->execute($sql, [$pr_number, $_SESSION['user_id'], $title, 0]);
    $request_id = $this->db->lastInsertId();
    $total = 0;
    // 4. 循环插入明细表
    foreach ($items as $item) {
        $sql = "INSERT INTO purchase_request_items (request_id, material_name, specification, quantity, unit, estimated_price) VALUES (?, ?, ?, ?, ?, ?)";
        $this->db->execute($sql, [$request_id, $item['name'], $item['spec'], $item['qty'], $item['unit'], $item['price']]);
        $total += $item['qty'] * $item['price'];
    }
    // 5. 更新主表的预估总金额
    $sql = "UPDATE purchase_requests SET total_amount = ? WHERE id = ?";
    $this->db->execute($sql, [$total, $request_id]);
    $this->db->commit();
    echo json_encode(['success' => true, 'message' => '采购申请已提交']);
} catch (Exception $e) {
    $this->db->rollback();
    echo json_encode(['success' => false, 'message' => '提交失败: ' . $e->getMessage()]);
}

审核操作 (Controller - approve 方法)

public function approve($request_id) {
    $action = $_POST['action']; // 'approve' 或 'reject'
    $comment = $_POST['comment'];
    $current_user_id = $_SESSION['user_id'];
    $current_role = $this->getUserRole($current_user_id);
    // 1. 获取当前申请单状态
    $request = $this->db->fetch("SELECT * FROM purchase_requests WHERE id = ?", [$request_id]);
    // 2. 权限校验(只有主管才能批准待主管审批的状态)
    if ($current_role == 'manager' && $request['status'] == 1) {
        $new_status = ($action == 'approve') ? 2 : 4; // 转到财务审批 或 拒绝
    } elseif ($current_role == 'finance' && $request['status'] == 2) {
        $new_status = ($action == 'approve') ? 3 : 4; // 最终批准 或 拒绝
    } else {
        die('权限不足或状态异常');
    }
    // 3. 更新申请单状态
    $sql = "UPDATE purchase_requests SET status = ? WHERE id = ?";
    $this->db->execute($sql, [$new_status, $request_id]);
    // 4. 记录审批日志
    $sql = "INSERT INTO approval_logs (request_id, approver_id, action, comment) VALUES (?, ?, ?, ?)";
    $this->db->execute($sql, [$request_id, $current_user_id, $action, $comment]);
    // 5. 如果最终批准,可以自动生成“采购计划单” (可选)
    if ($new_status == 3) {
        $this->generatePurchasePlan($request_id);
    }
    echo json_encode(['success' => true]);
}

前端界面 (HTML + JavaScript/jQuery)

采购申请表单

<form id="purchaseForm">
    <div>
        <label>采购事由:</label>
        <input type="text" name="title" required>
    </div>
    <div id="itemsContainer">
        <div class="item-row">
            <input type="text" name="items[0][name]" placeholder="物料名称" required>
            <input type="text" name="items[0][spec]" placeholder="规格">
            <input type="number" name="items[0][qty]" placeholder="数量" required>
            <input type="text" name="items[0][unit]" placeholder="单位" value="个">
            <input type="number" step="0.01" name="items[0][price]" placeholder="预估单价" required>
        </div>
    </div>
    <button type="button" onclick="addItem()">添加物料</button>
    <button type="submit">提交申请</button>
</form>

审批列表界面

<table>
    <thead>
        <tr>
            <th>单号</th>
            <th>申请人</th>
            <th>总金额</th>
            <th>状态</th>
            <th>操作</th>
        </tr>
    </thead>
    <tbody>
        <?php foreach ($requests as $req): ?>
        <tr>
            <td><?= $req['pr_number'] ?></td>
            <td><?= $req['applicant_name'] ?></td>
            <td><?= $req['total_amount'] ?></td>
            <td>
                <?php
                    $status_map = [0 => '草稿', 1 => '待主管审批', 2 => '待财务审批', 3 => '已批准', 4 => '已拒绝'];
                    echo $status_map[$req['status']];
                ?>
            </td>
            <td>
                <!-- 审批按钮,通常通过 session 判断当前用户角色来控制显示 -->
                <button onclick="approve(<?= $req['id'] ?>, 'approve')">通过</button>
                <button onclick="approve(<?= $req['id'] ?>, 'reject')">拒绝</button>
            </td>
        </tr>
        <?php endforeach; ?>
    </tbody>
</table>

注意事项与进阶优化

  1. 安全性

    • 所有SQL操作必须使用预处理语句(PDO或MySQLi prepared statements)防止SQL注入。
    • 权限管理:在每一个controller方法开头检查用户角色(如if($_SESSION['role'] != 'manager') die('无权限');)。
  2. 工作流复杂性

    • 上述代码是硬编码的审批流程,如果公司需要灵活的审批流(如超过3000元需总经理审批),你需要设计一个工作流引擎表
      • workflow_rules 表:存储条件(金额范围)、当前角色、下一步角色。
      • 审批时通过动态查询该表来决定$new_status
  3. 状态机模式

    • 强烈建议使用状态机来管理 status 字段的变化,而不是用 if...else,可以编写一个 StateMachine 类,定义每个状态允许的转换,避免逻辑混乱。
  4. 框架选择

    • Laravel:内置了 Gate(权限)、Event(记录日志)、Model(ORM事务),非常适合此类业务系统。
    • ThinkPHP 6+:国内常用,快速开发。
  5. 效率

    • 当数据量较大时(如10万条申请),需要对 purchase_requests 表根据 statuscreated_at 建立复合索引

一个可以直接运行的采购计划系统,核心思路是:

  1. 数据流:表单提交 -> 数据库事务写入(主表+明细表) -> 审批后更新状态 -> 生成计划。
  2. 代码基础安全(防SQL注入) + 事务 + 状态控制
  3. 关键文件控制器(CRUD逻辑) + 模型(数据库操作) + 视图(表单与列表)

你可以先按照这个结构搭建一个最小可行产品(MVP),然后逐步增加:邮件通知、导出Excel、与仓库系统对接等功能。

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