From 95f8acb4861773b3b7713814e53a577b777bf97f Mon Sep 17 00:00:00 2001
From: duyanhehe <duyanhex@gmail.com>
Date: Sun, 16 Mar 2025 16:35:41 +0700
Subject: [PATCH] updated save images logic

---
 app/backend/routes/product.py          | 147 ++++++++++++-------------
 app/backend/routes/shop.py             |  52 ++++-----
 app/core/config.py                     |   5 +
 app/static/default/default_product.png | Bin 0 -> 401 bytes
 app/static/default/default_shop.png    | Bin 0 -> 633 bytes
 5 files changed, 98 insertions(+), 106 deletions(-)
 create mode 100644 app/static/default/default_product.png
 create mode 100644 app/static/default/default_shop.png

diff --git a/app/backend/routes/product.py b/app/backend/routes/product.py
index daaaf9e..8c16bf7 100644
--- a/app/backend/routes/product.py
+++ b/app/backend/routes/product.py
@@ -1,10 +1,11 @@
 from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
 from sqlmodel import Session
 from datetime import datetime
-from backend.models.models import Product, ProductImage, User
-from backend.schemas.product import ProductRead, ProductImageRead
+from backend.models.models import Product, ProductImage, User, Shop
+from backend.schemas.product import ProductRead, ProductUpdate
 from backend.database import get_session
 from backend.routes.auth import get_current_user
+from core.config import settings
 import shutil
 import os
 
@@ -22,7 +23,7 @@ def create_product(
     stock: int = Form(...),
     shop_id: int = Form(...),
     category_id: int = Form(None),
-    images: UploadFile = File(None),  # Ensuring image is correctly set
+    images: list[UploadFile] = File(None),
     session: Session = Depends(get_session),
 ):
     product = Product(
@@ -38,16 +39,33 @@ def create_product(
     session.commit()
     session.refresh(product)
 
-    # Handling image upload
-    if images and images.filename:
-        file_ext = os.path.splitext(images.filename)[1]  # Get file extension
-        file_name = f"product_{product.id}{file_ext}"
-        file_location = os.path.join(static_dir, file_name)
-
-        with open(file_location, "wb") as buffer:
-            shutil.copyfileobj(images.file, buffer)
-
-        # Save image record in ProductImage
+    # Get the shop to create the correct directory
+    shop = session.get(Shop, shop_id)
+    if not shop:
+        raise HTTPException(status_code=404, detail="Shop not found")
+
+    shop_dir = os.path.join(settings.static_dir, f"shop_{shop.name}")
+    os.makedirs(shop_dir, exist_ok=True)
+
+    product_dir = os.path.join(shop_dir, f"product_{product.name}")
+    os.makedirs(product_dir, exist_ok=True)
+
+    # Handling multiple image uploads
+    if images:
+        for image in images:
+            if image.filename:
+                file_location = os.path.join(product_dir, image.filename)
+                with open(file_location, "wb") as buffer:
+                    shutil.copyfileobj(image.file, buffer)
+
+                # Save image record in ProductImage
+                product_image = ProductImage(
+                    product_id=product.id, image_url=file_location
+                )
+                session.add(product_image)
+                session.commit()
+    else:  # Save default image
+        file_location = os.path.join(settings.static_dir, "default/default_product.png")
         product_image = ProductImage(product_id=product.id, image_url=file_location)
         session.add(product_image)
         session.commit()
@@ -69,44 +87,57 @@ def read_product(product_id: int, session: Session = Depends(get_session)):
     return product
 
 
-@router.put("/{product_id}", response_model=ProductRead)
+@router.put("/{product_id}", response_model=ProductUpdate)
 def update_product(
     product_id: int,
-    name: str = Form(None),
-    description: str = Form(None),
-    price: float = Form(None),
-    stock: int = Form(None),
-    category_id: int = Form(None),
-    file: UploadFile = File(None),
+    name: str = Form(...),
+    description: str = Form(...),
+    price: float = Form(...),
+    stock: int = Form(...),
+    category_id: int = Form(...),
+    images: list[UploadFile] = File(...),
     session: Session = Depends(get_session),
 ):
     product = session.get(Product, product_id)
     if not product:
         raise HTTPException(status_code=404, detail="Product not found")
-    
-    if name:
-        product.name = name
-    if description:
-        product.description = description
-    if price is not None:
-        product.price = price
-    if stock is not None:
-        product.stock = stock
-    if category_id is not None:
-        product.category_id = category_id
+
+    # if name:
+    #     product.name = name
+    # if description:
+    #     product.description = description
+    # if price is not None:
+    #     product.price = price
+    # if stock is not None:
+    #     product.stock = stock
+    # if category_id is not None:
+    #     product.category_id = category_id
 
     session.add(product)
     session.commit()
     session.refresh(product)
 
-    if file and file.filename:
-        file_location = os.path.join(static_dir, f"product_{product.id}_{file.filename}")
-        with open(file_location, "wb") as buffer:
-            shutil.copyfileobj(file.file, buffer)
-        
-        image = ProductImage(product_id=product.id, image_url=file_location)
-        session.add(image)
-        session.commit()
+    # Get the shop to create the correct directory
+    shop = session.get(Shop, product.shop_id)
+    if not shop:
+        raise HTTPException(status_code=404, detail="Shop not found")
+
+    shop_dir = os.path.join(settings.static_dir, f"shop_{shop.name}")
+    os.makedirs(shop_dir, exist_ok=True)
+
+    product_dir = os.path.join(shop_dir, f"product_{product.name}")
+    os.makedirs(product_dir, exist_ok=True)
+
+    if images:
+        for file in images:
+            if file.filename:
+                file_location = os.path.join(product_dir, file.filename)
+                with open(file_location, "wb") as buffer:
+                    shutil.copyfileobj(file.file, buffer)
+
+                image = ProductImage(product_id=product.id, image_url=file_location)
+                session.add(image)
+                session.commit()
 
     return product
 
@@ -119,41 +150,3 @@ def delete_product(product_id: int, session: Session = Depends(get_session)):
     session.delete(product)
     session.commit()
     return {"message": "Product deleted successfully"}
-
-
-@router.post("/ProductImage/", response_model=ProductImageRead)
-def upload_product_image(
-    product_id: int = Form(...),
-    file: UploadFile = File(...),
-    session: Session = Depends(get_session),
-):
-    product = session.get(Product, product_id)
-    if not product:
-        raise HTTPException(status_code=404, detail="Product not found")
-
-    file_location = os.path.join(static_dir, f"product_{product.id}_{file.filename}")
-    with open(file_location, "wb") as buffer:
-        shutil.copyfileobj(file.file, buffer)
-
-    image = ProductImage(product_id=product.id, image_url=file_location)
-    session.add(image)
-    session.commit()
-    return image
-
-
-@router.get("/ProductImage/{product_id}", response_model=list[ProductImageRead])
-def get_product_images(product_id: int, session: Session = Depends(get_session)):
-    images = session.query(ProductImage).filter(ProductImage.product_id == product_id).all()
-    if not images:
-        raise HTTPException(status_code=404, detail="No images found for this product")
-    return images
-
-
-@router.delete("/ProductImage/{image_id}")
-def delete_product_image(image_id: int, session: Session = Depends(get_session)):
-    image = session.get(ProductImage, image_id)
-    if not image:
-        raise HTTPException(status_code=404, detail="Image not found")
-    session.delete(image)
-    session.commit()
-    return {"message": "Product image deleted successfully"}
diff --git a/app/backend/routes/shop.py b/app/backend/routes/shop.py
index 6641eb3..e6f364d 100644
--- a/app/backend/routes/shop.py
+++ b/app/backend/routes/shop.py
@@ -4,14 +4,12 @@ from backend.models.models import Shop, User
 from backend.schemas.shop import ShopCreate, ShopRead
 from backend.database import get_session
 from backend.routes.auth import get_current_user
+from core.config import settings
 import shutil
 import os
 
 router = APIRouter()
 
-static_dir = os.path.join("app", "static")
-os.makedirs(static_dir, exist_ok=True)
-
 
 @router.post("/", response_model=ShopRead)
 def create_shop(
@@ -19,32 +17,30 @@ def create_shop(
     description: str = Form(None),
     file: UploadFile = File(None),
     session: Session = Depends(get_session),
-    current_user: User = Depends(get_current_user),
-    #owner_id = int,
-
+    # current_user: User = Depends(get_current_user),
+    owner_id=int,
 ):
-    shop = ShopCreate(name=name, description=description, owner_id=current_user.id)
-    #shop = ShopCreate(name=name, description=description, owner_id=owner_id)
+    # shop = ShopCreate(name=name, description=description, owner_id=current_user.id)
+    shop = ShopCreate(name=name, description=description, owner_id=owner_id)
     db_shop = Shop.from_orm(shop)
 
+    session.add(db_shop)
+    session.commit()
+    session.refresh(db_shop)
+
+    shop_dir = os.path.join(settings.static_dir, f"shop_{db_shop.name}")
+    os.makedirs(shop_dir, exist_ok=True)
+
     if file and file.filename:
-        # Save the image to the static directory
-        file_location = os.path.join(static_dir, f"{db_shop.name}_{file.filename}")
+        file_location = os.path.join(shop_dir, file.filename)
         with open(file_location, "wb") as buffer:
             shutil.copyfileobj(file.file, buffer)
-
         db_shop.image_url = file_location
     else:
-        # Set a default image URL if no file is uploaded
-        db_shop.image_url = os.path.join(static_dir, "default_shop_image.png")
+        db_shop.image_url = os.path.join(
+            settings.static_dir, "default/default_shop.png"
+        )
 
-    session.add(db_shop)
-    session.commit()
-    session.refresh(db_shop)
-
-    # if file:
-    #     # Delete the image file after session commit
-    #     os.remove(file_location)
     return db_shop
 
 
@@ -79,25 +75,23 @@ def update_shop(
     if description:
         db_shop.description = description
 
+    shop_dir = os.path.join(settings.static_dir, f"shop_{db_shop.name}")
+    os.makedirs(shop_dir, exist_ok=True)
+
     if file and file.filename:
-        # Save the image to the static directory
-        file_location = os.path.join(static_dir, f"{db_shop.name}_{file.filename}")
+        file_location = os.path.join(shop_dir, file.filename)
         with open(file_location, "wb") as buffer:
             shutil.copyfileobj(file.file, buffer)
-
         db_shop.image_url = file_location
     else:
-        # Set a default image URL if no file is uploaded
-        db_shop.image_url = os.path.join(static_dir, "default_shop_image.png")
+        db_shop.image_url = os.path.join(
+            settings.static_dir, "default/default_shop.png"
+        )
 
     session.add(db_shop)
     session.commit()
     session.refresh(db_shop)
 
-    if file:
-        # Delete the image file after session commit
-        os.remove(file_location)
-
     return db_shop
 
 
diff --git a/app/core/config.py b/app/core/config.py
index 9666c8a..7e46517 100644
--- a/app/core/config.py
+++ b/app/core/config.py
@@ -1,5 +1,6 @@
 from pathlib import Path
 from pydantic_settings import BaseSettings, SettingsConfigDict
+import os
 
 
 class Settings(BaseSettings):
@@ -16,6 +17,10 @@ class Settings(BaseSettings):
     def database_url(self) -> str:
         return f"mysql+pymysql://{self.database_username}:{self.database_password}@{self.database_host}/{self.database_name}"
 
+    @property
+    def static_dir(self) -> str:
+        return os.path.join("app", "static")
+
     model_config = SettingsConfigDict(
         env_file=str(Path(__file__).resolve().parent.parent / ".env"),
         env_file_encoding="utf-8",
diff --git a/app/static/default/default_product.png b/app/static/default/default_product.png
new file mode 100644
index 0000000000000000000000000000000000000000..f8a26b2d08887153a17797e6762ee17d71a89d08
GIT binary patch
literal 401
zcmeAS@N?(olHy`uVBq!ia0y~yU@!t<4mJh`208nVjSLJ7oCO|{#S9GG!XV7ZFl&wk
z0|TS8r;B4q#hkY@482$!1zhK6ta!m0V{%toqLMe*@QZ+OUe*gu7U9TpW%J7iiaFe*
zIwYp>d~s4Xvc0?aT-{c=5Tnr8;Q9COIyOJHSp9&Zf+gp{4tBoqMGO{9^R6iza<XAQ
zzE#PuVf%#wt~a7zBKW49<|~lBwvTx^tL+VjSs5MP39FX`woaJln;`Uc2gm)Yjl40f
zt?~yfORsQ57Kz1V{=UPo`^$sG-scCa+^my@eybXu2>aoArnMvSod=t8f?Vv>`>wNR
zGydkVHafqfG;eC_p0=%z`(_ocs0<V{`mNp9bEsjZu~DeKvU7r-3s1585rc9#6<oZ8
zGe2ynWw4Nt{Xbu$q9CV7j{EuUlsrk<9(KKcjX`)=L?`z_*^7rlWLDO0FcVj5TWJy0
t{Wn@sP0mw{$vH~t-6bQL<BE@j?bp6~_<#DFZUzPh22WQ%mvv4FO#p73nezYu

literal 0
HcmV?d00001

diff --git a/app/static/default/default_shop.png b/app/static/default/default_shop.png
new file mode 100644
index 0000000000000000000000000000000000000000..ed0ec74950384a12f8f40a8e3bba9d1247c4c562
GIT binary patch
literal 633
zcmeAS@N?(olHy`uVBq!ia0y~yU@!t<4mJh`208nVjSLJ7oCO|{#S9GG!XV7ZFl&wk
z0|S$`r;B4q#hkY@4*H2W3bfffFOrE67S2D!yrN*rkp=pWj|3h2Cloj>Qm<vybDQV5
zSzYJ=b5UEtwO;pDUK!Ryo-<N>)VHQx3j1EduYFtbuX^dtm8*XKU-@r&wV08Skx|3#
z16l<vQ<%GyA246ob;iYxKfodLs93?`&W?7@3Hoby+;=%q!gR!2n`e23jdw#uX6r){
z*3Dwqr?`FgdZ(?r{_V@VVV`{YrMbQCrLFNdDQZ8kVbboK?26J}_jDJmexldfHG`#&
z-7lHL;$`!M;FqFCQ@Inmr0y`*x%ebs+Bhw_bw-7V;Z)`ad294zE*nI=TP$!^ecj56
zzl(k@T7J()lIicokd9}<&9e{qyPvhMlVm?9d$L<DXupi9yshbc8PjFcxx4#j6+iqZ
z&M(thx;yiD;OA?>pU(w;z8frj)IVD7^$)}66`Q`>m@YoBG3fiIXK@GrL=~N~nNq>u
zbH(I+=TEiu7j&zy@cA&rHyF=6(%mpC%(+g|^O4~PDT&Q>=CdEK(dkS)%ADVz?zMk;
zQEte~^s2L3e~+~^KNRZCy=h;yOzR16>Y1(Tbt~lbzdea^FRH%2>r(dZTMPB2zTKW4
zcThvPKY?df#?01;9p8j+PCb8iSH#CJ5u9%}{<d%Z;kR|+{of1k-+imIq{&9mF)m6p
zr9Wh%t<nj(om%}RPuWU0PX5&v@lA1)fRxV?j|wH%o(X=3oc0~#nCTsH!l!4#EBSm^
nCMT|kpKQWh+}w_t9+r=fepmi$on96L0|SGntDnm{r-UW|0E`xx

literal 0
HcmV?d00001

-- 
GitLab