From 679eb2119eea68ba86b15d9165d5379e908a0327 Mon Sep 17 00:00:00 2001 From: virtus Date: Mon, 21 Jul 2025 15:51:54 +0700 Subject: [PATCH] adding calculate currency for bussiness group --- apps/cmc_currency.py | 53 ++++++++++++++++++++++++++++++++++++++++++++ core/bot.py | 4 +++- main.py | 2 +- models/cmc_debt.py | 21 ++++++++++++++++++ repositories/debt.py | 52 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 apps/cmc_currency.py create mode 100644 models/cmc_debt.py create mode 100644 repositories/debt.py diff --git a/apps/cmc_currency.py b/apps/cmc_currency.py new file mode 100644 index 0000000..e80d03c --- /dev/null +++ b/apps/cmc_currency.py @@ -0,0 +1,53 @@ +import discord +from core.bot import bot, CHANNEL_CMC_CURRENCY_ID, OWNER_CHANNEL_CMC_CURRENCY_ID +from utils.common import format_vnd +from repositories.debt import DebtRepository +from discord.ext import commands +import math + +# Sử dụng quyền admin hoặc owner để xác định chủ nhóm + +debt_repo = DebtRepository() + +def is_correct_channel(ctx): + """Kiểm tra xem command có được thực hiện trong đúng channel không""" + return ctx.channel.id == CHANNEL_CMC_CURRENCY_ID + +def is_owner(ctx: commands.Context): + """Kiểm tra xem user có phải là chủ nhóm không""" + return ctx.author.id == OWNER_CHANNEL_CMC_CURRENCY_ID + +@bot.command(name="zadd") +async def zadd(ctx: commands.Context, amount: int, *names): + if not is_correct_channel(ctx): + return + if not is_owner(ctx): + await ctx.send("Bạn không có quyền sử dụng lệnh này!") + return + if not names: + await ctx.send("Bạn phải nhập ít nhất 1 tên!") + return + per_person = int(math.ceil(amount / len(names))) + msg = f"Chia {format_vnd(amount*1000)} cho {len(names)} người, mỗi người: {format_vnd(per_person*1000)}\n" + await ctx.send(msg) + +@bot.command(name="zminus") +async def zminus(ctx: commands.Context, name: str, amount: int): + if not is_correct_channel(ctx): + return + await debt_repo.minus_debt(name, amount) + await ctx.send(f"Đã trừ {format_vnd(amount*1000)} cho {name}") + +@bot.command(name="zcheck") +async def zcheck(ctx: commands.Context): + if not is_correct_channel(ctx): + return + debts = await debt_repo.get_all() + if not debts: + await ctx.send("Không ai nợ chủ nhóm!") + return + msg = "Tình hình nợ hiện tại:\n" + for d in debts: + msg += f"{d.name}: {format_vnd(d.amount*1000)}\n" + await ctx.send(msg) + diff --git a/core/bot.py b/core/bot.py index 6e73f4f..97a0847 100644 --- a/core/bot.py +++ b/core/bot.py @@ -22,6 +22,8 @@ currency_repo = CurrencyRepository() CHANNEL_HOME_DEBT_ID = int(os.getenv('CHANNEL_HOME_DEBT_ID', 0)) CHANNEL_NOI_TU_ID = int(os.getenv('CHANNEL_NOI_TU_ID', 0)) +CHANNEL_CMC_CURRENCY_ID = int(os.getenv('CHANNEL_CMC_CURRENCY_ID', 0)) +OWNER_CHANNEL_CMC_CURRENCY_ID = int(os.getenv('OWNER_CHANNEL_CMC_CURRENCY_ID', 0)) @bot.tree.command(name='help', description='Show help') @@ -40,7 +42,7 @@ async def help(interaction: discord.Interaction): CHANNEL_NOI_TU_ID: [ "!start", "!end" - ] + ], } # Kiểm tra xem channel có trong danh sách không diff --git a/main.py b/main.py index ea67d7e..e8c9d05 100644 --- a/main.py +++ b/main.py @@ -2,7 +2,7 @@ import os from dotenv import load_dotenv from core import events, tasks from core.bot import bot -from apps import home_debt, currency, noi_tu +from apps import home_debt, currency, noi_tu, cmc_currency # Load environment variables load_dotenv() diff --git a/models/cmc_debt.py b/models/cmc_debt.py new file mode 100644 index 0000000..ad34c3c --- /dev/null +++ b/models/cmc_debt.py @@ -0,0 +1,21 @@ +from dataclasses import dataclass +from typing import Optional + +@dataclass +class CMCDebt: + id: Optional[int] + name: str + amount: int + + def to_dict(self): + if self.id is None: + return { + "name": self.name, + "amount": self.amount + } + + return { + "id": self.id, + "name": self.name, + "amount": self.amount + } \ No newline at end of file diff --git a/repositories/debt.py b/repositories/debt.py new file mode 100644 index 0000000..b950ded --- /dev/null +++ b/repositories/debt.py @@ -0,0 +1,52 @@ +from typing import List, Optional +from models.cmc_debt import CMCDebt +from infra.db import postgres + +class DebtRepository: + def __init__(self): + self.table = postgres.get_table('cmc_debts') + + async def get(self, name: str) -> Optional[CMCDebt]: + try: + response = self.table.select('*').eq('name', name).execute() + if response.data: + return CMCDebt(**response.data[0]) + return None + except Exception as e: + print(f"Error getting debt: {e}") + return None + + async def upsert_debt(self, name: str, amount: int) -> Optional[CMCDebt]: + try: + old = await self.get(name) + if old: + new_amount = old.amount + amount + response = self.table.update({"amount": new_amount}).eq('name', name).execute() + return CMCDebt(**response.data[0]) + else: + debt = CMCDebt(id=None, name=name, amount=amount) + response = self.table.insert(debt.to_dict()).execute() + return CMCDebt(**response.data[0]) + except Exception as e: + print(f"Error upserting debt: {e}") + return None + + async def minus_debt(self, name: str, amount: int) -> Optional[CMCDebt]: + try: + old = await self.get(name) + if old: + new_amount = max(0, old.amount - amount) + response = self.table.update({"amount": new_amount}).eq('name', name).execute() + return CMCDebt(**response.data[0]) + return None + except Exception as e: + print(f"Error minusing debt: {e}") + return None + + async def get_all(self) -> List[CMCDebt]: + try: + response = self.table.select('*').execute() + return [CMCDebt(**debt) for debt in response.data] + except Exception as e: + print(f"Error getting all debts: {e}") + return [] \ No newline at end of file