334 lines
12 KiB
Python
334 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
당무 변경 다이얼로그
|
|
오늘의 당무자(부팀장, 운용)를 선택합니다.
|
|
"""
|
|
|
|
from datetime import date
|
|
from typing import Optional
|
|
|
|
from PySide6.QtWidgets import (
|
|
QWidget, QVBoxLayout, QHBoxLayout, QLabel
|
|
)
|
|
from PySide6.QtCore import Qt, Signal
|
|
from PySide6.QtGui import QFont
|
|
|
|
from ui.base.base_dialog import BaseDialog
|
|
from ui.components.custom_input import CustomComboBox, LabeledInput
|
|
from ui.styles.style_manager import StyleManager
|
|
from database.crud import CRUDManager
|
|
from database.models import TeamMember
|
|
from core.logger import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
class DutyChangeDialog(BaseDialog):
|
|
"""
|
|
당무 변경 다이얼로그
|
|
|
|
오늘의 당무자를 선택합니다.
|
|
부팀장과 운용을 각각 선택할 수 있습니다.
|
|
"""
|
|
|
|
duty_changed = Signal(str, str) # vice_leader_name, operator_name
|
|
|
|
def __init__(
|
|
self,
|
|
parent=None,
|
|
team: str = "",
|
|
shift: str = ""
|
|
):
|
|
self.team = team
|
|
self.shift = shift
|
|
self.crud = CRUDManager()
|
|
self.style_manager = StyleManager()
|
|
|
|
super().__init__(
|
|
parent,
|
|
title=f"당무 변경 - {team} {shift}",
|
|
width=400,
|
|
height=350,
|
|
min_width=350,
|
|
min_height=600,
|
|
resizable=True
|
|
)
|
|
|
|
self._setup_content()
|
|
self.add_confirm_cancel_buttons("저장", "취소")
|
|
|
|
self._load_current_duty()
|
|
|
|
def change_UI_Info(self, team: str, shift: str):
|
|
"""UI 정보 변경"""
|
|
self.team = team
|
|
self.shift = shift
|
|
self.title = f"당무 변경 - {team} {shift}"
|
|
self.setWindowTitle(self.title)
|
|
self._setup_content()
|
|
self._load_current_duty()
|
|
self.add_confirm_cancel_buttons("저장", "취소")
|
|
|
|
def _setup_content(self):
|
|
"""컨텐츠 설정"""
|
|
colors = self.style_manager.get_colors()
|
|
|
|
# 날짜 표시
|
|
today = date.today()
|
|
date_label = QLabel(f"📅 {today.year}년 {today.month}월 {today.day}일")
|
|
date_font = self.style_manager.get_font("dialog", "title")
|
|
date_label.setFont(date_font)
|
|
date_label.setAlignment(Qt.AlignCenter)
|
|
date_height = self.style_manager.calculate_label_height(
|
|
font=date_font, area="dialog", style="title"
|
|
)
|
|
date_label.setStyleSheet(f"""
|
|
color: {colors['text_primary']};
|
|
min-height: {date_height}px;
|
|
""")
|
|
self.content_layout.addWidget(date_label)
|
|
|
|
# 팀/근무 정보
|
|
info_label = QLabel(f"🏢 {self.team} | {self.shift}")
|
|
info_font = self.style_manager.get_font("dialog", "label")
|
|
info_label.setFont(info_font)
|
|
info_label.setAlignment(Qt.AlignCenter)
|
|
info_height = self.style_manager.calculate_label_height(
|
|
font=info_font, area="dialog", style="label"
|
|
)
|
|
info_label.setStyleSheet(f"""
|
|
color: {colors['text_tertiary']};
|
|
min-height: {info_height}px;
|
|
margin-bottom: 16px;
|
|
""")
|
|
self.content_layout.addWidget(info_label)
|
|
|
|
# 부팀장 선택
|
|
self.vice_leader_combo = CustomComboBox(
|
|
placeholder="부팀장 선택"
|
|
)
|
|
self._load_vice_leaders()
|
|
self.content_layout.addWidget(
|
|
LabeledInput("부팀장 당무", self.vice_leader_combo)
|
|
)
|
|
|
|
# 운용 선택
|
|
self.operator_combo = CustomComboBox(
|
|
placeholder="운용 선택"
|
|
)
|
|
self._load_operators()
|
|
self.content_layout.addWidget(
|
|
LabeledInput("운용 당무", self.operator_combo)
|
|
)
|
|
|
|
# 자동 선택 버튼들
|
|
auto_section = QWidget()
|
|
auto_layout = QHBoxLayout(auto_section)
|
|
auto_layout.setContentsMargins(0, 16, 0, 0)
|
|
auto_layout.setSpacing(8)
|
|
|
|
from ui.components.custom_button import CustomButton
|
|
|
|
# 다음 순번 버튼
|
|
next_btn = CustomButton(
|
|
"다음 순번 자동선택",
|
|
style_type="outline",
|
|
fixed_height=36
|
|
)
|
|
next_btn.clicked.connect(self._select_next_duty)
|
|
auto_layout.addWidget(next_btn)
|
|
|
|
self.content_layout.addWidget(auto_section)
|
|
|
|
self.content_layout.addStretch()
|
|
|
|
def _on_text_scale_changed(self, scale: float, label_font, input_font):
|
|
"""
|
|
텍스트 스케일 변경 시 호출
|
|
|
|
당무 변경 다이얼로그의 텍스트만 동적으로 조정합니다.
|
|
"""
|
|
colors = self.style_manager.get_colors()
|
|
|
|
# 날짜 라벨 폰트 조정
|
|
base_date_font = self.style_manager.get_font("dialog", "title")
|
|
date_size = int(base_date_font.pointSize() * scale)
|
|
date_font = QFont(base_date_font.family(), date_size, base_date_font.weight())
|
|
date_height = self.style_manager.calculate_label_height(
|
|
font=date_font, area="dialog", style="title"
|
|
)
|
|
|
|
# 날짜 라벨 찾기 및 업데이트
|
|
for i in range(self.content_layout.count()):
|
|
widget = self.content_layout.itemAt(i).widget()
|
|
if isinstance(widget, QLabel) and "📅" in widget.text():
|
|
widget.setFont(date_font)
|
|
widget.setStyleSheet(f"""
|
|
color: {colors['text_primary']};
|
|
min-height: {date_height}px;
|
|
""")
|
|
break
|
|
|
|
# 팀/근무 정보 라벨 폰트 조정
|
|
base_info_font = self.style_manager.get_font("dialog", "label")
|
|
info_size = int(base_info_font.pointSize() * scale)
|
|
info_font = QFont(base_info_font.family(), info_size, base_info_font.weight())
|
|
info_height = self.style_manager.calculate_label_height(
|
|
font=info_font, area="dialog", style="label"
|
|
)
|
|
|
|
# 팀/근무 정보 라벨 찾기 및 업데이트
|
|
for i in range(self.content_layout.count()):
|
|
widget = self.content_layout.itemAt(i).widget()
|
|
if isinstance(widget, QLabel) and "🏢" in widget.text():
|
|
widget.setFont(info_font)
|
|
widget.setStyleSheet(f"""
|
|
color: {colors['text_tertiary']};
|
|
min-height: {info_height}px;
|
|
margin-bottom: 16px;
|
|
""")
|
|
break
|
|
|
|
# LabeledInput 내부 라벨 및 입력 필드도 조정
|
|
for i in range(self.content_layout.count()):
|
|
item = self.content_layout.itemAt(i)
|
|
if item and item.widget():
|
|
widget = item.widget()
|
|
if isinstance(widget, LabeledInput):
|
|
# 라벨 폰트 조정
|
|
label = widget.label
|
|
label.setFont(label_font)
|
|
label_height = self.style_manager.calculate_label_height(
|
|
font=label_font, area="dialog", style="label"
|
|
)
|
|
label.setStyleSheet(f"""
|
|
color: {colors['text_primary']};
|
|
font-family: '{label_font.family()}';
|
|
font-size: {label_font.pointSize()}pt;
|
|
min-height: {label_height}px;
|
|
""")
|
|
|
|
# 입력 필드 폰트 및 높이 조정
|
|
input_widget = widget.input_widget
|
|
if hasattr(input_widget, 'setFont'):
|
|
input_widget.setFont(input_font)
|
|
input_height = self.style_manager.calculate_input_height(
|
|
font=input_font, area="dialog", style="input"
|
|
)
|
|
if hasattr(input_widget, 'setMinimumHeight'):
|
|
input_widget.setMinimumHeight(input_height)
|
|
|
|
def _load_vice_leaders(self):
|
|
"""부팀장 목록 로드"""
|
|
members = self.crud.get_team_members_by_team(
|
|
self.team,
|
|
"부팀장",
|
|
active_only=True
|
|
)
|
|
|
|
for member in members:
|
|
self.vice_leader_combo.addItem(member.name, member.id)
|
|
|
|
def _load_operators(self):
|
|
"""운용 목록 로드"""
|
|
members = self.crud.get_team_members_by_team(
|
|
self.team,
|
|
"운용",
|
|
active_only=True
|
|
)
|
|
|
|
for member in members:
|
|
self.operator_combo.addItem(member.name, member.id)
|
|
|
|
def _load_current_duty(self):
|
|
"""현재 당무 정보 로드"""
|
|
today = date.today()
|
|
duty = self.crud.get_duty_schedule(today, self.team, self.shift)
|
|
|
|
if duty:
|
|
# 부팀장 선택
|
|
if duty.vice_leader_name:
|
|
idx = self.vice_leader_combo.findText(duty.vice_leader_name)
|
|
if idx >= 0:
|
|
self.vice_leader_combo.setCurrentIndex(idx)
|
|
|
|
# 운용 선택
|
|
if duty.operator_name:
|
|
idx = self.operator_combo.findText(duty.operator_name)
|
|
if idx >= 0:
|
|
self.operator_combo.setCurrentIndex(idx)
|
|
|
|
def _select_next_duty(self):
|
|
"""다음 순번 자동 선택"""
|
|
today = date.today()
|
|
|
|
# 현재 당무 정보 조회
|
|
current_duty = self.crud.get_duty_schedule(today, self.team, self.shift)
|
|
|
|
# 부팀장 다음 순번
|
|
current_vice_leader_id = current_duty.vice_leader_id if current_duty else None
|
|
next_vice_leader = self.crud.get_next_duty_member(
|
|
self.team,
|
|
"부팀장",
|
|
current_vice_leader_id
|
|
)
|
|
|
|
if next_vice_leader:
|
|
idx = self.vice_leader_combo.findText(next_vice_leader.name)
|
|
if idx >= 0:
|
|
self.vice_leader_combo.setCurrentIndex(idx)
|
|
|
|
# 운용 다음 순번
|
|
current_operator_id = current_duty.operator_id if current_duty else None
|
|
next_operator = self.crud.get_next_duty_member(
|
|
self.team,
|
|
"운용",
|
|
current_operator_id
|
|
)
|
|
|
|
if next_operator:
|
|
idx = self.operator_combo.findText(next_operator.name)
|
|
if idx >= 0:
|
|
self.operator_combo.setCurrentIndex(idx)
|
|
|
|
def _on_confirm(self):
|
|
"""저장 버튼 클릭"""
|
|
today = date.today()
|
|
|
|
# 선택된 부팀장
|
|
vice_leader_name = self.vice_leader_combo.currentText()
|
|
vice_leader_id = self.vice_leader_combo.currentData()
|
|
|
|
# 선택된 운용
|
|
operator_name = self.operator_combo.currentText()
|
|
operator_id = self.operator_combo.currentData()
|
|
|
|
# placeholder 체크
|
|
if self.vice_leader_combo.currentIndex() == 0:
|
|
vice_leader_name = ""
|
|
vice_leader_id = None
|
|
|
|
if self.operator_combo.currentIndex() == 0:
|
|
operator_name = ""
|
|
operator_id = None
|
|
|
|
# DB에 저장
|
|
self.crud.upsert_duty_schedule(
|
|
duty_date=today,
|
|
team=self.team,
|
|
shift_type=self.shift,
|
|
vice_leader_id=vice_leader_id,
|
|
operator_id=operator_id,
|
|
vice_leader_name=vice_leader_name,
|
|
operator_name=operator_name
|
|
)
|
|
|
|
logger.info(
|
|
"당무 변경: %s %s - 부팀장: %s, 운용: %s",
|
|
self.team, self.shift, vice_leader_name, operator_name
|
|
)
|
|
|
|
self.duty_changed.emit(vice_leader_name, operator_name)
|
|
self.accept()
|
|
|