接上篇,我们已经用Python+SQLite搭好了进销存的骨架。今天给它装上“眼睛”——扫码枪。重点解决一个真实痛点:

扫码枪扫了,系统怎么知道是什么东西?新商品第一次扫怎么办?

一、先要明白扫码得到数字 如何知道是什么商品

扫码枪扫到的只是一串数字,它本身不知道这串数字代表什么。知道含义的是你的程序。

整个过程就是三步:

  1. 扫码枪把条码数字传给程序
  2. 程序拿着数字去数据库里查“这串数字对应哪个商品”
  3. 查到了就调出商品信息,执行入库或销售;没查到就让老板选一下,然后记住这个对应关系

用一句大白话总结:扫码枪报了串“身份证号”,程序去“户籍系统”里查这个人是谁。

二、数据库升级:增加两张“户籍表”

很多新手会把条码直接存到商品表里,但现实中会遇到两个问题:

  • 一个商品可能有多个条码(换了包装、换了供应商,条码就变了)
  • 同一个条码可能对应不同商品

所以最稳妥的做法是:单独建一张“条码映射表”,记录“条码↔商品ID”的对应关系。

新增表结构

-- 给商品表增加条码字段ALTER TABLE goods ADD COLUMN barcode TEXT;-- 创建条码映射表CREATE TABLE IF NOT EXISTS barcode_mapping (map_id INTEGER PRIMARY KEY AUTOINCREMENT,barcode TEXT UNIQUE NOT NULL,goods_id INTEGER NOT NULL,first_scan_time DATETIME DEFAULT (datetime('now','localtime')),last_scan_time DATETIME,scan_count INTEGER DEFAULT 1,FOREIGN KEY (goods_id) REFERENCES goods(goods_id));
三、界面改造:增加扫码工具栏

在软件界面顶部增加一个持久存在的扫码输入框,光标默认就在那里:

打开网易新闻 查看精彩图片

扫码区

def create_scan_toolbar(self, parent):"""在界面顶部创建全局扫码工具栏"""toolbar = ttk.LabelFrame(parent, text=" 扫码快捷录入", padding=5)toolbar.pack(fill=tk.X, padx=2, pady=5)self.scan_entry = ttk.Entry(frame, width=35, font=('Arial', 14))self.scan_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)self.scan_entry.focus_set()self.scan_entry.bind('', self.handle_barcode_scan)# F2快捷键回到扫码框self.root.bind('', lambda e: self.scan_entry.focus_set())
四、核心代码:扫码处理全流程 4.1 扫码主入口

def handle_barcode_scan(self, event):barcode = self.scan_entry.get().strip()if not barcode:return# 查条码映射表goods_id = self.db.find_goods_by_barcode_mapping(barcode)if goods_id:# 已知条码:直接处理self.db.update_barcode_scan_count(barcode)self.process_known_barcode(barcode, goods_id)else:# 未知条码:弹出商品选择窗口self.show_goods_selection_window(barcode)self.scan_entry.delete(0, tk.END)self.scan_entry.focus_set()
4.2 新条码弹窗选择商品(最核心的交互)

当扫到一个新条码时,自动弹窗让老板选择对应的商品:

打开网易新闻 查看精彩图片

扫到新条码 需要选择商品

def show_goods_selection_window(self, barcode):"""弹出商品选择窗口,让老板把条码和商品关联起来"""win = tk.Toplevel(self.root)win.title("新条码识别 - 请选择商品")win.geometry("600x500")win.transient(self.root)win.grab_set()# ... 创建商品列表Treeview,加载所有商品 ...def confirm_selection():selected = tree.selection()if not selected:returngoods_id = tree.item(selected[0])['values'][0]self.db.save_barcode_mapping(barcode, goods_id)win.destroy()self.process_known_barcode(barcode, goods_id)
4.3 智能联动:自动识别当前操作页

def process_known_barcode(self, barcode, goods_id):goods = self.db.get_goods_by_id(goods_id)current_tab = self.notebook.select()tab_text = self.notebook.tab(current_tab, 'text')if "采购" in tab_text:# 自动填充采购表单self.purchase_goods.set(f"{goods['goods_id']}-{goods['goods_name']}")self.purchase_price.insert(0, str(goods['cost_price']))self.purchase_qty.insert(0, "1")elif "销售" in tab_text:# 检查库存 + 自动填充销售表单stock = self.db.get_stock_balance(goods_id)if stock <= 0:messagebox.showerror("库存不足", f"库存为 0,无法销售!")returnself.sales_goods.set(f"{goods['goods_id']}-{goods['goods_name']} (库存:{stock})")self.sales_price.insert(0, str(goods['sale_price']))self.sales_qty.insert(0, "1")
五、完整操作演示 场景一:扫新条码 → 弹窗选商品 → 永久记住

打开网易新闻 查看精彩图片

第一次录入条码

场景二:采购入库

切换到「采购录入」页,扫码后自动填好商品和单价,确认数量后点击确认录入:

打开网易新闻 查看精彩图片

直接录入数量,金额自动计算

场景三:销售出库 + 自动验库存

切换到「销售录入」页,扫码后自动填好商品和售价:

打开网易新闻 查看精彩图片

销售出库

如果销售数量超过库存,系统自动拦截:

打开网易新闻 查看精彩图片

超出库存了

销售完成后,库存自动更新:

打开网易新闻 查看精彩图片

商品销售后的库存

七、小结

今天我们用 一张映射表 + 一个弹窗 + 四个核心函数,实现了扫码枪的“智能匹配”功能:

功能

效果

扫已知条码

自动识别,自动填表

扫未知条码

弹窗选商品,自动保存对应关系

切换标签页

自动判断是采购还是销售

一次匹配

永久使用,越用越快

扫码录入搞定了,下期讲:

一键导出Excel报表,月底对账不再愁。欢迎关注,我们下期见!