Repository: de-bankly/vendura-backend-service
Pull request #11: Feature/bestandsanpassung
Author: login: lulkebit
Labels: name: enhancement
description: New feature or request
Created: 2025-04-09T13:17:48Z | Merged: 2025-04-14T09:41:36Z

This pull request includes significant changes to the user and inventory management systems. The changes involve refactoring the `UserDTO` and `UserService` classes, adding new functionalities to the inventory management system, and introducing new classes and methods to handle product stock and supplier orders.

### User Management Changes:
* [`src/main/java/com/bankly/vendura/authentication/user/UserService.java`](diffhunk://#diff-b29a4b3f63a79a9df19ae91ef638d95ac612d6b91fbcdab4d0d32bcf97d0fef6L60-R60): Simplified role handling in `createUser` and `updateUser` methods by using `Set<String>` for roles instead of `Set<RoleDTO>`. [[1]](diffhunk://#diff-b29a4b3f63a79a9df19ae91ef638d95ac612d6b91fbcdab4d0d32bcf97d0fef6L60-R60) [[2]](diffhunk://#diff-b29a4b3f63a79a9df19ae91ef638d95ac612d6b91fbcdab4d0d32bcf97d0fef6L130-R136)
* [`src/main/java/com/bankly/vendura/authentication/user/model/UserDTO.java`](diffhunk://#diff-22e645d00b54fa4f6bdc4383c99d738ce899b2a5f25cad41cd30100eb7a56927L3-R40): Added new fields (`firstName`, `lastName`, `email`) and used builder pattern for object creation.
* [`src/main/java/com/bankly/vendura/authentication/user/model/UserFactory.java`](diffhunk://#diff-567dd3228552445d27aa251377a66bc33c941861ef2c7edd5379e0744b036daeR1-R23): Introduced `UserFactory` class to handle conversion between `User` and `UserDTO`.

### Inventory Management Enhancements:
* [`src/main/java/com/bankly/vendura/inventory/product/ProductControllerV1.java`](diffhunk://#diff-3e6553f502ae3284de28e271f80c5bc89fe735b65fa22f0e8807defe3a80054aL32-R45): Enhanced `getProducts` method to include an optional parameter for calculating stock.
* [`src/main/java/com/bankly/vendura/inventory/product/ProductInventoryControllerV1.java`](diffhunk://#diff-10a719ffac3dce57064bfb006283a003962bad163900e5a01d069df6977ae0e0R1-R106): Introduced `ProductInventoryControllerV1` class with methods for managing inventory status, low stock products, stock adjustments, and reorder checks.
* [`src/main/java/com/bankly/vendura/inventory/product/ProductStockService.java`](diffhunk://#diff-bb57b7abdc8e06b71c70749a89132b5b8ac7409de7e1ebff9a807f9ae817ddacR1-R144): Added `ProductStockService` class to handle stock level checks, reordering, and stock adjustments.

### Product Model Updates:
* [`src/main/java/com/bankly/vendura/inventory/product/model/Product.java`](diffhunk://#diff-9827300387d65e01ad93840dd73384bba99d79247adb61dbb67ada894426c001R28-R53): Added new fields (`shortDescription`, `longDescription`, `sku`, `minStockLevel`, `maxStockLevel`, `reorderPoint`, `reorderQuantity`, `leadTimeInDays`, `price`, `purchasePrice`).
* [`src/main/java/com/bankly/vendura/inventory/product/model/ProductDTO.java`](diffhunk://#diff-568dfafd6217be579b63a63cf81ba35e80bcd4e2481babddcbc92e82107c11a3R22-R35): Updated `ProductDTO` to include new fields corresponding to the changes in `Product`.
* [`src/main/java/com/bankly/vendura/inventory/product/model/ProductFactory.java`](diffhunk://#diff-3ab5ae067515a628ae1b12fb1c02e2c1613293221a5ee481b0c8870e55ef34cdL14-R65): Refactored `ProductFactory` to accommodate new fields in `Product` and `ProductDTO`.

### Supplier Order Management:
* [`src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderControllerV1.java`](diffhunk://#diff-1554051a1a06ceeab50f43697a7028d75888cd7753583987aad77ba6dd4e486dR3): Added new endpoints to handle supplier orders by status, supplier ID, automatic orders, and pending orders. [[1]](diffhunk://#diff-1554051a1a06ceeab50f43697a7028d75888cd7753583987aad77ba6dd4e486dR3) [[2]](diffhunk://#diff-1554051a1a06ceeab50f43697a7028d75888cd7753583987aad77ba6dd4e486dR18-R20) [[3]](diffhunk://#diff-1554051a1a06ceeab50f43697a7028d75888cd7753583987aad77ba6dd4e486dR36-R73)

These changes aim to improve the overall functionality and maintainability of the user and inventory management systems.


Diff:
diff --git a/src/main/java/com/bankly/vendura/authentication/user/UserControllerV1.java b/src/main/java/com/bankly/vendura/authentication/user/UserControllerV1.java
index 31393ff..6e70453 100644
--- a/src/main/java/com/bankly/vendura/authentication/user/UserControllerV1.java
+++ b/src/main/java/com/bankly/vendura/authentication/user/UserControllerV1.java
@@ -1,6 +1,7 @@
 package com.bankly.vendura.authentication.user;
 
 import com.bankly.vendura.authentication.user.model.UserDTO;
+import com.bankly.vendura.authentication.user.model.UserFactory;
 import com.bankly.vendura.authentication.user.model.UserRepository;
 import com.bankly.vendura.utilities.exceptions.EntityRetrieveException;
 import lombok.RequiredArgsConstructor;
@@ -30,7 +31,7 @@ public class UserControllerV1 {
   public ResponseEntity<?> getAuthenticatedUser(Authentication authentication) {
     return ResponseEntity.ok()
         .body(
-            UserDTO.fromUser(
+            UserFactory.toDTO(
                 this.userRepository
                     .findUserByUsername(authentication.getName())
                     .orElseThrow(
@@ -50,7 +51,7 @@ public ResponseEntity<?> getAuthenticatedUser(Authentication authentication) {
   @GetMapping
   @PreAuthorize("hasRole('ADMIN')")
   public ResponseEntity<?> getAllUsersPageable(Pageable pageable) {
-    return ResponseEntity.ok().body(this.userRepository.findAll(pageable).map(UserDTO::fromUser));
+    return ResponseEntity.ok().body(this.userRepository.findAll(pageable).map(UserFactory::toDTO));
   }
 
   /**
@@ -63,7 +64,7 @@ public ResponseEntity<?> getAllUsersPageable(Pageable pageable) {
   @PreAuthorize("hasRole('ADMIN')")
   public ResponseEntity<?> getUserById(@PathVariable("id") String id) {
     return ResponseEntity.ok(
-        UserDTO.fromUser(
+        UserFactory.toDTO(
             this.userRepository
                 .findById(id)
                 .orElseThrow(
@@ -81,7 +82,7 @@ public ResponseEntity<?> getUserById(@PathVariable("id") String id) {
   @PostMapping
   @PreAuthorize("hasRole('ADMIN')")
   public ResponseEntity<?> createUser(@RequestBody UserDTO userDTO) {
-    return ResponseEntity.ok().body(UserDTO.fromUser(this.userService.createUser(userDTO)));
+    return ResponseEntity.ok().body(UserFactory.toDTO(this.userService.createUser(userDTO)));
   }
 
   /**
@@ -94,6 +95,6 @@ public ResponseEntity<?> createUser(@RequestBody UserDTO userDTO) {
   @PutMapping("/{id}")
   @PreAuthorize("hasRole('ADMIN')")
   public ResponseEntity<?> updateUser(@RequestBody UserDTO userDTO, @PathVariable("id") String id) {
-    return ResponseEntity.ok(UserDTO.fromUser(this.userService.updateUser(id, userDTO)));
+    return ResponseEntity.ok(UserFactory.toDTO(this.userService.updateUser(id, userDTO)));
   }
 }
diff --git a/src/main/java/com/bankly/vendura/authentication/user/UserService.java b/src/main/java/com/bankly/vendura/authentication/user/UserService.java
index 13a35d4..0bfc59a 100644
--- a/src/main/java/com/bankly/vendura/authentication/user/UserService.java
+++ b/src/main/java/com/bankly/vendura/authentication/user/UserService.java
@@ -57,8 +57,7 @@ public User createUser(UserDTO userDTO) throws EntityCreationException {
     user.setEnabled(userDTO.getEnabled() == null || userDTO.getEnabled());
     user.setLocked(userDTO.getLocked() == null || userDTO.getLocked());
 
-    Set<String> roleIds =
-        userDTO.getRoles().stream().map(RoleDTO::getId).collect(Collectors.toSet());
+    Set<String> roleIds = userDTO.getRoles();
 
     for (String roleId : roleIds) {
       Role role =
@@ -127,14 +126,14 @@ public User updateUser(String id, UserDTO userDTO) {
       Set<Role> roles =
           userDTO.getRoles().stream()
               .map(
-                  roleDTO ->
+                  roleId ->
                       this.roleRepository
-                          .findById(roleDTO.getId())
+                          .findById(roleId)
                           .orElseThrow(
                               () ->
                                   new EntityUpdateException(
                                       "Cannot update roles because role with ID "
-                                          + roleDTO.getId()
+                                          + roleId
                                           + " not found",
                                       HttpStatus.NOT_FOUND,
                                       "roles")))
diff --git a/src/main/java/com/bankly/vendura/authentication/user/model/UserDTO.java b/src/main/java/com/bankly/vendura/authentication/user/model/UserDTO.java
index d142d57..5549357 100644
--- a/src/main/java/com/bankly/vendura/authentication/user/model/UserDTO.java
+++ b/src/main/java/com/bankly/vendura/authentication/user/model/UserDTO.java
@@ -1,30 +1,26 @@
 package com.bankly.vendura.authentication.user.model;
 
-import com.bankly.vendura.authentication.roles.model.RoleDTO;
-import java.util.Set;
-import java.util.stream.Collectors;
+import com.bankly.vendura.authentication.roles.model.Role;
 import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import java.util.Set;
+import java.util.stream.Collectors;
+
 @Data
+@Builder
 @NoArgsConstructor
 @AllArgsConstructor
 public class UserDTO {
-  private String id;
-  private String username;
-  private String password;
-  private Set<RoleDTO> roles;
-  private Boolean enabled;
-  private Boolean locked;
-
-  public static UserDTO fromUser(User user) {
-    return new UserDTO(
-        user.getId(),
-        user.getUsername(),
-        user.getPassword(),
-        user.getRoles().stream().map(RoleDTO::fromRole).collect(Collectors.toSet()),
-        user.isEnabled(),
-        user.isLocked());
-  }
+    private String id;
+    private String username;
+    private String firstName;
+    private String lastName;
+    private String email;
+    private String password;
+    private Boolean enabled;
+    private Boolean locked;
+    private Set<String> roles;
 }
diff --git a/src/main/java/com/bankly/vendura/authentication/user/model/UserFactory.java b/src/main/java/com/bankly/vendura/authentication/user/model/UserFactory.java
new file mode 100644
index 0000000..79f49bf
--- /dev/null
+++ b/src/main/java/com/bankly/vendura/authentication/user/model/UserFactory.java
@@ -0,0 +1,41 @@
+package com.bankly.vendura.authentication.user.model;
+
+import com.bankly.vendura.authentication.roles.model.Role;
+import java.util.stream.Collectors;
+
+public class UserFactory {
+    
+    public static UserDTO toDTO(User user) {
+        if (user == null) {
+            return null;
+        }
+        
+        return UserDTO.builder()
+                .id(user.getId())
+                .username(user.getUsername())
+                .enabled(user.isEnabled())
+                .locked(user.isLocked())
+                .roles(user.getRoles().stream()
+                        .map(Role::getId)
+                        .collect(Collectors.toSet()))
+                .build();
+    }
+    
+    public static User toEntity(UserDTO userDTO) {
+        if (userDTO == null) {
+            return null;
+        }
+        
+        User user = new User();
+        user.setId(userDTO.getId());
+        user.setUsername(userDTO.getUsername());
+        user.setPassword(userDTO.getPassword());
+        user.setEnabled(userDTO.getEnabled() == null || userDTO.getEnabled());
+        user.setLocked(userDTO.getLocked() == null || userDTO.getLocked());
+        
+        // Note: Converting Role IDs to Role entities would require a RoleRepository,
+        // which is not available to this factory method. This should be handled at the service level.
+        
+        return user;
+    }
+} 
\ No newline at end of file
diff --git a/src/main/java/com/bankly/vendura/inventory/product/ProductControllerV1.java b/src/main/java/com/bankly/vendura/inventory/product/ProductControllerV1.java
index 44cf75e..545bd0e 100644
--- a/src/main/java/com/bankly/vendura/inventory/product/ProductControllerV1.java
+++ b/src/main/java/com/bankly/vendura/inventory/product/ProductControllerV1.java
@@ -29,8 +29,12 @@ public class ProductControllerV1 {
 
   @GetMapping
   @PreAuthorize("hasRole('POS')")
-  public ResponseEntity<Page<ProductDTO>> getProducts(Pageable pageable) {
-    return ResponseEntity.ok(this.productRepository.findAll(pageable).map(ProductFactory::toDTO));
+  public ResponseEntity<Page<ProductDTO>> getProducts(
+      Pageable pageable,
+      @RequestParam(required = false, name = "calculateStock", defaultValue = "false")
+          boolean calculateStock) {
+    
+    return ResponseEntity.ok(this.productService.getProducts(pageable, calculateStock));
   }
 
   @GetMapping("/{id}")
@@ -40,20 +44,7 @@ public ResponseEntity<ProductDTO> getProductByID(
       @RequestParam(required = false, name = "calculateStock", defaultValue = "false")
           boolean calculateStock) {
 
-    ProductDTO productDTO =
-        ProductFactory.toDTO(
-            this.productRepository
-                .findById(id)
-                .orElseThrow(
-                    () ->
-                        new EntityRetrieveException(
-                            "Product not found", HttpStatus.NOT_FOUND, id)));
-
-    if (calculateStock) {
-      productDTO.setCurrentStock(productTransactionService.calculateCurrentStock(id));
-    }
-
-    return ResponseEntity.ok(productDTO);
+    return ResponseEntity.ok(this.productService.getProductById(id, calculateStock));
   }
 
   @PostMapping
diff --git a/src/main/java/com/bankly/vendura/inventory/product/ProductInventoryControllerV1.java b/src/main/java/com/bankly/vendura/inventory/product/ProductInventoryControllerV1.java
new file mode 100644
index 0000000..3e84b73
--- /dev/null
+++ b/src/main/java/com/bankly/vendura/inventory/product/ProductInventoryControllerV1.java
@@ -0,0 +1,106 @@
+package com.bankly.vendura.inventory.product;
+
+import com.bankly.vendura.inventory.product.model.Product;
+import com.bankly.vendura.inventory.product.model.ProductDTO;
+import com.bankly.vendura.inventory.product.model.ProductFactory;
+import com.bankly.vendura.inventory.product.model.ProductRepository;
+import com.bankly.vendura.inventory.transactions.product.ProductTransactionService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/v1/inventory")
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+public class ProductInventoryControllerV1 {
+
+    private final ProductStockService productStockService;
+    private final ProductTransactionService productTransactionService;
+    private final ProductRepository productRepository;
+
+    /**
+     * Get inventory status for dashboard
+     */
+    @GetMapping("/status")
+    @PreAuthorize("hasAnyRole('INVENTORY', 'SALES', 'ADMIN')")
+    public ResponseEntity<Map<String, Integer>> getInventoryStatus() {
+        Map<String, Integer> status = new HashMap<>();
+        
+        // Get total product count
+        long totalProducts = productRepository.count();
+        status.put("total", (int) totalProducts);
+        
+        // Get low stock products
+        List<Product> lowStockProducts = productStockService.getProductsLowOnStock();
+        status.put("lowStock", lowStockProducts.size());
+        
+        // Count out of stock products
+        int outOfStock = 0;
+        for (Product product : lowStockProducts) {
+            if (productTransactionService.calculateCurrentStock(product) <= 0) {
+                outOfStock++;
+            }
+        }
+        status.put("outOfStock", outOfStock);
+        
+        return ResponseEntity.ok(status);
+    }
+
+    /**
+     * Get all products that are low on stock
+     */
+    @GetMapping("/low-stock")
+    @PreAuthorize("hasRole('INVENTORY')")
+    public ResponseEntity<List<ProductDTO>> getLowStockProducts() {
+        List<Product> products = productStockService.getProductsLowOnStock();
+        
+        List<ProductDTO> productDTOs = products.stream()
+                .map(product -> {
+                    ProductDTO dto = ProductFactory.toDTO(product);
+                    dto.setCurrentStock(productTransactionService.calculateCurrentStock(product.getId()));
+                    return dto;
+                })
+                .collect(Collectors.toList());
+                
+        return ResponseEntity.ok(productDTOs);
+    }
+    
+    /**
+     * Adjust stock level for a product
+     */
+    @PostMapping("/{productId}/adjust")
+    @PreAuthorize("hasRole('INVENTORY')")
+    public ResponseEntity<?> adjustStock(
+            @PathVariable("productId") String productId,
+            @RequestParam("quantity") long quantity,
+            @RequestParam(value = "reason", required = false) String reason,
+            Authentication authentication) {
+            
+        productStockService.adjustStock(
+                productId,
+                quantity,
+                authentication.getName(),
+                reason
+        );
+        
+        return ResponseEntity.ok().build();
+    }
+    
+    /**
+     * Trigger automatic reordering check
+     */
+    @PostMapping("/reorder-check")
+    @PreAuthorize("hasRole('ADMIN')")
+    public ResponseEntity<?> triggerReorderCheck() {
+        productStockService.checkStockLevelsAndReorder();
+        return ResponseEntity.ok().build();
+    }
+} 
\ No newline at end of file
diff --git a/src/main/java/com/bankly/vendura/inventory/product/ProductService.java b/src/main/java/com/bankly/vendura/inventory/product/ProductService.java
index 5879cd8..544a631 100644
--- a/src/main/java/com/bankly/vendura/inventory/product/ProductService.java
+++ b/src/main/java/com/bankly/vendura/inventory/product/ProductService.java
@@ -7,18 +7,61 @@
 import com.bankly.vendura.inventory.product.model.ProductRepository;
 import com.bankly.vendura.inventory.productcategory.model.ProductCategoryFactory;
 import com.bankly.vendura.inventory.supplier.model.SupplierFactory;
+import com.bankly.vendura.inventory.transactions.product.ProductTransactionService;
 import com.bankly.vendura.utilities.exceptions.EntityCreationException;
 import com.bankly.vendura.utilities.exceptions.EntityRetrieveException;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Service;
+import java.util.UUID;
 
 @Service
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 public class ProductService {
 
   private final ProductRepository productRepository;
+  private final ProductTransactionService productTransactionService;
+
+  /**
+   * Get all products with optional stock calculation
+   * @param pageable Pagination parameters
+   * @param calculateStock Whether to calculate current stock for each product
+   * @return Page of product DTOs
+   */
+  public Page<ProductDTO> getProducts(Pageable pageable, boolean calculateStock) {
+    Page<ProductDTO> productDTOPage = this.productRepository.findAll(pageable).map(ProductFactory::toDTO);
+    
+    if (calculateStock) {
+      productDTOPage.getContent().forEach(productDTO -> {
+        productDTO.setCurrentStock(productTransactionService.calculateCurrentStock(productDTO.getId()));
+      });
+    }
+    
+    return productDTOPage;
+  }
+
+  /**
+   * Get a single product by ID with optional stock calculation
+   * @param id Product ID
+   * @param calculateStock Whether to calculate current stock for the product
+   * @return Product DTO
+   */
+  public ProductDTO getProductById(String id, boolean calculateStock) {
+    ProductDTO productDTO = ProductFactory.toDTO(
+        this.productRepository
+            .findById(id)
+            .orElseThrow(
+                () -> new EntityRetrieveException("Product not found", HttpStatus.NOT_FOUND, id)));
+
+    if (calculateStock) {
+      productDTO.setCurrentStock(productTransactionService.calculateCurrentStock(id));
+    }
+
+    return productDTO;
+  }
 
   public Product create(ProductDTO productDTO) {
 
@@ -28,8 +71,29 @@ public Product create(ProductDTO productDTO) {
     }
 
     Product product = ProductFactory.toEntity(productDTO);
+    
+    // Auto-generate ID if it's null
+    if (product.getId() == null) {
+      product.setId(generateUniqueProductId());
+    }
+    
     return this.productRepository.save(product);
   }
+  
+  /**
+   * Generates a unique product ID that doesn't already exist in the database
+   * @return A unique formatted product ID
+   */
+  private String generateUniqueProductId() {
+    String productId;
+    do {
+      // Generate an 8-character ID
+      productId = UUID.randomUUID().toString().substring(0, 8).toUpperCase();
+      // Check if this ID already exists
+    } while (this.productRepository.existsById(productId));
+    
+    return productId;
+  }
 
   public Product update(String id, ProductDTO productDTO) {
     Product product =
@@ -75,7 +139,6 @@ public Product update(String id, ProductDTO productDTO) {
     return this.productRepository.save(product);
   }
 
-
   public void delete(String id) {
     Product product =
             this.productRepository
diff --git a/src/main/java/com/bankly/vendura/inventory/product/ProductStockService.java b/src/main/java/com/bankly/vendura/inventory/product/ProductStockService.java
new file mode 100644
index 0000000..98a7be2
--- /dev/null
+++ b/src/main/java/com/bankly/vendura/inventory/product/ProductStockService.java
@@ -0,0 +1,143 @@
+package com.bankly.vendura.inventory.product;
+
+import com.bankly.vendura.authentication.user.model.User;
+import com.bankly.vendura.authentication.user.model.UserRepository;
+import com.bankly.vendura.inventory.product.model.Product;
+import com.bankly.vendura.inventory.product.model.ProductRepository;
+import com.bankly.vendura.inventory.supplier.model.Supplier;
+import com.bankly.vendura.inventory.supplierorder.SupplierOrderService;
+import com.bankly.vendura.inventory.supplierorder.model.SupplierOrder;
+import com.bankly.vendura.inventory.supplierorder.model.SupplierOrderDTO;
+import com.bankly.vendura.inventory.transactions.product.ProductTransactionService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+@Service
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+public class ProductStockService {
+
+    private final ProductRepository productRepository;
+    private final ProductTransactionService transactionService;
+    private final SupplierOrderService supplierOrderService;
+    private final UserRepository userRepository;
+
+    /**
+     * Check stock levels for all products and create supplier orders if needed
+     */
+    @Transactional
+    @Scheduled(cron = "0 0 * * * *") // Run once per hour
+    public void checkStockLevelsAndReorder() {
+        // Group products by supplier that need reordering
+        Map<Supplier, List<Product>> productsToReorder = new HashMap<>();
+        
+        for (Product product : productRepository.findAll()) {
+            if (product.getDefaultSupplier() == null || product.getReorderPoint() == null) {
+                continue; // Skip products without supplier or reorder point
+            }
+            
+            long currentStock = transactionService.calculateCurrentStock(product.getId());
+            // Check if stock is below reorder point
+            if (currentStock <= product.getReorderPoint()) {
+                productsToReorder
+                    .computeIfAbsent(product.getDefaultSupplier(), k -> new ArrayList<>())
+                    .add(product);
+            }
+        }
+        
+        // Create supplier orders for each supplier
+        for (Map.Entry<Supplier, List<Product>> entry : productsToReorder.entrySet()) {
+            createSupplierOrderForProducts(entry.getKey(), entry.getValue());
+        }
+    }
+    
+    /**
+     * Create a supplier order for a list of products
+     */
+    private void createSupplierOrderForProducts(Supplier supplier, List<Product> products) {
+        if (products.isEmpty()) {
+            return;
+        }
+        
+        // Create supplier order positions
+        Set<SupplierOrderDTO.Position> positions = new HashSet<>();
+        for (Product product : products) {
+            long currentStock = transactionService.calculateCurrentStock(product);
+            long quantityToOrder = product.getReorderQuantity() != null ? 
+                    product.getReorderQuantity() : 
+                    (product.getMaxStockLevel() != null ? 
+                            product.getMaxStockLevel() - currentStock : 10);
+                            
+            SupplierOrderDTO.Position position = new SupplierOrderDTO.Position();
+            position.setProduct(com.bankly.vendura.inventory.product.model.ProductFactory.toDTO(product));
+            position.setAmount((int) quantityToOrder);
+            positions.add(position);
+        }
+        
+        // Create the supplier order
+        SupplierOrderDTO orderDTO = new SupplierOrderDTO();
+        orderDTO.setTimestamp(new Date());
+        orderDTO.setPositions(positions);
+        orderDTO.setOrderStatus(SupplierOrderDTO.OrderStatus.PLACED);
+        
+        supplierOrderService.create(orderDTO);
+    }
+    
+    /**
+     * Check if product is low on stock
+     */
+    public boolean isLowOnStock(Product product) {
+        long currentStock = transactionService.calculateCurrentStock(product);
+        
+        // Products with zero stock are always considered low on stock
+        if (currentStock <= 0) {
+            return true;
+        }
+        
+        // For products with stock > 0, check against minStockLevel if available
+        if (product.getMinStockLevel() != null) {
+            return currentStock <= product.getMinStockLevel();
+        }
+        
+        return false;
+    }
+    
+    /**
+     * Get all products that are low on stock
+     */
+    public List<Product> getProductsLowOnStock() {
+        List<Product> lowStockProducts = new ArrayList<>();
+        
+        for (Product product : productRepository.findAll()) {
+            if (isLowOnStock(product)) {
+                lowStockProducts.add(product);
+            }
+        }
+        
+        return lowStockProducts;
+    }
+    
+    /**
+     * Record stock adjustment (manual inventory correction)
+     */
+    @Transactional
+    public void adjustStock(String productId, long quantityChange, String username, String reason) {
+        User user = userRepository.findUserByUsername(username)
+                .orElseThrow(() -> new RuntimeException("User not found"));
+        
+        Product product = productRepository.findById(productId)
+                .orElseThrow(() -> new RuntimeException("Product not found"));
+        
+        transactionService.createTransaction(
+                product,
+                quantityChange,
+                null, // No transaction cause for manual adjustments
+                user,
+                reason != null ? reason : "Manual stock adjustment"
+        );
+    }
+} 
\ No newline at end of file
diff --git a/src/main/java/com/bankly/vendura/inventory/product/model/Product.java b/src/main/java/com/bankly/vendura/inventory/product/model/Product.java
index ae64a7f..bb5b9c3 100644
--- a/src/main/java/com/bankly/vendura/inventory/product/model/Product.java
+++ b/src/main/java/com/bankly/vendura/inventory/product/model/Product.java
@@ -10,6 +10,7 @@
 import org.springframework.data.mongodb.core.mapping.DBRef;
 import org.springframework.data.mongodb.core.mapping.Document;
 
+import java.util.Comparator;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
@@ -25,18 +26,92 @@ public class Product {
 
   private String name;
 
+  private String shortDescription;
+
+  private String longDescription;
+
   @DBRef private ProductCategory productCategory;
 
   @DBRef private Brand brand;
 
   @DBRef private Supplier defaultSupplier;
 
+  private Long minStockLevel;
+
+  private Long maxStockLevel;
+
+  private Long reorderPoint;
+
+  private Long reorderQuantity;
+
+  private Long leadTimeInDays;
+
   @DBRef private Set<Product> connectedProducts = new HashSet<>();
 
   private boolean standalone;
 
   private List<PriceHistory> priceHistories;
 
+  /**
+   * Gets the current price from the latest price history entry
+   * @return the current price or 0 if no price history exists
+   */
+  public double getPrice() {
+    if (priceHistories == null || priceHistories.isEmpty()) {
+      return 0;
+    }
+    return priceHistories.stream()
+        .max(Comparator.comparing(PriceHistory::getTimestamp))
+        .map(PriceHistory::getPrice)
+        .orElse(0.0);
+  }
+
+  /**
+   * Gets the current purchase price from the latest price history entry
+   * @return the current purchase price or 0 if no price history exists
+   */
+  public double getPurchasePrice() {
+    if (priceHistories == null || priceHistories.isEmpty()) {
+      return 0;
+    }
+    return priceHistories.stream()
+        .max(Comparator.comparing(PriceHistory::getTimestamp))
+        .map(PriceHistory::getPurchasePrice)
+        .orElse(0.0);
+  }
+
+  /**
+   * Gets the price at a specific point in time
+   * @param date The date to check for price
+   * @return The price at the given date or latest price before that date
+   */
+  public double getPriceAtDate(Date date) {
+    if (priceHistories == null || priceHistories.isEmpty()) {
+      return 0;
+    }
+    return priceHistories.stream()
+        .filter(ph -> ph.getTimestamp().before(date) || ph.getTimestamp().equals(date))
+        .max(Comparator.comparing(PriceHistory::getTimestamp))
+        .map(PriceHistory::getPrice)
+        .orElse(0.0);
+  }
+
+  /**
+   * Gets the purchase price at a specific point in time
+   * @param date The date to check for purchase price
+   * @return The purchase price at the given date or latest price before that date
+   */
+  public double getPurchasePriceAtDate(Date date) {
+    if (priceHistories == null || priceHistories.isEmpty()) {
+      return 0;
+    }
+    return priceHistories.stream()
+        .filter(ph -> ph.getTimestamp().before(date) || ph.getTimestamp().equals(date))
+        .max(Comparator.comparing(PriceHistory::getTimestamp))
+        .map(PriceHistory::getPurchasePrice)
+        .orElse(0.0);
+  }
+
   @Data
   @NoArgsConstructor
   @AllArgsConstructor
diff --git a/src/main/java/com/bankly/vendura/inventory/product/model/ProductDTO.java b/src/main/java/com/bankly/vendura/inventory/product/model/ProductDTO.java
index 9b6b404..2379c70 100644
--- a/src/main/java/com/bankly/vendura/inventory/product/model/ProductDTO.java
+++ b/src/main/java/com/bankly/vendura/inventory/product/model/ProductDTO.java
@@ -8,6 +8,7 @@
 import lombok.NoArgsConstructor;
 import org.springframework.lang.Nullable;
 
+import java.util.Comparator;
 import java.util.Date;
 import java.util.List;
 import java.util.Set;
@@ -19,11 +20,19 @@ public class ProductDTO {
 
     private String id;
     private String name;
+    private String shortDescription;
+    private String longDescription;
     private ProductCategoryDTO productCategory;
     private BrandDTO brand;
 
     private SupplierDTO defaultSupplier;
-
+    
+    private Long minStockLevel;
+    private Long maxStockLevel;
+    private Long reorderPoint;
+    private Long reorderQuantity;
+    private Long leadTimeInDays;
+    
     private Set<ProductDTO> connectedProducts;
     private Boolean standalone;
 
@@ -32,6 +41,66 @@ public class ProductDTO {
     @Nullable
     private Long currentStock;
 
+    /**
+     * Gets the current price from the latest price history entry
+     * @return the current price or 0 if no price history exists
+     */
+    public double getPrice() {
+        if (priceHistories == null || priceHistories.isEmpty()) {
+            return 0;
+        }
+        return priceHistories.stream()
+            .max(Comparator.comparing(PriceHistoryDTO::getTimestamp))
+            .map(PriceHistoryDTO::getPrice)
+            .orElse(0.0);
+    }
+
+    /**
+     * Gets the current purchase price from the latest price history entry
+     * @return the current purchase price or 0 if no price history exists
+     */
+    public double getPurchasePrice() {
+        if (priceHistories == null || priceHistories.isEmpty()) {
+            return 0;
+        }
+        return priceHistories.stream()
+            .max(Comparator.comparing(PriceHistoryDTO::getTimestamp))
+            .map(PriceHistoryDTO::getPurchasePrice)
+            .orElse(0.0);
+    }
+
+    /**
+     * Gets the price at a specific point in time
+     * @param date The date to check for price
+     * @return The price at the given date or latest price before that date
+     */
+    public double getPriceAtDate(Date date) {
+        if (priceHistories == null || priceHistories.isEmpty()) {
+            return 0;
+        }
+        return priceHistories.stream()
+            .filter(ph -> ph.getTimestamp().before(date) || ph.getTimestamp().equals(date))
+            .max(Comparator.comparing(PriceHistoryDTO::getTimestamp))
+            .map(PriceHistoryDTO::getPrice)
+            .orElse(0.0);
+    }
+
+    /**
+     * Gets the purchase price at a specific point in time
+     * @param date The date to check for purchase price
+     * @return The purchase price at the given date or latest price before that date
+     */
+    public double getPurchasePriceAtDate(Date date) {
+        if (priceHistories == null || priceHistories.isEmpty()) {
+            return 0;
+        }
+        return priceHistories.stream()
+            .filter(ph -> ph.getTimestamp().before(date) || ph.getTimestamp().equals(date))
+            .max(Comparator.comparing(PriceHistoryDTO::getTimestamp))
+            .map(PriceHistoryDTO::getPurchasePrice)
+            .orElse(0.0);
+    }
+
     @Data
     @NoArgsConstructor
     @AllArgsConstructor
diff --git a/src/main/java/com/bankly/vendura/inventory/product/model/ProductFactory.java b/src/main/java/com/bankly/vendura/inventory/product/model/ProductFactory.java
index 64a465d..8e24fe9 100644
--- a/src/main/java/com/bankly/vendura/inventory/product/model/ProductFactory.java
+++ b/src/main/java/com/bankly/vendura/inventory/product/model/ProductFactory.java
@@ -11,45 +11,75 @@ public class ProductFactory {
 
   public static ProductDTO toDTO(Product product) {
     if (product == null) return null;
-    return new ProductDTO(
-        product.getId(),
-        product.getName(),
-        ProductCategoryFactory.toDTO(product.getProductCategory()),
-        BrandFactory.toDTO(product.getBrand()),
-        SupplierFactory.toDTO(product.getDefaultSupplier()),
+
+    ProductDTO productDTO = new ProductDTO();
+    productDTO.setId(product.getId());
+    productDTO.setName(product.getName());
+    productDTO.setShortDescription(product.getShortDescription());
+    productDTO.setLongDescription(product.getLongDescription());
+    productDTO.setProductCategory(ProductCategoryFactory.toDTO(product.getProductCategory()));
+    productDTO.setBrand(BrandFactory.toDTO(product.getBrand()));
+    productDTO.setDefaultSupplier(SupplierFactory.toDTO(product.getDefaultSupplier()));
+    productDTO.setMinStockLevel(product.getMinStockLevel());
+    productDTO.setMaxStockLevel(product.getMaxStockLevel());
+    productDTO.setReorderPoint(product.getReorderPoint());
+    productDTO.setReorderQuantity(product.getReorderQuantity());
+    productDTO.setLeadTimeInDays(product.getLeadTimeInDays());
+    productDTO.setConnectedProducts(
         product.getConnectedProducts().stream()
             .map(ProductFactory::toDTO)
-            .collect(Collectors.toSet()),
-        product.isStandalone(),
-        product.getPriceHistories().stream().map(ProductFactory::toDTO).toList(),
-        null);
+            .collect(Collectors.toSet()));
+    productDTO.setStandalone(product.isStandalone());
+    
+    // Transform priceHistories if available
+    if (product.getPriceHistories() != null) {
+      productDTO.setPriceHistories(
+          product.getPriceHistories().stream().map(ProductFactory::toDTO).collect(Collectors.toList()));
+    }
+
+    return productDTO;
   }
 
   public static Product toEntity(ProductDTO productDTO) {
     if (productDTO == null) return null;
-    return new Product(
-        productDTO.getId(),
-        productDTO.getName(),
-        ProductCategoryFactory.toEntity(productDTO.getProductCategory()),
-        BrandFactory.toEntity(productDTO.getBrand()),
-        SupplierFactory.toEntity(productDTO.getDefaultSupplier()),
-        productDTO.getConnectedProducts() != null
-            ? new HashSet<>(
-                productDTO.getConnectedProducts().stream()
-                    .map(ProductFactory::toEntity)
-                    .collect(Collectors.toSet()))
-            : new HashSet<>(),
-        productDTO.getStandalone() != null && productDTO.getStandalone(),
-        productDTO.getPriceHistories() != null
-            ? productDTO.getPriceHistories().stream().map(ProductFactory::toEntity).toList()
-            : new ArrayList<>());
+
+    Product product = new Product();
+    product.setId(productDTO.getId());
+    product.setName(productDTO.getName());
+    product.setShortDescription(productDTO.getShortDescription());
+    product.setLongDescription(productDTO.getLongDescription());
+    product.setProductCategory(ProductCategoryFactory.toEntity(productDTO.getProductCategory()));
+    product.setBrand(BrandFactory.toEntity(productDTO.getBrand()));
+    product.setDefaultSupplier(SupplierFactory.toEntity(productDTO.getDefaultSupplier()));
+    product.setMinStockLevel(productDTO.getMinStockLevel());
+    product.setMaxStockLevel(productDTO.getMaxStockLevel());
+    product.setReorderPoint(productDTO.getReorderPoint());
+    product.setReorderQuantity(productDTO.getReorderQuantity());
+    product.setLeadTimeInDays(productDTO.getLeadTimeInDays());
+    
+    if (productDTO.getConnectedProducts() != null) {
+      product.setConnectedProducts(
+          productDTO.getConnectedProducts().stream()
+              .map(ProductFactory::toEntity)
+              .collect(Collectors.toSet()));
+    }
+    
+    product.setStandalone(productDTO.getStandalone() != null ? productDTO.getStandalone() : true);
+    
+    // Transform priceHistories if available
+    if (productDTO.getPriceHistories() != null) {
+      product.setPriceHistories(
+          productDTO.getPriceHistories().stream().map(ProductFactory::toEntity).collect(Collectors.toList()));
+    }
+
+    return product;
   }
 
   public static ProductDTO.PriceHistoryDTO toDTO(Product.PriceHistory priceHistory) {
     return new ProductDTO.PriceHistoryDTO(
         priceHistory.getTimestamp(),
         priceHistory.getPurchasePrice(),
-        priceHistory.getPurchasePrice(),
+        priceHistory.getPrice(),
         SupplierFactory.toDTO(priceHistory.getSupplier()));
   }
 
diff --git a/src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderControllerV1.java b/src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderControllerV1.java
index e6eba87..7fa1773 100644
--- a/src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderControllerV1.java
+++ b/src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderControllerV1.java
@@ -1,5 +1,6 @@
 package com.bankly.vendura.inventory.supplierorder;
 
+import com.bankly.vendura.inventory.supplierorder.model.SupplierOrder;
 import com.bankly.vendura.inventory.supplierorder.model.SupplierOrderDTO;
 import com.bankly.vendura.inventory.supplierorder.model.SupplierOrderFactory;
 import com.bankly.vendura.inventory.supplierorder.model.SupplierOrderRepository;
@@ -14,6 +15,9 @@
 import org.springframework.security.core.Authentication;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+import java.util.stream.Collectors;
+
 @RestController
 @RequestMapping("/v1/supplierorder")
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
@@ -29,6 +33,44 @@ public ResponseEntity<Page<SupplierOrderDTO>> getSupplierOrders(Pageable pageabl
         this.supplierOrderRepository.findAll(pageable).map(SupplierOrderFactory::toDTO));
   }
 
+  @GetMapping("/status/{status}")
+  @PreAuthorize("hasRole('INVENTORY')")
+  public ResponseEntity<Page<SupplierOrderDTO>> getSupplierOrdersByStatus(
+      @PathVariable("status") String status, Pageable pageable) {
+    try {
+      SupplierOrder.OrderStatus orderStatus = SupplierOrder.OrderStatus.valueOf(status.toUpperCase());
+      return ResponseEntity.ok(
+          this.supplierOrderService.getSupplierOrdersByStatus(orderStatus, pageable).map(SupplierOrderFactory::toDTO));
+    } catch (IllegalArgumentException e) {
+      throw new EntityRetrieveException("Invalid order status", HttpStatus.BAD_REQUEST, status);
+    }
+  }
+  
+  @GetMapping("/supplier/{supplierId}")
+  @PreAuthorize("hasRole('INVENTORY')")
+  public ResponseEntity<Page<SupplierOrderDTO>> getSupplierOrdersBySupplierId(
+      @PathVariable("supplierId") String supplierId, Pageable pageable) {
+    return ResponseEntity.ok(
+        this.supplierOrderService.getSupplierOrdersBySupplierId(supplierId, pageable).map(SupplierOrderFactory::toDTO));
+  }
+  
+  @GetMapping("/automatic/{isAutomatic}")
+  @PreAuthorize("hasRole('INVENTORY')")
+  public ResponseEntity<Page<SupplierOrderDTO>> getAutomaticSupplierOrders(
+      @PathVariable("isAutomatic") boolean isAutomatic, Pageable pageable) {
+    return ResponseEntity.ok(
+        this.supplierOrderService.getAutomaticSupplierOrders(isAutomatic, pageable).map(SupplierOrderFactory::toDTO));
+  }
+  
+  @GetMapping("/pending")
+  @PreAuthorize("hasRole('INVENTORY')")
+  public ResponseEntity<List<SupplierOrderDTO>> getPendingSupplierOrders() {
+    return ResponseEntity.ok(
+        this.supplierOrderService.findPendingOrders().stream()
+            .map(SupplierOrderFactory::toDTO)
+            .collect(Collectors.toList()));
+  }
+
   @GetMapping("/{id}")
   @PreAuthorize("hasRole('INVENTORY')")
   public ResponseEntity<SupplierOrderDTO> getSupplierOrderById(@PathVariable("id") String id) {
diff --git a/src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java b/src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java
index b62a9a5..6ede1c5 100644
--- a/src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java
+++ b/src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java
@@ -3,6 +3,7 @@
 import com.bankly.vendura.authentication.user.model.User;
 import com.bankly.vendura.authentication.user.model.UserRepository;
 import com.bankly.vendura.inventory.product.model.ProductFactory;
+import com.bankly.vendura.inventory.supplier.model.SupplierRepository;
 import com.bankly.vendura.inventory.supplierorder.model.SupplierOrder;
 import com.bankly.vendura.inventory.supplierorder.model.SupplierOrderDTO;
 import com.bankly.vendura.inventory.supplierorder.model.SupplierOrderFactory;
@@ -10,9 +11,16 @@
 import com.bankly.vendura.inventory.transactions.product.ProductTransactionService;
 import com.bankly.vendura.utilities.exceptions.EntityRetrieveException;
 import com.bankly.vendura.utilities.exceptions.EntityUpdateException;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -21,15 +29,63 @@
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 public class SupplierOrderService {
 
+  private static final Logger logger = LoggerFactory.getLogger(SupplierOrderService.class);
+  
   private final ProductTransactionService productTransactionService;
   private final UserRepository userRepository;
   private final SupplierOrderRepository supplierOrderRepository;
+  private final SupplierRepository supplierRepository;
 
+  /**
+   * Create a new supplier order
+   */
+  @Transactional
   public SupplierOrder create(SupplierOrderDTO supplierOrderDTO) {
+    // Set default values if not provided
+    if (supplierOrderDTO.getTimestamp() == null) {
+      supplierOrderDTO.setTimestamp(new Date());
+    }
+    
+    if (supplierOrderDTO.getOrderStatus() == null) {
+      supplierOrderDTO.setOrderStatus(SupplierOrderDTO.OrderStatus.PLACED);
+    }
+    
     SupplierOrder supplierOrder = SupplierOrderFactory.fromDTO(supplierOrderDTO);
     return this.supplierOrderRepository.save(supplierOrder);
   }
 
+  /**
+   * Get supplier orders by status
+   */
+  public Page<SupplierOrder> getSupplierOrdersByStatus(SupplierOrder.OrderStatus status, Pageable pageable) {
+    return supplierOrderRepository.findByOrderStatus(status, pageable);
+  }
+  
+  /**
+   * Get supplier orders by supplier ID
+   */
+  public Page<SupplierOrder> getSupplierOrdersBySupplierId(String supplierId, Pageable pageable) {
+    return supplierOrderRepository.findBySupplierId(supplierId, pageable);
+  }
+  
+  /**
+   * Get supplier orders by automatic order flag
+   */
+  public Page<SupplierOrder> getAutomaticSupplierOrders(boolean isAutomatic, Pageable pageable) {
+    return supplierOrderRepository.findIsAutomaticOrder(isAutomatic, pageable);
+  }
+
+  /**
+   * Find pending supplier orders
+   */
+  public List<SupplierOrder> findPendingOrders() {
+    return supplierOrderRepository.findByOrderStatusIn(
+        List.of(SupplierOrder.OrderStatus.PLACED, SupplierOrder.OrderStatus.SHIPPED));
+  }
+
+  /**
+   * Update a supplier order
+   */
   @Transactional
   public SupplierOrder update(String id, SupplierOrderDTO supplierOrderDTO, String username) {
     SupplierOrder supplierOrder =
@@ -48,6 +104,31 @@ public SupplierOrder update(String id, SupplierOrderDTO supplierOrderDTO, String
       throw new EntityUpdateException(
           "Cannot update timestamp", HttpStatus.UNPROCESSABLE_ENTITY, "timestamp");
     }
+    
+    // Update supplier if provided
+    if (supplierOrderDTO.getSupplier() != null && supplierOrderDTO.getSupplier().getId() != null) {
+      supplierOrder.setSupplier(
+          supplierRepository
+              .findById(supplierOrderDTO.getSupplier().getId())
+              .orElseThrow(
+                  () ->
+                      new EntityRetrieveException(
+                          "Supplier not found", 
+                          HttpStatus.NOT_FOUND, 
+                          supplierOrderDTO.getSupplier().getId())));
+    }
+    
+    if (supplierOrderDTO.getExpectedDeliveryDate() != null) {
+      supplierOrder.setExpectedDeliveryDate(supplierOrderDTO.getExpectedDeliveryDate());
+    }
+    
+    if (supplierOrderDTO.getNotes() != null) {
+      supplierOrder.setNotes(supplierOrderDTO.getNotes());
+    }
+    
+    if (supplierOrderDTO.isAutomaticOrder() != supplierOrder.isAutomaticOrder()) {
+      supplierOrder.setAutomaticOrder(supplierOrderDTO.isAutomaticOrder());
+    }
 
     if (supplierOrderDTO.getPositions() != null) {
       supplierOrder.setPositions(
@@ -61,7 +142,7 @@ public SupplierOrder update(String id, SupplierOrderDTO supplierOrderDTO, String
     }
 
     if (supplierOrderDTO.getOrderStatus() != null) {
-
+      // Cannot change status from DELIVERED to something else
       if (supplierOrder.getOrderStatus() == SupplierOrder.OrderStatus.DELIVERED
           && supplierOrderDTO.getOrderStatus() != SupplierOrderDTO.OrderStatus.DELIVERED) {
         throw new EntityUpdateException(
@@ -70,10 +151,13 @@ public SupplierOrder update(String id, SupplierOrderDTO supplierOrderDTO, String
             "orderStatus");
       }
 
+      // When status changes to DELIVERED, create inventory transactions
       if (supplierOrderDTO.getOrderStatus() == SupplierOrderDTO.OrderStatus.DELIVERED
           && supplierOrder.getOrderStatus() != SupplierOrder.OrderStatus.DELIVERED) {
 
         User user = this.userRepository.findUserByUsername(username).orElseThrow();
+        
+        logger.info("Creating inventory transactions for supplier order {} marked as DELIVERED", id);
 
         for (SupplierOrder.Position position : supplierOrder.getPositions()) {
           this.productTransactionService.createTransaction(
@@ -82,7 +166,12 @@ public SupplierOrder update(String id, SupplierOrderDTO supplierOrderDTO, String
               supplierOrder,
               user,
               "Automatic entry in the warehouse because the status of the supplier order has been changed to DELIVERED");
+              
+          logger.info("Created transaction for product {} with quantity {}", 
+              position.getProduct().getId(), position.getAmount());
         }
+        
+        logger.info("All transactions created successfully for supplier order {}", id);
       }
 
       supplierOrder.setOrderStatus(supplierOrderDTO.getOrderStatus().toEntityStatus());
@@ -91,6 +180,10 @@ public SupplierOrder update(String id, SupplierOrderDTO supplierOrderDTO, String
     return this.supplierOrderRepository.save(supplierOrder);
   }
 
+  /**
+   * Delete a supplier order
+   */
+  @Transactional
   public void delete(String id) {
     SupplierOrder supplierOrder =
         this.supplierOrderRepository
@@ -99,6 +192,14 @@ public void delete(String id) {
                 () ->
                     new EntityRetrieveException(
                         "Supplier order not found", HttpStatus.NOT_FOUND, id));
+                        
+    // Can only delete orders that are not DELIVERED
+    if (supplierOrder.getOrderStatus() == SupplierOrder.OrderStatus.DELIVERED) {
+      throw new EntityUpdateException(
+          "Cannot delete a delivered order",
+          HttpStatus.UNPROCESSABLE_ENTITY,
+          "orderStatus");
+    }
 
     this.supplierOrderRepository.delete(supplierOrder);
   }
diff --git a/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrder.java b/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrder.java
index 06abc9a..6f9930e 100644
--- a/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrder.java
+++ b/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrder.java
@@ -13,6 +13,7 @@
 import org.springframework.data.annotation.Id;
 import org.springframework.data.mongodb.core.mapping.DBRef;
 import org.springframework.data.mongodb.core.mapping.Document;
+import com.bankly.vendura.inventory.supplier.model.Supplier;
 
 @Data
 @Document(collection = "supplier_orders")
@@ -23,6 +24,12 @@ public class SupplierOrder implements ProductTransactable {
   @Id private String id;
 
   private Date timestamp;
+  
+  @DBRef private Supplier supplier;
+  
+  private Date expectedDeliveryDate;
+  private String notes;
+  private boolean automaticOrder;
 
   private Set<Position> positions;
 
@@ -56,16 +63,8 @@ public double getTotalPrice() {
     double currentPrice = 0;
 
     for (Position position : this.positions) {
-      Product.PriceHistory priceHistory =
-          position.getProduct().getPriceHistories().stream()
-              .filter(
-                  productPriceHistory -> productPriceHistory.getTimestamp().before(this.timestamp))
-              .max(Comparator.comparing(Product.PriceHistory::getTimestamp))
-              .orElse(null);
-
-      if (priceHistory != null) {
-        currentPrice += priceHistory.getPurchasePrice() * position.getAmount();
-      }
+      double purchasePrice = position.getProduct().getPurchasePriceAtDate(this.timestamp);
+      currentPrice += purchasePrice * position.getAmount();
     }
 
     return currentPrice;
diff --git a/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderDTO.java b/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderDTO.java
index 5aad7aa..49bc8dc 100644
--- a/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderDTO.java
+++ b/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderDTO.java
@@ -4,6 +4,7 @@
 import java.util.Set;
 
 import com.bankly.vendura.inventory.product.model.ProductDTO;
+import com.bankly.vendura.inventory.supplier.model.SupplierDTO;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -14,6 +15,13 @@
 public class SupplierOrderDTO {
   private String id;
   private Date timestamp;
+  
+  private SupplierDTO supplier;
+  
+  private Date expectedDeliveryDate;
+  private String notes;
+  private boolean isAutomaticOrder;
+  
   private Set<Position> positions;
   private OrderStatus orderStatus;
 
diff --git a/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderFactory.java b/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderFactory.java
index 88f2f2e..1307f97 100644
--- a/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderFactory.java
+++ b/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderFactory.java
@@ -1,6 +1,7 @@
 package com.bankly.vendura.inventory.supplierorder.model;
 
 import com.bankly.vendura.inventory.product.model.ProductFactory;
+import com.bankly.vendura.inventory.supplier.model.SupplierFactory;
 
 import java.util.stream.Collectors;
 
@@ -9,8 +10,14 @@ public static SupplierOrderDTO toDTO(SupplierOrder supplierOrder) {
         return new SupplierOrderDTO(
                 supplierOrder.getId(),
                 supplierOrder.getTimestamp(),
+                SupplierFactory.toDTO(supplierOrder.getSupplier()),
+                supplierOrder.getExpectedDeliveryDate(),
+                supplierOrder.getNotes(),
+                supplierOrder.isAutomaticOrder(),
                 supplierOrder.getPositions().stream()
-                        .map(position -> new SupplierOrderDTO.Position(ProductFactory.toDTO(position.getProduct()), position.getAmount()))
+                        .map(position -> new SupplierOrderDTO.Position(
+                                ProductFactory.toDTO(position.getProduct()), 
+                                position.getAmount()))
                         .collect(Collectors.toSet()),
                 supplierOrder.getOrderStatus().toDtoStatus()
         );
@@ -20,8 +27,14 @@ public static SupplierOrder fromDTO(SupplierOrderDTO supplierOrderDTO) {
         return new SupplierOrder(
                 supplierOrderDTO.getId(),
                 supplierOrderDTO.getTimestamp(),
+                SupplierFactory.toEntity(supplierOrderDTO.getSupplier()),
+                supplierOrderDTO.getExpectedDeliveryDate(),
+                supplierOrderDTO.getNotes(),
+                supplierOrderDTO.isAutomaticOrder(),
                 supplierOrderDTO.getPositions().stream()
-                        .map(position -> new SupplierOrder.Position(ProductFactory.toEntity(position.getProduct()), position.getAmount()))
+                        .map(position -> new SupplierOrder.Position(
+                                ProductFactory.toEntity(position.getProduct()), 
+                                position.getAmount()))
                         .collect(Collectors.toSet()),
                 supplierOrderDTO.getOrderStatus().toEntityStatus()
         );
diff --git a/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderRepository.java b/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderRepository.java
index c8402b5..c6b31fc 100644
--- a/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderRepository.java
+++ b/src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderRepository.java
@@ -1,5 +1,59 @@
 package com.bankly.vendura.inventory.supplierorder.model;
 
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.data.mongodb.repository.Query;
 
-public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {}
+import java.util.Date;
+import java.util.List;
+
+public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {
+    
+    /**
+     * Find supplier orders by status
+     */
+    Page<SupplierOrder> findByOrderStatus(SupplierOrder.OrderStatus orderStatus, Pageable pageable);
+    
+    /**
+     * Find supplier orders by multiple statuses
+     */
+    List<SupplierOrder> findByOrderStatusIn(List<SupplierOrder.OrderStatus> orderStatuses);
+    
+    /**
+     * Find supplier orders by supplier
+     * @param supplierId The supplier ID
+     * @param pageable Pagination parameters
+     * @return Page of supplier orders
+     */
+    @Query("{ 'supplier._id': ?0 }")
+    Page<SupplierOrder> findBySupplierIdOrderByCreatedAtDesc(String supplierId, Pageable pageable);
+    
+    /**
+     * Find supplier orders by expected delivery date range
+     */
+    Page<SupplierOrder> findByExpectedDeliveryDateBetween(Date startDate, Date endDate, Pageable pageable);
+    
+    /**
+     * Find automatic supplier orders
+     */
+    Page<SupplierOrder> findByAutomaticOrder(boolean isAutomaticOrder, Pageable pageable);
+    
+    /**
+     * Find supplier orders by supplier ID
+     * @param supplierId The supplier ID
+     * @param pageable Pagination parameters
+     * @return Page of supplier orders
+     */
+    @Query("{ 'supplier._id': ?0 }")
+    Page<SupplierOrder> findBySupplierId(String supplierId, Pageable pageable);
+    
+    /**
+     * Find supplier orders by automatic order flag
+     * @param isAutomatic Whether the order is automatic
+     * @param pageable Pagination parameters
+     * @return Page of supplier orders
+     */
+    @Query("{ 'automaticOrder': ?0 }")
+    Page<SupplierOrder> findIsAutomaticOrder(boolean isAutomatic, Pageable pageable);
+}
diff --git a/src/main/java/com/bankly/vendura/inventory/transactions/product/ProductTransactionControllerV1.java b/src/main/java/com/bankly/vendura/inventory/transactions/product/ProductTransactionControllerV1.java
new file mode 100644
index 0000000..af63913
--- /dev/null
+++ b/src/main/java/com/bankly/vendura/inventory/transactions/product/ProductTransactionControllerV1.java
@@ -0,0 +1,66 @@
+package com.bankly.vendura.inventory.transactions.product;
+
+import com.bankly.vendura.inventory.product.model.ProductRepository;
+import com.bankly.vendura.inventory.transactions.product.model.ProductTransaction;
+import com.bankly.vendura.inventory.transactions.product.model.ProductTransactionDTO;
+import com.bankly.vendura.inventory.transactions.product.model.ProductTransactionFactory;
+import com.bankly.vendura.utilities.exceptions.EntityRetrieveException;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/v1/transaction/product")
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+public class ProductTransactionControllerV1 {
+
+    private final ProductTransactionService productTransactionService;
+    private final ProductRepository productRepository;
+
+    /**
+     * Get all transactions for a product
+     * @param productId Product ID
+     * @param pageable Pagination parameters
+     * @return Page of transactions
+     */
+    @GetMapping("/product/{productId}")
+    @PreAuthorize("hasAnyRole('INVENTORY', 'ADMIN')")
+    public ResponseEntity<Page<ProductTransactionDTO>> getTransactionsByProductId(
+            @PathVariable("productId") String productId,
+            Pageable pageable) {
+        
+        // Verify the product exists
+        productRepository.findById(productId)
+                .orElseThrow(() -> new EntityRetrieveException(
+                        "Product not found", HttpStatus.NOT_FOUND, productId));
+        
+        // Get transactions
+        Page<ProductTransactionDTO> transactions = productTransactionService
+                .findTransactionsByProductId(productId, pageable)
+                .map(ProductTransactionFactory::toDTO);
+        
+        return ResponseEntity.ok(transactions);
+    }
+
+    /**
+     * Get all transactions in the system
+     * @param pageable Pagination parameters
+     * @return Page of transactions
+     */
+    @GetMapping
+    @PreAuthorize("hasAnyRole('INVENTORY', 'ADMIN')")
+    public ResponseEntity<Page<ProductTransactionDTO>> getAllTransactions(Pageable pageable) {
+        Page<ProductTransactionDTO> transactions = productTransactionService
+                .findAllTransactions(pageable)
+                .map(ProductTransactionFactory::toDTO);
+        
+        return ResponseEntity.ok(transactions);
+    }
+} 
\ No newline at end of file
diff --git a/src/main/java/com/bankly/vendura/inventory/transactions/product/ProductTransactionService.java b/src/main/java/com/bankly/vendura/inventory/transactions/product/ProductTransactionService.java
index bec6b6f..ff6e017 100644
--- a/src/main/java/com/bankly/vendura/inventory/transactions/product/ProductTransactionService.java
+++ b/src/main/java/com/bankly/vendura/inventory/transactions/product/ProductTransactionService.java
@@ -7,11 +7,15 @@
 import com.bankly.vendura.inventory.transactions.product.model.ProductTransactionRepository;
 import com.bankly.vendura.inventory.transactions.product.model.StockAggregationResult;
 import java.util.Date;
+import java.util.List;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.aggregation.Aggregation;
 import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.stereotype.Service;
 
 @Service
@@ -32,7 +36,8 @@ public void createTransaction(
             .product(product)
             .quantity(quantity)
             .transactionCause(transactionCause)
-            .transactionType(transactionCause.getTransactionType())
+            .transactionType(transactionCause != null ? transactionCause.getTransactionType() : 
+                quantity > 0 ? ProductTransaction.TransactionType.WAREHOUSE_IN : ProductTransaction.TransactionType.WAREHOUSE_OUT)
             .issuer(issuer)
             .message(message)
             .timestamp(new Date())
@@ -57,4 +62,23 @@ public long calculateCurrentStock(String productId) {
 
     return result == null ? 0 : result.getQuantity();
   }
+  
+  /**
+   * Find all transactions for a product
+   * @param productId The product ID
+   * @param pageable Pagination parameters
+   * @return Page of transactions
+   */
+  public Page<ProductTransaction> findTransactionsByProductId(String productId, Pageable pageable) {
+    return productTransactionRepository.findByProductIdOrderByTimestampDesc(productId, pageable);
+  }
+  
+  /**
+   * Find all transactions in the system
+   * @param pageable Pagination parameters
+   * @return Page of transactions
+   */
+  public Page<ProductTransaction> findAllTransactions(Pageable pageable) {
+    return productTransactionRepository.findAllByOrderByTimestampDesc(pageable);
+  }
 }
diff --git a/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionDTO.java b/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionDTO.java
new file mode 100644
index 0000000..8612d80
--- /dev/null
+++ b/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionDTO.java
@@ -0,0 +1,26 @@
+package com.bankly.vendura.inventory.transactions.product.model;
+
+import com.bankly.vendura.authentication.user.model.UserDTO;
+import com.bankly.vendura.inventory.product.model.ProductDTO;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ProductTransactionDTO {
+    private String id;
+    private ProductDTO product;
+    private long quantity;
+    private String transactionType;
+    private String message;
+    private String transactionCauseType;
+    private String transactionCauseId;
+    private UserDTO issuer;
+    private Date timestamp;
+} 
\ No newline at end of file
diff --git a/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionFactory.java b/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionFactory.java
new file mode 100644
index 0000000..20cc4df
--- /dev/null
+++ b/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionFactory.java
@@ -0,0 +1,40 @@
+package com.bankly.vendura.inventory.transactions.product.model;
+
+import com.bankly.vendura.authentication.user.model.UserFactory;
+import com.bankly.vendura.inventory.product.model.ProductFactory;
+
+public class ProductTransactionFactory {
+
+    public static ProductTransactionDTO toDTO(ProductTransaction transaction) {
+        if (transaction == null) {
+            return null;
+        }
+
+        ProductTransactionDTO dto = ProductTransactionDTO.builder()
+                .id(transaction.getId())
+                .product(ProductFactory.toDTO(transaction.getProduct()))
+                .quantity(transaction.getQuantity())
+                .transactionType(transaction.getTransactionType().name())
+                .message(transaction.getMessage())
+                .issuer(UserFactory.toDTO(transaction.getIssuer()))
+                .timestamp(transaction.getTimestamp())
+                .build();
+
+        // Handle the transaction cause if present
+        if (transaction.getTransactionCause() != null) {
+            dto.setTransactionCauseType(transaction.getTransactionCause().getClass().getSimpleName());
+            // Assuming the transaction cause has an ID field
+            try {
+                java.lang.reflect.Method getIdMethod = transaction.getTransactionCause().getClass().getMethod("getId");
+                Object id = getIdMethod.invoke(transaction.getTransactionCause());
+                if (id != null) {
+                    dto.setTransactionCauseId(id.toString());
+                }
+            } catch (Exception e) {
+                // Ignore if the method doesn't exist
+            }
+        }
+
+        return dto;
+    }
+} 
\ No newline at end of file
diff --git a/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionRepository.java b/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionRepository.java
index de07852..81070ec 100644
--- a/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionRepository.java
+++ b/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionRepository.java
@@ -1,5 +1,25 @@
 package com.bankly.vendura.inventory.transactions.product.model;
 
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.data.mongodb.repository.Query;
 
-public interface ProductTransactionRepository extends MongoRepository<ProductTransaction, String> {}
+public interface ProductTransactionRepository extends MongoRepository<ProductTransaction, String> {
+    
+    /**
+     * Find all transactions for a product
+     * @param productId The product ID
+     * @param pageable Pagination parameters
+     * @return Page of transactions
+     */
+    @Query("{ 'product._id': ?0 }")
+    Page<ProductTransaction> findByProductIdOrderByTimestampDesc(String productId, Pageable pageable);
+    
+    /**
+     * Find all transactions ordered by timestamp
+     * @param pageable Pagination parameters
+     * @return Page of transactions
+     */
+    Page<ProductTransaction> findAllByOrderByTimestampDesc(Pageable pageable);
+}


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.


<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**src/main/java/com/bankly/vendura/inventory/transactions/product/ProductTransactionService.java:39**
* [nitpick] Consider adding parentheses around the nested ternary expression to improve clarity and prevent potential misinterpretation of operator precedence.
```
.transactionType(transactionCause != null ? transactionCause.getTransactionType() : quantity > 0 ? ProductTransaction.TransactionType.WAREHOUSE_IN : ProductTransaction.TransactionType.WAREHOUSE_OUT)
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T13:18:50Z
user: login: antonbowe
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T16:44:25Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-10T22:05:30Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-10T22:15:57Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-10T22:19:54Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-10T22:23:11Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-10T22:28:35Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-10T22:32:58Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-10T22:37:21Z
user: login: antonbowe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T09:21:06Z
user: login: antonbowe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T09:23:57Z
user: login: antonbowe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T09:25:55Z
user: login: antonbowe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T09:27:05Z
user: login: antonbowe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T09:27:11Z
user: login: antonbowe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T09:29:33Z
user: login: antonbowe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T09:33:46Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T17:49:12Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T18:02:32Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T18:07:18Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T18:13:35Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T18:15:06Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T18:19:15Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T18:22:55Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T18:23:03Z
user: login: lulkebit
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T18:26:27Z
user: login: antonbowe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T08:39:09Z
user: login: antonbowe
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T08:41:08Z
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 22 out of 22 changed files in this pull request and generated no comments.


<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**src/main/java/com/bankly/vendura/inventory/transactions/product/ProductTransactionService.java:39**
* The nested ternary operator used for setting the transactionType is hard to read and may lead to logical ambiguities; consider adding parentheses to clarify the intended evaluation order.
```
.transactionType(transactionCause != null ? transactionCause.getTransactionType() : quantity > 0 ? ProductTransaction.TransactionType.WAREHOUSE_IN : ProductTransaction.TransactionType.WAREHOUSE_OUT)
```
**src/main/java/com/bankly/vendura/inventory/product/model/ProductFactory.java:82**
* Ensure that using getPrice() instead of getPurchasePrice() for the price history DTO is intentional, as this change could affect how price data is represented in the DTO.
```
priceHistory.getPrice()
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T07:25:43Z
user: login: antonbowe
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T09:09:50Z
user: login: antonbowe
body: 🙏🙏🙏
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T09:39:07Z

Review comments:
diff_hunk: @@ -0,0 +1,144 @@
+package com.bankly.vendura.inventory.product;
+
+import com.bankly.vendura.authentication.user.model.User;
+import com.bankly.vendura.authentication.user.model.UserRepository;
+import com.bankly.vendura.inventory.product.model.Product;
+import com.bankly.vendura.inventory.product.model.ProductRepository;
+import com.bankly.vendura.inventory.supplier.model.Supplier;
+import com.bankly.vendura.inventory.supplierorder.SupplierOrderService;
+import com.bankly.vendura.inventory.supplierorder.model.SupplierOrder;
+import com.bankly.vendura.inventory.supplierorder.model.SupplierOrderDTO;
+import com.bankly.vendura.inventory.transactions.product.ProductTransactionService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+@Service
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+public class ProductStockService {
+
+    private final ProductRepository productRepository;
+    private final ProductTransactionService transactionService;
+    private final SupplierOrderService supplierOrderService;
+    private final UserRepository userRepository;
+
+    /**
+     * Check stock levels for all products and create supplier orders if needed
+     */
+    @Transactional
+    @Scheduled(cron = "0 0 * * * *") // Run once per hour
+    public void checkStockLevelsAndReorder() {
+        // Group products by supplier that need reordering
+        Map<Supplier, List<Product>> productsToReorder = new HashMap<>();
+        
+        for (Product product : productRepository.findAll()) {
+            if (product.getDefaultSupplier() == null || product.getReorderPoint() == null) {
+                continue; // Skip products without supplier or reorder point
+            }
+            
+            long currentStock = transactionService.calculateCurrentStock(product);
+            
path: src/main/java/com/bankly/vendura/inventory/product/ProductStockService.java
user: login: Copilot
body: The method calculateCurrentStock expects a product ID, so pass product.getId() instead of the product object.
```suggestion
            long currentStock = transactionService.calculateCurrentStock(product.getId());
```
created_at: 2025-04-09T13:18:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,144 @@
+package com.bankly.vendura.inventory.product;
+
+import com.bankly.vendura.authentication.user.model.User;
+import com.bankly.vendura.authentication.user.model.UserRepository;
+import com.bankly.vendura.inventory.product.model.Product;
+import com.bankly.vendura.inventory.product.model.ProductRepository;
+import com.bankly.vendura.inventory.supplier.model.Supplier;
+import com.bankly.vendura.inventory.supplierorder.SupplierOrderService;
+import com.bankly.vendura.inventory.supplierorder.model.SupplierOrder;
+import com.bankly.vendura.inventory.supplierorder.model.SupplierOrderDTO;
+import com.bankly.vendura.inventory.transactions.product.ProductTransactionService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+@Service
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+public class ProductStockService {
+
+    private final ProductRepository productRepository;
+    private final ProductTransactionService transactionService;
+    private final SupplierOrderService supplierOrderService;
+    private final UserRepository userRepository;
+
+    /**
+     * Check stock levels for all products and create supplier orders if needed
+     */
+    @Transactional
+    @Scheduled(cron = "0 0 * * * *") // Run once per hour
+    public void checkStockLevelsAndReorder() {
+        // Group products by supplier that need reordering
+        Map<Supplier, List<Product>> productsToReorder = new HashMap<>();
+        
+        for (Product product : productRepository.findAll()) {
+            if (product.getDefaultSupplier() == null || product.getReorderPoint() == null) {
+                continue; // Skip products without supplier or reorder point
+            }
+            
+            long currentStock = transactionService.calculateCurrentStock(product);
+            
+            // Check if stock is below reorder point
+            if (currentStock <= product.getReorderPoint()) {
+                productsToReorder
+                    .computeIfAbsent(product.getDefaultSupplier(), k -> new ArrayList<>())
+                    .add(product);
+            }
+        }
+        
+        // Create supplier orders for each supplier
+        for (Map.Entry<Supplier, List<Product>> entry : productsToReorder.entrySet()) {
+            createSupplierOrderForProducts(entry.getKey(), entry.getValue());
+        }
+    }
+    
+    /**
+     * Create a supplier order for a list of products
+     */
+    private void createSupplierOrderForProducts(Supplier supplier, List<Product> products) {
+        if (products.isEmpty()) {
+            return;
+        }
+        
+        // Create supplier order positions
+        Set<SupplierOrderDTO.Position> positions = new HashSet<>();
+        for (Product product : products) {
+            long currentStock = transactionService.calculateCurrentStock(product);
+            long quantityToOrder = product.getReorderQuantity() != null ? 
+                    product.getReorderQuantity() : 
+                    (product.getMaxStockLevel() != null ? 
+                            product.getMaxStockLevel() - currentStock : 10);
+                            
+            SupplierOrderDTO.Position position = new SupplierOrderDTO.Position();
+            position.setProduct(com.bankly.vendura.inventory.product.model.ProductFactory.toDTO(product));
+            position.setAmount((int) quantityToOrder);
+            positions.add(position);
+        }
+        
+        // Create the supplier order
+        SupplierOrderDTO orderDTO = new SupplierOrderDTO();
+        orderDTO.setTimestamp(new Date());
+        orderDTO.setPositions(positions);
+        orderDTO.setOrderStatus(SupplierOrderDTO.OrderStatus.PLACED);
+        
+        supplierOrderService.create(orderDTO);
path: src/main/java/com/bankly/vendura/inventory/product/ProductStockService.java
user: login: Copilot
body: Set the supplier field on the SupplierOrderDTO (e.g. orderDTO.setSupplier(SupplierFactory.toDTO(supplier))) before creating the order to ensure the supplier information is included.
created_at: 2025-04-09T13:18:50Z
author_association: CONTRIBUTOR
path: src/main/java/com/bankly/vendura/authentication/user/model/UserFactory.java
user: login: antonbowe
body: Ich würde an der Stelle dann auch die fromDTO oder toEntity Methode aus dem User hier in die UserFactory übernehmen
created_at: 2025-04-10T15:50:43Z
author_association: CONTRIBUTOR
path: src/main/java/com/bankly/vendura/inventory/product/ProductControllerV1.java
user: login: antonbowe
body: Bitte wegen SRP in eigene Methode im ProductService auslagern
created_at: 2025-04-10T15:52:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -25,12 +25,32 @@ public class Product {
 
   private String name;
 
+  private String shortDescription;
+
+  private String longDescription;
+
+  private String sku;
path: src/main/java/com/bankly/vendura/inventory/product/model/Product.java
user: login: antonbowe
body: Nur zum Verständnis: Wofür die SKU? Usages sind nur für Transfer ins und aus dem DTO.
created_at: 2025-04-10T15:58:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -25,12 +25,32 @@ public class Product {
 
   private String name;
 
+  private String shortDescription;
+
+  private String longDescription;
+
+  private String sku;
path: src/main/java/com/bankly/vendura/inventory/product/model/Product.java
user: login: antonbowe
body: Products sind die einzigen Entities, deren ID sich bewusst verändern lässt, weil sie durch einen Barcode? identifiziert werden, der = ID ist. Unterscheidet sich die SKU davon? Falls nein -> ID verwenden
created_at: 2025-04-10T15:59:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -25,12 +25,32 @@ public class Product {
 
   private String name;
 
+  private String shortDescription;
+
+  private String longDescription;
+
+  private String sku;
+
   @DBRef private ProductCategory productCategory;
 
   @DBRef private Brand brand;
 
   @DBRef private Supplier defaultSupplier;
 
+  private Long minStockLevel;
+
+  private Long maxStockLevel;
+
+  private Long reorderPoint;
+
+  private Long reorderQuantity;
+
+  private Long leadTimeInDays;
+
+  private double price;
path: src/main/java/com/bankly/vendura/inventory/product/model/Product.java
user: login: antonbowe
body: Price und purchase price sind redundant und können so nicht gespeichert werden, sondern über die priceHistories. Dort kann mit konkretem Timestamp, price, purchasePrice und Supplier gearbeitet werden. Der aktuelle purchasePrice und price ergibt sich immer aus dem PriceHistory Eintrag mit dem spätesten Datum. Das ermöglicht uns Liniendiagrammanalysen mit Preisschwankungen, Einkaufspreisschwankungen und einer flächigen Darstellung des Gewinns/Verlusts pro Einheit.
created_at: 2025-04-10T16:01:05Z
author_association: CONTRIBUTOR
path: src/main/java/com/bankly/vendura/inventory/product/model/ProductFactory.java
user: login: antonbowe
body: Du nimmst mir hier meine PriceHistories weg und ich sehe keine vernünftige funktionierende Alternative abgesehen von statischen und ungeloggten Preisen
created_at: 2025-04-10T16:03:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -21,15 +29,60 @@
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 public class SupplierOrderService {
 
+  private static final Logger logger = LoggerFactory.getLogger(SupplierOrderService.class);
+  
   private final ProductTransactionService productTransactionService;
   private final UserRepository userRepository;
   private final SupplierOrderRepository supplierOrderRepository;
+  private final SupplierRepository supplierRepository;
 
+  /**
+   * Create a new supplier order
+   */
+  @Transactional
   public SupplierOrder create(SupplierOrderDTO supplierOrderDTO) {
+    // Set default values if not provided
+    if (supplierOrderDTO.getTimestamp() == null) {
+      supplierOrderDTO.setTimestamp(new Date());
+    }
+    
+    if (supplierOrderDTO.getOrderStatus() == null) {
+      supplierOrderDTO.setOrderStatus(SupplierOrderDTO.OrderStatus.PLACED);
+    }
+    
+    if (supplierOrderDTO.getPurchaseOrderNumber() == null || supplierOrderDTO.getPurchaseOrderNumber().isEmpty()) {
path: src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java
user: login: antonbowe
body: Dafür ist eigentlich die ID da. Jetzt haben wir zwei Identifikationsfelder
created_at: 2025-04-10T16:05:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -21,15 +29,60 @@
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 public class SupplierOrderService {
 
+  private static final Logger logger = LoggerFactory.getLogger(SupplierOrderService.class);
+  
   private final ProductTransactionService productTransactionService;
   private final UserRepository userRepository;
   private final SupplierOrderRepository supplierOrderRepository;
+  private final SupplierRepository supplierRepository;
 
+  /**
+   * Create a new supplier order
+   */
+  @Transactional
   public SupplierOrder create(SupplierOrderDTO supplierOrderDTO) {
+    // Set default values if not provided
+    if (supplierOrderDTO.getTimestamp() == null) {
+      supplierOrderDTO.setTimestamp(new Date());
+    }
+    
+    if (supplierOrderDTO.getOrderStatus() == null) {
+      supplierOrderDTO.setOrderStatus(SupplierOrderDTO.OrderStatus.PLACED);
+    }
+    
+    if (supplierOrderDTO.getPurchaseOrderNumber() == null || supplierOrderDTO.getPurchaseOrderNumber().isEmpty()) {
+      supplierOrderDTO.setPurchaseOrderNumber(generatePurchaseOrderNumber());
+    }
+    
     SupplierOrder supplierOrder = SupplierOrderFactory.fromDTO(supplierOrderDTO);
     return this.supplierOrderRepository.save(supplierOrder);
   }
 
+  /**
+   * Generate a unique purchase order number
+   */
+  private String generatePurchaseOrderNumber() {
+    return "PO-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
path: src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java
user: login: antonbowe
body: hier muss geprüft werden, ob die Nummer schon vergeben ist
created_at: 2025-04-10T16:06:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -23,6 +24,13 @@ public class SupplierOrder implements ProductTransactable {
   @Id private String id;
 
   private Date timestamp;
+  
+  @DBRef private Supplier supplier;
+  
+  private String purchaseOrderNumber;
+  private Date expectedDeliveryDate;
+  private String notes;
+  private boolean isAutomaticOrder;
path: src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrder.java
user: login: antonbowe
body: Nur ästhetisch:
Property -> automaticOrder
Getter -> isAutomaticOrder()
created_at: 2025-04-10T16:38:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,25 @@
 package com.bankly.vendura.inventory.transactions.product.model;
 
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.data.mongodb.repository.Query;
 
-public interface ProductTransactionRepository extends MongoRepository<ProductTransaction, String> {}
+public interface ProductTransactionRepository extends MongoRepository<ProductTransaction, String> {
+    
+    /**
+     * Find all transactions for a product
+     * @param productId The product ID
+     * @param pageable Pagination parameters
+     * @return Page of transactions
+     */
+    @Query("{ 'product._id': ?0 }")
path: src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionRepository.java
user: login: antonbowe
body: was macht die Query hier? Oben arbeitest du mit product_Id im Methodennamen hier mit Query - ggf. begründet?
created_at: 2025-04-10T16:44:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -21,15 +29,60 @@
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 public class SupplierOrderService {
 
+  private static final Logger logger = LoggerFactory.getLogger(SupplierOrderService.class);
+  
   private final ProductTransactionService productTransactionService;
   private final UserRepository userRepository;
   private final SupplierOrderRepository supplierOrderRepository;
+  private final SupplierRepository supplierRepository;
 
+  /**
+   * Create a new supplier order
+   */
+  @Transactional
   public SupplierOrder create(SupplierOrderDTO supplierOrderDTO) {
+    // Set default values if not provided
+    if (supplierOrderDTO.getTimestamp() == null) {
+      supplierOrderDTO.setTimestamp(new Date());
+    }
+    
+    if (supplierOrderDTO.getOrderStatus() == null) {
+      supplierOrderDTO.setOrderStatus(SupplierOrderDTO.OrderStatus.PLACED);
+    }
+    
+    if (supplierOrderDTO.getPurchaseOrderNumber() == null || supplierOrderDTO.getPurchaseOrderNumber().isEmpty()) {
+      supplierOrderDTO.setPurchaseOrderNumber(generatePurchaseOrderNumber());
+    }
+    
     SupplierOrder supplierOrder = SupplierOrderFactory.fromDTO(supplierOrderDTO);
     return this.supplierOrderRepository.save(supplierOrder);
   }
 
+  /**
+   * Generate a unique purchase order number
+   */
+  private String generatePurchaseOrderNumber() {
+    return "PO-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
path: src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java
user: login: lulkebit
body: Guter Punkt! Ich werde die Methode anpassen, um sicherzustellen, dass keine doppelten Bestellnummern generiert werden:

```java
private String generatePurchaseOrderNumber() {
    String poNumber;
    do {
        poNumber = "PO-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    } while (purchaseOrderRepository.existsByPoNumber(poNumber));
    
    return poNumber;
}
```

Damit wird eine Schleife durchlaufen, bis eine eindeutige Nummer gefunden wird. Danke für den Hinweis!
created_at: 2025-04-10T22:05:30Z
author_association: COLLABORATOR
diff_hunk: @@ -1,5 +1,25 @@
 package com.bankly.vendura.inventory.transactions.product.model;
 
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.data.mongodb.repository.Query;
 
-public interface ProductTransactionRepository extends MongoRepository<ProductTransaction, String> {}
+public interface ProductTransactionRepository extends MongoRepository<ProductTransaction, String> {
+    
+    /**
+     * Find all transactions for a product
+     * @param productId The product ID
+     * @param pageable Pagination parameters
+     * @return Page of transactions
+     */
+    @Query("{ 'product._id': ?0 }")
path: src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransactionRepository.java
user: login: lulkebit
body: Die Methode `findByProductIdOrderByTimestampDesc` verwendet die `@Query`-Annotation, weil die tatsächliche Dokumentstruktur in MongoDB anders ist als der Methodenname suggeriert. 

In unserer `ProductTransaction`-Klasse (aus `vendura-backend-service/src/main/java/com/bankly/vendura/inventory/transactions/product/model/ProductTransaction.java`) speichern wir das Produkt als DBRef:
```java
@DBRef private Product product;
```

Das bedeutet, dass wir nicht direkt auf ein Feld `productId` zugreifen können, sondern auf das verschachtelte Feld `_id` innerhalb des `product`-Objekts. Die Query `{ 'product._id': ?0 }` adressiert genau diese Struktur.

Der Methodenname folgt dennoch den Spring Data Namenskonventionen für eine intuitive API, während die Query die tatsächliche Datenbankstruktur berücksichtigt. Dies ist ein üblicher Ansatz, um die Datenbankimplementierung von der API-Schnittstelle zu entkoppeln.

created_at: 2025-04-10T22:15:57Z
author_association: COLLABORATOR
path: src/main/java/com/bankly/vendura/authentication/user/model/UserFactory.java
user: login: lulkebit
body: Nach Analyse des Codes schlage ich vor, die Konvertierungslogik zu vereinheitlichen und dem Muster anderer Factory-Klassen im Projekt zu folgen.

Aktuell haben wir zwei identische Methoden für die Konvertierung von User zu UserDTO:
1. `UserDTO.fromUser(User user)` in UserDTO.java
2. `UserFactory.toDTO(User user)` in UserFactory.java

Dies ist inkonsistent mit anderen Factory-Klassen wie GiftCardFactory, SupplierFactory und ProductFactory, die sowohl `toDTO` als auch `toEntity`-Methoden enthalten.

Ich würde folgende Implementierung einer `toEntity`-Methode in der UserFactory vorschlagen:

```java
public static User toEntity(UserDTO userDTO) {
    if (userDTO == null) {
        return null;
    }
    
    User user = new User();
    user.setId(userDTO.getId());
    user.setUsername(userDTO.getUsername());
    user.setPassword(userDTO.getPassword());
    user.setEnabled(userDTO.getEnabled() == null || userDTO.getEnabled());
    user.setLocked(userDTO.getLocked() == null || userDTO.getLocked());
    
    // Hinweis: Die Konvertierung von Role-IDs zu Role-Entitäten würde ein RoleRepository benötigen,
    // was dieser Factory-Methode nicht zur Verfügung steht. Dies sollte auf Service-Ebene behandelt werden.
    
    return user;
}
```

Für vollständige Konsistenz im Code sollten wir auch:
1. Die `fromUser`-Methode aus UserDTO entfernen
2. Alle Referenzen zu `UserDTO.fromUser` durch `UserFactory.toDTO` ersetzen

Dies entspricht der Art und Weise, wie andere DTOs und Entitäten im Projekt konvertiert werden und macht den Code konsistenter und leichter zu warten.

created_at: 2025-04-10T22:19:54Z
author_association: COLLABORATOR
diff_hunk: @@ -25,12 +25,32 @@ public class Product {
 
   private String name;
 
+  private String shortDescription;
+
+  private String longDescription;
+
+  private String sku;
path: src/main/java/com/bankly/vendura/inventory/product/model/Product.java
user: login: lulkebit
body: Die SKU und die Produkt-ID dienen aktuell im Code unterschiedlichen Zwecken, wobei eine klare Abgrenzung fehlt:

- Die `id` ist der primäre MongoDB-Dokument-Identifier
- Die `sku` ist ein separates Feld, das in den DTO-Transformationen übertragen wird

In der Frontend-Implementierung (`ProductService.js`) wird interessanterweise ein Teil der ID als SKU verwendet:
```javascript
sku: product.id.substring(0, 8), // Using part of ID as SKU since backend doesn't have SKU
```

Da die Produkt-IDs durch Barcodes definiert werden und veränderbar sind (wie im Kommentar erwähnt), erscheint eine separate SKU tatsächlich redundant. Wenn der Barcode bereits als eindeutiger Produktidentifikator dient, sollte dieser als ID verwendet werden und das SKU-Feld kann entfernt werden.

Die aktuelle Implementierung schafft unnötige Duplizierung und potentielle Inkonsistenzen. Ich empfehle, nur das ID-Feld zu verwenden und das SKU-Feld zu entfernen, sofern keine besonderen Anforderungen vorliegen, die eine separate SKU notwendig machen.

created_at: 2025-04-10T22:23:11Z
author_association: COLLABORATOR
diff_hunk: @@ -25,12 +25,32 @@ public class Product {
 
   private String name;
 
+  private String shortDescription;
+
+  private String longDescription;
+
+  private String sku;
+
   @DBRef private ProductCategory productCategory;
 
   @DBRef private Brand brand;
 
   @DBRef private Supplier defaultSupplier;
 
+  private Long minStockLevel;
+
+  private Long maxStockLevel;
+
+  private Long reorderPoint;
+
+  private Long reorderQuantity;
+
+  private Long leadTimeInDays;
+
+  private double price;
path: src/main/java/com/bankly/vendura/inventory/product/model/Product.java
user: login: lulkebit
body: Ich stimme dem Kommentar vollständig zu. Die aktuellen Felder `price` und `purchasePrice` in der `Product`-Klasse sind tatsächlich redundant, da wir bereits mit `priceHistories` arbeiten.

Die vorgeschlagene Änderung bietet mehrere Vorteile:

1. **Bessere Datenintegrität**: Durch die Entfernung der redundanten Felder vermeiden wir inkonsistente Zustände.

2. **Klarere Geschäftslogik**: Der aktuelle Preis sollte immer der neueste Eintrag in `priceHistories` sein (mit dem spätesten Timestamp).

3. **Erweiterte Analysemöglichkeiten**: Die Historie ermöglicht Visualisierungen von Preisschwankungen, Einkaufspreisschwankungen und Gewinnmargen über Zeit.

Das Frontend in `ProductService.js` nutzt bereits diese Logik zur Preisberechnung:
```javascript
// Sort by timestamp descending to get latest price
const sortedPrices = [...product.priceHistories].sort(
  (a, b) => new Date(b.timestamp) - new Date(a.timestamp)
);
price = sortedPrices[0].price;
```

Ähnlich wird in `SupplierOrder.java` die Preishistorie für Berechnungen verwendet.

Ich werde diese Änderung umsetzen und die redundanten Felder entfernen, stattdessen aber Getter-Methoden hinzufügen, die den aktuellen Preis dynamisch berechnen.

created_at: 2025-04-10T22:28:35Z
author_association: COLLABORATOR
path: src/main/java/com/bankly/vendura/inventory/product/model/ProductFactory.java
user: login: lulkebit
body: In der `ProductFactory.java` werden die PriceHistories in den Konvertierungsmethoden nicht berücksichtigt:

In beiden Klassen (`Product.java` und `ProductDTO.java`) sind PriceHistories als Collections definiert:
- `Product.java`: `private List<PriceHistory> priceHistories;`
- `ProductDTO.java`: `private List<PriceHistoryDTO> priceHistories;`

Die Factory-Methoden `toDTO()` und `toEntity()` in `ProductFactory.java` setzen jedoch nur die einzelnen Attribute wie Name, Beschreibung, SKU usw. um, aber übertragen nicht die Listen der Preishistorien. 

Zwar existieren in der Factory Methoden zur Konvertierung einzelner PriceHistory-Objekte (`toDTO` und `toEntity` für `PriceHistory`/`PriceHistoryDTO`), aber die Listen werden beim Mapping zwischen `Product` und `ProductDTO` nicht berücksichtigt.

Die Lösung wäre, die Factory-Methoden zu erweitern, damit sie auch die PriceHistories-Listen konvertieren, ähnlich wie es bei `connectedProducts` bereits implementiert ist.

Der `ProductService` enthält in der `update()`-Methode bereits die korrekte Behandlung von PriceHistories, aber ohne die entsprechende Konvertierung in der Factory gehen diese Daten bei jeder Konvertierung verloren.

created_at: 2025-04-10T22:32:58Z
author_association: COLLABORATOR
diff_hunk: @@ -21,15 +29,60 @@
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 public class SupplierOrderService {
 
+  private static final Logger logger = LoggerFactory.getLogger(SupplierOrderService.class);
+  
   private final ProductTransactionService productTransactionService;
   private final UserRepository userRepository;
   private final SupplierOrderRepository supplierOrderRepository;
+  private final SupplierRepository supplierRepository;
 
+  /**
+   * Create a new supplier order
+   */
+  @Transactional
   public SupplierOrder create(SupplierOrderDTO supplierOrderDTO) {
+    // Set default values if not provided
+    if (supplierOrderDTO.getTimestamp() == null) {
+      supplierOrderDTO.setTimestamp(new Date());
+    }
+    
+    if (supplierOrderDTO.getOrderStatus() == null) {
+      supplierOrderDTO.setOrderStatus(SupplierOrderDTO.OrderStatus.PLACED);
+    }
+    
+    if (supplierOrderDTO.getPurchaseOrderNumber() == null || supplierOrderDTO.getPurchaseOrderNumber().isEmpty()) {
path: src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java
user: login: lulkebit
body: Die PurchaseOrderNumber dient hier als fachliche Referenz für Bestellungen und hat einen anderen Zweck als die technische ID. Während die ID für die interne Datenbankidentifikation genutzt wird, stellt die PurchaseOrderNumber ein benutzerfreundliches Referenzformat dar (z.B. "PO-12345ABC"), das in der Kommunikation mit Lieferanten und in geschäftlichen Dokumenten verwendet werden kann.

Diese Trennung zwischen technischer ID und fachlicher Referenznummer folgt dem Domain-Driven Design Ansatz und ist in Geschäftsanwendungen üblich. Die automatische Generierung sichert zudem, dass jede Bestellung eine eindeutige Referenznummer erhält, falls keine manuell angegeben wird.

created_at: 2025-04-10T22:37:21Z
author_association: COLLABORATOR
diff_hunk: @@ -25,12 +25,32 @@ public class Product {
 
   private String name;
 
+  private String shortDescription;
+
+  private String longDescription;
+
+  private String sku;
path: src/main/java/com/bankly/vendura/inventory/product/model/Product.java
user: login: antonbowe
body: -> SKU fällt weg
-> ID benutzen
-> wenn ID bei create == null, auto-generieren in dem von dir gewünschten Format
created_at: 2025-04-11T09:21:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -25,12 +25,32 @@ public class Product {
 
   private String name;
 
+  private String shortDescription;
+
+  private String longDescription;
+
+  private String sku;
+
   @DBRef private ProductCategory productCategory;
 
   @DBRef private Brand brand;
 
   @DBRef private Supplier defaultSupplier;
 
+  private Long minStockLevel;
+
+  private Long maxStockLevel;
+
+  private Long reorderPoint;
+
+  private Long reorderQuantity;
+
+  private Long leadTimeInDays;
+
+  private double price;
path: src/main/java/com/bankly/vendura/inventory/product/model/Product.java
user: login: antonbowe
body: -> Änderung umsetzen!
created_at: 2025-04-11T09:23:57Z
author_association: CONTRIBUTOR
path: src/main/java/com/bankly/vendura/inventory/product/model/ProductFactory.java
user: login: antonbowe
body: -> Implementierung wieder hinzufügen
created_at: 2025-04-11T09:25:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -21,15 +29,60 @@
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 public class SupplierOrderService {
 
+  private static final Logger logger = LoggerFactory.getLogger(SupplierOrderService.class);
+  
   private final ProductTransactionService productTransactionService;
   private final UserRepository userRepository;
   private final SupplierOrderRepository supplierOrderRepository;
+  private final SupplierRepository supplierRepository;
 
+  /**
+   * Create a new supplier order
+   */
+  @Transactional
   public SupplierOrder create(SupplierOrderDTO supplierOrderDTO) {
+    // Set default values if not provided
+    if (supplierOrderDTO.getTimestamp() == null) {
+      supplierOrderDTO.setTimestamp(new Date());
+    }
+    
+    if (supplierOrderDTO.getOrderStatus() == null) {
+      supplierOrderDTO.setOrderStatus(SupplierOrderDTO.OrderStatus.PLACED);
+    }
+    
+    if (supplierOrderDTO.getPurchaseOrderNumber() == null || supplierOrderDTO.getPurchaseOrderNumber().isEmpty()) {
path: src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java
user: login: antonbowe
body: -> ID Feld benutzen
created_at: 2025-04-11T09:27:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -21,15 +29,60 @@
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 public class SupplierOrderService {
 
+  private static final Logger logger = LoggerFactory.getLogger(SupplierOrderService.class);
+  
   private final ProductTransactionService productTransactionService;
   private final UserRepository userRepository;
   private final SupplierOrderRepository supplierOrderRepository;
+  private final SupplierRepository supplierRepository;
 
+  /**
+   * Create a new supplier order
+   */
+  @Transactional
   public SupplierOrder create(SupplierOrderDTO supplierOrderDTO) {
+    // Set default values if not provided
+    if (supplierOrderDTO.getTimestamp() == null) {
+      supplierOrderDTO.setTimestamp(new Date());
+    }
+    
+    if (supplierOrderDTO.getOrderStatus() == null) {
+      supplierOrderDTO.setOrderStatus(SupplierOrderDTO.OrderStatus.PLACED);
+    }
+    
+    if (supplierOrderDTO.getPurchaseOrderNumber() == null || supplierOrderDTO.getPurchaseOrderNumber().isEmpty()) {
+      supplierOrderDTO.setPurchaseOrderNumber(generatePurchaseOrderNumber());
+    }
+    
     SupplierOrder supplierOrder = SupplierOrderFactory.fromDTO(supplierOrderDTO);
     return this.supplierOrderRepository.save(supplierOrder);
   }
 
+  /**
+   * Generate a unique purchase order number
+   */
+  private String generatePurchaseOrderNumber() {
+    return "PO-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
path: src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java
user: login: antonbowe
body: -> umsetzen
created_at: 2025-04-11T09:27:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,36 @@
 package com.bankly.vendura.inventory.supplierorder.model;
 
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.repository.MongoRepository;
 
-public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {}
+import java.util.Date;
+import java.util.List;
+
+public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {
+    
+    /**
+     * Find supplier orders by status
+     */
+    Page<SupplierOrder> findByOrderStatus(SupplierOrder.OrderStatus orderStatus, Pageable pageable);
+    
+    /**
+     * Find supplier orders by multiple statuses
+     */
+    List<SupplierOrder> findByOrderStatusIn(List<SupplierOrder.OrderStatus> orderStatuses);
+    
+    /**
+     * Find supplier orders by supplier
+     */
+    Page<SupplierOrder> findBySupplier_Id(String supplierId, Pageable pageable);
+    
+    /**
+     * Find supplier orders by expected delivery date range
+     */
+    Page<SupplierOrder> findByExpectedDeliveryDateBetween(Date startDate, Date endDate, Pageable pageable);
+    
+    /**
+     * Find automatic supplier orders
+     */
+    Page<SupplierOrder> findByIsAutomaticOrder(boolean isAutomaticOrder, Pageable pageable);
path: src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderRepository.java
user: login: antonbowe
body: Entsprechend des Property Names anpassen
created_at: 2025-04-11T09:29:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,36 @@
 package com.bankly.vendura.inventory.supplierorder.model;
 
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.repository.MongoRepository;
 
-public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {}
+import java.util.Date;
+import java.util.List;
+
+public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {
+    
+    /**
+     * Find supplier orders by status
+     */
+    Page<SupplierOrder> findByOrderStatus(SupplierOrder.OrderStatus orderStatus, Pageable pageable);
+    
+    /**
+     * Find supplier orders by multiple statuses
+     */
+    List<SupplierOrder> findByOrderStatusIn(List<SupplierOrder.OrderStatus> orderStatuses);
+    
+    /**
+     * Find supplier orders by supplier
+     */
+    Page<SupplierOrder> findBySupplier_Id(String supplierId, Pageable pageable);
path: src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderRepository.java
user: login: antonbowe
body: Hässlich
created_at: 2025-04-11T09:33:45Z
author_association: CONTRIBUTOR
path: src/main/java/com/bankly/vendura/authentication/user/model/UserFactory.java
user: login: lulkebit
body: Wurde umgesetzt: https://github.com/de-bankly/vendura-backend-service/commit/a05abb397cd5d054cf469a66fda34d88c757ff70
created_at: 2025-04-11T17:49:11Z
author_association: COLLABORATOR
diff_hunk: @@ -25,12 +25,32 @@ public class Product {
 
   private String name;
 
+  private String shortDescription;
+
+  private String longDescription;
+
+  private String sku;
path: src/main/java/com/bankly/vendura/inventory/product/model/Product.java
user: login: lulkebit
body: Umgesetzt: https://github.com/de-bankly/vendura-backend-service/commit/caea746891f734417a66995b0650beb776617063 , https://github.com/de-bankly/vendura-app/commit/0fd8373b1bf0b0a8ead164c4bb36777425717c70
created_at: 2025-04-11T18:02:31Z
author_association: COLLABORATOR
path: src/main/java/com/bankly/vendura/inventory/product/ProductControllerV1.java
user: login: lulkebit
body: Umgesetzt: https://github.com/de-bankly/vendura-backend-service/commit/156de40ce153295b322d892f755730309fe0288b
created_at: 2025-04-11T18:07:18Z
author_association: COLLABORATOR
diff_hunk: @@ -25,12 +25,32 @@ public class Product {
 
   private String name;
 
+  private String shortDescription;
+
+  private String longDescription;
+
+  private String sku;
+
   @DBRef private ProductCategory productCategory;
 
   @DBRef private Brand brand;
 
   @DBRef private Supplier defaultSupplier;
 
+  private Long minStockLevel;
+
+  private Long maxStockLevel;
+
+  private Long reorderPoint;
+
+  private Long reorderQuantity;
+
+  private Long leadTimeInDays;
+
+  private double price;
path: src/main/java/com/bankly/vendura/inventory/product/model/Product.java
user: login: lulkebit
body: Umgesetzt: https://github.com/de-bankly/vendura-backend-service/commit/a6c54cdf33726dbd101667aaaea06116c9872f80
created_at: 2025-04-11T18:13:35Z
author_association: COLLABORATOR
path: src/main/java/com/bankly/vendura/inventory/product/model/ProductFactory.java
user: login: lulkebit
body: https://github.com/de-bankly/vendura-backend-service/commit/a6c54cdf33726dbd101667aaaea06116c9872f80
created_at: 2025-04-11T18:15:06Z
author_association: COLLABORATOR
diff_hunk: @@ -21,15 +29,60 @@
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 public class SupplierOrderService {
 
+  private static final Logger logger = LoggerFactory.getLogger(SupplierOrderService.class);
+  
   private final ProductTransactionService productTransactionService;
   private final UserRepository userRepository;
   private final SupplierOrderRepository supplierOrderRepository;
+  private final SupplierRepository supplierRepository;
 
+  /**
+   * Create a new supplier order
+   */
+  @Transactional
   public SupplierOrder create(SupplierOrderDTO supplierOrderDTO) {
+    // Set default values if not provided
+    if (supplierOrderDTO.getTimestamp() == null) {
+      supplierOrderDTO.setTimestamp(new Date());
+    }
+    
+    if (supplierOrderDTO.getOrderStatus() == null) {
+      supplierOrderDTO.setOrderStatus(SupplierOrderDTO.OrderStatus.PLACED);
+    }
+    
+    if (supplierOrderDTO.getPurchaseOrderNumber() == null || supplierOrderDTO.getPurchaseOrderNumber().isEmpty()) {
path: src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderService.java
user: login: lulkebit
body: Umgesetzt: https://github.com/de-bankly/vendura-backend-service/commit/4e6694c5f5f2ae11d6dd8bb5cf20e616664b29ce , https://github.com/de-bankly/vendura-app/commit/d062c55edf6d15a029fdbc5510f08207d7ba85bf
created_at: 2025-04-11T18:19:15Z
author_association: COLLABORATOR
diff_hunk: @@ -23,6 +24,13 @@ public class SupplierOrder implements ProductTransactable {
   @Id private String id;
 
   private Date timestamp;
+  
+  @DBRef private Supplier supplier;
+  
+  private String purchaseOrderNumber;
+  private Date expectedDeliveryDate;
+  private String notes;
+  private boolean isAutomaticOrder;
path: src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrder.java
user: login: lulkebit
body: Umgesetzt: https://github.com/de-bankly/vendura-backend-service/commit/15ab50e76f266ab132e67125b759f60ddebf0f63
created_at: 2025-04-11T18:22:55Z
author_association: COLLABORATOR
diff_hunk: @@ -1,5 +1,36 @@
 package com.bankly.vendura.inventory.supplierorder.model;
 
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.repository.MongoRepository;
 
-public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {}
+import java.util.Date;
+import java.util.List;
+
+public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {
+    
+    /**
+     * Find supplier orders by status
+     */
+    Page<SupplierOrder> findByOrderStatus(SupplierOrder.OrderStatus orderStatus, Pageable pageable);
+    
+    /**
+     * Find supplier orders by multiple statuses
+     */
+    List<SupplierOrder> findByOrderStatusIn(List<SupplierOrder.OrderStatus> orderStatuses);
+    
+    /**
+     * Find supplier orders by supplier
+     */
+    Page<SupplierOrder> findBySupplier_Id(String supplierId, Pageable pageable);
+    
+    /**
+     * Find supplier orders by expected delivery date range
+     */
+    Page<SupplierOrder> findByExpectedDeliveryDateBetween(Date startDate, Date endDate, Pageable pageable);
+    
+    /**
+     * Find automatic supplier orders
+     */
+    Page<SupplierOrder> findByIsAutomaticOrder(boolean isAutomaticOrder, Pageable pageable);
path: src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderRepository.java
user: login: lulkebit
body: Umgesetzt: https://github.com/de-bankly/vendura-backend-service/commit/15ab50e76f266ab132e67125b759f60ddebf0f63
created_at: 2025-04-11T18:23:03Z
author_association: COLLABORATOR
diff_hunk: @@ -1,5 +1,36 @@
 package com.bankly.vendura.inventory.supplierorder.model;
 
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.repository.MongoRepository;
 
-public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {}
+import java.util.Date;
+import java.util.List;
+
+public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {
+    
+    /**
+     * Find supplier orders by status
+     */
+    Page<SupplierOrder> findByOrderStatus(SupplierOrder.OrderStatus orderStatus, Pageable pageable);
+    
+    /**
+     * Find supplier orders by multiple statuses
+     */
+    List<SupplierOrder> findByOrderStatusIn(List<SupplierOrder.OrderStatus> orderStatuses);
+    
+    /**
+     * Find supplier orders by supplier
+     */
+    Page<SupplierOrder> findBySupplier_Id(String supplierId, Pageable pageable);
path: src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderRepository.java
user: login: lulkebit
body: Umgesetzt: https://github.com/de-bankly/vendura-backend-service/commit/8d3d4735e6457d32605b7aa8496b181cdc4772f2
created_at: 2025-04-11T18:26:27Z
author_association: COLLABORATOR
diff_hunk: @@ -29,6 +33,44 @@ public ResponseEntity<Page<SupplierOrderDTO>> getSupplierOrders(Pageable pageabl
         this.supplierOrderRepository.findAll(pageable).map(SupplierOrderFactory::toDTO));
   }
 
+  @GetMapping("/status/{status}")
+  @PreAuthorize("hasRole('INVENTORY')")
+  public ResponseEntity<Page<SupplierOrderDTO>> getSupplierOrdersByStatus(
+      @PathVariable("status") String status, Pageable pageable) {
+    try {
+      SupplierOrder.OrderStatus orderStatus = SupplierOrder.OrderStatus.valueOf(status.toUpperCase());
+      return ResponseEntity.ok(
+          this.supplierOrderRepository.findByOrderStatus(orderStatus, pageable).map(SupplierOrderFactory::toDTO));
+    } catch (IllegalArgumentException e) {
+      throw new EntityRetrieveException("Invalid order status", HttpStatus.BAD_REQUEST, status);
+    }
+  }
+  
+  @GetMapping("/supplier/{supplierId}")
+  @PreAuthorize("hasRole('INVENTORY')")
+  public ResponseEntity<Page<SupplierOrderDTO>> getSupplierOrdersBySupplierId(
+      @PathVariable("supplierId") String supplierId, Pageable pageable) {
+    return ResponseEntity.ok(
+        this.supplierOrderRepository.findBySupplier_Id(supplierId, pageable).map(SupplierOrderFactory::toDTO));
path: src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderControllerV1.java
user: login: antonbowe
body: Hast du mal probiert, das Projekt zu builden?
created_at: 2025-04-12T08:39:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -29,6 +33,44 @@ public ResponseEntity<Page<SupplierOrderDTO>> getSupplierOrders(Pageable pageabl
         this.supplierOrderRepository.findAll(pageable).map(SupplierOrderFactory::toDTO));
   }
 
+  @GetMapping("/status/{status}")
+  @PreAuthorize("hasRole('INVENTORY')")
+  public ResponseEntity<Page<SupplierOrderDTO>> getSupplierOrdersByStatus(
+      @PathVariable("status") String status, Pageable pageable) {
+    try {
+      SupplierOrder.OrderStatus orderStatus = SupplierOrder.OrderStatus.valueOf(status.toUpperCase());
+      return ResponseEntity.ok(
+          this.supplierOrderRepository.findByOrderStatus(orderStatus, pageable).map(SupplierOrderFactory::toDTO));
+    } catch (IllegalArgumentException e) {
+      throw new EntityRetrieveException("Invalid order status", HttpStatus.BAD_REQUEST, status);
+    }
+  }
+  
+  @GetMapping("/supplier/{supplierId}")
+  @PreAuthorize("hasRole('INVENTORY')")
+  public ResponseEntity<Page<SupplierOrderDTO>> getSupplierOrdersBySupplierId(
+      @PathVariable("supplierId") String supplierId, Pageable pageable) {
+    return ResponseEntity.ok(
+        this.supplierOrderRepository.findBySupplier_Id(supplierId, pageable).map(SupplierOrderFactory::toDTO));
path: src/main/java/com/bankly/vendura/inventory/supplierorder/SupplierOrderControllerV1.java
user: login: antonbowe
body: Offenbar nicht, sonst wäre dir aufgefallen, dass es fehlschlägt.
Den Build vor dem PR zu probieren, ist mindestens mal angebracht.
created_at: 2025-04-12T08:40:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,59 @@
 package com.bankly.vendura.inventory.supplierorder.model;
 
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.data.mongodb.repository.Query;
 
-public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {}
+import java.util.Date;
+import java.util.List;
+
+public interface SupplierOrderRepository extends MongoRepository<SupplierOrder, String> {
+    
+    /**
+     * Find supplier orders by status
+     */
+    Page<SupplierOrder> findByOrderStatus(SupplierOrder.OrderStatus orderStatus, Pageable pageable);
+    
+    /**
+     * Find supplier orders by multiple statuses
+     */
+    List<SupplierOrder> findByOrderStatusIn(List<SupplierOrder.OrderStatus> orderStatuses);
+    
+    /**
+     * Find supplier orders by supplier
+     * @param supplierId The supplier ID
+     * @param pageable Pagination parameters
+     * @return Page of supplier orders
+     */
+    @Query("{ 'supplier._id': ?0 }")
+    Page<SupplierOrder> findBySupplierIdOrderByCreatedAtDesc(String supplierId, Pageable pageable);
+    
+    /**
+     * Find supplier orders by expected delivery date range
+     */
+    Page<SupplierOrder> findByExpectedDeliveryDateBetween(Date startDate, Date endDate, Pageable pageable);
+    
+    /**
+     * Find automatic supplier orders
+     */
+    Page<SupplierOrder> findByAutomaticOrder(boolean isAutomaticOrder, Pageable pageable);
+    
+    /**
+     * Find supplier orders by supplier ID
+     * @param supplierId The supplier ID
+     * @param pageable Pagination parameters
+     * @return Page of supplier orders
+     */
+    @Query("{ 'supplier._id': ?0 }")
+    Page<SupplierOrder> findBySupplier_Id(String supplierId, Pageable pageable);
path: src/main/java/com/bankly/vendura/inventory/supplierorder/model/SupplierOrderRepository.java
user: login: antonbowe
body: Bitte refactoren
created_at: 2025-04-14T09:09:45Z
author_association: CONTRIBUTOR

PR comments:
user: login: lulkebit
created_at: 2025-04-11T18:26:59Z
body: Alle requested changes wurden umgesetzt. Bitte um erneutes review
author_association: COLLABORATOR
user: login: lulkebit
created_at: 2025-04-11T18:28:49Z
body: Weitere Änderungen lassen sich hier finden: https://github.com/de-bankly/vendura-app/pull/19
author_association: COLLABORATOR