feat: images uploader, endpoint for product images uploading
This commit is contained in:
@ -2,6 +2,7 @@ from sqlalchemy import or_, delete
|
||||
from sqlalchemy.orm import selectinload, joinedload
|
||||
|
||||
from modules.fulfillment_base.models import Product, ProductBarcode, BarcodeTemplate
|
||||
from modules.fulfillment_base.models.product import ProductImage
|
||||
from modules.fulfillment_base.schemas.product import (
|
||||
CreateProductSchema,
|
||||
UpdateProductSchema,
|
||||
@ -16,6 +17,7 @@ class ProductRepository(
|
||||
RepUpdateMixin[Product, UpdateProductSchema],
|
||||
RepGetByIdMixin[Product],
|
||||
):
|
||||
session: AsyncSession
|
||||
entity_class = Product
|
||||
entity_not_found_msg = "Товар не найден"
|
||||
|
||||
@ -95,3 +97,20 @@ class ProductRepository(
|
||||
await self._update_barcodes(product, data.barcodes)
|
||||
del data.barcodes
|
||||
return await self._apply_update_data_to_model(product, data, True)
|
||||
|
||||
async def delete_images(self, product_images: list[ProductImage], with_commit: bool = False):
|
||||
for img in product_images:
|
||||
await self.session.delete(img)
|
||||
if with_commit:
|
||||
await self.session.commit()
|
||||
else:
|
||||
await self.session.flush()
|
||||
|
||||
async def create_image(self, product_id: int, image_url: str) -> ProductImage:
|
||||
product_image = ProductImage(
|
||||
product_id=product_id,
|
||||
image_url=image_url,
|
||||
)
|
||||
self.session.add(product_image)
|
||||
await self.session.commit()
|
||||
return product_image
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import field_validator
|
||||
from pydantic import field_validator, model_validator
|
||||
|
||||
from modules.fulfillment_base.models import ProductBarcode
|
||||
from modules.fulfillment_base.schemas.barcode_template import BarcodeTemplateSchema
|
||||
@ -28,6 +28,17 @@ class CreateProductSchema(BaseSchema):
|
||||
size: Optional[str]
|
||||
additional_info: Optional[str]
|
||||
barcodes: list[str]
|
||||
image_url: str | None = None
|
||||
images: list[ProductImageSchema] | None = []
|
||||
|
||||
@model_validator(mode="after")
|
||||
def images_list_to_image_url(cls, values):
|
||||
images = values.images
|
||||
if not images:
|
||||
return values
|
||||
latest_image = images[-1]
|
||||
values.image_url = latest_image.image_url
|
||||
return values
|
||||
|
||||
|
||||
class ProductSchema(CreateProductSchema):
|
||||
@ -93,6 +104,10 @@ class UpdateProductResponse(BaseResponse):
|
||||
pass
|
||||
|
||||
|
||||
class ProductUploadImageResponse(BaseResponse):
|
||||
image_url: Optional[str] = None
|
||||
|
||||
|
||||
class DeleteProductResponse(BaseResponse):
|
||||
pass
|
||||
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import math
|
||||
|
||||
from fastapi import UploadFile
|
||||
|
||||
from external.s3_uploader import S3Uploader
|
||||
from modules.fulfillment_base.models import Product
|
||||
from modules.fulfillment_base.repositories import ProductRepository
|
||||
from modules.fulfillment_base.schemas.product import (
|
||||
CreateProductRequest,
|
||||
ProductSchema,
|
||||
UpdateProductRequest, GetProductsResponse,
|
||||
)
|
||||
from modules.fulfillment_base.schemas.product import *
|
||||
from schemas.base import PaginationSchema, PaginationInfoSchema
|
||||
from services.mixins import *
|
||||
|
||||
@ -46,5 +45,22 @@ class ProductService(
|
||||
),
|
||||
)
|
||||
|
||||
async def is_soft_delete(self, product: ProductSchema) -> bool:
|
||||
return True
|
||||
async def upload_image(
|
||||
self, product_id: int, upload_file: UploadFile
|
||||
) -> ProductUploadImageResponse:
|
||||
try:
|
||||
product: Product = await self.repository.get_by_id(product_id)
|
||||
s3_uploader = S3Uploader()
|
||||
|
||||
for image in product.images:
|
||||
s3_key = image.image_url.split("/")[-1]
|
||||
await s3_uploader.delete_image(s3_key)
|
||||
await self.repository.delete_images(product.images)
|
||||
|
||||
image_url = await s3_uploader.upload_from_upload_file_obj(upload_file)
|
||||
await self.repository.create_image(product_id, image_url)
|
||||
return ProductUploadImageResponse(
|
||||
ok=True, message="Изображение успешно загружено", image_url=image_url
|
||||
)
|
||||
except Exception as e:
|
||||
return ProductUploadImageResponse(ok=False, message=str(e))
|
||||
|
||||
Reference in New Issue
Block a user