zalupka
This commit is contained in:
@@ -29,6 +29,10 @@ target_metadata = BaseModel.metadata
|
|||||||
# can be acquired:
|
# can be acquired:
|
||||||
# my_important_option = config.get_main_option("my_important_option")
|
# my_important_option = config.get_main_option("my_important_option")
|
||||||
# ... etc.
|
# ... etc.
|
||||||
|
def include_object(object, name, type_, reflected, compare_to):
|
||||||
|
print(f"{type_}: {name}")
|
||||||
|
return True # Temporarily return True to debug all objects
|
||||||
|
|
||||||
|
|
||||||
def get_url():
|
def get_url():
|
||||||
url = config.get_main_option("sqlalchemy.url").format(
|
url = config.get_main_option("sqlalchemy.url").format(
|
||||||
@@ -65,7 +69,11 @@ def run_migrations_offline() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def do_run_migrations(connection: Connection) -> None:
|
def do_run_migrations(connection: Connection) -> None:
|
||||||
context.configure(connection=connection, target_metadata=target_metadata)
|
context.configure(connection=connection,
|
||||||
|
target_metadata=target_metadata,
|
||||||
|
include_schemas=True,
|
||||||
|
include_object=include_object,
|
||||||
|
)
|
||||||
with context.begin_transaction():
|
with context.begin_transaction():
|
||||||
context.run_migrations()
|
context.run_migrations()
|
||||||
|
|
||||||
|
|||||||
@@ -6,5 +6,4 @@ from .client import *
|
|||||||
from .service import *
|
from .service import *
|
||||||
from .product import *
|
from .product import *
|
||||||
from .secondary import *
|
from .secondary import *
|
||||||
|
|
||||||
configure_mappers()
|
configure_mappers()
|
||||||
|
|||||||
@@ -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, Sequence
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
from models.base import BaseModel
|
from models.base import BaseModel, metadata
|
||||||
|
from models.utils import add_sequence_to_model
|
||||||
|
|
||||||
|
|
||||||
@unique
|
@unique
|
||||||
@@ -35,6 +36,10 @@ class Deal(BaseModel):
|
|||||||
services = relationship('DealService', back_populates='deal')
|
services = relationship('DealService', back_populates='deal')
|
||||||
products = relationship('DealProduct', back_populates='deal')
|
products = relationship('DealProduct', back_populates='deal')
|
||||||
|
|
||||||
|
# TODO remake with sequence
|
||||||
|
rank = Column(String, nullable=False, comment='Lexorank')
|
||||||
|
|
||||||
|
comment = Column(String, nullable=False, server_default='', comment='Коментарий к заданию')
|
||||||
|
|
||||||
class DealStatusHistory(BaseModel):
|
class DealStatusHistory(BaseModel):
|
||||||
__tablename__ = 'deals_status_history'
|
__tablename__ = 'deals_status_history'
|
||||||
@@ -52,3 +57,4 @@ class DealStatusHistory(BaseModel):
|
|||||||
|
|
||||||
next_status_deadline = Column(DateTime,
|
next_status_deadline = Column(DateTime,
|
||||||
comment='Дедлайн до которого сделку нужно перевести на следующий этап')
|
comment='Дедлайн до которого сделку нужно перевести на следующий этап')
|
||||||
|
comment = Column(String, nullable=False, comment='Коментарий', server_default='')
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from sqlalchemy import Column, Integer, String, ForeignKey
|
from sqlalchemy import Column, Integer, String, ForeignKey, Sequence
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
from models import BaseModel
|
from models import BaseModel, metadata
|
||||||
|
|
||||||
|
deal_rank_seq = Sequence('test_ochko', start=1, increment=1, metadata=metadata)
|
||||||
|
|
||||||
|
sequence = Sequence('my_sequence_name')
|
||||||
|
|
||||||
|
|
||||||
class Product(BaseModel):
|
class Product(BaseModel):
|
||||||
@@ -13,6 +17,7 @@ class Product(BaseModel):
|
|||||||
client_id = Column(Integer, ForeignKey('clients.id'), nullable=False, comment='ID сделки')
|
client_id = Column(Integer, ForeignKey('clients.id'), nullable=False, comment='ID сделки')
|
||||||
client = relationship('Client', back_populates='products')
|
client = relationship('Client', back_populates='products')
|
||||||
barcodes = relationship('ProductBarcode', back_populates='product', cascade="all, delete-orphan")
|
barcodes = relationship('ProductBarcode', back_populates='product', cascade="all, delete-orphan")
|
||||||
|
my_column = Column(Integer, sequence)
|
||||||
|
|
||||||
|
|
||||||
class ProductBarcode(BaseModel):
|
class ProductBarcode(BaseModel):
|
||||||
|
|||||||
4
models/sequences.py
Normal file
4
models/sequences.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from sqlalchemy import Sequence
|
||||||
|
|
||||||
|
from models import BaseModel
|
||||||
|
|
||||||
4
models/utils.py
Normal file
4
models/utils.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
def add_sequence_to_model(sequence, metadata):
|
||||||
|
metadata.info.setdefault("sequences", set()).add(
|
||||||
|
(sequence.schema, sequence.name)
|
||||||
|
)
|
||||||
@@ -17,4 +17,5 @@ alembic
|
|||||||
python-dotenv
|
python-dotenv
|
||||||
aiohttp
|
aiohttp
|
||||||
aiohttp[speedups]
|
aiohttp[speedups]
|
||||||
openpyxl
|
openpyxl
|
||||||
|
lexorank-py
|
||||||
@@ -51,6 +51,18 @@ async def get_summary(
|
|||||||
):
|
):
|
||||||
return await DealService(session).get_summary()
|
return await DealService(session).get_summary()
|
||||||
|
|
||||||
|
@deal_router.post(
|
||||||
|
'/summaries/reorder',
|
||||||
|
response_model=DealSummaryReorderResponse,
|
||||||
|
operation_id='reorderDealSummaries'
|
||||||
|
)
|
||||||
|
async def reorder(
|
||||||
|
session: Annotated[AsyncSession, Depends(get_session)],
|
||||||
|
request: DealSummaryReorderRequest,
|
||||||
|
user: Annotated[User, Depends(get_current_user)]
|
||||||
|
):
|
||||||
|
return await DealService(session).reorder(request, user)
|
||||||
|
|
||||||
|
|
||||||
@deal_router.get(
|
@deal_router.get(
|
||||||
'/get-all',
|
'/get-all',
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class DealSummary(CustomModelCamel):
|
|||||||
changed_at: datetime.datetime
|
changed_at: datetime.datetime
|
||||||
status: int
|
status: int
|
||||||
total_price: int
|
total_price: int
|
||||||
|
rank: int
|
||||||
|
|
||||||
|
|
||||||
class DealServiceSchema(CustomModelCamel):
|
class DealServiceSchema(CustomModelCamel):
|
||||||
@@ -55,12 +56,14 @@ class DealSchema(CustomModelCamel):
|
|||||||
is_deleted: bool
|
is_deleted: bool
|
||||||
is_completed: bool
|
is_completed: bool
|
||||||
client: ClientSchema
|
client: ClientSchema
|
||||||
|
comment: str
|
||||||
|
|
||||||
|
|
||||||
class DealGeneralInfoSchema(CustomModelCamel):
|
class DealGeneralInfoSchema(CustomModelCamel):
|
||||||
name: str
|
name: str
|
||||||
is_deleted: bool
|
is_deleted: bool
|
||||||
is_completed: bool
|
is_completed: bool
|
||||||
|
comment: str
|
||||||
|
|
||||||
|
|
||||||
# endregion Entities
|
# endregion Entities
|
||||||
@@ -141,6 +144,14 @@ class DealUpdateGeneralInfoRequest(CustomModelCamel):
|
|||||||
data: DealGeneralInfoSchema
|
data: DealGeneralInfoSchema
|
||||||
|
|
||||||
|
|
||||||
|
class DealSummaryReorderRequest(CustomModelCamel):
|
||||||
|
deal_id: int
|
||||||
|
new_status: int
|
||||||
|
rank: int
|
||||||
|
next_status_deadline: datetime.datetime
|
||||||
|
comment: str
|
||||||
|
|
||||||
|
|
||||||
# endregion Requests
|
# endregion Requests
|
||||||
|
|
||||||
# region Responses
|
# region Responses
|
||||||
@@ -204,4 +215,8 @@ class DealAddProductResponse(OkMessageSchema):
|
|||||||
|
|
||||||
class DealUpdateGeneralInfoResponse(OkMessageSchema):
|
class DealUpdateGeneralInfoResponse(OkMessageSchema):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DealSummaryReorderResponse(OkMessageSchema):
|
||||||
|
pass
|
||||||
# endregion Responses
|
# endregion Responses
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import lexorank
|
||||||
|
|
||||||
import models.secondary
|
import models.secondary
|
||||||
from typing import Union
|
from typing import Union
|
||||||
import models.deal
|
import models.deal
|
||||||
@@ -19,6 +21,14 @@ class DealService(BaseService):
|
|||||||
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)
|
||||||
|
|
||||||
|
async def _get_rank(self):
|
||||||
|
query = await self.session.execute(select(Deal.rank).order_by(Deal.rank.desc()))
|
||||||
|
result = query.scalar_one_or_none()
|
||||||
|
if not result:
|
||||||
|
return str(lexorank.Bucket.BUCEKT_0.next())
|
||||||
|
rank = lexorank.parse(result)
|
||||||
|
return str(rank.next())
|
||||||
|
|
||||||
async def change_status(self, deal: Deal,
|
async def change_status(self, deal: Deal,
|
||||||
status: DealStatus,
|
status: DealStatus,
|
||||||
user: User,
|
user: User,
|
||||||
@@ -37,10 +47,12 @@ class DealService(BaseService):
|
|||||||
return status_change
|
return status_change
|
||||||
|
|
||||||
async def create(self, request: DealCreateRequest, user: User) -> DealCreateResponse:
|
async def create(self, request: DealCreateRequest, user: User) -> DealCreateResponse:
|
||||||
|
rank = await self._get_rank()
|
||||||
deal = Deal(
|
deal = Deal(
|
||||||
name=request.name,
|
name=request.name,
|
||||||
created_at=datetime.datetime.now(),
|
created_at=datetime.datetime.now(),
|
||||||
current_status=DealStatus.CREATED
|
current_status=DealStatus.CREATED,
|
||||||
|
rank=rank
|
||||||
)
|
)
|
||||||
self.session.add(deal)
|
self.session.add(deal)
|
||||||
await self.session.flush()
|
await self.session.flush()
|
||||||
@@ -60,11 +72,13 @@ class DealService(BaseService):
|
|||||||
request.client_name,
|
request.client_name,
|
||||||
ClientDetailsSchema(address=request.client_address))
|
ClientDetailsSchema(address=request.client_address))
|
||||||
await client_service.update_details(user, client, ClientDetailsSchema(address=request.client_address))
|
await client_service.update_details(user, client, ClientDetailsSchema(address=request.client_address))
|
||||||
|
rank = await self._get_rank()
|
||||||
deal = Deal(
|
deal = Deal(
|
||||||
name=request.name,
|
name=request.name,
|
||||||
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,
|
||||||
|
rank=rank
|
||||||
)
|
)
|
||||||
self.session.add(deal)
|
self.session.add(deal)
|
||||||
await self.session.flush()
|
await self.session.flush()
|
||||||
@@ -91,15 +105,25 @@ class DealService(BaseService):
|
|||||||
.group_by(models.secondary.DealService.deal_id)
|
.group_by(models.secondary.DealService.deal_id)
|
||||||
.subquery()
|
.subquery()
|
||||||
)
|
)
|
||||||
q = (select(
|
q = (
|
||||||
Deal,
|
select(
|
||||||
func.coalesce(service_subquery.c.total_price, 0)
|
Deal,
|
||||||
|
func.coalesce(service_subquery.c.total_price, 0)
|
||||||
|
)
|
||||||
|
.order_by(
|
||||||
|
Deal.rank.desc()
|
||||||
|
)
|
||||||
|
.options(
|
||||||
|
selectinload(Deal.status_history),
|
||||||
|
joinedload(Deal.client)
|
||||||
|
)
|
||||||
|
.outerjoin(
|
||||||
|
service_subquery, Deal.id == service_subquery.c.deal_id)
|
||||||
|
.where(
|
||||||
|
Deal.is_deleted == False,
|
||||||
|
Deal.is_completed == False
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.options(selectinload(Deal.status_history),
|
|
||||||
joinedload(Deal.client))
|
|
||||||
.outerjoin(service_subquery, Deal.id == service_subquery.c.deal_id)
|
|
||||||
.where(Deal.is_deleted == False,
|
|
||||||
Deal.is_completed == False))
|
|
||||||
deals_query = await self.session.execute(q)
|
deals_query = await self.session.execute(q)
|
||||||
summaries = []
|
summaries = []
|
||||||
for deal, total_price in deals_query.all():
|
for deal, total_price in deals_query.all():
|
||||||
@@ -112,7 +136,8 @@ class DealService(BaseService):
|
|||||||
name=deal.name,
|
name=deal.name,
|
||||||
changed_at=last_status.changed_at,
|
changed_at=last_status.changed_at,
|
||||||
status=last_status.to_status,
|
status=last_status.to_status,
|
||||||
total_price=total_price
|
total_price=total_price,
|
||||||
|
rank=deal.rank
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return DealSummaryResponse(summaries=summaries)
|
return DealSummaryResponse(summaries=summaries)
|
||||||
@@ -156,6 +181,7 @@ class DealService(BaseService):
|
|||||||
if not deal:
|
if not deal:
|
||||||
raise HTTPException(status_code=404, detail="Сделка не найдена")
|
raise HTTPException(status_code=404, detail="Сделка не найдена")
|
||||||
deal.name = request.data.name
|
deal.name = request.data.name
|
||||||
|
deal.comment = request.data.comment
|
||||||
deal.is_deleted = request.data.is_deleted
|
deal.is_deleted = request.data.is_deleted
|
||||||
deal.is_completed = request.data.is_completed
|
deal.is_completed = request.data.is_completed
|
||||||
await self.session.commit()
|
await self.session.commit()
|
||||||
@@ -164,6 +190,9 @@ class DealService(BaseService):
|
|||||||
await self.session.rollback()
|
await self.session.rollback()
|
||||||
return DealUpdateGeneralInfoResponse(ok=False, message=str(e))
|
return DealUpdateGeneralInfoResponse(ok=False, message=str(e))
|
||||||
|
|
||||||
|
async def reorder(self, request: DealSummaryReorderRequest, user: User) -> DealSummaryReorderResponse:
|
||||||
|
pass
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Deal services
|
# region Deal services
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
import string
|
import string
|
||||||
|
|
||||||
|
import lexorank
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
pass
|
prev = lexorank.middle(lexorank.Bucket.BUCEKT_0)
|
||||||
|
ranks = [prev]
|
||||||
|
for _ in range(1_000_000):
|
||||||
|
ranks.append(prev.next())
|
||||||
|
prev = ranks[-1]
|
||||||
|
print('generated')
|
||||||
|
sorted_ranks = list(sorted(ranks))
|
||||||
|
for idx in range(len(sorted_ranks)):
|
||||||
|
print(sorted_ranks[idx], ' ', ranks[idx])
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|||||||
21
test/test.py
21
test/test.py
@@ -3,29 +3,12 @@ import asyncio
|
|||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from backend.session import session_maker
|
from backend.session import session_maker
|
||||||
|
from migrations.env import run_async_migrations
|
||||||
from models import Product, ProductBarcode
|
from models import Product, ProductBarcode
|
||||||
|
|
||||||
|
|
||||||
async def main(session: AsyncSession):
|
async def main(session: AsyncSession):
|
||||||
client_ids = [8, 18]
|
await run_async_migrations()
|
||||||
for client_id in client_ids:
|
|
||||||
for i in range(1, 500 + 1):
|
|
||||||
product = Product(
|
|
||||||
name=f"Товар №{i}",
|
|
||||||
article=f"Ариткул товара №{i}",
|
|
||||||
client_id=client_id
|
|
||||||
)
|
|
||||||
session.add(product)
|
|
||||||
await session.flush()
|
|
||||||
for j in range(1, 5 + 1):
|
|
||||||
barcode = ProductBarcode(
|
|
||||||
barcode=f"Штрихкод №{j} для товара №{i}",
|
|
||||||
product_id=product.id
|
|
||||||
)
|
|
||||||
session.add(barcode)
|
|
||||||
await session.flush()
|
|
||||||
await session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
async def preload():
|
async def preload():
|
||||||
async with session_maker() as session:
|
async with session_maker() as session:
|
||||||
|
|||||||
Reference in New Issue
Block a user