Notifications added
This commit is contained in:
@@ -13,6 +13,7 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.rit.canteen.sales.service.SystemNotificationService;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -29,6 +30,9 @@ public class FeedbackController {
|
||||
@Autowired
|
||||
private ItemRatingRepository itemRatingRepository;
|
||||
|
||||
@Autowired
|
||||
private SystemNotificationService notificationService;
|
||||
|
||||
@GetMapping
|
||||
public Page<Feedback> getAllFeedback(
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@@ -188,6 +192,14 @@ public class FeedbackController {
|
||||
order.setHasFeedback(true);
|
||||
orderRepository.save(order);
|
||||
|
||||
// Notify Admins
|
||||
notificationService.createNotification(
|
||||
"New Feedback Received",
|
||||
"A new feedback has been submitted by " + (feedback.getUserName() != null ? feedback.getUserName() : "a customer") + " for Order #" + order.getDisplayOrderId(),
|
||||
"FEEDBACK",
|
||||
"/feedback"
|
||||
);
|
||||
|
||||
return ResponseEntity.ok(savedFeedback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.rit.canteen.sales.service.SystemNotificationService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -22,6 +23,9 @@ public class ProductController {
|
||||
@Autowired
|
||||
private StockUpdateController stockUpdateController;
|
||||
|
||||
@Autowired
|
||||
private SystemNotificationService notificationService;
|
||||
|
||||
@GetMapping
|
||||
public org.springframework.data.domain.Page<Product> getAllProducts(
|
||||
@RequestParam(required = false) String search,
|
||||
@@ -53,6 +57,16 @@ public class ProductController {
|
||||
public Product createProduct(@Valid @RequestBody Product product) {
|
||||
Product savedProduct = productRepository.save(product);
|
||||
updateStallAssociations(savedProduct, product.getStalls());
|
||||
|
||||
if (savedProduct.isDraft()) {
|
||||
notificationService.createNotification(
|
||||
"Draft Product Created",
|
||||
"A new product draft '" + savedProduct.getName() + "' has been created and requires review before publishing.",
|
||||
"PRODUCT",
|
||||
"/inventory/products"
|
||||
);
|
||||
}
|
||||
|
||||
return productRepository.findById(savedProduct.getId()).orElse(savedProduct);
|
||||
}
|
||||
|
||||
@@ -249,6 +263,13 @@ public class ProductController {
|
||||
Product updated = productRepository.save(product);
|
||||
updateStallAssociations(updated, productDetails.getStalls());
|
||||
|
||||
notificationService.createNotification(
|
||||
"Product Published",
|
||||
"Product '" + productDetails.getName() + "' is now live in the inventory with ID: " + finalProductId,
|
||||
"PRODUCT",
|
||||
"/inventory/products"
|
||||
);
|
||||
|
||||
return ResponseEntity.ok(productRepository.findById(updated.getId()).orElse(updated));
|
||||
}
|
||||
})
|
||||
|
||||
@@ -10,6 +10,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.rit.canteen.sales.service.SystemNotificationService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -22,6 +24,9 @@ public class PurchaseController {
|
||||
@Autowired
|
||||
private PurchaseService purchaseService;
|
||||
|
||||
@Autowired
|
||||
private SystemNotificationService notificationService;
|
||||
|
||||
@GetMapping("/orders")
|
||||
public List<PurchaseOrder> getAllOrders() {
|
||||
return purchaseService.getAllOrders();
|
||||
@@ -30,7 +35,17 @@ public class PurchaseController {
|
||||
@PostMapping("/orders")
|
||||
public PurchaseOrder createOrder(@RequestBody PurchaseOrder order) {
|
||||
logger.info("Received request to create/update order: {}", order.getPurchaseId());
|
||||
return purchaseService.createOrder(order);
|
||||
PurchaseOrder saved = purchaseService.createOrder(order);
|
||||
|
||||
// Notify Admins
|
||||
notificationService.createNotification(
|
||||
"Procurement Update",
|
||||
"A new purchase order (" + saved.getPurchaseId() + ") has been created/updated for vendor: " + (saved.getVendor() != null ? saved.getVendor().getName() : "Unknown"),
|
||||
"PURCHASE",
|
||||
"/purchases/orders"
|
||||
);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
@GetMapping("/orders/{id}/history")
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.rit.canteen.sales.controller;
|
||||
|
||||
import com.rit.canteen.sales.model.SystemNotification;
|
||||
import com.rit.canteen.sales.service.SystemNotificationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/notifications")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class SystemNotificationController {
|
||||
|
||||
@Autowired
|
||||
private SystemNotificationService notificationService;
|
||||
|
||||
@GetMapping
|
||||
public List<SystemNotification> getUnread() {
|
||||
return notificationService.getUnreadNotifications();
|
||||
}
|
||||
|
||||
@GetMapping("/all")
|
||||
public List<SystemNotification> getAll() {
|
||||
return notificationService.getAllNotifications();
|
||||
}
|
||||
|
||||
@PostMapping("/mark-read/{id}")
|
||||
public void markRead(@PathVariable Long id) {
|
||||
notificationService.markAsRead(id);
|
||||
}
|
||||
|
||||
@PostMapping("/mark-all-read")
|
||||
public void markAllRead() {
|
||||
notificationService.markAllAsRead();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.rit.canteen.sales.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "system_notifications")
|
||||
public class SystemNotification {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String title;
|
||||
|
||||
@Column(nullable = false, length = 1000)
|
||||
private String message;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String type; // FEEDBACK, PURCHASE, PRODUCT, COUPON
|
||||
|
||||
@Column(nullable = false)
|
||||
private boolean isRead = false;
|
||||
|
||||
@Column(nullable = true)
|
||||
private String link; // URL to navigate to
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
this.createdAt = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public SystemNotification() {}
|
||||
|
||||
public SystemNotification(String title, String message, String type, String link) {
|
||||
this.title = title;
|
||||
this.message = message;
|
||||
this.type = type;
|
||||
this.link = link;
|
||||
this.createdAt = LocalDateTime.now();
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
|
||||
public String getTitle() { return title; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
|
||||
public String getMessage() { return message; }
|
||||
public void setMessage(String message) { this.message = message; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public boolean isRead() { return isRead; }
|
||||
public void setRead(boolean read) { isRead = read; }
|
||||
|
||||
public String getLink() { return link; }
|
||||
public void setLink(String link) { this.link = link; }
|
||||
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
}
|
||||
@@ -5,7 +5,11 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.util.Optional;
|
||||
|
||||
import java.util.List;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Repository
|
||||
public interface CouponRepository extends JpaRepository<CouponCode, Long> {
|
||||
Optional<CouponCode> findByCode(String code);
|
||||
List<CouponCode> findByExpiryDateBeforeAndIsActiveTrue(LocalDateTime threshold);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.rit.canteen.sales.repository;
|
||||
|
||||
import com.rit.canteen.sales.model.SystemNotification;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface SystemNotificationRepository extends JpaRepository<SystemNotification, Long> {
|
||||
List<SystemNotification> findByIsReadFalseOrderByCreatedAtDesc();
|
||||
List<SystemNotification> findAllByOrderByCreatedAtDesc();
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.rit.canteen.sales.service;
|
||||
|
||||
import com.rit.canteen.sales.model.CouponCode;
|
||||
import com.rit.canteen.sales.model.SystemNotification;
|
||||
import com.rit.canteen.sales.repository.CouponRepository;
|
||||
import com.rit.canteen.sales.repository.SystemNotificationRepository;
|
||||
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.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class SystemNotificationService {
|
||||
|
||||
@Autowired
|
||||
private SystemNotificationRepository notificationRepository;
|
||||
|
||||
@Autowired
|
||||
private CouponRepository couponRepository;
|
||||
|
||||
@Transactional
|
||||
public void createNotification(String title, String message, String type, String link) {
|
||||
SystemNotification notification = new SystemNotification(title, message, type, link);
|
||||
notificationRepository.save(notification);
|
||||
}
|
||||
|
||||
public List<SystemNotification> getUnreadNotifications() {
|
||||
return notificationRepository.findByIsReadFalseOrderByCreatedAtDesc();
|
||||
}
|
||||
|
||||
public List<SystemNotification> getAllNotifications() {
|
||||
return notificationRepository.findAllByOrderByCreatedAtDesc();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void markAsRead(Long id) {
|
||||
notificationRepository.findById(id).ifPresent(n -> {
|
||||
n.setRead(true);
|
||||
notificationRepository.save(n);
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void markAllAsRead() {
|
||||
List<SystemNotification> unread = notificationRepository.findByIsReadFalseOrderByCreatedAtDesc();
|
||||
for (SystemNotification n : unread) {
|
||||
n.setRead(true);
|
||||
}
|
||||
notificationRepository.saveAll(unread);
|
||||
}
|
||||
|
||||
// Triggered every 6 hours to check for expiring coupons
|
||||
@Scheduled(fixedRate = 21600000)
|
||||
@Transactional
|
||||
public void checkExpiringCoupons() {
|
||||
LocalDateTime threshold = LocalDateTime.now().plusHours(48);
|
||||
List<CouponCode> expiringSoon = couponRepository.findByExpiryDateBeforeAndIsActiveTrue(threshold);
|
||||
|
||||
for (CouponCode coupon : expiringSoon) {
|
||||
String title = "Coupon Expiring Soon: " + coupon.getCode();
|
||||
// Avoid duplicate notifications for the same coupon within the last 24 hours
|
||||
boolean exists = notificationRepository.findAllByOrderByCreatedAtDesc().stream()
|
||||
.anyMatch(n -> n.getTitle().equals(title) && n.getCreatedAt().isAfter(LocalDateTime.now().minusDays(1)));
|
||||
|
||||
if (!exists) {
|
||||
createNotification(
|
||||
title,
|
||||
"Ritz Coupon code '" + coupon.getCode() + "' is set to expire on " + coupon.getExpiryDate() + ". Consider extending or updating it.",
|
||||
"COUPON",
|
||||
"/ritz/coupons"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user