接上篇,我们已经用Python+SQLite搭好了进销存的骨架。今天给它装上“眼睛”——扫码枪。重点解决一个真实痛点:
扫码枪扫了,系统怎么知道是什么东西?新商品第一次扫怎么办?
一、先要明白扫码得到数字 如何知道是什么商品
扫码枪扫到的只是一串数字,它本身不知道这串数字代表什么。知道含义的是你的程序。
整个过程就是三步:
- 扫码枪把条码数字传给程序
- 程序拿着数字去数据库里查“这串数字对应哪个商品”
- 查到了就调出商品信息,执行入库或销售;没查到就让老板选一下,然后记住这个对应关系
用一句大白话总结:扫码枪报了串“身份证号”,程序去“户籍系统”里查这个人是谁。
二、数据库升级:增加两张“户籍表”
很多新手会把条码直接存到商品表里,但现实中会遇到两个问题:
- 一个商品可能有多个条码(换了包装、换了供应商,条码就变了)
- 同一个条码可能对应不同商品
所以最稳妥的做法是:单独建一张“条码映射表”,记录“条码↔商品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报表,月底对账不再愁。欢迎关注,我们下期见!
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.