Skip to content

Commit

Permalink
Merge pull request #102 from sanchitc05/sanchitc05/issue95
Browse files Browse the repository at this point in the history
[FEATURE] Enhance Reporting and Analytics Capabilities
  • Loading branch information
MastanSayyad authored Nov 9, 2024
2 parents 70142f9 + 51c05e3 commit 1ea359d
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.libraryman_api.analytics;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/api/analytics")
public class AnalyticsController {

private final AnalyticsService analyticsService;

public AnalyticsController(AnalyticsService analyticsService) {
this.analyticsService = analyticsService;
}

@GetMapping("/overview")
public ResponseEntity<Map<String, Object>> getLibraryOverview() {
return ResponseEntity.ok(analyticsService.getLibraryOverview());
}

@GetMapping("/popular-books")
public ResponseEntity<List<Map<String, Object>>> getPopularBooks(@RequestParam(defaultValue = "10") int limit) {
return ResponseEntity.ok(analyticsService.getPopularBooks(limit));
}

@GetMapping("/borrowing-trends")
public ResponseEntity<Map<String, Long>> getBorrowingTrends(
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
return ResponseEntity.ok(analyticsService.getBorrowingTrends(startDate, endDate));
}

@GetMapping("/member-activity")
public ResponseEntity<List<Map<String, Object>>> getMemberActivityReport() {
return ResponseEntity.ok(analyticsService.getMemberActivityReport());
}
}
45 changes: 45 additions & 0 deletions src/main/java/com/libraryman_api/analytics/AnalyticsService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.libraryman_api.analytics;

import com.libraryman_api.book.BookRepository;
import com.libraryman_api.borrowing.BorrowingRepository;
import com.libraryman_api.member.MemberRepository;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AnalyticsService {

private final BookRepository bookRepository;
private final BorrowingRepository borrowingRepository;
private final MemberRepository memberRepository;

public AnalyticsService(BookRepository bookRepository, BorrowingRepository borrowingRepository, MemberRepository memberRepository) {
this.bookRepository = bookRepository;
this.borrowingRepository = borrowingRepository;
this.memberRepository = memberRepository;
}

public Map<String, Object> getLibraryOverview() {
Map<String, Object> overview = new HashMap<>();
overview.put("totalBooks", bookRepository.count());
overview.put("totalMembers", memberRepository.count());
overview.put("totalBorrowings", borrowingRepository.count());
return overview;
}

public List<Map<String, Object>> getPopularBooks(int limit) {
return borrowingRepository.findMostBorrowedBooks(limit);
}

public Map<String, Long> getBorrowingTrends(LocalDate startDate, LocalDate endDate) {
return borrowingRepository.getBorrowingTrendsBetweenDates(startDate, endDate);
}

public List<Map<String, Object>> getMemberActivityReport() {
return memberRepository.getMemberActivityReport();
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
package com.libraryman_api.borrowing;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

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

@Repository
public interface BorrowingRepository extends JpaRepository<Borrowings, Integer> {

// Underscore (_) used for property traversal, navigating from Borrowings to Members entity via 'member' property
Page<Borrowings> findByMember_memberId(int memberId, Pageable pageable);
Page<Borrowings> findByMember_memberId(int memberId, Pageable pageable); {
try {
Page<Borrowings> borrowings = borrowingRepository.findByMember_memberId(memberId, pageable);

List<Borrowings> findByBook_bookId(int bookId);
if (borrowings.isEmpty()) {
throw new ResourceNotFoundException("Member didn't borrow any book");
}
return borrowings.map(this::EntityToDto);
} catch (PropertyReferenceException ex) {
throw new InvalidSortFieldException("The specified 'sortBy' value is invalid.");
}
}

@Query(value = "SELECT b.title AS bookTitle, COUNT(*) AS borrowCount " +
"FROM borrowings br JOIN books b ON br.book_id = b.book_id " +
"GROUP BY b.book_id ORDER BY borrowCount DESC LIMIT :limit", nativeQuery = true)
List<Map<String, Object>> findMostBorrowedBooks(int limit);

@Query("SELECT FUNCTION('DATE', b.borrowDate) as date, COUNT(*) as count " +
"FROM Borrowings b " +
"WHERE b.borrowDate BETWEEN :startDate AND :endDate " +
"GROUP BY FUNCTION('DATE', b.borrowDate)")
Map<String, Long> getBorrowingTrendsBetweenDates(LocalDate startDate, LocalDate endDate);
}
16 changes: 9 additions & 7 deletions src/main/java/com/libraryman_api/member/MemberRepository.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.libraryman_api.member;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;
import java.util.Optional;

@Repository
Expand All @@ -12,10 +15,9 @@ public interface MemberRepository extends JpaRepository<Members, Integer> {

Optional<Members> findByUsername(String username);

/**
* SELECT SUM(amount) AS totalFines
* FROM fines
* WHERE memberId = [memberId] AND paid = false;
*/
}

@Query(value = "SELECT m.name AS memberName, COUNT(b.borrowing_id) AS borrowCount, " +
"SUM(CASE WHEN b.return_date IS NULL THEN 1 ELSE 0 END) AS currentBorrowings " +
"FROM members m LEFT JOIN borrowings b ON m.member_id = b.member_id " +
"GROUP BY m.member_id ORDER BY borrowCount DESC", nativeQuery = true)
List<Map<String, Object>> getMemberActivityReport();
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ public SecurityFilterChain web(HttpSecurity http) throws Exception {
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests((request) -> request
// make sure it is in order to access the proper Url

.requestMatchers("/api/signup").permitAll()
.requestMatchers("/api/login").permitAll()
.requestMatchers("/api/logout").permitAll()
.requestMatchers("/api/analytics/**").hasAnyRole("ADMIN", "LIBRARIAN") // New line for analytics
.anyRequest().authenticated()
)
.logout(logout -> logout
Expand Down Expand Up @@ -85,5 +85,4 @@ public CorsConfigurationSource corsConfigurationSource() {
public CorsFilter corsFilter() {
return new CorsFilter(corsConfigurationSource());
}

}

0 comments on commit 1ea359d

Please sign in to comment.