Добавлено новое поле promocode в модель StatReferralsItem и модель Ref. Обновлены функции в fill_db.py для генерации уникальных промокодов при создании реферальных ссылок. Обновлены эндпоинты в integration_api.py для возврата промокодов вместе с реферальными ссылками. Удалены устаревшие функции работы с промокодами из кода. Обновлены SQL-скрипты и модели для учета новых полей.

This commit is contained in:
Redsandyg 2025-06-15 17:03:41 +03:00
parent 92df59ad23
commit d113ae4adb
8 changed files with 28 additions and 100 deletions

View File

@ -89,6 +89,7 @@ class StatReferralsItem(BaseModel):
ref: str ref: str
agent: Optional[str] = None agent: Optional[str] = None
description: str description: str
promocode: str
salesSum: float salesSum: float
salesCount: int salesCount: int

View File

@ -1,7 +1,7 @@
import random import random
from uuid import uuid4 from uuid import uuid4
from sqlmodel import Session from sqlmodel import Session
from sql_models import TgAgent, Ref, Sale, Account, Company, AgentTransaction, PartnerTransaction, CompanyBalance, AgentBalance, IntegrationToken, PromoCode from sql_models import TgAgent, Ref, Sale, Account, Company, AgentTransaction, PartnerTransaction, CompanyBalance, AgentBalance, IntegrationToken
from sqlalchemy import text from sqlalchemy import text
from datetime import datetime, timedelta from datetime import datetime, timedelta
from hashlib import sha256 from hashlib import sha256
@ -72,7 +72,7 @@ def fill_db():
date_list = get_date_list(7) # 8 дней: от недели назад до сегодня date_list = get_date_list(7) # 8 дней: от недели назад до сегодня
with Session(AUTH_DB_ENGINE) as session: with Session(AUTH_DB_ENGINE) as session:
# Очистка таблиц # Очистка таблиц
session.execute(text("DELETE FROM promocode")) # session.execute(text("DELETE FROM promocode"))
session.execute(text("DELETE FROM sale")) session.execute(text("DELETE FROM sale"))
session.execute(text("DELETE FROM ref")) session.execute(text("DELETE FROM ref"))
session.execute(text("DELETE FROM tgagent")) session.execute(text("DELETE FROM tgagent"))
@ -154,45 +154,25 @@ def fill_db():
# Отладка: количество агентов # Отладка: количество агентов
agent_count = session.execute(text("SELECT COUNT(*) FROM tgagent")).scalar() agent_count = session.execute(text("SELECT COUNT(*) FROM tgagent")).scalar()
print(f'Агентов в базе: {agent_count}') print(f'Агентов в базе: {agent_count}')
# Генерация промокодов для каждого агента с try/except
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
try:
for tg_agent in tg_agents:
promocode_count = random.randint(2, 4)
for _ in range(promocode_count):
promocode = ''.join(random.choices(alphabet, k=8))
# Проверяем уникальность
while session.execute(text("SELECT 1 FROM promocode WHERE promocode = :code"), {"code": promocode}).first():
promocode = ''.join(random.choices(alphabet, k=8))
promo = PromoCode(
promocode=promocode,
perc=10.0,
agent_id=tg_agent.id,
description=random.choice(DESCRIPTIONS),
create_dttm=datetime.utcnow(),
update_dttm=datetime.utcnow()
)
session.add(promo)
session.commit()
except Exception as e:
print(f'Ошибка при добавлении промокодов: {e}')
session.rollback()
# Отладка: количество промокодов
count = session.execute(text("SELECT COUNT(*) FROM promocode")).scalar()
print(f'Промокодов в базе: {count}')
# 3. Refs (минимум 22 на агента) # 3. Refs (минимум 22 на агента)
refs = [] refs = []
desc_count = len(ALL_DESCRIPTIONS) desc_count = len(ALL_DESCRIPTIONS)
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
for tg_agent in tg_agents: for tg_agent in tg_agents:
ref_count = random.randint(22, int(22 * 1.25)) # от 22 до 27 ref_count = random.randint(22, int(22 * 1.25)) # от 22 до 27
for j in range(ref_count): for j in range(ref_count):
ref_val = str(uuid4()) ref_val = str(uuid4())
desc_val = ALL_DESCRIPTIONS[(j % desc_count)] desc_val = ALL_DESCRIPTIONS[(j % desc_count)]
dt = random.choice(date_list) dt = random.choice(date_list)
promocode = ''.join(random.choices(alphabet, k=8))
# Проверяем уникальность промокода среди уже созданных рефов
while any(r.promocode == promocode for r in refs):
promocode = ''.join(random.choices(alphabet, k=8))
ref = Ref( ref = Ref(
tg_agent_id=tg_agent.id, tg_agent_id=tg_agent.id,
ref=ref_val, ref=ref_val,
description=desc_val, description=desc_val,
promocode=promocode,
create_dttm=dt, create_dttm=dt,
update_dttm=dt update_dttm=dt
) )

View File

@ -1,5 +1,4 @@
from sqlmodel import SQLModel from sqlmodel import SQLModel
from sql_models import Company, TgAgent, Ref, Sale, AgentTransaction, PartnerTransaction, CompanyBalance, AgentBalance, Account, IntegrationToken, PromoCode
from helpers_bff import AUTH_DB_ENGINE from helpers_bff import AUTH_DB_ENGINE
from sqlalchemy.schema import CreateTable from sqlalchemy.schema import CreateTable
import os import os

View File

@ -7,10 +7,10 @@ import uuid
from random import choices from random import choices
import string import string
from sql_models import Company, IntegrationToken, Ref, Sale, AgentTransaction, PartnerTransaction, AgentBalance, TgAgent, CompanyBalance, PromoCode from sql_models import Company, IntegrationToken, Ref, Sale, AgentTransaction, PartnerTransaction, AgentBalance, TgAgent, CompanyBalance
from integration_models import Token, SaleCreateRequest, SaleCreateResponse, TransactionStatus, WithdrawRequest, WithdrawResponse from integration_models import Token, SaleCreateRequest, SaleCreateResponse, TransactionStatus, WithdrawRequest, WithdrawResponse
from bff_models import RegisterResponse, TgAuthResponse from bff_models import RegisterResponse, TgAuthResponse
from tg_models import RefAddRequest, RefResponse, RefAddResponse, RefStatResponse, RegisterRequest, StatResponse, PromoCodeAddRequest, PromoCodeResponse from tg_models import RefAddRequest, RefResponse, RefAddResponse, RefStatResponse, RegisterRequest, StatResponse
from helpers_bff import AUTH_DB_ENGINE, get_integration_db, create_integration_jwt_token, get_current_company_from_jwt, get_tg_agent_by_tg_id, get_current_tg_agent from helpers_bff import AUTH_DB_ENGINE, get_integration_db, create_integration_jwt_token, get_current_company_from_jwt, get_tg_agent_by_tg_id, get_current_tg_agent
app = FastAPI() app = FastAPI()
@ -61,22 +61,28 @@ def get_refs(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Sess
Возвращает список реферальных ссылок текущего Telegram-агента. Возвращает список реферальных ссылок текущего Telegram-агента.
""" """
refs = db.exec(select(Ref).where(Ref.tg_agent_id == current_tg_agent.id)).all() refs = db.exec(select(Ref).where(Ref.tg_agent_id == current_tg_agent.id)).all()
return [RefResponse(ref=r.ref, description=r.description or "") for r in refs] return [RefResponse(ref=r.ref, description=r.description or "", promocode=r.promocode) for r in refs]
@app.post("/ref/add", tags=["agent-tg"], response_model=RefAddResponse) @app.post("/ref/add", tags=["agent-tg"], response_model=RefAddResponse)
def add_ref(req: RefAddRequest, current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_integration_db)): def add_ref(req: RefAddRequest, current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_integration_db)):
""" """
Добавляет новую реферальную ссылку для текущего Telegram-агента. Добавляет новую реферальную ссылку для текущего Telegram-агента.
""" """
# Генерация промокода (логика как была для промокодов)
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
promocode = ''.join(choices(alphabet, k=8))
while db.exec(select(Ref).where(Ref.promocode == promocode)).first():
promocode = ''.join(choices(alphabet, k=8))
new_ref = Ref( new_ref = Ref(
tg_agent_id=current_tg_agent.id, tg_agent_id=current_tg_agent.id,
ref=str(uuid.uuid4()), ref=str(uuid.uuid4()),
description=req.description description=req.description,
promocode=promocode
) )
db.add(new_ref) db.add(new_ref)
db.commit() db.commit()
db.refresh(new_ref) db.refresh(new_ref)
return {"ref": new_ref.ref} return {"ref": new_ref.ref, "promocode": new_ref.promocode, "description": new_ref.description}
@app.get("/ref/stat", tags=["agent-tg"], response_model=RefStatResponse) @app.get("/ref/stat", tags=["agent-tg"], response_model=RefStatResponse)
def get_ref_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_integration_db)): def get_ref_stat(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_integration_db)):
@ -306,32 +312,3 @@ def register(req: RegisterRequest, db: Session = Depends(get_integration_db)):
db.commit() db.commit()
db.refresh(new_tg_agent) db.refresh(new_tg_agent)
return {"msg": "TgAgent registered successfully"} return {"msg": "TgAgent registered successfully"}
@app.post("/promocode/add", tags=["agent-tg"], response_model=PromoCodeResponse)
def add_promocode(req: PromoCodeAddRequest, current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_integration_db)):
"""
Создает новый промокод для текущего Telegram-агента.
"""
description = req.description
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
promocode = ''.join(choices(alphabet, k=8))
while db.exec(select(PromoCode).where(PromoCode.promocode == promocode)).first():
promocode = ''.join(choices(alphabet, k=8))
new_code = PromoCode(
promocode=promocode,
perc=10.0,
agent_id=current_tg_agent.id,
description=description
)
db.add(new_code)
db.commit()
db.refresh(new_code)
return PromoCodeResponse(promocode=new_code.promocode, perc=new_code.perc, description=new_code.description)
@app.get("/promocode", tags=["agent-tg"], response_model=List[PromoCodeResponse])
def get_promocodes(current_tg_agent: TgAgent = Depends(get_current_tg_agent), db: Session = Depends(get_integration_db)):
"""
Получает все промокоды текущего Telegram-агента.
"""
codes = db.exec(select(PromoCode).where(PromoCode.agent_id == current_tg_agent.id)).all()
return [PromoCodeResponse(promocode=c.promocode, perc=c.perc, description=c.description) for c in codes]

View File

@ -252,6 +252,7 @@ def get_referrals_stat(
"ref": ref.ref, "ref": ref.ref,
"agent": agent.name if agent and agent.name else f"Агент {ref.tg_agent_id}", "agent": agent.name if agent and agent.name else f"Агент {ref.tg_agent_id}",
"description": ref.description or "", "description": ref.description or "",
"promocode": ref.promocode,
"salesSum": sales_sum, "salesSum": sales_sum,
"salesCount": sales_count "salesCount": sales_count
}) })

View File

@ -110,26 +110,12 @@ CREATE TABLE agent_transactions (
; ;
CREATE TABLE promocode (
id INTEGER NOT NULL,
promocode VARCHAR NOT NULL,
perc FLOAT NOT NULL,
agent_id INTEGER NOT NULL,
description VARCHAR,
create_dttm DATETIME NOT NULL,
update_dttm DATETIME NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY(agent_id) REFERENCES tgagent (id)
)
;
CREATE TABLE ref ( CREATE TABLE ref (
id INTEGER NOT NULL, id INTEGER NOT NULL,
tg_agent_id INTEGER NOT NULL, tg_agent_id INTEGER NOT NULL,
ref VARCHAR NOT NULL, ref VARCHAR NOT NULL,
description VARCHAR, description VARCHAR,
promocode VARCHAR(8) NOT NULL,
create_dttm DATETIME NOT NULL, create_dttm DATETIME NOT NULL,
update_dttm DATETIME NOT NULL, update_dttm DATETIME NOT NULL,
PRIMARY KEY (id), PRIMARY KEY (id),

View File

@ -37,13 +37,13 @@ class TgAgent(SQLModel, table=True):
refs: List["Ref"] = Relationship(back_populates="tg_agent") refs: List["Ref"] = Relationship(back_populates="tg_agent")
agent_transactions: List["AgentTransaction"] = Relationship(back_populates="tg_agent") agent_transactions: List["AgentTransaction"] = Relationship(back_populates="tg_agent")
agent_balance: Optional["AgentBalance"] = Relationship(back_populates="tg_agent") agent_balance: Optional["AgentBalance"] = Relationship(back_populates="tg_agent")
promocodes: List["PromoCode"] = Relationship(back_populates="agent")
class Ref(SQLModel, table=True): class Ref(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True) id: Optional[int] = Field(default=None, primary_key=True)
tg_agent_id: int = Field(foreign_key="tgagent.id") tg_agent_id: int = Field(foreign_key="tgagent.id")
ref: str ref: str
description: Optional[str] = None description: Optional[str] = None
promocode: str = Field(index=True, unique=True, max_length=8)
create_dttm: datetime = Field(default_factory=datetime.utcnow) create_dttm: datetime = Field(default_factory=datetime.utcnow)
update_dttm: datetime = Field(default_factory=datetime.utcnow) update_dttm: datetime = Field(default_factory=datetime.utcnow)
@ -138,14 +138,3 @@ class IntegrationToken(SQLModel, table=True):
use_dttm: Optional[datetime] = None use_dttm: Optional[datetime] = None
company: "Company" = Relationship(back_populates="integration_tokens") company: "Company" = Relationship(back_populates="integration_tokens")
class PromoCode(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
promocode: str = Field(index=True, unique=True)
perc: float = Field(default=10.0)
agent_id: int = Field(foreign_key="tgagent.id")
description: Optional[str] = None
create_dttm: datetime = Field(default_factory=datetime.utcnow)
update_dttm: datetime = Field(default_factory=datetime.utcnow)
agent: "TgAgent" = Relationship(back_populates="promocodes")

View File

@ -7,6 +7,7 @@ from uuid import UUID
class RefResponse(BaseModel): class RefResponse(BaseModel):
ref: str ref: str
description: str description: str
promocode: str
class RefAddRequest(BaseModel): class RefAddRequest(BaseModel):
description: str description: str
@ -25,6 +26,8 @@ class RegisterRequest(BaseModel):
# New Response Models for TG APIs # New Response Models for TG APIs
class RefAddResponse(BaseModel): class RefAddResponse(BaseModel):
ref: str ref: str
promocode: str
description: str
class RefStatItem(BaseModel): class RefStatItem(BaseModel):
description: str description: str
@ -38,11 +41,3 @@ class StatResponse(BaseModel):
totalSales: int totalSales: int
totalIncome: float totalIncome: float
availableWithdrawal: float availableWithdrawal: float
class PromoCodeAddRequest(BaseModel):
description: Optional[str] = None
class PromoCodeResponse(BaseModel):
promocode: str
perc: float
description: Optional[str] = None