feat: billing guest access
This commit is contained in:
		@@ -16,3 +16,5 @@ TELEGRAM_BOT_TOKEN = os.environ.get('TELEGRAM_BOT_TOKEN')
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
SECRET_KEY = os.environ.get('SECRET_KEY')
 | 
					SECRET_KEY = os.environ.get('SECRET_KEY')
 | 
				
			||||||
S3_API_KEY = os.environ.get('S3_API_KEY')
 | 
					S3_API_KEY = os.environ.get('S3_API_KEY')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BILLING_API_KEY = os.environ.get('BILLING_API_KEY')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,9 +6,11 @@ from sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			|||||||
from backend.session import get_session
 | 
					from backend.session import get_session
 | 
				
			||||||
from models import User
 | 
					from models import User
 | 
				
			||||||
from schemas.base import PaginationSchema
 | 
					from schemas.base import PaginationSchema
 | 
				
			||||||
from services.auth import get_current_user
 | 
					from services.auth import get_current_user, authorized_user, guest_user
 | 
				
			||||||
from utils.dependecies import pagination_parameters
 | 
					from utils.dependecies import pagination_parameters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SessionDependency = Annotated[AsyncSession, Depends(get_session)]
 | 
					SessionDependency = Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
PaginationDependency = Annotated[PaginationSchema, Depends(pagination_parameters)]
 | 
					PaginationDependency = Annotated[PaginationSchema, Depends(pagination_parameters)]
 | 
				
			||||||
CurrentUserDependency = Annotated[User, Depends(get_current_user)]
 | 
					CurrentUserDependency = Annotated[User, Depends(get_current_user)]
 | 
				
			||||||
 | 
					AuthorizedUserDependency = Annotated[User, Depends(authorized_user)]
 | 
				
			||||||
 | 
					GuestUserDependency = Annotated[User, Depends(guest_user)]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								external/billing/__init__.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								external/billing/__init__.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					from .schemas import *
 | 
				
			||||||
 | 
					from .enums import *
 | 
				
			||||||
 | 
					from .billing_client import BillingClient
 | 
				
			||||||
							
								
								
									
										27
									
								
								external/billing/billing_client.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								external/billing/billing_client.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					import aiohttp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .schemas import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BillingClient:
 | 
				
			||||||
 | 
					    def __init__(self, api_key: str):
 | 
				
			||||||
 | 
					        self.api_key = api_key
 | 
				
			||||||
 | 
					        self.headers = {
 | 
				
			||||||
 | 
					            'Authorization': f'Bearer {self.api_key}'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self.base_url = 'https://billing.denco.store'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def _method(self, http_method, method, **kwargs):
 | 
				
			||||||
 | 
					        async with aiohttp.ClientSession(headers=self.headers) as session:
 | 
				
			||||||
 | 
					            async with session.request(http_method, self.base_url + method, **kwargs) as response:
 | 
				
			||||||
 | 
					                return await response.json()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def create(self, request: CreateBillRequestSchema) -> CreateBillingResponseSchema:
 | 
				
			||||||
 | 
					        json_data = request.model_dump()
 | 
				
			||||||
 | 
					        response = await self._method('POST', '/create', json=json_data)
 | 
				
			||||||
 | 
					        return CreateBillingResponseSchema.model_validate(response)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def notify_received(self, request: NotifyReceivedBillRequestSchema) -> NotifyReceivedBillResponseSchema:
 | 
				
			||||||
 | 
					        json_data = request.model_dump()
 | 
				
			||||||
 | 
					        response = await self._method('POST', '/notify-received', json=json_data)
 | 
				
			||||||
 | 
					        return NotifyReceivedBillResponseSchema.model_validate(response)
 | 
				
			||||||
							
								
								
									
										6
									
								
								external/billing/enums.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								external/billing/enums.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					from enum import StrEnum
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NotificationChannel(StrEnum):
 | 
				
			||||||
 | 
					    PAYMENT_DETAILS = 'PAYMENT_DETAILS'
 | 
				
			||||||
 | 
					    PAYMENT_VERIFICATION = 'PAYMENT_VERIFICATION'
 | 
				
			||||||
							
								
								
									
										81
									
								
								external/billing/schemas.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								external/billing/schemas.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					import re
 | 
				
			||||||
 | 
					from typing import List
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pydantic import field_validator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from schemas.base import BaseSchema
 | 
				
			||||||
 | 
					from .enums import NotificationChannel
 | 
				
			||||||
 | 
					from datetime import datetime as dt
 | 
				
			||||||
 | 
					from datetime import date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					phone_regexp = re.compile(r'^((\+7)([0-9]){10})$')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateBillingRequestValue(BaseSchema):
 | 
				
			||||||
 | 
					    name: str = ""
 | 
				
			||||||
 | 
					    unit: str = "Руб"
 | 
				
			||||||
 | 
					    vat: str = "None"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    price: int
 | 
				
			||||||
 | 
					    amount: int = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateBillRequestItems(BaseSchema):
 | 
				
			||||||
 | 
					    values: List[CreateBillingRequestValue]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateBillRequestSchema(BaseSchema):
 | 
				
			||||||
 | 
					    listener_transaction_id: int
 | 
				
			||||||
 | 
					    payer_name: str
 | 
				
			||||||
 | 
					    payer_inn: int
 | 
				
			||||||
 | 
					    payer_phone: str | None
 | 
				
			||||||
 | 
					    items: CreateBillRequestItems
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @field_validator("payer_phone", mode="before")
 | 
				
			||||||
 | 
					    def payer_phone_validator(cls, phone: str) -> str:
 | 
				
			||||||
 | 
					        if phone is None:
 | 
				
			||||||
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not phone.startswith("+"):
 | 
				
			||||||
 | 
					            phone = f"+{phone}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if phone_regexp.match(phone):
 | 
				
			||||||
 | 
					            return phone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NotifyReceivedBillRequestSchema(BaseSchema):
 | 
				
			||||||
 | 
					    listener_transaction_id: int
 | 
				
			||||||
 | 
					    channel: NotificationChannel
 | 
				
			||||||
 | 
					    received: bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateBillingResponseSchema(BaseSchema):
 | 
				
			||||||
 | 
					    ok: bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NotifyReceivedBillResponseSchema(BaseSchema):
 | 
				
			||||||
 | 
					    ok: bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BillPaymentInfo(BaseSchema):
 | 
				
			||||||
 | 
					    pdf_url: str
 | 
				
			||||||
 | 
					    due_date: date
 | 
				
			||||||
 | 
					    payment_amount: int
 | 
				
			||||||
 | 
					    invoice_number: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @field_validator('due_date', mode='plain')
 | 
				
			||||||
 | 
					    def serialize_due_date(value: str) -> date:
 | 
				
			||||||
 | 
					        date = dt.strptime(value, '%Y-%m-%d').date()
 | 
				
			||||||
 | 
					        return date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BillPaymentStatus(BaseSchema):
 | 
				
			||||||
 | 
					    payed: bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BillStatusUpdateRequest(BaseSchema):
 | 
				
			||||||
 | 
					    listener_transaction_id: int
 | 
				
			||||||
 | 
					    channel: NotificationChannel
 | 
				
			||||||
 | 
					    info: BillPaymentInfo | BillPaymentStatus
 | 
				
			||||||
							
								
								
									
										1
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								main.py
									
									
									
									
									
								
							@@ -42,6 +42,7 @@ routers_list = [
 | 
				
			|||||||
    routers.marketplace_router,
 | 
					    routers.marketplace_router,
 | 
				
			||||||
    routers.payroll_router,
 | 
					    routers.payroll_router,
 | 
				
			||||||
    routers.time_tracking_router,
 | 
					    routers.time_tracking_router,
 | 
				
			||||||
 | 
					    routers.billing_router
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
for router in routers_list:
 | 
					for router in routers_list:
 | 
				
			||||||
    app.include_router(router)
 | 
					    app.include_router(router)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,5 +10,6 @@ from .barcode import *
 | 
				
			|||||||
from .shipping_warehouse import *
 | 
					from .shipping_warehouse import *
 | 
				
			||||||
from .marketplace import *
 | 
					from .marketplace import *
 | 
				
			||||||
from .payroll import *
 | 
					from .payroll import *
 | 
				
			||||||
 | 
					from .billing import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
configure_mappers()
 | 
					configure_mappers()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								models/billing.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								models/billing.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					import datetime
 | 
				
			||||||
 | 
					from typing import TYPE_CHECKING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sqlalchemy import ForeignKey
 | 
				
			||||||
 | 
					from sqlalchemy.orm import Mapped, mapped_column, relationship
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from models import BaseModel
 | 
				
			||||||
 | 
					if TYPE_CHECKING:
 | 
				
			||||||
 | 
					    from models import Deal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DealBillRequest(BaseModel):
 | 
				
			||||||
 | 
					    __tablename__ = 'deal_bill_requests'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    deal_id: Mapped[int] = mapped_column(ForeignKey('deals.id'),
 | 
				
			||||||
 | 
					                                         nullable=False,
 | 
				
			||||||
 | 
					                                         primary_key=True,
 | 
				
			||||||
 | 
					                                         unique=True)
 | 
				
			||||||
 | 
					    deal: Mapped['Deal'] = relationship(back_populates='bill_request')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    created_at: Mapped[datetime.datetime] = mapped_column(nullable=False)
 | 
				
			||||||
 | 
					    paid: Mapped[bool] = mapped_column(nullable=False, default=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pdf_url: Mapped[str] = mapped_column(nullable=True)
 | 
				
			||||||
 | 
					    invoice_number: Mapped[str] = mapped_column(nullable=True)
 | 
				
			||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
from enum import IntEnum, unique
 | 
					from enum import IntEnum, unique
 | 
				
			||||||
 | 
					from typing import Optional, TYPE_CHECKING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean
 | 
					from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean
 | 
				
			||||||
from sqlalchemy.orm import relationship, backref, Mapped, mapped_column
 | 
					from sqlalchemy.orm import relationship, backref, Mapped, mapped_column
 | 
				
			||||||
@@ -7,6 +8,9 @@ from models.base import BaseModel
 | 
				
			|||||||
from .marketplace import BaseMarketplace
 | 
					from .marketplace import BaseMarketplace
 | 
				
			||||||
from .shipping_warehouse import ShippingWarehouse
 | 
					from .shipping_warehouse import ShippingWarehouse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if TYPE_CHECKING:
 | 
				
			||||||
 | 
					    from . import DealBillRequest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@unique
 | 
					@unique
 | 
				
			||||||
class DealStatus(IntEnum):
 | 
					class DealStatus(IntEnum):
 | 
				
			||||||
@@ -33,6 +37,7 @@ class Deal(BaseModel):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    is_deleted = Column(Boolean, nullable=False, server_default='0', default=False, comment='Удалена')
 | 
					    is_deleted = Column(Boolean, nullable=False, server_default='0', default=False, comment='Удалена')
 | 
				
			||||||
    is_completed = Column(Boolean, nullable=False, server_default='0', default=False, comment='Завершена')
 | 
					    is_completed = Column(Boolean, nullable=False, server_default='0', default=False, comment='Завершена')
 | 
				
			||||||
 | 
					    is_locked: Mapped[bool] = mapped_column(default=False, server_default='0')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shipping_warehouse_id: Mapped[int] = mapped_column(ForeignKey('shipping_warehouses.id'), nullable=True)
 | 
					    shipping_warehouse_id: Mapped[int] = mapped_column(ForeignKey('shipping_warehouses.id'), nullable=True)
 | 
				
			||||||
    shipping_warehouse: Mapped["ShippingWarehouse"] = relationship()
 | 
					    shipping_warehouse: Mapped["ShippingWarehouse"] = relationship()
 | 
				
			||||||
@@ -58,6 +63,7 @@ class Deal(BaseModel):
 | 
				
			|||||||
    lexorank = Column(String, nullable=False, comment='Lexorank', index=True)
 | 
					    lexorank = Column(String, nullable=False, comment='Lexorank', index=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    comment = Column(String, nullable=False, server_default='', comment='Коментарий к заданию')
 | 
					    comment = Column(String, nullable=False, server_default='', comment='Коментарий к заданию')
 | 
				
			||||||
 | 
					    bill_request: Mapped[Optional['DealBillRequest']] = relationship(back_populates='deal', lazy='joined')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealStatusHistory(BaseModel):
 | 
					class DealStatusHistory(BaseModel):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,3 +11,4 @@ from .role import role_router
 | 
				
			|||||||
from .marketplace import marketplace_router
 | 
					from .marketplace import marketplace_router
 | 
				
			||||||
from .payroll import payroll_router
 | 
					from .payroll import payroll_router
 | 
				
			||||||
from .time_tracking import time_tracking_router
 | 
					from .time_tracking import time_tracking_router
 | 
				
			||||||
 | 
					from .billing import billing_router
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,19 +4,14 @@ from fastapi import APIRouter, Depends
 | 
				
			|||||||
from sqlalchemy.ext.asyncio import AsyncSession
 | 
					from sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backend.session import get_session
 | 
					from backend.session import get_session
 | 
				
			||||||
from schemas.barcode import (GetBarcodeTemplateByIdResponse,
 | 
					from schemas.barcode import *
 | 
				
			||||||
                             GetBarcodeTemplateByIdRequest,
 | 
					from services.auth import authorized_user, guest_user
 | 
				
			||||||
                             BarcodeTemplateCreateResponse,
 | 
					 | 
				
			||||||
                             BarcodeTemplateCreateRequest, GetAllBarcodeTemplateAttributesResponse,
 | 
					 | 
				
			||||||
                             CreateBarcodeTemplateAttributeResponse, CreateBarcodeTemplateAttributeRequest,
 | 
					 | 
				
			||||||
                             BarcodeTemplateUpdateResponse, BarcodeTemplateUpdateRequest,
 | 
					 | 
				
			||||||
                             GetAllBarcodeTemplatesResponse, BarcodeTemplateDeleteRequest,
 | 
					 | 
				
			||||||
                             BarcodeTemplateDeleteResponse, GetAllBarcodeTemplateSizesResponse)
 | 
					 | 
				
			||||||
from services.barcode import BarcodeService
 | 
					from services.barcode import BarcodeService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
barcode_router = APIRouter(
 | 
					barcode_router = APIRouter(
 | 
				
			||||||
    prefix='/barcode',
 | 
					    prefix='/barcode',
 | 
				
			||||||
    tags=['barcode'],
 | 
					    tags=['barcode'],
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										51
									
								
								routers/billing.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								routers/billing.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					from fastapi import APIRouter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from backend.dependecies import SessionDependency, CurrentUserDependency
 | 
				
			||||||
 | 
					from external.billing import BillStatusUpdateRequest
 | 
				
			||||||
 | 
					from schemas.billing import *
 | 
				
			||||||
 | 
					from services.billing import BillingService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					billing_router = APIRouter(
 | 
				
			||||||
 | 
					    prefix='/billing',
 | 
				
			||||||
 | 
					    tags=['billing']
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@billing_router.post(
 | 
				
			||||||
 | 
					    '/webhook'
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def webhook(
 | 
				
			||||||
 | 
					        request: BillStatusUpdateRequest,
 | 
				
			||||||
 | 
					        session: SessionDependency
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        await BillingService(session).process_update(request)
 | 
				
			||||||
 | 
					        return {'ok': True}
 | 
				
			||||||
 | 
					    except Exception as e:
 | 
				
			||||||
 | 
					        print(e)
 | 
				
			||||||
 | 
					        return {'ok': False}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@billing_router.post(
 | 
				
			||||||
 | 
					    '/create-deal-bill',
 | 
				
			||||||
 | 
					    operation_id='create_deal_bill',
 | 
				
			||||||
 | 
					    response_model=CreateDealBillResponse
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def create_deal_bill(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: CreateDealBillRequest,
 | 
				
			||||||
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await BillingService(session).create_deal_billing(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@billing_router.get(
 | 
				
			||||||
 | 
					    '/deal-bill-request/{deal_id}',
 | 
				
			||||||
 | 
					    response_model=GetDealBillById,
 | 
				
			||||||
 | 
					    operation_id='get_deal_bill_by_id'
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def get_deal_bill_by_id(
 | 
				
			||||||
 | 
					        deal_id: int,
 | 
				
			||||||
 | 
					        session: SessionDependency
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await BillingService(session).get_deal_bill_by_id(deal_id)
 | 
				
			||||||
@@ -6,13 +6,13 @@ from sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			|||||||
from backend.session import get_session
 | 
					from backend.session import get_session
 | 
				
			||||||
from models import User
 | 
					from models import User
 | 
				
			||||||
from schemas.client import *
 | 
					from schemas.client import *
 | 
				
			||||||
from services.auth import get_current_user
 | 
					from services.auth import get_current_user, authorized_user
 | 
				
			||||||
from services.client import ClientService
 | 
					from services.client import ClientService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
client_router = APIRouter(
 | 
					client_router = APIRouter(
 | 
				
			||||||
    prefix="/client",
 | 
					    prefix="/client",
 | 
				
			||||||
    tags=['client'],
 | 
					    tags=['client'],
 | 
				
			||||||
    dependencies=[Depends(get_current_user)]
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										181
									
								
								routers/deal.py
									
									
									
									
									
								
							
							
						
						
									
										181
									
								
								routers/deal.py
									
									
									
									
									
								
							@@ -3,22 +3,24 @@ from typing import Annotated
 | 
				
			|||||||
from fastapi import APIRouter, Depends
 | 
					from fastapi import APIRouter, Depends
 | 
				
			||||||
from sqlalchemy.ext.asyncio import AsyncSession
 | 
					from sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backend.dependecies import SessionDependency
 | 
					from backend.dependecies import SessionDependency, CurrentUserDependency
 | 
				
			||||||
from backend.session import get_session
 | 
					from backend.session import get_session
 | 
				
			||||||
from models import User
 | 
					from models import User
 | 
				
			||||||
from schemas.deal import *
 | 
					from schemas.deal import *
 | 
				
			||||||
from services.auth import get_current_user
 | 
					from services.auth import get_current_user, authorized_user, guest_user
 | 
				
			||||||
from services.deal import DealService
 | 
					from services.deal import DealService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
deal_router = APIRouter(
 | 
					deal_router = APIRouter(
 | 
				
			||||||
    prefix='/deal',
 | 
					    prefix='/deal',
 | 
				
			||||||
    tags=['deal'],
 | 
					    tags=['deal'],
 | 
				
			||||||
    dependencies=[Depends(get_current_user)]
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Deal
 | 
					# region Deal
 | 
				
			||||||
@deal_router.post('/create')
 | 
					@deal_router.post(
 | 
				
			||||||
 | 
					    '/create',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
async def create(
 | 
					async def create(
 | 
				
			||||||
        request: DealCreateRequest,
 | 
					        request: DealCreateRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
@@ -30,7 +32,8 @@ async def create(
 | 
				
			|||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/delete',
 | 
					    '/delete',
 | 
				
			||||||
    response_model=DealDeleteResponse,
 | 
					    response_model=DealDeleteResponse,
 | 
				
			||||||
    operation_id='deleteDeal'
 | 
					    operation_id='deleteDeal',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def delete(
 | 
					async def delete(
 | 
				
			||||||
        request: DealDeleteRequest,
 | 
					        request: DealDeleteRequest,
 | 
				
			||||||
@@ -39,7 +42,11 @@ async def delete(
 | 
				
			|||||||
    return await DealService(session).delete(request)
 | 
					    return await DealService(session).delete(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post('/quickCreate', response_model=DealQuickCreateResponse)
 | 
					@deal_router.post(
 | 
				
			||||||
 | 
					    '/quickCreate',
 | 
				
			||||||
 | 
					    response_model=DealQuickCreateResponse,
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
async def quick_create(
 | 
					async def quick_create(
 | 
				
			||||||
        request: DealQuickCreateRequest,
 | 
					        request: DealQuickCreateRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
@@ -48,7 +55,11 @@ async def quick_create(
 | 
				
			|||||||
    return await DealService(session).quick_create(request, user)
 | 
					    return await DealService(session).quick_create(request, user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post('/changeStatus', response_model=DealChangeStatusResponse)
 | 
					@deal_router.post(
 | 
				
			||||||
 | 
					    '/changeStatus',
 | 
				
			||||||
 | 
					    response_model=DealChangeStatusResponse,
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
async def change_status(
 | 
					async def change_status(
 | 
				
			||||||
        request: DealChangeStatusRequest,
 | 
					        request: DealChangeStatusRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
@@ -57,10 +68,12 @@ async def change_status(
 | 
				
			|||||||
    return await DealService(session).change_status_manual(request, user)
 | 
					    return await DealService(session).change_status_manual(request, user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.get('/summaries',
 | 
					@deal_router.get(
 | 
				
			||||||
 | 
					    '/summaries',
 | 
				
			||||||
    response_model=DealSummaryResponse,
 | 
					    response_model=DealSummaryResponse,
 | 
				
			||||||
                 operation_id='getDealSummaries'
 | 
					    operation_id='getDealSummaries',
 | 
				
			||||||
                 )
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
async def get_summary(
 | 
					async def get_summary(
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
@@ -70,7 +83,8 @@ async def get_summary(
 | 
				
			|||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/summaries/reorder',
 | 
					    '/summaries/reorder',
 | 
				
			||||||
    response_model=DealSummaryResponse,
 | 
					    response_model=DealSummaryResponse,
 | 
				
			||||||
    operation_id='reorderDealSummaries'
 | 
					    operation_id='reorderDealSummaries',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def reorder(
 | 
					async def reorder(
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
@@ -83,7 +97,8 @@ async def reorder(
 | 
				
			|||||||
@deal_router.get(
 | 
					@deal_router.get(
 | 
				
			||||||
    '/get-all',
 | 
					    '/get-all',
 | 
				
			||||||
    response_model=DealGetAllResponse,
 | 
					    response_model=DealGetAllResponse,
 | 
				
			||||||
    operation_id='getAllDeals'
 | 
					    operation_id='getAllDeals',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def get_all(
 | 
					async def get_all(
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
@@ -95,19 +110,22 @@ async def get_all(
 | 
				
			|||||||
@deal_router.get(
 | 
					@deal_router.get(
 | 
				
			||||||
    '/get/{deal_id}',
 | 
					    '/get/{deal_id}',
 | 
				
			||||||
    response_model=DealSchema,
 | 
					    response_model=DealSchema,
 | 
				
			||||||
    operation_id='getDealById'
 | 
					    operation_id='getDealById',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def get_deal_by_id(
 | 
					async def get_deal_by_id(
 | 
				
			||||||
        deal_id: int,
 | 
					        deal_id: int,
 | 
				
			||||||
 | 
					        user: CurrentUserDependency,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).get_by_id(deal_id)
 | 
					    return await DealService(session).get_by_id(user, deal_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/update-general-info',
 | 
					    '/update-general-info',
 | 
				
			||||||
    response_model=DealUpdateGeneralInfoResponse,
 | 
					    response_model=DealUpdateGeneralInfoResponse,
 | 
				
			||||||
    operation_id='updateDealGeneralInfo'
 | 
					    operation_id='updateDealGeneralInfo',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def update_general_info(
 | 
					async def update_general_info(
 | 
				
			||||||
        request: DealUpdateGeneralInfoRequest,
 | 
					        request: DealUpdateGeneralInfoRequest,
 | 
				
			||||||
@@ -115,16 +133,34 @@ async def update_general_info(
 | 
				
			|||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).update_general_info(request)
 | 
					    return await DealService(session).update_general_info(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/add-kit',
 | 
					    '/add-kit',
 | 
				
			||||||
    response_model=DealAddKitResponse,
 | 
					    response_model=DealAddKitResponse,
 | 
				
			||||||
    operation_id='add_kit_to_deal'
 | 
					    operation_id='add_kit_to_deal'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def add_kit_to_deal(
 | 
					async def add_kit_to_deal(
 | 
				
			||||||
        session:SessionDependency,
 | 
					        session: SessionDependency,
 | 
				
			||||||
        request:DealAddKitRequest
 | 
					        request: DealAddKitRequest
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).add_kit_to_deal(request)
 | 
					    return await DealService(session).add_kit_to_deal(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@deal_router.post(
 | 
				
			||||||
 | 
					    '/create-guest-url',
 | 
				
			||||||
 | 
					    response_model=DealCreateGuestUrlResponse,
 | 
				
			||||||
 | 
					    operation_id='create_deal_guest_url',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					async def create_guest_url(
 | 
				
			||||||
 | 
					        session: SessionDependency,
 | 
				
			||||||
 | 
					        request: DealCreateGuestUrlRequest,
 | 
				
			||||||
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return DealService(session).create_guest_url(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# endregion
 | 
					# endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Deal services
 | 
					# region Deal services
 | 
				
			||||||
@@ -132,11 +168,12 @@ async def add_kit_to_deal(
 | 
				
			|||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/services/add/multiple',
 | 
					    '/services/add/multiple',
 | 
				
			||||||
    response_model=DealAddServicesResponse,
 | 
					    response_model=DealAddServicesResponse,
 | 
				
			||||||
    operation_id='addMultipleDealServices'
 | 
					    operation_id='addMultipleDealServices',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def services_add(
 | 
					async def services_add(
 | 
				
			||||||
        request: DealAddServicesRequest,
 | 
					        request: DealAddServicesRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).add_services(request)
 | 
					    return await DealService(session).add_services(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -144,73 +181,86 @@ async def services_add(
 | 
				
			|||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/services/add',
 | 
					    '/services/add',
 | 
				
			||||||
    response_model=DealAddServiceResponse,
 | 
					    response_model=DealAddServiceResponse,
 | 
				
			||||||
    operation_id='addDealService'
 | 
					    operation_id='addDealService',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def services_add(
 | 
					async def services_add(
 | 
				
			||||||
        request: DealAddServiceRequest,
 | 
					        request: DealAddServiceRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).add_service(request)
 | 
					    return await DealService(session).add_service(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/services/update-quantity',
 | 
					    '/services/update-quantity',
 | 
				
			||||||
    response_model=DealUpdateServiceQuantityResponse,
 | 
					    response_model=DealUpdateServiceQuantityResponse,
 | 
				
			||||||
    operation_id='updateDealServiceQuantity'
 | 
					    operation_id='updateDealServiceQuantity',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def services_update_quantity(
 | 
					async def services_update_quantity(
 | 
				
			||||||
        request: DealUpdateServiceQuantityRequest,
 | 
					        request: DealUpdateServiceQuantityRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).update_service_quantity(request)
 | 
					    return await DealService(session).update_service_quantity(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/services/update',
 | 
					    '/services/update',
 | 
				
			||||||
    response_model=DealUpdateServiceResponse,
 | 
					    response_model=DealUpdateServiceResponse,
 | 
				
			||||||
    operation_id='updateDealService'
 | 
					    operation_id='updateDealService',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def services_update(
 | 
					async def services_update(
 | 
				
			||||||
        request: DealUpdateServiceRequest,
 | 
					        request: DealUpdateServiceRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).update_service(request)
 | 
					    return await DealService(session).update_service(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/services/delete',
 | 
					    '/services/delete',
 | 
				
			||||||
    response_model=DealDeleteServiceResponse,
 | 
					    response_model=DealDeleteServiceResponse,
 | 
				
			||||||
    operation_id='deleteDealService'
 | 
					    operation_id='deleteDealService',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def services_delete(
 | 
					async def services_delete(
 | 
				
			||||||
        request: DealDeleteServiceRequest,
 | 
					        request: DealDeleteServiceRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).delete_service(request)
 | 
					    return await DealService(session).delete_service(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/services/delete/multiple',
 | 
					    '/services/delete/multiple',
 | 
				
			||||||
    response_model=DealDeleteServicesResponse,
 | 
					    response_model=DealDeleteServicesResponse,
 | 
				
			||||||
    operation_id='deleteMultipleDealServices'
 | 
					    operation_id='deleteMultipleDealServices',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def services_delete(
 | 
					async def services_delete(
 | 
				
			||||||
        request: DealDeleteServicesRequest,
 | 
					        request: DealDeleteServicesRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).delete_services(request)
 | 
					    return await DealService(session).delete_services(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/services/copy',
 | 
					    '/services/copy',
 | 
				
			||||||
    response_model=DealServicesCopyResponse,
 | 
					    response_model=DealServicesCopyResponse,
 | 
				
			||||||
    operation_id='copy_product_services'
 | 
					    operation_id='copy_product_services',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def services_copy(
 | 
					async def services_copy(
 | 
				
			||||||
        session: SessionDependency,
 | 
					        session: SessionDependency,
 | 
				
			||||||
        request: DealServicesCopyRequest
 | 
					        request: DealServicesCopyRequest,
 | 
				
			||||||
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).copy_services(request)
 | 
					    return await DealService(session).copy_services(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# endregion
 | 
					# endregion
 | 
				
			||||||
@@ -219,63 +269,84 @@ async def services_copy(
 | 
				
			|||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/products/update-quantity',
 | 
					    '/products/update-quantity',
 | 
				
			||||||
    response_model=DealUpdateProductQuantityResponse,
 | 
					    response_model=DealUpdateProductQuantityResponse,
 | 
				
			||||||
    operation_id='updateDealProductQuantity')
 | 
					    operation_id='updateDealProductQuantity',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
async def products_update(
 | 
					async def products_update(
 | 
				
			||||||
        request: DealUpdateProductQuantityRequest,
 | 
					        request: DealUpdateProductQuantityRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]):
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
    return await DealService(session).update_product_quantity(request)
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DealService(session).update_product_quantity(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/products/add',
 | 
					    '/products/add',
 | 
				
			||||||
    response_model=DealAddProductResponse,
 | 
					    response_model=DealAddProductResponse,
 | 
				
			||||||
    operation_id='addDealProduct')
 | 
					    operation_id='addDealProduct',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
async def products_add(
 | 
					async def products_add(
 | 
				
			||||||
        request: DealAddProductRequest,
 | 
					        request: DealAddProductRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]):
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
    return await DealService(session).add_product(request)
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DealService(session).add_product(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/products/delete',
 | 
					    '/products/delete',
 | 
				
			||||||
    response_model=DealDeleteProductResponse,
 | 
					    response_model=DealDeleteProductResponse,
 | 
				
			||||||
    operation_id='deleteDealProduct')
 | 
					    operation_id='deleteDealProduct',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
async def products_delete(
 | 
					async def products_delete(
 | 
				
			||||||
        request: DealDeleteProductRequest,
 | 
					        request: DealDeleteProductRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]):
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
    return await DealService(session).delete_product(request)
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DealService(session).delete_product(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/products/delete/multiple',
 | 
					    '/products/delete/multiple',
 | 
				
			||||||
    response_model=DealDeleteProductsResponse,
 | 
					    response_model=DealDeleteProductsResponse,
 | 
				
			||||||
    operation_id='deleteMultipleDealProducts')
 | 
					    operation_id='deleteMultipleDealProducts',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
async def products_delete(
 | 
					async def products_delete(
 | 
				
			||||||
        request: DealDeleteProductsRequest,
 | 
					        request: DealDeleteProductsRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]):
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
    return await DealService(session).delete_products(request)
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return await DealService(session).delete_products(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/product/update',
 | 
					    '/product/update',
 | 
				
			||||||
    response_model=DealUpdateProductResponse,
 | 
					    response_model=DealUpdateProductResponse,
 | 
				
			||||||
    operation_id='updateDealProduct'
 | 
					    operation_id='updateDealProduct',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def products_update(
 | 
					async def products_update(
 | 
				
			||||||
        request: DealUpdateProductRequest,
 | 
					        request: DealUpdateProductRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).update_product(request)
 | 
					    return await DealService(session).update_product(user, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@deal_router.post(
 | 
					@deal_router.post(
 | 
				
			||||||
    '/product/add-kit',
 | 
					    '/product/add-kit',
 | 
				
			||||||
    response_model=DealProductAddKitResponse,
 | 
					    response_model=DealProductAddKitResponse,
 | 
				
			||||||
    operation_id='add_kit_to_deal_product'
 | 
					    operation_id='add_kit_to_deal_product',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def add_kit_to_deal_product(
 | 
					async def add_kit_to_deal_product(
 | 
				
			||||||
        session: SessionDependency,
 | 
					        session: SessionDependency,
 | 
				
			||||||
        request: DealProductAddKitRequest
 | 
					        request: DealProductAddKitRequest,
 | 
				
			||||||
 | 
					        user: CurrentUserDependency
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await DealService(session).add_kit_to_deal_product(request)
 | 
					    return await DealService(session).add_kit_to_deal_product(user, request)
 | 
				
			||||||
# endregion
 | 
					# endregion
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
from fastapi import APIRouter
 | 
					from fastapi import APIRouter, Depends
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backend.dependecies import SessionDependency
 | 
					from backend.dependecies import SessionDependency
 | 
				
			||||||
from schemas.marketplace import *
 | 
					from schemas.marketplace import *
 | 
				
			||||||
 | 
					from services.auth import authorized_user
 | 
				
			||||||
from services.marketplace import MarketplaceService
 | 
					from services.marketplace import MarketplaceService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
marketplace_router = APIRouter(
 | 
					marketplace_router = APIRouter(
 | 
				
			||||||
    prefix="/marketplace",
 | 
					    prefix="/marketplace",
 | 
				
			||||||
    tags=["marketplace"]
 | 
					    tags=["marketplace"],
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
from fastapi import APIRouter
 | 
					from fastapi import APIRouter, Depends
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backend.dependecies import SessionDependency, PaginationDependency, CurrentUserDependency
 | 
					from backend.dependecies import SessionDependency, PaginationDependency, CurrentUserDependency
 | 
				
			||||||
from schemas.finances import CreatePayRateRequest, UpdatePayRateRequest, DeletePayRateRequest, \
 | 
					from schemas.finances import CreatePayRateRequest, UpdatePayRateRequest, DeletePayRateRequest, \
 | 
				
			||||||
@@ -6,11 +6,13 @@ from schemas.finances import CreatePayRateRequest, UpdatePayRateRequest, DeleteP
 | 
				
			|||||||
    DeletePayRateResponse
 | 
					    DeletePayRateResponse
 | 
				
			||||||
from schemas.payment_record import GetPaymentRecordsResponse, CreatePaymentRecordResponse, CreatePaymentRecordRequest, \
 | 
					from schemas.payment_record import GetPaymentRecordsResponse, CreatePaymentRecordResponse, CreatePaymentRecordRequest, \
 | 
				
			||||||
    DeletePaymentRecordResponse, DeletePaymentRecordRequest
 | 
					    DeletePaymentRecordResponse, DeletePaymentRecordRequest
 | 
				
			||||||
 | 
					from services.auth import authorized_user
 | 
				
			||||||
from services.payroll import PayrollService
 | 
					from services.payroll import PayrollService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
payroll_router = APIRouter(
 | 
					payroll_router = APIRouter(
 | 
				
			||||||
    prefix="/payroll",
 | 
					    prefix="/payroll",
 | 
				
			||||||
    tags=["payroll"]
 | 
					    tags=["payroll"],
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
from fastapi import APIRouter
 | 
					from fastapi import APIRouter, Depends
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backend.dependecies import SessionDependency
 | 
					from backend.dependecies import SessionDependency
 | 
				
			||||||
from schemas.position import *
 | 
					from schemas.position import *
 | 
				
			||||||
 | 
					from services.auth import authorized_user
 | 
				
			||||||
from services.position import PositionService
 | 
					from services.position import PositionService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
position_router = APIRouter(
 | 
					position_router = APIRouter(
 | 
				
			||||||
    prefix="/position",
 | 
					    prefix="/position",
 | 
				
			||||||
    tags=["position"]
 | 
					    tags=["position"],
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,18 +6,20 @@ from fastapi import APIRouter, Depends, UploadFile
 | 
				
			|||||||
from sqlalchemy.ext.asyncio import AsyncSession
 | 
					from sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import utils.dependecies
 | 
					import utils.dependecies
 | 
				
			||||||
 | 
					from backend.dependecies import CurrentUserDependency
 | 
				
			||||||
from backend.session import get_session
 | 
					from backend.session import get_session
 | 
				
			||||||
from schemas.barcode import GetProductBarcodeResponse, GetProductBarcodeRequest, GetProductBarcodePdfResponse, \
 | 
					from schemas.barcode import GetProductBarcodeResponse, GetProductBarcodeRequest, GetProductBarcodePdfResponse, \
 | 
				
			||||||
    GetProductBarcodePdfRequest
 | 
					    GetProductBarcodePdfRequest
 | 
				
			||||||
from schemas.base import PaginationSchema
 | 
					from schemas.base import PaginationSchema
 | 
				
			||||||
from schemas.product import *
 | 
					from schemas.product import *
 | 
				
			||||||
 | 
					from services.auth import guest_user
 | 
				
			||||||
from services.barcode import BarcodeService
 | 
					from services.barcode import BarcodeService
 | 
				
			||||||
from services.product import ProductService
 | 
					from services.product import ProductService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
product_router = APIRouter(
 | 
					product_router = APIRouter(
 | 
				
			||||||
    prefix="/product",
 | 
					    prefix="/product",
 | 
				
			||||||
    tags=["product"],
 | 
					    tags=["product"],
 | 
				
			||||||
    # dependencies=[Depends(get_current_user)]
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,7 +30,7 @@ product_router = APIRouter(
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
async def create_product(
 | 
					async def create_product(
 | 
				
			||||||
        request: ProductCreateRequest,
 | 
					        request: ProductCreateRequest,
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await ProductService(session).create(request)
 | 
					    return await ProductService(session).create(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -146,9 +148,7 @@ async def get_product_barcode_pdf(
 | 
				
			|||||||
        filename=filename,
 | 
					        filename=filename,
 | 
				
			||||||
        mime_type='application/pdf'
 | 
					        mime_type='application/pdf'
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    # return StreamingResponse(content=pdf_buffer,
 | 
					
 | 
				
			||||||
    #                          media_type='application/pdf',
 | 
					 | 
				
			||||||
    #                          headers={"Content-Disposition": f"inline; filename={filename}"})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@product_router.post(
 | 
					@product_router.post(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
from fastapi import APIRouter
 | 
					from fastapi import APIRouter, Depends
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backend.dependecies import SessionDependency
 | 
					from backend.dependecies import SessionDependency
 | 
				
			||||||
from schemas.role import *
 | 
					from schemas.role import *
 | 
				
			||||||
 | 
					from services.auth import authorized_user
 | 
				
			||||||
from services.role import RoleService
 | 
					from services.role import RoleService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
role_router = APIRouter(
 | 
					role_router = APIRouter(
 | 
				
			||||||
    prefix='/role',
 | 
					    prefix='/role',
 | 
				
			||||||
    tags=['role']
 | 
					    tags=['role'],
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,22 +6,23 @@ from sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			|||||||
import enums.service
 | 
					import enums.service
 | 
				
			||||||
from backend.dependecies import SessionDependency
 | 
					from backend.dependecies import SessionDependency
 | 
				
			||||||
from backend.session import get_session
 | 
					from backend.session import get_session
 | 
				
			||||||
from schemas.base import BaseEnumSchema, BaseEnumListSchema
 | 
					from schemas.base import BaseEnumListSchema
 | 
				
			||||||
from schemas.service import *
 | 
					from schemas.service import *
 | 
				
			||||||
from services.auth import get_current_user
 | 
					from services.auth import guest_user, authorized_user
 | 
				
			||||||
from services.service import ServiceService
 | 
					from services.service import ServiceService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
service_router = APIRouter(
 | 
					service_router = APIRouter(
 | 
				
			||||||
    prefix="/service",
 | 
					    prefix="/service",
 | 
				
			||||||
    tags=['service'],
 | 
					    tags=['service'],
 | 
				
			||||||
    dependencies=[Depends(get_current_user)]
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@service_router.get(
 | 
					@service_router.get(
 | 
				
			||||||
    '/get-all',
 | 
					    '/get-all',
 | 
				
			||||||
    response_model=ServiceGetAllResponse,
 | 
					    response_model=ServiceGetAllResponse,
 | 
				
			||||||
    operation_id="get_all_services"
 | 
					    operation_id="get_all_services",
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def get_all(
 | 
					async def get_all(
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
@@ -32,7 +33,8 @@ async def get_all(
 | 
				
			|||||||
@service_router.post(
 | 
					@service_router.post(
 | 
				
			||||||
    '/create',
 | 
					    '/create',
 | 
				
			||||||
    response_model=ServiceCreateResponse,
 | 
					    response_model=ServiceCreateResponse,
 | 
				
			||||||
    operation_id="create_service"
 | 
					    operation_id="create_service",
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def create(
 | 
					async def create(
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
@@ -44,7 +46,8 @@ async def create(
 | 
				
			|||||||
@service_router.post(
 | 
					@service_router.post(
 | 
				
			||||||
    '/update',
 | 
					    '/update',
 | 
				
			||||||
    response_model=ServiceUpdateResponse,
 | 
					    response_model=ServiceUpdateResponse,
 | 
				
			||||||
    operation_id="update_service"
 | 
					    operation_id="update_service",
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def update(
 | 
					async def update(
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
@@ -56,7 +59,8 @@ async def update(
 | 
				
			|||||||
@service_router.post(
 | 
					@service_router.post(
 | 
				
			||||||
    '/delete',
 | 
					    '/delete',
 | 
				
			||||||
    response_model=ServiceDeleteResponse,
 | 
					    response_model=ServiceDeleteResponse,
 | 
				
			||||||
    operation_id="delete_service"
 | 
					    operation_id="delete_service",
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def delete(
 | 
					async def delete(
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
@@ -68,7 +72,8 @@ async def delete(
 | 
				
			|||||||
@service_router.get(
 | 
					@service_router.get(
 | 
				
			||||||
    '/categories/get-all',
 | 
					    '/categories/get-all',
 | 
				
			||||||
    response_model=ServiceGetAllCategoriesResponse,
 | 
					    response_model=ServiceGetAllCategoriesResponse,
 | 
				
			||||||
    operation_id="get_all_service_categories"
 | 
					    operation_id="get_all_service_categories",
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def get_all_categories(
 | 
					async def get_all_categories(
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
@@ -79,7 +84,8 @@ async def get_all_categories(
 | 
				
			|||||||
@service_router.post(
 | 
					@service_router.post(
 | 
				
			||||||
    '/categories/create',
 | 
					    '/categories/create',
 | 
				
			||||||
    response_model=ServiceCreateCategoryResponse,
 | 
					    response_model=ServiceCreateCategoryResponse,
 | 
				
			||||||
    operation_id="create_service_category"
 | 
					    operation_id="create_service_category",
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def create_category(
 | 
					async def create_category(
 | 
				
			||||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
@@ -91,7 +97,8 @@ async def create_category(
 | 
				
			|||||||
@service_router.get(
 | 
					@service_router.get(
 | 
				
			||||||
    '/types/get-all',
 | 
					    '/types/get-all',
 | 
				
			||||||
    response_model=BaseEnumListSchema,
 | 
					    response_model=BaseEnumListSchema,
 | 
				
			||||||
    operation_id="get_all_service_types"
 | 
					    operation_id="get_all_service_types",
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def get_all_service_types(
 | 
					async def get_all_service_types(
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
@@ -104,7 +111,8 @@ async def get_all_service_types(
 | 
				
			|||||||
@service_router.get(
 | 
					@service_router.get(
 | 
				
			||||||
    '/kits/get-all',
 | 
					    '/kits/get-all',
 | 
				
			||||||
    response_model=GetAllServicesKitsResponse,
 | 
					    response_model=GetAllServicesKitsResponse,
 | 
				
			||||||
    operation_id='get_all_services_kits'
 | 
					    operation_id='get_all_services_kits',
 | 
				
			||||||
 | 
					    dependencies=[Depends(guest_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def get_all_services_kits(
 | 
					async def get_all_services_kits(
 | 
				
			||||||
        session: SessionDependency
 | 
					        session: SessionDependency
 | 
				
			||||||
@@ -115,7 +123,8 @@ async def get_all_services_kits(
 | 
				
			|||||||
@service_router.post(
 | 
					@service_router.post(
 | 
				
			||||||
    '/kits/create',
 | 
					    '/kits/create',
 | 
				
			||||||
    response_model=CreateServicesKitResponse,
 | 
					    response_model=CreateServicesKitResponse,
 | 
				
			||||||
    operation_id='create_services_kit'
 | 
					    operation_id='create_services_kit',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def create_services_kit(
 | 
					async def create_services_kit(
 | 
				
			||||||
        session: SessionDependency,
 | 
					        session: SessionDependency,
 | 
				
			||||||
@@ -127,7 +136,8 @@ async def create_services_kit(
 | 
				
			|||||||
@service_router.post(
 | 
					@service_router.post(
 | 
				
			||||||
    '/kits/update',
 | 
					    '/kits/update',
 | 
				
			||||||
    response_model=UpdateServicesKitResponse,
 | 
					    response_model=UpdateServicesKitResponse,
 | 
				
			||||||
    operation_id='update_services_kit'
 | 
					    operation_id='update_services_kit',
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
async def update_services_kit(
 | 
					async def update_services_kit(
 | 
				
			||||||
        session: SessionDependency,
 | 
					        session: SessionDependency,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,13 +5,13 @@ from sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from backend.session import get_session
 | 
					from backend.session import get_session
 | 
				
			||||||
from schemas.shipping_warehouse import GetAllShippingWarehousesResponse
 | 
					from schemas.shipping_warehouse import GetAllShippingWarehousesResponse
 | 
				
			||||||
from services.auth import get_current_user
 | 
					from services.auth import authorized_user
 | 
				
			||||||
from services.shipping_warehouse import ShippingWarehouseService
 | 
					from services.shipping_warehouse import ShippingWarehouseService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
shipping_warehouse_router = APIRouter(
 | 
					shipping_warehouse_router = APIRouter(
 | 
				
			||||||
    prefix="/shipping-warehouse",
 | 
					    prefix="/shipping-warehouse",
 | 
				
			||||||
    tags=["shipping-warehouse"],
 | 
					    tags=["shipping-warehouse"],
 | 
				
			||||||
    dependencies=[Depends(get_current_user)]
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
from fastapi import APIRouter
 | 
					from fastapi import APIRouter, Depends
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backend.dependecies import SessionDependency, CurrentUserDependency
 | 
					from backend.dependecies import SessionDependency, CurrentUserDependency
 | 
				
			||||||
from schemas.time_tracking import *
 | 
					from schemas.time_tracking import *
 | 
				
			||||||
 | 
					from services.auth import authorized_user
 | 
				
			||||||
from services.time_tracking import TimeTrackingService
 | 
					from services.time_tracking import TimeTrackingService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
time_tracking_router = APIRouter(
 | 
					time_tracking_router = APIRouter(
 | 
				
			||||||
    prefix="/time-tracking",
 | 
					    prefix="/time-tracking",
 | 
				
			||||||
    tags=["time-tracking"]
 | 
					    tags=["time-tracking"],
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
from fastapi import APIRouter
 | 
					from fastapi import APIRouter, Depends
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backend.dependecies import SessionDependency
 | 
					from backend.dependecies import SessionDependency
 | 
				
			||||||
from schemas.user import *
 | 
					from schemas.user import *
 | 
				
			||||||
 | 
					from services.auth import authorized_user
 | 
				
			||||||
from services.user import UserService
 | 
					from services.user import UserService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
user_router = APIRouter(
 | 
					user_router = APIRouter(
 | 
				
			||||||
    prefix="/user",
 | 
					    prefix="/user",
 | 
				
			||||||
    tags=["user"]
 | 
					    tags=["user"],
 | 
				
			||||||
 | 
					    dependencies=[Depends(authorized_user)]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								schemas/billing.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								schemas/billing.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					import datetime
 | 
				
			||||||
 | 
					from typing import Optional
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from schemas.base import BaseSchema, OkMessageSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DealBillRequestSchema(BaseSchema):
 | 
				
			||||||
 | 
					    deal_id: int
 | 
				
			||||||
 | 
					    created_at: datetime.datetime
 | 
				
			||||||
 | 
					    paid: bool
 | 
				
			||||||
 | 
					    pdf_url: Optional[str]
 | 
				
			||||||
 | 
					    invoice_number: Optional[str]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateDealBillRequest(BaseSchema):
 | 
				
			||||||
 | 
					    deal_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateDealBillResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GetDealBillById(BaseSchema):
 | 
				
			||||||
 | 
					    deal_bill: DealBillRequestSchema
 | 
				
			||||||
@@ -4,6 +4,7 @@ from typing import List, Optional, Union
 | 
				
			|||||||
from pydantic import constr, field_validator
 | 
					from pydantic import constr, field_validator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from schemas.base import BaseSchema, OkMessageSchema
 | 
					from schemas.base import BaseSchema, OkMessageSchema
 | 
				
			||||||
 | 
					from schemas.billing import DealBillRequestSchema
 | 
				
			||||||
from schemas.client import ClientSchema
 | 
					from schemas.client import ClientSchema
 | 
				
			||||||
from schemas.marketplace import BaseMarketplaceSchema
 | 
					from schemas.marketplace import BaseMarketplaceSchema
 | 
				
			||||||
from schemas.product import ProductSchema
 | 
					from schemas.product import ProductSchema
 | 
				
			||||||
@@ -71,9 +72,11 @@ class DealSchema(BaseSchema):
 | 
				
			|||||||
    status_history: List[DealStatusHistorySchema]
 | 
					    status_history: List[DealStatusHistorySchema]
 | 
				
			||||||
    is_deleted: bool
 | 
					    is_deleted: bool
 | 
				
			||||||
    is_completed: bool
 | 
					    is_completed: bool
 | 
				
			||||||
 | 
					    is_locked: bool
 | 
				
			||||||
    client: ClientSchema
 | 
					    client: ClientSchema
 | 
				
			||||||
    comment: str
 | 
					    comment: str
 | 
				
			||||||
    shipping_warehouse: Optional[Union[ShippingWarehouseSchema, str]] = None
 | 
					    shipping_warehouse: Optional[Union[ShippingWarehouseSchema, str]] = None
 | 
				
			||||||
 | 
					    bill_request: Optional[DealBillRequestSchema] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DealGeneralInfoSchema(BaseSchema):
 | 
					class DealGeneralInfoSchema(BaseSchema):
 | 
				
			||||||
@@ -202,6 +205,10 @@ class DealAddKitRequest(BaseSchema):
 | 
				
			|||||||
    kit_id: int
 | 
					    kit_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DealCreateGuestUrlRequest(BaseSchema):
 | 
				
			||||||
 | 
					    deal_id: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# endregion Requests
 | 
					# endregion Requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Responses
 | 
					# region Responses
 | 
				
			||||||
@@ -293,4 +300,8 @@ class DealProductAddKitResponse(OkMessageSchema):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class DealAddKitResponse(OkMessageSchema):
 | 
					class DealAddKitResponse(OkMessageSchema):
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DealCreateGuestUrlResponse(OkMessageSchema):
 | 
				
			||||||
 | 
					    url: str
 | 
				
			||||||
# endregion Responses
 | 
					# endregion Responses
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,8 +19,10 @@ oauth2_schema = HTTPBearer()
 | 
				
			|||||||
algorithm = 'HS256'
 | 
					algorithm = 'HS256'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def get_current_user(session: Annotated[AsyncSession, Depends(get_session)],
 | 
					async def get_current_user(
 | 
				
			||||||
                           token: Annotated[HTTPAuthorizationCredentials, Depends(oauth2_schema)]) -> User | None:
 | 
					        session: Annotated[AsyncSession, Depends(get_session)],
 | 
				
			||||||
 | 
					        token: Annotated[HTTPAuthorizationCredentials, Depends(oauth2_schema)]
 | 
				
			||||||
 | 
					) -> Union[User, None, dict]:
 | 
				
			||||||
    if not token.credentials:
 | 
					    if not token.credentials:
 | 
				
			||||||
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid token')
 | 
					        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid token')
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
@@ -28,6 +30,8 @@ async def get_current_user(session: Annotated[AsyncSession, Depends(get_session)
 | 
				
			|||||||
        user_id = payload.get('sub')
 | 
					        user_id = payload.get('sub')
 | 
				
			||||||
        if not user_id:
 | 
					        if not user_id:
 | 
				
			||||||
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Invalid credentials')
 | 
					            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Invalid credentials')
 | 
				
			||||||
 | 
					        if user_id == 'guest':
 | 
				
			||||||
 | 
					            return payload
 | 
				
			||||||
        user_id = int(user_id)
 | 
					        user_id = int(user_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        user = await session.get(User, user_id)
 | 
					        user = await session.get(User, user_id)
 | 
				
			||||||
@@ -35,16 +39,26 @@ async def get_current_user(session: Annotated[AsyncSession, Depends(get_session)
 | 
				
			|||||||
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid credentials')
 | 
					            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid credentials')
 | 
				
			||||||
        return user
 | 
					        return user
 | 
				
			||||||
    except JWTError as e:
 | 
					    except JWTError as e:
 | 
				
			||||||
        print(e)
 | 
					        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid token')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def authorized_user(
 | 
				
			||||||
 | 
					        user: Annotated[User, Depends(get_current_user)]
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    if type(user) is User:
 | 
				
			||||||
 | 
					        return user
 | 
				
			||||||
 | 
					    raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid token')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def guest_user(user: Annotated[User, Depends(get_current_user)]):
 | 
				
			||||||
 | 
					    if (type(user) is User) or (type(user) is dict):
 | 
				
			||||||
 | 
					        return user
 | 
				
			||||||
    raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid token')
 | 
					    raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid token')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AuthService(BaseService):
 | 
					class AuthService(BaseService):
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def _generate_jwt_token(user: User) -> str:
 | 
					    def _generate_jwt_token(payload: dict) -> str:
 | 
				
			||||||
        payload = {
 | 
					 | 
				
			||||||
            'sub': str(user.id)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return jwt.encode(payload, backend.config.SECRET_KEY, algorithm=algorithm)
 | 
					        return jwt.encode(payload, backend.config.SECRET_KEY, algorithm=algorithm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def authenticate(self, request: AuthLoginRequest):
 | 
					    async def authenticate(self, request: AuthLoginRequest):
 | 
				
			||||||
@@ -60,5 +74,16 @@ class AuthService(BaseService):
 | 
				
			|||||||
            )
 | 
					            )
 | 
				
			||||||
            self.session.add(user)
 | 
					            self.session.add(user)
 | 
				
			||||||
            await self.session.commit()
 | 
					            await self.session.commit()
 | 
				
			||||||
        access_token = self._generate_jwt_token(user)
 | 
					        payload = {
 | 
				
			||||||
 | 
					            'sub': str(user.id)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        access_token = self._generate_jwt_token(payload)
 | 
				
			||||||
        return AuthLoginResponse(access_token=access_token)
 | 
					        return AuthLoginResponse(access_token=access_token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_deal_guest_token(self, deal_id: int):
 | 
				
			||||||
 | 
					        payload = {
 | 
				
			||||||
 | 
					            'sub': 'guest',
 | 
				
			||||||
 | 
					            'deal_id': deal_id
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return self._generate_jwt_token(payload)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										118
									
								
								services/billing.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								services/billing.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
				
			|||||||
 | 
					import datetime
 | 
				
			||||||
 | 
					from typing import List
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from fastapi import HTTPException
 | 
				
			||||||
 | 
					from sqlalchemy import select
 | 
				
			||||||
 | 
					from starlette import status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import backend.config
 | 
				
			||||||
 | 
					from external.billing import BillingClient, CreateBillingRequestValue, CreateBillRequestSchema, CreateBillRequestItems, \
 | 
				
			||||||
 | 
					    BillStatusUpdateRequest, NotificationChannel, NotifyReceivedBillRequestSchema, BillPaymentInfo
 | 
				
			||||||
 | 
					from models import DealBillRequest, Deal
 | 
				
			||||||
 | 
					from schemas.billing import *
 | 
				
			||||||
 | 
					from services.base import BaseService
 | 
				
			||||||
 | 
					from services.deal import DealService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BillingService(BaseService):
 | 
				
			||||||
 | 
					    async def _process_update_details(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            request: BillStatusUpdateRequest
 | 
				
			||||||
 | 
					    ):
 | 
				
			||||||
 | 
					        billing_client = BillingClient(backend.config.BILLING_API_KEY)
 | 
				
			||||||
 | 
					        notify_received_request = NotifyReceivedBillRequestSchema(
 | 
				
			||||||
 | 
					            listener_transaction_id=request.listener_transaction_id,
 | 
				
			||||||
 | 
					            channel=NotificationChannel.PAYMENT_DETAILS,
 | 
				
			||||||
 | 
					            received=True
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        response = await billing_client.notify_received(notify_received_request)
 | 
				
			||||||
 | 
					        deal_bill_request = await self._get_deal_bill_by_id(request.listener_transaction_id)
 | 
				
			||||||
 | 
					        if not response.ok:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        deal_bill_request.pdf_url = request.info.pdf_url
 | 
				
			||||||
 | 
					        deal_bill_request.invoice_number = request.info.invoice_number
 | 
				
			||||||
 | 
					        await self.session.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def _process_update_verification(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            request: BillStatusUpdateRequest
 | 
				
			||||||
 | 
					    ):
 | 
				
			||||||
 | 
					        billing_client = BillingClient(backend.config.BILLING_API_KEY)
 | 
				
			||||||
 | 
					        notify_received_request = NotifyReceivedBillRequestSchema(
 | 
				
			||||||
 | 
					            listener_transaction_id=request.listener_transaction_id,
 | 
				
			||||||
 | 
					            channel=NotificationChannel.PAYMENT_VERIFICATION,
 | 
				
			||||||
 | 
					            received=True
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        response = await billing_client.notify_received(notify_received_request)
 | 
				
			||||||
 | 
					        if not response.ok:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        deal_bill_request = await self._get_deal_bill_by_id(request.listener_transaction_id)
 | 
				
			||||||
 | 
					        if not deal_bill_request:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        deal_bill_request.paid = request.info.payed
 | 
				
			||||||
 | 
					        await self.session.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def process_update(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            request: BillStatusUpdateRequest
 | 
				
			||||||
 | 
					    ):
 | 
				
			||||||
 | 
					        if request.channel == NotificationChannel.PAYMENT_DETAILS:
 | 
				
			||||||
 | 
					            await self._process_update_details(request)
 | 
				
			||||||
 | 
					        elif request.channel == NotificationChannel.PAYMENT_VERIFICATION:
 | 
				
			||||||
 | 
					            await self._process_update_verification(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def create_deal_billing(self, user, request: CreateDealBillRequest) -> CreateDealBillResponse:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            deal_service = DealService(self.session)
 | 
				
			||||||
 | 
					            billing_client = BillingClient(backend.config.BILLING_API_KEY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            deal: Deal = await deal_service.get_by_id(user, request.deal_id)
 | 
				
			||||||
 | 
					            billing_request_values: List[CreateBillingRequestValue] = []
 | 
				
			||||||
 | 
					            for product in deal.products:
 | 
				
			||||||
 | 
					                for service in product.services:
 | 
				
			||||||
 | 
					                    billing_request_values.append(
 | 
				
			||||||
 | 
					                        CreateBillingRequestValue(
 | 
				
			||||||
 | 
					                            name=f'[{product.product.name}] - {service.service.name}',
 | 
				
			||||||
 | 
					                            price=service.price,
 | 
				
			||||||
 | 
					                            amount=product.quantity
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					            for service in deal.services:
 | 
				
			||||||
 | 
					                billing_request_values.append(
 | 
				
			||||||
 | 
					                    CreateBillingRequestValue(
 | 
				
			||||||
 | 
					                        name=f'{service.service.name}',
 | 
				
			||||||
 | 
					                        price=service.price,
 | 
				
			||||||
 | 
					                        amount=service.quantity
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            create_bill_request = CreateBillRequestSchema(
 | 
				
			||||||
 | 
					                listener_transaction_id=deal.id,
 | 
				
			||||||
 | 
					                payer_name=deal.client.name,
 | 
				
			||||||
 | 
					                payer_inn=deal.client.details.inn,
 | 
				
			||||||
 | 
					                payer_phone=deal.client.details.phone_number,
 | 
				
			||||||
 | 
					                items=CreateBillRequestItems(
 | 
				
			||||||
 | 
					                    values=billing_request_values
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            create_bill_response = await billing_client.create(create_bill_request)
 | 
				
			||||||
 | 
					            if not create_bill_response.ok:
 | 
				
			||||||
 | 
					                return CreateDealBillResponse(ok=create_bill_response.ok, message='Ошибка!')
 | 
				
			||||||
 | 
					            deal_bill_request = DealBillRequest(
 | 
				
			||||||
 | 
					                deal_id=request.deal_id,
 | 
				
			||||||
 | 
					                created_at=datetime.datetime.now()
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            self.session.add(deal_bill_request)
 | 
				
			||||||
 | 
					            deal.is_locked = True
 | 
				
			||||||
 | 
					            await self.session.commit()
 | 
				
			||||||
 | 
					            return CreateDealBillResponse(ok=create_bill_response.ok, message='Заявка успешно создана!')
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            return CreateDealBillResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def _get_deal_bill_by_id(self, deal_id: int) -> Optional[DealBillRequest]:
 | 
				
			||||||
 | 
					        return await self.session.scalar(select(DealBillRequest).where(DealBillRequest.deal_id == deal_id))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def get_deal_bill_by_id(self, deal_id: int) -> GetDealBillById:
 | 
				
			||||||
 | 
					        deal_bill = await self._get_deal_bill_by_id(deal_id)
 | 
				
			||||||
 | 
					        if not deal_bill:
 | 
				
			||||||
 | 
					            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='Deal bill was not found')
 | 
				
			||||||
 | 
					        return GetDealBillById(deal_bill=DealBillRequestSchema.model_validate(deal_bill))
 | 
				
			||||||
							
								
								
									
										120
									
								
								services/deal.py
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								services/deal.py
									
									
									
									
									
								
							@@ -1,16 +1,16 @@
 | 
				
			|||||||
import lexorank
 | 
					import lexorank
 | 
				
			||||||
 | 
					 | 
				
			||||||
import models.secondary
 | 
					 | 
				
			||||||
from typing import Union
 | 
					 | 
				
			||||||
import models.deal
 | 
					 | 
				
			||||||
from fastapi import HTTPException
 | 
					from fastapi import HTTPException
 | 
				
			||||||
from sqlalchemy import select, func, update, delete, insert
 | 
					from sqlalchemy import select, func, update, delete, insert
 | 
				
			||||||
from sqlalchemy.orm import joinedload, selectinload
 | 
					from sqlalchemy.orm import joinedload, selectinload
 | 
				
			||||||
 | 
					from starlette import status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import models.deal
 | 
				
			||||||
 | 
					import models.secondary
 | 
				
			||||||
from models import User, Service, Client
 | 
					from models import User, Service, Client
 | 
				
			||||||
from models.deal import *
 | 
					from models.deal import *
 | 
				
			||||||
from schemas.client import ClientDetailsSchema
 | 
					from schemas.client import ClientDetailsSchema
 | 
				
			||||||
from schemas.deal import *
 | 
					from schemas.deal import *
 | 
				
			||||||
 | 
					from services.auth import AuthService
 | 
				
			||||||
from services.base import BaseService
 | 
					from services.base import BaseService
 | 
				
			||||||
from services.client import ClientService
 | 
					from services.client import ClientService
 | 
				
			||||||
from services.service import ServiceService
 | 
					from services.service import ServiceService
 | 
				
			||||||
@@ -20,6 +20,15 @@ from services.shipping_warehouse import ShippingWarehouseService
 | 
				
			|||||||
class DealService(BaseService):
 | 
					class DealService(BaseService):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # region Deal
 | 
					    # region Deal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def grant_access(user: Union[models.User, dict], deal_id):
 | 
				
			||||||
 | 
					        if type(user) is models.User:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        user_deal_id = user['deal_id']
 | 
				
			||||||
 | 
					        if int(user_deal_id) != int(deal_id):
 | 
				
			||||||
 | 
					            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid token')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def _get_deal_by_id(self, deal_id) -> Union[Deal, None]:
 | 
					    async def _get_deal_by_id(self, deal_id) -> Union[Deal, None]:
 | 
				
			||||||
        return await self.session.get(Deal, deal_id)
 | 
					        return await self.session.get(Deal, deal_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -211,7 +220,9 @@ class DealService(BaseService):
 | 
				
			|||||||
            result.append(DealSchema.model_validate(deal))
 | 
					            result.append(DealSchema.model_validate(deal))
 | 
				
			||||||
        return DealGetAllResponse(deals=result)
 | 
					        return DealGetAllResponse(deals=result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def get_by_id(self, deal_id: int) -> DealSchema:
 | 
					    async def get_by_id(self, user: Union[models.User, dict], deal_id: int, return_raw=False) -> Union[
 | 
				
			||||||
 | 
					        DealSchema, models.Deal]:
 | 
				
			||||||
 | 
					        self.grant_access(user, deal_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        deal = await self.session.scalar(
 | 
					        deal = await self.session.scalar(
 | 
				
			||||||
            select(Deal)
 | 
					            select(Deal)
 | 
				
			||||||
@@ -244,7 +255,8 @@ class DealService(BaseService):
 | 
				
			|||||||
            )
 | 
					            )
 | 
				
			||||||
            .where(Deal.id == deal_id)
 | 
					            .where(Deal.id == deal_id)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					        if return_raw:
 | 
				
			||||||
 | 
					            return deal
 | 
				
			||||||
        if not deal:
 | 
					        if not deal:
 | 
				
			||||||
            raise HTTPException(status_code=404, detail="Сделка не найдена")
 | 
					            raise HTTPException(status_code=404, detail="Сделка не найдена")
 | 
				
			||||||
        return DealSchema.model_validate(deal)
 | 
					        return DealSchema.model_validate(deal)
 | 
				
			||||||
@@ -360,11 +372,17 @@ class DealService(BaseService):
 | 
				
			|||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            return DealAddKitResponse(ok=False, message=str(e))
 | 
					            return DealAddKitResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_guest_url(self, user: models.User, request: DealCreateGuestUrlRequest) -> DealCreateGuestUrlResponse:
 | 
				
			||||||
 | 
					        if not user.is_admin:
 | 
				
			||||||
 | 
					            return DealCreateGuestUrlResponse(ok=False, message='Создать ссылку может только администратор', url="")
 | 
				
			||||||
 | 
					        access_token = AuthService(self.session).create_deal_guest_token(request.deal_id)
 | 
				
			||||||
 | 
					        url = f"deals/{request.deal_id}?accessToken={access_token}"
 | 
				
			||||||
 | 
					        return DealCreateGuestUrlResponse(ok=True, message='Ссылка успешно создана!', url=url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # endregion
 | 
					    # endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # region Deal services
 | 
					    # region Deal services
 | 
				
			||||||
    async def add_services(self, request: DealAddServicesRequest):
 | 
					    async def add_services(self, request: DealAddServicesRequest):
 | 
				
			||||||
        # TODO refactor
 | 
					 | 
				
			||||||
        deal: Deal = await self.session.scalar(
 | 
					        deal: Deal = await self.session.scalar(
 | 
				
			||||||
            select(Deal)
 | 
					            select(Deal)
 | 
				
			||||||
            .options(selectinload(Deal.services))
 | 
					            .options(selectinload(Deal.services))
 | 
				
			||||||
@@ -404,9 +422,13 @@ class DealService(BaseService):
 | 
				
			|||||||
        await self.session.commit()
 | 
					        await self.session.commit()
 | 
				
			||||||
        return DealAddServicesResponse(ok=True, message='Услуги успешно добавлены')
 | 
					        return DealAddServicesResponse(ok=True, message='Услуги успешно добавлены')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def update_service_quantity(self,
 | 
					    async def update_service_quantity(
 | 
				
			||||||
                                      request: DealUpdateServiceQuantityRequest) -> DealUpdateServiceQuantityResponse:
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					            request: DealUpdateServiceQuantityRequest
 | 
				
			||||||
 | 
					    ) -> DealUpdateServiceQuantityResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
            deal_service = await self.session.scalar(
 | 
					            deal_service = await self.session.scalar(
 | 
				
			||||||
                select(models.secondary.DealService)
 | 
					                select(models.secondary.DealService)
 | 
				
			||||||
                .where(models.secondary.DealService.deal_id == request.deal_id,
 | 
					                .where(models.secondary.DealService.deal_id == request.deal_id,
 | 
				
			||||||
@@ -421,8 +443,12 @@ class DealService(BaseService):
 | 
				
			|||||||
            await self.session.rollback()
 | 
					            await self.session.rollback()
 | 
				
			||||||
            return DealUpdateServiceQuantityResponse(ok=False, message=str(e))
 | 
					            return DealUpdateServiceQuantityResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def add_service(self, request: DealAddServiceRequest) -> DealAddServiceResponse:
 | 
					    async def add_service(self,
 | 
				
			||||||
 | 
					                          user: Union[models.User, dict],
 | 
				
			||||||
 | 
					                          request: DealAddServiceRequest
 | 
				
			||||||
 | 
					                          ) -> DealAddServiceResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
            deal = await self.session.scalar(select(Deal).where(Deal.id == request.deal_id))
 | 
					            deal = await self.session.scalar(select(Deal).where(Deal.id == request.deal_id))
 | 
				
			||||||
            if not deal:
 | 
					            if not deal:
 | 
				
			||||||
                raise HTTPException(status_code=404, detail="Сделка не найдена")
 | 
					                raise HTTPException(status_code=404, detail="Сделка не найдена")
 | 
				
			||||||
@@ -450,8 +476,13 @@ class DealService(BaseService):
 | 
				
			|||||||
            await self.session.rollback()
 | 
					            await self.session.rollback()
 | 
				
			||||||
            return DealAddServiceResponse(ok=False, message=str(e))
 | 
					            return DealAddServiceResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def delete_service(self, request: DealDeleteServiceRequest) -> DealDeleteServiceResponse:
 | 
					    async def delete_service(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					            request: DealDeleteServiceRequest
 | 
				
			||||||
 | 
					    ) -> DealDeleteServiceResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
            deal_service = await self.session.scalar(
 | 
					            deal_service = await self.session.scalar(
 | 
				
			||||||
                select(models.secondary.DealService)
 | 
					                select(models.secondary.DealService)
 | 
				
			||||||
                .where(models.secondary.DealService.deal_id == request.deal_id,
 | 
					                .where(models.secondary.DealService.deal_id == request.deal_id,
 | 
				
			||||||
@@ -466,8 +497,13 @@ class DealService(BaseService):
 | 
				
			|||||||
            await self.session.rollback()
 | 
					            await self.session.rollback()
 | 
				
			||||||
            return DealDeleteServiceResponse(ok=False, message=str(e))
 | 
					            return DealDeleteServiceResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def delete_services(self, request: DealDeleteServicesRequest) -> DealDeleteServicesResponse:
 | 
					    async def delete_services(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					            request: DealDeleteServicesRequest
 | 
				
			||||||
 | 
					    ) -> DealDeleteServicesResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request)
 | 
				
			||||||
            deal_services = await self.session.scalars(
 | 
					            deal_services = await self.session.scalars(
 | 
				
			||||||
                select(models.secondary.DealService)
 | 
					                select(models.secondary.DealService)
 | 
				
			||||||
                .where(models.secondary.DealService.deal_id == request.deal_id,
 | 
					                .where(models.secondary.DealService.deal_id == request.deal_id,
 | 
				
			||||||
@@ -481,8 +517,13 @@ class DealService(BaseService):
 | 
				
			|||||||
            await self.session.rollback()
 | 
					            await self.session.rollback()
 | 
				
			||||||
            return DealDeleteServicesResponse(ok=False, message=str(e))
 | 
					            return DealDeleteServicesResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def update_service(self, request: DealUpdateServiceRequest) -> DealUpdateServiceResponse:
 | 
					    async def update_service(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					            request: DealUpdateServiceRequest
 | 
				
			||||||
 | 
					    ) -> DealUpdateServiceResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
            deal_service = await self.session.scalar(
 | 
					            deal_service = await self.session.scalar(
 | 
				
			||||||
                select(models.secondary.DealService)
 | 
					                select(models.secondary.DealService)
 | 
				
			||||||
                .where(models.secondary.DealService.deal_id == request.deal_id,
 | 
					                .where(models.secondary.DealService.deal_id == request.deal_id,
 | 
				
			||||||
@@ -535,9 +576,13 @@ class DealService(BaseService):
 | 
				
			|||||||
            await self.session.rollback()
 | 
					            await self.session.rollback()
 | 
				
			||||||
            return DealUpdateServiceQuantityResponse(ok=False, message=str(e))
 | 
					            return DealUpdateServiceQuantityResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def copy_services(self, request: DealServicesCopyRequest) -> DealServicesCopyResponse:
 | 
					    async def copy_services(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					            request: DealServicesCopyRequest
 | 
				
			||||||
 | 
					    ) -> DealServicesCopyResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
            source_services_stmt = (
 | 
					            source_services_stmt = (
 | 
				
			||||||
                select(
 | 
					                select(
 | 
				
			||||||
                    models.DealProductService
 | 
					                    models.DealProductService
 | 
				
			||||||
@@ -614,9 +659,13 @@ class DealService(BaseService):
 | 
				
			|||||||
    # endregion
 | 
					    # endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # region Deal products
 | 
					    # region Deal products
 | 
				
			||||||
    async def update_product_quantity(self,
 | 
					    async def update_product_quantity(
 | 
				
			||||||
                                      request: DealUpdateProductQuantityRequest) -> DealUpdateProductQuantityResponse:
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					            request: DealUpdateProductQuantityRequest
 | 
				
			||||||
 | 
					    ) -> DealUpdateProductQuantityResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
            # check if there is no deal or no product with different exceptions
 | 
					            # check if there is no deal or no product with different exceptions
 | 
				
			||||||
            deal_product = await self.session.scalar(
 | 
					            deal_product = await self.session.scalar(
 | 
				
			||||||
                select(models.secondary.DealProduct)
 | 
					                select(models.secondary.DealProduct)
 | 
				
			||||||
@@ -632,8 +681,15 @@ class DealService(BaseService):
 | 
				
			|||||||
            await self.session.rollback()
 | 
					            await self.session.rollback()
 | 
				
			||||||
            return DealUpdateProductQuantityResponse(ok=False, message=str(e))
 | 
					            return DealUpdateProductQuantityResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def add_product(self, request: DealAddProductRequest) -> DealAddProductResponse:
 | 
					    async def add_product(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            request: DealAddProductRequest
 | 
				
			||||||
 | 
					    ) -> DealAddProductResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            deal = await self.session.scalar(select(Deal).where(Deal.id == request.deal_id))
 | 
					            deal = await self.session.scalar(select(Deal).where(Deal.id == request.deal_id))
 | 
				
			||||||
            if not deal:
 | 
					            if not deal:
 | 
				
			||||||
                raise HTTPException(status_code=404, detail="Сделка не найдена")
 | 
					                raise HTTPException(status_code=404, detail="Сделка не найдена")
 | 
				
			||||||
@@ -670,8 +726,13 @@ class DealService(BaseService):
 | 
				
			|||||||
            await self.session.rollback()
 | 
					            await self.session.rollback()
 | 
				
			||||||
            return DealAddProductResponse(ok=False, message=str(e))
 | 
					            return DealAddProductResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def delete_product(self, request: DealDeleteProductRequest) -> DealDeleteProductResponse:
 | 
					    async def delete_product(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					            request: DealDeleteProductRequest
 | 
				
			||||||
 | 
					    ) -> DealDeleteProductResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
            deal_product = await self.session.scalar(
 | 
					            deal_product = await self.session.scalar(
 | 
				
			||||||
                select(models.secondary.DealProduct)
 | 
					                select(models.secondary.DealProduct)
 | 
				
			||||||
                .where(models.secondary.DealProduct.deal_id == request.deal_id,
 | 
					                .where(models.secondary.DealProduct.deal_id == request.deal_id,
 | 
				
			||||||
@@ -686,8 +747,13 @@ class DealService(BaseService):
 | 
				
			|||||||
            await self.session.rollback()
 | 
					            await self.session.rollback()
 | 
				
			||||||
            return DealDeleteProductResponse(ok=False, message=str(e))
 | 
					            return DealDeleteProductResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def delete_products(self, request: DealDeleteProductsRequest) -> DealDeleteProductsResponse:
 | 
					    async def delete_products(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					            request: DealDeleteProductsRequest
 | 
				
			||||||
 | 
					    ) -> DealDeleteProductsResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
            deal_products = await self.session.scalars(
 | 
					            deal_products = await self.session.scalars(
 | 
				
			||||||
                select(models.secondary.DealProduct)
 | 
					                select(models.secondary.DealProduct)
 | 
				
			||||||
                .where(models.secondary.DealProduct.deal_id == request.deal_id,
 | 
					                .where(models.secondary.DealProduct.deal_id == request.deal_id,
 | 
				
			||||||
@@ -701,8 +767,13 @@ class DealService(BaseService):
 | 
				
			|||||||
            await self.session.rollback()
 | 
					            await self.session.rollback()
 | 
				
			||||||
            return DealDeleteProductsResponse(ok=False, message=str(e))
 | 
					            return DealDeleteProductsResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def update_product(self, request: DealUpdateProductRequest):
 | 
					    async def update_product(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					            request: DealUpdateProductRequest
 | 
				
			||||||
 | 
					    ):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
            deal_product: models.DealProduct = await self.session.scalar(
 | 
					            deal_product: models.DealProduct = await self.session.scalar(
 | 
				
			||||||
                select(models.secondary.DealProduct)
 | 
					                select(models.secondary.DealProduct)
 | 
				
			||||||
                .where(models.secondary.DealProduct.deal_id == request.deal_id,
 | 
					                .where(models.secondary.DealProduct.deal_id == request.deal_id,
 | 
				
			||||||
@@ -781,8 +852,13 @@ class DealService(BaseService):
 | 
				
			|||||||
            await self.session.rollback()
 | 
					            await self.session.rollback()
 | 
				
			||||||
            return DealUpdateProductResponse(ok=False, message=str(e))
 | 
					            return DealUpdateProductResponse(ok=False, message=str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def add_kit_to_deal_product(self, request: DealProductAddKitRequest) -> DealProductAddKitResponse:
 | 
					    async def add_kit_to_deal_product(
 | 
				
			||||||
 | 
					            self,
 | 
				
			||||||
 | 
					            user: Union[models.User, dict],
 | 
				
			||||||
 | 
					            request: DealProductAddKitRequest
 | 
				
			||||||
 | 
					    ) -> DealProductAddKitResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 | 
					            self.grant_access(user, request.deal_id)
 | 
				
			||||||
            service_service = ServiceService(self.session)
 | 
					            service_service = ServiceService(self.session)
 | 
				
			||||||
            kit = await service_service.get_kit_by_id(request.kit_id)
 | 
					            kit = await service_service.get_kit_by_id(request.kit_id)
 | 
				
			||||||
            if not kit:
 | 
					            if not kit:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					from typing import Union
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from fastapi import HTTPException
 | 
					from fastapi import HTTPException
 | 
				
			||||||
from sqlalchemy import select, func, Integer, update
 | 
					from sqlalchemy import select, func, Integer, update
 | 
				
			||||||
from sqlalchemy.orm import selectinload
 | 
					from sqlalchemy.orm import selectinload
 | 
				
			||||||
@@ -5,25 +7,17 @@ from sqlalchemy.orm import selectinload
 | 
				
			|||||||
import utils.barcodes
 | 
					import utils.barcodes
 | 
				
			||||||
from backend import config
 | 
					from backend import config
 | 
				
			||||||
from external.s3_uploader.uploader import S3Uploader
 | 
					from external.s3_uploader.uploader import S3Uploader
 | 
				
			||||||
from models.product import Product, ProductBarcode, ProductImage
 | 
					from models import User
 | 
				
			||||||
 | 
					from models.product import Product, ProductImage
 | 
				
			||||||
from schemas.base import PaginationSchema
 | 
					from schemas.base import PaginationSchema
 | 
				
			||||||
from services.base import BaseService
 | 
					 | 
				
			||||||
from schemas.product import *
 | 
					from schemas.product import *
 | 
				
			||||||
 | 
					from services.base import BaseService
 | 
				
			||||||
from utils.dependecies import is_valid_pagination
 | 
					from utils.dependecies import is_valid_pagination
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProductService(BaseService):
 | 
					class ProductService(BaseService):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def create(self, request: ProductCreateRequest) -> ProductCreateResponse:
 | 
					    async def create(self, request: ProductCreateRequest) -> ProductCreateResponse:
 | 
				
			||||||
        # Unique article validation
 | 
					 | 
				
			||||||
        # existing_product_query = await self.session.execute(
 | 
					 | 
				
			||||||
        #     select(Product)
 | 
					 | 
				
			||||||
        #     .where(Product.client_id == request.client_id,
 | 
					 | 
				
			||||||
        #            Product.article == request.article)
 | 
					 | 
				
			||||||
        # )
 | 
					 | 
				
			||||||
        # existing_product = existing_product_query.first()
 | 
					 | 
				
			||||||
        # if existing_product:
 | 
					 | 
				
			||||||
        #     return ProductCreateResponse(ok=False, message='Товар с таким артикулом уже существует у клиента')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Creating product
 | 
					        # Creating product
 | 
				
			||||||
        product_dict = request.dict()
 | 
					        product_dict = request.dict()
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user