理发店收银管理系统 python、sqlite3、pyqt5

给姐姐家店写的一个,功能比较简单,结合gpt

功能包含:次卡和充值卡,可以查剩余次数、以及查找消费记录

···后期会把sqlite3转到mysql,换成springboot的一个项目

1.使用技术:

Python、sqlite3、PyQt5

2.页面

3.sqlite3

一共三张数据表:

  • user_card : 次卡数据
  • user_store : 储蓄卡
  • consumption: 消费记录表
    消费记录为了省事,包含了所有的记录,

4.代码(主要部分)

python 复制代码
import re
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, \
    QTableWidget, QTableWidgetItem, QHeaderView, QMessageBox, QDialog, QFormLayout, QInputDialog, QMainWindow
from PyQt5.QtGui import QColor, QPalette, QImage, QPixmap, QBrush, QPainter
from PyQt5.QtCore import Qt, QDate, QDateTime
import sqlite3


class BackgroundWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        # self.image_path = "image/background.png"
        self.image_path = "image/panda.png"

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        # 绘制背景图片
        background_image = QImage(self.image_path)
        background_image = background_image.scaled(self.size(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
        painter.drawImage(0, 0, background_image)

        # 绘制半透明遮罩层
        opacity = 0.6
        overlay_color = QColor(0, 0, 0, int(255 * opacity))
        painter.setCompositionMode(QPainter.CompositionMode_DestinationOver)
        painter.fillRect(self.rect(), overlay_color)

        super().paintEvent(event)


class ConsumeCard(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("理发店收银系统")
        self.resize(1200, 800)

        # 创建数据库连接
        self.connection = sqlite3.connect("db/barbershop.db")
        self.cursor = self.connection.cursor()

        # 创建界面控件
        self.id_label = QLabel("ID:")
        self.id_input = QLineEdit()
        self.name_label = QLabel("姓名:")
        self.name_input = QLineEdit()
        self.tel_label = QLabel("电话:")
        self.tel_input = QLineEdit()
        self.remain_label = QLabel("次数:")
        self.remain_input = QLineEdit()
        self.remark_label = QLabel("备注:")
        self.remark_input = QLineEdit()
        # self.discount_label = QLabel("折扣:")
        # self.discount_input = QLineEdit()

        self.create_user_button = QPushButton("新建用户")
        self.search_label = QLabel("查询(ID或电话):")
        self.search_input = QLineEdit()
        self.search_button = QPushButton("查询")
        self.clear_button = QPushButton("清除")
        self.recharge_button = QPushButton("充值")
        self.consume_button = QPushButton("消费")
        # self.record_button = QPushButton("消费记录")
        self.consumption_record_button = QPushButton("消费记录")

        self.user_table = QTableWidget()

        # 设置布局
        form_layout = QFormLayout()
        # form_layout.addRow(self.id_label, self.id_input)
        form_layout.addRow(self.name_label, self.name_input)
        form_layout.addRow(self.tel_label, self.tel_input)
        form_layout.addRow(self.remain_label, self.remain_input)
        form_layout.addRow(self.remark_label, self.remark_input)
        # form_layout.addRow(self.discount_label, self.discount_input)

        button_layout = QHBoxLayout()
        button_layout.addWidget(self.create_user_button)
        button_layout.addWidget(self.search_label)
        button_layout.addWidget(self.search_input)
        button_layout.addWidget(self.search_button)
        button_layout.addWidget(self.clear_button)
        button_layout.addWidget(self.recharge_button)
        button_layout.addWidget(self.consume_button)
        button_layout.addWidget(self.consumption_record_button)

        main_layout = QVBoxLayout()
        main_layout.addLayout(form_layout)
        main_layout.addLayout(button_layout)
        main_layout.addWidget(self.user_table)

        self.setLayout(main_layout)

        # 绑定信号与槽函数
        self.create_user_button.clicked.connect(self.create_user)
        self.search_button.clicked.connect(self.search_user)
        self.clear_button.clicked.connect(self.clear)
        self.recharge_button.clicked.connect(self.recharge)
        self.consume_button.clicked.connect(self.consume)
        # self.record_button.clicked.connect(self.show_consumption_records)
        self.consumption_record_button.clicked.connect(self.show_consumption_record)


        # 初始化用户表格
        self.init_user_table()

        # 当前选中的用户信息
        self.current_user = None

        background_widget = BackgroundWidget()
        background_widget.setLayout(main_layout)
        self.setCentralWidget(background_widget)

        self.setAttribute(Qt.WA_TranslucentBackground)  # 设置窗口背景透明

        # 设置样式
        self.setStyleSheet(
            
        )

    def set_background_image(self, image_path):
        background_image = QImage(image_path)
        background_image = background_image.scaled(self.size(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
        palette = QPalette()
        palette.setBrush(QPalette.Background, QBrush(background_image))
        self.setPalette(palette)

    def init_user_table(self):
        self.user_table.setColumnCount(5)
        self.user_table.setHorizontalHeaderLabels(["ID", "姓名", "电话", "剩余次数", "备注"])
        self.user_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.user_table.setSelectionBehavior(QTableWidget.SelectRows)
        self.user_table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.user_table.cellClicked.connect(self.show_user_info)

        self.update_user_table()

    def update_user_table(self):
        self.user_table.clearContents()
        self.cursor.execute("SELECT id, name, tel, remain, remark FROM user_card")
        users = self.cursor.fetchall()
        self.user_table.setRowCount(len(users))
        for i, user in enumerate(users):
            for j in range(len(user)):
                item = QTableWidgetItem(str(user[j]))
                item.setTextAlignment(Qt.AlignCenter)
                self.user_table.setItem(i, j, item)

    def show_user_info(self, row):
        self.id_input.setText(self.user_table.item(row, 0).text())
        self.name_input.setText(self.user_table.item(row, 1).text())
        self.tel_input.setText(self.user_table.item(row, 2).text())
        self.remain_input.setText(self.user_table.item(row, 3).text())
        self.remark_input.setText(self.user_table.item(row, 4).text())
        # self.discount_input.setText(self.user_table.item(row, 5).text())

        # 存储选中的用户信息
        self.current_user = {
            'id': self.user_table.item(row, 0).text(),
            'name': self.user_table.item(row, 1).text(),
            'tel': self.user_table.item(row, 2).text(),
            'remain': self.user_table.item(row, 3).text(),
            'remark': self.user_table.item(row, 4).text(),
            # 'discount': self.user_table.item(row, 5).text()
        }

    def create_user(self):
        name = self.name_input.text()
        tel = self.tel_input.text()
        remain = self.remain_input.text()
        remark = self.remark_input.text()
        # discount = self.discount_input.text()

        if not name or not tel or not remain:
            QMessageBox.warning(self, "错误", "请填写完整用户信息")
            return

        try:
            remain = int(remain)
            # discount = float(discount)
        except ValueError:
            QMessageBox.warning(self, "错误", "次数必须是数字")
            return

        # 验证手机号格式
        if not self.validate_phone_number(tel):
            QMessageBox.warning(self, "错误", "手机号格式错误")
            return

        # 检查是否已经存在该手机号的用户
        self.cursor.execute("SELECT id FROM user_card WHERE tel = ?", (tel,))
        existing_user = self.cursor.fetchone()
        if existing_user:
            QMessageBox.warning(self, "错误", "已存在该用户手机号")
            return


        current_datetime = QDateTime.currentDateTime()
        formatted_datetime = current_datetime.toString(Qt.ISODate)
        formatted_datetime = formatted_datetime[:10] + " " + formatted_datetime[11:]
        self.cursor.execute("INSERT INTO consumption_record (name, tel, consumption, balance, consumption_time, remark) "
                            "VALUES (?, ?, ?, ?, ?, ?)",
                            (name, tel, remain, remain, formatted_datetime, remark))
        self.cursor.execute("INSERT INTO user_card (name, tel, remain, remark) "
                            "VALUES (?, ?, ?, ?)",
                            (name, tel, remain, remark))
        self.connection.commit()
        self.update_user_table()
        self.clear()

        QMessageBox.information(self, "成功", "用户创建成功")

    # 验证手机号
    def validate_phone_number(self, phone_number):
        pattern = r"^1[3-9]\d{9}$"
        return re.match(pattern, phone_number) is not None

    def search_user(self):
        keyword = self.search_input.text()
        self.cursor.execute(
            "SELECT id, name, tel, remain, remark  FROM user_card WHERE id LIKE ? OR name like ? OR tel LIKE ?",
            (f"%{keyword}%", f"%{keyword}%", f"%{keyword}%"))
        users = self.cursor.fetchall()
        if len(users) == 0:
            QMessageBox.warning(self, "错误", "未找到用户")
            return

        self.user_table.clearContents()
        self.user_table.setRowCount(len(users))
        for i, user in enumerate(users):
            for j in range(len(user)):
                item = QTableWidgetItem(str(user[j]))
                item.setTextAlignment(Qt.AlignCenter)
                self.user_table.setItem(i, j, item)

    def clear(self):
        self.id_input.clear()
        self.name_input.clear()
        self.tel_input.clear()
        self.remain_input.clear()
        self.remark_input.clear()
        # self.discount_input.clear()
        self.user_table.clearSelection()

        # 重置当前选中的用户信息
        self.current_user = None

    def recharge(self):
        if self.current_user is None:
            QMessageBox.warning(self, "错误", "请先选择用户")
            return

        id = self.current_user['id']
        name = self.current_user['name']
        tel = self.current_user['tel']
        remain = self.current_user['remain']
        remark = self.current_user['remark']

        # amount, ok = QInputDialog.getDouble(self, "充值", "请输入充值次数:", decimals=2)
        amount, ok = QInputDialog.getInt(self, "充值", "请输入充值次数:")
        if ok and amount > 0:
            self.cursor.execute("UPDATE user_card SET remain = remain + ? WHERE id = ?", (amount, id))
            try:
                remain = int(remain)
                amount = int(amount)
            except ValueError:
                QMessageBox.warning(self, "错误", "余额和折扣必须是数字")
                return
            current_datetime = QDateTime.currentDateTime()
            formatted_datetime = current_datetime.toString(Qt.ISODate)
            formatted_datetime = formatted_datetime[:10] + " " + formatted_datetime[11:]
            self.cursor.execute("INSERT INTO consumption_record (name, tel, consumption, balance, consumption_time, remark) "
                                "VALUES (?, ?, ?, ?, ?, ?)",
                                (name, tel, amount, remain + amount, formatted_datetime, remark))
            self.connection.commit()
            self.update_user_table()
            self.clear()
            QMessageBox.information(self, "成功", "充值成功")

        # 重置当前选中的用户信息
        self.current_user = None

    def consume(self):
        if self.current_user is None:
            QMessageBox.warning(self, "错误", "请先选择用户")
            return

        id = self.current_user['id']
        name = self.current_user['name']
        tel = self.current_user['tel']
        remain = self.current_user['remain']
        remark = self.current_user['remark']

        # amount, ok = QInputDialog.getDouble(self, "消费", "请输入消费金额:", decimals=2)
        amount, ok = QInputDialog.getInt(self, "消费", "请输入消费金额:")
        if ok and amount > 0:
            # self.cursor.execute("SELECT discount FROM user_card WHERE id = ?", (id,))
            # discount = self.cursor.fetchone()[0]

            try:
                remain = int(remain)
                # discount = float(discount)
                amount = int(amount)
            except ValueError:
                QMessageBox.warning(self, "错误", "余额和折扣必须是数字")
                return

            # amount *= discount
            if remain < amount:
                QMessageBox.warning(self, "错误", "余额不足")
                return

            self.cursor.execute("UPDATE user_card SET remain = remain - ? WHERE id = ?", (amount, id))
            current_datetime = QDateTime.currentDateTime()
            formatted_datetime = current_datetime.toString(Qt.ISODate)
            formatted_datetime = formatted_datetime[:10] + " " + formatted_datetime[11:]
            self.cursor.execute(
                "INSERT INTO consumption_record (name, tel, consumption, balance, consumption_time, remark) "
                "VALUES (?, ?, ?, ?, ?, ?)",
                (name, tel, -amount, remain - amount, formatted_datetime, remark))
            self.connection.commit()
            self.update_user_table()
            self.clear()
            QMessageBox.information(self, "成功", "消费成功")

        # 重置当前选中的用户信息
        self.current_user = None


    def show_consumption_record(self):
        if self.current_user is None:
            QMessageBox.warning(self, "错误", "请先选择用户")
            return

        tel = self.current_user['tel']
        self.cursor.execute(
            "SELECT id, name, tel, consumption, balance, consumption_time, remark FROM consumption_record WHERE tel = ?",
            (tel,))
        records = self.cursor.fetchall()

        dialog = QDialog(self)
        dialog.setWindowTitle("消费记录")
        dialog.resize(1400, 600)

        table = QTableWidget(dialog)
        table.setColumnCount(6)
        table.setHorizontalHeaderLabels(["姓名", "电话", "消费", "剩余次数", "消费时间", "备注"])
        table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        table.setSelectionBehavior(QTableWidget.SelectRows)
        table.setEditTriggers(QTableWidget.NoEditTriggers)
        table.setRowCount(len(records))

        for i, record in enumerate(records):
            for j in range(1, len(record)):
                item = QTableWidgetItem(str(record[j]))
                item.setTextAlignment(Qt.AlignCenter)
                table.setItem(i, j - 1, item)

        main_layout = QVBoxLayout()
        main_layout.addWidget(table)
        dialog.setLayout(main_layout)

        dialog.exec_()

    # def get_consumption_records(self, phone_number):
    #     self.cursor.execute("SELECT * FROM consumption_record WHERE tel=?",
    #                         (phone_number,))
    #     return self.cursor.fetchall()

    def closeEvent(self, event):
        self.connection.close()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    cashier = ConsumeCard()
    cashier.show()
    sys.exit(app.exec_())
相关推荐
nuclear20111 小时前
使用Python 在Excel中创建和取消数据分组 - 详解
python·excel数据分组·创建excel分组·excel分类汇总·excel嵌套分组·excel大纲级别·取消excel分组
Lucky小小吴1 小时前
有关django、python版本、sqlite3版本冲突问题
python·django·sqlite
GIS 数据栈1 小时前
每日一书 《基于ArcGIS的Python编程秘笈》
开发语言·python·arcgis
爱分享的码瑞哥2 小时前
Python爬虫中的IP封禁问题及其解决方案
爬虫·python·tcp/ip
Mr.Q2 小时前
OpenCV和Qt坐标系不一致问题
qt·opencv
傻啦嘿哟3 小时前
如何使用 Python 开发一个简单的文本数据转换为 Excel 工具
开发语言·python·excel
B站计算机毕业设计超人3 小时前
计算机毕业设计SparkStreaming+Kafka旅游推荐系统 旅游景点客流量预测 旅游可视化 旅游大数据 Hive数据仓库 机器学习 深度学习
大数据·数据仓库·hadoop·python·kafka·课程设计·数据可视化
IT古董3 小时前
【人工智能】Python在机器学习与人工智能中的应用
开发语言·人工智能·python·机器学习
湫ccc4 小时前
《Python基础》之pip换国内镜像源
开发语言·python·pip
hakesashou4 小时前
Python中常用的函数介绍
java·网络·python