From 9c905f22de4fa2e2f60ea9d473c14cb075a244e2 Mon Sep 17 00:00:00 2001 From: Tolmachev Igor Date: Thu, 26 Mar 2026 16:23:52 +0300 Subject: Add invoices command --- libs/__init__.py | 3 ++- libs/invoice.py | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 libs/invoice.py (limited to 'libs') diff --git a/libs/__init__.py b/libs/__init__.py index 65f8ab7..55e6b19 100644 --- a/libs/__init__.py +++ b/libs/__init__.py @@ -1,8 +1,9 @@ -from . import fsm, msg, storage, user +from . import fsm, invoice, msg, storage, user __all__ = [ "storage", "fsm", "msg", "user", + "invoice", ] diff --git a/libs/invoice.py b/libs/invoice.py new file mode 100644 index 0000000..92b82f7 --- /dev/null +++ b/libs/invoice.py @@ -0,0 +1,69 @@ +from enum import StrEnum, auto + +from pydantic import BaseModel +from sqlalchemy import and_, select +from sqlalchemy.ext.asyncio import AsyncSession + +from models import Invoice, Payment, PaymentStatus, User, UserRole + + +class InvoiceStatus(StrEnum): + PAID = auto() + UNPAID = auto() + + +class InvoicePayments(BaseModel): + user_status: dict[int, PaymentStatus] + status: InvoiceStatus + + +async def get_invoice_payments( + session: AsyncSession, + invoice: Invoice, +) -> InvoicePayments: + users = await session.scalars( + select(User).where( + and_( + User.role != UserRole.ADMIN, + User.datetime <= invoice.datetime, + ) + ) + ) + payments = await session.scalars( + select(Payment).where(Payment.invoice_id == invoice.id) + ) + + user_status = {u.id: PaymentStatus.REJECTED for u in users} + for p in payments: + if ( + p.status != PaymentStatus.REJECTED + and user_status[p.user_id] == PaymentStatus.REJECTED + ): + user_status[p.user_id] = p.status + + status = ( + InvoiceStatus.PAID + if all(s == PaymentStatus.ACCEPTED for s in user_status.values()) + else InvoiceStatus.UNPAID + ) + + return InvoicePayments(user_status=user_status, status=status) + + +async def get_payment_status( + session: AsyncSession, + invoice_id: int, + user_id: int, +) -> PaymentStatus: + payments = await session.scalars( + select(Payment).where( + and_( + Payment.invoice_id == invoice_id, + Payment.user_id == user_id, + ) + ) + ) + for p in payments: + if p.status != PaymentStatus.REJECTED: + return p.status + return PaymentStatus.REJECTED -- cgit v1.3