Обновлены идентификаторы API и добавлен генератор уникальных идентификаторов для продаж. В функции создания продажи добавлены проверки на наличие балансов агента и компании, а также улучшена логика обновления балансов. Установлен уровень изоляции для транзакций. Обновлены комментарии для ясности кода.

This commit is contained in:
Redsandyg 2025-06-11 11:01:26 +03:00
parent 1cc18e0364
commit 736f04bb7e
3 changed files with 30 additions and 52 deletions

View File

@ -1,17 +1,18 @@
import uuid
import requests import requests
import json import json
# Конфигурация API # Конфигурация API
BASE_URL = "http://127.0.0.1:8001" BASE_URL = "http://127.0.0.1:8001"
API_KEY = "7c06945b-f4b8-4929-8350-b9841405a609" API_KEY = "672a1437-70e8-461f-9bff-20f5ce4a023d"
REF = "8c514fcb-7a79-4ed1-9c8a-0af2fcab88c0" REF = "9bd1a6bd-98e1-48f4-a120-3b3d016011c0"
# Данные для запроса на создание продажи # Данные для запроса на создание продажи
# Замените эти значения на актуальные для вашей продажи # Замените эти значения на актуальные для вашей продажи
sale_data = { sale_data = {
"cost": 100.50, # Стоимость продажи "cost": 100.50, # Стоимость продажи
"ref": REF, # Ваш реферальный код "ref": REF, # Ваш реферальный код
"sale_id": "UNIQUE_SALE_ID_12345" # Уникальный идентификатор продажи для вашей компании "sale_id": str(uuid.uuid4()) # Уникальный идентификатор продажи для вашей компании
} }
# Эндпоинты # Эндпоинты

View File

@ -61,8 +61,14 @@ async def create_sale(
""" """
Регистрирует новую продажу в системе. Регистрирует новую продажу в системе.
""" """
# Устанавливаем уровень изоляции для текущей транзакции
db.connection(execution_options={'isolation_level': 'SERIALIZABLE'})
# 1. Найти Ref по `ref` и `company.id` # 1. Найти Ref по `ref` и `company.id`
# Сначала находим TgAgent, связанный с компанией, затем Ref # Сначала находим TgAgent, связанный с компанией, затем Ref
tg_agent = db.exec( tg_agent = db.exec(
select(TgAgent) select(TgAgent)
.join(Ref) .join(Ref)
@ -90,7 +96,18 @@ async def create_sale(
# 3. Рассчитать crediting # 3. Рассчитать crediting
crediting_amount = req.cost * (company.agent_commission / 100.0) crediting_amount = req.cost * (company.agent_commission / 100.0)
# 4. Создать Sale # 4. Проверить и обновить AgentBalance и CompanyBalance
# AgentBalance
agent_balance = db.exec(select(AgentBalance).where(AgentBalance.tg_agent_id == tg_agent.id)).first()
if not agent_balance:
raise HTTPException(status_code=404, detail="Баланс агента не найден")
# CompanyBalance
company_balance = db.exec(select(CompanyBalance).where(CompanyBalance.company_id == company.id)).first()
if not company_balance:
raise HTTPException(status_code=404, detail="Баланс компании не найден")
# 5. Создать Sale
new_sale = Sale( new_sale = Sale(
cost=req.cost, cost=req.cost,
crediting=crediting_amount, crediting=crediting_amount,
@ -100,28 +117,9 @@ async def create_sale(
sale_dttm=datetime.utcnow() sale_dttm=datetime.utcnow()
) )
db.add(new_sale) db.add(new_sale)
db.commit()
db.refresh(new_sale)
# 5. Обновить AgentBalance и CompanyBalance
# AgentBalance
agent_balance = db.exec(select(AgentBalance).where(AgentBalance.tg_agent_id == tg_agent.id)).first()
if not agent_balance:
agent_balance = AgentBalance(tg_agent_id=tg_agent.id, available_balance=0.0, frozen_balance=0.0)
db.add(agent_balance)
db.commit()
db.refresh(agent_balance)
# CompanyBalance
company_balance = db.exec(select(CompanyBalance).where(CompanyBalance.company_id == company.id)).first()
if not company_balance:
company_balance = CompanyBalance(company_id=company.id, available_balance=0.0, pending_balance=0.0)
db.add(company_balance)
db.commit()
db.refresh(company_balance)
# Создать AgentTransaction # Создать AgentTransaction
agent_transaction_status = TransactionStatus.NEW if company.auto_approve_transactions else TransactionStatus.WAITING agent_transaction_status = TransactionStatus.DONE # auto_approve_transactions отвечает только за апрув агентских транзакций на вывод
agent_transaction = AgentTransaction( agent_transaction = AgentTransaction(
tg_agent_id=tg_agent.id, tg_agent_id=tg_agent.id,
amount=crediting_amount, amount=crediting_amount,
@ -129,38 +127,17 @@ async def create_sale(
transaction_group=uuid.uuid4() transaction_group=uuid.uuid4()
) )
db.add(agent_transaction) db.add(agent_transaction)
db.commit()
db.refresh(agent_transaction)
# Создать PartnerTransaction # Обновление балансов для продаж - всегда в замороженный/ожидающий баланс
partner_transaction_status = TransactionStatus.NEW if company.auto_approve_transactions else TransactionStatus.PROCESS
partner_transaction = PartnerTransaction(
company_id=company.id,
type="sale_crediting",
amount=crediting_amount,
status=partner_transaction_status.value,
transaction_group=agent_transaction.transaction_group,
agent_transaction_id=agent_transaction.id
)
db.add(partner_transaction)
db.commit()
db.refresh(partner_transaction)
# Обновление балансов в зависимости от auto_approve_transactions
if company.auto_approve_transactions:
agent_balance.available_balance += crediting_amount
company_balance.available_balance -= crediting_amount
company_balance.updated_dttm = datetime.utcnow()
else:
agent_balance.frozen_balance += crediting_amount agent_balance.frozen_balance += crediting_amount
company_balance.pending_balance -= crediting_amount company_balance.pending_balance -= crediting_amount
company_balance.updated_dttm = datetime.utcnow() company_balance.updated_dttm = datetime.utcnow()
db.add(agent_balance)
db.add(company_balance)
db.commit() db.commit()
db.refresh(new_sale)
db.refresh(agent_balance) db.refresh(agent_balance)
db.refresh(company_balance) db.refresh(company_balance)
db.refresh(agent_transaction)
return { return {
"msg": "Продажа успешно зарегистрирована", "msg": "Продажа успешно зарегистрирована",

View File

@ -12,7 +12,7 @@ class Company(SQLModel, table=True):
key: str = Field(index=True, unique=True) key: str = Field(index=True, unique=True)
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)
auto_approve_transactions: bool = Field(default=False) auto_approve_transactions: bool = Field(default=False) # Отвечает за автоматическое одобрение агентских транзакций на вывод.
integration_tokens: List["IntegrationToken"] = Relationship(back_populates="company") integration_tokens: List["IntegrationToken"] = Relationship(back_populates="company")