diff --git a/src/main/java/jewellery/inventory/controller/ProductInOrganizationController.java b/src/main/java/jewellery/inventory/controller/ProductInOrganizationController.java new file mode 100644 index 00000000..bc23c8ea --- /dev/null +++ b/src/main/java/jewellery/inventory/controller/ProductInOrganizationController.java @@ -0,0 +1,51 @@ +package jewellery.inventory.controller; + +import io.swagger.v3.oas.annotations.Operation; +import jakarta.validation.Valid; +import java.util.UUID; +import jewellery.inventory.dto.request.ProductRequestDto; +import jewellery.inventory.dto.response.ProductsInOrganizationResponseDto; +import jewellery.inventory.service.ProductInOrganizationService; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/organizations") +@AllArgsConstructor +public class ProductInOrganizationController { + private final ProductInOrganizationService productInOrganizationService; + + @Operation(summary = "Get all products in organization") + @ResponseStatus(HttpStatus.OK) + @GetMapping("/{organizationId}/products") + public ProductsInOrganizationResponseDto getAllProductsInOrganization( + @PathVariable UUID organizationId) { + return productInOrganizationService.getProductsInOrganization(organizationId); + } + + @Operation(summary = "Create a new product in organization") + @ResponseStatus(HttpStatus.CREATED) + @PostMapping("/products") + public ProductsInOrganizationResponseDto createProductInOrganization( + @RequestBody @Valid ProductRequestDto productRequestDto) { + return productInOrganizationService.createProductInOrganization(productRequestDto); + } + + @Operation(summary = "Delete a new product in organization") + @ResponseStatus(HttpStatus.NO_CONTENT) + @DeleteMapping("/products/{productId}") + public void deleteProductInOrganization( + @PathVariable("productId") UUID productId) { + productInOrganizationService.deleteProductInOrganization(productId); + } + + @Operation(summary = "Update a product in organization") + @ResponseStatus(HttpStatus.OK) + @PutMapping("/products/{productId}") + public ProductsInOrganizationResponseDto updateProduct( + @PathVariable("productId") UUID productId, + @Valid @RequestBody ProductRequestDto productRequestDto) { + return productInOrganizationService.updateProduct(productId, productRequestDto); + } +} diff --git a/src/main/java/jewellery/inventory/dto/response/ProductsInOrganizationResponseDto.java b/src/main/java/jewellery/inventory/dto/response/ProductsInOrganizationResponseDto.java new file mode 100644 index 00000000..6bbaae95 --- /dev/null +++ b/src/main/java/jewellery/inventory/dto/response/ProductsInOrganizationResponseDto.java @@ -0,0 +1,17 @@ +package jewellery.inventory.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.util.List; + +@Data +@SuperBuilder +@AllArgsConstructor +@NoArgsConstructor +public class ProductsInOrganizationResponseDto { + private OrganizationResponseDto organization; + private List products; +} diff --git a/src/main/java/jewellery/inventory/exception/GlobalExceptionHandler.java b/src/main/java/jewellery/inventory/exception/GlobalExceptionHandler.java index dead3fe7..921f4848 100644 --- a/src/main/java/jewellery/inventory/exception/GlobalExceptionHandler.java +++ b/src/main/java/jewellery/inventory/exception/GlobalExceptionHandler.java @@ -89,7 +89,9 @@ public ResponseEntity handleBadDataExceptions(RuntimeException ex) { UserIsNotPartOfOrganizationException.class, UserIsPartOfOrganizationException.class, OrphanResourcesInOrganizationException.class, - OrphanProductsInOrganizationException.class + OrphanProductsInOrganizationException.class, + OrganizationNotOwnerException.class, + ProductIsNotPartOfOrganizationException.class }) public ResponseEntity handleEntityConstraintConflict(RuntimeException ex) { return createErrorResponse(HttpStatus.CONFLICT, ex.getMessage(), ex); @@ -111,7 +113,7 @@ private ResponseEntity createErrorResponse( String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT_PATTERN)); body.put(TIMESTAMP_KEY, date); body.put(ERROR_KEY, error); - logger.error("Error occurred: " + ex.getMessage(), ex); + logger.error("Error occurred: {} " , ex.getMessage(), ex); return new ResponseEntity<>(body, status); } diff --git a/src/main/java/jewellery/inventory/exception/organization/OrganizationNotOwnerException.java b/src/main/java/jewellery/inventory/exception/organization/OrganizationNotOwnerException.java new file mode 100644 index 00000000..ad77d404 --- /dev/null +++ b/src/main/java/jewellery/inventory/exception/organization/OrganizationNotOwnerException.java @@ -0,0 +1,10 @@ +package jewellery.inventory.exception.organization; + + +import java.util.UUID; + +public class OrganizationNotOwnerException extends RuntimeException { + public OrganizationNotOwnerException(UUID organizationId, UUID productId) { + super("Organization with id " + organizationId + " is not the owner of a product with id " + productId); + } + } diff --git a/src/main/java/jewellery/inventory/exception/organization/ProductIsNotPartOfOrganizationException.java b/src/main/java/jewellery/inventory/exception/organization/ProductIsNotPartOfOrganizationException.java new file mode 100644 index 00000000..8a5308a0 --- /dev/null +++ b/src/main/java/jewellery/inventory/exception/organization/ProductIsNotPartOfOrganizationException.java @@ -0,0 +1,9 @@ +package jewellery.inventory.exception.organization; + +import java.util.UUID; + +public class ProductIsNotPartOfOrganizationException extends RuntimeException { + public ProductIsNotPartOfOrganizationException(UUID productId) { + super("The Product with id " + productId + "is not owned of Organization"); + } +} diff --git a/src/main/java/jewellery/inventory/mapper/ProductInOrganizationMapper.java b/src/main/java/jewellery/inventory/mapper/ProductInOrganizationMapper.java new file mode 100644 index 00000000..de8e502f --- /dev/null +++ b/src/main/java/jewellery/inventory/mapper/ProductInOrganizationMapper.java @@ -0,0 +1,25 @@ +package jewellery.inventory.mapper; + +import jewellery.inventory.dto.response.ProductResponseDto; +import jewellery.inventory.dto.response.ProductsInOrganizationResponseDto; +import jewellery.inventory.model.Organization; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@RequiredArgsConstructor +public class ProductInOrganizationMapper { + private final OrganizationMapper organizationMapper; + + public ProductsInOrganizationResponseDto mapToProductsInOrganizationResponseDto( + Organization organization, List products) { + ProductsInOrganizationResponseDto productsInOrganizationResponseDto = + new ProductsInOrganizationResponseDto(); + + productsInOrganizationResponseDto.setOrganization(organizationMapper.toResponse(organization)); + productsInOrganizationResponseDto.setProducts(products); + return productsInOrganizationResponseDto; + } +} diff --git a/src/main/java/jewellery/inventory/model/EventType.java b/src/main/java/jewellery/inventory/model/EventType.java index 5883e097..9e0f9446 100644 --- a/src/main/java/jewellery/inventory/model/EventType.java +++ b/src/main/java/jewellery/inventory/model/EventType.java @@ -23,5 +23,8 @@ public enum EventType { ORGANIZATION_USER_DELETE, ORGANIZATION_USER_UPDATE, ORGANIZATION_ADD_RESOURCE_QUANTITY, - ORGANIZATION_REMOVE_RESOURCE_QUANTITY + ORGANIZATION_REMOVE_RESOURCE_QUANTITY, + ORGANIZATION_PRODUCT_CREATE, + ORGANIZATION_PRODUCT_UPDATE, + ORGANIZATION_PRODUCT_DISASSEMBLY } diff --git a/src/main/java/jewellery/inventory/model/resource/ResourceInProduct.java b/src/main/java/jewellery/inventory/model/resource/ResourceInProduct.java index d925e2ad..6262d188 100644 --- a/src/main/java/jewellery/inventory/model/resource/ResourceInProduct.java +++ b/src/main/java/jewellery/inventory/model/resource/ResourceInProduct.java @@ -1,11 +1,11 @@ package jewellery.inventory.model.resource; +import java.math.BigDecimal; +import java.util.UUID; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; -import java.math.BigDecimal; -import java.util.UUID; import jewellery.inventory.model.Product; import lombok.Getter; import lombok.Setter; @@ -14,9 +14,12 @@ @Getter @Setter public class ResourceInProduct { - @Id @GeneratedValue private UUID id; + @Id + @GeneratedValue + private UUID id; - @ManyToOne private Resource resource; + @ManyToOne + private Resource resource; private BigDecimal quantity; diff --git a/src/main/java/jewellery/inventory/service/ProductInOrganizationService.java b/src/main/java/jewellery/inventory/service/ProductInOrganizationService.java new file mode 100644 index 00000000..e7e75ee8 --- /dev/null +++ b/src/main/java/jewellery/inventory/service/ProductInOrganizationService.java @@ -0,0 +1,310 @@ +package jewellery.inventory.service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import jewellery.inventory.aspect.EntityFetcher; +import jewellery.inventory.aspect.annotation.LogCreateEvent; +import jewellery.inventory.aspect.annotation.LogDeleteEvent; +import jewellery.inventory.aspect.annotation.LogUpdateEvent; +import jewellery.inventory.dto.request.ProductRequestDto; +import jewellery.inventory.dto.request.resource.ResourceQuantityRequestDto; +import jewellery.inventory.dto.response.ProductsInOrganizationResponseDto; +import jewellery.inventory.exception.invalid_resource_quantity.InsufficientResourceQuantityException; +import jewellery.inventory.exception.organization.OrganizationNotOwnerException; +import jewellery.inventory.exception.organization.ProductIsNotPartOfOrganizationException; +import jewellery.inventory.mapper.ProductInOrganizationMapper; +import jewellery.inventory.model.*; +import jewellery.inventory.model.resource.Resource; +import jewellery.inventory.model.resource.ResourceInProduct; +import jewellery.inventory.repository.ProductRepository; +import jewellery.inventory.repository.ResourceInProductRepository; +import lombok.AllArgsConstructor; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@AllArgsConstructor +public class ProductInOrganizationService implements EntityFetcher { + private static final Logger logger = LogManager.getLogger(ProductInOrganizationService.class); + private final OrganizationService organizationService; + private final ProductService productService; + private final ProductInOrganizationMapper mapper; + private final ResourceInOrganizationService resourceInOrganizationService; + private final ResourceInProductRepository resourceInProductRepository; + private final ProductRepository productRepository; + + public ProductsInOrganizationResponseDto getProductsInOrganization(UUID organizationId) { + Organization organization = organizationService.getOrganization(organizationId); + organizationService.validateUserInOrganization(organization); + + return mapper.mapToProductsInOrganizationResponseDto( + organization, productService.getProductsResponse(organization.getProductsOwned())); + } + + @Transactional + @LogUpdateEvent(eventType = EventType.ORGANIZATION_PRODUCT_UPDATE) + public ProductsInOrganizationResponseDto updateProduct( + UUID productId, ProductRequestDto productRequestDto) { + + Organization organization = organizationService.getOrganization(productRequestDto.getOwnerId()); + + organizationService.validateCurrentUserPermission( + organization, OrganizationPermission.EDIT_PRODUCT); + + Product product = productService.getProduct(productId); + throwExceptionIfOrganizationNotOwner(organization.getId(), product); + productService.throwExceptionIfProductIsSold(product); + moveQuantityFromResourcesInProductToResourcesInOrganization(product); + productService.disassembleProductContent(product); + + setProductFields(productRequestDto, organization, product); + productRepository.save(product); + + return addProductContents(organization, productRequestDto, product); + } + + @Transactional + @LogCreateEvent(eventType = EventType.ORGANIZATION_PRODUCT_CREATE) + public ProductsInOrganizationResponseDto createProductInOrganization( + ProductRequestDto productRequestDto) { + Organization organization = organizationService.getOrganization(productRequestDto.getOwnerId()); + + organizationService.validateCurrentUserPermission( + organization, OrganizationPermission.CREATE_PRODUCT); + + Product product = persistProductWithoutResourcesAndProducts(productRequestDto, organization); + + return addProductContents(organization, productRequestDto, product); + } + + @Transactional + @LogDeleteEvent(eventType = EventType.ORGANIZATION_PRODUCT_DISASSEMBLY) + public void deleteProductInOrganization(UUID productId) { + Product product = productService.getProduct(productId); + validateProductIsOwnedOrganization(product); + Organization organization = product.getOrganization(); + + organizationService.validateCurrentUserPermission( + organization, OrganizationPermission.DISASSEMBLE_PRODUCT); + + productService.throwExceptionIfProductIsSold(product); + productService.throwExceptionIfProductIsPartOfAnotherProduct(productId, product); + + moveQuantityFromResourcesInProductToResourcesInOrganization(product); + + productService.disassembleProductContent(product); + productService.deleteProductById(productId); + } + + private void validateProductIsOwnedOrganization(Product product) { + if (product.getOrganization() == null) { + throw new ProductIsNotPartOfOrganizationException(product.getId()); + } + } + + private ProductsInOrganizationResponseDto addProductContents( + Organization organization, ProductRequestDto productRequestDto, Product product) { + addProductsContentToProduct(productRequestDto, product); + addResourcesToProduct(productRequestDto, organization, product); + + return mapper.mapToProductsInOrganizationResponseDto( + organization, productService.getProductsResponse(List.of(product))); + } + + private Product persistProductWithoutResourcesAndProducts( + ProductRequestDto productRequestDto, Organization organization) { + Product product = getProductWithoutResourcesAndProduct(productRequestDto, organization); + productService.saveProduct(product); + return product; + } + + private Product getProductWithoutResourcesAndProduct( + ProductRequestDto productRequestDto, Organization organization) { + logger.debug("Creating product without resources and products"); + Product product = new Product(); + setProductFields(productRequestDto, organization, product); + return product; + } + + private void setProductFields( + ProductRequestDto productRequestDto, Organization organization, Product product) { + product.setOwner(null); + product.setOrganization(organization); + product.setAuthors(productService.getAuthors(productRequestDto)); + product.setPartOfSale(null); + product.setDescription(productRequestDto.getDescription()); + product.setProductionNumber(productRequestDto.getProductionNumber()); + product.setCatalogNumber(productRequestDto.getCatalogNumber()); + product.setAdditionalPrice(productRequestDto.getAdditionalPrice()); + product.setProductsContent(new ArrayList<>()); + product.setResourcesContent(new ArrayList<>()); + logger.debug("Product fields have been set successfully for product: {}", product); + } + + private void addProductsContentToProduct(ProductRequestDto productRequestDto, Product product) { + if (productRequestDto.getProductsContent() != null) { + product.setProductsContent( + getProductsInProduct(productRequestDto.getProductsContent(), product)); + logger.debug("Products content added successfully to product: {}", product); + productService.saveProduct(product); + } + } + + private List getProductsInProduct( + List productsIdInRequest, Product parentProduct) { + List products = new ArrayList<>(); + if (productsIdInRequest != null) { + productsIdInRequest.forEach( + productId -> { + Product product = productService.getProduct(productId); + productService.throwExceptionIfProductIsPartOfItself(product, parentProduct.getId()); + productService.throwExceptionIfProductIsSold(product); + if ((product.getOrganization() != null) + && parentProduct + .getOrganization() + .getId() + .equals(product.getOrganization().getId())) { + product.setContentOf(parentProduct); + products.add(product); + logger.debug("Added product '{}' to the list.", product); + } else { + logger.error( + "Organization with ID '{}' is not the owner of product with ID '{}'.", + parentProduct.getOrganization().getId(), + product.getId()); + throw new OrganizationNotOwnerException( + parentProduct.getOrganization().getId(), product.getId()); + } + }); + } + logger.debug("Products in product retrieved successfully."); + return products; + } + + private void addResourcesToProduct( + ProductRequestDto productRequestDto, Organization organization, Product product) { + + List resourcesInProducts = + transferResourcesQuantitiesFromOrganizationToProduct( + organization, productRequestDto.getResourcesContent(), product); + logger.debug("Resources added successfully to product: {}", product); + + product.setResourcesContent(resourcesInProducts); + } + + private List transferResourcesQuantitiesFromOrganizationToProduct( + Organization organization, + List incomingResourceInProductList, + Product product) { + List resourcesForAdd = new ArrayList<>(); + + for (ResourceQuantityRequestDto resourceQuantity : incomingResourceInProductList) { + resourcesForAdd.add( + transferSingleResourceQuantityFromOrganizationToProduct( + organization, resourceQuantity, product)); + } + logger.debug("Resources quantities transferred successfully from organization to product."); + return resourcesForAdd; + } + + private ResourceInProduct transferSingleResourceQuantityFromOrganizationToProduct( + Organization organization, + ResourceQuantityRequestDto incomingResourceInProduct, + Product product) { + logger.debug( + "Transferring single resource quantity from organization to product for product: {}", + product); + + ResourceInOrganization resourceInOrganization = + resourceInOrganizationService.findResourceInOrganizationOrThrow( + organization, incomingResourceInProduct.getResourceId()); + + checkResourceAvailability(resourceInOrganization, incomingResourceInProduct); + + resourceInOrganizationService.removeQuantityFromResource( + organization.getId(), + incomingResourceInProduct.getResourceId(), + incomingResourceInProduct.getQuantity()); + + logger.debug( + "Quantity '{}' of resource '{}' removed from organization '{}'.", + incomingResourceInProduct.getQuantity(), + resourceInOrganization.getResource(), + organization.getName()); + + return createResourceInProduct( + incomingResourceInProduct.getQuantity(), resourceInOrganization.getResource(), product); + } + + private ResourceInProduct createResourceInProduct( + BigDecimal quantity, Resource resource, Product product) { + ResourceInProduct resourceInProduct = new ResourceInProduct(); + resourceInProduct.setResource(resource); + resourceInProduct.setQuantity(quantity); + resourceInProduct.setProduct(product); + logger.debug("ResourceInProduct created successfully for product: {}", product); + return resourceInProduct; + } + + private void checkResourceAvailability( + ResourceInOrganization resourceInOrganization, + ResourceQuantityRequestDto incomingResourceInProduct) { + if (resourceInOrganization.getQuantity().compareTo(incomingResourceInProduct.getQuantity()) + < 0) { + logger.error( + "Insufficient quantity of resource '{}' in organization. Requested: {}, Available: {}", + resourceInOrganization.getResource(), + incomingResourceInProduct.getQuantity(), + resourceInOrganization.getQuantity()); + + throw new InsufficientResourceQuantityException( + incomingResourceInProduct.getQuantity(), resourceInOrganization.getQuantity()); + } + } + + private void throwExceptionIfOrganizationNotOwner(UUID organizationId, Product product) { + if (!organizationId.equals(product.getOrganization().getId())) { + logger.error( + "Organization with ID '{}' is not the owner of product with ID '{}'.", + organizationId, + product.getId()); + throw new OrganizationNotOwnerException(organizationId, product.getId()); + } + } + + private void moveQuantityFromResourcesInProductToResourcesInOrganization(Product product) { + List resourcesInProduct = product.getResourcesContent(); + resourcesInProduct.forEach( + resourceInProduct -> { + logger.info( + "Adding resource: {} to organization: {} with quantity {}", + resourceInProduct.getResource(), + product.getOrganization(), + resourceInProduct.getQuantity()); + resourceInOrganizationService.addResourceToOrganization( + product.getOrganization(), + resourceInProduct.getResource(), + resourceInProduct.getQuantity(), + BigDecimal.ZERO); + + resourceInProduct.setProduct(null); + resourceInProductRepository.delete(resourceInProduct); + logger.info("Resource deleted from product: {}", product); + }); + product.setResourcesContent(null); + } + + @Override + public Object fetchEntity(Object... ids) { + Product product = productRepository.findById((UUID) ids[0]).orElse(null); + if (product == null || product.getOrganization() == null) { + return null; + } + return mapper.mapToProductsInOrganizationResponseDto( + product.getOrganization(), productService.getProductsResponse(List.of(product))); + } +} diff --git a/src/main/java/jewellery/inventory/service/ProductService.java b/src/main/java/jewellery/inventory/service/ProductService.java index b6d8e6c6..c80f0181 100644 --- a/src/main/java/jewellery/inventory/service/ProductService.java +++ b/src/main/java/jewellery/inventory/service/ProductService.java @@ -86,6 +86,10 @@ public List getAllProducts() { return products.stream().map(productMapper::mapToProductResponseDto).toList(); } + public List getProductsResponse(List products) { + return products.stream().map(productMapper::mapToProductResponseDto).toList(); + } + public List getByOwner(UUID ownerId) { List products = productRepository.findAllByOwnerId(ownerId); logger.info("Get product by owner with ID: {}", ownerId); @@ -102,6 +106,10 @@ public ProductResponseDto getProductResponse(UUID id) { return productMapper.mapToProductResponseDto(getProduct(id)); } + public Product saveProduct(Product product) { + return productRepository.save(product); + } + public void updateProductOwnerAndSale(Product product, User newOwner, Sale sale) { updateProductOwnerRecursively(product, newOwner); if (sale == null) { @@ -153,6 +161,9 @@ public void deleteProduct(UUID id) throws IOException { productRepository.deleteById(id); logger.info("Deleted product by ID: {}", id); } + public void deleteProductById(UUID productId){ + productRepository.deleteById(productId); + } @LogUpdateEvent(eventType = EventType.PRODUCT_TRANSFER) public ProductResponseDto transferProduct(UUID productId, UUID recipientId) { @@ -170,7 +181,7 @@ private void deleteImageWhenAttached(UUID id, Product product) throws IOExceptio } } - private void throwExceptionIfProductIsPartOfAnotherProduct(UUID id, Product product) { + public void throwExceptionIfProductIsPartOfAnotherProduct(UUID id, Product product) { if (product.getContentOf() != null) { throw new ProductIsContentException(id); } @@ -182,13 +193,13 @@ private void throwExceptionIfProductOwnerEqualsRecipient(Product product, UUID r } } - private void throwExceptionIfProductIsSold(Product product) { + public void throwExceptionIfProductIsSold(Product product) { if (product.getPartOfSale() != null) { throw new ProductIsSoldException(product.getId()); } } - private void disassembleProductContent(Product product) { + public void disassembleProductContent(Product product) { if (product.getProductsContent() != null) { logger.debug("Disassembling product content for product with ID: {}", product.getId()); @@ -280,7 +291,7 @@ private List getProductsInProduct( return products; } - private void throwExceptionIfProductIsPartOfItself(Product product, UUID parentId) { + public void throwExceptionIfProductIsPartOfItself(Product product, UUID parentId) { if (product.getId().equals(parentId)) { throw new ProductPartOfItselfException(); } @@ -321,7 +332,7 @@ private void setProductFields(ProductRequestDto productRequestDto, User user, Pr product.setResourcesContent(new ArrayList<>()); } - private List getAuthors(ProductRequestDto productRequestDto) { + public List getAuthors(ProductRequestDto productRequestDto) { logger.debug("Getting authors for product."); List authorsIds = productRequestDto.getAuthors(); List authors = new ArrayList<>(); @@ -383,7 +394,8 @@ private ResourceInProduct transferSingleResourceQuantityFromUserToProduct( owner.getId(), product.getId()); - ResourceInUser resourceInUser = getResourceInUser(owner, incomingResourceInProduct.getResourceId()); + ResourceInUser resourceInUser = + getResourceInUser(owner, incomingResourceInProduct.getResourceId()); resourceInUserService.removeQuantityFromResourceNoLog( owner.getId(), resourceInUser.getResource().getId(), diff --git a/src/main/java/jewellery/inventory/service/ResourceInOrganizationService.java b/src/main/java/jewellery/inventory/service/ResourceInOrganizationService.java index 9e84ded3..3e070903 100644 --- a/src/main/java/jewellery/inventory/service/ResourceInOrganizationService.java +++ b/src/main/java/jewellery/inventory/service/ResourceInOrganizationService.java @@ -26,7 +26,6 @@ public class ResourceInOrganizationService implements EntityFetcher { private static final Logger logger = LogManager.getLogger(ResourceInOrganizationService.class); private final ResourceInOrganizationRepository resourceInOrganizationRepository; - private final UserInOrganizationService userInOrganizationService; private final OrganizationService organizationService; private final ResourceService resourceService; private final ResourceInOrganizationMapper resourceInOrganizationMapper; @@ -39,6 +38,7 @@ public ResourcesInOrganizationResponseDto addResourceToOrganization( ResourceInOrganizationRequestDto resourceInOrganizationRequestDto) { Organization organization = organizationService.getOrganization(resourceInOrganizationRequestDto.getOrganizationId()); + organizationService.validateCurrentUserPermission( organization, OrganizationPermission.ADD_RESOURCE_QUANTITY); @@ -103,7 +103,7 @@ private void removeQuantityFromResource( logger.debug("ResourceInOrganization after quantity removal: {}", resourceInOrganization); } - private ResourceInOrganization findResourceInOrganizationOrThrow( + public ResourceInOrganization findResourceInOrganizationOrThrow( Organization previousOwner, UUID resourceId) { return findResourceInOrganization(previousOwner, resourceId) .orElseThrow( @@ -150,7 +150,7 @@ private ResourceInOrganization getResourceInOrganization( () -> createAndAddNewResourceInOrganization(organization, resource, BigDecimal.ZERO)); } - private ResourceInOrganization addResourceToOrganization( + public ResourceInOrganization addResourceToOrganization( Organization organization, Resource resource, BigDecimal quantity, BigDecimal dealPrice) { logger.info( "Adding resource to organization. Organization: {}, Resource: {}, Quantity: {}", diff --git a/src/test/java/jewellery/inventory/helper/OrganizationTestHelper.java b/src/test/java/jewellery/inventory/helper/OrganizationTestHelper.java index 73c22a89..0a3b6201 100644 --- a/src/test/java/jewellery/inventory/helper/OrganizationTestHelper.java +++ b/src/test/java/jewellery/inventory/helper/OrganizationTestHelper.java @@ -5,10 +5,7 @@ import jewellery.inventory.dto.request.OrganizationRequestDto; import jewellery.inventory.dto.request.UserInOrganizationRequestDto; import jewellery.inventory.dto.response.*; -import jewellery.inventory.model.Organization; -import jewellery.inventory.model.OrganizationPermission; -import jewellery.inventory.model.User; -import jewellery.inventory.model.UserInOrganization; +import jewellery.inventory.model.*; public class OrganizationTestHelper { private static final String ORGANIZATION_NAME = "Test Name"; @@ -24,7 +21,16 @@ public static Organization getTestOrganization() { return organization; } - public static Organization getOrganizationWithUserWithNoPermissions(Organization organization, User user) { + public static Organization setProductAndResourcesToOrganization(Organization organization, Product product, ResourceInOrganization resourceInOrganization) { + product.setOrganization(organization); + organization.setProductsOwned(new ArrayList<>()); + organization.getProductsOwned().add(product); + organization.setResourceInOrganization(List.of(resourceInOrganization)); + return organization; + } + + public static Organization getOrganizationWithUserWithNoPermissions( + Organization organization, User user) { organization.setUsersInOrganization( List.of(new UserInOrganization(UUID.randomUUID(), user, organization, new ArrayList<>()))); return organization; diff --git a/src/test/java/jewellery/inventory/helper/ProductTestHelper.java b/src/test/java/jewellery/inventory/helper/ProductTestHelper.java index f9f5bbb1..5a24c7a8 100644 --- a/src/test/java/jewellery/inventory/helper/ProductTestHelper.java +++ b/src/test/java/jewellery/inventory/helper/ProductTestHelper.java @@ -39,6 +39,23 @@ public static ProductRequestDto getProductRequestDto( return productRequestDto; } + public static ProductRequestDto getProductRequestDtoForOrganization( + User author,UUID organizationId,UUID resourceId, + BigDecimal quantity) { + ProductRequestDto productRequestDto = new ProductRequestDto(); + productRequestDto.setOwnerId(organizationId); + productRequestDto.setProductionNumber("1234"); + productRequestDto.setCatalogNumber("1"); + productRequestDto.setAuthors(List.of(author.getId())); + productRequestDto.setDescription("This is test product"); + productRequestDto.setAdditionalPrice(BigDecimal.ZERO); + ResourceQuantityRequestDto resourceQuantityRequestDto = new ResourceQuantityRequestDto(); + resourceQuantityRequestDto.setResourceId(resourceId); + resourceQuantityRequestDto.setQuantity(quantity); + productRequestDto.setResourcesContent(List.of(resourceQuantityRequestDto)); + return productRequestDto; + } + @NotNull public static ProductRequestDto getProductRequestDto( ResourcesInUserResponseDto resourcesInUser, User user) { @@ -74,8 +91,9 @@ public static Product getTestProduct(User user, Resource pearl) { testProduct.setOwner(user); testProduct.setDescription("This is Test Product"); testProduct.setResourcesContent(List.of(getResourceInProduct(pearl))); - testProduct.setProductsContent(null); + testProduct.setProductsContent(new ArrayList<>()); testProduct.setContentOf(null); + testProduct.setResourcesContent(new ArrayList<>()); testProduct.setAdditionalPrice(BigDecimal.TEN); return testProduct; } diff --git a/src/test/java/jewellery/inventory/helper/ResourceInOrganizationTestHelper.java b/src/test/java/jewellery/inventory/helper/ResourceInOrganizationTestHelper.java index 7c64ea71..a22deca2 100644 --- a/src/test/java/jewellery/inventory/helper/ResourceInOrganizationTestHelper.java +++ b/src/test/java/jewellery/inventory/helper/ResourceInOrganizationTestHelper.java @@ -25,7 +25,7 @@ public static ResourceInOrganization createResourceInOrganization( .id(UUID.randomUUID()) .organization(organization) .resource(resource) - .quantity(BigDecimal.TEN) + .quantity(BigDecimal.valueOf(100)) .dealPrice(BigDecimal.ONE) .build(); } diff --git a/src/test/java/jewellery/inventory/integration/ProductInOrganizationCrudIntegrationTest.java b/src/test/java/jewellery/inventory/integration/ProductInOrganizationCrudIntegrationTest.java new file mode 100644 index 00000000..d08e55d9 --- /dev/null +++ b/src/test/java/jewellery/inventory/integration/ProductInOrganizationCrudIntegrationTest.java @@ -0,0 +1,280 @@ +package jewellery.inventory.integration; + +import static jewellery.inventory.helper.ResourceTestHelper.getPearlRequestDto; +import static jewellery.inventory.helper.SystemEventTestHelper.getCreateOrDeleteEventPayload; +import static jewellery.inventory.helper.SystemEventTestHelper.getUpdateEventPayload; +import static jewellery.inventory.model.EventType.*; +import static jewellery.inventory.utils.BigDecimalUtil.getBigDecimal; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import jewellery.inventory.dto.request.*; +import jewellery.inventory.dto.request.resource.ResourceQuantityRequestDto; +import jewellery.inventory.dto.request.resource.ResourceRequestDto; +import jewellery.inventory.dto.response.*; +import jewellery.inventory.dto.response.resource.ResourceResponseDto; +import jewellery.inventory.helper.*; +import jewellery.inventory.model.User; +import jewellery.inventory.model.resource.PreciousStone; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +class ProductInOrganizationCrudIntegrationTest extends AuthenticatedIntegrationTestBase { + private static final BigDecimal RESOURCE_QUANTITY = getBigDecimal("100"); + private static final BigDecimal RESOURCE_PRICE = getBigDecimal("105"); + + private String getBaseResourceAvailabilityUrl() { + return buildUrl("organizations", "resources-availability"); + } + + private String getBaseResourceUrl() { + return buildUrl("resources"); + } + + private String buildUrl(String... paths) { + return "/" + String.join("/", paths); + } + + private String getBaseOrganizationUrl() { + return buildUrl("organizations"); + } + + private String getProductUrl(UUID id) { + return "/products/" + id; + } + + private String getOrganizationProductsUrl(String organizationId) { + return buildUrl("organizations", organizationId, "products"); + } + + private PreciousStone preciousStone; + private ProductRequestDto productRequestDto; + private OrganizationResponseDto organization; + + @BeforeEach + void setUp() { + User user = createUserInDatabase(UserTestHelper.createTestUserRequest()); + organization = createOrganization(); + preciousStone = createPreciousStoneInDatabase(); + productRequestDto = + ProductTestHelper.getProductRequestDtoForOrganization( + user, organization.getId(), preciousStone.getId(), RESOURCE_QUANTITY); + } + + @Test + void getAllProductsFromOrganizationSuccessfully() { + OrganizationResponseDto organizationResponseDto = createOrganization(); + + ResponseEntity response = + this.testRestTemplate.exchange( + getOrganizationProductsUrl(organizationResponseDto.getId().toString()), + HttpMethod.GET, + null, + ProductsInOrganizationResponseDto.class); + + assertEquals(HttpStatus.OK, response.getStatusCode()); + } + + @Test + void createProductInOrganizationSuccessfully() throws JsonProcessingException { + OrganizationResponseDto organizationResponseDto = createOrganization(); + ResourceResponseDto resourceResponse = sendCreateResourceRequest(); + ResourceInOrganizationRequestDto resourceInOrganizationRequest = + ResourceInOrganizationTestHelper.createResourceInOrganizationRequestDto( + organizationResponseDto.getId(), + resourceResponse.getId(), + RESOURCE_QUANTITY, + RESOURCE_PRICE); + ResponseEntity resource = + sendResourceToOrganization(resourceInOrganizationRequest); + assertProductsInOrganizationSize(organizationResponseDto.getId().toString(), 0); + + ResponseEntity productInOrganizationResponse = + createProduct( + setOwnerAndResourceToProductRequest( + productRequestDto, + organizationResponseDto.getId(), + resourceResponse.getId(), + RESOURCE_QUANTITY)); + + assertNotNull(productInOrganizationResponse.getBody()); + assertEquals(1, productInOrganizationResponse.getBody().getProducts().size()); + assertEquals(HttpStatus.CREATED, productInOrganizationResponse.getStatusCode()); + Map expectedEventPayload = + getCreateOrDeleteEventPayload(productInOrganizationResponse.getBody(), objectMapper); + systemEventTestHelper.assertEventWasLogged(ORGANIZATION_PRODUCT_CREATE, expectedEventPayload); + assertProductsInOrganizationSize(organizationResponseDto.getId().toString(), 1); + } + + @Test + void updateProductInOrganizationSuccessfully() throws JsonProcessingException { + OrganizationResponseDto organizationResponseDto = createOrganization(); + ResourceResponseDto resourceResponse = sendCreateResourceRequest(); + ResourceInOrganizationRequestDto resourceInOrganizationRequest = + ResourceInOrganizationTestHelper.createResourceInOrganizationRequestDto( + organizationResponseDto.getId(), + resourceResponse.getId(), + RESOURCE_QUANTITY, + RESOURCE_PRICE); + ResponseEntity resource = + sendResourceToOrganization(resourceInOrganizationRequest); + ResponseEntity resource2 = + sendResourceToOrganization(resourceInOrganizationRequest); + ResponseEntity productInOrganizationResponse = + createProduct( + setOwnerAndResourceToProductRequest( + productRequestDto, + organizationResponseDto.getId(), + resourceResponse.getId(), + RESOURCE_QUANTITY)); + + ResponseEntity updatedProductInOrganizationResponse = + updateProduct( + productRequestDto, + productInOrganizationResponse.getBody().getProducts().get(0).getId().toString()); + + assertEquals(HttpStatus.OK, updatedProductInOrganizationResponse.getStatusCode()); + Map expectedEventPayload = + getUpdateEventPayload( + productInOrganizationResponse.getBody(), + Objects.requireNonNull(updatedProductInOrganizationResponse.getBody()), + objectMapper); + systemEventTestHelper.assertEventWasLogged(ORGANIZATION_PRODUCT_UPDATE, expectedEventPayload); + assertProductsInOrganizationSize(organizationResponseDto.getId().toString(), 1); + } + + @Test + void deleteProductInOrganizationSuccessfully() throws JsonProcessingException { + sendResourceToOrganization( + ResourceInOrganizationTestHelper.createResourceInOrganizationRequestDto( + organization.getId(), preciousStone.getId(), RESOURCE_QUANTITY, RESOURCE_PRICE)); + ResponseEntity productInOrganizationResponse = + createProduct( + setOwnerAndResourceToProductRequest( + productRequestDto, organization.getId(), preciousStone.getId(), RESOURCE_QUANTITY)); + UUID productId = productInOrganizationResponse.getBody().getProducts().get(0).getId(); + + ResponseEntity response = + this.testRestTemplate.exchange( + getBaseOrganizationUrl() + getProductUrl(productId), + HttpMethod.DELETE, + null, + String.class); + + assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode()); + Map expectedEventPayload = + getCreateOrDeleteEventPayload(productInOrganizationResponse.getBody(), objectMapper); + systemEventTestHelper.assertEventWasLogged( + ORGANIZATION_PRODUCT_DISASSEMBLY, expectedEventPayload); + assertProductsInOrganizationSize( + productInOrganizationResponse.getBody().getOrganization().getId().toString(), 0); + } + + private void assertProductsInOrganizationSize(String organizationId, int assertSize) { + ResponseEntity organizationProductsResponse = + this.testRestTemplate.exchange( + getOrganizationProductsUrl(organizationId), + HttpMethod.GET, + null, + ProductsInOrganizationResponseDto.class); + + assertEquals(assertSize, organizationProductsResponse.getBody().getProducts().size()); + } + + private OrganizationResponseDto createOrganization() { + OrganizationRequestDto organizationRequestDto = + OrganizationTestHelper.getTestOrganizationRequest(); + ResponseEntity response = + this.testRestTemplate.postForEntity( + getBaseOrganizationUrl(), organizationRequestDto, OrganizationResponseDto.class); + + OrganizationResponseDto organizationResponseDto = response.getBody(); + assertNotNull(organizationResponseDto); + return organizationResponseDto; + } + + private ResourceResponseDto sendCreateResourceRequest() { + ResourceRequestDto resourceRequest = getPearlRequestDto(); + ResponseEntity resourceResponseEntity = + this.testRestTemplate.postForEntity( + getBaseResourceUrl(), resourceRequest, ResourceResponseDto.class); + + assertEquals(HttpStatus.CREATED, resourceResponseEntity.getStatusCode()); + + ResourceResponseDto createdResource = resourceResponseEntity.getBody(); + assertNotNull(createdResource); + assertNotNull(createdResource.getId()); + return createdResource; + } + + private ResponseEntity sendResourceToOrganization( + ResourceInOrganizationRequestDto resourceInOrganizationRequest) { + return this.testRestTemplate.postForEntity( + getBaseResourceAvailabilityUrl(), + resourceInOrganizationRequest, + ResourcesInOrganizationResponseDto.class); + } + + @Nullable + private ResponseEntity createProduct( + ProductRequestDto productRequestDto) { + return this.testRestTemplate.postForEntity( + getBaseOrganizationUrl() + "/products", + productRequestDto, + ProductsInOrganizationResponseDto.class); + } + + @Nullable + private ResponseEntity updateProduct( + ProductRequestDto productRequestDto, String productId) { + + HttpEntity requestEntity = new HttpEntity<>(productRequestDto, headers); + + return this.testRestTemplate.exchange( + getBaseOrganizationUrl() + "/products/" + productId, + HttpMethod.PUT, + requestEntity, + ProductsInOrganizationResponseDto.class); + } + + @Nullable + private PreciousStone createPreciousStoneInDatabase() { + ResourceRequestDto resourceRequest = ResourceTestHelper.getPreciousStoneRequestDto(); + ResponseEntity createResource = + this.testRestTemplate.postForEntity( + getBaseResourceUrl(), resourceRequest, PreciousStone.class); + + return createResource.getBody(); + } + + @Nullable + private User createUserInDatabase(UserRequestDto userRequestDto) { + ResponseEntity createUser = + this.testRestTemplate.postForEntity("/users", userRequestDto, User.class); + return createUser.getBody(); + } + + private ProductRequestDto setOwnerAndResourceToProductRequest( + ProductRequestDto productRequestDto, + UUID organizationId, + UUID resourceId, + BigDecimal quantity) { + productRequestDto.setOwnerId(organizationId); + ResourceQuantityRequestDto resourceQuantityRequestDto = new ResourceQuantityRequestDto(); + resourceQuantityRequestDto.setResourceId(resourceId); + resourceQuantityRequestDto.setQuantity(quantity); + productRequestDto.setResourcesContent(List.of(resourceQuantityRequestDto)); + return productRequestDto; + } +} diff --git a/src/test/java/jewellery/inventory/unit/service/ProductInOrganizationServiceTest.java b/src/test/java/jewellery/inventory/unit/service/ProductInOrganizationServiceTest.java new file mode 100644 index 00000000..a508e8b3 --- /dev/null +++ b/src/test/java/jewellery/inventory/unit/service/ProductInOrganizationServiceTest.java @@ -0,0 +1,161 @@ +package jewellery.inventory.unit.service; + +import static jewellery.inventory.helper.OrganizationTestHelper.*; +import static jewellery.inventory.helper.ProductTestHelper.getProductRequestDtoForOrganization; +import static jewellery.inventory.helper.ProductTestHelper.getTestProduct; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import jewellery.inventory.dto.request.ProductRequestDto; +import jewellery.inventory.dto.response.ProductResponseDto; +import jewellery.inventory.dto.response.ProductsInOrganizationResponseDto; +import jewellery.inventory.helper.*; +import jewellery.inventory.mapper.ProductInOrganizationMapper; +import jewellery.inventory.model.Organization; +import jewellery.inventory.model.Product; +import jewellery.inventory.model.ResourceInOrganization; +import jewellery.inventory.model.User; +import jewellery.inventory.model.resource.Resource; +import jewellery.inventory.repository.ProductRepository; +import jewellery.inventory.repository.ResourceInProductRepository; +import jewellery.inventory.service.OrganizationService; +import jewellery.inventory.service.ProductInOrganizationService; +import jewellery.inventory.service.ProductService; +import jewellery.inventory.service.ResourceInOrganizationService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class ProductInOrganizationServiceTest { + @InjectMocks private ProductInOrganizationService productInOrganizationService; + @Mock private OrganizationService organizationService; + @Mock private ProductService productService; + @Mock private ProductRepository productRepository; + @Mock private ProductInOrganizationMapper mapper; + @Mock private ResourceInOrganizationService resourceInOrganizationService; + @Mock private ResourceInProductRepository resourceInProductRepository; + private static final BigDecimal QUANTITY = BigDecimal.valueOf(30); + + private Organization organization; + private Organization organizationWithProduct; + private ResourceInOrganization resourceInOrganization; + private ProductRequestDto productRequestDto; + private ProductRequestDto productWithProductRequestDto; + private Product product; + private ProductsInOrganizationResponseDto productsInOrganizationResponseDto; + + @BeforeEach + void setUp() { + + User user = UserTestHelper.createSecondTestUser(); + organization = OrganizationTestHelper.getTestOrganization(); + Resource resource = ResourceTestHelper.getPearl(); + product = getTestProduct(user, resource); + resourceInOrganization = + ResourceInOrganizationTestHelper.createResourceInOrganization(organization, resource); + organization.setResourceInOrganization(List.of(resourceInOrganization)); + productRequestDto = + getProductRequestDtoForOrganization(user, organization.getId(), user.getId(), QUANTITY); + productWithProductRequestDto = + getProductRequestDtoForOrganization(user, organization.getId(), user.getId(), QUANTITY); + productWithProductRequestDto.setProductsContent(List.of(product.getId())); + organizationWithProduct = + setProductAndResourcesToOrganization( + OrganizationTestHelper.getTestOrganization(), product, resourceInOrganization); + productsInOrganizationResponseDto = + new ProductsInOrganizationResponseDto( + getTestOrganizationResponseDto(OrganizationTestHelper.getTestOrganization()), + List.of(productToResponse(product))); + } + + @Test + void getAllProductsInOrganizationSuccessfully() { + when(organizationService.getOrganization(organizationWithProduct.getId())) + .thenReturn(organizationWithProduct); + when(mapper.mapToProductsInOrganizationResponseDto(organizationWithProduct, new ArrayList<>())) + .thenReturn(productsInOrganizationResponseDto); + + ProductsInOrganizationResponseDto products = + productInOrganizationService.getProductsInOrganization(organizationWithProduct.getId()); + + assertNotNull(products); + assertEquals(1, products.getProducts().size()); + } + + @Test + void createProductInOrganizationSuccessfully() { + when(organizationService.getOrganization(organization.getId())).thenReturn(organization); + when(resourceInOrganizationService.findResourceInOrganizationOrThrow( + organization, productRequestDto.getResourcesContent().get(0).getResourceId())) + .thenReturn(resourceInOrganization); + when(mapper.mapToProductsInOrganizationResponseDto(organization, new ArrayList<>())) + .thenReturn(productsInOrganizationResponseDto); + + ProductsInOrganizationResponseDto productsInOrganizationResponse = + productInOrganizationService.createProductInOrganization(productRequestDto); + + assertNotNull(productsInOrganizationResponse); + assertEquals(1, productsInOrganizationResponse.getProducts().size()); + } + + @Test + void createProductWithProductInOrganizationSuccessfully() { + when(organizationService.getOrganization(organization.getId())).thenReturn(organization); + when(resourceInOrganizationService.findResourceInOrganizationOrThrow( + organization, + productWithProductRequestDto.getResourcesContent().get(0).getResourceId())) + .thenReturn(resourceInOrganization); + product.setOrganization(organization); + when(mapper.mapToProductsInOrganizationResponseDto(organization, new ArrayList<>())) + .thenReturn(productsInOrganizationResponseDto); + when(productService.getProduct(any(UUID.class))).thenReturn(product); + + ProductsInOrganizationResponseDto productsInOrganizationResponse = + productInOrganizationService.createProductInOrganization(productWithProductRequestDto); + + assertNotNull(productsInOrganizationResponse); + assertEquals(1, productsInOrganizationResponse.getProducts().size()); + } + + @Test + void updateProductInOrganizationSuccessfully() { + when(organizationService.getOrganization(organization.getId())).thenReturn(organization); + product.setOrganization(organization); + when(productService.getProduct(product.getId())).thenReturn(product); + when(resourceInOrganizationService.findResourceInOrganizationOrThrow( + organization, productRequestDto.getResourcesContent().get(0).getResourceId())) + .thenReturn(resourceInOrganization); + when(mapper.mapToProductsInOrganizationResponseDto(eq(organization), anyList())) + .thenReturn(productsInOrganizationResponseDto); + + ProductsInOrganizationResponseDto productsInOrganizationResponse = + productInOrganizationService.updateProduct(product.getId(), productRequestDto); + + assertNotNull(productsInOrganizationResponse); + assertEquals(1, productsInOrganizationResponse.getProducts().size()); + } + + @Test + void deleteProductInOrganizationSuccessfully() { + when(productService.getProduct(product.getId())).thenReturn(product); + + productInOrganizationService.deleteProductInOrganization(product.getId()); + + verify(productService, times(1)).deleteProductById(product.getId()); + } + + private ProductResponseDto productToResponse(Product product) { + ProductResponseDto productResponseDto = new ProductResponseDto(); + productResponseDto.setId(product.getId()); + return productResponseDto; + } +} diff --git a/src/test/java/jewellery/inventory/unit/service/ProductServiceTest.java b/src/test/java/jewellery/inventory/unit/service/ProductServiceTest.java index 313c5652..f9e2fcfb 100644 --- a/src/test/java/jewellery/inventory/unit/service/ProductServiceTest.java +++ b/src/test/java/jewellery/inventory/unit/service/ProductServiceTest.java @@ -330,7 +330,7 @@ void testUpdateProductSuccessfullyWhenProductIsPartOfAnotherProduct() { verify(userRepository,times(1)).findById(user.getId()); verify(resourceInUserRepository, times(1)) .findByResourceIdAndOwnerId(pearl.getId(), user.getId()); - verify(productRepository, times(1)).save(innerProduct); + verify(productRepository, times(2)).save(innerProduct); } @Test diff --git a/src/test/java/jewellery/inventory/unit/service/ResourceInOrganizationServiceTest.java b/src/test/java/jewellery/inventory/unit/service/ResourceInOrganizationServiceTest.java index a53b573c..f0e27d67 100644 --- a/src/test/java/jewellery/inventory/unit/service/ResourceInOrganizationServiceTest.java +++ b/src/test/java/jewellery/inventory/unit/service/ResourceInOrganizationServiceTest.java @@ -43,7 +43,7 @@ class ResourceInOrganizationServiceTest { private ResourceInOrganization resourceInOrganization; private static final BigDecimal QUANTITY = BigDecimal.ONE; private static final BigDecimal NEGATIVE_QUANTITY = BigDecimal.valueOf(-5); - private static final BigDecimal BIG_QUANTITY = BigDecimal.valueOf(30); + private static final BigDecimal BIG_QUANTITY = BigDecimal.valueOf(1000); private static final BigDecimal DEAL_PRICE = BigDecimal.TEN; @BeforeEach