拓冰建站拓冰建站
首页 / 资讯中心 / 正文

OpenMRP开源制造ERP:从MRP运算到部署上线的实践指南

最近在调研制造型企业的数字化方案时经常听到类似的困扰公司用 Excel 或者进销存软件管生产物料编码越加越多订单结构越来越复杂往往到月底才发现该买的材料没有买、该排的产没有排库存数据和生产计划完全对不上。这种时候很多团队的第一反应是“上一套 ERP 系统”。但走进 ERP 选型又会发现另一个难题商用 ERP 实施成本高、交付周期长SaaS ERP 虽然上线快但定制能力有限核心数据也不在自己手里。于是越来越多人开始关注开源 ERP 方案。本文要聊的 OpenMRP是一个在海外开发者社区被持续关注的开源制造 ERP 项目开发周期超过 4 年。这篇文章会围绕它的定位、制造业务流程、技术架构、部署方式和上线最佳实践展开帮助你判断这类开源 ERP 是否适合你的团队。1. 为什么制造业需要开源ERPOpenMRP的定位与价值1.1 从MRP到ERP先理解概念边界在讲 OpenMRP 之前有必要先把 MRP 和 ERP 这两个词理清楚。MRP 全称是Material Requirements Planning也就是物料需求计划。它解决的核心问题是现有库存够不够还差多少什么时候需要采购什么时候需要安排生产MRP 运算依赖三个核心输入BOMBill of Materials物料清单一个成品由哪些原材料/半成品组成每个组件需要多少数量。库存数据当前可用库存、在途采购、在制数量。需求数据销售订单、预测订单、安全库存策略。ERP 全称是Enterprise Resource Planning企业资源计划。它是在 MRP 之上扩展出来的企业级管理系统覆盖销售、采购、库存、生产、财务、人力资源等全链路。所以可以这样理解MRP 是制造业 ERP 的灵魂ERP 是承载 MRP 及其周边业务的骨架。一个真正面向制造的 ERP不能只做进销存必须要把“物料需求计算”这个能力做扎实。1.2 商用ERP与开源ERP的取舍国内企业接触比较多的 ERP通常有用友、金蝶、简道云 ERP、星云 ERP 这类产品。它们各有优势实施服务体系成熟、行业模板丰富、财务模块往往很强。但也要客观看待商用 ERP 的普遍问题实施成本高软件授权、实施服务、二次开发费用加起来对中小制造企业是笔不小的预算。定制响应慢制造企业的工艺路线、计件工资、质检规则差别很大标准功能往往不能完全匹配。数据自主权受限SaaS 模式下数据存储在服务商侧的平台上退出成本高。开源 ERP 的价值恰好体现在这几个方面源码开放可以按企业业务做定制没有 License 费用降低起步门槛数据自主控制适合对数据安全要求高的制造企业。OpenMRP 就是这样一个面向制造场景的开源 ERP 系统。它最大的标签不是“免费的 ERP”而是“长期维护的开源制造 ERP”。1.3 OpenMRP项目的核心定位从项目标题可以看出OpenMRP 已经经历超过 4 年的持续开发。这个时间长度在开源项目里其实很能说明问题。企业级软件和开源工具不同它需要覆盖真实业务场景经过大量需求打磨。很多开源项目活跃一两年就停止维护了而一个制造 ERP 能持续迭代 4 年意味着它背后已经有明确的维护节奏和真实用户反馈。OpenMRP 的定位可以归纳为三点面向制造业核心能力围绕 BOM、物料需求计算、工单、采购、库存展开而不是做一个通用进销存。开源可定制企业可以基于源码进行二次开发扩展工序、计件、质检等特殊业务。长周期演进4 年积累迭代出来的是相对完整的模块体系和数据结构不是教学 Demo。2. 制造ERP的核心业务流程与功能模块2.1 制造企业ERP的标准流程环要判断一个开源 ERP 是否适合生产制造场景先要看它能不能跑通制造企业最核心的业务闭环销售订单 → 主生产计划 → MRP运算 → 生产工单 采购计划 ↑ ↓ 财务核算 ← 成品发货 ← 完工入库 ← 车间领料/报工 ← 采购到货这个循环里每一步都会产生数据联动销售订单录入后系统要能锁定商品库存。库存不足时MRP 运算要能自动拆出“生产建议”和“采购建议”。生产建议转成生产工单后按 BOM 展开生成“用料计划”。车间领料时系统扣减原材料库存报工完工后系统增加成品库存。采购到货、质检合格后原材料库存得到补充。发货后触发应收采购入库后触发应付成本数据归集到财务模块。如果一套 ERP 只能管理“进出存”不能自动计算“缺什么、什么时候缺、需要买多少、需要做多少”那它本质上还是进销存不是面向制造的 ERP。2.2 OpenMRP的核心模块清单围绕上面这个业务闭环一个成熟的制造 ERP 至少需要以下模块模块核心功能物料管理料号编码、品名规格、分类、多计量单位、批次/序列号产品数据BOM 维护、BOM 版本管理、工艺路线销售管理报价单、销售订单、发货、应收采购管理采购申请、采购订单、到货、质检、应付库存管理出入库、盘点、调拨、库存锁定、库存台账生产管理工单、派工、领料、报工、完工入库财务管理成本核算、应收应付、凭证报表看板库存周转、订单履约、生产进度、采购到货对于 OpenMRP 这类开源制造 ERP最值得关注的仍然是生产域和物料域是否完善。因为销售、采购、库存这些通用能力开源界和商用软件都有较成熟方案但真正贴合车间作业场景的 MRP 运算和工单管理才是最考验项目功力的地方。2.3 与传统进销存系统的区别很多中小制造企业早期用的是进销存管理软件它能记录“材料入库、成品出库、库存查询”但回答不了这三个计划类的问题这个订单需要什么时候开始生产按照现有库存我还缺多少原材料如果供应商交期是 7 天我应该在什么时间下达采购订单进销存软件没有 BOM 展开能力和需求计算能力这些问题只能靠人工在 Excel 里算。OpenMRP 这类制造 ERP 的价值就是把“人工算料”变成“系统自动算料”这也是 ERP 与进销存最本质的差别。3. 技术架构与项目演进视角3.1 常见的开源ERP技术栈由于 OpenMRP 的具体技术栈需要以官方仓库的 README 为准这里从开源 ERP 的技术选型共性出发梳理一套典型的开源制造 ERP 技术架构。一个适合制造企业的开源 ERP 通常采用前后端分离架构后端常见选择是 Java/Spring Boot、Python/Django、Node.js/NestJS。Spring Boot 在企业级应用中更常见因为生态成熟、事务管理完善Python/Django 的优势是开发效率高适合快速迭代。前端B 端管理后台常用的有 Vue 3 Element Plus、React Ant Design。国内团队对 Vue 生态更熟悉上手成本低。数据库PostgreSQL 或 MySQL。制造业 ERP 涉及大量关联查询和复杂事务PostgreSQL 在复杂 SQL 和 JSON 扩展上更有优势。缓存与任务队列Redis 用于缓存和分布式锁Celery 或 RabbitMQ 用于异步任务比如批量 MRP 运算、报表导出、消息通知。部署Docker Compose 适合中小团队单机/小集群部署Kubernetes 适合更大规模场景。下面是这类开源 ERP 常见的目录结构openmrp/ ├── backend/ │ ├── apps/ │ │ ├── mrp/ │ │ ├── sales/ │ │ ├── purchase/ │ │ ├── inventory/ │ │ ├── production/ │ │ └── finance/ │ └── core/ ├── frontend/ │ ├── src/ │ │ ├── views/ │ │ ├── components/ │ │ └── api/ ├── docs/ └── docker-compose.yml模块按业务域拆分而不是把所有功能塞在单一大目录里这是企业级系统与个人项目的重要区别。3.2 为什么“4年”对开源ERP很重要很多人看到 4 年开发周期第一反应是“这项目是不是太慢了”。但站在企业级软件的角度4 年恰恰是一个加分项数据库结构经得起真实业务推敲。第一版数据结构在落地后往往需要调整持续迭代意味着表结构、字段设计已经经过多轮重构比全新系统稳定。权限模型和审批流经过了打磨。权限和审批是 ERP 上线时的隐形门槛这类设计很难一次性做对需要在不同企业场景里不断磨合。模块度更高。项目从单模块扩展到多模块之后自然会产生“核心基础数据、业务交易数据、报表数据”的层级划分二次开发更容易定位落点。社区和文档积累更多。开源软件最怕“网上连个解决方案都搜不到”4 年项目通常积累了较完整的部署文档、常见问题记录和社区讨论。3.3 模块化与可扩展性设计对于打算引入 OpenMRP 的团队要在选型阶段重点看三个可扩展性设计第一基础数据和交易数据是否分离。物料、BOM、客户、供应商这些是基础数据销售订单、采购订单、工单属于交易数据。两类数据如果混在一个表里后续报表和审计会非常痛苦。第二是否预留接口层。现代制造企业周边通常有 MES、WMS、电子发票平台ERP 需要与这些系统对接。有没有 REST API 或消息队列事件直接决定后续集成的成本。第三二次开发是否安全。最怕的是为了改一个需求直接改动核心表。优秀的开源项目会鼓励通过扩展模块或 API 层实现定制保持核心代码稳定。4. 本地部署实战从源码到可运行系统这一节演示的是开源 ERP 最常见的部署模式后端应用 前端应用 PostgreSQL Redis。OpenMRP 的具体命令请以官方文档为准下面重点讲清楚部署思路与关键验证点。4.1 环境准备在开始部署之前需要准备好以下基础环境Linux 服务器或本地开发机推荐 Ubuntu 22.04Docker 与 Docker ComposeGit浏览器用于访问前端页面如果你需要本地二次开发环境还需要安装对应技术栈的运行时例如# 示例如果后端基于 Python需要 Python 3.10 python3 --version # 如果后端基于 Node.js需要 Node 18 node -v # 如果后端基于 Java需要 JDK 17 java -version版本需要根据你实际拉取的项目代码调整以仓库 README 为准。4.2 获取项目源码通过 Git 克隆项目到本地目录git clone 你的OpenMRP仓库地址 cd openmrp如果你只是体验功能不需要二次开发推荐直接使用 Docker Compose 启动整套环境。4.3 初始化数据库企业级 ERP 首次启动时需要创建数据库、执行迁移脚本、初始化基础数据。PostgreSQL 创建数据库的通用命令CREATE DATABASE openmrp; CREATE USER openmrp WITH PASSWORD your_strong_password; ALTER ROLE openmrp SET client_encoding TO utf8; ALTER ROLE openmrp SET default_transaction_isolation TO read committed; GRANT ALL PRIVILEGES ON DATABASE openmrp TO openmrp;执行数据库迁移的通用命令模式如下# Python/Django 项目 python manage.py migrate # Node.js 项目 npm run db:migrate # Java/Spring Boot 项目 ./mvnw flyway:migrate迁移的含义是把项目中的数据结构定义同步到数据库比如创建表、字段、索引。4.4 使用 Docker Compose 启动应用如果你的项目提供了 docker-compose.yml可以通过以下命令启动docker compose up -d一个典型的 ERP 环境编排文件结构如下version: 3.8 services: postgres: image: postgres:16-alpine container_name: openmrp-postgres environment: POSTGRES_DB: openmrp POSTGRES_USER: openmrp POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - pgdata:/var/lib/postgresql/data ports: - 5432:5432 healthcheck: test: [CMD-SHELL, pg_isready -U openmrp] interval: 5s timeout: 5s retries: 5 redis: image: redis:7-alpine container_name: openmrp-redis ports: - 6379:6379 openmrp: build: . container_name: openmrp-app depends_on: postgres: condition: service_healthy redis: condition: service_started environment: DATABASE_URL: postgres://openmrp:${DB_PASSWORD}postgres:5432/openmrp REDIS_URL: redis://redis:6379/0 APP_PORT: 8080 ports: - 8080:8080 volumes: - ./data:/app/data volumes: pgdata:.env 环境变量文件示例DB_PASSWORDchange_me_before_production启动之后用以下命令查看容器状态docker compose ps如果所有服务都处于 healthy/running 状态说明应用已经正常启动。4.5 浏览器验证打开浏览器访问http://localhost:8080通常会出现登录页面或者初始化设置页面。首次登录后系统会引导你创建管理员账号、设置公司基本信息这是企业级系统第一次初始化时最常见的流程。部署验证清单[ ] 数据库容器是否健康运行[ ] Redis 是否可连接[ ] 后端应用日志是否报错[ ] 前端页面是否可以正常加载[ ] 能否完成管理员账号创建[ ] 能否进入主界面5. 初始配置与基础数据准备很多 ERP 项目上线失败根源不在软件本身而是基础数据没准备好。制造企业在正式使用 OpenMRP 前需要先把以下基础数据整理好。5.1 公司参数设置开始录入业务数据之前先配置公司层面的信息公司名称、地址、税号本位币人民币或美元会计期间自然月或自定义期间默认税率库存计价方式移动平均、先进先出、标准成本这些参数会影响后续所有业务单据的金额计算建议由财务负责人参与确认。5.2 物料主数据与单位管理物料主数据是制造业 ERP 的基石。一个物料至少需要以下属性料号唯一编码建议使用有规律的编码规则例如“原材料-R-001”品名规格完整描述物料物料分类原材料、半成品、成品、辅料计量单位件、个、千克、米默认仓库采购属性默认供应商、采购提前期生产属性默认工序、是否自制如果需要批量导入通常支持 CSV 格式字段结构可以参考item_code,item_name,specification,category,unit,default_warehouse,is_purchased,is_manufactured R-001,Q235钢板,2mm*1250*2500,原材料,张,原材料仓库,true,false FG-001,设备支架,Q235焊接件,半成品,件,半成品仓,false,true导入前一定要做数据清洗检查料号是否重复检查单位是否统一检查同一种物料是否被录成多个不同名称5.3 BOM结构的建立BOM 是 MRP 运算的核心依据。一个简单的 BOM 示例成品“设备支架总成”由以下组件构成1 件 设备支架自制件2 个 M8 螺栓外购件1 个 垫片外购件0.5 千克 焊丝辅助材料在系统中需要把子件和用量逐一录入并且指定“发料方式”和“损耗率”。BOM 维护最常见的问题是版本管理。例如旧版本 BOM 用 2 个螺栓新版本改成 4 个螺栓那么已经下达的旧生产工单继续按旧 BOM 领料。新下达的工单按新 BOM 领料。系统里要能保留历史 BOM 版本不能直接覆盖。5.4 库存期初录入系统正式启用之前需要把当前仓库里的实际库存录入系统作为期初数据。常见做法是仓库盘点获取实盘数量。整理成 Excel 导入模板。系统导入后做一次“期初库存盘点单”过账。财务同步确认期初库存金额。期初数据如果不准确后续所有 MRP 运算都会失真所以在正式业务开始前务必确保库存准确率接近 100%。5.5 用户与权限设置制造 ERP 涉及生产、采购、销售、财务多个部门必须做好权限隔离。建议按照“最小权限原则”设计角色角色核心权限系统管理员系统配置、用户管理、基础数据销售专员销售订单、发货单、客户管理计划员MRP运算、生产工单、采购申请采购专员采购订单、采购到货、供应商管理仓库管理员出入库、盘点、库存查询车间主任工单执行、领料、报工、完工入库财务人员应收应付、成本核算、凭证厂长/总经理全部报表查询不开放业务单据修改权限6. 制造业务闭环示例从订单到发货这一节演示一个典型的制造业务闭环帮助你理解 OpenMRP 这类系统在真实场景中的工作方式。6.1 销售订单创建客户下达订单购买 100 台设备支架总成交付日期为 15 天后。系统操作路径选择客户。录入产品“设备支架总成”数量 100单价 500 元。确认交期。系统自动检查可用库存当前成品库存 30 台可用 30 台缺口 70 台。订单提交后系统给出提示“库存不足请安排生产计划”。在这个过程中系统已经将“可用库存锁定”了可发货的 30 台部分避免被其他订单重复占用。6.2 MRP运算与计划建议计划员运行 MRP 运算模块系统按以下逻辑展开计算判断净需求需求 100 - 可用库存 30 - 在制数量 0 净需求 70。展开 BOM70 台成品需要 70 件 设备支架 140 个 螺栓 70 个 垫片 35 千克 焊丝。判断每个组件的现有库存情况。生成计划建议生产工单70 台 设备支架总成。采购建议根据材料库存缺口生成螺栓、垫片、焊丝的采购计划。下面给出一个简化版 MRP 净需求计算 SQL 示例帮助理解核心运算逻辑。注意这仅用于理解 MRP 思路不是 OpenMRP 的实际查询代码。-- 简化版净需求计算逻辑 SELECT bom.parent_item_id, bom.component_item_id, bom.quantity_per_unit, COALESCE(SUM(inventory.on_hand_qty), 0) AS available_qty, demand.demand_qty, (demand.demand_qty * bom.quantity_per_unit - COALESCE(SUM(inventory.on_hand_qty), 0)) AS net_requirement FROM bom LEFT JOIN inventory ON inventory.item_id bom.component_item_id LEFT JOIN ( SELECT item_id, SUM(quantity) AS demand_qty FROM sales_order_line WHERE status confirmed GROUP BY item_id ) demand ON demand.item_id bom.parent_item_id GROUP BY bom.parent_item_id, bom.component_item_id, bom.quantity_per_unit, demand.demand_qty;真实系统中的 MRP 还要考虑在途采购、安全库存、批量规则、提前期、供应商交期等因素比上面这个简化 SQL 复杂得多但基本逻辑是一致的需求 × 用量 - 可用库存 净需求。6.3 生产工单下达与领料计划员审核生产建议后将建议转成生产工单工单编号MO-2025-001产品设备支架总成数量70 台计划开工日期明天计划完工日期第 10 天工单下达后车间按工单领料领 70 件 设备支架领 140 个 螺栓领 70 个 垫片领 35 千克 焊丝系统扣减原材料库存并生成“在制量”在制品数量会参与后续 MRP 计算避免重复采购。6.4 车间报工与完工入库车间每天报工登记每个工序的完成数量、工时、不良数量。例如工序 1切割/焊接完成 70 台用时 8 小时工序 2组装完成 70 台用时 6 小时工序 3检验合格 70 台不良 0全部工序完成后执行“完工入库”系统增加 70 台成品库存。此时成品库存变为 30 70 100 台可以满足客户订单。6.5 发货与财务核算仓库根据销售订单做发货发货数量100 台发货后成品库存清零系统生成发货单财务确认应收 50000 元采购模块完成材料入库后财务确认应付。生产成本归集后可以查看这批订单的实际毛利销售额100 × 500 50000 元 材料成本xx 元 人工成本xx 元 制造费用xx 元 毛利xx 元一个完整的“接单 - 计划 - 采购 - 生产 - 发货 - 核算”闭环就是制造 ERP 每天的核心工作。7. 常见问题与排查思路无论选择 OpenMRP 还是其他开源 ERP在上线和日常使用中都会遇到下面这些问题。7.1 部署阶段常见问题问题现象常见原因解决思路数据库连接失败连接地址或密码配置错误检查 DATABASE_URL使用 psql 单独测试连接端口占用8080 或 5432 已被其他程序占用换端口或停止占用进程页面能打开但接口 500数据库迁移未执行重新执行 migrate 命令登录后权限异常首次登录后未正确初始化管理员角色进入系统设置检查管理员权限Redis 连接超时Redis 服务未启动或地址错误检查容器状态确认 REDIS_URL排查数据库连接问题可以先在宿主机上执行psql postgres://openmrp:密码localhost:5432/openmrp -c SELECT 1;如果这个命令能返回1说明数据库连接没问题问题大概率出在应用配置上。7.2 业务数据阶段常见问题问题现象常见原因解决思路MRP算出的采购数量偏大BOM用量错误或库存数据不准检查BOM子件用量重做库存盘点库存出现负数发货/领料时未审核销售或工单库存被重复扣减检查单据审核状态做库存调整单料号重复导入模板没有做唯一性校验导入前用Excel去重数据库增加唯一索引单位换算错误同一物料存在多个单位但未配置换算率在物料主数据中维护单位换算关系库存数据不准确是制造业 ERP 最常见的问题。建议每周做循环盘点重点核对高价值物料和动态频繁的物料。不要等到月末才发现问题那时查找原因的工作量会非常大。7.3 运维阶段常见问题问题现象常见原因解决思路备份恢复失败备份文件不完整或版本不匹配定期做恢复演练备份要区分数据文件与代码版本系统响应变慢报表查询未走索引或者数据量增长后未优化使用慢查询日志定位SQL补充索引升级后功能异常跳过版本升级或未执行增量迁移脚本严格按版本顺序升级升级前备份外系统对接失败API 接口变更或网络策略隔离检查接口文档确认网络白名单开源 ERP 系统上线后运维一定要做到两件事每日备份每周恢复演练。升级前先看 upgrade 文档不要跳版本。8. 开源ERP的上线建议与最佳实践8.1 先梳理业务流程再考虑系统功能很多企业犯的错误是软件还没选先要求系统按现有习惯来。实际上更合理的顺序是画出企业现在的业务流程图现状。标出哪些环节是卡点、哪些数据是靠人工传递的。设计“系统化之后”的目标流程未来。再拿目标流程与 ERP 功能做匹配。制造业还有一个现实问题不同部门的编码习惯完全不一样。仓库叫“钢板”采购叫“Q235板材”财务叫“原材料”。如果不统一物料编码和命名规则系统上线第一天就会数据混乱。8.2 数据治理是上线成功的关键制造 ERP 的数据治理要重点盯三块物料主数据。建议由专人负责制定编码规则审核新物料创建。料号一旦使用不轻易删除通过“禁用”控制。BOM 准确率。BOM 不准MRP 算出来的所有计划都不可信。建议新 BOM 在下发生产前由工艺部门做一次“试算确认”。库存准确率。期初盘点要细致日常出库要及时录入定期做循环盘点。8.3 权限、审批与操作日志开源 ERP 开放性强更要注意权限边界。每个账号只配置完成岗位工作所需的最少权限。敏感操作修改单价、删除单据、作废工单必须走审批流程。开启操作日志记录谁在什么时间改了哪个单据、改了什么字段。在 SQL 层面还可以补充行级权限。也就是说仓库主管只能看到自己仓库的库存数据销售经理只能看到自己团队的客户和订单。这类数据隔离在制造企业中非常重要。8.4 备份、升级与安全生产环境一定要重视以下事项事项推荐做法数据库备份每日自动全量备份异地保存一份恢复演练每月至少执行一次真实恢复演练服务器安全不开放数据库端口到公网使用防火墙白名单密码策略强制强密码禁止共用超级管理员账号代码版本生产环境部署锁版本不随便拉最新代码升级前至少要在测试环境完整跑一遍尤其是数据库迁移脚本。不要在数据未备份时直接在生产环境升级。8.5 二次开发的取舍开源 ERP 最大的价值在于可二次开发但也要谨慎取舍。推荐通过扩展方式开发新增独立的扩展模块不修改核心表。通过 API 与外部系统对接。前端组件化新功能优先做成独立页面。不推荐直接修改核心代码直接修改核心业务表结构升级时容易冲突。在核心代码里写死企业特有逻辑导致后续项目无法共用。制造业企业的差异点通常集中在工序管理、计件工资、质检规则、条码管理。这些功能应在二次开发模块里实现而不是改乱核心流程。9. 总结与选型建议OpenMRP 这类开源制造 ERP真正适合的场景是企业有内部研发团队愿意投入时间做定制化适配同时希望掌握核心数据和系统源码。它在制造业务建模、物料需求计划、BOM 管理、工单管理上的价值远比通用进销存软件更适合制造企业。选型时建议按以下步骤走第一步先看业务流程闭环。把手头的成品订单、BOM、原材料库存、供应商资料整理成一套测试数据在系统里走一遍从销售订单到发货的完整流程看系统是否顺畅。第二步看二次开发成本。尝试通过 API 对接一个简单的第三方系统评估接口文档质量和开发体验。第三步参考社区活跃度。看最近一年的提交记录、Issue 回复速度、文档更新频率。开源项目最怕的不是功能少而是维护停滞。第四步评估团队能力和实施节奏。没有专职 IT 的团队直接上开源 ERP 风险较大建议先咨询有实施经验的顾问团队或者先在测试环境跑两到三个月再决定是否全面上线。制造业数字化转型并不一定等于购买昂贵的商用 ERP。把业务流程想清楚把数据基础打扎实选择一个像 OpenMRP 这样可掌控、可持续迭代的开源方案同样可以走出一条适合自己企业的落地路径。如果你所在的公司正处于“进销存不够用、商用 ERP 又太贵”的阶段不妨先下载一份 OpenMRP 源码在本地跑通流程用真实业务数据验证它的能力边界。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门