From 61d27d2389b0b99611c58f30c9455912fa4b51ef Mon Sep 17 00:00:00 2001 From: fakz9 Date: Thu, 9 May 2024 01:32:37 +0300 Subject: [PATCH] othr --- barcodes/attributes/__init__.py | 42 ++++++------- .../attributes/article_attribute_writer.py | 14 ++--- barcodes/attributes/name_attribute_writer.py | 14 ++--- barcodes/barcode.py | 30 ++++----- barcodes/generator.py | 12 ++-- models/barcode.py | 29 +++++++-- models/client.py | 2 +- models/deal.py | 5 +- models/product.py | 6 +- models/secondary.py | 38 +++++++----- routers/barcode.py | 15 ++++- schemas/barcode.py | 8 +++ schemas/client.py | 2 + services/barcode.py | 61 +++++++++++-------- services/client.py | 12 +++- services/deal.py | 4 +- 16 files changed, 179 insertions(+), 115 deletions(-) diff --git a/barcodes/attributes/__init__.py b/barcodes/attributes/__init__.py index 3d4106f..457e2b7 100644 --- a/barcodes/attributes/__init__.py +++ b/barcodes/attributes/__init__.py @@ -1,21 +1,21 @@ -from abc import abstractmethod, ABC - -from .article_attribute_writer import ArticleAttributeWriter -from .name_attribute_writer import NameAttributeWriter -from ..barcode import Barcode - - -class BaseAttributeWriter(ABC): - @abstractmethod - def write(self, barcode: Barcode): - pass - - -class AttributeWriterFactory: - @staticmethod - def get_writer(key: str): - match key: - case 'name': - return NameAttributeWriter() - case 'article': - return ArticleAttributeWriter() +# from abc import abstractmethod, ABC +# +# from .article_attribute_writer import ArticleAttributeWriter +# from .name_attribute_writer import NameAttributeWriter +# from ..barcode import Barcode +# +# +# class BaseAttributeWriter(ABC): +# @abstractmethod +# def write(self, barcode: Barcode): +# pass +# +# +# class AttributeWriterFactory: +# @staticmethod +# def get_writer(key: str): +# match key: +# case 'name': +# return NameAttributeWriter() +# case 'article': +# return ArticleAttributeWriter() diff --git a/barcodes/attributes/article_attribute_writer.py b/barcodes/attributes/article_attribute_writer.py index 0806a17..98c620f 100644 --- a/barcodes/attributes/article_attribute_writer.py +++ b/barcodes/attributes/article_attribute_writer.py @@ -1,7 +1,7 @@ -from barcodes.attributes import BaseAttributeWriter -from barcodes.barcode import Barcode - - -class ArticleAttributeWriter(BaseAttributeWriter): - def write(self, barcode: Barcode): - pass +# from barcodes.attributes import BaseAttributeWriter +# from barcodes.barcode import Barcode +# +# +# class ArticleAttributeWriter(BaseAttributeWriter): +# def write(self, barcode: Barcode): +# pass diff --git a/barcodes/attributes/name_attribute_writer.py b/barcodes/attributes/name_attribute_writer.py index 85ee6a7..d57cd38 100644 --- a/barcodes/attributes/name_attribute_writer.py +++ b/barcodes/attributes/name_attribute_writer.py @@ -1,7 +1,7 @@ -from barcodes.attributes import BaseAttributeWriter -from barcodes.barcode import Barcode - - -class NameAttributeWriter(BaseAttributeWriter): - def write(self, barcode: Barcode): - pass \ No newline at end of file +# from barcodes.attributes import BaseAttributeWriter +# from barcodes.barcode import Barcode +# +# +# class NameAttributeWriter(BaseAttributeWriter): +# def write(self, barcode: Barcode): +# pass \ No newline at end of file diff --git a/barcodes/barcode.py b/barcodes/barcode.py index 5e8a64d..941dccc 100644 --- a/barcodes/barcode.py +++ b/barcodes/barcode.py @@ -1,15 +1,15 @@ -from .attributes import AttributeWriterFactory -from models import ProductBarcode, BarcodeTemplate, BarcodeTemplateAttribute - - -class Barcode: - def __init__(self, session, barcode: ProductBarcode): - self.session = session - self.barcode = barcode - - def render(self, template: BarcodeTemplate): - for attribute in template.attributes: - attribute: BarcodeTemplateAttribute - writer = AttributeWriterFactory.get_writer(attribute.key) - writer.write(self) - +# from .attributes import AttributeWriterFactory +# from models import ProductBarcode, BarcodeTemplate, BarcodeTemplateAttribute +# +# +# class Barcode: +# def __init__(self, session, barcode: ProductBarcode): +# self.session = session +# self.barcode = barcode +# +# def render(self, template: BarcodeTemplate): +# for attribute in template.attributes: +# attribute: BarcodeTemplateAttribute +# writer = AttributeWriterFactory.get_writer(attribute.key) +# writer.write(self) +# diff --git a/barcodes/generator.py b/barcodes/generator.py index 6fbfad1..8b07233 100644 --- a/barcodes/generator.py +++ b/barcodes/generator.py @@ -1,6 +1,6 @@ -from models import ProductBarcode - - -class BarcodeGenerator: - def __init__(self, barcode: ProductBarcode): - self.barcode = barcode +# from models import ProductBarcode +# +# +# class BarcodeGenerator: +# def __init__(self, barcode: ProductBarcode): +# self.barcode = barcode diff --git a/models/barcode.py b/models/barcode.py index a664a02..7f4be24 100644 --- a/models/barcode.py +++ b/models/barcode.py @@ -1,7 +1,7 @@ -from sqlalchemy import Integer, Column, String, Boolean +from sqlalchemy import Integer, Column, String, Boolean, ForeignKey from sqlalchemy.orm import relationship -from models import BaseModel +from models import BaseModel, barcode_template_attribute_link class BarcodeTemplateAttribute(BaseModel): @@ -11,14 +11,31 @@ class BarcodeTemplateAttribute(BaseModel): name = Column(String, nullable=False, index=True, comment='Метка атрибута') +class BarcodeTemplateAdditionalField(BaseModel): + __tablename__ = 'barcode_template_additional_fields' + id = Column(Integer, autoincrement=True, primary_key=True, index=True) + name = Column(String, nullable=False) + value = Column(String, nullable=False) + + barcode_template_id = Column(Integer, ForeignKey('barcode_templates.id'), nullable=False) + barcode_template = relationship('BarcodeTemplate', back_populates='additional_fields') + + class BarcodeTemplate(BaseModel): __tablename__ = 'barcode_templates' id = Column(Integer, autoincrement=True, primary_key=True, index=True) name = Column(String, nullable=False, index=True, comment='Название шаблона') - attributes = relationship('BarcodeTemplateAttributeLink', - back_populates='barcode_template', - cascade="all, delete-orphan", - lazy='joined') + attributes = relationship('BarcodeTemplateAttribute', + secondary=barcode_template_attribute_link, + # back_populates='barcode_template', + # cascade="all, delete-orphan", + lazy='selectin' + ) + additional_fields = relationship('BarcodeTemplateAdditionalField', + back_populates='barcode_template', + lazy='selectin' + ) + is_default = Column(Boolean, nullable=False, default=False, comment='По умолчанию') # size diff --git a/models/client.py b/models/client.py index 8be03ff..cca67c5 100644 --- a/models/client.py +++ b/models/client.py @@ -14,7 +14,7 @@ class Client(BaseModel): details = relationship('ClientDetails', uselist=False, back_populates='client', cascade='all, delete') barcode_template_id = Column(Integer, ForeignKey('barcode_templates.id'), nullable=True) - barcode_template = relationship('BarcodeTemplate') + barcode_template = relationship('BarcodeTemplate', lazy='selectin') class ClientDetails(BaseModel): diff --git a/models/deal.py b/models/deal.py index 442f6f2..221e592 100644 --- a/models/deal.py +++ b/models/deal.py @@ -1,10 +1,9 @@ from enum import IntEnum, unique -from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean, Sequence +from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean from sqlalchemy.orm import relationship, backref -from models.base import BaseModel, metadata -from models.utils import add_sequence_to_model +from models.base import BaseModel @unique diff --git a/models/product.py b/models/product.py index 52f9163..e6fc3fd 100644 --- a/models/product.py +++ b/models/product.py @@ -1,11 +1,7 @@ from sqlalchemy import Column, Integer, String, ForeignKey, Sequence from sqlalchemy.orm import relationship -from models import BaseModel, metadata - -deal_rank_seq = Sequence('test_ochko', start=1, increment=1, metadata=metadata) - -sequence = Sequence('my_sequence_name') +from models import BaseModel class Product(BaseModel): diff --git a/models/secondary.py b/models/secondary.py index a971056..6e77a01 100644 --- a/models/secondary.py +++ b/models/secondary.py @@ -33,18 +33,26 @@ class DealProduct(BaseModel): quantity = Column(Integer, nullable=False, comment='Кол-во продукта') -class BarcodeTemplateAttributeLink(BaseModel): - __tablename__ = 'barcode_template_attributes_links' - barcode_template_id = Column(Integer, - ForeignKey('barcode_templates.id'), - nullable=False, - comment='ID Шаблона ШК', - primary_key=True) - barcode_template = relationship('BarcodeTemplate', back_populates='attributes') - - attribute_id = Column(Integer, - ForeignKey('barcode_template_attributes.id'), - nullable=False, - comment='ID Атрибута', - primary_key=True) - attribute = relationship('BarcodeTemplateAttribute') +# class BarcodeTemplateAttributeLink(BaseModel): +# __tablename__ = 'barcode_template_attributes_links' +# barcode_template_id = Column(Integer, +# ForeignKey('barcode_templates.id'), +# nullable=False, +# comment='ID Шаблона ШК', +# primary_key=True) +# barcode_template = relationship('BarcodeTemplate', +# # back_populates='attributes' +# ) +# +# attribute_id = Column(Integer, +# ForeignKey('barcode_template_attributes.id'), +# nullable=False, +# comment='ID Атрибута', +# primary_key=True) +# attribute = relationship('BarcodeTemplateAttribute') +barcode_template_attribute_link = Table( + 'barcode_template_attribute_links', + BaseModel.metadata, + Column('barcode_template_id', ForeignKey('barcode_templates.id')), + Column('attribute_id', ForeignKey('barcode_template_attributes.id')) +) diff --git a/routers/barcode.py b/routers/barcode.py index 331f047..ba20101 100644 --- a/routers/barcode.py +++ b/routers/barcode.py @@ -10,7 +10,8 @@ from schemas.barcode import (GetBarcodeTemplateByIdResponse, BarcodeTemplateCreateRequest, GetAllBarcodeTemplateAttributesResponse, CreateBarcodeTemplateAttributeResponse, CreateBarcodeTemplateAttributeRequest, BarcodeTemplateUpdateResponse, BarcodeTemplateUpdateRequest, - GetAllBarcodeTemplatesResponse) + GetAllBarcodeTemplatesResponse, BarcodeTemplateDeleteRequest, + BarcodeTemplateDeleteResponse) from services.barcode import BarcodeService barcode_router = APIRouter( @@ -67,6 +68,18 @@ async def update_barcode_template( return await BarcodeService(session).update_barcode_template(request) +@barcode_router.post( + '/template/delete', + response_model=BarcodeTemplateDeleteResponse, + operation_id='delete_barcode_template' +) +async def delete_barcode_template( + request: BarcodeTemplateDeleteRequest, + session: Annotated[AsyncSession, Depends(get_session)] +): + return await BarcodeService(session).delete_template(request) + + # endregion # region Template attributes diff --git a/schemas/barcode.py b/schemas/barcode.py index b4f96b3..b171ffa 100644 --- a/schemas/barcode.py +++ b/schemas/barcode.py @@ -40,6 +40,10 @@ class CreateBarcodeTemplateAttributeRequest(CustomModelCamel): label: str +class BarcodeTemplateDeleteRequest(CustomModelCamel): + id: int + + # endregion # region Responses @@ -66,4 +70,8 @@ class GetAllBarcodeTemplatesResponse(CustomModelCamel): class GetAllBarcodeTemplateAttributesResponse(CustomModelCamel): attributes: list[BarcodeTemplateAttributeSchema] + + +class BarcodeTemplateDeleteResponse(OkMessageSchema): + pass # endregion diff --git a/schemas/client.py b/schemas/client.py index 5a13119..fffebe4 100644 --- a/schemas/client.py +++ b/schemas/client.py @@ -2,6 +2,7 @@ from typing import List from pydantic import validator, field_validator +from schemas.barcode import BarcodeTemplateSchema from schemas.base import CustomModelCamel, OkMessageSchema @@ -20,6 +21,7 @@ class ClientDetailsSchema(CustomModelCamel): class ClientSchema(CustomModelCamel): id: int name: str + barcode_template: BarcodeTemplateSchema | None = None details: ClientDetailsSchema | None = None diff --git a/services/barcode.py b/services/barcode.py index f0cbeaa..61e20b4 100644 --- a/services/barcode.py +++ b/services/barcode.py @@ -1,13 +1,15 @@ -from sqlalchemy import select, update +from sqlalchemy import select, update, insert +from sqlalchemy.orm import selectinload -from models import BarcodeTemplate, BarcodeTemplateAttribute, BarcodeTemplateAttributeLink +from models import BarcodeTemplate, BarcodeTemplateAttribute, barcode_template_attribute_link from schemas.barcode import (GetBarcodeTemplateByIdRequest, GetBarcodeTemplateByIdResponse, BarcodeTemplateCreateResponse, BarcodeTemplateCreateRequest, CreateBarcodeTemplateAttributeRequest, BarcodeTemplateUpdateResponse, BarcodeTemplateUpdateRequest, BarcodeTemplateAttributeSchema, GetAllBarcodeTemplateAttributesResponse, - GetAllBarcodeTemplatesResponse) + GetAllBarcodeTemplatesResponse, BarcodeTemplateDeleteRequest, + BarcodeTemplateDeleteResponse) from services.base import BaseService @@ -23,7 +25,12 @@ class BarcodeService(BaseService): return query.scalar() async def get_all_barcode_templates(self) -> GetAllBarcodeTemplatesResponse: - stmt = select(BarcodeTemplate).order_by(BarcodeTemplate.id) + stmt = ( + select(BarcodeTemplate) + .options( + selectinload(BarcodeTemplate.attributes) + ) + .order_by(BarcodeTemplate.id)) query = await self.session.execute(stmt) templates = query.scalars().all() return GetAllBarcodeTemplatesResponse(templates=templates) @@ -43,10 +50,12 @@ class BarcodeService(BaseService): raise ValueError('Шаблон с таким именем уже существует') # create template then add attributes - template = BarcodeTemplate(name=request.name, is_default=request.is_default) + request_dict = request.dict() + del request_dict['attribute_ids'] + template = BarcodeTemplate(**request_dict) self.session.add(template) await self.session.flush() - + await self.session.refresh(template) # get all attributes from database stmt = select(BarcodeTemplateAttribute).filter( BarcodeTemplateAttribute.id.in_(request.attribute_ids)) @@ -55,12 +64,7 @@ class BarcodeService(BaseService): # add attributes to template for attribute in attributes: - template_attribute_link = BarcodeTemplateAttributeLink( - barcode_template_id=template.id, - attribute_id=attribute.id - ) - self.session.add(template_attribute_link) - await self.session.flush() + template.attributes.append(attribute) await self.session.commit() return BarcodeTemplateCreateResponse(message='Шаблон успешно создан', ok=True, @@ -97,24 +101,22 @@ class BarcodeService(BaseService): ) # difference deleted and new - template_attributes = set([attribute.attribute_id for attribute in template.attributes]) + template_attributes = set([attribute.id for attribute in template.attributes]) request_attributes = set(request.attribute_ids) - new_attributes = request_attributes.difference(template_attributes) - deleted_attributes = template_attributes.difference(request_attributes) + new_attribute_ids = request_attributes.difference(template_attributes) + deleted_attribute_ids = template_attributes.difference(request_attributes) # delete attributes for attribute in template.attributes: - if attribute.attribute_id not in deleted_attributes: + if attribute.id not in deleted_attribute_ids: continue - await self.session.delete(attribute) - - # add new attributes - for new_attribute in new_attributes: - template_attribute_link = BarcodeTemplateAttributeLink( - barcode_template_id=template.id, - attribute_id=new_attribute - ) - self.session.add(template_attribute_link) + template.attributes.remove(attribute) + for new_attribute_id in new_attribute_ids: + stmt = insert(barcode_template_attribute_link).values({ + 'barcode_template_id': template.id, + 'attribute_id': new_attribute_id + }) + await self.session.execute(stmt) await self.session.flush() await self.session.commit() @@ -125,6 +127,15 @@ class BarcodeService(BaseService): return BarcodeTemplateUpdateResponse(message=str(e), ok=False) + async def delete_template(self, request: BarcodeTemplateDeleteRequest) -> BarcodeTemplateDeleteResponse: + try: + template = await self.session.get(BarcodeTemplate, request.id) + await self.session.delete(template) + await self.session.commit() + return BarcodeTemplateDeleteResponse(ok=True, message='Шаблон успешно удален') + except Exception as e: + return BarcodeTemplateDeleteResponse(ok=False, message=str(e)) + # endregion # region Template attributes diff --git a/services/client.py b/services/client.py index f0b9a0d..e457238 100644 --- a/services/client.py +++ b/services/client.py @@ -91,7 +91,17 @@ class ClientService(BaseService): client = await self.get_by_id(request.data.id) if not client: return ClientUpdateResponse(ok=False, message='Клиент не найден') - await self.session.execute(update(Client).where(Client.id == client.id).values(name=request.data.name)) + request_dict = request.data.dict() + del request_dict['id'] + del request_dict['details'] + del request_dict['barcode_template'] + request_dict['barcode_template_id'] = request.data.barcode_template.id + stmt = ( + update(Client) + .where(Client.id == client.id) + .values(**request_dict) + ) + await self.session.execute(stmt) await self.update_details(user, client, request.data.details) await self.session.commit() return ClientUpdateResponse(ok=True, message='Клиент обновлен') diff --git a/services/deal.py b/services/deal.py index 35945b7..6af1317 100644 --- a/services/deal.py +++ b/services/deal.py @@ -21,7 +21,7 @@ class DealService(BaseService): async def _get_deal_by_id(self, deal_id) -> Union[Deal, None]: return await self.session.get(Deal, deal_id) - async def _get_rank_for_deal(self, deal_status: DealStatus) -> int: + async def _get_rank_for_deal(self, deal_status: DealStatus) -> str: deal_query = await self.session.execute( select(Deal).where(Deal.current_status == deal_status).order_by(Deal.lexorank.desc()).limit(1)) deal = deal_query.scalar_one_or_none() @@ -35,7 +35,7 @@ class DealService(BaseService): user: User, deadline: datetime.datetime = None, rank=None, - comment: str = '') -> DealStatusHistory: + comment: str = ''): if not deal.current_status == status: deadline = deadline status_change = DealStatusHistory(