📖 Теория

⚡ Кратко

  • Базовый класс Receipt хранит ID и сумму.
  • SaleReceipt и ReturnReceipt валидируют знак суммы.
  • Shift управляет чеками и считает итоги по типам.
  • Миксины уведомлений требуют полей через hasattr.

Система чеков

Базовый класс Receipt хранит общие данные: ID и сумму. Наследники отвечают за валидацию знака суммы и формат строкового представления.

class Receipt:
    def __init__(self, receipt_id: int, amount: float) -> None:
        self.id = receipt_id
        self.amount = amount

    def __str__(self) -> str:
        return f"{self.__class__.__name__} {self.id}: {self.amount}"

SaleReceipt и ReturnReceipt

class SaleReceipt(Receipt):
    def __init__(self, receipt_id: int, amount: float) -> None:
        if amount <= 0:
            raise ValueError("SaleReceipt amount must be positive.")
        super().__init__(receipt_id, amount)

    def __str__(self) -> str:
        return f"{self.__class__.__name__} {self.id}: +{self.amount}"


class ReturnReceipt(Receipt):
    def __init__(self, receipt_id: int, amount: float) -> None:
        if amount >= 0:
            raise ValueError("ReturnReceipt amount must be negative.")
        super().__init__(receipt_id, amount)

    def __str__(self) -> str:
        return f"{self.__class__.__name__} {self.id}: {self.amount}"

Класс Shift

Смена содержит список чеков и флаг закрытия. Методы позволяют добавлять продажи и возвраты, закрывать смену и считать итоги по типам.

Миксины уведомлений

class EmailNotifyMixin:
    def email_notify(self, message: str) -> None:
        if not hasattr(self, "email"):
            raise AttributeError("Missing 'email'")
        print(f"Email to {self.email}: {message}")