diff --git a/barcodes/attributes/__init__.py b/barcodes/attributes/__init__.py index 457e2b7..aa69432 100644 --- a/barcodes/attributes/__init__.py +++ b/barcodes/attributes/__init__.py @@ -1,21 +1,24 @@ -# 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 models import Product +from .article_attribute_getter import ArticleAttributeGetter +from .client_name_attribute_getter import ClientNameAttributeGetter +from .name_attribute_getter import NameAttributeGetter + + +class BaseAttributeGetter(ABC): + @abstractmethod + def get_value(self, product: Product): + pass + + +class AttributeWriterFactory: + @staticmethod + def get_writer(key: str): + match key: + case 'name': + return NameAttributeGetter() + case 'article': + return ArticleAttributeGetter() + case 'client.name': + return ClientNameAttributeGetter() diff --git a/barcodes/attributes/article_attribute_getter.py b/barcodes/attributes/article_attribute_getter.py new file mode 100644 index 0000000..a103da9 --- /dev/null +++ b/barcodes/attributes/article_attribute_getter.py @@ -0,0 +1,7 @@ +from barcodes.attributes import BaseAttributeGetter +from models import Product + + +class ArticleAttributeGetter(BaseAttributeGetter): + def get_value(self, product: Product): + return product.article diff --git a/barcodes/attributes/article_attribute_writer.py b/barcodes/attributes/article_attribute_writer.py deleted file mode 100644 index 98c620f..0000000 --- a/barcodes/attributes/article_attribute_writer.py +++ /dev/null @@ -1,7 +0,0 @@ -# from barcodes.attributes import BaseAttributeWriter -# from barcodes.barcode import Barcode -# -# -# class ArticleAttributeWriter(BaseAttributeWriter): -# def write(self, barcode: Barcode): -# pass diff --git a/barcodes/attributes/client_name_attribute_getter.py b/barcodes/attributes/client_name_attribute_getter.py new file mode 100644 index 0000000..826b763 --- /dev/null +++ b/barcodes/attributes/client_name_attribute_getter.py @@ -0,0 +1,8 @@ +from barcodes.attributes import BaseAttributeGetter +from models import Product, Client + + +class ClientNameAttributeGetter(BaseAttributeGetter): + def get_value(self, product: Product): + client: Client = product.client + return client.name diff --git a/barcodes/attributes/name_attribute_getter.py b/barcodes/attributes/name_attribute_getter.py new file mode 100644 index 0000000..ce0232a --- /dev/null +++ b/barcodes/attributes/name_attribute_getter.py @@ -0,0 +1,7 @@ +from barcodes.attributes import BaseAttributeGetter +from models import Product + + +class NameAttributeGetter(BaseAttributeGetter): + def get_value(self, product: Product): + return product.name diff --git a/barcodes/attributes/name_attribute_writer.py b/barcodes/attributes/name_attribute_writer.py deleted file mode 100644 index d57cd38..0000000 --- a/barcodes/attributes/name_attribute_writer.py +++ /dev/null @@ -1,7 +0,0 @@ -# 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 deleted file mode 100644 index 941dccc..0000000 --- a/barcodes/barcode.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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 deleted file mode 100644 index 8b07233..0000000 --- a/barcodes/generator.py +++ /dev/null @@ -1,6 +0,0 @@ -# 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 7f4be24..d3448e6 100644 --- a/models/barcode.py +++ b/models/barcode.py @@ -13,12 +13,11 @@ class BarcodeTemplateAttribute(BaseModel): class BarcodeTemplateAdditionalField(BaseModel): __tablename__ = 'barcode_template_additional_fields' - id = Column(Integer, autoincrement=True, primary_key=True, index=True) - name = Column(String, nullable=False) + name = Column(String, nullable=False, primary_key=True, comment='Название поля') value = Column(String, nullable=False) - barcode_template_id = Column(Integer, ForeignKey('barcode_templates.id'), nullable=False) - barcode_template = relationship('BarcodeTemplate', back_populates='additional_fields') + barcode_template_id = Column(Integer, ForeignKey('barcode_templates.id'), nullable=False, primary_key=True) + barcode_template = relationship('BarcodeTemplate') class BarcodeTemplate(BaseModel): @@ -27,14 +26,13 @@ class BarcodeTemplate(BaseModel): name = Column(String, nullable=False, index=True, comment='Название шаблона') attributes = relationship('BarcodeTemplateAttribute', secondary=barcode_template_attribute_link, - # back_populates='barcode_template', - # cascade="all, delete-orphan", + cascade="all", lazy='selectin' ) additional_fields = relationship('BarcodeTemplateAdditionalField', + lazy='selectin', back_populates='barcode_template', - lazy='selectin' - ) + cascade="all") is_default = Column(Boolean, nullable=False, default=False, comment='По умолчанию') diff --git a/models/product.py b/models/product.py index e6fc3fd..562a348 100644 --- a/models/product.py +++ b/models/product.py @@ -15,7 +15,7 @@ class Product(BaseModel): barcodes = relationship('ProductBarcode', back_populates='product', cascade="all, delete-orphan") barcode_template_id = Column(Integer, ForeignKey('barcode_templates.id'), nullable=True) - barcode_template = relationship('BarcodeTemplate') + barcode_template = relationship('BarcodeTemplate', lazy='joined') class ProductBarcode(BaseModel): diff --git a/schemas/barcode.py b/schemas/barcode.py index b171ffa..0beec07 100644 --- a/schemas/barcode.py +++ b/schemas/barcode.py @@ -1,3 +1,5 @@ +from typing import List + from schemas.base import CustomModelCamel, OkMessageSchema @@ -8,11 +10,17 @@ class BarcodeTemplateAttributeSchema(CustomModelCamel): name: str +class BarcodeTemplateAdditionalAttributeSchema(CustomModelCamel): + name: str + value: str + + class BaseBarcodeTemplateSchema(CustomModelCamel): name: str is_default: bool width: int height: int + additional_attributes: list[BarcodeTemplateAdditionalAttributeSchema] class BarcodeTemplateSchema(BaseBarcodeTemplateSchema): @@ -20,6 +28,16 @@ class BarcodeTemplateSchema(BaseBarcodeTemplateSchema): attributes: list[BarcodeTemplateAttributeSchema] +class BarcodeAttributeSchema(CustomModelCamel): + name: str + value: str + + +class BarcodeSchema(CustomModelCamel): + barcode: str + attributes: List[BarcodeAttributeSchema] + + # endregion # region Requests @@ -44,6 +62,12 @@ class BarcodeTemplateDeleteRequest(CustomModelCamel): id: int +class GetProductBarcodeRequest(CustomModelCamel): + product_id: int + barcode: str + barcode_template_id: int | None = None + + # endregion # region Responses @@ -74,4 +98,8 @@ class GetAllBarcodeTemplateAttributesResponse(CustomModelCamel): class BarcodeTemplateDeleteResponse(OkMessageSchema): pass + + +class GetProductBarcodeResponse(CustomModelCamel): + barcode: BarcodeSchema # endregion diff --git a/schemas/client.py b/schemas/client.py index fffebe4..10f319a 100644 --- a/schemas/client.py +++ b/schemas/client.py @@ -1,6 +1,6 @@ from typing import List -from pydantic import validator, field_validator +from pydantic import field_validator from schemas.barcode import BarcodeTemplateSchema from schemas.base import CustomModelCamel, OkMessageSchema diff --git a/schemas/product.py b/schemas/product.py index f5b0da1..7353d8f 100644 --- a/schemas/product.py +++ b/schemas/product.py @@ -1,9 +1,8 @@ from typing import List - -from pydantic import validator, field_validator - -from models import ProductBarcode +from schemas.barcode import BarcodeTemplateSchema from schemas.base import CustomModelCamel, PaginationInfoSchema, OkMessageSchema +from pydantic import field_validator +from models import ProductBarcode # region Entities @@ -14,6 +13,7 @@ class ProductSchema(CustomModelCamel): article: str client_id: int barcodes: list[str] + barcode_template: BarcodeTemplateSchema | None = None @field_validator('barcodes', mode="before") def barcodes_to_list(cls, v): @@ -30,7 +30,7 @@ class ProductCreateRequest(CustomModelCamel): article: str client_id: int barcodes: List[str] - + barcode_template: BarcodeTemplateSchema | None = None class ProductDeleteRequest(CustomModelCamel): product_id: int diff --git a/services/barcode.py b/services/barcode.py index 61e20b4..7bb57ad 100644 --- a/services/barcode.py +++ b/services/barcode.py @@ -1,20 +1,52 @@ from sqlalchemy import select, update, insert -from sqlalchemy.orm import selectinload +from sqlalchemy.orm import selectinload, joinedload -from models import BarcodeTemplate, BarcodeTemplateAttribute, barcode_template_attribute_link -from schemas.barcode import (GetBarcodeTemplateByIdRequest, - GetBarcodeTemplateByIdResponse, - BarcodeTemplateCreateResponse, - BarcodeTemplateCreateRequest, CreateBarcodeTemplateAttributeRequest, - BarcodeTemplateUpdateResponse, BarcodeTemplateUpdateRequest, - BarcodeTemplateAttributeSchema, GetAllBarcodeTemplateAttributesResponse, - GetAllBarcodeTemplatesResponse, BarcodeTemplateDeleteRequest, - BarcodeTemplateDeleteResponse) +from models import BarcodeTemplate, BarcodeTemplateAttribute, barcode_template_attribute_link, Product +from schemas.barcode import * from services.base import BaseService class BarcodeService(BaseService): + # region Barcode + async def get_barcode(self, request: GetProductBarcodeRequest) -> GetProductBarcodeResponse: + # get product by id + stmt = ( + select(Product) + .options( + joinedload(Product.client) + ) + .filter(Product.id == request.product_id) + ) + query = await self.session.execute(stmt) + product: Product = query.scalar() + if not product: + raise ValueError('Товар не найден') + + # get barcode template by id + if request.barcode_template_id: + stmt = select(BarcodeTemplate).filter(BarcodeTemplate.id == request.barcode_template_id) + query = await self.session.execute(stmt) + barcode_template = query.scalar() + if not barcode_template: + raise ValueError('Шаблон не найден') + elif product.barcode_template: + barcode_template = product.barcode_template + elif product.client.barcode_template: + barcode_template = product.client.barcode_template + else: + stmt = select(BarcodeTemplate).filter(BarcodeTemplate.is_default == True) + query = await self.session.execute(stmt) + barcode_template = query.scalar() + if not barcode_template: + raise ValueError('Стандартный шаблон не найден') + barcode_template: BarcodeTemplate + + + # endregion + + # endregion + # region Template async def get_barcode_template_by_id(self, request: GetBarcodeTemplateByIdRequest) -> GetBarcodeTemplateByIdResponse: diff --git a/services/product.py b/services/product.py index 7243e33..05963c2 100644 --- a/services/product.py +++ b/services/product.py @@ -26,6 +26,9 @@ class ProductService(BaseService): # Creating product product_dict = request.dict() del product_dict['barcodes'] + del product_dict['barcode_template'] + if request.barcode_template: + product_dict['barcode_template_id'] = request.barcode_template.id product = Product(**product_dict) self.session.add(product) @@ -60,6 +63,10 @@ class ProductService(BaseService): product_dict = request.product.dict() del product_dict['id'] del product_dict['barcodes'] + del product_dict['barcode_template'] + if request.product.barcode_template: + product_dict['barcode_template_id'] = request.product.barcode_template.id + await self.session.execute( update(Product) .where(Product.id == request.product.id)