Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ private void seedOrders(
.id(UUID.randomUUID())
.customer(customers.get(1)).courier(couriers.get(1))
.region(regions.get(1))
.status(Order.OrderStatus.SHIPPED)
.status(Order.OrderStatus.DELIVERED)
.orderPlacedTimestamp(placed2)
.shippedTimestamp(placed2.plusDays(ORDER_2_SHIP_DAYS)
.plusHours(ORDER_2_SHIP_HOURS))
Expand All @@ -283,9 +283,8 @@ private void seedOrders(
.id(UUID.randomUUID())
.customer(customers.get(0)).courier(couriers.get(0))
.region(regions.get(2))
.status(Order.OrderStatus.DELIVERY_FAILED)
.orderPlacedTimestamp(placed3)
.status(Order.OrderStatus.DELIVERY_FAILED)
.status(Order.OrderStatus.DELIVERED)
.orderPlacedTimestamp(placed3)
.shippedTimestamp(placed3.plusHours(ORDER_3_SHIP_HOURS))
.deliveredTimestamp(null)
Expand Down
19 changes: 17 additions & 2 deletions src/main/java/com/Podzilla/analytics/models/Product.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

import java.math.BigDecimal;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.UUID;

import java.util.List;

@Entity
@Table(name = "products")
@Data
Expand All @@ -23,6 +27,9 @@ public class Product {
private BigDecimal cost;
private int lowStockThreshold;

@OneToMany(mappedBy = "product", cascade = CascadeType.ALL)
private List<OrderItem> orderItems;

public static Builder builder() {
return new Builder();
}
Expand All @@ -33,8 +40,10 @@ public static class Builder {
private String category;
private BigDecimal cost;
private int lowStockThreshold;
private List<OrderItem> orderItems;

public Builder() { }
public Builder() {
}

public Builder id(final UUID id) {
this.id = id;
Expand All @@ -61,8 +70,14 @@ public Builder lowStockThreshold(final int lowStockThreshold) {
return this;
}

public Builder orderItems(final List<OrderItem> orderItems) {
this.orderItems = orderItems;
return this;
}

public Product build() {
return new Product(id, name, category, cost, lowStockThreshold);
return new Product(
id, name, category, cost, lowStockThreshold, orderItems);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.Podzilla.analytics.repositories;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

Expand Down Expand Up @@ -149,8 +148,8 @@ OrderFailureRateProjection calculateFailureRate(
+ "GROUP BY period "
+ "ORDER BY totalRevenue DESC")
List<RevenueSummaryProjection> findRevenueSummaryByPeriod(
@Param("startDate") LocalDate startDate,
@Param("endDate") LocalDate endDate,
@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate,
@Param("reportPeriod") String reportPeriod);

@Query("SELECT p.category AS category, "
Expand All @@ -164,6 +163,6 @@ List<RevenueSummaryProjection> findRevenueSummaryByPeriod(
+ "GROUP BY p.category "
+ "ORDER BY totalRevenue DESC")
List<RevenueByCategoryProjection> findRevenueByCategory(
@Param("startDate") LocalDate startDate,
@Param("endDate") LocalDate endDate);
@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,38 @@
import com.Podzilla.analytics.api.projections.product.TopSellingProductProjection;
import com.Podzilla.analytics.models.Product;
import java.util.UUID;

public interface ProductRepository extends JpaRepository<Product, UUID> {

@Query("SELECT p.id AS id, "
+ "p.name AS name, "
+ "p.category AS category, "
+ "SUM(oi.quantity * oi.pricePerUnit) AS totalRevenue, "
+ "SUM(oi.quantity) AS totalUnits "
+ "FROM OrderItem oi "
+ "JOIN oi.order o "
+ "JOIN oi.product p "
+ "WHERE o.finalStatusTimestamp >= :startDate "
+ "AND o.finalStatusTimestamp < :endDate "
+ "AND o.status = 'DELIVERED' "
+ "COALESCE(SUM(CASE WHEN o.finalStatusTimestamp >= :startDate "
+ "AND o.finalStatusTimestamp < :endDate "
+ "AND o.status = 'DELIVERED' THEN oi.quantity * oi.pricePerUnit "
+ "ELSE 0 END), 0) "
+ "AS totalRevenue, "
+ "COALESCE(SUM(CASE WHEN o.finalStatusTimestamp >= :startDate "
+ "AND o.finalStatusTimestamp < :endDate "
+ "AND o.status = 'DELIVERED' THEN oi.quantity ELSE 0 END), 0) "
+ "AS totalUnits "
+ "FROM Product p "
+ "LEFT JOIN p.orderItems oi "
+ "LEFT JOIN oi.order o "
+ "GROUP BY p.id, p.name, p.category "
+ "ORDER BY CASE WHEN :sortBy = 'REVENUE' "
+ "THEN SUM(oi.quantity * oi.pricePerUnit) "
+ " WHEN :sortBy = 'UNITS' THEN SUM(oi.quantity) "
+ " ELSE SUM(oi.quantity * oi.pricePerUnit) END DESC")
+ "THEN COALESCE(SUM(CASE WHEN o.finalStatusTimestamp >= "
+ ":startDate AND o.finalStatusTimestamp < :endDate "
+ "AND o.status = 'DELIVERED' THEN oi.quantity * oi.pricePerUnit "
+ "ELSE 0 END), 0) "
+ "ELSE COALESCE(SUM(CASE WHEN o.finalStatusTimestamp >= "
+ ":startDate AND o.finalStatusTimestamp < :endDate "
+ "AND o.status = 'DELIVERED' THEN oi.quantity ELSE 0 END), 0) "
+ "END DESC "
+ "LIMIT :limit")
List<TopSellingProductProjection> findTopSellers(
@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate,
@Param("limit") Integer limit,
@Param("sortBy") String sortBy // Pass the enum name as a String
);
@Param("sortBy") String sortBy);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.Podzilla.analytics.services;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -25,9 +27,13 @@ public List<RevenueSummaryResponse> getRevenueSummary(
final LocalDate endDate,
final String periodString) {

LocalDateTime startDateTime = startDate.atStartOfDay();
LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX);

final List<RevenueSummaryProjection> revenueData = orderRepository
.findRevenueSummaryByPeriod(startDate,
endDate, periodString);
.findRevenueSummaryByPeriod(
startDateTime,
endDateTime, periodString);

final List<RevenueSummaryResponse> summaryList = new ArrayList<>();

Expand Down Expand Up @@ -55,9 +61,13 @@ public List<RevenueSummaryResponse> getRevenueSummary(
public List<RevenueByCategoryResponse> getRevenueByCategory(
final LocalDate startDate, final LocalDate endDate) {

LocalDateTime startDateTime = startDate.atStartOfDay();
LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX);

final List<RevenueByCategoryProjection> queryResults = orderRepository
.findRevenueByCategory(startDate,
endDate);
.findRevenueByCategory(
startDateTime,
endDateTime);

final List<RevenueByCategoryResponse> summaryList = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -52,7 +53,8 @@ void getRevenueSummary_WithValidData_ShouldReturnCorrectSummary() {
summaryProjection(LocalDate.of(2025, 1, 1), new BigDecimal("1000.00")),
summaryProjection(LocalDate.of(2025, 2, 1), new BigDecimal("2000.00")));

when(orderRepository.findRevenueSummaryByPeriod(eq(startDate), eq(endDate), eq("MONTHLY")))
when(orderRepository.findRevenueSummaryByPeriod(eq(startDate.atStartOfDay()), eq(endDate.atTime(LocalTime.MAX)),
eq("MONTHLY")))
.thenReturn(projections);

// Act
Expand Down Expand Up @@ -120,7 +122,8 @@ void getRevenueByCategory_WithValidData_ShouldReturnCorrectCategories() {
categoryProjection("Books", new BigDecimal("3000.00")),
categoryProjection("Electronics", new BigDecimal("5000.00")));

when(orderRepository.findRevenueByCategory(eq(startDate), eq(endDate)))
when(orderRepository.findRevenueByCategory(eq(startDate.atStartOfDay()), eq(endDate.atTime(
LocalTime.MAX))))
.thenReturn(projections);// Act
List<RevenueByCategoryResponse> result = revenueReportService.getRevenueByCategory(startDate, endDate);

Expand Down Expand Up @@ -167,7 +170,8 @@ public BigDecimal getTotalRevenue() {
}
});

when(orderRepository.findRevenueByCategory(eq(startDate), eq(endDate)))
when(orderRepository.findRevenueByCategory(eq(startDate.atStartOfDay()), eq(endDate.atTime(
LocalTime.MAX))))
.thenReturn(projections);

// Act
Expand Down