aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorTolmachev Igor <me@igorek.dev>2026-03-26 16:23:52 +0300
committerTolmachev Igor <me@igorek.dev>2026-03-26 16:23:52 +0300
commit9c905f22de4fa2e2f60ea9d473c14cb075a244e2 (patch)
tree366fa6c5fb5bbe1d29e383effa7df816cadf22a4 /libs
parent4d0f8a48502dfa6bc7e9b39444573fe7377bdfce (diff)
downloadvpn_manager_bot-9c905f22de4fa2e2f60ea9d473c14cb075a244e2.tar.gz
vpn_manager_bot-9c905f22de4fa2e2f60ea9d473c14cb075a244e2.zip
Add invoices command
Diffstat (limited to 'libs')
-rw-r--r--libs/__init__.py3
-rw-r--r--libs/invoice.py69
2 files changed, 71 insertions, 1 deletions
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 @@
1from . import fsm, msg, storage, user 1from . import fsm, invoice, msg, storage, user
2 2
3__all__ = [ 3__all__ = [
4 "storage", 4 "storage",
5 "fsm", 5 "fsm",
6 "msg", 6 "msg",
7 "user", 7 "user",
8 "invoice",
8] 9]
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 @@
1from enum import StrEnum, auto
2
3from pydantic import BaseModel
4from sqlalchemy import and_, select
5from sqlalchemy.ext.asyncio import AsyncSession
6
7from models import Invoice, Payment, PaymentStatus, User, UserRole
8
9
10class InvoiceStatus(StrEnum):
11 PAID = auto()
12 UNPAID = auto()
13
14
15class InvoicePayments(BaseModel):
16 user_status: dict[int, PaymentStatus]
17 status: InvoiceStatus
18
19
20async def get_invoice_payments(
21 session: AsyncSession,
22 invoice: Invoice,
23) -> InvoicePayments:
24 users = await session.scalars(
25 select(User).where(
26 and_(
27 User.role != UserRole.ADMIN,
28 User.datetime <= invoice.datetime,
29 )
30 )
31 )
32 payments = await session.scalars(
33 select(Payment).where(Payment.invoice_id == invoice.id)
34 )
35
36 user_status = {u.id: PaymentStatus.REJECTED for u in users}
37 for p in payments:
38 if (
39 p.status != PaymentStatus.REJECTED
40 and user_status[p.user_id] == PaymentStatus.REJECTED
41 ):
42 user_status[p.user_id] = p.status
43
44 status = (
45 InvoiceStatus.PAID
46 if all(s == PaymentStatus.ACCEPTED for s in user_status.values())
47 else InvoiceStatus.UNPAID
48 )
49
50 return InvoicePayments(user_status=user_status, status=status)
51
52
53async def get_payment_status(
54 session: AsyncSession,
55 invoice_id: int,
56 user_id: int,
57) -> PaymentStatus:
58 payments = await session.scalars(
59 select(Payment).where(
60 and_(
61 Payment.invoice_id == invoice_id,
62 Payment.user_id == user_id,
63 )
64 )
65 )
66 for p in payments:
67 if p.status != PaymentStatus.REJECTED:
68 return p.status
69 return PaymentStatus.REJECTED