Добавлен новый файл integration_api.py для интеграционного API, реализованы функции для создания и проверки токенов, а также эндпоинт для загрузки данных о продажах. Обновлены модели и логика работы с датами в fill_db.py и main.py для использования поля sale_date вместо create_dttm.

This commit is contained in:
Redsandyg 2025-06-09 12:52:49 +03:00
parent 6e804953c0
commit 57188186c0
4 changed files with 82 additions and 5 deletions

View File

@ -165,6 +165,7 @@ def fill_db():
ref=ref.id, ref=ref.id,
sale_id=str(uuid4()), sale_id=str(uuid4()),
company_id=company.id, company_id=company.id,
sale_date=dt,
create_dttm=dt, create_dttm=dt,
update_dttm=dt update_dttm=dt
) )

75
integration_api.py Normal file
View File

@ -0,0 +1,75 @@
from fastapi import FastAPI, HTTPException, status, Depends, Request
from sqlmodel import Session, select
from typing import Optional
from datetime import datetime, timedelta
import jwt
from jwt.exceptions import InvalidTokenError
from pydantic import BaseModel
from sql_models import Sale
from helpers_bff import get_db, AUTH_DB_ENGINE # Assuming these are the correct imports
app = FastAPI()
# Конфигурация для интеграционного API токена
INTEGRATION_SECRET_KEY = "your-integration-super-secret-key" # Смените это на безопасный ключ!
INTEGRATION_ALGORITHM = "HS256"
INTEGRATION_TOKEN_EXPIRE_MINUTES = 60 * 24 # 24 часа
class IntegrationTokenData(BaseModel):
client_id: str
class SaleCreate(BaseModel):
cost: float
crediting: float
ref_id: int
sale_id: str
company_id: int
sale_date: datetime = datetime.utcnow()
def create_integration_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=INTEGRATION_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, INTEGRATION_SECRET_KEY, algorithm=INTEGRATION_ALGORITHM)
return encoded_jwt
async def verify_integration_token(request: Request):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate integration credentials",
headers={"WWW-Authenticate": "Bearer"},
)
auth_header = request.headers.get("Authorization")
if not auth_header or not auth_header.startswith("Bearer "):
raise credentials_exception
token = auth_header.replace("Bearer ", "").strip()
try:
payload = jwt.decode(token, INTEGRATION_SECRET_KEY, algorithms=[INTEGRATION_ALGORITHM])
client_id: str = payload.get("client_id")
if client_id is None:
raise credentials_exception
# Здесь вы можете добавить логику для проверки client_id, например, из базы данных
except InvalidTokenError:
raise credentials_exception
return True # Токен действителен
@app.post("/sale", status_code=status.HTTP_201_CREATED)
async def upload_sale(sale_data: SaleCreate, db: Session = Depends(get_db), verified: bool = Depends(verify_integration_token)):
if not verified:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Not authorized")
db_sale = Sale(cost=sale_data.cost, crediting=sale_data.crediting, ref=sale_data.ref_id, sale_id=sale_data.sale_id, company_id=sale_data.company_id, sale_date=sale_data.sale_date)
db.add(db_sale)
db.commit()
db.refresh(db_sale)
return {"message": "Sale uploaded successfully", "sale_id": db_sale.id}
@app.get("/generate-integration-token")
async def generate_token_endpoint(client_id: str):
token_data = {"client_id": client_id}
token = create_integration_access_token(token_data)
return {"access_token": token, "token_type": "bearer"}

10
main.py
View File

@ -236,11 +236,11 @@ def get_dashboard_chart_total(current_account: Account = Depends(get_current_acc
# Группируем продажи по дате (день) # Группируем продажи по дате (день)
result = db.exec( result = db.exec(
select( select(
func.strftime('%Y-%m-%d', Sale.create_dttm).label('date'), func.strftime('%Y-%m-%d', Sale.sale_date).label('date'),
func.sum(Sale.cost).label('revenue'), func.sum(Sale.cost).label('revenue'),
func.count(Sale.id).label('sales') func.count(Sale.id).label('sales')
).where(Sale.company_id == current_account.company_id).group_by(func.strftime('%Y-%m-%d', Sale.create_dttm)) ).where(Sale.company_id == current_account.company_id).group_by(func.strftime('%Y-%m-%d', Sale.sale_date))
.order_by(func.strftime('%Y-%m-%d', Sale.create_dttm)) .order_by(func.strftime('%Y-%m-%d', Sale.sale_date))
).all() ).all()
# Преобразуем результат в нужный формат # Преобразуем результат в нужный формат
data = [ data = [
@ -368,9 +368,9 @@ def get_sales_stat(
""" """
sales_query = select(Sale).where(Sale.company_id == current_account.company_id) sales_query = select(Sale).where(Sale.company_id == current_account.company_id)
if date_start: if date_start:
sales_query = sales_query.where(Sale.create_dttm >= date_start) sales_query = sales_query.where(Sale.sale_date >= date_start)
if date_end: if date_end:
sales_query = sales_query.where(Sale.create_dttm <= date_end) sales_query = sales_query.where(Sale.sale_date <= date_end)
sales = db.exec(sales_query).all() sales = db.exec(sales_query).all()
ref_ids = list(set(sale.ref for sale in sales)) ref_ids = list(set(sale.ref for sale in sales))
refs = db.exec(select(Ref).where(Ref.id.in_(ref_ids))).all() if ref_ids else [] refs = db.exec(select(Ref).where(Ref.id.in_(ref_ids))).all() if ref_ids else []

View File

@ -39,6 +39,7 @@ class Sale(SQLModel, table=True):
ref: int = Field(foreign_key="ref.id") ref: int = Field(foreign_key="ref.id")
sale_id: str sale_id: str
company_id: int = Field(foreign_key="company.id") company_id: int = Field(foreign_key="company.id")
sale_dttm: datetime = Field(default_factory=datetime.utcnow)
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)