Skip to content

Commit

Permalink
tenant can now create product
Browse files Browse the repository at this point in the history
  • Loading branch information
harmlessprince committed Feb 2, 2025
1 parent 295d714 commit 034d726
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("hasAuthority('shop_owner')")
@PreAuthorize("hasAuthority('store_owner')")
public @interface ShopOwnerAccess {
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
import com.harmlessprince.ecommerceApi.color.ColorRepository;
import com.harmlessprince.ecommerceApi.contexts.TenantContext;
import com.harmlessprince.ecommerceApi.custom.ShopOwnerAccess;
import com.harmlessprince.ecommerceApi.exceptions.CustomBadRequestException;
import com.harmlessprince.ecommerceApi.handler.CustomSuccessResponse;

import com.harmlessprince.ecommerceApi.productCategory.Category;
import com.harmlessprince.ecommerceApi.productCategory.TenantCategory;
import com.harmlessprince.ecommerceApi.productCategory.TenantCategoryService;
import com.harmlessprince.ecommerceApi.productCategory.repositories.ProductCategoryRepository;
import com.harmlessprince.ecommerceApi.specification.SpecificationService;
import jakarta.validation.Valid;
Expand All @@ -20,6 +23,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
Expand All @@ -34,6 +38,7 @@ public class ProductController {
private final SpecificationService specificationService;
private final BrandRepository brandRepository;
private final ProductCategoryRepository productCategoryRepository;
private final TenantCategoryService tenantCategoryService;
private final ColorRepository colorRepository;


Expand Down Expand Up @@ -62,26 +67,36 @@ public ResponseEntity<CustomSuccessResponse<Map<String, Object>>> allProduct(
@PostMapping
@ShopOwnerAccess
public ResponseEntity<CustomSuccessResponse<Object>> createProduct(@RequestBody @Valid ProductRequest productRequest) {


Optional<Brand> brand = brandRepository.findById(productRequest.getBrandId());
Optional<Category> category = productCategoryRepository.findById(productRequest.getCategoryId());
Optional<Color> color = colorRepository.findById(productRequest.getColorId());
specificationService.validateSpecifications(productRequest.getSpecifications());

if (brand.isEmpty() && !productRequest.getBrandId().isEmpty()) {
throw new IllegalArgumentException("Invalid brand");
Optional<Brand> brand = Optional.empty();
Optional<Color> color = Optional.empty();
Optional<TenantCategory> category;
if (StringUtils.hasText(productRequest.getBrandId())){
brand = brandRepository.findById(productRequest.getBrandId());
if (brand.isEmpty()) {
throw new CustomBadRequestException("Invalid brand");
}
}
if (category.isEmpty() && !productRequest.getCategoryId().isEmpty()) {
throw new IllegalArgumentException("Invalid Category");
if (StringUtils.hasText(productRequest.getColorId())){
color = colorRepository.findById(productRequest.getColorId());
if (color.isEmpty()) {
throw new CustomBadRequestException("Invalid color");
}
}
if (color.isEmpty() && !productRequest.getColorId().isEmpty()) {
throw new IllegalArgumentException("Invalid Color");
if (StringUtils.hasText(productRequest.getCategoryId())){
category = tenantCategoryService.findByIdAndTenantId(productRequest.getCategoryId(), TenantContext.getCurrentTenantID());
if (category.isEmpty()) {
throw new CustomBadRequestException("Invalid category");
}
}else {
throw new CustomBadRequestException("Invalid category");
}
specificationService.validateSpecifications(productRequest.getSpecifications());

productRequest.setTenantId(TenantContext.getCurrentTenantID());

Product product = productService.create(productRequest, brand, category, color);
String categoryName = category.get().getName();

Product product = productService.create(productRequest, brand, categoryName, color);
return ResponseEntity.ok(new CustomSuccessResponse<>(productMapper.fromEntity(product)));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,55 +23,22 @@ public class ProductMapper {
private final ColorRepository colorRepository;

public ProductResponse fromEntity(Product entity) {
return new ProductResponse(
entity.getId(),
entity.getName(),
entity.getSlug(),
entity.getDescription(),
entity.getImage(),
entity.getThumbnail(),
entity.getImageList(),
entity.getPrice(),
entity.getNewPrice(),
entity.getRamSize(),
entity.getStorage(),
entity.getSize(),
entity.getQuantityInStock(),
entity.getBrand(),
entity.getDiscount(),
entity.getCategory(),
entity.getColor(),
entity.getSpecifications(),
entity.getVariations(),
entity.getFeatures() == null ? Collections.emptyList() : entity.getFeatures()
);
return new ProductResponse(entity.getId(), entity.getName(), entity.getSlug(), entity.getDescription(), entity.getImage(), entity.getThumbnail(), entity.getImageList(), entity.getPrice(), entity.getNewPrice(), entity.getRamSize(), entity.getStorage(), entity.getSize(), entity.getQuantityInStock(), entity.getBrand(), entity.getDiscount(), entity.getCategory(), entity.getColor(), entity.getSpecifications(), entity.getVariations(), entity.getFeatures() == null ? Collections.emptyList() : entity.getFeatures());
}




public Product toEntity(ProductRequest request, Optional<Brand> brand, Optional<Category> category, Optional<Color> color) {
public Product toEntity(ProductRequest request, Optional<Brand> brand, String categoryName, Optional<Color> color) {
request.setSlug();
Product product = Product
.builder()
.name(request.getName())
.slug(request.getSlug())
.description(request.getDescription())
.sku(request.getSku())
.thumbnail(request.getThumbnail())
.image(request.getImage())
.imageList(request.getImageList())
.price(request.getPrice())
.ramSize(request.getRamSize())
.Storage(request.getStorage())
.size(request.getSize())
.quantityInStock(request.getQuantityInStock())
.features(request.getFeatures())
.discount(request.getDiscount())
.build();
Product product = Product.builder().name(request.getName()).slug(request.getSlug()).description(request.getDescription()).sku(request.getSku()).thumbnail(request.getThumbnail()).image(request.getImage()).imageList(request.getImageList()).price(request.getPrice()).ramSize(request.getRamSize()).Storage(request.getStorage()).size(request.getSize()).quantityInStock(request.getQuantityInStock()).features(request.getFeatures()).discount(request.getDiscount()).tenantId(request.getTenantId()).build();
brand.ifPresent(value -> product.setBrand(value.getName()));
category.ifPresent(value -> product.setCategory(value.getName()));
color.ifPresent(value -> product.setColor(value.getName()));
product.setCategory(categoryName);

if (color.isPresent()) {
product.setColor(color.get().getName());
} else {
product.setColor(request.getCustomColor());
}

product.setNewPrice(request.getPrice());
if (request.getSpecifications() != null && !request.getSpecifications().isEmpty()) {
product.setSpecifications(new HashSet<>(request.getSpecifications()));
Expand Down Expand Up @@ -99,15 +66,11 @@ public Product toEntity(ProductRequest request, Optional<Brand> brand, Optional<
}



public List<ProductResponse> fromEntityList(List<Product> products) {
return products.stream().map(this::fromEntity).collect(Collectors.toList());
}

public Product toEntityForUpdate(
Product existingProduct,
UpdateProductRequest request
) {
public Product toEntityForUpdate(Product existingProduct, UpdateProductRequest request) {
log.info("Request {}", request);
// Update fields only if they are present in the request; otherwise, keep existing values
existingProduct.setName(Optional.ofNullable(request.getName()).orElse(existingProduct.getName()));
Expand All @@ -126,30 +89,29 @@ public Product toEntityForUpdate(


// Update relationships
if (request.getBrandId() != null && !request.getBrandId().isEmpty() && !request.getBrandId().isBlank()){
if (request.getBrandId() != null && !request.getBrandId().isEmpty() && !request.getBrandId().isBlank()) {
Optional<Brand> brand = brandRepository.findFirstById(request.getBrandId());
brand.ifPresentOrElse(value -> existingProduct.setBrand(value.getName()), () -> {
brand.ifPresentOrElse(value -> existingProduct.setBrand(value.getName()), () -> {
throw new CustomBadRequestException("Invalid brand ID");
});
}

if (request.getCategoryId() != null && !request.getCategoryId().isEmpty() && !request.getCategoryId().isBlank()){
if (request.getCategoryId() != null && !request.getCategoryId().isEmpty() && !request.getCategoryId().isBlank()) {
Optional<Category> category = productRepository.findFirstById(request.getColorId());
category.ifPresentOrElse(value -> existingProduct.setBrand(value.getName()), () -> {
category.ifPresentOrElse(value -> existingProduct.setBrand(value.getName()), () -> {
throw new CustomBadRequestException("Invalid Category ID");
});
}
if (request.getColorId() != null && !request.getColorId().isEmpty() && !request.getColorId().isBlank()){
if (request.getColorId() != null && !request.getColorId().isEmpty() && !request.getColorId().isBlank()) {
Optional<Color> color = colorRepository.findFirstById(request.getColorId());
color.ifPresentOrElse(value -> existingProduct.setBrand(value.getName()), () -> {
color.ifPresentOrElse(value -> existingProduct.setBrand(value.getName()), () -> {
throw new CustomBadRequestException("Invalid Color ID");
});
}else {
} else {
existingProduct.setColor(Optional.ofNullable(request.getCustomColor()).orElse(existingProduct.getColor()));
}



// Update specifications
if (request.getSpecifications() != null && !request.getSpecifications().isEmpty()) {
existingProduct.setSpecifications(new HashSet<>(request.getSpecifications()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,13 @@ public class ProductRequest implements Serializable {

private String tenantId;

@NotEmpty(message = "color is required")
@Size(min = 10)
private String colorId;

@Size(min = 3)
private String customColor;


@Size(min = 1, message = "At least one specification is required")
private List<ProductSpecificationDTO> specifications;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.harmlessprince.ecommerceApi.exceptions.CustomBadRequestException;
import com.harmlessprince.ecommerceApi.exceptions.CustomResourceNotFoundException;
import com.harmlessprince.ecommerceApi.productCategory.Category;
import com.harmlessprince.ecommerceApi.productCategory.TenantCategory;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -57,9 +58,9 @@ public Optional<ProductPriceDetail> findVariationProductPriceDetail(ProductColor
return priceDetail;
}

public Product create(ProductRequest data, Optional<Brand> brand, Optional<Category> productCategory, Optional<Color> color) {
Product product = productMapper.toEntity(data, brand, productCategory, color);
Optional<Product> existingProduct = productRepository.findFirstBySlug(product.getSlug());
public Product create(ProductRequest data, Optional<Brand> brand, String categoryName, Optional<Color> color) {
Product product = productMapper.toEntity(data, brand, categoryName, color);
Optional<Product> existingProduct = productRepository.findFirstByNameAndTenantId(data.getName(), product.getTenantId());
if (existingProduct.isPresent()) {
throw new CustomBadRequestException("Product with supplied name already exists");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.harmlessprince.ecommerceApi.productCategory.filters.TenantCategoryFilter;
import com.harmlessprince.ecommerceApi.productCategory.repositories.TenantCategoryRepository;
import com.harmlessprince.ecommerceApi.productCategory.requests.CreateCategoryRequest;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

Expand Down Expand Up @@ -35,4 +37,8 @@ public Optional<TenantCategory> findByName(String id, String tenantId) {
public List<TenantCategory> all(Map<String, Object> requestParams) {
return categoryFilter.findAll(requestParams);
}

public Optional<TenantCategory> findByIdAndTenantId( String categoryId, String tenantId) {
return tenantCategoryRepository.findFirstByIdAndTenantId(categoryId, tenantId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ public void run() {
for (ProductRequest productRequest : productRequests) {
Optional<Brand> brand = brands.stream().filter(value -> value.getId().equals(productRequest.getBrandId())).findFirst();
Optional<Category> category = categories.stream().filter(value -> value.getId().equals(productRequest.getCategoryId())).findFirst();
productService.create(productRequest, brand, category, Optional.empty());
String categoryName = category.isPresent() ? category.get().getName() : "";
productService.create(productRequest, brand, categoryName, Optional.empty());
}

}
Expand Down

0 comments on commit 034d726

Please sign in to comment.