本文目录导读:

我来介绍几种盘点库存商品的脚本方法,从简单到复杂,涵盖不同应用场景。
基础盘点脚本(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系统
- 支持多仓库盘点
- 自动生成差异分析报告
- 数据校验和异常预警
需要根据你的具体业务场景选择合适的方法,如果需要更详细的某个方案或扩展功能,请告诉我!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播