othr
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -3,3 +3,4 @@
 | 
				
			|||||||
.venv
 | 
					.venv
 | 
				
			||||||
.idea
 | 
					.idea
 | 
				
			||||||
__pycache__
 | 
					__pycache__
 | 
				
			||||||
 | 
					/venv
 | 
				
			||||||
							
								
								
									
										16
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								main.py
									
									
									
									
									
								
							@@ -1,8 +1,21 @@
 | 
				
			|||||||
from fastapi import FastAPI
 | 
					from fastapi import FastAPI
 | 
				
			||||||
 | 
					from fastapi.middleware.cors import CORSMiddleware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import routers
 | 
					import routers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					origins = [
 | 
				
			||||||
 | 
					    'http://localhost:5173'
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
app = FastAPI()
 | 
					app = FastAPI()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					app.add_middleware(
 | 
				
			||||||
 | 
					    CORSMiddleware,
 | 
				
			||||||
 | 
					    allow_origins=origins,
 | 
				
			||||||
 | 
					    allow_credentials=True,
 | 
				
			||||||
 | 
					    allow_methods=["*"],
 | 
				
			||||||
 | 
					    allow_headers=["*"],
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
routers_list = [
 | 
					routers_list = [
 | 
				
			||||||
    routers.auth_router,
 | 
					    routers.auth_router,
 | 
				
			||||||
    routers.deal_router,
 | 
					    routers.deal_router,
 | 
				
			||||||
@@ -10,6 +23,3 @@ routers_list = [
 | 
				
			|||||||
]
 | 
					]
 | 
				
			||||||
for router in routers_list:
 | 
					for router in routers_list:
 | 
				
			||||||
    app.include_router(router)
 | 
					    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
 | 
					from models import BaseModel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -7,5 +8,23 @@ class Client(BaseModel):
 | 
				
			|||||||
    __tablename__ = 'clients'
 | 
					    __tablename__ = 'clients'
 | 
				
			||||||
    id = Column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
					    id = Column(Integer, autoincrement=True, primary_key=True, index=True)
 | 
				
			||||||
    name = Column(String, nullable=False, unique=True, comment='Название клиента')
 | 
					    name = Column(String, nullable=False, unique=True, comment='Название клиента')
 | 
				
			||||||
    address = Column(String)
 | 
					 | 
				
			||||||
    created_at = Column(DateTime, nullable=False, comment='Дата создания')
 | 
					    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 sqlalchemy.ext.asyncio import AsyncSession
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from backend.session import get_session
 | 
					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
 | 
					from services.client import ClientService
 | 
				
			||||||
 | 
					
 | 
				
			||||||
client_router = APIRouter(
 | 
					client_router = APIRouter(
 | 
				
			||||||
@@ -19,3 +22,25 @@ async def search_clients(
 | 
				
			|||||||
        session: Annotated[AsyncSession, Depends(get_session)]
 | 
					        session: Annotated[AsyncSession, Depends(get_session)]
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    return await ClientService(session).search_clients(ClientSearchRequest(name=name))
 | 
					    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
 | 
					    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):
 | 
					class ClientSearchRequest(CustomModel):
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,3 +28,16 @@ class ClientCreateRequest(CustomModel):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ClientSearchResponse(CustomModel):
 | 
					class ClientSearchResponse(CustomModel):
 | 
				
			||||||
    clients: List[ClientSchema]
 | 
					    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
 | 
					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 services.base import BaseService
 | 
				
			||||||
from schemas.client import *
 | 
					from schemas.client import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -14,10 +16,51 @@ class ClientService(BaseService):
 | 
				
			|||||||
        client = await self.session.scalar(select(Client).where(Client.name == name))
 | 
					        client = await self.session.scalar(select(Client).where(Client.name == name))
 | 
				
			||||||
        return client
 | 
					        return client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def create_client_raw(self, name: str, address: str) -> Client:
 | 
					    async def get_by_id(self, client_id: int) -> Union[Client, None]:
 | 
				
			||||||
        client = Client(name=name, address=address, created_at=datetime.datetime.now())
 | 
					        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)
 | 
					        self.session.add(client)
 | 
				
			||||||
        await self.session.flush()
 | 
					        await self.session.flush()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await self.update_details(user, client, details_schema)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return client
 | 
					        return client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def search_clients(self, request: ClientSearchRequest) -> ClientSearchResponse:
 | 
					    async def search_clients(self, request: ClientSearchRequest) -> ClientSearchResponse:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ from sqlalchemy import select
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from models import User, Deal
 | 
					from models import User, Deal
 | 
				
			||||||
from models.deal import *
 | 
					from models.deal import *
 | 
				
			||||||
 | 
					from schemas.client import ClientDetailsSchema
 | 
				
			||||||
from schemas.deal import *
 | 
					from schemas.deal import *
 | 
				
			||||||
from services.base import BaseService
 | 
					from services.base import BaseService
 | 
				
			||||||
from services.client import ClientService
 | 
					from services.client import ClientService
 | 
				
			||||||
@@ -49,7 +50,11 @@ class DealService(BaseService):
 | 
				
			|||||||
        client_service = ClientService(self.session)
 | 
					        client_service = ClientService(self.session)
 | 
				
			||||||
        client = await client_service.get_by_name(request.client_name)
 | 
					        client = await client_service.get_by_name(request.client_name)
 | 
				
			||||||
        if not client:
 | 
					        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(
 | 
					        deal = Deal(
 | 
				
			||||||
            name=request.name,
 | 
					            name=request.name,
 | 
				
			||||||
            created_at=datetime.datetime.now(),
 | 
					            created_at=datetime.datetime.now(),
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user