当前位置: 首页 > article >正文

Python PySide + SQLite3 开发的 《️ POS点销管理系统》可用初型

图:

 

 

 

目录:

开发说明书:

POS点销管理系统开发说明

1. 系统概述

本系统是一个基于 Python PySide6 开发的现代化 POS 点销管理系统,集成了商品管理、库存管理、会员管理、订单管理等核心功能。

2. 技术栈

  • 开发语言: Python 3.8+

  • GUI 框架: PySide6

  • 数据库: SQLite3

  • 样式框架: Qss

3. 系统功能模块

3.1 基础功能

  • 用户登录

    • 默认管理员账号: admin

    • 默认管理员密码: admin123

    • 多角色权限控制(管理员/收银员/经理)

3.2 核心模块

  1. 商品管理

    • 商品增删改查

    • 商品分类管理

    • 商品图片管理

    • 商品导入导出

    • 条码扫描支持

  2. 库存管理

    • 库存状态查看

    • 库存调整记录

    • 库存预警

    • 出入库管理

  3. 会员管理

    • 会员信息管理

    • 会员积分系统

    • 会员等级管理

    • 消费记录查询

  4. 订单管理

    • 订单创建与结算

    • 订单状态管理

    • 订单历史查询

    • 退款处理

3.3 界面设计

  • 现代化 Design 风格

  • 响应式布局

  • 直观的操作界面

  • 统一的视觉风格

4. 目录结构

├── main.py # 程序入口

├── database/

│ └── db_manager.py # 数据库管理

├── style/

│ └── style.qss # 界面样式

└── views/

├── login_window.py # 登录窗口

├── main_window.py # 主窗口

├── product_window.py # 商品管理

├── category_window.py # 分类管理

├── inventory_window.py # 库存管理

├── customer_window.py # 会员管理

├── employee_window.py # 员工管理

└── order_window.py # 订单管理

数据库结构:

1. 商品表 (products)

字段名

数据类型

约束/说明

中文说明

product_id

INTEGER

PRIMARY KEY, AUTOINCREMENT

商品ID(主键,自增)

product_code

VARCHAR(50)

UNIQUE, NOT NULL

商品编码(唯一,非空)

product_name

VARCHAR(100)

NOT NULL

商品名称(非空)

category_id

INTEGER

类别ID

unit_price

DECIMAL(10,2)

NOT NULL

单价(非空)

stock_quantity

INTEGER

NOT NULL, DEFAULT 0

库存数量(非空,默认0)

image_path

TEXT

图片路径

created_at

TIMESTAMP

DEFAULT CURRENT_TIMESTAMP

创建时间(默认当前时间)

updated_at

TIMESTAMP

DEFAULT CURRENT_TIMESTAMP

更新时间(默认当前时间)

2. 商品类别表 (categories)

字段名

数据类型

约束/说明

中文说明

category_id

INTEGER

PRIMARY KEY, AUTOINCREMENT

类别ID(主键,自增)

category_name

VARCHAR(50)

NOT NULL

类别名称(非空)

description

TEXT

类别描述

3. 订单表 (orders)

字段名

数据类型

约束/说明

中文说明

order_id

INTEGER

PRIMARY KEY, AUTOINCREMENT

订单ID(主键,自增)

order_number

VARCHAR(50)

UNIQUE, NOT NULL

订单编号(唯一,非空)

customer_id

INTEGER

客户ID

employee_id

INTEGER

NOT NULL

员工ID(非空)

order_date

TIMESTAMP

DEFAULT CURRENT_TIMESTAMP

订单日期(默认当前时间)

total_amount

DECIMAL(10,2)

NOT NULL

总金额(非空)

payment_method

TEXT

CHECK: IN ('cash', 'card', 'mobile_payment'), NOT NULL

支付方式(现金/卡/移动支付,非空)

status

TEXT

CHECK: IN ('completed', 'cancelled', 'refunded'), DEFAULT 'completed'

订单状态(完成/取消/退款,默认完成)

4. 订单明细表 (order_details)

字段名

数据类型

约束/说明

中文说明

order_detail_id

INTEGER

PRIMARY KEY, AUTOINCREMENT

订单明细ID(主键,自增)

order_id

INTEGER

NOT NULL, FOREIGN KEY REFERENCES orders(order_id)

订单ID(外键,非空)

product_id

INTEGER

NOT NULL, FOREIGN KEY REFERENCES products(product_id)

商品ID(外键,非空)

quantity

INTEGER

NOT NULL

数量(非空)

unit_price

DECIMAL(10,2)

NOT NULL

单价(非空)

subtotal

DECIMAL(10,2)

NOT NULL

小计(非空)

5. 员工表 (employees)

字段名

数据类型

约束/说明

中文说明

employee_id

INTEGER

PRIMARY KEY, AUTOINCREMENT

员工ID(主键,自增)

username

VARCHAR(50)

UNIQUE, NOT NULL

用户名(唯一,非空)

password_hash

VARCHAR(255)

NOT NULL

密码哈希值(非空)

full_name

VARCHAR(100)

NOT NULL

姓名(非空)

role

TEXT

CHECK: IN ('admin', 'cashier', 'manager'), NOT NULL

角色(管理员/收银员/经理,非空)

contact_number

VARCHAR(20)

联系电话

email

VARCHAR(100)

邮箱

is_active

BOOLEAN

DEFAULT 1

是否激活(默认是)

6. 客户表 (customers)

字段名

数据类型

约束/说明

中文说明

customer_id

INTEGER

PRIMARY KEY, AUTOINCREMENT

客户ID(主键,自增)

customer_name

VARCHAR(100)

NOT NULL

客户姓名(非空)

phone_number

VARCHAR(20)

电话号码

email

VARCHAR(100)

邮箱

membership_level

TEXT

CHECK: IN ('regular', 'silver', 'gold'), DEFAULT 'regular'

会员等级(普通/银卡/金卡,默认普通)

points

INTEGER

DEFAULT 0

积分(默认0)

created_at

TIMESTAMP

DEFAULT CURRENT_TIMESTAMP

创建时间(默认当前时间)

7. 库存交易记录表 (inventory_transactions)

字段名

数据类型

约束/说明

中文说明

transaction_id

INTEGER

PRIMARY KEY, AUTOINCREMENT

库存记录ID(主键,自增)

product_id

INTEGER

NOT NULL, FOREIGN KEY REFERENCES products(product_id)

商品ID(外键,非空)

transaction_type

TEXT

CHECK: IN ('in', 'out'), NOT NULL

交易类型(入库/出库,非空)

quantity

INTEGER

NOT NULL

数量(非空)

transaction_date

TIMESTAMP

DEFAULT CURRENT_TIMESTAMP

交易日期(默认当前时间)

notes

TEXT

备注

employee_id

INTEGER

NOT NULL, FOREIGN KEY REFERENCES employees(employee_id)

员工ID(外键,非空)

8. 积分历史表 (points_history)

字段名

数据类型

约束/说明

中文说明

history_id

INTEGER

PRIMARY KEY, AUTOINCREMENT

积分历史ID(主键,自增)

customer_id

INTEGER

NOT NULL, FOREIGN KEY REFERENCES customers(customer_id)

客户ID(外键,非空)

points_change

INTEGER

NOT NULL

积分变动(非空)

notes

TEXT

备注

created_at

TIMESTAMP

DEFAULT CURRENT_TIMESTAMP

创建时间(默认当前时间)

约束说明

  • PRIMARY KEY: 主键,唯一标识每一行
  • AUTOINCREMENT: 自动递增,通常用于主键
  • UNIQUE: 唯一约束,确保字段值不重复
  • NOT NULL: 非空约束,确保字段值不能为空
  • FOREIGN KEY: 外键,用于关联其他表
  • CHECK: 检查约束,确保字段值符合指定条件
  • DEFAULT: 默认值,当未提供字段值时使用默认值

代码: 

main.py

import sys
import warnings
from PySide6.QtWidgets import QApplication, QDialog
from views.main_window import MainWindow
from views.login_window import LoginDialog
from database.db_manager import DatabaseManager


# 添加警告过滤
warnings.filterwarnings("ignore", message="zbar.*")

def load_stylesheet(filename):
    with open(filename, "r", encoding='utf-8') as f:
        return f.read()

def main():
    # 创建应用程序实例
    app = QApplication(sys.argv)
    
    # 应用 Fluent UI 风格
    app.setStyle("Fusion")
    # 加载 QSS 文件
    stylesheet = load_stylesheet("style/style.qss")
    app.setStyleSheet(stylesheet)
    
    # 初始化数据库管理器
    db_manager = DatabaseManager()
    
    # 创建并显示登录窗口
    login_dialog = LoginDialog(db_manager)
    if login_dialog.exec() == QDialog.Accepted:
        # 登录成功,创建并显示主窗口
        window = MainWindow(db_manager)
        window.handle_login_success(login_dialog.user_info)  # 传递用户信息
        window.show()
        return app.exec()
    else:
        # 登录失败或取消,直接退出程序
        return 0

if __name__ == '__main__':
    sys.exit(main())

db_manager.py

import sqlite3
from datetime import datetime
import os
import random
import hashlib

class DatabaseManager:
    def __init__(self, db_path="db/pos_system.db"):
        # 确保数据库目录存在
        os.makedirs(os.path.dirname(db_path), exist_ok=True)
        self.db_path = db_path
        self.create_tables()

    def get_connection(self):
        return sqlite3.connect(self.db_path)

    def create_tables(self):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            
            # 创建商品表 (products)
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS products (
                    product_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    product_code VARCHAR(50) UNIQUE NOT NULL,
                    product_name VARCHAR(100) NOT NULL,
                    category_id INTEGER,
                    unit_price DECIMAL(10,2) NOT NULL,
                    stock_quantity INTEGER NOT NULL DEFAULT 0,
                    image_path TEXT,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    FOREIGN KEY (category_id) REFERENCES categories(category_id)
                )
            ''')

            # 创建商品类别表 (categories)
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS categories (
                    category_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    category_name VARCHAR(50) NOT NULL,
                    description TEXT
                )
            ''')

            # 创建订单表 (orders)
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS orders (
                    order_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    order_number VARCHAR(50) UNIQUE NOT NULL,
                    customer_id INTEGER,
                    employee_id INTEGER NOT NULL,
                    order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    total_amount DECIMAL(10,2) NOT NULL,
                    payment_method TEXT CHECK(payment_method IN ('现金', '微信', '支付宝')) NOT NULL,
                    status TEXT CHECK(status IN ('完成', '取消', '已退款')) DEFAULT '完成',
                    FOREIGN KEY (customer_id) REFERENCES customers(customer_id),
                    FOREIGN KEY (employee_id) REFERENCES employees(employee_id)
                )
            ''')

            # 创建订单明细表 (order_details)
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS order_details (
                    order_detail_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    order_id INTEGER NOT NULL,
                    product_id INTEGER NOT NULL,
                    quantity INTEGER NOT NULL,
                    unit_price DECIMAL(10,2) NOT NULL,
                    subtotal DECIMAL(10,2) NOT NULL,
                    FOREIGN KEY (order_id) REFERENCES orders(order_id),
                    FOREIGN KEY (product_id) REFERENCES products(product_id)
                )
            ''')

            # 创建员工表 (employees)
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS employees (
                    employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    username VARCHAR(50) UNIQUE NOT NULL,
                    password_hash VARCHAR(255) NOT NULL,
                    full_name VARCHAR(100) NOT NULL,
                    role TEXT CHECK(role IN ('admin', 'cashier', 'manager')) NOT NULL,
                    contact_number VARCHAR(20),
                    email VARCHAR(100),
                    is_active BOOLEAN DEFAULT 1
                )
            ''')

            # 创建客户表 (customers)
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS customers (
                    customer_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    customer_name VARCHAR(100) NOT NULL,
                    phone_number VARCHAR(20),
                    email VARCHAR(100),
                    membership_level TEXT CHECK(membership_level IN ('普通', 'Vip', '黄金Vip')) DEFAULT '普通',
                    points INTEGER DEFAULT 0,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            ''')

            # 创建库存交易记录表 (inventory_transactions)
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS inventory_transactions (
                    transaction_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    product_id INTEGER NOT NULL,
                    transaction_type TEXT CHECK(transaction_type IN ('in', 'out')) NOT NULL,
                    quantity INTEGER NOT NULL,
                    transaction_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    notes TEXT,
                    employee_id INTEGER NOT NULL,
                    FOREIGN KEY (product_id) REFERENCES products(product_id),
                    FOREIGN KEY (employee_id) REFERENCES employees(employee_id)
                )
            ''')

            # 创建积分历史表 (points_history)
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS points_history (
                    history_id INTEGER PRIMARY KEY AUTOINCREMENT,
                    customer_id INTEGER NOT NULL,
                    points_change INTEGER NOT NULL,
                    notes TEXT,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
                )
            ''')

            # 创建触发器:更新商品的更新时间
            cursor.execute('''
                CREATE TRIGGER IF NOT EXISTS update_product_timestamp
                AFTER UPDATE ON products
                BEGIN
                    UPDATE products SET updated_at = CURRENT_TIMESTAMP
                    WHERE product_id = NEW.product_id;
                END
            ''')

            # 添加默认管理员账号
            cursor.execute('SELECT COUNT(*) FROM employees')
            if cursor.fetchone()[0] == 0:
                # 默认密码: admin123
                default_password = hashlib.sha256('admin123'.encode()).hexdigest()
                cursor.execute('''
                    INSERT INTO employees (username, password_hash, full_name, role)
                    VALUES (?, ?, ?, ?)
                ''', ('admin', default_password, '系统管理员', 'admin'))
                
                # 添加默认收银员账号
                cashier_password = hashlib.sha256('cashier123'.encode()).hexdigest()
                cursor.execute('''
                    INSERT INTO employees (username, password_hash, full_name, role)
                    VALUES (?, ?, ?, ?)
                ''', ('cashier', cashier_password, '收银员', 'cashier'))

            conn.commit()

    def add_product(self, product_code, product_name, category_id, unit_price, stock_quantity=0, image_path=None):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute('''
                INSERT INTO products (product_code, product_name, category_id, unit_price, stock_quantity, image_path)
                VALUES (?, ?, ?, ?, ?, ?)
            ''', (product_code, product_name, category_id, unit_price, stock_quantity, image_path))
            return cursor.lastrowid

    def get_all_products(self):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute('''
                SELECT p.*, c.category_name 
                FROM products p 
                LEFT JOIN categories c ON p.category_id = c.category_id
            ''')
            return cursor.fetchall()

    def get_product_by_code(self, product_code):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute('SELECT * FROM products WHERE product_code = ?', (product_code,))
            return cursor.fetchone()

    def update_product(self, product_id, **kwargs):
        """更新商品信息"""
        allowed_fields = {
            'product_code', 'product_name', 'category_id',
            'unit_price', 'stock_quantity', 'image_path'
        }
        update_fields = {k: v for k, v in kwargs.items() if k in allowed_fields}
        
        if not update_fields:
            return False
            
        query = 'UPDATE products SET ' + ', '.join(f'{k} = ?' for k in update_fields.keys())
        query += ' WHERE product_id = ?'
        
        with self.get_connection() as conn:
            cursor = conn.cursor()
            try:
                cursor.execute(query, list(update_fields.values()) + [product_id])
                return cursor.rowcount > 0
            except Exception as e:
                conn.rollback()
                raise e

    def delete_product(self, product_id):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute('DELETE FROM products WHERE product_id = ?', (product_id,))
            return cursor.rowcount > 0

    def add_category(self, category_name, description=None):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute('''
                INSERT INTO categories (category_name, description)
                VALUES (?, ?)
            ''', (category_name, description))
            return cursor.lastrowid

    def get_all_categories(self):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute('SELECT * FROM categories')
            return cursor.fetchall()

    def update_category(self, category_id, category_name=None, description=None):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            update_fields = []
            params = []
            
            if category_name is not None:
                update_fields.append('category_name = ?')
                params.append(category_name)
            if description is not None:
                update_fields.append('description = ?')
                params.append(description)
                
            if not update_fields:
                return False
                
            params.append(category_id)
            query = f'UPDATE categories SET {", ".join(update_fields)} WHERE category_id = ?'
            cursor.execute(query, params)
            return cursor.rowcount > 0

    def delete_category(self, category_id):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            # 检查是否有商品使用此类别
            cursor.execute('SELECT COUNT(*) FROM products WHERE category_id = ?', (category_id,))
            if cursor.fetchone()[0] > 0:
                return False
            cursor.execute('DELETE FROM categories WHERE category_id = ?', (category_id,))
            return cursor.rowcount > 0

    def add_employee(self, username, password_hash, full_name, role, contact_number=None, email=None):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute('''
                INSERT INTO employees (username, password_hash, full_name, role, contact_number, email)
                VALUES (?, ?, ?, ?, ?, ?)
            ''', (username, password_hash, full_name, role, contact_number, email))
            return cursor.lastrowid

    def get_all_employees(self):
        with self.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute('SELECT * FROM employees')
            return cursor.fetchall()

    def update_employee(self, employee_id, **kwargs):
        allowed_fields = {'username', 'password_hash', &

http://www.kler.cn/a/465055.html

相关文章:

  • JAVA类和对象练习
  • Tableau数据可视化与仪表盘搭建-安装教程
  • Cursor连接腾讯云Cloud Studio开发环境
  • Windows平台下如何手动安装MYSQL
  • PostgreSQL对称between比较运算
  • [CTF/网络安全] 攻防世界 simple_php 解题详析
  • Postman[8] 断言
  • edeg插件/扩展推荐:助力生活工作
  • 【视频笔记】基于PyTorch从零构建多模态(视觉)大模型 by Umar Jamil【持续更新】
  • CM3/CM4时钟系统
  • STM32-笔记28-蓝牙模块
  • SQL 总结
  • 125个Docker的常用命令
  • 数据库-MySQL-limit优化(全面 易理解)
  • 小米15震撼发布:手机吊起一人一椅,创新极限测试
  • 基于微信小程序的面部动作检测
  • 百度二面,MySQL 怎么做权重搜索?
  • SQL 中的 EXISTS
  • 开源自荐 - NoteGen 一款专注于记录和写作的跨端 AI 笔记
  • Web3的核心理念:去中心化如何改变互联网结构
  • Linux和ROS(Robot Operating System)在底层实现上的差异
  • 记一次 dockerfile 的循环依赖错误
  • 【three.js】场景搭建
  • [极客大挑战 2019]Secret File
  • 小程序组件 —— 22 组件案例 - 轮播区域绘制
  • Ansible Jinja2 语法简介及使用