Initialized Counter login and fixed bugs in the edit products option

This commit is contained in:
Sidharth Prabhu
2026-04-16 10:42:43 +05:30
parent d4cef8d241
commit 9af9f0599a
39 changed files with 1115 additions and 85 deletions

View File

@@ -7,8 +7,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/base-items")
public class BaseItemController {
@@ -18,8 +16,12 @@ public class BaseItemController {
@GetMapping
public org.springframework.data.domain.Page<BaseItem> getAllBaseItems(
@RequestParam(required = false) String search,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
if (search != null && !search.isEmpty()) {
return baseItemRepository.findByNameContainingIgnoreCase(search, org.springframework.data.domain.PageRequest.of(page, size));
}
return baseItemRepository.findAll(org.springframework.data.domain.PageRequest.of(page, size));
}

View File

@@ -40,6 +40,7 @@ public class OrderController {
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate,
@RequestParam(required = false) String status,
@RequestParam(required = false) String paymentType,
@RequestParam(required = false) String orderType,
@RequestParam(required = false) String search,
@RequestParam(defaultValue = "false") boolean archived,
@RequestParam(defaultValue = "0") int page,
@@ -66,6 +67,9 @@ public class OrderController {
if (paymentType != null && !paymentType.isEmpty()) {
predicates.add(cb.equal(root.get("paymentMethod"), paymentType));
}
if (orderType != null && !orderType.isEmpty()) {
predicates.add(cb.equal(root.get("orderType"), orderType));
}
if (search != null && !search.isEmpty()) {
String searchLower = "%" + search.toLowerCase() + "%";
Join<Order, User> userJoin = root.join("user", JoinType.LEFT);

View File

@@ -18,8 +18,12 @@ public class ProductController {
@GetMapping
public org.springframework.data.domain.Page<Product> getAllProducts(
@RequestParam(required = false) String search,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
if (search != null && !search.isEmpty()) {
return productRepository.findByNameOrCategoryContainingIgnoreCase(search, org.springframework.data.domain.PageRequest.of(page, size));
}
return productRepository.findAllWithStalls(org.springframework.data.domain.PageRequest.of(page, size));
}

View File

@@ -108,9 +108,10 @@ public class UserController {
*/
@GetMapping("/users")
public ResponseEntity<Page<LoginResponse.UserDto>> getAllUsers(
@RequestParam(required = false) String search,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Page<LoginResponse.UserDto> users = userService.getAllUsers(PageRequest.of(page, size));
Page<LoginResponse.UserDto> users = userService.getAllUsers(search, PageRequest.of(page, size));
return ResponseEntity.ok(users);
}

View File

@@ -0,0 +1,53 @@
package com.rit.canteen.sales.counter.config;
import com.rit.canteen.sales.counter.model.CounterCategory;
import com.rit.canteen.sales.counter.model.CounterProduct;
import com.rit.canteen.sales.counter.repository.CounterCategoryRepository;
import com.rit.canteen.sales.counter.repository.CounterProductRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
import java.util.List;
@Configuration
public class CounterDataLoader {
@Bean
CommandLineRunner initCounterDatabase(CounterCategoryRepository categoryRepository, CounterProductRepository productRepository) {
return args -> {
if (categoryRepository.count() == 0) {
CounterCategory iceCream = categoryRepository.save(new CounterCategory("ICE CREAM"));
CounterCategory biscuit = categoryRepository.save(new CounterCategory("BISCUIT"));
CounterCategory juice = categoryRepository.save(new CounterCategory("READYMADE JUICE"));
CounterCategory chocolate = categoryRepository.save(new CounterCategory("CHOCOLATE"));
CounterCategory snacks = categoryRepository.save(new CounterCategory("SNACKS"));
CounterCategory bakery = categoryRepository.save(new CounterCategory("BAKERY"));
List<CounterProduct> products = Arrays.asList(
new CounterProduct("CM BUTTER SCOTCH CONE", 40.0, 47, iceCream),
new CounterProduct("CM CHOCOLATE CONE", 50.0, 24, iceCream),
new CounterProduct("CM COOKIES AND CREAM", 50.0, 58, iceCream),
new CounterProduct("CM SIPUP CHOCOLATE", 10.0, 111, iceCream),
new CounterProduct("CM SIPUP STRAWBERRY", 10.0, 118, iceCream),
new CounterProduct("CM SIPUP PINEAPPLE", 10.0, 120, iceCream),
new CounterProduct("CM VANILLA CUP", 10.0, 31, iceCream),
new CounterProduct("CM PINE APPLE STICK ICE", 10.0, 25, iceCream),
new CounterProduct("CM MINI VANILLA CONE", 20.0, 128, iceCream),
new CounterProduct("CM PISTA STICK ICE", 20.0, 25, iceCream),
new CounterProduct("CM BALL ICE CREAM", 20.0, 18, iceCream),
new CounterProduct("CM CHOCOBAR WITH POUCH", 30.0, 100, iceCream),
new CounterProduct("CM DILSE BUTTER/CHOCO", 30.0, 18, iceCream),
new CounterProduct("CM DILSE REDVEL/VANILLA", 40.0, 20, iceCream),
new CounterProduct("CM SIPUP PISTA", 10.0, 118, iceCream),
new CounterProduct("COCONUT ICE CREAM", 45.0, 30, iceCream),
new CounterProduct("Coke", 25.0, 100, juice)
);
productRepository.saveAll(products);
System.out.println("Counter Database seeded with initial categories and products.");
}
};
}
}

View File

@@ -0,0 +1,31 @@
package com.rit.canteen.sales.counter.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.file.Path;
import java.nio.file.Paths;
@Configuration
public class CounterWebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
Path uploadDir = Paths.get("uploads").toAbsolutePath().normalize();
// Ensure the directory exists
try {
if (!java.nio.file.Files.exists(uploadDir)) {
java.nio.file.Files.createDirectories(uploadDir);
}
} catch (java.io.IOException e) {
System.err.println("Could not create uploads directory: " + e.getMessage());
}
String uploadPath = uploadDir.toUri().toString();
registry.addResourceHandler("/uploads/**")
.addResourceLocations(uploadPath);
}
}

View File

@@ -0,0 +1,23 @@
package com.rit.canteen.sales.counter.controller;
import com.rit.canteen.sales.model.BaseItem;
import com.rit.canteen.sales.repository.BaseItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/counter/categories")
public class CounterCategoryController {
@Autowired
private BaseItemRepository baseItemRepository;
@GetMapping
public List<BaseItem> getAllCategories() {
return baseItemRepository.findAll();
}
// Management endpoints are disabled for the counter billing dashboard
}

View File

@@ -0,0 +1,53 @@
package com.rit.canteen.sales.counter.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping("/api/counter/upload")
public class CounterImageUploadController {
private static final String UPLOAD_DIR = "uploads/products";
@PostMapping
public ResponseEntity<?> uploadImage(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body(Map.of("error", "No file selected"));
}
try {
// Create uploads directory if it doesn't exist
Path uploadPath = Paths.get(UPLOAD_DIR).toAbsolutePath().normalize();
Files.createDirectories(uploadPath);
// Generate unique filename to prevent collisions
String originalFilename = file.getOriginalFilename();
String extension = "";
if (originalFilename != null && originalFilename.contains(".")) {
extension = originalFilename.substring(originalFilename.lastIndexOf("."));
}
String uniqueFilename = UUID.randomUUID().toString() + extension;
// Save the file
Path filePath = uploadPath.resolve(uniqueFilename);
Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
// Return the URL path that the frontend can use
String imageUrl = "/uploads/products/" + uniqueFilename;
return ResponseEntity.ok(Map.of("imageUrl", imageUrl));
} catch (IOException e) {
return ResponseEntity.internalServerError()
.body(Map.of("error", "Failed to upload image: " + e.getMessage()));
}
}
}

View File

@@ -0,0 +1,47 @@
package com.rit.canteen.sales.counter.controller;
import com.rit.canteen.sales.counter.model.CounterInfo;
import com.rit.canteen.sales.counter.service.CounterInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/counter/counters")
public class CounterInfoController {
@Autowired
private CounterInfoService counterService;
@GetMapping
public List<CounterInfo> getAllCounters() {
return counterService.getAllCounters();
}
@GetMapping("/{id}")
public CounterInfo getCounterById(@PathVariable Long id) {
return counterService.getCounterById(id)
.orElseThrow(() -> new RuntimeException("Counter not found"));
}
@PostMapping
public CounterInfo createCounter(@RequestBody CounterInfo counter) {
return counterService.createCounter(counter);
}
@PutMapping("/{id}")
public CounterInfo updateCounter(@PathVariable Long id, @RequestBody CounterInfo counter) {
return counterService.updateCounter(id, counter);
}
@DeleteMapping("/{id}")
public void deleteCounter(@PathVariable Long id) {
counterService.deleteCounter(id);
}
@PostMapping("/{counterId}/assign-product/{productId}")
public void assignProduct(@PathVariable Long counterId, @PathVariable Long productId) {
counterService.assignProductToCounter(counterId, productId);
}
}

View File

@@ -0,0 +1,50 @@
package com.rit.canteen.sales.counter.controller;
import com.rit.canteen.sales.model.Order;
import com.rit.canteen.sales.counter.service.CounterOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/counter/orders")
public class CounterOrderController {
@Autowired
private CounterOrderService orderService;
@GetMapping
public List<Order> getAllOrders() {
return orderService.getAllOrders();
}
@GetMapping("/{id}")
public ResponseEntity<Order> getOrderById(@PathVariable Long id) {
return orderService.getOrderById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public Order createOrder(@RequestBody Order order) {
return orderService.createOrder(order);
}
@PutMapping("/{id}")
public ResponseEntity<Order> updateOrder(@PathVariable Long id, @RequestBody Order orderDetails) {
try {
Order updatedOrder = orderService.updateOrder(id, orderDetails);
return ResponseEntity.ok(updatedOrder);
} catch (RuntimeException e) {
return ResponseEntity.notFound().build();
}
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteOrder(@PathVariable Long id) {
orderService.deleteOrder(id);
return ResponseEntity.ok().build();
}
}

View File

@@ -0,0 +1,28 @@
package com.rit.canteen.sales.counter.controller;
import com.rit.canteen.sales.model.Product;
import com.rit.canteen.sales.repository.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/counter/products")
public class CounterProductController {
@Autowired
private ProductRepository productRepository;
@GetMapping
public List<Product> getAllProducts() {
return productRepository.findAll();
}
@GetMapping("/category/{categoryName}")
public List<Product> getProductsByCategory(@PathVariable String categoryName) {
return productRepository.findByCategory(categoryName);
}
// Management endpoints are disabled for the counter billing dashboard
}

View File

@@ -0,0 +1,51 @@
package com.rit.canteen.sales.counter.model;
import jakarta.persistence.*;
import java.util.List;
@Entity
@Table(name = "counter_categories")
public class CounterCategory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String name;
@OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
@com.fasterxml.jackson.annotation.JsonIgnore
private List<CounterProduct> products;
public CounterCategory() {
}
public CounterCategory(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<CounterProduct> getProducts() {
return products;
}
public void setProducts(List<CounterProduct> products) {
this.products = products;
}
}

View File

@@ -0,0 +1,63 @@
package com.rit.canteen.sales.counter.model;
import jakarta.persistence.*;
import java.util.List;
@Entity
@Table(name = "counter_info")
public class CounterInfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String name;
@Column
private String location;
@OneToMany(mappedBy = "counter")
@com.fasterxml.jackson.annotation.JsonIgnore
private List<CounterProduct> products;
public CounterInfo() {
}
public CounterInfo(String name, String location) {
this.name = name;
this.location = location;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public List<CounterProduct> getProducts() {
return products;
}
public void setProducts(List<CounterProduct> products) {
this.products = products;
}
}

View File

@@ -0,0 +1,71 @@
package com.rit.canteen.sales.counter.model;
import jakarta.persistence.*;
import java.time.LocalDateTime;
import java.util.List;
@Entity
@Table(name = "counter_orders")
public class CounterOrder {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "order_id")
private List<CounterOrderItem> items;
@Column(nullable = false)
private Double totalAmount;
@Column(nullable = false)
private String status;
@Column(name = "created_at")
private LocalDateTime createdAt;
public CounterOrder() {
this.createdAt = LocalDateTime.now();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<CounterOrderItem> getItems() {
return items;
}
public void setItems(List<CounterOrderItem> items) {
this.items = items;
}
public Double getTotalAmount() {
return totalAmount;
}
public void setTotalAmount(Double totalAmount) {
this.totalAmount = totalAmount;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(LocalDateTime createdAt) {
this.createdAt = createdAt;
}
}

View File

@@ -0,0 +1,78 @@
package com.rit.canteen.sales.counter.model;
import jakarta.persistence.*;
@Entity
@Table(name = "counter_order_items")
public class CounterOrderItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "product_name", nullable = false)
private String productName;
@Column(nullable = false)
private Integer quantity;
@Column(name = "unit_price", nullable = false)
private Double unitPrice;
@Column(name = "total_price", nullable = false)
private Double totalPrice;
@Column(name = "product_id")
private Long productId;
public CounterOrderItem() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getProductId() {
return productId;
}
public void setProductId(Long productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public Double getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(Double unitPrice) {
this.unitPrice = unitPrice;
}
public Double getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(Double totalPrice) {
this.totalPrice = totalPrice;
}
}

View File

@@ -0,0 +1,109 @@
package com.rit.canteen.sales.counter.model;
import jakarta.persistence.*;
@Entity
@Table(name = "counter_products")
public class CounterProduct {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Double price;
@Column(nullable = false)
private Integer stock;
@Column(columnDefinition = "TEXT")
private String description;
@Column
private String imageUrl;
@ManyToOne
@JoinColumn(name = "category_id")
private CounterCategory category;
@ManyToOne
@JoinColumn(name = "counter_id")
private CounterInfo counter;
public CounterProduct() {
}
public CounterProduct(String name, Double price, Integer stock, CounterCategory category) {
this.name = name;
this.price = price;
this.stock = stock;
this.category = category;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public CounterCategory getCategory() {
return category;
}
public void setCategory(CounterCategory category) {
this.category = category;
}
public CounterInfo getCounter() {
return counter;
}
public void setCounter(CounterInfo counter) {
this.counter = counter;
}
}

View File

@@ -0,0 +1,12 @@
package com.rit.canteen.sales.counter.repository;
import com.rit.canteen.sales.counter.model.CounterCategory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface CounterCategoryRepository extends JpaRepository<CounterCategory, Long> {
Optional<CounterCategory> findByName(String name);
}

View File

@@ -0,0 +1,12 @@
package com.rit.canteen.sales.counter.repository;
import com.rit.canteen.sales.counter.model.CounterInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface CounterInfoRepository extends JpaRepository<CounterInfo, Long> {
Optional<CounterInfo> findByName(String name);
}

View File

@@ -0,0 +1,13 @@
package com.rit.canteen.sales.counter.repository;
import com.rit.canteen.sales.counter.model.CounterOrder;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CounterOrderRepository extends JpaRepository<CounterOrder, Long> {
List<CounterOrder> findByStatus(String status);
List<CounterOrder> findAllByOrderByCreatedAtDesc();
}

View File

@@ -0,0 +1,14 @@
package com.rit.canteen.sales.counter.repository;
import com.rit.canteen.sales.counter.model.CounterCategory;
import com.rit.canteen.sales.counter.model.CounterProduct;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CounterProductRepository extends JpaRepository<CounterProduct, Long> {
List<CounterProduct> findByCategoryName(String categoryName);
List<CounterProduct> findByCategory(CounterCategory category);
}

View File

@@ -0,0 +1,39 @@
package com.rit.canteen.sales.counter.service;
import com.rit.canteen.sales.counter.model.CounterCategory;
import com.rit.canteen.sales.counter.repository.CounterCategoryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class CounterCategoryService {
@Autowired
private CounterCategoryRepository categoryRepository;
public List<CounterCategory> getAllCategories() {
return categoryRepository.findAll();
}
public Optional<CounterCategory> getCategoryByName(String name) {
return categoryRepository.findByName(name);
}
public CounterCategory createCategory(CounterCategory category) {
return categoryRepository.save(category);
}
public CounterCategory updateCategory(Long id, CounterCategory categoryDetails) {
CounterCategory category = categoryRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Category not found"));
category.setName(categoryDetails.getName());
return categoryRepository.save(category);
}
public void deleteCategory(Long id) {
categoryRepository.deleteById(id);
}
}

View File

@@ -0,0 +1,55 @@
package com.rit.canteen.sales.counter.service;
import com.rit.canteen.sales.counter.model.CounterInfo;
import com.rit.canteen.sales.counter.model.CounterProduct;
import com.rit.canteen.sales.counter.repository.CounterInfoRepository;
import com.rit.canteen.sales.counter.repository.CounterProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class CounterInfoService {
@Autowired
private CounterInfoRepository counterRepository;
@Autowired
private CounterProductRepository productRepository;
public List<CounterInfo> getAllCounters() {
return counterRepository.findAll();
}
public Optional<CounterInfo> getCounterById(Long id) {
return counterRepository.findById(id);
}
public CounterInfo createCounter(CounterInfo counter) {
return counterRepository.save(counter);
}
public CounterInfo updateCounter(Long id, CounterInfo counterDetails) {
CounterInfo counter = counterRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Counter not found"));
counter.setName(counterDetails.getName());
counter.setLocation(counterDetails.getLocation());
return counterRepository.save(counter);
}
public void deleteCounter(Long id) {
counterRepository.deleteById(id);
}
public void assignProductToCounter(Long counterId, Long productId) {
CounterInfo counter = counterRepository.findById(counterId)
.orElseThrow(() -> new RuntimeException("Counter not found"));
CounterProduct product = productRepository.findById(productId)
.orElseThrow(() -> new RuntimeException("Product not found"));
product.setCounter(counter);
productRepository.save(product);
}
}

View File

@@ -0,0 +1,64 @@
package com.rit.canteen.sales.counter.service;
import com.rit.canteen.sales.model.Order;
import com.rit.canteen.sales.model.OrderItem;
import com.rit.canteen.sales.repository.OrderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@Service
public class CounterOrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private CounterProductService productService;
public List<Order> getAllOrders() {
return orderRepository.findAll();
}
public Optional<Order> getOrderById(Long id) {
return orderRepository.findById(id);
}
public Order createOrder(Order order) {
order.setCreatedAt(LocalDateTime.now());
if (order.getStatus() == null) {
order.setStatus("COMPLETED");
}
// Ensure bidirectional relationship for items
if (order.getItems() != null) {
for (OrderItem item : order.getItems()) {
item.setOrder(order);
// Update stock if product ID is present
if (item.getProductId() != null) {
productService.updateStock(item.getProductId(), item.getQuantity());
}
}
}
return orderRepository.save(order);
}
public Order updateOrder(Long id, Order orderDetails) {
Order order = orderRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Order not found"));
order.setItems(orderDetails.getItems());
order.setTotalAmount(orderDetails.getTotalAmount());
order.setStatus(orderDetails.getStatus());
return orderRepository.save(order);
}
public void deleteOrder(Long id) {
orderRepository.deleteById(id);
}
}

View File

@@ -0,0 +1,58 @@
package com.rit.canteen.sales.counter.service;
import com.rit.canteen.sales.counter.model.CounterProduct;
import com.rit.canteen.sales.counter.repository.CounterProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class CounterProductService {
@Autowired
private CounterProductRepository productRepository;
public List<CounterProduct> getAllProducts() {
return productRepository.findAll();
}
public List<CounterProduct> getProductsByCategory(String categoryName) {
return productRepository.findByCategoryName(categoryName);
}
public Optional<CounterProduct> getProductById(Long id) {
return productRepository.findById(id);
}
public CounterProduct createProduct(CounterProduct product) {
return productRepository.save(product);
}
public CounterProduct updateProduct(Long id, CounterProduct productDetails) {
CounterProduct product = productRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Product not found"));
product.setName(productDetails.getName());
product.setPrice(productDetails.getPrice());
product.setStock(productDetails.getStock());
product.setDescription(productDetails.getDescription());
product.setImageUrl(productDetails.getImageUrl());
product.setCategory(productDetails.getCategory());
product.setCounter(productDetails.getCounter());
return productRepository.save(product);
}
public void deleteProduct(Long id) {
productRepository.deleteById(id);
}
public CounterProduct updateStock(Long productId, Integer quantity) {
CounterProduct product = productRepository.findById(productId)
.orElseThrow(() -> new RuntimeException("Product not found"));
product.setStock(product.getStock() - quantity);
return productRepository.save(product);
}
}

View File

@@ -1,10 +1,6 @@
package com.rit.canteen.sales.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
@Entity
@@ -18,9 +14,11 @@ public class BaseItem {
@NotBlank(message = "Item name is required")
private String name;
@Column(columnDefinition = "TEXT")
private String description;
private boolean active;
@Column(nullable = false)
private boolean active = true;
public BaseItem() {}
@@ -30,35 +28,15 @@ public class BaseItem {
this.active = active;
}
public Long getId() {
return id;
}
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public void setId(Long id) {
this.id = id;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getName() {
return name;
}
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public boolean isActive() { return active; }
public void setActive(boolean active) { this.active = active; }
}

View File

@@ -4,16 +4,17 @@ public class DashboardStats {
private long totalSales;
private int activeOrders;
private int dailyCustomers;
private double revenueGrowth;
private double growth;
public DashboardStats(long totalSales, int activeOrders, int dailyCustomers, double revenueGrowth) {
public DashboardStats() {}
public DashboardStats(long totalSales, int activeOrders, int dailyCustomers, double growth) {
this.totalSales = totalSales;
this.activeOrders = activeOrders;
this.dailyCustomers = dailyCustomers;
this.revenueGrowth = revenueGrowth;
this.growth = growth;
}
// Getters and Setters
public long getTotalSales() { return totalSales; }
public void setTotalSales(long totalSales) { this.totalSales = totalSales; }
@@ -23,6 +24,6 @@ public class DashboardStats {
public int getDailyCustomers() { return dailyCustomers; }
public void setDailyCustomers(int dailyCustomers) { this.dailyCustomers = dailyCustomers; }
public double getRevenueGrowth() { return revenueGrowth; }
public void setRevenueGrowth(double revenueGrowth) { this.revenueGrowth = revenueGrowth; }
public double getGrowth() { return growth; }
public void setGrowth(double growth) { this.growth = growth; }
}

View File

@@ -9,6 +9,8 @@ public class GeneralDashboardData {
private List<Map<String, Object>> hourlySales;
private List<String> insights;
public GeneralDashboardData() {}
public GeneralDashboardData(DashboardStats stats, List<Map<String, Object>> storeOverview, List<Map<String, Object>> hourlySales, List<String> insights) {
this.stats = stats;
this.storeOverview = storeOverview;
@@ -16,9 +18,15 @@ public class GeneralDashboardData {
this.insights = insights;
}
// Getters
public DashboardStats getStats() { return stats; }
public void setStats(DashboardStats stats) { this.stats = stats; }
public List<Map<String, Object>> getStoreOverview() { return storeOverview; }
public void setStoreOverview(List<Map<String, Object>> storeOverview) { this.storeOverview = storeOverview; }
public List<Map<String, Object>> getHourlySales() { return hourlySales; }
public void setHourlySales(List<Map<String, Object>> hourlySales) { this.hourlySales = hourlySales; }
public List<String> getInsights() { return insights; }
public void setInsights(List<String> insights) { this.insights = insights; }
}

View File

@@ -41,6 +41,9 @@ public class Order {
@Column(nullable = false)
private LocalDateTime createdAt;
@Column(nullable = false)
private String orderType = "STORE_ORDER"; // STORE_ORDER, QR_ORDER, MY_ORDER, etc.
@Column(name = "is_archived", nullable = false)
private boolean isArchived = false;
@@ -97,6 +100,9 @@ public class Order {
public boolean isArchived() { return isArchived; }
public void setArchived(boolean archived) { isArchived = archived; }
public String getOrderType() { return orderType; }
public void setOrderType(String orderType) { this.orderType = orderType; }
public List<OrderItem> getItems() { return items; }
public void setItems(List<OrderItem> items) { this.items = items; }
}

View File

@@ -1,10 +1,13 @@
package com.rit.canteen.sales.repository;
import com.rit.canteen.sales.model.BaseItem;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface BaseItemRepository extends JpaRepository<BaseItem, Long> {
boolean existsByName(String name);
Page<BaseItem> findByNameContainingIgnoreCase(String name, Pageable pageable);
}

View File

@@ -9,6 +9,11 @@ import java.util.List;
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
@Query("SELECT DISTINCT p FROM Product p LEFT JOIN FETCH p.stalls " +
"WHERE LOWER(p.name) LIKE LOWER(CONCAT('%', :search, '%')) " +
"OR LOWER(p.category) LIKE LOWER(CONCAT('%', :search, '%'))")
org.springframework.data.domain.Page<Product> findByNameOrCategoryContainingIgnoreCase(String search, org.springframework.data.domain.Pageable pageable);
@Query(value = "SELECT DISTINCT p FROM Product p LEFT JOIN FETCH p.stalls",
countQuery = "SELECT count(p) FROM Product p")
org.springframework.data.domain.Page<Product> findAllWithStalls(org.springframework.data.domain.Pageable pageable);

View File

@@ -2,6 +2,7 @@ package com.rit.canteen.sales.repository;
import com.rit.canteen.sales.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@@ -10,4 +11,8 @@ import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByMobileNumber(String mobileNumber);
boolean existsByMobileNumber(String mobileNumber);
@Query("SELECT u FROM User u WHERE LOWER(u.name) LIKE LOWER(CONCAT('%', :search, '%')) " +
"OR u.mobileNumber LIKE CONCAT('%', :search, '%')")
org.springframework.data.domain.Page<User> findByNameOrMobileContainingIgnoreCase(String search, org.springframework.data.domain.Pageable pageable);
}

View File

@@ -50,7 +50,7 @@ public class DashboardService {
hourMap.put("value", 0);
for (Object[] row : hourlyData) {
int h = (int) row[0];
int h = ((Number) row[0]).intValue();
if (h >= i && h < i + 2) {
BigDecimal val = (BigDecimal) row[1];
hourMap.put("value", ((Number) hourMap.get("value")).doubleValue() + val.doubleValue());

View File

@@ -158,16 +158,22 @@ public class UserService {
}
/**
* Get all registered users for administration dashboard (Paginated).
* Get all registered users for administration dashboard (Paginated with Search).
*/
public Page<LoginResponse.UserDto> getAllUsers(Pageable pageable) {
return userRepository.findAll(pageable)
.map(user -> new LoginResponse.UserDto(
user.getId(),
user.getMobileNumber(),
user.getName(),
user.isLoggedIn()
));
public Page<LoginResponse.UserDto> getAllUsers(String search, Pageable pageable) {
Page<User> users;
if (search != null && !search.isEmpty()) {
users = userRepository.findByNameOrMobileContainingIgnoreCase(search, pageable);
} else {
users = userRepository.findAll(pageable);
}
return users.map(user -> new LoginResponse.UserDto(
user.getId(),
user.getMobileNumber(),
user.getName(),
user.isLoggedIn()
));
}
/**