fix: removed crap, category on service and deal

This commit is contained in:
2024-09-27 04:50:01 +03:00
parent 5df64d4916
commit 91cf44f3ae
10 changed files with 258 additions and 64 deletions

View File

View File

@@ -1,33 +0,0 @@
from typing import Annotated
from fastapi import HTTPException, Depends
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy import select
from starlette import status
from backend import config
from database import User
from jose import jwt
from database.base import DatabaseDependency
oauth2_scheme = OAuth2PasswordBearer("")
ALGORITHM = "HS256"
def generate_jwt_token(user: User):
return jwt.encode({'sub': user.id}, settings.SECRET_KEY, algorithm=ALGORITHM)
def require_jwt_sub(token: Annotated[str, Depends(oauth2_scheme)]):
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[ALGORITHM])
user_id = payload.get("sub")
if not user_id:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid authorization credentials')
return payload
async def get_current_user(db_session: DatabaseDependency, user_id: Annotated[int, Depends(require_jwt_sub)]) -> User:
user = await db_session.scalar(select(User).where(User.id == user_id))
if user:
return user

View File

@@ -1,27 +0,0 @@
import hmac
import hashlib
from backend import config
def _generate_hash(telegram_data: dict):
data = telegram_data.copy()
del data['hash']
keys = sorted(data.keys())
string_arr = []
for key in keys:
if data[key] is not None:
string_arr.append(key + '=' + str(data[key]))
string_cat = '\n'.join(string_arr)
secret_key = hashlib.sha256(settings.TELEGRAM_BOT_TOKEN.encode('utf-8')).digest()
hash_bytes = bytes(string_cat, 'utf-8')
hmac_hash = hmac.new(secret_key, hash_bytes, hashlib.sha256).hexdigest()
return hmac_hash
def telegram_authorize(telegram_data: dict):
generated_hash = _generate_hash(telegram_data)
user_hash = telegram_data['hash']
return generated_hash == user_hash

View File

@@ -9,7 +9,7 @@ from .marketplace import BaseMarketplace
from .shipping_warehouse import ShippingWarehouse
if TYPE_CHECKING:
from . import DealBillRequest
from . import DealBillRequest, ServicePriceCategory
@unique
@@ -23,6 +23,12 @@ class DealStatus(IntEnum):
CANCELLED = 6
class DealPriceCategory(BaseModel):
__tablename__ = 'deal_price_category'
deal_id: Mapped[int] = mapped_column(ForeignKey('deals.id'), primary_key=True, unique=True)
category_id: Mapped[int] = mapped_column(ForeignKey('service_price_category.id'), primary_key=True)
class Deal(BaseModel):
__tablename__ = 'deals'
id = Column(Integer, autoincrement=True, primary_key=True, index=True)
@@ -64,6 +70,9 @@ class Deal(BaseModel):
comment = Column(String, nullable=False, server_default='', comment='Коментарий к заданию')
bill_request: Mapped[Optional['DealBillRequest']] = relationship(back_populates='deal', lazy='joined')
category: Mapped[Optional["ServicePriceCategory"]] = relationship('ServicePriceCategory',
secondary=DealPriceCategory.__table__,
lazy='joined')
class DealStatusHistory(BaseModel):

View File

@@ -42,6 +42,10 @@ class Service(BaseModel):
lazy='selectin',
order_by="asc(ServicePriceRange.from_quantity)",
cascade="all, delete-orphan")
category_prices = relationship('ServiceCategoryPrice',
back_populates='service',
lazy='selectin',
cascade="all, delete-orphan")
class ServicePriceRange(BaseModel):
@@ -54,6 +58,23 @@ class ServicePriceRange(BaseModel):
price = Column(Double, nullable=False, comment='Цена')
class ServiceCategoryPrice(BaseModel):
__tablename__ = 'service_category_prices'
service_id: Mapped[int] = mapped_column(ForeignKey('services.id'), primary_key=True)
category_id: Mapped[int] = mapped_column(ForeignKey('service_price_category.id'), primary_key=True)
price: Mapped[float] = mapped_column(Double, nullable=False, comment='Цена')
service: Mapped["Service"] = relationship('Service', lazy='joined', back_populates='category_prices')
category: Mapped["ServicePriceCategory"] = relationship('ServicePriceCategory', lazy='joined')
class ServicePriceCategory(BaseModel):
__tablename__ = 'service_price_category'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(nullable=False)
class ServiceCategory(BaseModel):
__tablename__ = 'service_categories'
id = Column(Integer, autoincrement=True, primary_key=True, index=True)

View File

@@ -17,6 +17,7 @@ service_router = APIRouter(
)
# region Services
@service_router.get(
'/get-all',
response_model=ServiceGetAllResponse,
@@ -69,6 +70,10 @@ async def delete(
return await ServiceService(session).delete(request)
# endregion
# region Categories
@service_router.get(
'/categories/get-all',
response_model=ServiceGetAllCategoriesResponse,
@@ -94,6 +99,9 @@ async def create_category(
return await ServiceService(session).create_category(request)
# endregion
# region Types
@service_router.get(
'/types/get-all',
response_model=BaseEnumListSchema,
@@ -108,6 +116,10 @@ async def get_all_service_types(
return BaseEnumListSchema(items=result)
# endregion
# region Kits
@service_router.get(
'/kits/get-all',
response_model=GetAllServicesKitsResponse,
@@ -144,3 +156,60 @@ async def update_services_kit(
request: UpdateServicesKitRequest
):
return await ServiceService(session).update_kit(request)
# endregion
# region Price Categories
# crud price categories
@service_router.get(
'/price-categories/get-all',
response_model=GetAllPriceCategoriesResponse,
operation_id='get_all_price_categories',
dependencies=[Depends(guest_user)]
)
async def get_all_price_categories(
session: SessionDependency
):
return await ServiceService(session).get_all_price_categories()
@service_router.post(
'/price-categories/create',
response_model=CreatePriceCategoryResponse,
operation_id='create_price_category',
dependencies=[Depends(authorized_user)]
)
async def create_price_category(
session: SessionDependency,
request: CreatePriceCategoryRequest
):
return await ServiceService(session).create_price_category(request)
@service_router.post(
'/price-categories/update',
response_model=UpdatePriceCategoryResponse,
operation_id='update_price_category',
dependencies=[Depends(authorized_user)]
)
async def update_price_category(
session: SessionDependency,
request: UpdatePriceCategoryRequest
):
return await ServiceService(session).update_price_category(request)
@service_router.post(
'/price-categories/delete',
response_model=DeletePriceCategoryResponse,
operation_id='delete_price_category',
dependencies=[Depends(authorized_user)]
)
async def delete_price_category(
session: SessionDependency,
request: DeletePriceCategoryRequest
):
return await ServiceService(session).delete_price_category(request)
# endregion

View File

@@ -3,12 +3,13 @@ from typing import List, Optional, Union
from pydantic import constr, field_validator
from models import ServiceCategoryPrice, ServicePriceCategory
from schemas.base import BaseSchema, OkMessageSchema
from schemas.billing import DealBillRequestSchema
from schemas.client import ClientSchema
from schemas.marketplace import BaseMarketplaceSchema
from schemas.product import ProductSchema
from schemas.service import ServiceSchema
from schemas.service import ServiceSchema, ServicePriceCategorySchema
from schemas.shipping_warehouse import ShippingWarehouseSchema
from schemas.user import UserSchema
@@ -37,6 +38,7 @@ class DealSummary(BaseSchema):
shipment_warehouse_id: Optional[int]
shipment_warehouse_name: Optional[str]
class DealServiceSchema(BaseSchema):
service: ServiceSchema
quantity: int
@@ -81,6 +83,7 @@ class DealSchema(BaseSchema):
comment: str
shipping_warehouse: Optional[Union[ShippingWarehouseSchema, str]] = None
bill_request: Optional[DealBillRequestSchema] = None
category: Optional[ServicePriceCategorySchema] = None
class DealGeneralInfoSchema(BaseSchema):
@@ -110,6 +113,7 @@ class DealQuickCreateRequest(BaseSchema):
acceptance_date: datetime.datetime
shipping_warehouse: constr(strip_whitespace=True)
base_marketplace: BaseMarketplaceSchema
category: Optional[ServicePriceCategorySchema] = None
class DealSummaryRequest(BaseSchema):
@@ -212,9 +216,11 @@ class DealAddKitRequest(BaseSchema):
class DealCreateGuestUrlRequest(BaseSchema):
deal_id: int
class DealCompleteRequest(BaseSchema):
deal_id: int
# endregion Requests
# region Responses
@@ -311,6 +317,7 @@ class DealAddKitResponse(OkMessageSchema):
class DealCreateGuestUrlResponse(OkMessageSchema):
url: str
class DealCompleteResponse(OkMessageSchema):
pass

View File

@@ -4,6 +4,8 @@ from schemas.base import BaseSchema, OkMessageSchema, BaseEnumSchema
# region Entities
# region Services
class ServicePriceRangeSchema(BaseSchema):
id: int | None
from_quantity: int
@@ -16,6 +18,16 @@ class ServiceCategorySchema(BaseSchema):
name: str
class ServicePriceCategorySchema(BaseSchema):
id: int
name: str
class ServiceCategoryPriceSchema(BaseSchema):
category: ServicePriceCategorySchema
price: float
class ServiceSchema(BaseSchema):
id: int
name: str
@@ -23,9 +35,13 @@ class ServiceSchema(BaseSchema):
price: float
service_type: int
price_ranges: List[ServicePriceRangeSchema]
category_prices: List[ServiceCategoryPriceSchema]
cost: Optional[int]
# endregion
# region Kits
class BaseServiceKitSchema(BaseSchema):
name: str
service_type: int
@@ -47,6 +63,12 @@ class UpdateServiceKitSchema(BaseServiceKitSchema):
# endregion
# region Category prices
# endregion
# endregion
# region Requests
class ServiceCreateRequest(BaseSchema):
@@ -73,6 +95,19 @@ class UpdateServicesKitRequest(BaseSchema):
data: UpdateServiceKitSchema
class CreatePriceCategoryRequest(BaseSchema):
name: str
class UpdatePriceCategoryRequest(BaseSchema):
id: int
name: str
class DeletePriceCategoryRequest(BaseSchema):
id: int
# endregion
@@ -111,4 +146,21 @@ class UpdateServicesKitResponse(OkMessageSchema):
class GetAllServicesKitsResponse(BaseSchema):
services_kits: List[GetServiceKitSchema]
class GetAllPriceCategoriesResponse(BaseSchema):
price_categories: List[ServicePriceCategorySchema]
class CreatePriceCategoryResponse(OkMessageSchema):
pass
class UpdatePriceCategoryResponse(OkMessageSchema):
pass
class DeletePriceCategoryResponse(OkMessageSchema):
pass
# endregion

View File

@@ -130,6 +130,14 @@ class DealService(BaseService):
user,
deadline=request.acceptance_date,
comment=request.comment)
# add category if specified
if request.category:
deal_category = DealPriceCategory(
deal_id=deal.id,
category_id=request.category.id
)
self.session.add(deal_category)
await self.session.commit()
return DealQuickCreateResponse(deal_id=deal.id)

View File

@@ -3,7 +3,8 @@ from typing import Union
from sqlalchemy import select, update, insert, delete
from sqlalchemy.orm import joinedload
from models import Service, ServiceCategory, ServicePriceRange, ServicesKit, services_kit_services
from models import Service, ServiceCategory, ServicePriceRange, ServicesKit, services_kit_services, \
ServiceCategoryPrice, ServicePriceCategory
from services.base import BaseService
from schemas.service import *
@@ -27,6 +28,7 @@ class ServiceService(BaseService):
del service_dict['id']
del service_dict['category']
del service_dict['price_ranges']
del service_dict['category_prices']
service = Service(**service_dict)
self.session.add(service)
await self.session.flush()
@@ -37,7 +39,15 @@ class ServiceService(BaseService):
del price_range_dict['id']
price_range_obj = ServicePriceRange(**price_range_dict)
self.session.add(price_range_obj)
category_prices = request.service.category_prices
for category_price in category_prices:
category_price_dict = category_price.model_dump()
category_price_dict['service_id'] = service.id
category_price_dict['category_id'] = category_price.category.id
del category_price_dict['category']
category_price_obj = ServiceCategoryPrice(**category_price_dict)
self.session.add(category_price_obj)
await self.session.commit()
return ServiceCreateResponse(ok=True, message="Услуга успешно создана")
except Exception as e:
@@ -54,6 +64,7 @@ class ServiceService(BaseService):
service_dict['category_id'] = raw_service.category.id
del service_dict['category']
del service_dict['price_ranges']
del service_dict['category_prices']
await self.session.execute(
update(Service)
.where(Service.id == raw_service.id)
@@ -81,6 +92,26 @@ class ServiceService(BaseService):
del price_range_dict['id']
price_range_obj = ServicePriceRange(**price_range_dict)
self.session.add(price_range_obj)
# deleting previouse category prices
stmt = (
delete(
ServiceCategoryPrice
).where(
ServiceCategoryPrice.service_id == service.id
)
)
await self.session.execute(stmt)
await self.session.flush()
# inserting new category prices
for category_price in raw_service.category_prices:
category_price_dict = category_price.dict()
category_price_dict['service_id'] = raw_service.id
category_price_dict['category_id'] = category_price.category.id
del category_price_dict['category']
category_price_obj = ServiceCategoryPrice(**category_price_dict)
self.session.add(category_price_obj)
await self.session.commit()
return ServiceUpdateResponse(ok=True, message="Услуга успешно обновлена")
except Exception as e:
@@ -205,3 +236,60 @@ class ServiceService(BaseService):
except Exception as e:
return UpdateServicesKitResponse(ok=False, message=str(e))
async def get_all_price_categories(self) -> GetAllPriceCategoriesResponse:
query = await (self.session
.scalars(select(ServicePriceCategory)
.order_by(ServicePriceCategory.id)))
price_categories = []
for category in query.all():
price_categories.append(ServicePriceCategorySchema.model_validate(category))
return GetAllPriceCategoriesResponse(price_categories=price_categories)
async def create_price_category(self, request: CreatePriceCategoryRequest) -> ServiceCreateCategoryResponse:
try:
raw_category = request.name
category = ServicePriceCategory(name=raw_category)
self.session.add(category)
await self.session.commit()
return ServiceCreateCategoryResponse(ok=True, message="Категория цен успешно создана")
except Exception as e:
return ServiceCreateCategoryResponse(ok=False, message=f"Неудалось создать категорию цен, ошибка: {e}")
async def update_price_category(self, request: UpdatePriceCategoryRequest) -> ServiceUpdateResponse:
try:
raw_category = request.name
category = await (self.session.get(ServicePriceCategory, request.id))
if not category:
return ServiceUpdateResponse(ok=False, message="Категория цен не найдена")
await self.session.execute(
update(ServicePriceCategory)
.where(ServicePriceCategory.id == request.id)
.values(name=raw_category)
)
await self.session.commit()
return ServiceUpdateResponse(ok=True, message="Категория цен успешно обновлена")
except Exception as e:
return ServiceUpdateResponse(ok=False, message=f"Неудалось обновить категорию цен, ошибка: {e}")
async def delete_price_category(self, request: DeletePriceCategoryRequest) -> ServiceDeleteResponse:
try:
category = await (
self.session
.scalar(
select(
ServicePriceCategory
)
.filter(
ServicePriceCategory.id == request.id
)
)
)
if not category:
return ServiceDeleteResponse(ok=False, message="Категория цен не найдена")
await self.session.delete(category)
await self.session.commit()
return ServiceDeleteResponse(ok=True, message="Категория цен успешно удалена")
except Exception as e:
return ServiceDeleteResponse(ok=False, message=f"Неудалось удалить категорию цен, ошибка: {e}")