feat: temp barcode templates
This commit is contained in:
		@@ -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()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								barcodes/attributes/article_attribute_getter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								barcodes/attributes/article_attribute_getter.py
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
# from barcodes.attributes import BaseAttributeWriter
 | 
			
		||||
# from barcodes.barcode import Barcode
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# class ArticleAttributeWriter(BaseAttributeWriter):
 | 
			
		||||
#     def write(self, barcode: Barcode):
 | 
			
		||||
#         pass
 | 
			
		||||
							
								
								
									
										8
									
								
								barcodes/attributes/client_name_attribute_getter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								barcodes/attributes/client_name_attribute_getter.py
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										7
									
								
								barcodes/attributes/name_attribute_getter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								barcodes/attributes/name_attribute_getter.py
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
# from barcodes.attributes import BaseAttributeWriter
 | 
			
		||||
# from barcodes.barcode import Barcode
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# class NameAttributeWriter(BaseAttributeWriter):
 | 
			
		||||
#     def write(self, barcode: Barcode):
 | 
			
		||||
#         pass
 | 
			
		||||
@@ -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)
 | 
			
		||||
#
 | 
			
		||||
@@ -1,6 +0,0 @@
 | 
			
		||||
# from models import ProductBarcode
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# class BarcodeGenerator:
 | 
			
		||||
#     def __init__(self, barcode: ProductBarcode):
 | 
			
		||||
#         self.barcode = barcode
 | 
			
		||||
@@ -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='По умолчанию')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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):
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user