feat: shipping warehouse and cost
This commit is contained in:
3
main.py
3
main.py
@@ -31,7 +31,8 @@ routers_list = [
|
|||||||
routers.client_router,
|
routers.client_router,
|
||||||
routers.service_router,
|
routers.service_router,
|
||||||
routers.product_router,
|
routers.product_router,
|
||||||
routers.barcode_router
|
routers.barcode_router,
|
||||||
|
routers.shipping_warehouse_router
|
||||||
]
|
]
|
||||||
for router in routers_list:
|
for router in routers_list:
|
||||||
app.include_router(router)
|
app.include_router(router)
|
||||||
|
|||||||
@@ -7,4 +7,6 @@ from .service import *
|
|||||||
from .product import *
|
from .product import *
|
||||||
from .secondary import *
|
from .secondary import *
|
||||||
from .barcode import *
|
from .barcode import *
|
||||||
|
from .shipping_warehouse import *
|
||||||
|
|
||||||
configure_mappers()
|
configure_mappers()
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
from sqlalchemy.orm import declarative_base
|
from sqlalchemy.ext.asyncio import AsyncAttrs
|
||||||
|
from sqlalchemy.orm import declarative_base, DeclarativeBase
|
||||||
|
|
||||||
|
|
||||||
|
class BaseModel(DeclarativeBase, AsyncAttrs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
BaseModel = declarative_base()
|
|
||||||
metadata = BaseModel.metadata
|
metadata = BaseModel.metadata
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
from enum import IntEnum, unique
|
from enum import IntEnum, unique
|
||||||
|
|
||||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean
|
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean
|
||||||
from sqlalchemy.orm import relationship, backref
|
from sqlalchemy.orm import relationship, backref, Mapped, mapped_column
|
||||||
|
|
||||||
from models.base import BaseModel
|
from models.base import BaseModel
|
||||||
|
from .shipping_warehouse import ShippingWarehouse
|
||||||
|
|
||||||
|
|
||||||
@unique
|
@unique
|
||||||
@@ -32,6 +33,9 @@ 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='Завершена')
|
||||||
|
|
||||||
|
shipping_warehouse_id: Mapped[int] = mapped_column(ForeignKey('shipping_warehouses.id'), nullable=True)
|
||||||
|
shipping_warehouse: Mapped["ShippingWarehouse"] = relationship()
|
||||||
|
|
||||||
services = relationship('DealService', back_populates='deal', cascade="all, delete-orphan")
|
services = relationship('DealService', back_populates='deal', cascade="all, delete-orphan")
|
||||||
|
|
||||||
products = relationship('DealProduct', back_populates='deal', cascade="all, delete-orphan")
|
products = relationship('DealProduct', back_populates='deal', cascade="all, delete-orphan")
|
||||||
|
|||||||
@@ -13,12 +13,22 @@ class Service(BaseModel):
|
|||||||
category_id = Column(Integer, ForeignKey('service_categories.id'), nullable=False, comment='ID категории услуги')
|
category_id = Column(Integer, ForeignKey('service_categories.id'), nullable=False, comment='ID категории услуги')
|
||||||
category = relationship('ServiceCategory', lazy='joined')
|
category = relationship('ServiceCategory', lazy='joined')
|
||||||
|
|
||||||
price = Column(Double, nullable=False, comment='Стоимость услуги')
|
price = Column(
|
||||||
|
Double,
|
||||||
|
nullable=False,
|
||||||
|
comment='Стоимость услуги'
|
||||||
|
)
|
||||||
|
cost = Column(
|
||||||
|
Double,
|
||||||
|
nullable=False,
|
||||||
|
server_default='0',
|
||||||
|
comment='Себестоимость услуги'
|
||||||
|
)
|
||||||
|
|
||||||
service_type = Column(Integer,
|
service_type = Column(Integer,
|
||||||
server_default=f'{enums.service.ServiceType.DEAL_SERVICE}',
|
server_default=f'{enums.service.ServiceType.DEAL_SERVICE}',
|
||||||
nullable=False,
|
nullable=False,
|
||||||
comment='Тип услуги')
|
comment='Тип услуги')
|
||||||
|
|
||||||
price_ranges = relationship('ServicePriceRange',
|
price_ranges = relationship('ServicePriceRange',
|
||||||
back_populates='service',
|
back_populates='service',
|
||||||
lazy='selectin',
|
lazy='selectin',
|
||||||
|
|||||||
9
models/shipping_warehouse.py
Normal file
9
models/shipping_warehouse.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
|
||||||
|
from models import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class ShippingWarehouse(BaseModel):
|
||||||
|
__tablename__ = 'shipping_warehouses'
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
name: Mapped[str] = mapped_column(nullable=False)
|
||||||
@@ -4,3 +4,4 @@ from .client import client_router
|
|||||||
from .service import service_router
|
from .service import service_router
|
||||||
from .product import product_router
|
from .product import product_router
|
||||||
from .barcode import barcode_router
|
from .barcode import barcode_router
|
||||||
|
from .shipping_warehouse import shipping_warehouse_router
|
||||||
|
|||||||
28
routers/shipping_warehouse.py
Normal file
28
routers/shipping_warehouse.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
from typing import Annotated
|
||||||
|
|
||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
|
from backend.session import get_session
|
||||||
|
from schemas.shipping_warehouse import GetAllShippingWarehousesResponse
|
||||||
|
from services.auth import get_current_user
|
||||||
|
from services.shipping_warehouse import ShippingWarehouseService
|
||||||
|
|
||||||
|
shipping_warehouse_router = APIRouter(
|
||||||
|
prefix="/shipping-warehouse",
|
||||||
|
tags=["shipping-warehouse"],
|
||||||
|
dependencies=[Depends(get_current_user)]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@shipping_warehouse_router.get(
|
||||||
|
'/get-all',
|
||||||
|
response_model=GetAllShippingWarehousesResponse,
|
||||||
|
operation_id='get_all_shipping_warehouses'
|
||||||
|
)
|
||||||
|
async def get_all(
|
||||||
|
session: Annotated[AsyncSession, Depends(get_session)]
|
||||||
|
):
|
||||||
|
return await ShippingWarehouseService(session).get_all()
|
||||||
|
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ class CustomModelCamel(BaseModel):
|
|||||||
alias_generator = to_camel
|
alias_generator = to_camel
|
||||||
populate_by_name = True
|
populate_by_name = True
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_sql_model(cls, model, fields: dict):
|
def from_sql_model(cls, model, fields: dict):
|
||||||
model_dict = {c.name: getattr(model, c.name) for c in model.__table__.columns}
|
model_dict = {c.name: getattr(model, c.name) for c in model.__table__.columns}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import datetime
|
import datetime
|
||||||
from typing import List
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from pydantic import constr
|
||||||
|
|
||||||
from schemas.base import CustomModelCamel, OkMessageSchema
|
from schemas.base import CustomModelCamel, OkMessageSchema
|
||||||
from schemas.client import ClientSchema
|
from schemas.client import ClientSchema
|
||||||
from schemas.product import ProductSchema
|
from schemas.product import ProductSchema
|
||||||
from schemas.service import ServiceSchema
|
from schemas.service import ServiceSchema
|
||||||
|
from schemas.shipping_warehouse import ShippingWarehouseSchema
|
||||||
from schemas.user import UserSchema
|
from schemas.user import UserSchema
|
||||||
|
|
||||||
|
|
||||||
@@ -66,6 +69,7 @@ class DealSchema(CustomModelCamel):
|
|||||||
is_completed: bool
|
is_completed: bool
|
||||||
client: ClientSchema
|
client: ClientSchema
|
||||||
comment: str
|
comment: str
|
||||||
|
shipping_warehouse: Optional[ShippingWarehouseSchema] = None
|
||||||
|
|
||||||
|
|
||||||
class DealGeneralInfoSchema(CustomModelCamel):
|
class DealGeneralInfoSchema(CustomModelCamel):
|
||||||
@@ -88,10 +92,11 @@ class DealCreateRequest(CustomModelCamel):
|
|||||||
|
|
||||||
|
|
||||||
class DealQuickCreateRequest(CustomModelCamel):
|
class DealQuickCreateRequest(CustomModelCamel):
|
||||||
name: str
|
name: constr(strip_whitespace=True)
|
||||||
client_name: str
|
client_name: constr(strip_whitespace=True)
|
||||||
comment: str
|
comment: str
|
||||||
acceptance_date: datetime.datetime
|
acceptance_date: datetime.datetime
|
||||||
|
shipping_warehouse: constr(strip_whitespace=True)
|
||||||
|
|
||||||
|
|
||||||
class DealSummaryRequest(CustomModelCamel):
|
class DealSummaryRequest(CustomModelCamel):
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class ServiceSchema(CustomModelCamel):
|
|||||||
price: float
|
price: float
|
||||||
service_type: int
|
service_type: int
|
||||||
price_ranges: List[ServicePriceRangeSchema]
|
price_ranges: List[ServicePriceRangeSchema]
|
||||||
|
cost: Optional[int]
|
||||||
|
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|||||||
12
schemas/shipping_warehouse.py
Normal file
12
schemas/shipping_warehouse.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from schemas.base import CustomModelCamel
|
||||||
|
|
||||||
|
|
||||||
|
class ShippingWarehouseSchema(CustomModelCamel):
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
|
||||||
|
|
||||||
|
class GetAllShippingWarehousesResponse(CustomModelCamel):
|
||||||
|
shipping_warehouses: List[ShippingWarehouseSchema]
|
||||||
@@ -13,6 +13,7 @@ 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
|
||||||
|
from services.shipping_warehouse import ShippingWarehouseService
|
||||||
|
|
||||||
|
|
||||||
class DealService(BaseService):
|
class DealService(BaseService):
|
||||||
@@ -90,6 +91,10 @@ class DealService(BaseService):
|
|||||||
request.client_name,
|
request.client_name,
|
||||||
ClientDetailsSchema()
|
ClientDetailsSchema()
|
||||||
)
|
)
|
||||||
|
shipping_warehouse_service = ShippingWarehouseService(self.session)
|
||||||
|
shipping_warehouse = await shipping_warehouse_service.get_by_name(name=request.shipping_warehouse)
|
||||||
|
if not shipping_warehouse:
|
||||||
|
shipping_warehouse = await shipping_warehouse_service.create_by_name(name=request.shipping_warehouse)
|
||||||
|
|
||||||
rank = await self._get_rank_for_deal(DealStatus.CREATED)
|
rank = await self._get_rank_for_deal(DealStatus.CREATED)
|
||||||
deal = Deal(
|
deal = Deal(
|
||||||
@@ -97,7 +102,8 @@ class DealService(BaseService):
|
|||||||
created_at=datetime.datetime.now(),
|
created_at=datetime.datetime.now(),
|
||||||
client_id=client.id,
|
client_id=client.id,
|
||||||
current_status=DealStatus.CREATED,
|
current_status=DealStatus.CREATED,
|
||||||
lexorank=rank
|
lexorank=rank,
|
||||||
|
shipping_warehouse_id=shipping_warehouse.id
|
||||||
)
|
)
|
||||||
self.session.add(deal)
|
self.session.add(deal)
|
||||||
await self.session.flush()
|
await self.session.flush()
|
||||||
@@ -167,7 +173,8 @@ class DealService(BaseService):
|
|||||||
price_subquery, Deal.id == price_subquery.c.deal_id)
|
price_subquery, Deal.id == price_subquery.c.deal_id)
|
||||||
.where(
|
.where(
|
||||||
Deal.is_deleted == False,
|
Deal.is_deleted == False,
|
||||||
Deal.is_completed == False
|
Deal.is_completed == False,
|
||||||
|
Deal.current_status != DealStatus.COMPLETED
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
deals_query = await self.session.execute(q)
|
deals_query = await self.session.execute(q)
|
||||||
@@ -203,7 +210,9 @@ class DealService(BaseService):
|
|||||||
deal = await self.session.scalar(
|
deal = await self.session.scalar(
|
||||||
select(Deal)
|
select(Deal)
|
||||||
.options(
|
.options(
|
||||||
joinedload(Deal.client).joinedload(Client.details),
|
joinedload(Deal.shipping_warehouse),
|
||||||
|
joinedload(Deal.client)
|
||||||
|
.joinedload(Client.details),
|
||||||
selectinload(Deal.services)
|
selectinload(Deal.services)
|
||||||
.joinedload(models.secondary.DealService.service)
|
.joinedload(models.secondary.DealService.service)
|
||||||
.joinedload(Service.category),
|
.joinedload(Service.category),
|
||||||
@@ -220,6 +229,7 @@ class DealService(BaseService):
|
|||||||
.joinedload(DealStatusHistory.user),
|
.joinedload(DealStatusHistory.user),
|
||||||
selectinload(Deal.status_history)
|
selectinload(Deal.status_history)
|
||||||
.noload(DealStatusHistory.deal),
|
.noload(DealStatusHistory.deal),
|
||||||
|
|
||||||
)
|
)
|
||||||
.where(Deal.id == deal_id)
|
.where(Deal.id == deal_id)
|
||||||
)
|
)
|
||||||
|
|||||||
37
services/shipping_warehouse.py
Normal file
37
services/shipping_warehouse.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
from typing import Union
|
||||||
|
|
||||||
|
from sqlalchemy import select
|
||||||
|
|
||||||
|
import models
|
||||||
|
from schemas.shipping_warehouse import GetAllShippingWarehousesResponse, ShippingWarehouseSchema
|
||||||
|
from services.base import BaseService
|
||||||
|
|
||||||
|
|
||||||
|
class ShippingWarehouseService(BaseService):
|
||||||
|
async def get_all(self) -> GetAllShippingWarehousesResponse:
|
||||||
|
stmt = (
|
||||||
|
select(
|
||||||
|
models.ShippingWarehouse
|
||||||
|
)
|
||||||
|
.order_by(
|
||||||
|
models.ShippingWarehouse.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
shipping_warehouses = (await self.session.scalars(stmt)).all()
|
||||||
|
result = []
|
||||||
|
for shipping_warehouse in shipping_warehouses:
|
||||||
|
result.append(ShippingWarehouseSchema.model_validate(shipping_warehouse))
|
||||||
|
return GetAllShippingWarehousesResponse(shipping_warehouses=result)
|
||||||
|
|
||||||
|
async def get_by_name(self, name: str) -> Union[models.ShippingWarehouse, None]:
|
||||||
|
stmt = select(models.ShippingWarehouse).where(models.ShippingWarehouse.name == name)
|
||||||
|
shipping_warehouse = await self.session.scalar(stmt)
|
||||||
|
return shipping_warehouse
|
||||||
|
|
||||||
|
async def create_by_name(self, name: str) -> models.ShippingWarehouse:
|
||||||
|
shipping_warehouse = models.ShippingWarehouse(
|
||||||
|
name=name
|
||||||
|
)
|
||||||
|
self.session.add(shipping_warehouse)
|
||||||
|
await self.session.flush()
|
||||||
|
return shipping_warehouse
|
||||||
9
test.py
Normal file
9
test.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.set_int_max_str_digits(-0)
|
||||||
|
with open('Дизайн.jpg', 'rb') as rf:
|
||||||
|
data = int.from_bytes(rf.read())
|
||||||
|
|
||||||
|
with open('result', 'wb') as rf:
|
||||||
|
rf.write(data.to_bytes(length=len(str(data))))
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
from pprint import pprint
|
|
||||||
|
|
||||||
import lexorank
|
|
||||||
from lexorank import Bucket, middle
|
|
||||||
|
|
||||||
prev = middle(Bucket.BUCEKT_0)
|
|
||||||
ranks = [prev]
|
|
||||||
for _ in range(9):
|
|
||||||
ranks.append(prev.next())
|
|
||||||
prev = ranks[-1]
|
|
||||||
middle_ranks = lexorank.between(ranks[1], ranks[2])
|
|
||||||
pprint(ranks)
|
|
||||||
print('----------')
|
|
||||||
ranks.append(middle_ranks)
|
|
||||||
ranks = sorted(ranks)
|
|
||||||
pprint(ranks)
|
|
||||||
1241
test/test.json
1241
test/test.json
File diff suppressed because it is too large
Load Diff
28
test/test.py
28
test/test.py
@@ -1,28 +0,0 @@
|
|||||||
import asyncio
|
|
||||||
|
|
||||||
from sqlalchemy import select, func, union
|
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
|
||||||
from sqlalchemy.orm import joinedload
|
|
||||||
|
|
||||||
from backend.session import session_maker
|
|
||||||
from external.s3_uploader.uploader import S3Uploader
|
|
||||||
from models import Deal, DealProduct, Service
|
|
||||||
|
|
||||||
import models
|
|
||||||
import models.secondary
|
|
||||||
|
|
||||||
|
|
||||||
async def main(session: AsyncSession):
|
|
||||||
file_bytes = open('photo_2024-04-01 10.26.39.jpeg', 'rb').read()
|
|
||||||
uploader = S3Uploader('1cc46590-4532-4046-97aa-baf3e49f20ad-AUF')
|
|
||||||
response = await uploader.upload(file_bytes)
|
|
||||||
print(response)
|
|
||||||
|
|
||||||
|
|
||||||
async def preload():
|
|
||||||
async with session_maker() as session:
|
|
||||||
await main(session)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
asyncio.run(preload())
|
|
||||||
Reference in New Issue
Block a user