脚本如何盘点库存商品

wen 实用脚本 30

本文目录导读:

脚本如何盘点库存商品

  1. 基础盘点脚本(CSV/Excel格式)
  2. 批量盘点工具(带条码扫描)
  3. Web版盘点系统(Flask + SQLite)
  4. 自动化盘点脚本(批量处理)
  5. 使用建议

我来介绍几种盘点库存商品的脚本方法,从简单到复杂,涵盖不同应用场景。

基础盘点脚本(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"

使用建议

  1. 选择合适的工具

    • 小规模盘点:使用Python CSV脚本或Excel宏
    • 实时盘点:使用带条码扫描的GUI工具
    • 企业级:使用Web系统配合数据库
  2. 最佳实践

    • 盘点前备份数据
    • 使用条码/二维码减少人为错误
    • 定期进行周期性盘点
    • 保留历史盘点数据
  3. 扩展功能

    • 对接ERP/WMS系统
    • 支持多仓库盘点
    • 自动生成差异分析报告
    • 数据校验和异常预警

需要根据你的具体业务场景选择合适的方法,如果需要更详细的某个方案或扩展功能,请告诉我!

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