diff --git a/src/main/java/com/kasina/automobileapi/controller/ProductController.java b/src/main/java/com/kasina/automobileapi/controller/ProductController.java index 9e2510c..1777433 100644 --- a/src/main/java/com/kasina/automobileapi/controller/ProductController.java +++ b/src/main/java/com/kasina/automobileapi/controller/ProductController.java @@ -1,13 +1,17 @@ package com.kasina.automobileapi.controller; +import com.kasina.automobileapi.model.ImageModel; import com.kasina.automobileapi.model.Product; import com.kasina.automobileapi.dto.ProductDto; import com.kasina.automobileapi.service.ProductService; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.util.List; import java.util.Optional; @@ -41,6 +45,18 @@ public ResponseEntity getProductByCategory(@PathVariable Long id) { return new ResponseEntity<>(product, HttpStatus.OK); } + /* @PostMapping(value = "/add-products", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity> addMultipleProducts(@RequestBody List productDtos, + @RequestPart("imageFile")MultipartFile[] imageFile) { + + try{ + List addedProducts = productService.addMultipleProducts(productDtos, imageFile); + return new ResponseEntity<>(addedProducts, HttpStatus.CREATED); + }catch (Exception e) { + System.out.println(e.getMessage()); + return null; + } + }*/ @PostMapping public ResponseEntity addProduct(@RequestBody ProductDto productDto){ @@ -60,4 +76,5 @@ public ResponseEntity deleteProduct(@PathVariable Long id) { return ResponseEntity.ok("Product deleted successfully"); } + } diff --git a/src/main/java/com/kasina/automobileapi/dto/ProductDto.java b/src/main/java/com/kasina/automobileapi/dto/ProductDto.java index d45d695..1aa5824 100644 --- a/src/main/java/com/kasina/automobileapi/dto/ProductDto.java +++ b/src/main/java/com/kasina/automobileapi/dto/ProductDto.java @@ -1,5 +1,6 @@ package com.kasina.automobileapi.dto; +import com.kasina.automobileapi.model.ImageModel; import lombok.AllArgsConstructor; import lombok.Data; import lombok.RequiredArgsConstructor; @@ -15,6 +16,6 @@ public class ProductDto { private String description; private String shortDescription; private BigDecimal price; - private String image; private List categories; + private String image; } diff --git a/src/main/java/com/kasina/automobileapi/model/ImageModel.java b/src/main/java/com/kasina/automobileapi/model/ImageModel.java new file mode 100644 index 0000000..2412ad4 --- /dev/null +++ b/src/main/java/com/kasina/automobileapi/model/ImageModel.java @@ -0,0 +1,35 @@ +package com.kasina.automobileapi.model; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import java.math.BigDecimal; +import java.time.Instant; + +@Data +@AllArgsConstructor +@RequiredArgsConstructor +@Entity +@Table(name = "images") +public class ImageModel { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String name; + private String type; + @Lob + private byte[] picByte; + + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "product_id") + private Product product; + + public ImageModel(String originalFilename, String contentType, byte[] bytes) { + } +} diff --git a/src/main/java/com/kasina/automobileapi/model/Product.java b/src/main/java/com/kasina/automobileapi/model/Product.java index 1ac3846..06ef0db 100644 --- a/src/main/java/com/kasina/automobileapi/model/Product.java +++ b/src/main/java/com/kasina/automobileapi/model/Product.java @@ -8,7 +8,9 @@ import lombok.NoArgsConstructor; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; @Data @@ -27,6 +29,9 @@ public class Product { private BigDecimal price; private String image; + /*@OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true) + private List images = new ArrayList<>();*/ + @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "user_id") @JsonIgnore @@ -55,4 +60,5 @@ public void removeCategory(Category category) { } + } diff --git a/src/main/java/com/kasina/automobileapi/repository/ImageModelRepository.java b/src/main/java/com/kasina/automobileapi/repository/ImageModelRepository.java new file mode 100644 index 0000000..0e85131 --- /dev/null +++ b/src/main/java/com/kasina/automobileapi/repository/ImageModelRepository.java @@ -0,0 +1,7 @@ +package com.kasina.automobileapi.repository; + +import com.kasina.automobileapi.model.ImageModel; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ImageModelRepository extends JpaRepository { +} diff --git a/src/main/java/com/kasina/automobileapi/service/CategoryService.java b/src/main/java/com/kasina/automobileapi/service/CategoryService.java index f748934..9e7a304 100644 --- a/src/main/java/com/kasina/automobileapi/service/CategoryService.java +++ b/src/main/java/com/kasina/automobileapi/service/CategoryService.java @@ -16,11 +16,10 @@ public class CategoryService { private final CategoryRepository categoryRepository; - - // Create a new Category - public Category createCategory(Category Category) { - return categoryRepository.save(Category); + public Category createCategory(Category category) { + Optional defaultCategoryOpt = categoryRepository.findByName(category.getName()); + return defaultCategoryOpt.orElseGet(() -> categoryRepository.save(category)); } // Get all Categories @@ -29,7 +28,6 @@ public List getAllCategories() { } // Get a Category by ID - public Category getCategoryById(Long userId) { return categoryRepository.findById(userId) .orElseThrow(() -> new NoSuchElementException("Category not found with ID: " + userId)); diff --git a/src/main/java/com/kasina/automobileapi/service/ProductService.java b/src/main/java/com/kasina/automobileapi/service/ProductService.java index 04803f6..4fa82d4 100644 --- a/src/main/java/com/kasina/automobileapi/service/ProductService.java +++ b/src/main/java/com/kasina/automobileapi/service/ProductService.java @@ -1,17 +1,27 @@ package com.kasina.automobileapi.service; import com.kasina.automobileapi.model.Category; +import com.kasina.automobileapi.model.ImageModel; import com.kasina.automobileapi.model.Product; import com.kasina.automobileapi.dto.ProductDto; import com.kasina.automobileapi.dto.UrlErrorResponseDto; import com.kasina.automobileapi.model.User; +import com.kasina.automobileapi.repository.ImageModelRepository; import com.kasina.automobileapi.repository.ProductRepository; import com.kasina.automobileapi.repository.UserRepository; +import jakarta.persistence.EntityNotFoundException; import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; @Service @@ -19,10 +29,16 @@ public class ProductService { @Autowired private final ProductRepository productRepository; + + @Autowired + private final ImageModelRepository imageModelRepository; @Autowired private final UserService userService; @Autowired private final CategoryService categoryService; + @Value("${upload.path}") + private String uploadPath; + public Product createProduct(ProductDto productDto) { @@ -48,6 +64,34 @@ public Product createProduct(ProductDto productDto) { return productRepository.save(product); } + // add multiple products at once + + /*public List addMultipleProducts(List productDtos, MultipartFile[] imageFiles) throws IOException { + User currentUser = userService.getCurrentUser(); + List addedProducts = new ArrayList<>(); + List images = uploadImage(imageFiles); + for (ProductDto productDto : productDtos) { + Set categories = new HashSet<>(); + Product product = new Product(); + product.setName(productDto.getName()); + product.setDescription(productDto.getDescription()); + product.setShortDescription(productDto.getShortDescription()); + product.setPrice(productDto.getPrice()); + product.setUser(currentUser); + // product.setProductImages(images); + + for (String categoryName : productDto.getCategories()) { + Category category = categoryService.getDefaultCategory(categoryName); + categories.add(category); + } + product.setCategories(categories); + addedProducts.add(product); + } + + return productRepository.saveAll(addedProducts); + }*/ + + public Product updateProduct(ProductDto productDto, Long id){ Set categories = new HashSet<>(); User currentUser = userService.getCurrentUser(); @@ -97,4 +141,35 @@ public Optional> findProductByCategory(Long catId) { Category category = categoryService.getCategoryById(catId); return productRepository.findByCategories(category); } + + public List uploadImage(MultipartFile[] imageFiles) throws IOException { + + Set newImages = new HashSet<>(); + for(MultipartFile imageFile: imageFiles){ + ImageModel file = new ImageModel( + imageFile.getOriginalFilename(), + imageFile.getContentType(), + imageFile.getBytes() + ); + newImages.add(file); + } + return imageModelRepository.saveAll(newImages); + } + + public ImageModel saveImage(MultipartFile file) throws IOException { + String fileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename())); + ImageModel image = new ImageModel(fileName, file.getContentType(), file.getBytes()); + return imageModelRepository.save(image); + } + + public String storeImage(MultipartFile file) { + String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename(); + Path filePath = Paths.get(uploadPath + fileName); + try { + Files.write(filePath, file.getBytes()); + } catch (IOException e) { + throw new RuntimeException("Failed to store image: " + e.getMessage()); + } + return fileName; + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 21212d1..0012848 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -19,3 +19,8 @@ app.jwt.secret=404E635266556A586E3272357538782F413F4428472B4B6250645367566B5970 app.jwt.expiration = logging.level.org.springframework.security=TRACE +upload.path=/path/to/your/image/upload/directory/ + +spring.servlet.multipart.enabled=true +spring.servlet.multipart.max-file-size=10MB +spring.servlet.multipart.max-request-size=10MB