common update

This commit is contained in:
2025-06-18 11:48:41 +07:00
parent 88c4ee362e
commit 047290e2ea
27 changed files with 1533 additions and 87 deletions
+103
View File
@@ -0,0 +1,103 @@
from typing import List, Optional
from datetime import datetime
from models.debt_group import HomeMember, Expense, ExpenseShare
from infra.db import postgres
class HomeDebtRepository:
_instance = None
_initialized = False
def __new__(cls):
if cls._instance is None:
cls._instance = super(HomeDebtRepository, cls).__new__(cls)
return cls._instance
def __init__(self):
if not HomeDebtRepository._initialized:
self.db = postgres.get_table('home_members')
HomeDebtRepository._initialized = True
async def add_member(self, discord_user_id: int, name: str) -> HomeMember:
"""Thêm thành viên mới vào nhà"""
data = await self.db.table("home_members").insert({
"discord_user_id": discord_user_id,
"name": name
}).execute()
return HomeMember(**data.data[0])
async def get_member(self, discord_user_id: int) -> Optional[HomeMember]:
"""Lấy thông tin thành viên theo discord_user_id"""
data = await self.db.table("home_members").select("*").eq("discord_user_id", discord_user_id).execute()
if not data.data:
return None
return HomeMember(**data.data[0])
async def get_all_members(self) -> List[HomeMember]:
"""Lấy danh sách tất cả thành viên"""
data = await self.db.table("home_members").select("*").execute()
return [HomeMember(**member) for member in data.data]
async def add_expense(self, amount: float, description: str, paid_by: int) -> Expense:
"""Thêm khoản chi tiêu mới"""
# Tạo expense
expense_data = await self.db.table("expenses").insert({
"amount": amount,
"description": description,
"paid_by": paid_by
}).execute()
expense = Expense(**expense_data.data[0])
# Lấy danh sách thành viên
members = await self.get_all_members()
share_amount = amount / len(members)
# Tạo expense shares cho từng thành viên
for member in members:
await self.db.table("expense_shares").insert({
"expense_id": expense.id,
"member_id": member.discord_user_id,
"share_amount": share_amount,
"is_paid": member.discord_user_id == paid_by # Người trả tiền được đánh dấu là đã trả
}).execute()
return expense
async def get_expense(self, expense_id: int) -> Optional[Expense]:
"""Lấy thông tin khoản chi tiêu"""
data = await self.db.table("expenses").select("*").eq("id", expense_id).execute()
if not data.data:
return None
return Expense(**data.data[0])
async def get_all_expenses(self) -> List[Expense]:
"""Lấy danh sách tất cả khoản chi tiêu"""
data = await self.db.table("expenses").select("*").order("created_at", desc=True).execute()
return [Expense(**expense) for expense in data.data]
async def get_expense_shares(self, expense_id: int) -> List[ExpenseShare]:
"""Lấy danh sách chia tiền của một khoản chi tiêu"""
data = await self.db.table("expense_shares").select("*").eq("expense_id", expense_id).execute()
return [ExpenseShare(**share) for share in data.data]
async def mark_share_as_paid(self, share_id: int) -> Optional[ExpenseShare]:
"""Đánh dấu một phần chia tiền đã được trả"""
data = await self.db.table("expense_shares").update({
"is_paid": True
}).eq("id", share_id).execute()
if not data.data:
return None
return ExpenseShare(**data.data[0])
async def get_member_balance(self, discord_user_id: int) -> float:
"""Tính số dư của một thành viên (số tiền phải trả - số tiền đã trả)"""
# Lấy tất cả expense shares của thành viên
data = await self.db.table("expense_shares").select("*").eq("member_id", discord_user_id).execute()
shares = [ExpenseShare(**share) for share in data.data]
# Tính tổng số tiền phải trả
total_owed = sum(share.share_amount for share in shares)
# Tính tổng số tiền đã trả
total_paid = sum(share.share_amount for share in shares if share.is_paid)
return total_owed - total_paid