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)]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
183
routers/deal.py
183
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(
|
||||||
response_model=DealSummaryResponse,
|
'/summaries',
|
||||||
operation_id='getDealSummaries'
|
response_model=DealSummaryResponse,
|
||||||
)
|
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')
|
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')
|
||||||
|
|
||||||
|
|
||||||
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