목차
- 개발환경
- 개발완료보고서
- 요구사항 세부내역
- 순서도
- 일정표
- 파일 첨부
- 실행화면
- 코드 전문
개발환경
- 운영체제: Window OS
- 개발언어: Python
- 개발 툴: Pycharm
- DBSM: SQLite
- 추가 패키지: PyQt
개발완료 보고서
일정표
요구사항분석서
순서도
파일 첨부
실행화면
코드 전문
mega_kiosk_ver1
import os
import sys
import ast
import sqlite3
import datetime
import pandas as pd
from random import randint
from PyQt5 import uic
from PyQt5.QtGui import *
import shopping_cart
from shopping_cart import *
from manager_page import *
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
def resource_path(relative_path):
"""UI 받아오는 함수"""
base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, relative_path)
# UI 불러오기
main_page_class = uic.loadUiType(resource_path('./UI/mega_ui_ver3.ui'))[0] # 메가 메인 UI 불러오기
choose_option_class = uic.loadUiType(resource_path('./UI/mega_choose_option_page.ui'))[0] # 메가 음료옵션창 불러오기
msg_box_class = uic.loadUiType(resource_path('./UI/msg_box.ui'))[0] # 메세지박스 ui 불러오기
point_page_class = uic.loadUiType(resource_path('./UI/point_page.ui'))[0] # 포인트페이지 창 띄우기
manager_page_class = uic.loadUiType(resource_path('./UI/manager_page.ui'))[0] # 관리자페이지
receipt_page = uic.loadUiType(resource_path('./UI/receipt_page_2.ui'))[0] # 영수증 창
# main_page_ui = resource_path('./UI/mega_ui_ver3.ui')
# choose_option_ui = resource_path('./UI/mega_choose_option_page.ui')
# msg_box_ui = resource_path('./UI/msg_box.ui')
# point_page_ui = resource_path('./UI/point_page.ui')
# manager_page_ui = resource_path('./UI/manager_page.ui')
class Rept(QDialog, receipt_page):
"""영수증"""
def __init__(self, parent, order_num, t_price):
super().__init__()
self.setupUi(self)
self.parent = parent
self.order_number_label.setText(str(order_num))
self.total_price_label.setText(str(t_price))
self.set_datetime()
self.parent.fill_the_table_widget(self.tableWidget)
def set_datetime(self):
now = datetime.datetime.now()
formatted_now = now.strftime("%Y-%m-%d %H:%M:%S")
self.date_label.setText(str(formatted_now))
class Point_Page(QDialog, point_page_class):
"""포인트 적립 창"""
data_signal = pyqtSignal(str)
def __init__(self):
super().__init__()
self.setupUi(self)
# 화면 설정
self.setWindowFlags(
Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint) # 프레임 지우기 / 윈도우가 다른 창 위에 항상 최상위로 유지되도록 함
self.setAttribute(Qt.WA_TranslucentBackground, True) # 배경 투명하게 함
# 버튼 모으기
buttons = self.point_buttons.findChildren(QPushButton)
for button in buttons:
button.clicked.connect(self.write_point_num)
# 버튼 시그널 설정
self.point_confirm_btn.clicked.connect(self.point_check) # 확인 버튼
self.cancel_btn.clicked.connect(self.close) # x 버튼
def write_point_num(self):
"""번호를 누르면 번호창에 업데이트 된다"""
num_list = [str(num) for num in range(0, 10)] # 버튼은 0부터 010까지 존재함
num_list.append('010')
self.user_num = []
btn_name = self.sender().text() # 누른 버튼 텍스트 가져옴
now_label_text = self.user_number_label.text() # 라벨의 텍스트 가져옴
if btn_name in num_list:
now_label_text += str(btn_name)
self.only_num = now_label_text.replace('-', '')
self.user_num.append(self.user_num.append(btn_name))
print('누를때', self.user_num)
if len(self.only_num) <= 11:
self.user_number_label.setText(self.mask_numbers(now_label_text))
else:
self.user_num = self.user_num[:-1]
print('지울때', self.user_num)
now_label_text = now_label_text[:-1]
self.user_number_label.setText(self.mask_numbers(now_label_text))
def mask_numbers(self, i):
i = i.replace('-', '')
if len(i) <= 3:
return i
elif 3 < len(i) < 8:
return f'{i[:3]}-{(len(i) - 3) * "*"}'
else:
return i[:3] + '-****-' + i[7:]
def point_check(self):
now_label_text = self.user_number_label.text() # 라벨의 텍스트 가져옴
if len(now_label_text) == 11:
self.data_signal.emit(now_label_text)
self.close()
else:
self.close()
con = sqlite3.connect('./DATA/data.db')
df = pd.read_sql('select * from order_table', con)
df.loc[:, 'customer_id'] = self.user_num
df.to_sql('order_table', con, if_exists='replace', index=False)
con.commit()
con.close()
print('포인트 적립 확인')
lass MSG_Dialog(QDialog, msg_box_class):
"""메세지 박스 다이얼로그"""
data_signal = pyqtSignal(str)
def __init__(self, parent, page_data):
super().__init__(parent)
self.parent = parent
self.setupUi(self)
# 화면 설정
self.setWindowFlags(
Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint) # 프레임 지우기 / 윈도우가 다른 창 위에 항상 최상위로 유지되도록 함
self.setAttribute(Qt.WA_TranslucentBackground, True) # 배경 투명하게 함
self.sign = page_data
self.stackedWidget.setCurrentWidget(self.one_btn_page)
# 버튼 페이지 설정
if page_data == 1:
self.info_label.setText("메뉴가 품절이라 선택하실 수 없습니다.")
elif page_data == 2:
self.info_label.setText("메뉴를 1개 이상 선택하셔야 합니다.")
elif page_data == 3:
self.info_label.setText(f"결제중입니다.. 5초 후에 창이 닫힙니다.")
self.remain_time = 5
self.p_timer = QTimer()
self.p_timer.timeout.connect(self.update_p_timer)
self.p_timer.setInterval(1000)
self.p_timer.start()
elif page_data == 4:
self.info_label.setText("포인트 적립을 하시겠습니까?")
self.stackedWidget.setCurrentWidget(self.two_btn_page)
elif page_data == 5:
self.info_label.setText("회원정보가 사라집니다. 계속하시겠습니까?")
self.stackedWidget.setCurrentWidget(self.two_btn_page)
elif page_data == 6:
self.info_label.setText("유효한 카드번호가 아닙니다. 다시 입력하세요.")
elif page_data == 7:
self.info_label.setText("이미 KT할인이 적용되었습니다.")
elif page_data == 8:
self.info_label.setText("영수증 출력을 하시겠습니까?")
self.stackedWidget.setCurrentWidget(self.two_btn_page)
else:
pass
# 버튼 누르면 정보 넘겨주기
self.ok_btn.clicked.connect(self.check_and_close) # 확인 누르면 확인하고 창 닫힘
self.no_btn.clicked.connect(self.check_no_btn_and_close) # 취소 누르면 창 닫힘
self.yes_btn.clicked.connect(self.show_num_keypad)
def check_and_close(self):
print('닫기를 탐')
if self.sign == 8:
print('영수증 드릴게')
else:
self.close()
def check_no_btn_and_close(self):
if self.sign == 4:
print('여기서 오픈 페이지로 바뀝니다. 그리고 데이터 삭제해야 함')
self.close()
msg_box_page = MSG_Dialog(self.parent, 8) # 포인트 창이 뜨고
msg_box_page.exec_()
if self.sign == 8:
self.close()
self.parent.stackedWidget.setCurrentWidget(self.parent.opening_page)
self.parent.timer.start()
self.parent.delete_order_table_values() # 테이블 내용 삭제
else:
self.close()
def update_p_timer(self):
self.remain_time -= 1
if self.remain_time == 0: # 시간이 종료되면
self.p_timer.stop() # 타이머가 멈추고
self.close()
self.show_point_msg_box()
self.info_label.setText(f"결제중입니다.. {self.remain_time}초 후에 창이 닫힙니다.")
def show_point_msg_box(self):
msg_box_page = MSG_Dialog(self.parent, 4) # 포인트 창이 뜨고
msg_box_page.exec_()
def show_num_keypad(self):
"""숫자패드 창 띄우기"""
if not self.sign == 8:
self.close()
key_page = Point_Page()
key_page.data_signal.connect(self.get_label_text)
key_page.show()
key_page.exec_()
else:
self.parent.order_num += 1 # 주문번호 늘리기
rept = Rept(self.parent, self.parent.order_num, self.parent.get_total_price() )
rept.show()
rept.exec_()
self.close()
self.parent.stackedWidget.setCurrentWidget(self.parent.opening_page)
self.parent.timer.start()
self.parent.delete_order_table_values() # 테이블 내용 삭제
class Option_Class(QDialog, choose_option_class):
"""선택옵션 창"""
data_signal = pyqtSignal(str)
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.setupUi(self)
# 화면 설정
self.setWindowFlags(
Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint) # 프레임 지우기 / 윈도우가 다른 창 위에 항상 최상위로 유지되도록 함
self.setAttribute(Qt.WA_TranslucentBackground, True) # 배경 투명하게 함
self.move(30, 40) # 창 이동
# 가격 이름 메뉴정보 불러오기
data = parent.send_info
self.drink_name = data['menu_name_x'].to_string(index=False)
self.drink_price = data['price'].to_string(index=False)
self.drink_info = data['info'].to_string(index=False)
# 정보 담기
self.menu_photo_label.setPixmap(QPixmap(data['img_path'].to_string(index=False))) # 메뉴 이미지
self.menu_name_label.setText(str(self.drink_name)) # 메뉴 이름
self.menu_info_label.setText(str(self.drink_info)) # 메뉴 정보
self.menu_price_label.setText(str(self.drink_price) + '원') # 메뉴 가격
# 옵션 위한 테이블 생성
option_df = data.loc[:, 'cinnamon':'zero_cider_changed']
option_df_dict = option_df.to_dict('list')
option_df_keys = list(option_df_dict.keys())
option_df_keys.append('decaffein')
print(option_df_keys)
option_df_dict_not_null = {key: [int(x) for x in value[0].split(',')] for key, value in option_df_dict.items()
if value != ['0']} # 0이 들어가지 않은 인수형의 숫자 반환
if '디카페인' in self.drink_name: # 디카페인은 db에서 분리를안해서 후작업
option_df_dict_not_null['decaffein'] = 1
del option_df_dict_not_null['strong_or_weak']
# 음료에 따라 옵션창 띄워주는 부분
self.option_frame_list = [getattr(self, f'option_frame_{frame}') for frame in range(1, 13)] # 프레임들을 리스트에 담음
for idx, key in enumerate(option_df_keys): # 음료에 맞게 옵션창 띄워줌
if key in list(option_df_dict_not_null.keys()):
self.option_frame_list[idx].setVisible(True) # 음료에 있는 카테고리만 보여주고
else:
self.option_frame_list[idx].setVisible(False) # 나머지는 안보여줌
# 버튼 한번만 눌리게 체크
self.btn_duplicates_check()
# 버튼 누를 때마다 옵션 가격 추가해주는 시그널 연결
self.option_buttons = self.option_bottom_frame.findChildren(QPushButton)
for option_btn in self.option_buttons:
option_btn.clicked.connect(self.set_extra_charge)
if option_btn.isChecked():
self.set_extra_charge()
# 버튼 시그널 연결
self.cancel_btn.clicked.connect(lambda x: self.close()) # 창 종료하기
self.cancel_btn.clicked.connect(self.close) # 창 종료하기
self.order_btn.clicked.connect(self.order_confirm)
self.reset_btn.clicked.connect(self.btn_duplicates_check) # 옵션 초기화 버튼
# db불러오기
self.con = sqlite3.connect('./DATA/data.db') # 데이터베이스 연결 정보 설정
def set_extra_charge(self):
"""버튼 누를 때마다 옵션 가격 추가해주는 부분"""
# 옵션 가격 데이터 불러오기
option_price = pd.read_csv('./DATA/drinks_price.csv')
option_price_eng_name = option_price['eng_name'].to_list()
# 눌린 버튼들 확인하기 및 라벨에 업데이트
add_price = 0
self.customer_order_option_list = []
self.customer_order_option_list_kor = []
self.option_buttons = self.option_bottom_frame.findChildren(QPushButton)
for btn in self.option_buttons:
if btn.isChecked() and btn.isVisible(): # 체크된 버튼만 확인
btn_object_name = btn.objectName() # 버튼 객체 이름
idx = option_price_eng_name.index(btn_object_name) # 버튼의 index확인
drinks_price = option_price.loc[idx, 'noraml_drink'] # 체크된 옵션 가격 가져오기
drinks_option_name = option_price.loc[idx, 'eng_name'] # 체크된 옵션 영어 이름 가져오기
drinks_option_kor_name = option_price.loc[idx, 'kor_name']
add_price += drinks_price # 가격 더해주기
if '안함' not in drinks_option_kor_name:
self.customer_order_option_list_kor.append(drinks_option_kor_name)
self.customer_order_option_list.append(drinks_option_name)
# 상단에 값 추가
self.update_drink_price = str(int(self.drink_price) + int(add_price))
self.menu_price_label.setText(self.update_drink_price + '원')
if len(self.customer_order_option_list_kor) != 0:
self.choose_option_label.setText(str(', '.join(self.customer_order_option_list_kor)))
else:
self.choose_option_label.setText('없음')
def btn_duplicates_check(self):
"""각 옵션창 프레임 내에 있는 버튼들 한번만 눌리게"""
# 버튼 그룹 담아주기
self.option_button_groups = []
# 프레임들 안에 있는 버튼들을 각각 버튼 그룹으로 담아줌
for i in range(1, 13):
option_frame = self.option_frame_list[i - 1]
buttons = option_frame.findChildren(QPushButton)
button_group = QButtonGroup()
button_group.setExclusive(True)
for btn in buttons:
button_group.addButton(btn)
button_group.buttonClicked.connect(self.btn_check) # 중복버튼 누르기 방지
button_group.buttonClicked.connect(self.btn_clicked_style) # 버튼 색 바뀌게 하기
self.option_button_groups.append(button_group)
# 각 옵션 선택창 안에 들어있는 1번 버튼 눌리게 하기
for btn_group in self.option_button_groups:
btn_group.buttons()[0].click() # 첫번째 버튼 무조건 눌리게
def btn_clicked_style(self, btn):
"""선택한 옵션버튼 색 바꿔줌"""
for btn_group in self.option_button_groups:
if btn in btn_group.buttons():
for button in btn_group.buttons():
button.setStyleSheet('')
btn.setStyleSheet('border: 3px solid rgb(229, 79, 65);')
def btn_check(self):
"""버튼 그룹 가져와서 체크하는 부분"""
sender = self.sender() # 버튼 모두를 가져옴
for button_group in self.option_button_groups:
if sender not in button_group.buttons():
button_group.setExclusive(True)
def close(self):
self.parent.remove_label()
self.accept()
def order_confirm(self):
"""선택옵션 확인 후 db에 저장"""
self.parent.drink_num += 1 # 주문 수량 늘려줌
option_str = str(self.customer_order_option_list) # 리스트 str형태로 바꿔주기
cur = self.con.cursor() # 커서 생성
cur.execute("INSERT INTO order_table (id, drink_cnt, order_drink, price, custom_option)"
"VALUES(?,?,?,?,?);", # SQL 쿼리 실행
(self.parent.drink_num, 1, self.drink_name, self.update_drink_price, option_str))
self.con.commit() # 변경사항 저장
# 장바구니 리스트위젯에 값 넣어주기
add_shopping_item_to_listwidget(
self.parent.drinks_cart_list_widget, str(self.parent.drink_num),
self.drink_name, self.update_drink_price, self.parent.menu_cnt_label, self.parent.payment_admit_btn)
# 메뉴 갯수 라벨에 넣어주기(담은 메뉴 수 라벨)
cur.execute('SELECT SUM(drink_cnt) FROM order_table') # 테이블에 있는 메뉴 수 세서
result = cur.fetchone()[0] # 이를 튜플 형태로 가져오고 첫번째 값만 가져옴
self.parent.menu_cnt_label.setText(str(result) + '개')
order_df = pd.read_sql('select * from order_table', self.con)
order_df['drink_cnt'] = order_df['drink_cnt'].astype(int)
order_df['price'] = order_df['price'].astype(int)
total_price = (order_df['drink_cnt'] * order_df['price']).sum()
self.parent.payment_admit_btn.setText(f' {str(total_price)}원\n 결제하기')
cur.close() # 연결 종료
self.con.close()
# 선택옵션 창 종료
self.parent.remove_label()
self.accept()
self.close()
class WindowClass(QMainWindow, main_page_class):
"""오픈화면 & 메인화면 창"""
clicked = pyqtSignal()
def add_page_mouse_press(self, event):
"""오픈화면 누르면 발생하는 이벤트"""
self.stackedWidget.setCurrentWidget(self.main_page)
def __init__(self):
super().__init__()
self.setupUi(self)
# 오픈화면 #######################################################################################################
self.stackedWidget.setCurrentIndex(0) # 시작할때 화면은 오픈 페이지로 설정
self.set_ad_image() # 이미지 변경
self.setWindowFlags(Qt.FramelessWindowHint) # 프레임 지우기
self.move(10,30) #창이동
# 페이지 이동 및 타이머 시작
self.ad_label.mousePressEvent = lambda event: (self.stackedWidget.setCurrentWidget(self.main_page)) # 페이지 이동)
# 메인화면 시작 ##################################################################################################
# 0. DB 불러오기
con = sqlite3.connect('./DATA/data.db')
self.price_df = pd.read_sql('select * from drinks_price', con) # 가격 테이블
self.menu_df = pd.read_sql('select * from drinks_menu', con) # 음료상세정보 전체 테이블
self.img_path_df = pd.read_sql('select * from drinks_img_path', con) # 음료 이미지 경로 테이블
self.order_table_df = pd.read_sql('select * from order_table', con) #
self.drink_num = 0 # 음료 주문번호
self.order_num = 100 # 고객 주문번호 100부터 시작
# 1. 타이머
# 타이머 기본 설정값
self.DURATION_INT = 120
self.remaining_time = self.DURATION_INT
# # 타이머와 관련된 변수들
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_timer)
self.timer.setInterval(1000)
# 2. 카테고리 버튼 이동
self.category_stackedWidget.setCurrentWidget(self.category_1) # 기본값
self.category_btn_list = [getattr(self, f"category_btn_{i}") for i in range(1, 16)] # 카테고리 버튼 리스트화
for btn in self.category_btn_list:
btn.clicked.connect(self.set_categroy_num) # 카테고리 하단 메뉴 크기 설정
btn.clicked.connect(self.change_categroy_btn_color) # 버튼 색 바꾸기
btn.clicked.connect(self.show_menu_arrow_btn) # 카테고리 하단 메뉴 크기 설정
btn.clicked.connect(lambda: self.menu_stackedWidget.setCurrentWidget(self.page_1)) # 음료 페이지 1페이지로 초기화
btn.clicked.connect(
lambda x, category=btn: self.start_timer(btn)) # 카테고리 버튼 누를 때마다 타이머 초기화
# 3. 카테고리 페이지 넘기기 (메인화면 페이지 넘기기)
self.category_right_btn.clicked.connect(lambda: self.check_current_page(1))
self.category_right_btn_2.clicked.connect(lambda: self.check_current_page(2))
self.category_left_btn.clicked.connect(lambda: self.check_current_page(1))
self.category_left_btn_2.clicked.connect(lambda: self.check_current_page(2))
# 4. 커피 메뉴 좌/우 버튼
self.category_btn_1.click()
self.menu_arrow_btn_num = 2
self.menu_left_btn.clicked.connect(lambda: self.menu_stackedWidget.setCurrentWidget(self.page_1))
self.menu_right_btn.clicked.connect(lambda: self.menu_stackedWidget.setCurrentWidget(self.page_2))
self.menu_right_btn.clicked.connect(self.show_menu_arrow_btn)
self.menu_left_btn.clicked.connect(self.show_menu_arrow_btn)
# 5. 프레임 버튼 클릭하기 및 가격 폰트 변경
self.menu_frame_list = [getattr(self, f"menu_frame_{i}") for i in range(1, 25)] # 메뉴 프레임 리스트화
for frame in self.menu_frame_list:
frame.mousePressEvent = lambda event, name=frame.objectName(): self.click_frame(event, name)
# 6. 버튼 시그널 연결
self.all_remove_label.clicked.connect(self.delete_order_table_values) # 전체 삭제 버튼
self.home_button.clicked.connect(
lambda: self.stackedWidget.setCurrentWidget(self.opening_page)) # 홈 버튼 누르면 오픈화면으로 이동
# 7. 관리자페이지
self.logo_label.mousePressEvent = lambda event: self.open_manager_page()
self.manager_page_num = 0
# 99. 스타일시트 관련된 부분
# 가격 폰트 변경
self.menu_price_label_list = [getattr(self, f"menu_price_label_{i}") for i in range(1, 25)] # 가격 폰트 리스트
for label in self.menu_price_label_list:
label.setStyleSheet('color: rgb(229, 79, 64);font: 63 12pt "Pretendard SemiBold";')
# 주문확인화면 시작 ############################################################################################
# 1. 주문확인창 시작 및 테이블위젯 채우기
self.payment_admit_btn.clicked.connect(self.move_to_order_check_page)
# 2. 버튼 시그널 연결 모음
self.cancel_btn_2.clicked.connect(self.timer_restart_and_go_to_main_page)
self.back_to_main_page_btn.clicked.connect(self.timer_restart_and_go_to_main_page)
self.eat_here_btn.clicked.connect(lambda: self.move_to_payment_choose('for_here'))
self.take_out_btn.clicked.connect(lambda: self.move_to_payment_choose('to_go'))
# 결제수단선택창 ############################################################################################
# 버튼 시그널 연결
self.payment_choose_signal()
self.cancel_btn.clicked.connect(
lambda: self.stackedWidget.setCurrentWidget(self.order_check_page)) # x 버튼 누르면 주문확인창으로 이동
self.kt_discount = False
# 카드 / 큐알코드 결제창 ######################################################################################
### 1. 카드 결제창
# 버튼 클릭 이벤트
self.cancel_btn_3.clicked.connect(
lambda: self.stackedWidget.setCurrentWidget(self.payment_choose_page)) # x 버튼 누르면 결제선택수단창으로 이동
self.cancel_btn_4.clicked.connect(
lambda: self.stackedWidget.setCurrentWidget(self.payment_choose_page)) # 취소 버튼 누르면 결제선택수단창으로 이동
self.card_img_frame.mousePressEvent = lambda event: self.mobile_pay_msgbox()
self.barcode_type = None
### 2. 큐알코드 결제창
# self.qr_check_frame.mousePressEvent = lambda event: self.fill_the_table_widget()
# self.check_coupon_num.clicked.connect(self.) # 쿠폰 조회버튼
self.use_coupon.clicked.connect(self.askRcpt) # 쿠폰사용버튼 -> 영수증 물어보는 함수로 이동 및 종료
self.cancel_btn_5.clicked.connect(
lambda: self.stackedWidget.setCurrentWidget(self.payment_choose_page)) # x 버튼 누르면 결제선택수단창으로 이동
self.order_btn_2.clicked.connect(self.check_discount_and_move) # 할인 적용하고 이동
# 숫자 키보드 버튼 누를때 이벤트 발생
keyboard_buttons = self.keyboard_frame.findChildren(QPushButton)
for btn in keyboard_buttons:
btn.clicked.connect(self.change_card_num)
# 기타 스타일시트 변경 부분 ###############################################################################
# 큐알코드 커서 변경해주기
self.qr_check_frame.setCursor(QCursor(QPixmap('./img/qt자료/bacord').scaled(80, 80)))
self.card_label.setCursor(QCursor(QPixmap('./img/qt자료/payment_phone.png').scaled(120, 100)))
self.horizontalSlider.setCursor(QCursor(QPixmap('./img/qt자료/matercard.png').scaled(80, 70)))
## 함수 시작 #######################################################################################################
'''결제창 관련 함수'''
def askRcpt(self):
"""영수증 물어보는 함수로 이동"""
# 만약 결제 전이라면 이동하지 않음
try:
card_num = self.table_widget_qr_code.item(0, 0).text()
except AttributeError:
card_num = ''
if len(card_num) > 0:
msg_box_page = MSG_Dialog(self, 8)
msg_box_page.exec_()
def check_discount_and_move(self):
d_price = self.get_discount_price() # 할인금액
t_price = self.get_total_price() # 총 금액
self.r_price = t_price - d_price # 총금액 - 할인금액 = 사용자의결제금액
self.total_payment_price.setText(f' 주문금액: {str(t_price)}원 - 할인금액:{str(d_price)}원')
self.total_payment_price_2.setText(f' 결제금액: {str(self.r_price)}원')
self.payment_choose_title_bar.setText(f' 결제수단 선택({str(self.r_price)})원')
self.stackedWidget.setCurrentWidget(self.payment_choose_page)
def mobile_pay_msgbox(self):
"""모바일 페이 메세지박스 띄우기"""
msg_box_page = MSG_Dialog(self, 3)
msg_box_page.exec_()
def set_table_widget(self, tablewidget, row, column, labels):
"""큐알코드 테이블 위젯 값 설정하기"""
self.table_widget_qr_code.setRowCount(row) # 행 갯수 설정
self.table_widget_qr_code.setColumnCount(column) # 열 갯수 설정
self.table_widget_qr_code.setVerticalHeaderLabels(labels) # 행 제목 설정
self.table_widget_qr_code.horizontalHeader().setVisible(False) # 열 헤더 숨기기
self.table_widget_qr_code.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
if self.barcode_type == 'qr_payment':
print(self.get_total_price())
print(self.get_discount_price())
self.table_widget_qr_code.setItem(4, 0, QtWidgets.QTableWidgetItem(
f"{str(int(self.get_total_price()) -self.get_discount_price())}원"))
def change_card_num(self):
"""큐알코드 선택창에서 키패드 번호 입력"""
# 사용자가 누른 키패드 번호 받아옴
sender_name = self.sender().text()
print('사용자가 누른 번호', sender_name)
if self.barcode_type == 'kt_discount':
card_num_row = 3
if self.barcode_type == 'qr_payment':
card_num_row = 2
else:
card_num_row = 1
self.insert_value_in_tablewidget(self.table_widget_qr_code, sender_name, card_num_row)
def insert_value_in_tablewidget(self, tablewidget, sender_obj, card_row):
# 키패드 번호 리스트에 저장
keypad_numbers = [str(num) for num in range(10)]
keypad_numbers.extend(['00', '000'])
# 현재 테이블위젯에 있는 카드번호
try:
card_num = tablewidget.item(card_row, 0).text()
except AttributeError:
card_num = ''
string = (card_num + sender_obj).replace('-', '')
print('카드번호는', card_num)
# 테이블 위젯에 조건에 따라 값 넣어줌
if sender_obj in keypad_numbers and len(string) <= 16: # 키패드 리스트에 값이 있다면(0~9, 00, 000)
string = (card_num + sender_obj).replace('-', '')
divided_4_letter = '-'.join([string[i:i + 4] for i in range(0, len(string), 4)])
tablewidget.setItem(card_row, 0, QtWidgets.QTableWidgetItem(divided_4_letter)) # 카드 번호 위치에 값 넣어줌
# tablewidget.item(card_row, 0).setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) # 값 오른쪽 정렬
elif sender_obj == 'clear':
tablewidget.setItem(card_row, 0, QtWidgets.QTableWidgetItem('')) # clear 되었을 때 값 넣어주기
elif sender_obj == '승인':
if card_num.replace('-', '') == '1111222233334444':
if self.barcode_type == 'kt_discount':
kt_info = ['KT할인', '특정할인', '20230601 ~ 20230930', card_num, str(self.get_total_price()) + '원',
str(self.get_discount_price()) + '원']
self.set_number_in_qr_payment_table(6, kt_info)
if self.barcode_type == 'qr_payment':
coupon_info = [str(self.get_total_price() - self.get_discount_price()) + '원', str(randint(1, 3)), card_num]
self.set_number_in_qr_payment_table(3, coupon_info)
else:
msg_box_page = MSG_Dialog(self, 6) # 유효한 카드번호가 아닙니다. 다시 입력하세요.
msg_box_page.exec_()
elif sender_obj == '←':
card_num = card_num[:-1]
tablewidget.setItem(card_row, 0, QtWidgets.QTableWidgetItem(card_num)) # 하나 줄여서 값 넣어주기
tablewidget.item(card_row, 0).setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) # 값 오른쪽 정렬
else:
pass
def set_number_in_qr_payment_table(self, num, value):
"""qr/바코드 창에 값 넣어줌"""
print('바코드 창 탑니다..')
nums = [n for n in range(num)]
for i in nums:
self.table_widget_qr_code.setItem(nums[i], 0, QtWidgets.QTableWidgetItem(value[i]))
def get_discount_price(self):
"""할인된 금액 리턴"""
con = sqlite3.connect('./DATA/data.db')
order_df = pd.read_sql('select * from order_table', con)
if self.barcode_type == 'kt_discount':
order_df.loc[0, 'discount_price'] = 1900
order_df.to_sql('order_table', con, if_exists='replace', index=False)
con.commit()
con.close()
discount_p = order_df.loc[0, 'discount_price']
if discount_p == None:
discount_p = 0
return discount_p
'''결제수단 선택창 관련 함수'''
def payment_choose_signal(self):
"""결제수단 버튼에 따라 다른 정보 전달"""
payment_btn_df = pd.read_csv('./DATA/payment_choose.csv') # csv 값 가져오기(결제버튼 정보)
payment_choose_buttons = self.payment_choose_main_widget.findChildren(QPushButton) # 결제창에 있는 모든 버튼 가져오기
for btn in payment_choose_buttons:
con1 = payment_btn_df['btn_name'] == btn.objectName() # 버튼객체이름과 같은 버튼이라는 조건에 맞다면
crs_btn = payment_btn_df.loc[con1, ['kor_name', 'type']].to_dict('list') # 버튼 이름과 결제형태 딕셔너리 형식으로 가져오기
btn.clicked.connect(
lambda x, y=crs_btn['kor_name'][0], z=crs_btn['type'][0]: self.move_to_payment_page(y, z))
def move_to_payment_page(self, name, type):
"""전달해준 정보에 따라 다른 결제창 불러오기"""
print('타입', type)
print('kt할인여부', self.kt_discount)
# 카드 결제창 이동
if type == 1: # 카드
self.payment_card_title_bar.setText(" " + name)
self.stackedWidget.setCurrentWidget(self.charge_page)
self.update_card_payment_table()
elif type == 2 or (type == 3 and not self.kt_discount) or type == 4: # qr/바코드 창으로 이동
self.move_to_payment_page_for_qr(name, type)
else:
msg_box_page = MSG_Dialog(self, 7)
msg_box_page.exec_()
def move_to_payment_page_for_qr(self, name, type):
"""선택한 버튼에 따라 맞는 결제창으로 이동"""
self.table_widget_qr_code.clearContents() # 테이블 위젯 지우기
self.table_widget_qr_code.setRowCount(0)
if type == 2: # 쿠폰 조회창
self.qr_check_btns_stackwidget.setCurrentWidget(self.coupon_check_btn)
lab = ['쿠폰번호', '쿠폰명칭', '잔여금액', '받을금액', '결제금액']
self.barcode_type = 'coupon_payment'
if type == 4: # qr/바코드 결제창 이동
self.qr_check_btns_stackwidget.setCurrentWidget(self.coupon_check_btn)
lab = ['총 결제금액', '할부개월', '카드번호']
self.barcode_type = 'qr_payment'
else: # kt 할인창 이동
self.qr_check_btns_stackwidget.setCurrentWidget(self.kt_check_btn)
lab = ['제휴사명', '할인종료', '유효기간', '카드번호', '대상금액', '할인금액']
self.barcode_type = 'kt_discount'
self.kt_discount = True
self.set_table_widget(self.table_widget_qr_code, len(lab), 1, lab) # 테이블에 값 넣어주기
self.barcord_payment_title_bar.setText(" " + name) # 창 상단의 이름 바꾸기
self.stackedWidget.setCurrentWidget(self.barcod_payment_page) # qr/바코드 페이지로 이동
def get_total_price(self):
"""총 가격 계산 및 반환"""
con = sqlite3.connect('./DATA/data.db')
order_table_df = pd.read_sql('select * from order_table', con)
# 총 가격 계산
order_table_df['drink_cnt'] = order_table_df['drink_cnt'].astype(int)
order_table_df['price'] = order_table_df['price'].astype(int)
total_price = (order_table_df['drink_cnt'] * order_table_df['price']).sum()
return total_price
def get_total_cnt(self):
"""총 갯수 계산 및 반환"""
con = sqlite3.connect('./DATA/data.db')
order_table_df = pd.read_sql('select * from order_table', con)
total_count = order_table_df['drink_cnt'].sum()
return total_count
def update_card_payment_table(self):
"""카드 결제창 테이블 위젯 값 업데이트"""
total_price = self.get_total_price() # 총 가격
discount_price = self.get_discount_price()
f_price = total_price - discount_price
# 카드번호 랜덤으로 만들어줄것
card_num = self.make_random_card_num()
# 카드 테이블에 값 업데이트 해주기
self.card_payment_table_widget.setRowCount(3)
self.card_payment_table_widget.setColumnCount(1)
self.card_payment_table_widget.horizontalHeader().setVisible(False) # 열 헤더를 숨깁니다.
self.card_payment_table_widget.setItem(0, 0, QtWidgets.QTableWidgetItem(str(f_price) + '원'))
self.card_payment_table_widget.setItem(1, 0, QtWidgets.QTableWidgetItem('0개월'))
self.card_payment_table_widget.setItem(2, 0, QtWidgets.QTableWidgetItem(card_num))
self.card_payment_table_widget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) # 열 너비를 조정합니다.
def make_random_card_num(self):
"""카드 번호 랜덤으로 만들어주기"""
random_card_num = [str(randint(1000, 9999)) for _ in range(4)]
random_card_num_for_print = ' '.join(random_card_num)
mask_card_num = "*" * (len(random_card_num_for_print) - 4) + random_card_num_for_print[-4:]
return mask_card_num
'''주문 확인창 관련 함수'''
def insert_img_for_recommend(self):
"""추천 디저트 메뉴 5개 넣음"""
menu_and_price_join_df = pd.merge(self.menu_df, self.img_path_df, on='id') # 조인
con1 = (menu_and_price_join_df['category'] == '디저트')
def move_to_payment_choose(self, state):
"""포장/매장 선택하는 것 db에 저장해주기"""
con = sqlite3.connect('./DATA/data.db')
order_table_df = pd.read_sql('select * from order_table', con)
order_table_df.loc[:, 'for_here_or_to_go'] = state
order_table_df.to_sql('order_table', con, if_exists='replace', index=False)
con.commit()
con.close()
self.stackedWidget.setCurrentWidget(self.payment_choose_page)
def timer_restart_and_go_to_main_page(self):
"""타이머 재시작 및 메인 페이지로 이동"""
self.timer.start()
self.stackedWidget.setCurrentWidget(self.main_page)
def fill_the_table_widget(self, table):
"""테이블 위젯 채우기"""
# 업데이트한 db불러오기
con = sqlite3.connect('./DATA/data.db')
order_table_df = pd.read_sql('select * from order_table', con)
price_df = pd.read_csv('./DATA/drinks_price.csv') # 가격 csv 도 불러오기(한글이름으로 비교)
# 테이블위젯 행 값 계산
row = order_table_df['id'].count()
table.setRowCount(row) # 행값 적용
# 옵션 값 딕셔너리 화 하기
order_table_dict = pd.DataFrame(order_table_df).to_dict()
# 테이블위젯 값 생성하고 넣기
for idx in range(row):
# 테이블위젯 값 생성
drink_option_df = order_table_df.loc[idx, 'custom_option'] # 각 행의 옵션을 가져와서
drink_option_list = ast.literal_eval(drink_option_df) # 문자열로 되어 있는 리스트들을 리스트처럼 만들어줌
option_choices_no_choice = [price_df[price_df['eng_name'] == i]['kor_name'].to_string(index=False)
# 그리고 not choice가 써져 있지 않은 값들을 리스트에 넣어줌
for i in drink_option_list if 'no_choice' not in i]
# 값 넣기
items = [QTableWidgetItem(str(order_table_dict[col][idx])) for col in ['order_drink', 'drink_cnt', 'price']]
items.append(QTableWidgetItem(','.join(option_choices_no_choice)))
# 테이블 위젯 가운데로 정렬
for item in items:
item.setTextAlignment(Qt.AlignCenter) # Qt.AlignHCenter 가운데로 정렬
# 테이블위젯에 값 넣기
for col, item in enumerate(items):
table.setItem(idx, col, item)
# 테이블위젯 열 길이 헤더 크기만큼 정렬해주기
header = table.horizontalHeader()
header.setSectionResizeMode(0, QHeaderView.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
def move_to_order_check_page(self):
"""주문확인창"""
# 타이머 중단
self.timer.stop()
# 현재 db 연결
con = sqlite3.connect('./DATA/data.db')
order_table_df = pd.read_sql('select * from order_table', con)
total_price = self.get_total_price() # 총 가격 계산
total_count = order_table_df['drink_cnt'].sum() # 총 갯수 계산
discount_price = order_table_df['discount_price'].sum() # 할인금 계산
# 라벨 및 버튼에 넣어주기
self.total_price_for_check_page.setText(str(total_price) + '원')
self.payment_choose_title_bar.setText(f' 결제수단 선택({str(int(total_price) - int(discount_price))}원)') # 이건 결제수단 선택창임
self.total_payment_price.setText(f' 주문금액: {str(total_price)}원 - 할인금액:{str(discount_price)}원') # 이건 결제수단 선택창임
self.total_payment_price_2.setText(f' 결제금액: {str(total_price)}원') # 이건 결제수단 선택창임
self.total_cnt_for_check_page.setText(str(total_count) + '개')
# 총 갯수가 0 초과하면 창 넘어가기
if total_count > 0:
self.stackedWidget.setCurrentWidget(self.order_check_page) # 주문 확인 창으로 이동
self.fill_the_table_widget(self.tableWidget_menu_check) # 테이블위젯 값 채우기
self.fill_the_table_widget(self.tableWidget_menu_2_for_qr) # 일단 여기에 넣음 @@@@@@@@@@@@@@@@@@@ 수정필요
else:
msg_box_page = MSG_Dialog(self, 2) # 1보다 작으면 메세지 창 띄우기
msg_box_page.exec_()
'''메인창 관련 함수'''
def open_manager_page(self):
"""관리자 페이지 열기"""
self.manager_page_num += 1
if self.manager_page_num == 5:
self.manager_page_num = 0
manager_page = Manager_Page()
manager_page.show()
manager_page.exec_()
# sell_c = manager_page.MenuWidget.check_btn_sell()
# sold_c = manager_page.MenuWidget.check_btn_sold_out()
# print('판매', sell_c, '판매된', sold_c)
self.stackedWidget.setCurrentWidget(self.opening_page)
def check_current_page(self, num):
if num == 1:
self.category_stackedWidget.setCurrentWidget(self.category_2)
self.category_btn_11.click()
elif num == 2:
self.category_stackedWidget.setCurrentWidget(self.category_1)
self.category_btn_1.click()
self.menu_stackedWidget.setCurrentWidget(self.page_1)
def delete_order_table_values(self):
""" 주문 값 삭제"""
# 리스트 위젯 값 삭제
self.drinks_cart_list_widget.clear()
conn = sqlite3.connect('./DATA/data.db') # 데이터베이스 연결 정보 설정
cur = conn.cursor() # 커서 생성
cur.execute("DELETE FROM 'order_table'") # SQL 쿼리 실행
cur.execute("SELECT SUM(drink_cnt) FROM 'order_table'")
# cursor.execute('SELECT SUM(column_name) FROM table_name')
result = cur.fetchone()[0]
if result == None:
result = 0
self.menu_cnt_label.setText(str(result) + '개')
order_df = pd.read_sql('select * from order_table', conn)
order_df['drink_cnt'] = order_df['drink_cnt'].astype(int)
order_df['price'] = order_df['price'].astype(int)
total_price = (order_df['drink_cnt'] * order_df['price']).sum()
self.payment_admit_btn.setText(f' {str(total_price)}원\n 결제하기')
conn.commit() # 변경사항 저장
cur.close() # 연결 종료
conn.close()
def start_timer(self, category):
"""타이머 시작하는 함수"""
self.timer.stop()
self.remaining_time = self.DURATION_INT
self.timer.start()
def update_timer(self):
"""타이머 시간 업데이트"""
if self.stackedWidget.currentWidget() == self.main_page: # 메인페이지에서만 구동함
self.remaining_time -= 1
if self.remaining_time == 0:
self.remaining_time = self.DURATION_INT
self.stackedWidget.setCurrentWidget(self.main_page)
self.timer_label.setText(f"{str(self.remaining_time)}초")
else:
pass
def click_frame(self, event, name):
"""메뉴 선택하고 선택옵션 창 띄우기"""
# print(f'{name}프레임을 선택했습니다.')
option_page_df = pd.merge(self.menu_df, self.img_path_df, on='id')
print(option_page_df.columns)
# 조건설정
condition1 = (option_page_df['category'] == self.user_clicked_category)
condition2 = (option_page_df['category_num'] == int(name[11:]))
# 조건에 맞는 변수이름에 저장
sold_out_state = option_page_df.loc[condition1 & condition2, 'sold_out']
self.send_info = option_page_df.loc[condition1 & condition2]
print(self.send_info['info'])
if sold_out_state.sum() > 0:
msg_box_page = MSG_Dialog(self, 1)
# msg_box_page.show()
msg_box_page.exec_()
else:
# print('낫품절')
self.show_sample_label()
dialog_page = Option_Class(self)
dialog_page.show()
def remove_label(self):
"""선택옵션창 뒤에 검은 화면 숨겨줌"""
self.sample_label.hide()
def show_sample_label(self):
"""임시 검은 라벨 띄우기"""
self.sample_label = QLabel(self)
self.sample_label.setGeometry(0, 0, 768, 1024)
self.sample_label.setStyleSheet('background-color: rgba(45,45,45,200);')
self.sample_label.show()
def show_menu_arrow_btn(self):
"""카테고리 개수에 따라 메뉴 화살표상태를 변경합니다."""
current_page = self.menu_stackedWidget.currentWidget().objectName()
self.menu_right_btn.setVisible(current_page == 'page_1' and self.menu_arrow_btn_num == 2)
self.menu_left_btn.setVisible(current_page == 'page_2' and self.menu_arrow_btn_num == 2)
def set_categroy_num(self):
"""카테고리 숫자에 따라 음료 라벨 보여주기"""
# [1] 카테고리 수 만큼 프레임 보여주기
menu_frame_list = [getattr(self, f"menu_frame_{i}") for i in range(1, 25)] # 담길 라벨 리스트화
btn_name = self.sender().text() # 버튼 이름 가져오기
self.user_clicked_category = btn_name
# 값 초기화
self.connn = sqlite3.connect('./DATA/data.db')
self.menu_df = pd.read_sql('select * from drinks_menu', self.connn) # 음료상세정보 전체 테이블
category_drinks_num = len(self.menu_df[self.menu_df['category'] == btn_name]) # 카테고리 메뉴 갯수 세기
# 카테고리 번호만큼 프레임 보여주기
for index, frame in enumerate(menu_frame_list):
getattr(self, f'menu_img_{index + 1}').clear() # 라벨 클리어 시켜주기
getattr(self, f'menu_name_label_{index + 1}').clear()
getattr(self, f'menu_price_label_{index + 1}').clear()
if index + 1 <= category_drinks_num: # 해당하는 카테고리 번호까지 프레임의 background-color 바꿔준다.
frame.setStyleSheet('background-color: white;')
else:
frame.setStyleSheet('background-color: rgb(255, 204, 0);')
self.insert_img(btn_name, category_drinks_num)
def insert_img(self, btn_name, category_drinks_num):
# [2] 이미지 삽입
# 1) menu table과 img_path 테이블을 join (key = id)
menu_and_price_join_df = pd.merge(self.menu_df, self.img_path_df, how='left', on='id') # 조인
con1 = (menu_and_price_join_df['category'] == btn_name) # 버튼 번호에 맞는 조건 설정
user_click_category_df = menu_and_price_join_df.loc[
con1, ['id', 'category', 'category_num', 'sold_out', 'menu_name_x', 'img_path',
'price']] # 테이블 2차 가공 원하는 열만
# 2)이미지 열을 라벨에 입힌다. 카테고리 번호에 맞게
con3 = user_click_category_df['sold_out'] == 1
for i in range(1, category_drinks_num + 1):
con2 = user_click_category_df['category_num'] == i # 조건: 카테고리 번호가 일치해야 함
drink_img = user_click_category_df.loc[con2, 'img_path'].values
drink_name = user_click_category_df.loc[con2, 'menu_name_x'].values
drink_price = user_click_category_df.loc[con2, 'price'].values
sold_out_state = user_click_category_df.loc[con2 & con3, 'sold_out'].values
if sold_out_state.size > 0:
print(drink_name, '품절')
getattr(self, f'menu_img_{i}').setPixmap(
QPixmap('./img/qt자료/sold_out_3.png').scaled(175, 180, Qt.IgnoreAspectRatio))
elif drink_img.size > 0 and drink_name.size > 0 and drink_price.size > 0:
getattr(self, f'menu_img_{i}').setPixmap(QPixmap(drink_img[0]))
getattr(self, f'menu_name_label_{i}').setText(str(drink_name[0]))
getattr(self, f'menu_price_label_{i}').setText(f'{str(drink_price[0])}원')
self.connn.close()
# self.menu_arrow_btn_num = category_drinks_num % 12 > 0
print('페이지번호', category_drinks_num // 12)
print('나머지', category_drinks_num % 12)
if category_drinks_num > 12:
self.menu_arrow_btn_num = 2
else:
self.menu_arrow_btn_num = 1
def change_categroy_btn_color(self):
"""메인화면 상단 카테고리 버튼 색 바뀌게 함"""
btn_object = self.sender() # 버튼 객체 가져오기
# 선택한 버튼 색 바꾸고 그 외의 색 바꾸기
for btn in self.category_btn_list:
if btn == btn_object:
btn.setStyleSheet('''
background-color: rgb(45, 45, 45);
border: 2px solid rgb(45, 45, 45);
border-radius:15px; color:white;
''')
else:
btn.setStyleSheet('''
background-color: rgb(255, 204, 0);
border: 2px solid rgb(45, 45, 45);
border-radius:15px;
color:black;
''')
'''오프닝 페이지 관련 함수'''
def set_ad_image(self):
"""3초에 한번씩 오픈 페이지 이미지 변하게 함"""
self.ad_img_num = 1 # 오픈 페이지 이미지 변수 설정
self.ad_label.setPixmap(QPixmap(f'./img/ad/ad_img_{self.ad_img_num}').scaled(QSize(768, 1024))) # 첫번째 이미지
# 3초 타이머 설정.
ad_timer = QTimer(self)
ad_timer.timeout.connect(self.change_ad_image) # 타임아웃되면 change_ad_image 함수로 이동
ad_timer.start(3000)
def change_ad_image(self):
"""3초에 1번씩 이미지 변경해 줌"""
self.ad_img_num += 1 # 이미지 변수에 1씩 더해줌
if self.ad_img_num == 5: # 만약 5라면
self.ad_img_num = 1 # 1로 만들어준다
pixmap = QPixmap(f'./img/ad/ad_img_{self.ad_img_num}') # 사진 경로 받아오기
self.ad_label.setPixmap(QPixmap(pixmap).scaled(QSize(768, 1024))) # 라벨 이미지에 설정함
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
manager_page.py
import os
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
import sqlite3
import pandas as pd
def resource_path(relative_path):
base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, relative_path)
form = resource_path('./UI/manager_page.ui')
form_class = uic.loadUiType(form)[0]
form_2 = resource_path('./UI/menu_widget.ui')
form_class_2 = uic.loadUiType(form_2)[0]
class Manager_Page(QDialog, form_class):
def __init__(self):
super( ).__init__( )
self.setupUi(self)
btn_list = self.stackedWidget.findChildren(QPushButton)
self.category_btn_list = [btn for btn in btn_list if 'left' not in btn.objectName() and 'right' not in btn.objectName()]
arrow_list = [a for a in btn_list if a not in self.category_btn_list]
# 버튼 시그널 연결
for c_btn in self.category_btn_list:
c_btn.clicked.connect(self.make_list_for_category)
for arrow in arrow_list:
arrow.clicked.connect(self.move_stacked_widget)
self.cancel_btn.clicked.connect(self.close)
# 기본 화면 구성
self.pushButton_2.click()
self.stackedWidget_2.setCurrentWidget(self.password_page)
# 관리자 버튼 입력
p_btn_list = self.point_buttons.findChildren(QPushButton)
for p_btn in p_btn_list:
p_btn.clicked.connect(self.write_point_num)
self.manager_page_check.clicked.connect(self.check_manager_password)
def check_manager_password(self):
"""관리자인지 확인하고 페이지 넘기기"""
if self.manager_num_label.text() == '1234':
self.stackedWidget_2.setCurrentWidget(self.menu_manage_page)
else:
self.manager_num_label.setText('관리자 비밀번호가 아닙니다.')
def write_point_num(self):
"""번호를 누르면 번호창에 업데이트 된다"""
num_list = [str(num) for num in range(0, 10)] # 버튼은 0부터 010까지 존재함
btn_name = self.sender().text() # 누른 버튼 텍스트 가져옴
now_label_text = self.manager_num_label.text() # 라벨의 텍스트 가져옴
if btn_name in num_list:
now_label_text += str(btn_name)
self.manager_num_label.setText(now_label_text)
elif btn_name =='clear':
self.manager_num_label.setText('')
else:
now_label_text = now_label_text[:-1]
self.manager_num_label.setText(now_label_text)
def move_stacked_widget(self):
"""버튼에 따라 카테고리 스택위젯 넘기기"""
arrow_btn_obj = self.sender().objectName()
current_index = self.stackedWidget.currentIndex()
if 'right' in arrow_btn_obj:
self.stackedWidget.setCurrentIndex(current_index + 1)
else:
self.stackedWidget.setCurrentIndex(current_index - 1)
def make_list_for_category(self):
"""누른 카데고리에 따라 품절여부 보여주기"""
# 위젯 모두 불러오고 숨겨주기
widget_list = self.widget.findChildren(QWidget)
for i in widget_list:
i.setVisible(False)
# 버튼 스타일시트 변경해줌(초기화)
for btn in self.category_btn_list:
btn.setStyleSheet('')
# 누른 버튼만 스타일 바꿔주기
btn_ = self.sender()
btn_.setStyleSheet('''
background-color: rgb(45,45,45);
color:white;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
''')
# db연결
con = sqlite3.connect('./DATA/data.db')
self.menu_df = pd.read_sql('select * from drinks_menu', con) # 음료상세정보 전체 테이블
condition = self.menu_df.loc[self.menu_df['category']== btn_.text()]
menu_list = condition[['menu_name', 'sold_out']].values.tolist()
for index, menu_name in enumerate(menu_list):
self.initialize_widget(menu_name[0], menu_name[1], index)
def initialize_widget(self, menu_name, sold_out, index):
if self.widget.layout() is None:
v_layout = QVBoxLayout(self)
self.widget.setLayout(v_layout)
v_layout = self.widget.layout()
v_layout.addWidget(MenuWidget(self, menu_name, sold_out, index))
class MenuWidget(QWidget, form_class_2):
def __init__(self, parent, menu_name, sold_out, row):
super( ).__init__( )
self.setupUi(self)
self.parent = parent
# self.setStyleSheet(self.styleSheet()+self.parent.styleSheet())
self.label.setText(menu_name)
self.label.setStyleSheet('background-color: #F3F3F3')
self.pushButton.setText('판매')
self.pushButton_2.setText('품절')
''' 스타일시트'''
self.sold_out_y = '''
color: rgb(229, 79, 64);
border: 2px solid rgb(229, 79, 64);
border-radius: 10px;
font: 63 12pt "Pretendard SemiBold";
'''
self.sold_out_n = '''
border: 2px solid rgb(229, 79, 64);
border: 2px solid black;
border-radius:10px;
font: 63 12pt "Pretendard SemiBold";
'''
if sold_out == 1:
self.set_stylesheet_btn(self.pushButton, self.sold_out_n)
self.set_stylesheet_btn(self.pushButton_2, self.sold_out_y)
if sold_out == 0:
self.set_stylesheet_btn(self.pushButton, self.sold_out_y)
self.set_stylesheet_btn(self.pushButton_2, self.sold_out_n)
self.row_index = row
self.pushButton.clicked.connect(self.check_btn_sell)
self.pushButton_2.clicked.connect(self.check_btn_sold_out)
def set_stylesheet_btn(self, btn, style):
btn.setStyleSheet(style)
def check_btn_sell(self):
con = sqlite3.connect('./DATA/data.db')
menu_df = pd.read_sql('select * from drinks_menu', con) # 음료상세정보 전체 테이블
condition = menu_df.loc[menu_df['menu_name'] == self.label.text()]
menu_list = condition[['menu_name', 'sold_out']].values.tolist()
print(menu_list[0][0], menu_list[0][1])
if menu_list[0][1] == 0:
self.show_msgbox('이미 판매중인 상품입니다.')
else:
self.show_msgbox('판매로 상품을 전환합니다.')
update_query = f"UPDATE drinks_menu SET sold_out = 0 WHERE menu_name='{menu_list[0][0]}'"
con.execute(update_query)
con.commit()
con.close()
self.set_stylesheet_btn(self.pushButton, self.sold_out_y)
self.set_stylesheet_btn(self.pushButton_2, self.sold_out_n)
return self.label.text()
def check_btn_sold_out(self):
con = sqlite3.connect('./DATA/data.db')
menu_df = pd.read_sql('select * from drinks_menu', con) # 음료상세정보 전체 테이블
condition = menu_df.loc[menu_df['menu_name'] == self.label.text()]
menu_list = condition[['menu_name', 'sold_out']].values.tolist()
print(menu_list[0][0], menu_list[0][1])
if menu_list[0][1] == 1:
self.show_msgbox('이미 품절중인 상품입니다.')
else:
self.show_msgbox('품절로 상품을 전환합니다.')
update_query = f"UPDATE drinks_menu SET sold_out = 1 WHERE menu_name='{menu_list[0][0]}'"
con.execute(update_query)
con.commit()
self.set_stylesheet_btn(self.pushButton, self.sold_out_n)
self.set_stylesheet_btn(self.pushButton_2, self.sold_out_y)
con.close()
return self.label.text()
def show_msgbox(self, text):
msgbox = QMessageBox()
msgbox.setText(text)
msgbox.show()
msgbox.exec_()
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = Manager_Page( )
myWindow.show( )
app.exec_( )
shopping_cart.py
from PyQt5.QtWidgets import * # QApplication, QVBoxLayout, QListWidgetItem, QListWidget, QLabel, QPushButton, QHBoxLayout, QWidget
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import pandas as pd
import sqlite3
# from mega_kiosk_ver1 import WindowClass
class ShoppingItemWidget(QWidget):
def __init__(self, idx, name, price, list_widget, label, btn):
super().__init__()
# 이미지 불러오기
plus_btn_img = QPixmap('./img/qt자료/plus-icon.png')
minus_btn_img = QPixmap('./img/qt자료/minus_icon.png')
cancel_img = QPixmap('./img/qt자료/cancel_icon.png')
self.cnt_label = label
self.price_btn = btn
self.name_label = QLabel(name)
self.name_label.setFixedSize(220, 40)
self.quantity_label = QLabel('1')
self.quantity_label.setFixedSize(30, 40)
self.quantity_label.setAlignment(Qt.AlignCenter)
self.index_label = QLabel(idx)
self.index_label.setFixedSize(30, 40)
self.price_label = QLabel(price + '원')
self.price_label.setStyleSheet('color:rgb(229, 79, 65)')
# (-) 버튼 생성
self.decrease_button = QPushButton()
self.decrease_button.setFixedSize(40, 40)
self.decrease_button.setStyleSheet('background-color: rgb(229, 79, 64);')
self.decrease_button.setIcon(QIcon(minus_btn_img))
self.decrease_button.clicked.connect(self.decrease_quantity)
# (+) 버튼 생성
self.increase_button = QPushButton()
self.increase_button.setFixedSize(40, 40)
self.increase_button.setStyleSheet('background-color: rgb(229, 79, 64);')
self.increase_button.setIcon(QIcon(plus_btn_img))
self.increase_button.clicked.connect(self.increase_quantity)
# (삭제) 버튼 생성
self.delete_button = QPushButton()
self.delete_button.setFixedSize(40, 40)
self.delete_button.setIcon(QIcon(cancel_img))
self.delete_button.setIconSize(QSize(38,38))
self.delete_button.setStyleSheet('background-color: transparent ;')
self.delete_button.clicked.connect(self.delete_item)
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.delete_button)
# layout.addWidget(self.index_label)
layout.addWidget(self.name_label)
layout.addWidget(self.decrease_button)
layout.addWidget(self.quantity_label)
layout.addWidget(self.increase_button)
layout.addWidget(self.price_label)
self.setLayout(layout)
self.list_widget = list_widget
self.price = int(price)
self.idx_text = self.index_label.text()
def decrease_quantity(self):
"""리스트위젯 수량 업데이트 해줌(-)"""
quantity = int(self.quantity_label.text())
if quantity > 1:
quantity -= 1
self.quantity_label.setText(str(quantity))
# db에서 수량 줄임
con = sqlite3.connect('./DATA/data.db')
order_df = pd.read_sql('select * from order_table', con)
drinks_count = int(order_df.loc[order_df['id'] == self.idx_text, 'drink_cnt'].iloc[0]) - 1
order_df.loc[order_df['id'] == self.idx_text, 'drink_cnt'] = drinks_count
order_df.to_sql('order_table', con, if_exists='replace', index=False)
con.commit()
con.close()
# total_price = (order_df['drink_cnt'] * order_df['price']).sum()
self.cnt_label.setText(str(drinks_count) + '개')
# self.price_btn.setText(str(total_price)+'원')
self.update_price(drinks_count)
def increase_quantity(self):
"""리스트위젯 수량 업데이트 해줌(+)"""
quantity = int(self.quantity_label.text())
quantity += 1
self.quantity_label.setText(str(quantity))
# db에서 수량 추가
con = sqlite3.connect('./DATA/data.db')
order_df = pd.read_sql('select * from order_table', con)
drinks_count = int(order_df.loc[order_df['id'] == self.idx_text, 'drink_cnt'].iloc[0]) + 1
order_df.loc[order_df['id'] == self.idx_text, 'drink_cnt'] = drinks_count
order_df.to_sql('order_table', con, if_exists='replace', index=False)
con.commit()
con.close()
self.cnt_label.setText(str(drinks_count) + '개')
self.update_price(drinks_count)
def update_price(self, cnt):
"""리스트 위젯 가격 업데이트 해주는 함수"""
quantity = int(self.quantity_label.text())
new_price = self.price * quantity
self.price_label.setText(str(new_price) + '원')
# 합 구하기
con = sqlite3.connect('./DATA/data.db')
order_df = pd.read_sql('select * from order_table', con)
order_df['drink_cnt'] = order_df['drink_cnt'].astype(int)
order_df['price'] = order_df['price'].astype(int)
total_price = (order_df['drink_cnt'] * order_df['price']).sum()
self.cnt_label.setText(str(cnt) + '개')
self.price_btn.setText(f' {str(total_price)}원\n 결제하기')
def delete_item(self):
"""리스트위젯에서 아이템 지우고 db에서 지우는 함수"""
# 리스트위젯에서 아이템 지워주기
item = self.list_widget.itemAt(self.pos())
row = self.list_widget.row(item)
self.list_widget.takeItem(row)
# db에서 id에 맞는 행 지워주기
con = sqlite3.connect('./DATA/data.db')
order_df = pd.read_sql('select * from order_table', con)
order_df = order_df[order_df['id'] != self.index_label.text()]
order_df.to_sql('order_table', con, if_exists='replace', index=False)
con.commit()
con.close()
order_df['drink_cnt'] = order_df['drink_cnt'].astype(int)
order_df['price'] = order_df['price'].astype(int)
total_price = (order_df['drink_cnt'] * order_df['price']).sum()
drinks_count = (order_df['drink_cnt']).sum()
self.cnt_label.setText(f'{str(drinks_count)} 개')
self.price_btn.setText(f' {str(total_price)}원\n 결제하기')
def add_shopping_item_to_listwidget(list_widget, idx, name, price, label, btn):
item_widget = ShoppingItemWidget(idx, name, price, list_widget, label, btn)
item = QListWidgetItem()
item.setSizeHint(item_widget.sizeHint())
list_widget.addItem(item)
list_widget.setItemWidget(item, item_widget)
'공부_백업용 > 프로젝트 모음' 카테고리의 다른 글
[팀프로젝트] (23.7.10 ~ 7.16) 채팅 프로그램 만들기 개발완료보고서 (2) | 2023.08.19 |
---|---|
[팀프로젝트] (23.7.3 ~ 7.8) 서울 관광 프로그램 개발완성보고서 (0) | 2023.08.19 |
[개인프로젝트] (23.6.28 ~ 7.1) 영화추천기 개발완료 보고서 (0) | 2023.07.01 |
[프로젝트] 개인프로젝트 - 키오스크 제작: 요구분석서 작성하기 (0) | 2023.06.12 |
[팀프로젝트] (23.5.11 ~ 5.25) Pyqt, Python 사용해 RPG 게임 만들기 (2) | 2023.05.29 |