othr
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -3,3 +3,4 @@
 | 
			
		||||
.venv
 | 
			
		||||
.idea
 | 
			
		||||
__pycache__
 | 
			
		||||
/venv
 | 
			
		||||
							
								
								
									
										16
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								main.py
									
									
									
									
									
								
							@@ -1,8 +1,21 @@
 | 
			
		||||
from fastapi import FastAPI
 | 
			
		||||
from fastapi.middleware.cors import CORSMiddleware
 | 
			
		||||
 | 
			
		||||
import routers
 | 
			
		||||
 | 
			
		||||
origins = [
 | 
			
		||||
    'http://localhost:5173'
 | 
			
		||||
]
 | 
			
		||||
app = FastAPI()
 | 
			
		||||
 | 
			
		||||
app.add_middleware(
 | 
			
		||||
    CORSMiddleware,
 | 
			
		||||
    allow_origins=origins,
 | 
			
		||||
    allow_credentials=True,
 | 
			
		||||
    allow_methods=["*"],
 | 
			
		||||
    allow_headers=["*"],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
routers_list = [
 | 
			
		||||
    routers.auth_router,
 | 
			
		||||
    routers.deal_router,
 | 
			
		||||
@@ -10,6 +23,3 @@ routers_list = [
 | 
			
		||||
]
 | 
			
		||||
for router in routers_list:
 | 
			
		||||
    app.include_router(router)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
from sqlalchemy import Column, Integer, String, DateTime
 | 
			
		||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, BigInteger
 | 
			
		||||
from sqlalchemy.orm import relationship
 | 
			
		||||
 | 
			
		||||
from models import BaseModel
 | 
			
		||||
 | 
			
		||||
@@ -7,5 +8,23 @@ class Client(BaseModel):
 | 
			
		||||
    __tablename__ = 'clients'
 | 
			
		||||
    id = Column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
			
		||||
    name = Column(String, nullable=False, unique=True, comment='Название клиента')
 | 
			
		||||
    address = Column(String)
 | 
			
		||||
    created_at = Column(DateTime, nullable=False, comment='Дата создания')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientDetails(BaseModel):
 | 
			
		||||
    __tablename__ = 'client_details'
 | 
			
		||||
 | 
			
		||||
    id = Column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
			
		||||
 | 
			
		||||
    client_id = Column(Integer, ForeignKey('clients.id'), unique=True, nullable=False, comment='ID клиента')
 | 
			
		||||
    client = relationship('Client', backref='details', uselist=False)
 | 
			
		||||
 | 
			
		||||
    address = Column(String)
 | 
			
		||||
    phone_number = Column(String)
 | 
			
		||||
    inn = Column(BigInteger)
 | 
			
		||||
    email = Column(String)
 | 
			
		||||
 | 
			
		||||
    last_modified_at = Column(DateTime, nullable=False)
 | 
			
		||||
 | 
			
		||||
    modified_by_user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
 | 
			
		||||
    modified_by_user = relationship('User')
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								models/product.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								models/product.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
from sqlalchemy import Column, Integer, String, ForeignKey
 | 
			
		||||
from sqlalchemy.orm import relationship
 | 
			
		||||
 | 
			
		||||
from models import BaseModel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Product(BaseModel):
 | 
			
		||||
    __tablename__ = 'products'
 | 
			
		||||
    id = Column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
			
		||||
    name = Column(String, nullable=False, index=True)
 | 
			
		||||
    article = Column(String, nullable=False, index=True)
 | 
			
		||||
 | 
			
		||||
    client_id = Column(Integer, ForeignKey('clients.id'), nullable=False, comment='ID сделки')
 | 
			
		||||
    client = relationship('Client', back_populates='status_history')
 | 
			
		||||
 | 
			
		||||
@@ -4,7 +4,10 @@ from fastapi import APIRouter, Depends
 | 
			
		||||
from sqlalchemy.ext.asyncio import AsyncSession
 | 
			
		||||
 | 
			
		||||
from backend.session import get_session
 | 
			
		||||
from schemas.client import ClientSearchRequest
 | 
			
		||||
from models import User
 | 
			
		||||
from schemas.client import ClientSearchRequest, ClientUpdateDetailsRequest, ClientUpdateDetailsResponse, \
 | 
			
		||||
    ClientGetAllResponse
 | 
			
		||||
from services.auth import get_current_user
 | 
			
		||||
from services.client import ClientService
 | 
			
		||||
 | 
			
		||||
client_router = APIRouter(
 | 
			
		||||
@@ -19,3 +22,25 @@ async def search_clients(
 | 
			
		||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
			
		||||
):
 | 
			
		||||
    return await ClientService(session).search_clients(ClientSearchRequest(name=name))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@client_router.post('/update-details')
 | 
			
		||||
async def update_client_details(
 | 
			
		||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
			
		||||
        user: Annotated[User, Depends(get_current_user)],
 | 
			
		||||
        request: ClientUpdateDetailsRequest,
 | 
			
		||||
):
 | 
			
		||||
    service = ClientService(session)
 | 
			
		||||
    client = await service.get_by_id(request.client_id)
 | 
			
		||||
    if not client:
 | 
			
		||||
        return ClientUpdateDetailsResponse(ok=False)
 | 
			
		||||
    await service.update_details(user, client, request.details)
 | 
			
		||||
    await session.commit()
 | 
			
		||||
    return ClientUpdateDetailsResponse(ok=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@client_router.get('/get-all', operation_id='get_all_clients', response_model=ClientGetAllResponse)
 | 
			
		||||
async def get_all_clients(
 | 
			
		||||
        session: Annotated[AsyncSession, Depends(get_session)],
 | 
			
		||||
):
 | 
			
		||||
    return await ClientService(session).get_all()
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,15 @@ class ClientSchema(CustomModel):
 | 
			
		||||
    name: str
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientDetailsSchema(CustomModel):
 | 
			
		||||
    address: str | None = None
 | 
			
		||||
    phone_number: str | None = None
 | 
			
		||||
    inn: int | None = None
 | 
			
		||||
    email: str | None = None
 | 
			
		||||
 | 
			
		||||
    # TODO add email validation
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientSearchRequest(CustomModel):
 | 
			
		||||
    name: str
 | 
			
		||||
 | 
			
		||||
@@ -19,3 +28,16 @@ class ClientCreateRequest(CustomModel):
 | 
			
		||||
 | 
			
		||||
class ClientSearchResponse(CustomModel):
 | 
			
		||||
    clients: List[ClientSchema]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientUpdateDetailsRequest(CustomModel):
 | 
			
		||||
    client_id: int
 | 
			
		||||
    details: ClientDetailsSchema
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientUpdateDetailsResponse(CustomModel):
 | 
			
		||||
    ok: bool
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientGetAllResponse(CustomModel):
 | 
			
		||||
    clients: List[ClientSchema]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
import datetime
 | 
			
		||||
from typing import Union
 | 
			
		||||
from typing import Union, Annotated
 | 
			
		||||
 | 
			
		||||
from sqlalchemy import select
 | 
			
		||||
from fastapi import Depends
 | 
			
		||||
from sqlalchemy import select, update
 | 
			
		||||
 | 
			
		||||
from models import Client
 | 
			
		||||
from models import Client, ClientDetails, User
 | 
			
		||||
from services.auth import get_current_user
 | 
			
		||||
from services.base import BaseService
 | 
			
		||||
from schemas.client import *
 | 
			
		||||
 | 
			
		||||
@@ -14,10 +16,51 @@ class ClientService(BaseService):
 | 
			
		||||
        client = await self.session.scalar(select(Client).where(Client.name == name))
 | 
			
		||||
        return client
 | 
			
		||||
 | 
			
		||||
    async def create_client_raw(self, name: str, address: str) -> Client:
 | 
			
		||||
        client = Client(name=name, address=address, created_at=datetime.datetime.now())
 | 
			
		||||
    async def get_by_id(self, client_id: int) -> Union[Client, None]:
 | 
			
		||||
        return await self.session.get(Client, client_id)
 | 
			
		||||
 | 
			
		||||
    async def get_details_by_client_id(self, client_id: int) -> Union[ClientDetails, None]:
 | 
			
		||||
        details = await self.session.scalar(select(ClientDetails).where(ClientDetails.client_id == client_id))
 | 
			
		||||
        return details
 | 
			
		||||
 | 
			
		||||
    async def get_all(self) -> ClientGetAllResponse:
 | 
			
		||||
        clients_query = await self.session.scalars(select(Client))
 | 
			
		||||
        clients = clients_query.all()
 | 
			
		||||
        result = []
 | 
			
		||||
        for client in clients:
 | 
			
		||||
            result.append(ClientSchema.model_validate(client))
 | 
			
		||||
        return ClientGetAllResponse(clients=result)
 | 
			
		||||
 | 
			
		||||
    async def create_details(self, user, client: Client, request: ClientDetailsSchema):
 | 
			
		||||
        dict_data = request.dict()
 | 
			
		||||
        dict_data['client_id'] = client.id
 | 
			
		||||
        dict_data['last_modified_at'] = datetime.datetime.now()
 | 
			
		||||
        dict_data['modified_by_user_id'] = user.id
 | 
			
		||||
        details = ClientDetails(**dict_data)
 | 
			
		||||
        self.session.add(details)
 | 
			
		||||
        await self.session.flush()
 | 
			
		||||
        return details
 | 
			
		||||
 | 
			
		||||
    async def update_details(self, user: User, client: Client, request: ClientDetailsSchema) -> ClientDetails:
 | 
			
		||||
        details = await self.get_details_by_client_id(client_id=client.id)
 | 
			
		||||
        if not details:
 | 
			
		||||
            details = await self.create_details(user, client, request)
 | 
			
		||||
        dict_data = request.dict()
 | 
			
		||||
        dict_data['last_modified_at'] = datetime.datetime.now()
 | 
			
		||||
        dict_data['modified_by_user_id'] = user.id
 | 
			
		||||
        await self.session.execute(update(ClientDetails).where(ClientDetails.id == details.id).values(**dict_data))
 | 
			
		||||
        await self.session.flush()
 | 
			
		||||
 | 
			
		||||
    async def create_client_raw(self,
 | 
			
		||||
                                user: User,
 | 
			
		||||
                                client_name: str,
 | 
			
		||||
                                details_schema: ClientDetailsSchema) -> Client:
 | 
			
		||||
        client = Client(name=client_name, created_at=datetime.datetime.now())
 | 
			
		||||
        self.session.add(client)
 | 
			
		||||
        await self.session.flush()
 | 
			
		||||
 | 
			
		||||
        await self.update_details(user, client, details_schema)
 | 
			
		||||
 | 
			
		||||
        return client
 | 
			
		||||
 | 
			
		||||
    async def search_clients(self, request: ClientSearchRequest) -> ClientSearchResponse:
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ from sqlalchemy import select
 | 
			
		||||
 | 
			
		||||
from models import User, Deal
 | 
			
		||||
from models.deal import *
 | 
			
		||||
from schemas.client import ClientDetailsSchema
 | 
			
		||||
from schemas.deal import *
 | 
			
		||||
from services.base import BaseService
 | 
			
		||||
from services.client import ClientService
 | 
			
		||||
@@ -49,7 +50,11 @@ class DealService(BaseService):
 | 
			
		||||
        client_service = ClientService(self.session)
 | 
			
		||||
        client = await client_service.get_by_name(request.client_name)
 | 
			
		||||
        if not client:
 | 
			
		||||
            client = await client_service.create_client_raw(request.client_name, request.client_address)
 | 
			
		||||
            client = await client_service.create_client_raw(
 | 
			
		||||
                user,
 | 
			
		||||
                request.client_name,
 | 
			
		||||
                ClientDetailsSchema(address=request.client_address))
 | 
			
		||||
        await client_service.update_details(user, client, ClientDetailsSchema(address=request.client_address))
 | 
			
		||||
        deal = Deal(
 | 
			
		||||
            name=request.name,
 | 
			
		||||
            created_at=datetime.datetime.now(),
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user