本文目录导读:

我来介绍几种盘点库存商品的脚本方法,从简单到复杂,涵盖不同应用场景。
基础盘点脚本(CSV/Excel格式)
Python版本
import csv
from datetime import datetime
class InventoryChecker:
def __init__(self, inventory_file, stock_file):
"""
inventory_file: 系统记录的库存清单
stock_file: 实际盘点的库存数据
"""
self.inventory = self._load_csv(inventory_file)
self.actual_stock = self._load_csv(stock_file)
def _load_csv(self, file_path):
"""加载CSV文件"""
data = {}
with open(file_path, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
sku = row.get('SKU') or row.get('商品编码')
quantity = int(row.get('数量', 0))
data[sku] = {
'name': row.get('商品名称', ''),
'quantity': quantity,
'location': row.get('库位', '')
}
return data
def compare_stock(self):
"""对比系统库存和实际库存"""
differences = []
all_skus = set(list(self.inventory.keys()) + list(self.actual_stock.keys()))
for sku in all_skus:
sys_qty = self.inventory.get(sku, {}).get('quantity', 0)
actual_qty = self.actual_stock.get(sku, {}).get('quantity', 0)
if sys_qty != actual_qty:
differences.append({
'SKU': sku,
'商品名称': self.inventory.get(sku, {}).get('name', '未知'),
'系统库存': sys_qty,
'实际库存': actual_qty,
'差异': actual_qty - sys_qty,
'库位': self.inventory.get(sku, {}).get('location', '')
})
return differences
def generate_report(self, output_file):
"""生成盘点报告"""
differences = self.compare_stock()
with open(output_file, 'w', encoding='utf-8', newline='') as f:
writer = csv.DictWriter(f, fieldnames=[
'SKU', '商品名称', '系统库存', '实际库存', '差异', '库位'
])
writer.writeheader()
writer.writerows(differences)
print(f"盘点完成!发现 {len(differences)} 个差异项")
print(f"报告已保存至:{output_file}")
# 统计摘要
total_diff = sum([d['差异'] for d in differences])
print(f"总差异数量:{total_diff}")
print(f"盘盈:{sum([d['差异'] for d in differences if d['差异'] > 0])}")
print(f"盘亏:{abs(sum([d['差异'] for d in differences if d['差异'] < 0]))}")
# 使用示例
if __name__ == "__main__":
checker = InventoryChecker('system_inventory.csv', 'actual_stock.csv')
checker.generate_report(f'inventory_check_{datetime.now().strftime("%Y%m%d")}.csv')
批量盘点工具(带条码扫描)
Python脚本(支持条码枪连续扫描)
import tkinter as tk
from tkinter import ttk, messagebox
import json
import csv
from datetime import datetime
class BarcodeInventoryScanner:
def __init__(self):
self.root = tk.Tk()
self.root.title("扫码盘点工具")
self.root.geometry("600x500")
# 存储盘点数据
self.scanned_items = {}
self.current_sku = ""
self.setup_ui()
def setup_ui(self):
# 商品信息展示区
frame = ttk.LabelFrame(self.root, text="扫描结果", padding=10)
frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# 当前扫描的SKU
self.sku_entry = ttk.Entry(frame, font=("Arial", 12))
self.sku_entry.pack(fill=tk.X, pady=5)
self.sku_entry.bind('<Return>', self.process_scan)
# 表格显示
columns = ('商品编码', '商品名称', '扫描数量')
self.tree = ttk.Treeview(frame, columns=columns, show='headings', height=15)
self.tree.heading('商品编码', text='商品编码')
self.tree.heading('商品名称', text='商品名称')
self.tree.heading('扫描数量', text='扫描数量')
self.tree.pack(fill=tk.BOTH, expand=True)
# 统计信息
info_frame = ttk.Frame(self.root)
info_frame.pack(fill=tk.X, padx=10)
self.items_count = ttk.Label(info_frame, text="已扫描商品数:0")
self.items_count.pack(side=tk.LEFT, padx=5)
self.total_qty = ttk.Label(info_frame, text="总数量:0")
self.total_qty.pack(side=tk.LEFT, padx=5)
# 操作按钮
btn_frame = ttk.Frame(self.root)
btn_frame.pack(fill=tk.X, padx=10, pady=10)
ttk.Button(btn_frame, text="导出盘点结果", command=self.export_report).pack(side=tk.LEFT, padx=5)
ttk.Button(btn_frame, text="清空数据", command=self.clear_data).pack(side=tk.LEFT, padx=5)
ttk.Button(btn_frame, text="退出", command=self.root.quit).pack(side=tk.RIGHT, padx=5)
def process_scan(self, event):
"""处理条码扫描"""
sku = self.sku_entry.get().strip()
if sku:
# 查询商品信息(可以从数据库或商品主数据中获取)
product_info = self.get_product_info(sku)
if product_info:
# 累加扫描数量(条码枪通常每次扫描一个,数量为1)
if sku in self.scanned_items:
self.scanned_items[sku]['quantity'] += 1
else:
self.scanned_items[sku] = {
'name': product_info['name'],
'quantity': 1
}
# 更新界面
self.update_display()
self.sku_entry.delete(0, tk.END)
else:
messagebox.showwarning("警告", f"未找到商品:{sku}")
self.sku_entry.select_range(0, tk.END)
def get_product_info(self, sku):
"""获取商品信息(示例:可以改为数据库查询或API调用)"""
# 示例商品数据
products = {
'001': {'name': '商品A'},
'002': {'name': '商品B'},
'003': {'name': '商品C'},
}
return products.get(sku)
def update_display(self):
"""更新界面显示"""
# 清空表格
for item in self.tree.get_children():
self.tree.delete(item)
# 重新填充数据
for sku, info in self.scanned_items.items():
self.tree.insert('', 'end', values=(
sku, info['name'], info['quantity']
))
# 更新统计信息
self.items_count.config(text=f"已扫描商品数:{len(self.scanned_items)}")
total = sum([v['quantity'] for v in self.scanned_items.values()])
self.total_qty.config(text=f"总数量:{total}")
def export_report(self):
"""导出盘点报告"""
if not self.scanned_items:
messagebox.showinfo("提示", "没有扫描数据可以导出")
return
filename = f"inventory_scan_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
with open(filename, 'w', encoding='utf-8', newline='') as f:
writer = csv.writer(f)
writer.writerow(['商品编码', '商品名称', '盘点数量'])
for sku, info in self.scanned_items.items():
writer.writerow([sku, info['name'], info['quantity']])
messagebox.showinfo("导出成功", f"盘点数据已保存至:{filename}")
def clear_data(self):
"""清空扫描数据"""
if messagebox.askyesno("确认", "确定要清空所有扫描数据吗?"):
self.scanned_items.clear()
self.update_display()
def run(self):
self.root.mainloop()
# 启动扫码盘点工具
if __name__ == "__main__":
app = BarcodeInventoryScanner()
app.run()
Web版盘点系统(Flask + SQLite)
服务端脚本
from flask import Flask, request, jsonify, render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import json
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///inventory.db'
db = SQLAlchemy(app)
# 数据库模型
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
sku = db.Column(db.String(50), unique=True, nullable=False)
name = db.Column(db.String(100), nullable=False)
current_stock = db.Column(db.Integer, default=0)
location = db.Column(db.String(50))
class InventoryCheck(db.Model):
id = db.Column(db.Integer, primary_key=True)
product_id = db.Column(db.Integer, db.ForeignKey('product.id'))
stock_before = db.Column(db.Integer)
stock_after = db.Column(db.Integer)
check_time = db.Column(db.DateTime, default=datetime.utcnow)
operator = db.Column(db.String(50))
# 盘点API接口
@app.route('/api/check_stock', methods=['POST'])
def check_stock():
"""处理盘点数据"""
data = request.json
sku = data.get('sku')
actual_quantity = data.get('quantity')
product = Product.query.filter_by(sku=sku).first()
if not product:
return jsonify({'error': '商品不存在'}), 404
# 记录盘点差异
check = InventoryCheck(
product_id=product.id,
stock_before=product.current_stock,
stock_after=actual_quantity,
operator=data.get('operator', '系统')
)
db.session.add(check)
db.session.commit()
# 更新库存
product.current_stock = actual_quantity
db.session.commit()
return jsonify({
'message': '盘点成功',
'product': product.name,
'before': check.stock_before,
'after': actual_quantity,
'difference': actual_quantity - check.stock_before
})
@app.route('/api/check_report')
def check_report():
"""获取盘点报告"""
checks = InventoryCheck.query.order_by(InventoryCheck.check_time.desc()).all()
report = []
for check in checks:
product = Product.query.get(check.product_id)
report.append({
'id': check.id,
'product': product.name,
'sku': product.sku,
'before': check.stock_before,
'after': check.stock_after,
'difference': check.stock_after - check.stock_before,
'time': check.check_time.strftime('%Y-%m-%d %H:%M:%S'),
'operator': check.operator
})
return jsonify(report)
# 盘点页面
@app.route('/')
def index():
return render_template('inventory_check.html')
if __name__ == '__main__':
db.create_all()
app.run(debug=True)
自动化盘点脚本(批量处理)
批量处理脚本
#!/bin/bash
# 适用于Linux/Mac的批量盘点脚本
# 设置变量
INVENTORY_FILE="inventory_$(date +%Y%m%d).csv"
REPORT_FILE="check_report_$(date +%Y%m%d).txt"
TEMP_FILE="/tmp/inventory_temp.txt"
echo "=== 库存盘点脚本 ===" > $REPORT_FILE
echo "时间:$(date)" >> $REPORT_FILE
echo "---------------------" >> $REPORT_FILE
# 模拟从数据库导出库存数据
echo "正在导出系统库存数据..."
# 实际使用时替换为数据库查询或API调用
echo "001,商品A,100,A-01" > $INVENTORY_FILE
echo "002,商品B,50,B-02" >> $INVENTORY_FILE
echo "003,商品C,200,C-01" >> $INVENTORY_FILE
# 模拟读取实际盘点数据(从CSV或手动输入)
echo "读取实际盘点数据..."
while IFS=, read -r sku name qty_location
do
# 从实际盘点文件或输入获取数量
read -p "请输入 $sku ($name) 的盘点数量: " actual_qty
system_qty=$(grep "^$sku," $INVENTORY_FILE | cut -d, -f3)
if [ $system_qty -ne $actual_qty ]; then
diff=$((actual_qty - system_qty))
echo "差异:$sku ($name) - 系统:$system_qty, 实际:$actual_qty, 差异:$diff" >> $REPORT_FILE
fi
done < $INVENTORY_FILE
echo "盘点完成!报告已保存至 $REPORT_FILE"
使用建议
-
选择合适的工具:
- 小规模盘点:使用Python CSV脚本或Excel宏
- 实时盘点:使用带条码扫描的GUI工具
- 企业级:使用Web系统配合数据库
-
最佳实践:
- 盘点前备份数据
- 使用条码/二维码减少人为错误
- 定期进行周期性盘点
- 保留历史盘点数据
-
扩展功能:
- 对接ERP/WMS系统
- 支持多仓库盘点
- 自动生成差异分析报告
- 数据校验和异常预警
需要根据你的具体业务场景选择合适的方法,如果需要更详细的某个方案或扩展功能,请告诉我!