import sqlite3
import math
from PySide6.QtWidgets import (
QApplication, QMainWindow, QPushButton, QLabel, QVBoxLayout,
QWidget, QTableWidget, QTableWidgetItem, QLineEdit, QFormLayout,
QDialog, QFileDialog, QMessageBox, QComboBox, QHBoxLayout
)
from PySide6.QtCore import Qt
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

class ModernMainWindow(QMainWindow):
def init(self):
super().init()
self.setWindowTitle("مدیریت هزینه‌های کافی شاپ")
self.setGeometry(100, 100, 800, 600)
self.setStyleSheet("background-color: #2E2E2E; color: white; font-family: B Nazanin;")


    # Main layout
    main_widget = QWidget()
    self.setCentralWidget(main_widget)
    layout = QVBoxLayout(main_widget)

    # Title label
    title_label = QLabel("مدیریت کافی‌شاپ")
    title_label.setStyleSheet("font-size: 24px; font-weight: bold; color: Gold;")
    title_label.setAlignment(Qt.AlignCenter)
    layout.addWidget(title_label)

    # Buttons
    btn_materials = self.create_styled_button("مواد اولیه")
    btn_materials.clicked.connect(self.manage_materials)
    layout.addWidget(btn_materials)

    btn_recipes = self.create_styled_button("رسپی‌ها")
    btn_recipes.clicked.connect(self.manage_recipes)
    layout.addWidget(btn_recipes)

    btn_menu = self.create_styled_button("نمایش منو")
    btn_menu.clicked.connect(self.show_menu)
    layout.addWidget(btn_menu)

    # Footer
    footer_label = QLabel("Made By LoGiT3X with 🧡")
    footer_label.setStyleSheet("font-size: 12px; font-weight: bold; color: #f024b3;")
    footer_label.setAlignment(Qt.AlignCenter)
    layout.addWidget(footer_label)

def create_styled_button(self, text):
    """Create a styled button with rounded corners and hover effects."""
    button = QPushButton(text)
    button.setStyleSheet("""
        QPushButton {
            background-color: #0786b0;
            color: black;
            border: 2px solid #fcd40d;
            border-radius: 25px;
            font-size: 20px;
            padding: 10px;
            text-align: center;
        }
        QPushButton:hover {
            background-color: #17627a;
            border-color: fcd40d;
        }
        QPushButton:pressed {
            background-color: #fcd40d;
            border-color: #FF0000;
        }
    """)
    return button

def manage_materials(self):
    """Open the materials management window."""
    dialog = MaterialsDialog(self)
    dialog.exec()

def manage_recipes(self):
    """Open the recipes management window."""
    dialog = RecipesDialog(self)
    dialog.exec()

def show_menu(self):
    """Open the menu display window."""
    dialog = MenuDialog(self)
    dialog.exec()
class MaterialsDialog(QDialog):
def init(self, parent=None):
super().init(parent)
self.setWindowTitle("مدیریت مواد اولیه")
self.setStyleSheet("background-color: #2E2E2E; color: white; font-family: B Nazanin;")
self.setGeometry(100, 100, 600, 400)


    layout = QVBoxLayout(self)

    # Table
    self.table = QTableWidget()
    self.table.setColumnCount(2)
    self.table.setHorizontalHeaderLabels(["نام مواد", "قیمت هر گرم"])
    self.refresh_materials()
    layout.addWidget(self.table)

    # Add form
    form_layout = QFormLayout()
    self.name_input = QLineEdit()
    self.price_input = QLineEdit()
    form_layout.addRow("نام:", self.name_input)
    form_layout.addRow("قیمت هر گرم:", self.price_input)

    add_button = QPushButton("اضافه کردن")
    add_button.clicked.connect(self.add_material)
    form_layout.addWidget(add_button)

    layout.addLayout(form_layout)

def refresh_materials(self):
    """Refresh the materials table."""
    conn = sqlite3.connect("coffee_shop.db")
    cursor = conn.cursor()
    cursor.execute("SELECT name, price_per_gram FROM materials")
    materials = cursor.fetchall()
    conn.close()

    self.table.setRowCount(len(materials))
    for row, material in enumerate(materials):
        self.table.setItem(row, 0, QTableWidgetItem(material[0]))
        self.table.setItem(row, 1, QTableWidgetItem(str(material[1])))

def add_material(self):
    """Add a new material."""
    name = self.name_input.text()
    price = self.price_input.text()

    if not name or not price:
        QMessageBox.warning(self, "خطا", "تمام فیلدها را پر کنید.")
        return

    try:
        price = float(price)
    except ValueError:
        QMessageBox.warning(self, "خطا", "قیمت باید عدد باشد.")
        return

    conn = sqlite3.connect("coffee_shop.db")
    cursor = conn.cursor()
    try:
        cursor.execute("INSERT INTO materials (name, price_per_gram) VALUES (?, ?)", (name, price))
        conn.commit()
    except sqlite3.IntegrityError:
        QMessageBox.warning(self, "خطا", "این ماده قبلاً ثبت شده است.")
    finally:
        conn.close()

    self.refresh_materials()
    self.name_input.clear()
    self.price_input.clear()
class RecipesDialog(QDialog):
def init(self, parent=None):
super().init(parent)
self.setWindowTitle("مدیریت رسپی‌ها")
self.setStyleSheet("background-color: #2E2E2E; color: white; font-family: B Nazanin;")
self.setGeometry(100, 100, 800, 500)


    layout = QVBoxLayout(self)

    # Table
    self.table = QTableWidget()
    self.table.setColumnCount(2)
    self.table.setHorizontalHeaderLabels(["نام رسپی", "تعداد مواد اولیه"])
    self.refresh_recipes()
    layout.addWidget(self.table)

    # Buttons
    button_layout = QHBoxLayout()
    add_button = QPushButton("اضافه کردن رسپی")
    add_button.clicked.connect(self.add_recipe)
    button_layout.addWidget(add_button)

    edit_button = QPushButton("ویرایش رسپی")
    edit_button.clicked.connect(self.edit_recipe)
    button_layout.addWidget(edit_button)

    delete_button = QPushButton("حذف رسپی")
    delete_button.clicked.connect(self.delete_recipe)
    button_layout.addWidget(delete_button)

    layout.addLayout(button_layout)

def refresh_recipes(self):
    """Fetch recipes and display them in the table."""
    conn = sqlite3.connect("coffee_shop.db")
    cursor = conn.cursor()
    cursor.execute("""
        SELECT r.id, r.name, COUNT(rd.material_id) 
        FROM recipes r
        LEFT JOIN recipe_details rd ON r.id = rd.recipe_id
        GROUP BY r.id
    """)
    recipes = cursor.fetchall()
    conn.close()

    self.table.setRowCount(len(recipes))
    for row, (recipe_id, name, material_count) in enumerate(recipes):
        self.table.setItem(row, 0, QTableWidgetItem(name))
        self.table.setItem(row, 1, QTableWidgetItem(str(material_count)))

def add_recipe(self):
    """Open a dialog to add a new recipe."""
    dialog = RecipeEditDialog(self)
    dialog.exec()
    self.refresh_recipes()

def edit_recipe(self):
    """Open a dialog to edit the selected recipe."""
    selected_row = self.table.currentRow()
    if selected_row == -1:
        QMessageBox.warning(self, "خطا", "لطفاً یک رسپی را انتخاب کنید.")
        return

    recipe_name = self.table.item(selected_row, 0).text()
    dialog = RecipeEditDialog(self, recipe_name)
    dialog.exec()
    self.refresh_recipes()

def delete_recipe(self):
    """Delete the selected recipe."""
    selected_row = self.table.currentRow()
    if selected_row == -1:
        QMessageBox.warning(self, "خطا", "لطفاً یک رسپی را انتخاب کنید.")
        return

    recipe_name = self.table.item(selected_row, 0).text()
    confirm = QMessageBox.question(
        self, "حذف رسپی", f"آیا مطمئن هستید که می‌خواهید رسپی '{recipe_name}' را حذف کنید؟",
        QMessageBox.Yes | QMessageBox.No
    )
    if confirm == QMessageBox.Yes:
        conn = sqlite3.connect("coffee_shop.db")
        cursor = conn.cursor()
        cursor.execute("DELETE FROM recipes WHERE name = ?", (recipe_name,))
        cursor.execute("DELETE FROM recipe_details WHERE recipe_id = (SELECT id FROM recipes WHERE name = ?)",
                       (recipe_name,))
        conn.commit()
        conn.close()
        self.refresh_recipes()
class RecipeEditDialog(QDialog):
def init(self, parent=None, recipe_name=None):
super().init(parent)
self.recipe_name = recipe_name
self.setWindowTitle("ویرایش رسپی" if recipe_name else "اضافه کردن رسپی")
self.setStyleSheet("background-color: #2E2E2E; color: white; font-family: B Nazanin;")
self.setGeometry(100, 100, 600, 400)


    layout = QVBoxLayout(self)

    # Recipe name
    self.name_input = QLineEdit()
    if recipe_name:
        self.name_input.setText(recipe_name)
    layout.addWidget(QLabel("نام رسپی:"))
    layout.addWidget(self.name_input)

    # Materials table
    self.table = QTableWidget()
    self.table.setColumnCount(2)
    self.table.setHorizontalHeaderLabels(["مواد اولیه", "مقدار (گرم)"])
    layout.addWidget(self.table)

    # Add material
    form_layout = QFormLayout()
    self.material_combo = QComboBox()
    self.material_combo.addItems(self.get_material_names())
    self.quantity_input = QLineEdit()
    form_layout.addRow("مواد اولیه:", self.material_combo)
    form_layout.addRow("مقدار (گرم):", self.quantity_input)

    add_material_button = QPushButton("اضافه کردن ماده")
    add_material_button.clicked.connect(self.add_material)
    form_layout.addWidget(add_material_button)
    layout.addLayout(form_layout)

    # Save button
    save_button = QPushButton("ذخیره رسپی")
    save_button.clicked.connect(self.save_recipe)
    layout.addWidget(save_button)

    if recipe_name:
        self.load_recipe()

def get_material_names(self):
    """Get all material names from the database."""
    conn = sqlite3.connect("coffee_shop.db")
    cursor = conn.cursor()
    cursor.execute("SELECT name FROM materials")
    materials = [row[0] for row in cursor.fetchall()]
    conn.close()
    return materials

def load_recipe(self):
    """Load the selected recipe details."""
    conn = sqlite3.connect("coffee_shop.db")
    cursor = conn.cursor()
    cursor.execute("""
        SELECT m.name, rd.quantity
        FROM recipe_details rd
        JOIN materials m ON rd.material_id = m.id
        WHERE rd.recipe_id = (SELECT id FROM recipes WHERE name = ?)
    """, (self.recipe_name,))
    materials = cursor.fetchall()
    conn.close()

    self.table.setRowCount(len(materials))
    for row, (material_name, quantity) in enumerate(materials):
        self.table.setItem(row, 0, QTableWidgetItem(material_name))
        self.table.setItem(row, 1, QTableWidgetItem(str(quantity)))

def add_material(self):
    """Add a material to the recipe."""
    material_name = self.material_combo.currentText()
    quantity = self.quantity_input.text()
    if not quantity:
        QMessageBox.warning(self, "خطا", "لطفاً مقدار را وارد کنید.")
        return

    try:
        quantity = float(quantity)
    except ValueError:
        QMessageBox.warning(self, "خطا", "مقدار باید عدد باشد.")
        return

    current_row_count = self.table.rowCount()
    self.table.insertRow(current_row_count)
    self.table.setItem(current_row_count, 0, QTableWidgetItem(material_name))
    self.table.setItem(current_row_count, 1, QTableWidgetItem(str(quantity)))

def save_recipe(self):
    """Save the recipe to the database."""
    recipe_name = self.name_input.text()
    if not recipe_name:
        QMessageBox.warning(self, "خطا", "لطفاً نام رسپی را وارد کنید.")
        return

    materials = []
    for row in range(self.table.rowCount()):
        material_name = self.table.item(row, 0).text()
        quantity = self.table.item(row, 1).text()
        try:
            quantity = float(quantity)
            materials.append((material_name, quantity))
        except ValueError:
            QMessageBox.warning(self, "خطا", f"مقدار برای '{material_name}' نامعتبر است.")
            return

    conn = sqlite3.connect("coffee_shop.db")
    cursor = conn.cursor()

    if self.recipe_name:  # Update existing recipe
        cursor.execute("UPDATE recipes SET name = ? WHERE name = ?", (recipe_name, self.recipe_name))
        cursor.execute("DELETE FROM recipe_details WHERE recipe_id = (SELECT id FROM recipes WHERE name = ?)",
                       (recipe_name,))
    else:  # Insert new recipe
        cursor.execute("INSERT INTO recipes (name) VALUES (?)", (recipe_name,))
    recipe_id = cursor.execute("SELECT id FROM recipes WHERE name = ?", (recipe_name,)).fetchone()[0]

    for material_name, quantity in materials:
        material_id = cursor.execute("SELECT id FROM materials WHERE name = ?", (material_name,)).fetchone()[0]
        cursor.execute("INSERT INTO recipe_details (recipe_id, material_id, quantity) VALUES (?, ?, ?)",
                       (recipe_id, material_id, quantity))

    conn.commit()
    conn.close()
    QMessageBox.information(self, "موفقیت", "رسپی با موفقیت ذخیره شد.")
    self.accept()
class MenuDialog(QDialog):
def init(self, parent=None):
super().init(parent)
self.setWindowTitle("نمایش منو")
self.setStyleSheet("background-color: #2E2E2E; color: white; font-family: B Nazanin;")
self.setGeometry(100, 100, 800, 500)


    layout = QVBoxLayout(self)

    # Table
    self.table = QTableWidget()
    self.table.setColumnCount(2)
    self.table.setHorizontalHeaderLabels(["نام محصول", "قیمت نهایی (تومان)"])
    self.refresh_menu()
    layout.addWidget(self.table)

    # Export button
    export_button = QPushButton("ذخیره به PDF")
    export_button.clicked.connect(self.export_to_pdf)
    layout.addWidget(export_button)

def refresh_menu(self):
    """Fetch menu items and display them in the table."""
    prices = self.calculate_prices()
    self.table.setRowCount(len(prices))
    for row, (name, final_price) in enumerate(prices):
        self.table.setItem(row, 0, QTableWidgetItem(name))
        self.table.setItem(row, 1, QTableWidgetItem(str(final_price)))

def calculate_prices(self):
    """Calculate prices for each recipe."""
    conn = sqlite3.connect("coffee_shop.db")
    cursor = conn.cursor()
    cursor.execute("""
        SELECT r.name, 
               SUM(rd.quantity * m.price_per_gram) AS raw_price
        FROM recipes r
        JOIN recipe_details rd ON r.id = rd.recipe_id
        JOIN materials m ON rd.material_id = m.id
        GROUP BY r.id
    """)
    data = cursor.fetchall()
    conn.close()

    prices = []
    for name, raw_price in data:
        if raw_price is None:
            continue
        raw_price = round(raw_price, 2)
        selling_price = round(raw_price * 3.3, 2)
        price_with_tax = round(selling_price * 1.1, 2)
        final_price = math.ceil(price_with_tax)
        prices.append((name, final_price))
    return prices

def export_to_pdf(self):
    """Export the menu to a PDF file."""
    file_path, _ = QFileDialog.getSaveFileName(self, "ذخیره فایل", filter="PDF Files (*.pdf)")
    if not file_path:
        return

    prices = self.calculate_prices()
    if not prices:
        QMessageBox.warning(self, "خطا", "هیچ محصولی برای ذخیره وجود ندارد.")
        return

    try:
        c = canvas.Canvas(file_path, pagesize=letter)
        c.setFont("Helvetica", 12)
        c.drawString(30, 750, "گزارش منوی کافی‌شاپ")
        y = 730
        for name, final_price in prices:
            c.drawString(30, y, f"{name}: {final_price} تومان")
            y -= 20
            if y < 50:  # Create a new page if the content exceeds one page
                c.showPage()
                c.setFont("Helvetica", 12)
                y = 750
        c.save()
        QMessageBox.information(self, "موفقیت", "منو با موفقیت به PDF ذخیره شد.")
    except Exception as e:
        QMessageBox.critical(self, "خطا", f"خطایی رخ داد: {str(e)}")
if name == "main":
# Initialize SQLite database
def init_db():
conn = sqlite3.connect("coffee_shop.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS materials (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
price_per_gram REAL NOT NULL
)
""")
cursor.execute("""
CREATE TABLE IF NOT EXISTS recipes (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL
)
""")
cursor.execute("""
CREATE TABLE IF NOT EXISTS recipe_details (
recipe_id INTEGER NOT NULL,
material_id INTEGER NOT NULL,
quantity REAL NOT NULL,
FOREIGN KEY(recipe_id) REFERENCES recipes(id),
FOREIGN KEY(material_id) REFERENCES materials(id)
)
""")
conn.commit()
conn.close()


init_db()

app = QApplication([])
window = ModernMainWindow()
window.show()
app.exec() 
به بخش نمایش منو ویژگیهای زیر رو اضافه کن:

قیمت اولیه : قیمت خام مجموع مواد اولیه
قیمت ثانویه : قیمت اولیه ضربدر 3.3
قیمت : قیمت ثانویه + 10% مالیات

همچنین جداول و صفحات جدید برنامه رو زیباتر و خواناتر کن
و در انتها کل کد رو با این تغییرات بهم بده
و مطمئن شو همه ی بخش های برنامه سالم کار کنند