如果只用 AI 聊天工具生成一段 Python 代码,你已经能做到;真正难的是让代码成为一个能维护、能跑接口、能批量处理数据的库存系统。这篇文章把 WorkBuddy 和 Python 放在同一条工作流里,演示一个相对完整的落地路径:从一句话业务需求,到 SQLite 数据表,再到商品入库、出库、库存流水、低库存预警和 FastAPI 接口。
WorkBuddy 这类智能工作台工具,价值点不是替代你写代码,而是把“我想做库存管理系统”这句话先拆成模块、字段、动作和验收点,再由人确认后生成对应代码。Python 则承担最终运行环境。两者结合后,你可以上午把需求说清楚,下午就拿到一个能启动、能调接口、能导 Excel 的本地系统原型。
文章后面会给出提示词模板、数据模型、库存业务代码、FastAPI 接口示例、Excel 批量任务和常见问题排查清单。适合刚入门 Python、或者想把公司内部的零散表格整理成一个小系统的开发者和业务同学。整个系统属于轻量本地版,不是高并发生产方案,但它足够作为第一个可运行版本。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 项目类型 | AI 工作台辅助设计 + Python 本地业务系统 |
| 功能范围 | 商品档案、入库、出库、盘点调整、库存流水、低库存预警 |
| 数据存储 | SQLite 起步,后续可迁移 PostgreSQL / MySQL |
| 接口能力 | FastAPI 提供 REST API,支持 curl / Python 调用 |
| 批量任务 | Excel 商品导入、低库存报表导出 |
| 运行平台 | Windows / macOS / Linux,需要本机 Python 环境 |
| 启动方式 | uvicorn 启动服务,浏览器访问接口文档 |
| 适合场景 | 个人项目、小团队内部工具、进销存系统原型 |
| 不适合场景 | 高并发电商、复杂多仓、需要精细权限控制的正式生产系统 |
| 合规注意 | 不要上传真实客户信息给 AI 工具,上线前必须人工审查代码 |
从表格能看出,这个组合解决的是“从需求到可用系统”的效率问题,而不是“零代码无脑生成一切”。WorkBuddy 在这里做需求结构化与代码生成辅助,Python 负责业务落地。
2. WorkBuddy 在库存系统中的角色
很多刚接触 WorkBuddy 的人,会把它理解成一个聊天框。你在里面问“帮我写个库存管理系统”,它可能会给你一段扁平代码;这段代码放在真实项目里往往不能直接用。更合理的做法,是把 WorkBuddy 当成一个“需求拆解 + 代码草稿 + 流程编排”的辅助层。
从公开信息和常见版本形态看,WorkBuddy 更像偏办公场景的智能工作台,带有对话式任务拆解、技能扩展、业务流程编排等能力。不同版本对功能入口的叫法可能不一样,有的叫“技能”,有的叫“工作流”,有的叫“助手”。本文不绑定某个具体版本的操作按钮,只描述通用落地路径。
实际使用中,你可以让 WorkBuddy 先做三件事:
- 把一句话业务需求展开成模块列表和字段清单。
- 按清单逐段生成 Python 代码,而不是一次性输出超大文件。
- 说明数据表之间怎么关联、接口怎么设计、批量任务怎么跑。
这三件事做完后,你得到的是“可执行的工程文档和代码片段”,而不是一个不可控的黑盒。库存系统涉及金额、数量、负库存等问题,如果让 AI 跳过人工审查直接生成生产代码,风险很高。
WorkBuddy 不是大模型私有化部署工具,所以不需要考虑显卡、显存之类的问题。它更多的价值在于帮你把流程可视化、可复用。真正承担库存数据读写和接口服务的,是本地 Python 程序。
3. 需求拆解:一句话如何变成系统模块
“做一个商品库存管理系统”这句话太模糊。如果直接把这句话丢给 WorkBuddy,它给出的表结构大概率不完整。正确做法是先给一个更完整的提示词:
请帮我设计一个商品库存管理系统。 业务要求: 1. 维护商品档案,包括商品编码、名称、分类、单价、最低库存。 2. 支持入库、出库、盘点调整三种库存变动。 3. 每次变动都要记录流水,能查到变动前数量、变动后数量、关联单号和备注。 4. 库存数量不能为负数。 5. 查询商品列表时能显示当前库存,并能筛选低库存商品。 6. 数据先用 SQLite 保存,用 FastAPI 提供接口。 7. 另写一个批量脚本,可以从 Excel 导入商品,也能导出低库存报表。 请先输出表结构设计,再按模块输出 Python 代码。提示词里的每一条,其实对应最终系统里的一个模块。
商品档案是主数据,要解决“这个商品存不存在”的问题。商品编码应该唯一,后续所有入库、出库操作都通过编码定位商品。
入库和出库是库存变动的基本动作。入库增加库存,出库减少库存;出库前必须校验当前库存是否足够。盘点调整则用于修正账面库存和实物库存的差异,可以理解为直接把库存设置为盘点后的实际数量。
库存流水是审计线索。没有流水,你只能看到最终库存,查不到为什么变成这个数。最基础的流水至少包含变动类型、变动数量、变动前数量、变动后数量、关联单号和时间。
低库存预警是给业务看的。当你定义了最低库存字段后,只要当前库存小于等于最低库存,系统就应该提醒补货。
把需求拆到这里,再让 WorkBuddy 生成代码,准确率会高很多。这也是“一句话设计”的真正含义:不是只给一句话,而是用一句话把需求主线说明白,再让它展开子任务。
4. 环境准备与项目初始化
先确认本机已经安装了 Python。打开终端执行:
python --version如果显示的是Python 3.9+版本,一般可以跑通下面的示例。Python 版本过低时,建议先升级或安装新版 Python。
创建一个项目目录,并初始化虚拟环境:
mkdir inventory-system cd inventory-system python -m venv venvWindows 系统激活虚拟环境:
venv\Scripts\activatemacOS / Linux 系统激活虚拟环境:
source venv/bin/activate激活后,命令行提示符前面会出现(venv),说明已经进入独立环境。接下来安装依赖:
pip install fastapi uvicorn sqlalchemy pandas openpyxl python-multipart依赖说明如下:
| 依赖包 | 作用 |
|---|---|
| fastapi | 提供 REST 接口服务 |
| uvicorn | 启动并运行 FastAPI 服务 |
| sqlalchemy | 数据库 ORM,用来操作 SQLite |
| pandas | 读取 Excel 文件、生成报表 |
| openpyxl | pandas 读写 Excel 的底层引擎 |
| python-multipart | 后续如果要接收文件上传时需要 |
安装完成后,在项目目录里建立如下结构:
inventory-system/ ├── models.py ├── stock_service.py ├── main.py ├── batch.py ├── products.xlsx └── inventory.dbproducts.xlsx是测试用的 Excel 文件,后面会用到。inventory.db由 SQLAlchemy 自动创建,不需要手动建。
如果本机没有安装 Python,也可以使用 Anaconda 或 Miniconda 创建虚拟环境。核心思路一样:先隔离依赖,再逐个安装包。
5. 数据模型设计:建表代码
新建models.py,写入数据库模型:
from datetime import datetime from sqlalchemy import Float, String, Text, DateTime, ForeignKey, create_engine from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, sessionmaker DATABASE_URL = "sqlite:///inventory.db" engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False}) SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False) class Base(DeclarativeBase): pass class Product(Base): __tablename__ = "product" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) code: Mapped[str] = mapped_column(String(64), unique=True, index=True) name: Mapped[str] = mapped_column(String(128), index=True) category: Mapped[str] = mapped_column(String(64), default="") min_stock: Mapped[float] = mapped_column(Float, default=0) stock_qty: Mapped[float] = mapped_column(Float, default=0) unit_price: Mapped[float] = mapped_column(Float, default=0) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now) class StockFlow(Base): __tablename__ = "stock_flow" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) product_id: Mapped[int] = mapped_column(ForeignKey("product.id"), index=True) change_type: Mapped[str] = mapped_column(String(16)) quantity: Mapped[float] = mapped_column(Float) before_qty: Mapped[float] = mapped_column(Float, default=0) after_qty: Mapped[float] = mapped_column(Float, default=0) relate_no: Mapped[str] = mapped_column(String(64), default="") remark: Mapped[str] = mapped_column(Text, default="") created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, index=True)Product表存商品主数据,StockFlow表存库存流水。这里采用“商品表冗余当前库存”的简单模型,适合小型系统。
不要在表里直接存储对象,也不要让商品编码成为可变字段。商品编码是业务主键,一旦创建,后续不应允许随意修改。如果需要更换编码,可以新建商品并迁移库存。
接下来在 Python 交互式环境或脚本中执行建表:
from models import Base, engine Base.metadata.create_all(bind=engine)运行后,项目目录下会出现inventory.db文件。你可以用 SQLite 工具查看表结构,确认product和stock_flow两张表都已经创建。
这一步做完,WorkBuddy 生成的“表结构设计”就落到真实数据库里了。字段命名、类型、索引,直接影响后面的接口和批量脚本,值得花几分钟检查。
6. 库存业务核心逻辑
建表只是第一步,库存管理的核心在“变动逻辑”。建议把所有库存变动逻辑收拢到一个StockService类里,不要让路由函数直接修改库存。这样接口、命令行脚本和以后接入 WorkBuddy 时,都复用同一套校验规则。
新建stock_service.py:
from sqlalchemy.orm import Session from models import Product, StockFlow class StockService: def __init__(self, db: Session): self.db = db def _get_product(self, product_code: str) -> Product: product = ( self.db.query(Product) .filter(Product.code == product_code) .first() ) if not product: raise ValueError(f"商品 {product_code} 不存在") return product def _write_flow( self, product: Product, before_qty: float, after_qty: float, change_type: str, quantity: float, relate_no: str, remark: str, ) -> StockFlow: product.stock_qty = after_qty flow = StockFlow( product_id=product.id, change_type=change_type, quantity=quantity, before_qty=before_qty, after_qty=after_qty, relate_no=relate_no, remark=remark, ) self.db.add(flow) self.db.commit() self.db.refresh(flow) return flow def stock_in(self, product_code: str, quantity: float, relate_no: str = "", remark: str = ""): if quantity <= 0: raise ValueError("入库数量必须大于 0") product = self._get_product(product_code) before_qty = product.stock_qty after_qty = before_qty + quantity return self._write_flow( product, before_qty, after_qty, "in", quantity, relate_no, remark ) def stock_out(self, product_code: str, quantity: float, relate_no: str = "", remark: str = ""): if quantity <= 0: raise ValueError("出库数量必须大于 0") product = self._get_product(product_code) before_qty = product.stock_qty if before_qty < quantity: raise ValueError(f"商品 {product_code} 库存不足,当前库存 {before_qty}") after_qty = before_qty - quantity return self._write_flow( product, before_qty, after_qty, "out", quantity, relate_no, remark )这段代码做了三件事:校验商品是否存在、校验出库数量是否超过当前库存、写入库存流水。你不需要在接口层重复写这些判断。
再看盘点调整方法:
def stock_adjust(self, product_code: str, actual_qty: float, relate_no: str = "", remark: str = ""): if actual_qty < 0: raise ValueError("实际库存不能为负数") product = self._get_product(product_code) before_qty = product.stock_qty after_qty = actual_qty return self._write_flow( product, before_qty, after_qty, "adjust", abs(after_qty - before_qty), relate_no, remark, )stock_adjust的做法是把库存修正为盘点后的实际数量。比如账面库存是 5,盘点发现只有 3,就把actual_qty传 3,流水里会记录差异 2。
这里的重点是“所有库存变动都必须有流水”。即使只是修正差异,也要留下审计线索。否则后续很难排查某个数据是怎么错的。
需要说明的是,SQLite 适合单机低并发。如果未来有多个窗口同时开单,建议把数据库迁移到 PostgreSQL,并在事务级别加行锁。对本地演示和小团队内部使用,SQLAlchemy 配合 SQLite 已经足够。
7. FastAPI 接口服务
新建main.py,将库存服务发布成 HTTP 接口。先写基础入口:
from contextlib import asynccontextmanager from fastapi import Depends, FastAPI, HTTPException from pydantic import BaseModel from sqlalchemy.orm import Session from models import Base, SessionLocal, Product, engine from stock_service import StockService @asynccontextmanager async def lifespan(app: FastAPI): Base.metadata.create_all(bind=engine) yield app = FastAPI(title="库存管理系统 API", lifespan=lifespan) def get_db(): db = SessionLocal() try: yield db finally: db.close() class ProductCreateIn(BaseModel): code: str name: str category: str = "" min_stock: float = 0 unit_price: float = 0 class StockChangeIn(BaseModel): product_code: str quantity: float relate_no: str = "" remark: str = ""接口列表如下:
POST /products创建商品。GET /products查询商品列表。POST /stock/in入库。POST /stock/out出库。POST /stock/adjust盘点调整。GET /stock/low低库存预警。
继续在main.py里写路由:
@app.post("/products") def create_product(body: ProductCreateIn, db: Session = Depends(get_db)): exists = db.query(Product).filter(Product.code == body.code).first() if exists: raise HTTPException(status_code=400, detail="商品编码已存在") product = Product( code=body.code, name=body.name, category=body.category, min_stock=body.min_stock, unit_price=body.unit_price, ) db.add(product) db.commit() db.refresh(product) return product @app.get("/products") def list_products(db: Session = Depends(get_db)): return db.query(Product).order_by(Product.code).all() @app.get("/stock/low") def low_stock_list(db: Session = Depends(get_db)): products = ( db.query(Product) .filter(Product.stock_qty <= Product.min_stock) .order_by(Product.stock_qty.asc()) .all() ) return [ { "code": p.code, "name": p.name, "stock_qty": p.stock_qty, "min_stock": p.min_stock, } for p in products ] @app.post("/stock/in") def stock_in(body: StockChangeIn, db: Session = Depends(get_db)): service = StockService(db) try: flow = service.stock_in( product_code=body.product_code, quantity=body.quantity, relate_no=body.relate_no, remark=body.remark, ) except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) return {"status": "ok", "flow_id": flow.id, "after_qty": flow.after_qty} @app.post("/stock/out") def stock_out(body: StockChangeIn, db: Session = Depends(get_db)): service = StockService(db) try: flow = service.stock_out( product_code=body.product_code, quantity=body.quantity, relate_no=body.relate_no, remark=body.remark, ) except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) return {"status": "ok", "flow_id": flow.id, "after_qty": flow.after_qty}启动服务:
uvicorn main:app --reload --host 127.0.0.1 --port 8000浏览器打开http://127.0.0.1:8000/docs,能看到 FastAPI 自动生成的交互式接口文档。这个页面可以用来测试所有接口,不需要额外安装 Postman。
先用文档页创建一个商品。假设商品编码是SKU1001,创建库存的商品接口会返回商品信息。然后调用入库接口,quantity填 10,再查询低库存列表时应该能够看到库存在安全线以上的商品不在预警里。
这套接口的访问范围只绑定本机地址,适合本地测试和局域网内部调用。不要直接绑定0.0.0.0放到公网,除非你加了登录鉴权和 HTTPS。
8. WorkBuddy 中如何完成“一句话设计”
现在回到 WorkBuddy 的使用方式。拿到 Python 工程后,WorkBuddy 还能做什么?它不只是聊天工具,还可以作为系统的“设计入口”和“流程编排入口”。
8.1 把完整需求写进一条提示词
把第 3 节那段较长的提示词发给 WorkBuddy。它大概率会先输出业务模块拆解,然后给出数据库表设计。你应该检查它是否覆盖了:商品主数据、库存流水、出入库校验、低库存判断、接口列表、批量导入。
如果你只想发一句话,也建议把关键词压缩得更明确:
用 Python 设计一个商品库存管理系统,包含商品档案、入库、出库、盘点调整、库存流水和低库存预警,数据存 SQLite,用 FastAPI 提供接口,后续要支持 Excel 批量导入。一句话能说清主方向,但完整需求要靠后续追问补齐。想让 WorkBuddy 少走弯路,最好在提示词里告诉它“先不要写代码,先输出设计方案”。等设计方案确认后,再让它按模块生成代码。这样不会一上来就得到一大堆混乱的代码。
8.2 让 WorkBuddy 输出任务清单,再逐段生成代码
WorkBuddy 更适合承担“项目经理 + 初级程序员”的角色。你可以这样安排对话:
- 第一轮:确认表结构和模块清单。
- 第二轮:让它生成
models.py完整代码。 - 第三轮:让它生成
stock_service.py,重点看库存不足校验和流水记录。 - 第四轮:让它生成
main.py接口文件。 - 第五轮:让它检查一遍代码可能存在的边界条件。
每轮都只聚焦一个文件或一个模块。你每确认一轮,就把它输出的代码保存到本地对应文件,再进入下一轮。如果一次要求生成全部代码,后续排查 Bug 的成本会高很多。
WorkBuddy 如果支持自定义技能或工作流,可以把这套提示词沉淀成一个“库存系统生成技能”。下次只要输入商品字段、仓库名称、是否需要批次管理等参数,就能快速生成另一个业务系统草稿。具体入口以你使用的 WorkBuddy 版本为准,不同版本对“技能”的定义不完全一致。
8.3 把本地 API 接入 WorkBuddy
如果你的 WorkBuddy 版本支持 API 接入或自定义工具,可以把本地 FastAPI 服务注册为工具。你需要给 WorkBuddy 提供接口文档地址和访问说明。对于本机服务,默认地址是:
http://127.0.0.1:8000/docs注册后,WorkBuddy 可以在对话里调用入库、出库、查询商品等接口。比如你说“SKU1001 入库 20 件”,它能先解析出商品编码和数量,再调用本地的POST /stock/in接口完成操作。
这里有两个前提:服务必须处于启动状态,WorkBuddy 所在进程必须能访问到该地址。如果是云端的 WorkBuddy 服务,通常访问不了你本机的127.0.0.1,你需要用内网穿透或把服务部署到同一台服务器。为了稳妥,先确认网络可达性,再测试自动调用。
接口接入后,你仍然要保留人工确认机制。AI 助手帮你触发接口不等于业务上可以免除审批。实际项目里,建议把“创建退货单”“批量冲销”这类敏感操作设置为需要人工二次确认。
9. Excel 批量任务:导入与预警报表
库存系统最常用的批量任务有两个:批量初始化商品、导出低库存清单。新建batch.py。
先写商品导入逻辑:
import pandas as pd from models import Product, SessionLocal, engine from sqlalchemy.exc import IntegrityError def import_products_from_excel(path: str): df = pd.read_excel(path, dtype={"code": str}) db = SessionLocal() try: for row in df.to_dict("records"): code = str(row.get("code") or "").strip() if not code: continue product = db.query(Product).filter(Product.code == code).first() if product: product.name = row.get("name") or product.name product.category = row.get("category") or product.category product.min_stock = float(row.get("min_stock") or 0) product.unit_price = float(row.get("unit_price") or 0) else: product = Product( code=code, name=row.get("name") or "", category=row.get("category") or "", min_stock=float(row.get("min_stock") or 0), unit_price=float(row.get("unit_price") or 0), ) db.add(product) db.commit() print("导入完成") except IntegrityError as exc: db.rollback() print("导入失败,存在重复或非法数据:", exc) finally: db.close()再写低库存报表导出:
def export_low_stock(path: str = "low_stock.xlsx"): db = SessionLocal() try: products = ( db.query(Product) .filter(Product.stock_qty <= Product.min_stock) .order_by(Product.stock_qty.asc()) .all() ) records = [ { "商品编码": p.code, "商品名称": p.name, "当前库存": p.stock_qty, "最低库存": p.min_stock, "缺货数量": max(p.min_stock - p.stock_qty, 0), } for p in products ] df = pd.DataFrame(records) df.to_excel(path, index=False) print(f"已导出低库存报表:{path}") finally: db.close()调用方式:
python batch.py可以在batch.py文件末尾加一段话:
if __name__ == "__main__": import_products_from_excel("products.xlsx") export_low_stock("low_stock.xlsx")Excel 模板至少需要这几列:code、name、category、min_stock、unit_price。建议先用三五行数据测试,确认能导入后再处理完整表格。
批量导入的幂等性很重要。上面的导入逻辑对已存在的商品做更新,而不是重复插入。如果数据仍然出错,先检查 Excel 列名是否匹配、商品编码是否有隐形空格。
导出低库存报表可以在 Windows 下用任务计划程序定时执行,也可以在 Linux 下用 cron。WorkBuddy 如果支持定时工作流,也可以让它提醒你触发这个脚本,但定时任务最终仍要落在能运行 Python 的机器上。
10. 测试与效果验证
不要直接把 WorkBuddy 生成的代码当成品上线。先走一遍冒烟测试。
建议顺序:
- 启动服务。
- 创建商品
SKU1001。 - 入库 20 件。
- 出库 5 件。
- 查询商品,确认库存是 15。
- 尝试超量出库,确认接口返回 400。
- 查询库存流水,确认有两条记录。
- 把最低库存设为 10,再出库 6 件,使库存变成 9,查询低库存列表。
- 用 Excel 导入 10 个商品,确认不报错。
- 导出低库存报表,确认 Excel 文件能打开。
也可以写一段简单的 Python 测试脚本:
import requests BASE_URL = "http://127.0.0.1:8000" # 创建商品 r = requests.post(f"{BASE_URL}/products", json={ "code": "SKU1001", "name": "测试商品", "min_stock": 10, "unit_price": 20.5, }) print("创建商品:", r.status_code, r.json()) # 入库 r = requests.post(f"{BASE_URL}/stock/in", json={ "product_code": "SKU1001", "quantity": 20, "remark": "初始化库存" }) print("入库:", r.status_code, r.json()) # 出库 r = requests.post(f"{BASE_URL}/stock/out", json={ "product_code": "SKU1001", "quantity": 5, "remark": "销售出库" }) print("出库:", r.status_code, r.json()) # 查询商品 r = requests.get(f"{BASE_URL}/products") print("商品列表:", r.status_code) for item in r.json(): if item["code"] == "SKU1001": print("当前库存:", item["stock_qty"])判断标准很简单:
- 当前库存和手工计算结果一致。
- 流水数量、类型、变动前后数量一致。
- 低库存商品能被准确筛出。
- 多次重复导入 Excel 不会产生重复商品。
如果所有测试通过,再把系统交给业务同事试用。试用阶段不要马上删除原来的 Excel 表格,建议并行运行一段时间,确认系统数据没有问题后再切换。
11. 资源占用与性能观察
很多开发者会关心这个系统跑起来占多少资源。作为纯 Python 的本地服务,FastAPI + SQLite 在空载时占用的 CPU 基本可以忽略,内存也远低于本地启动一个桌面端软件的量级。具体数字取决于 Python 进程、依赖包数量和系统状态,不同机器差异很大,不能一概而论。
想观察资源占用,Windows 下打开任务管理器,macOS 下可以用活动监视器,Linux 下用:
top或:
htop观察的核心不是“内存数字多好看”,而是服务是否稳定。如果运行半个月后内存持续上涨,优先检查是否有数据库连接未关闭、批量任务是否持有 Session。文章里的示例代码用SessionLocal()后都会在finally里关闭连接,这个习惯要保持。
批量导入大 Excel 时,不要逐行提交事务。上面的示例是一次性收集后统一commit,可以明显减少磁盘写入。如果文件有几万行,建议分成每 500 行提交一次,避免单次事务过大。具体批次大小需要根据机器性能调整。
SQLite 的性能上限取决于写并发。当入库、出库、报表同时访问时,可能出现短暂的锁等待。如果是单机个人使用,影响很小;如果多人同时操作,就要考虑把数据库切换到 PostgreSQL。切换时只需要修改DATABASE_URL,模型代码基本不用大改。
接口响应时间也可以通过 WorkBuddy 或脚本观察。第一次访问接口时,Python 需要加载依赖,响应时间会略高;之后正常请求通常都在毫秒级。如果查询变慢,先看是否缺索引。商品编码已经有唯一索引,流水表的product_id和created_at也建了索引,常规查询不会有明显压力。
12. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
运行python提示找不到命令 | Python 未安装或未加入 PATH | 执行python --version | 安装 Python,或在 IDE 中配置解释器 |
ModuleNotFoundError | 依赖没有安装到当前环境 | 看报错中的包名 | 执行pip install 包名 |
| 端口 8000 被占用 | 有其他服务占用端口 | netstat -ano查看端口 | 换端口启动,如--port 8001 |
| 创建商品时报编码已存在 | 商品编码重复 | 查询已有商品 | 修改 Excel 中的编码,或改为更新逻辑 |
| 出库返回库存不足 | 当前库存小于出库数量 | 查询商品当前库存 | 入库后再出库,或增加盘点调整 |
| 数据库没有生成表 | create_all未执行或路径不对 | 检查当前目录是否有 SQLite 文件 | 在 app 启动时执行Base.metadata.create_all(bind=engine) |
| Excel 导入后商品数量不对 | Excel 列名与代码不匹配 | 打印df.head() | 统一列名为code,name,category,min_stock,unit_price |
| WorkBuddy 调用本地接口失败 | 服务未启动或网络隔离 | 先用浏览器访问接口地址 | 启动 uvicorn,或把服务部署到同一网络 |
| 批量任务重复执行后数据翻倍 | 导入逻辑没有做幂等处理 | 检查现有商品编码 | 先查再更新,不使用无条件新增 |
| 多个窗口同时操作库存 | SQLite 写锁冲突 | 看报错是否包含database is locked | 减少并发,或迁移 PostgreSQL |
遇到报错时先读第一行异常类型,不要只看最后一行提示。比如sqlalchemy.exc.IntegrityError说明是数据库唯一约束冲突,requests.exceptions.ConnectionError说明服务没启动或端口不通。
WorkBuddy 生成的代码偶尔会出现上下文不一致的问题。比如前面设计了stock_qty字段,后面生成的查询却用了quantity。遇到这种问题,把完整的表结构重新粘贴给它,并要求“对照 models.py 里的字段重新生成”。
13. 最佳实践与使用建议
先消化一下前面的技术细节,再给几条工程化建议。
第一,把提示词当成项目文档来管理。在项目里新建prompts.md,保存你问 WorkBuddy 的核心提示词。下次调整字段或新增模块时,直接基于旧提示词修改,而不是重新描述一遍需求。
第二,先小参数验证,再全量导入。第一次运行批量导入时,只放 5 行数据。确认逻辑正确后再处理完整 Excel,可以避免把一堆脏数据写进数据库。
第三,不要对商品做物理删除。库存系统里,商品一旦发生过入库或出库,它的历史流水就有价值。如果商品下架,建议增加is_active字段标记停用,而不是从表里删除。
第四,涉及金额和数量的修改要留痕。系统里的出库、盘点操作,尽量记录操作人和关联单号。示例中的流水表字段可以继续扩展,比如增加operator字段。
第五,AI 生成代码必须经过人工审查。WorkBuddy 帮你节省的是起草时间,不能替代代码审查。上线前至少要看一遍库存写操作部分,确认不会出现负数库存和异常流水。
第六,注意隐私与合规。不要把真实客户列表、供应商价格、员工信息直接粘贴到 AI 工具里。测试时使用虚构数据,确认稳定后再处理真实数据。如果系统要放公网或保存敏感数据,需要增加登录认证、权限控制和操作日志。
第七,备份 SQLite 文件。系统简单不代表数据不重要。定期复制inventory.db到其他目录,或直接使用 SQLite 的备份命令。对多数小团队来说,一个每日自动备份脚本能解决很多意外问题。
14. 继续扩展:从库存系统到更多业务系统
这套方案的扩展性比传统“找 AI 写一个脚本”好很多。库存管理系统只是商品进销存的一部分,接下来可以继续加销售订单、采购单、供应商管理、批次效期、多仓库调拨。WorkBuddy 在这样的扩展中依然作为需求拆解和代码生成辅助层,你只需要把新增需求按相同方式提示给它。
如果业务变复杂,建议把数据模型从 SQLite 平滑迁移到 PostgreSQL,把服务从单文件拆成 routers、services、models 分层,再接入后端管理系统或移动端。那时候 Python 工程本身已经成型,WorkBuddy 可以帮你生成新的模块代码和测试用例,但整个工程的架构边界需要你来把握。
对大多数还没有信息系统的团队来说,现在最值得做的不是等一个完整商业软件,而是先让 WorkBuddy 辅助你快速搭出一个能跑通的小系统。库存数据如果能从 Excel 转移到带流水和接口的本地系统中,后面的报表、预警、业务系统对接都会顺畅很多。
建议先按第 10 节的测试流程跑一遍。只要前台服务和后台库存逻辑走通,你就具备了一套可以持续演化的基础工程。之后再决定是继续在 FastAPI 上加功能,还是换成更复杂的 Web 框架。方向不同,但底层的库存模型和业务规则不会变化太多。